@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/runtime/index.js
CHANGED
|
@@ -2454,7 +2454,7 @@ var init_SvgGrid = __esm({
|
|
|
2454
2454
|
x,
|
|
2455
2455
|
y,
|
|
2456
2456
|
cols = 4,
|
|
2457
|
-
rows = 3,
|
|
2457
|
+
rows: rows2 = 3,
|
|
2458
2458
|
spacing = 20,
|
|
2459
2459
|
nodeRadius = 3,
|
|
2460
2460
|
color = "var(--color-primary)",
|
|
@@ -2463,7 +2463,7 @@ var init_SvgGrid = __esm({
|
|
|
2463
2463
|
highlights = []
|
|
2464
2464
|
}) => {
|
|
2465
2465
|
const highlightSet = new Set(highlights);
|
|
2466
|
-
return /* @__PURE__ */ jsx("g", { className, opacity, children: Array.from({ length:
|
|
2466
|
+
return /* @__PURE__ */ jsx("g", { className, opacity, children: Array.from({ length: rows2 }).map(
|
|
2467
2467
|
(_, row) => Array.from({ length: cols }).map((_2, col) => {
|
|
2468
2468
|
const index = row * cols + col;
|
|
2469
2469
|
const isHighlighted = highlightSet.has(index);
|
|
@@ -3123,7 +3123,7 @@ var init_Input = __esm({
|
|
|
3123
3123
|
onClear,
|
|
3124
3124
|
value,
|
|
3125
3125
|
options,
|
|
3126
|
-
rows = 3,
|
|
3126
|
+
rows: rows2 = 3,
|
|
3127
3127
|
onChange,
|
|
3128
3128
|
...props
|
|
3129
3129
|
}, ref) => {
|
|
@@ -3173,7 +3173,7 @@ var init_Input = __esm({
|
|
|
3173
3173
|
ref,
|
|
3174
3174
|
value,
|
|
3175
3175
|
onChange,
|
|
3176
|
-
rows,
|
|
3176
|
+
rows: rows2,
|
|
3177
3177
|
className: baseClassName,
|
|
3178
3178
|
...props
|
|
3179
3179
|
}
|
|
@@ -5429,66 +5429,6 @@ var init_RangeSlider = __esm({
|
|
|
5429
5429
|
RangeSlider.displayName = "RangeSlider";
|
|
5430
5430
|
}
|
|
5431
5431
|
});
|
|
5432
|
-
function easeOut(t) {
|
|
5433
|
-
return t * (2 - t);
|
|
5434
|
-
}
|
|
5435
|
-
var AnimatedCounter;
|
|
5436
|
-
var init_AnimatedCounter = __esm({
|
|
5437
|
-
"components/marketing/atoms/AnimatedCounter.tsx"() {
|
|
5438
|
-
"use client";
|
|
5439
|
-
init_cn();
|
|
5440
|
-
init_Typography();
|
|
5441
|
-
AnimatedCounter = ({
|
|
5442
|
-
value: rawValue,
|
|
5443
|
-
duration = 600,
|
|
5444
|
-
prefix,
|
|
5445
|
-
suffix,
|
|
5446
|
-
className
|
|
5447
|
-
}) => {
|
|
5448
|
-
const numericRaw = typeof rawValue === "number" ? rawValue : Number.parseFloat(String(rawValue ?? ""));
|
|
5449
|
-
const value = !Number.isNaN(numericRaw) ? numericRaw : 0;
|
|
5450
|
-
const [displayValue, setDisplayValue] = useState(value);
|
|
5451
|
-
const previousValueRef = useRef(value);
|
|
5452
|
-
const animationFrameRef = useRef(null);
|
|
5453
|
-
useEffect(() => {
|
|
5454
|
-
const from = previousValueRef.current;
|
|
5455
|
-
const to = value;
|
|
5456
|
-
previousValueRef.current = value;
|
|
5457
|
-
if (from === to) {
|
|
5458
|
-
setDisplayValue(to);
|
|
5459
|
-
return;
|
|
5460
|
-
}
|
|
5461
|
-
const startTime = performance.now();
|
|
5462
|
-
const diff = to - from;
|
|
5463
|
-
function animate(currentTime) {
|
|
5464
|
-
const elapsed = currentTime - startTime;
|
|
5465
|
-
const progress = Math.min(elapsed / duration, 1);
|
|
5466
|
-
const easedProgress = easeOut(progress);
|
|
5467
|
-
setDisplayValue(from + diff * easedProgress);
|
|
5468
|
-
if (progress < 1) {
|
|
5469
|
-
animationFrameRef.current = requestAnimationFrame(animate);
|
|
5470
|
-
} else {
|
|
5471
|
-
setDisplayValue(to);
|
|
5472
|
-
}
|
|
5473
|
-
}
|
|
5474
|
-
animationFrameRef.current = requestAnimationFrame(animate);
|
|
5475
|
-
return () => {
|
|
5476
|
-
if (animationFrameRef.current !== null) {
|
|
5477
|
-
cancelAnimationFrame(animationFrameRef.current);
|
|
5478
|
-
}
|
|
5479
|
-
};
|
|
5480
|
-
}, [value, duration]);
|
|
5481
|
-
const decimalPlaces = Number.isInteger(value) ? 0 : String(value).split(".")[1]?.length ?? 0;
|
|
5482
|
-
const formattedValue = displayValue.toFixed(decimalPlaces);
|
|
5483
|
-
return /* @__PURE__ */ jsxs(Typography, { variant: "h3", className: cn("tabular-nums", className), children: [
|
|
5484
|
-
prefix,
|
|
5485
|
-
formattedValue,
|
|
5486
|
-
suffix
|
|
5487
|
-
] });
|
|
5488
|
-
};
|
|
5489
|
-
AnimatedCounter.displayName = "AnimatedCounter";
|
|
5490
|
-
}
|
|
5491
|
-
});
|
|
5492
5432
|
function useInfiniteScroll(onLoadMore, options = {}) {
|
|
5493
5433
|
const { rootMargin = "200px", hasMore = true, isLoading = false } = options;
|
|
5494
5434
|
const observerRef = useRef(null);
|
|
@@ -7970,15 +7910,15 @@ function HeaderSkeleton({ className }) {
|
|
|
7970
7910
|
] })
|
|
7971
7911
|
] });
|
|
7972
7912
|
}
|
|
7973
|
-
function TableSkeleton({ rows = 5, columns = 4, className }) {
|
|
7913
|
+
function TableSkeleton({ rows: rows2 = 5, columns = 4, className }) {
|
|
7974
7914
|
return /* @__PURE__ */ jsxs(VStack, { gap: "none", className: cn("border border-border rounded-lg overflow-hidden", className), children: [
|
|
7975
7915
|
/* @__PURE__ */ jsx(HStack, { className: "px-4 py-3 bg-muted/30 border-b border-border", children: Array.from({ length: columns }).map((_, i) => /* @__PURE__ */ jsx(SkeletonBlock, { className: "h-4 flex-1 mx-2" }, i)) }),
|
|
7976
|
-
Array.from({ length:
|
|
7916
|
+
Array.from({ length: rows2 }).map((_, rowIdx) => /* @__PURE__ */ jsx(
|
|
7977
7917
|
HStack,
|
|
7978
7918
|
{
|
|
7979
7919
|
className: cn(
|
|
7980
7920
|
"px-4 py-3",
|
|
7981
|
-
rowIdx <
|
|
7921
|
+
rowIdx < rows2 - 1 && "border-b border-border"
|
|
7982
7922
|
),
|
|
7983
7923
|
children: Array.from({ length: columns }).map((_2, colIdx) => /* @__PURE__ */ jsx(SkeletonLine, { className: "flex-1 mx-2" }, colIdx))
|
|
7984
7924
|
},
|
|
@@ -8026,18 +7966,18 @@ function CardSkeleton({ className }) {
|
|
|
8026
7966
|
}
|
|
8027
7967
|
);
|
|
8028
7968
|
}
|
|
8029
|
-
function TextSkeleton({ rows = 3, className }) {
|
|
8030
|
-
return /* @__PURE__ */ jsx(VStack, { gap: "sm", className, children: Array.from({ length:
|
|
7969
|
+
function TextSkeleton({ rows: rows2 = 3, className }) {
|
|
7970
|
+
return /* @__PURE__ */ jsx(VStack, { gap: "sm", className, children: Array.from({ length: rows2 }).map((_, i) => /* @__PURE__ */ jsx(
|
|
8031
7971
|
SkeletonLine,
|
|
8032
7972
|
{
|
|
8033
|
-
className: i ===
|
|
7973
|
+
className: i === rows2 - 1 ? "w-2/3" : "w-full"
|
|
8034
7974
|
},
|
|
8035
7975
|
i
|
|
8036
7976
|
)) });
|
|
8037
7977
|
}
|
|
8038
7978
|
function Skeleton({
|
|
8039
7979
|
variant = "text",
|
|
8040
|
-
rows,
|
|
7980
|
+
rows: rows2,
|
|
8041
7981
|
columns,
|
|
8042
7982
|
fields,
|
|
8043
7983
|
className
|
|
@@ -8047,15 +7987,15 @@ function Skeleton({
|
|
|
8047
7987
|
case "header":
|
|
8048
7988
|
return /* @__PURE__ */ jsx(HeaderSkeleton, { className });
|
|
8049
7989
|
case "table":
|
|
8050
|
-
return /* @__PURE__ */ jsx(TableSkeleton, { rows, columns, className });
|
|
7990
|
+
return /* @__PURE__ */ jsx(TableSkeleton, { rows: rows2, columns, className });
|
|
8051
7991
|
case "form":
|
|
8052
7992
|
return /* @__PURE__ */ jsx(FormSkeleton, { fields, className });
|
|
8053
7993
|
case "card":
|
|
8054
7994
|
return /* @__PURE__ */ jsx(CardSkeleton, { className });
|
|
8055
7995
|
case "text":
|
|
8056
|
-
return /* @__PURE__ */ jsx(TextSkeleton, { rows, className });
|
|
7996
|
+
return /* @__PURE__ */ jsx(TextSkeleton, { rows: rows2, className });
|
|
8057
7997
|
default:
|
|
8058
|
-
return /* @__PURE__ */ jsx(TextSkeleton, { rows, className });
|
|
7998
|
+
return /* @__PURE__ */ jsx(TextSkeleton, { rows: rows2, className });
|
|
8059
7999
|
}
|
|
8060
8000
|
}
|
|
8061
8001
|
var pulseClass;
|
|
@@ -9209,7 +9149,7 @@ var init_Menu = __esm({
|
|
|
9209
9149
|
className
|
|
9210
9150
|
}) => {
|
|
9211
9151
|
const eventBus = useEventBus();
|
|
9212
|
-
const { t } = useTranslate();
|
|
9152
|
+
const { t, direction } = useTranslate();
|
|
9213
9153
|
const [isOpen, setIsOpen] = useState(false);
|
|
9214
9154
|
const [activeSubMenu, setActiveSubMenu] = useState(null);
|
|
9215
9155
|
const [triggerRect, setTriggerRect] = useState(null);
|
|
@@ -9263,6 +9203,18 @@ var init_Menu = __esm({
|
|
|
9263
9203
|
"bottom-start": "top-full left-0 mt-2",
|
|
9264
9204
|
"bottom-end": "top-full right-0 mt-2"
|
|
9265
9205
|
};
|
|
9206
|
+
const rtlMirror = {
|
|
9207
|
+
"top-left": "top-right",
|
|
9208
|
+
"top-right": "top-left",
|
|
9209
|
+
"bottom-left": "bottom-right",
|
|
9210
|
+
"bottom-right": "bottom-left",
|
|
9211
|
+
"top-start": "top-end",
|
|
9212
|
+
"top-end": "top-start",
|
|
9213
|
+
"bottom-start": "bottom-end",
|
|
9214
|
+
"bottom-end": "bottom-start"
|
|
9215
|
+
};
|
|
9216
|
+
const effectivePosition = direction === "rtl" ? rtlMirror[position] ?? position : position;
|
|
9217
|
+
const subMenuSideClass = direction === "rtl" ? "right-full mr-2" : "left-full ml-2";
|
|
9266
9218
|
const triggerChild = React84__default.isValidElement(trigger) ? trigger : /* @__PURE__ */ jsx(Typography, { variant: "small", as: "span", children: trigger });
|
|
9267
9219
|
const triggerElement = React84__default.cloneElement(
|
|
9268
9220
|
triggerChild,
|
|
@@ -9290,7 +9242,7 @@ var init_Menu = __esm({
|
|
|
9290
9242
|
onMouseEnter: () => hasSubMenu && setActiveSubMenu(itemId),
|
|
9291
9243
|
"data-testid": item.event ? `action-${item.event}` : void 0,
|
|
9292
9244
|
className: cn(
|
|
9293
|
-
"w-full flex items-center justify-between gap-3 px-4 py-2 text-
|
|
9245
|
+
"w-full flex items-center justify-between gap-3 px-4 py-2 text-start",
|
|
9294
9246
|
"text-sm transition-colors",
|
|
9295
9247
|
"hover:bg-muted",
|
|
9296
9248
|
"focus:outline-none focus:bg-muted",
|
|
@@ -9309,7 +9261,7 @@ var init_Menu = __esm({
|
|
|
9309
9261
|
}
|
|
9310
9262
|
),
|
|
9311
9263
|
item.badge !== void 0 && /* @__PURE__ */ jsx(Badge, { variant: "default", size: "sm", children: item.badge }),
|
|
9312
|
-
hasSubMenu && /* @__PURE__ */ jsx(Icon, { name: "chevron-right", size: "sm", className: "flex-shrink-0" })
|
|
9264
|
+
hasSubMenu && /* @__PURE__ */ jsx(Icon, { name: direction === "rtl" ? "chevron-left" : "chevron-right", size: "sm", className: "flex-shrink-0" })
|
|
9313
9265
|
] })
|
|
9314
9266
|
},
|
|
9315
9267
|
itemId
|
|
@@ -9329,7 +9281,8 @@ var init_Menu = __esm({
|
|
|
9329
9281
|
Box,
|
|
9330
9282
|
{
|
|
9331
9283
|
className: cn(
|
|
9332
|
-
"absolute
|
|
9284
|
+
"absolute top-0 z-50",
|
|
9285
|
+
subMenuSideClass,
|
|
9333
9286
|
menuContainerStyles
|
|
9334
9287
|
),
|
|
9335
9288
|
children: renderMenuItems(item.subMenu)
|
|
@@ -9347,12 +9300,12 @@ var init_Menu = __esm({
|
|
|
9347
9300
|
className: cn(
|
|
9348
9301
|
"absolute z-50",
|
|
9349
9302
|
menuContainerStyles,
|
|
9350
|
-
positionClasses3[
|
|
9303
|
+
positionClasses3[effectivePosition],
|
|
9351
9304
|
className
|
|
9352
9305
|
),
|
|
9353
9306
|
style: {
|
|
9354
|
-
left:
|
|
9355
|
-
right:
|
|
9307
|
+
left: effectivePosition.includes("left") ? 0 : "auto",
|
|
9308
|
+
right: effectivePosition.includes("right") ? 0 : "auto"
|
|
9356
9309
|
},
|
|
9357
9310
|
role: "menu",
|
|
9358
9311
|
children: renderMenuItems(items)
|
|
@@ -9670,7 +9623,7 @@ var init_MapView = __esm({
|
|
|
9670
9623
|
shadowSize: [41, 41]
|
|
9671
9624
|
});
|
|
9672
9625
|
L.Marker.prototype.options.icon = defaultIcon;
|
|
9673
|
-
const { useEffect: useEffect71, useRef: useRef66, useCallback:
|
|
9626
|
+
const { useEffect: useEffect71, useRef: useRef66, useCallback: useCallback114, useState: useState103 } = React84__default;
|
|
9674
9627
|
const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
|
|
9675
9628
|
const { useEventBus: useEventBus3 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
|
|
9676
9629
|
function MapUpdater({ centerLat, centerLng, zoom }) {
|
|
@@ -9716,7 +9669,7 @@ var init_MapView = __esm({
|
|
|
9716
9669
|
}) {
|
|
9717
9670
|
const eventBus = useEventBus3();
|
|
9718
9671
|
const [clickedPosition, setClickedPosition] = useState103(null);
|
|
9719
|
-
const handleMapClick =
|
|
9672
|
+
const handleMapClick = useCallback114((lat, lng) => {
|
|
9720
9673
|
if (showClickedPin) {
|
|
9721
9674
|
setClickedPosition({ lat, lng });
|
|
9722
9675
|
}
|
|
@@ -9725,7 +9678,7 @@ var init_MapView = __esm({
|
|
|
9725
9678
|
eventBus.emit(`UI:${mapClickEvent}`, { latitude: lat, longitude: lng });
|
|
9726
9679
|
}
|
|
9727
9680
|
}, [onMapClick, mapClickEvent, eventBus, showClickedPin]);
|
|
9728
|
-
const handleMarkerClick =
|
|
9681
|
+
const handleMarkerClick = useCallback114((marker) => {
|
|
9729
9682
|
onMarkerClick?.(marker);
|
|
9730
9683
|
if (markerClickEvent) {
|
|
9731
9684
|
eventBus.emit(`UI:${markerClickEvent}`, { ...marker });
|
|
@@ -9946,7 +9899,7 @@ function InputPattern({
|
|
|
9946
9899
|
function TextareaPattern({
|
|
9947
9900
|
value = "",
|
|
9948
9901
|
placeholder,
|
|
9949
|
-
rows = 4,
|
|
9902
|
+
rows: rows2 = 4,
|
|
9950
9903
|
disabled = false,
|
|
9951
9904
|
fieldError,
|
|
9952
9905
|
onChange,
|
|
@@ -9966,7 +9919,7 @@ function TextareaPattern({
|
|
|
9966
9919
|
{
|
|
9967
9920
|
value: localValue,
|
|
9968
9921
|
placeholder,
|
|
9969
|
-
rows,
|
|
9922
|
+
rows: rows2,
|
|
9970
9923
|
disabled,
|
|
9971
9924
|
error: fieldError,
|
|
9972
9925
|
onChange: handleChange,
|
|
@@ -10451,6 +10404,91 @@ var init_ActionPalette = __esm({
|
|
|
10451
10404
|
ActionPalette.displayName = "ActionPalette";
|
|
10452
10405
|
}
|
|
10453
10406
|
});
|
|
10407
|
+
function parseValue(value) {
|
|
10408
|
+
if (value === "" || value == null) return { num: 0, prefix: "", suffix: "", decimals: 0 };
|
|
10409
|
+
const match = String(value).match(/^([^0-9]*)([0-9]+(?:\.[0-9]+)?)(.*)$/);
|
|
10410
|
+
if (!match) {
|
|
10411
|
+
return { num: 0, prefix: "", suffix: String(value), decimals: 0 };
|
|
10412
|
+
}
|
|
10413
|
+
const numStr = match[2];
|
|
10414
|
+
const decimalIdx = numStr.indexOf(".");
|
|
10415
|
+
const decimals = decimalIdx >= 0 ? numStr.length - decimalIdx - 1 : 0;
|
|
10416
|
+
return {
|
|
10417
|
+
prefix: match[1],
|
|
10418
|
+
num: parseFloat(numStr),
|
|
10419
|
+
suffix: match[3],
|
|
10420
|
+
decimals
|
|
10421
|
+
};
|
|
10422
|
+
}
|
|
10423
|
+
var AnimatedCounter;
|
|
10424
|
+
var init_AnimatedCounter = __esm({
|
|
10425
|
+
"components/core/molecules/AnimatedCounter.tsx"() {
|
|
10426
|
+
"use client";
|
|
10427
|
+
init_cn();
|
|
10428
|
+
init_Box();
|
|
10429
|
+
init_Typography();
|
|
10430
|
+
AnimatedCounter = ({
|
|
10431
|
+
value,
|
|
10432
|
+
label,
|
|
10433
|
+
duration = 1500,
|
|
10434
|
+
className
|
|
10435
|
+
}) => {
|
|
10436
|
+
const ref = useRef(null);
|
|
10437
|
+
const [displayValue, setDisplayValue] = useState("0");
|
|
10438
|
+
const [hasAnimated, setHasAnimated] = useState(false);
|
|
10439
|
+
const animate = useCallback(() => {
|
|
10440
|
+
const { num: num2, prefix, suffix, decimals } = parseValue(value);
|
|
10441
|
+
if (num2 === 0) {
|
|
10442
|
+
setDisplayValue(String(value));
|
|
10443
|
+
return;
|
|
10444
|
+
}
|
|
10445
|
+
const startTime = performance.now();
|
|
10446
|
+
const tick = (now2) => {
|
|
10447
|
+
const elapsed = now2 - startTime;
|
|
10448
|
+
const progress = Math.min(elapsed / duration, 1);
|
|
10449
|
+
const eased = 1 - Math.pow(1 - progress, 3);
|
|
10450
|
+
const current = eased * num2;
|
|
10451
|
+
setDisplayValue(`${prefix}${current.toFixed(decimals)}${suffix}`);
|
|
10452
|
+
if (progress < 1) {
|
|
10453
|
+
requestAnimationFrame(tick);
|
|
10454
|
+
} else {
|
|
10455
|
+
setDisplayValue(String(value));
|
|
10456
|
+
}
|
|
10457
|
+
};
|
|
10458
|
+
requestAnimationFrame(tick);
|
|
10459
|
+
}, [value, duration]);
|
|
10460
|
+
useEffect(() => {
|
|
10461
|
+
if (hasAnimated) return;
|
|
10462
|
+
const el = ref.current;
|
|
10463
|
+
if (!el) return;
|
|
10464
|
+
const observer2 = new IntersectionObserver(
|
|
10465
|
+
(entries) => {
|
|
10466
|
+
if (entries[0].isIntersecting) {
|
|
10467
|
+
setHasAnimated(true);
|
|
10468
|
+
animate();
|
|
10469
|
+
observer2.disconnect();
|
|
10470
|
+
}
|
|
10471
|
+
},
|
|
10472
|
+
{ threshold: 0.3 }
|
|
10473
|
+
);
|
|
10474
|
+
observer2.observe(el);
|
|
10475
|
+
return () => observer2.disconnect();
|
|
10476
|
+
}, [hasAnimated, animate]);
|
|
10477
|
+
return /* @__PURE__ */ jsxs(Box, { ref, className: cn("flex flex-col items-center gap-1 p-4", className), children: [
|
|
10478
|
+
/* @__PURE__ */ jsx(
|
|
10479
|
+
Typography,
|
|
10480
|
+
{
|
|
10481
|
+
variant: "h2",
|
|
10482
|
+
className: "text-primary font-bold tabular-nums",
|
|
10483
|
+
children: hasAnimated ? displayValue : "0"
|
|
10484
|
+
}
|
|
10485
|
+
),
|
|
10486
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body2", color: "muted", className: "text-center", children: label })
|
|
10487
|
+
] });
|
|
10488
|
+
};
|
|
10489
|
+
AnimatedCounter.displayName = "AnimatedCounter";
|
|
10490
|
+
}
|
|
10491
|
+
});
|
|
10454
10492
|
var AuthLayout;
|
|
10455
10493
|
var init_AuthLayout = __esm({
|
|
10456
10494
|
"components/core/templates/AuthLayout.tsx"() {
|
|
@@ -11804,6 +11842,39 @@ var init_IsometricCanvas2 = __esm({
|
|
|
11804
11842
|
init_IsometricCanvas();
|
|
11805
11843
|
}
|
|
11806
11844
|
});
|
|
11845
|
+
|
|
11846
|
+
// components/game/organisms/boardEntity.ts
|
|
11847
|
+
function boardEntity(entity) {
|
|
11848
|
+
if (!entity) return void 0;
|
|
11849
|
+
return Array.isArray(entity) ? entity[0] : entity;
|
|
11850
|
+
}
|
|
11851
|
+
function str(v) {
|
|
11852
|
+
return v == null ? "" : String(v);
|
|
11853
|
+
}
|
|
11854
|
+
function num(v, fallback = 0) {
|
|
11855
|
+
const n = Number(v);
|
|
11856
|
+
return Number.isFinite(n) ? n : fallback;
|
|
11857
|
+
}
|
|
11858
|
+
function rows(v) {
|
|
11859
|
+
return Array.isArray(v) ? v : [];
|
|
11860
|
+
}
|
|
11861
|
+
function vec2(v) {
|
|
11862
|
+
const o = v ?? {};
|
|
11863
|
+
return { x: num(o.x), y: num(o.y) };
|
|
11864
|
+
}
|
|
11865
|
+
function unitPosition(u) {
|
|
11866
|
+
return vec2(u.position);
|
|
11867
|
+
}
|
|
11868
|
+
function unitTeam(u) {
|
|
11869
|
+
return str(u.team);
|
|
11870
|
+
}
|
|
11871
|
+
function unitHealth(u) {
|
|
11872
|
+
return num(u.health);
|
|
11873
|
+
}
|
|
11874
|
+
var init_boardEntity = __esm({
|
|
11875
|
+
"components/game/organisms/boardEntity.ts"() {
|
|
11876
|
+
}
|
|
11877
|
+
});
|
|
11807
11878
|
function BattleBoard({
|
|
11808
11879
|
entity,
|
|
11809
11880
|
scale = 0.45,
|
|
@@ -11830,43 +11901,49 @@ function BattleBoard({
|
|
|
11830
11901
|
attackEvent,
|
|
11831
11902
|
className
|
|
11832
11903
|
}) {
|
|
11833
|
-
const
|
|
11834
|
-
const
|
|
11835
|
-
const
|
|
11836
|
-
const
|
|
11837
|
-
const
|
|
11838
|
-
const
|
|
11839
|
-
const
|
|
11840
|
-
const
|
|
11841
|
-
const
|
|
11842
|
-
const
|
|
11843
|
-
const
|
|
11904
|
+
const board = boardEntity(entity) ?? {};
|
|
11905
|
+
const tiles = Array.isArray(board.tiles) ? board.tiles : [];
|
|
11906
|
+
const features = Array.isArray(board.features) ? board.features : [];
|
|
11907
|
+
const boardWidth = num(board.boardWidth, 8);
|
|
11908
|
+
const boardHeight = num(board.boardHeight, 6);
|
|
11909
|
+
const assetManifest = board.assetManifest;
|
|
11910
|
+
const backgroundImage = board.backgroundImage;
|
|
11911
|
+
const units = rows(board.units);
|
|
11912
|
+
const selectedUnitId = board.selectedUnitId ?? null;
|
|
11913
|
+
const currentPhase = str(board.phase) || "observation";
|
|
11914
|
+
const currentTurn = num(board.turn, 1);
|
|
11915
|
+
const gameResult = board.gameResult ?? null;
|
|
11844
11916
|
const eventBus = useEventBus();
|
|
11845
11917
|
const { t } = useTranslate();
|
|
11846
11918
|
const [hoveredTile, setHoveredTile] = useState(null);
|
|
11847
11919
|
const [isShaking, setIsShaking] = useState(false);
|
|
11848
11920
|
const selectedUnit = useMemo(
|
|
11849
|
-
() => units.find((u) => u.id === selectedUnitId) ?? null,
|
|
11921
|
+
() => units.find((u) => str(u.id) === selectedUnitId) ?? null,
|
|
11850
11922
|
[units, selectedUnitId]
|
|
11851
11923
|
);
|
|
11852
11924
|
const hoveredUnit = useMemo(() => {
|
|
11853
11925
|
if (!hoveredTile) return null;
|
|
11854
|
-
return units.find(
|
|
11855
|
-
|
|
11856
|
-
|
|
11926
|
+
return units.find((u) => {
|
|
11927
|
+
const p2 = unitPosition(u);
|
|
11928
|
+
return p2.x === hoveredTile.x && p2.y === hoveredTile.y && unitHealth(u) > 0;
|
|
11929
|
+
}) ?? null;
|
|
11857
11930
|
}, [hoveredTile, units]);
|
|
11858
|
-
const playerUnits = useMemo(() => units.filter((u) => u
|
|
11859
|
-
const enemyUnits = useMemo(() => units.filter((u) => u
|
|
11931
|
+
const playerUnits = useMemo(() => units.filter((u) => unitTeam(u) === "player" && unitHealth(u) > 0), [units]);
|
|
11932
|
+
const enemyUnits = useMemo(() => units.filter((u) => unitTeam(u) === "enemy" && unitHealth(u) > 0), [units]);
|
|
11860
11933
|
const validMoves = useMemo(() => {
|
|
11861
11934
|
if (!selectedUnit || currentPhase !== "movement") return [];
|
|
11862
11935
|
const moves = [];
|
|
11863
|
-
const range = selectedUnit.movement;
|
|
11936
|
+
const range = num(selectedUnit.movement);
|
|
11937
|
+
const origin = unitPosition(selectedUnit);
|
|
11864
11938
|
for (let dy = -range; dy <= range; dy++) {
|
|
11865
11939
|
for (let dx = -range; dx <= range; dx++) {
|
|
11866
|
-
const nx =
|
|
11867
|
-
const ny =
|
|
11940
|
+
const nx = origin.x + dx;
|
|
11941
|
+
const ny = origin.y + dy;
|
|
11868
11942
|
const dist = Math.abs(dx) + Math.abs(dy);
|
|
11869
|
-
if (dist > 0 && dist <= range && nx >= 0 && nx < boardWidth && ny >= 0 && ny < boardHeight && !units.some((u) =>
|
|
11943
|
+
if (dist > 0 && dist <= range && nx >= 0 && nx < boardWidth && ny >= 0 && ny < boardHeight && !units.some((u) => {
|
|
11944
|
+
const p2 = unitPosition(u);
|
|
11945
|
+
return p2.x === nx && p2.y === ny && unitHealth(u) > 0;
|
|
11946
|
+
})) {
|
|
11870
11947
|
moves.push({ x: nx, y: ny });
|
|
11871
11948
|
}
|
|
11872
11949
|
}
|
|
@@ -11875,11 +11952,14 @@ function BattleBoard({
|
|
|
11875
11952
|
}, [selectedUnit, currentPhase, units, boardWidth, boardHeight]);
|
|
11876
11953
|
const attackTargets = useMemo(() => {
|
|
11877
11954
|
if (!selectedUnit || currentPhase !== "action") return [];
|
|
11878
|
-
|
|
11879
|
-
|
|
11880
|
-
|
|
11955
|
+
const sp = unitPosition(selectedUnit);
|
|
11956
|
+
const sTeam = unitTeam(selectedUnit);
|
|
11957
|
+
return units.filter((u) => unitTeam(u) !== sTeam && unitHealth(u) > 0).filter((u) => {
|
|
11958
|
+
const p2 = unitPosition(u);
|
|
11959
|
+
const dx = Math.abs(p2.x - sp.x);
|
|
11960
|
+
const dy = Math.abs(p2.y - sp.y);
|
|
11881
11961
|
return dx <= 1 && dy <= 1 && dx + dy > 0;
|
|
11882
|
-
}).map((u) => u
|
|
11962
|
+
}).map((u) => unitPosition(u));
|
|
11883
11963
|
}, [selectedUnit, currentPhase, units]);
|
|
11884
11964
|
const MOVE_SPEED_MS_PER_TILE = 300;
|
|
11885
11965
|
const movementAnimRef = useRef(null);
|
|
@@ -11919,23 +11999,25 @@ function BattleBoard({
|
|
|
11919
11999
|
return () => clearInterval(interval);
|
|
11920
12000
|
}, []);
|
|
11921
12001
|
const isoUnits = useMemo(() => {
|
|
11922
|
-
return units.filter((u) => u
|
|
11923
|
-
const
|
|
12002
|
+
return units.filter((u) => unitHealth(u) > 0).map((unit) => {
|
|
12003
|
+
const id = str(unit.id);
|
|
12004
|
+
const pos = movingPositions.get(id) ?? unitPosition(unit);
|
|
12005
|
+
const unitTraits = Array.isArray(unit.traits) ? unit.traits : void 0;
|
|
11924
12006
|
return {
|
|
11925
|
-
id
|
|
12007
|
+
id,
|
|
11926
12008
|
position: pos,
|
|
11927
|
-
name: unit.name,
|
|
11928
|
-
team: unit
|
|
11929
|
-
health: unit
|
|
11930
|
-
maxHealth: unit.maxHealth,
|
|
11931
|
-
unitType: unit.unitType,
|
|
11932
|
-
heroId: unit.heroId,
|
|
11933
|
-
sprite: unit.sprite,
|
|
11934
|
-
traits:
|
|
11935
|
-
name:
|
|
11936
|
-
currentState:
|
|
11937
|
-
states:
|
|
11938
|
-
cooldown:
|
|
12009
|
+
name: str(unit.name),
|
|
12010
|
+
team: unitTeam(unit),
|
|
12011
|
+
health: unitHealth(unit),
|
|
12012
|
+
maxHealth: num(unit.maxHealth),
|
|
12013
|
+
unitType: unit.unitType == null ? void 0 : str(unit.unitType),
|
|
12014
|
+
heroId: unit.heroId == null ? void 0 : str(unit.heroId),
|
|
12015
|
+
sprite: unit.sprite == null ? void 0 : str(unit.sprite),
|
|
12016
|
+
traits: unitTraits?.map((tr) => ({
|
|
12017
|
+
name: tr.name,
|
|
12018
|
+
currentState: tr.currentState,
|
|
12019
|
+
states: tr.states,
|
|
12020
|
+
cooldown: tr.cooldown ?? 0
|
|
11939
12021
|
}))
|
|
11940
12022
|
};
|
|
11941
12023
|
});
|
|
@@ -11947,8 +12029,8 @@ function BattleBoard({
|
|
|
11947
12029
|
[scale, baseOffsetX]
|
|
11948
12030
|
);
|
|
11949
12031
|
const checkGameEnd = useCallback(() => {
|
|
11950
|
-
const pa = units.filter((u) => u
|
|
11951
|
-
const ea = units.filter((u) => u
|
|
12032
|
+
const pa = units.filter((u) => unitTeam(u) === "player" && unitHealth(u) > 0);
|
|
12033
|
+
const ea = units.filter((u) => unitTeam(u) === "enemy" && unitHealth(u) > 0);
|
|
11952
12034
|
if (pa.length === 0) {
|
|
11953
12035
|
onGameEnd?.("defeat");
|
|
11954
12036
|
if (gameEndEvent) {
|
|
@@ -11962,21 +12044,22 @@ function BattleBoard({
|
|
|
11962
12044
|
}
|
|
11963
12045
|
}, [units, onGameEnd, gameEndEvent, eventBus]);
|
|
11964
12046
|
const handleUnitClick = useCallback((unitId) => {
|
|
11965
|
-
const unit = units.find((u) => u.id === unitId);
|
|
12047
|
+
const unit = units.find((u) => str(u.id) === unitId);
|
|
11966
12048
|
if (!unit) return;
|
|
11967
12049
|
if (unitClickEvent) {
|
|
11968
12050
|
eventBus.emit(`UI:${unitClickEvent}`, { unitId });
|
|
11969
12051
|
}
|
|
11970
12052
|
if (currentPhase === "action" && selectedUnit) {
|
|
11971
|
-
|
|
11972
|
-
|
|
12053
|
+
const up = unitPosition(unit);
|
|
12054
|
+
if (unitTeam(unit) === "enemy" && attackTargets.some((t2) => t2.x === up.x && t2.y === up.y)) {
|
|
12055
|
+
const damage = calculateDamage ? calculateDamage(selectedUnit, unit) : Math.max(1, num(selectedUnit.attack) - num(unit.defense));
|
|
11973
12056
|
setIsShaking(true);
|
|
11974
12057
|
setTimeout(() => setIsShaking(false), 300);
|
|
11975
12058
|
onAttack?.(selectedUnit, unit, damage);
|
|
11976
12059
|
if (attackEvent) {
|
|
11977
12060
|
eventBus.emit(`UI:${attackEvent}`, {
|
|
11978
|
-
attackerId: selectedUnit.id,
|
|
11979
|
-
targetId: unit.id,
|
|
12061
|
+
attackerId: str(selectedUnit.id),
|
|
12062
|
+
targetId: str(unit.id),
|
|
11980
12063
|
damage
|
|
11981
12064
|
});
|
|
11982
12065
|
}
|
|
@@ -11991,9 +12074,9 @@ function BattleBoard({
|
|
|
11991
12074
|
if (currentPhase === "movement" && selectedUnit) {
|
|
11992
12075
|
if (movementAnimRef.current) return;
|
|
11993
12076
|
if (validMoves.some((m) => m.x === x && m.y === y)) {
|
|
11994
|
-
const from = { ...selectedUnit
|
|
12077
|
+
const from = { ...unitPosition(selectedUnit) };
|
|
11995
12078
|
const to = { x, y };
|
|
11996
|
-
startMoveAnimation(selectedUnit.id, from, to, () => {
|
|
12079
|
+
startMoveAnimation(str(selectedUnit.id), from, to, () => {
|
|
11997
12080
|
onUnitMove?.(selectedUnit, to);
|
|
11998
12081
|
});
|
|
11999
12082
|
}
|
|
@@ -12151,6 +12234,7 @@ var init_BattleBoard = __esm({
|
|
|
12151
12234
|
init_Typography();
|
|
12152
12235
|
init_Stack();
|
|
12153
12236
|
init_IsometricCanvas2();
|
|
12237
|
+
init_boardEntity();
|
|
12154
12238
|
init_isometric();
|
|
12155
12239
|
BattleBoard.displayName = "BattleBoard";
|
|
12156
12240
|
}
|
|
@@ -13373,24 +13457,24 @@ var init_CodeBlock = __esm({
|
|
|
13373
13457
|
return;
|
|
13374
13458
|
}
|
|
13375
13459
|
lineEls.forEach((el) => {
|
|
13376
|
-
const
|
|
13377
|
-
if (hiddenLines.has(
|
|
13460
|
+
const num2 = parseInt(el.getAttribute("data-line") ?? "-1", 10);
|
|
13461
|
+
if (hiddenLines.has(num2)) {
|
|
13378
13462
|
el.style.display = "none";
|
|
13379
13463
|
return;
|
|
13380
13464
|
}
|
|
13381
13465
|
el.style.display = "";
|
|
13382
13466
|
el.style.position = "relative";
|
|
13383
13467
|
el.style.paddingLeft = "1.2em";
|
|
13384
|
-
const region = foldStartMap.get(
|
|
13468
|
+
const region = foldStartMap.get(num2);
|
|
13385
13469
|
if (!region) return;
|
|
13386
|
-
const isCollapsed = collapsed.has(
|
|
13470
|
+
const isCollapsed = collapsed.has(num2);
|
|
13387
13471
|
const toggle = document.createElement("span");
|
|
13388
13472
|
toggle.className = "fold-toggle";
|
|
13389
13473
|
toggle.textContent = isCollapsed ? "\u25B6" : "\u25BC";
|
|
13390
13474
|
toggle.style.cssText = "position:absolute;left:0;top:0;width:1.2em;text-align:center;cursor:pointer;color:#858585;font-size:10px;user-select:none;line-height:inherit;height:100%";
|
|
13391
13475
|
toggle.addEventListener("click", (e) => {
|
|
13392
13476
|
e.stopPropagation();
|
|
13393
|
-
toggleFoldRef.current(
|
|
13477
|
+
toggleFoldRef.current(num2);
|
|
13394
13478
|
});
|
|
13395
13479
|
el.insertBefore(toggle, el.firstChild);
|
|
13396
13480
|
if (isCollapsed) {
|
|
@@ -15643,10 +15727,13 @@ var init_BookChapterView = __esm({
|
|
|
15643
15727
|
init_cn();
|
|
15644
15728
|
BookChapterView = ({
|
|
15645
15729
|
chapter,
|
|
15730
|
+
orbitalSchema,
|
|
15646
15731
|
direction,
|
|
15647
15732
|
className
|
|
15648
15733
|
}) => {
|
|
15649
15734
|
const { t: _t } = useTranslate();
|
|
15735
|
+
const title = String(chapter.title ?? "");
|
|
15736
|
+
const content = String(chapter.content ?? "");
|
|
15650
15737
|
return /* @__PURE__ */ jsxs(
|
|
15651
15738
|
VStack,
|
|
15652
15739
|
{
|
|
@@ -15654,16 +15741,16 @@ var init_BookChapterView = __esm({
|
|
|
15654
15741
|
className: cn("px-6 py-8 max-w-4xl mx-auto w-full", className),
|
|
15655
15742
|
style: { direction },
|
|
15656
15743
|
children: [
|
|
15657
|
-
/* @__PURE__ */ jsx(Typography, { variant: "h1", className: "text-3xl font-bold", children:
|
|
15744
|
+
/* @__PURE__ */ jsx(Typography, { variant: "h1", className: "text-3xl font-bold", children: title }),
|
|
15658
15745
|
/* @__PURE__ */ jsx(Divider, {}),
|
|
15659
|
-
!!
|
|
15746
|
+
!!orbitalSchema && /* @__PURE__ */ jsx(ScaledDiagram, { children: /* @__PURE__ */ jsx(
|
|
15660
15747
|
JazariStateMachine,
|
|
15661
15748
|
{
|
|
15662
|
-
schema:
|
|
15749
|
+
schema: orbitalSchema,
|
|
15663
15750
|
direction
|
|
15664
15751
|
}
|
|
15665
15752
|
) }),
|
|
15666
|
-
/* @__PURE__ */ jsx(ContentRenderer, { content
|
|
15753
|
+
/* @__PURE__ */ jsx(ContentRenderer, { content, direction })
|
|
15667
15754
|
]
|
|
15668
15755
|
}
|
|
15669
15756
|
);
|
|
@@ -15761,7 +15848,7 @@ var init_BookNavBar = __esm({
|
|
|
15761
15848
|
BookNavBar = ({
|
|
15762
15849
|
currentPage,
|
|
15763
15850
|
totalPages,
|
|
15764
|
-
chapterTitle,
|
|
15851
|
+
chapterTitle: chapterTitle2,
|
|
15765
15852
|
direction,
|
|
15766
15853
|
className
|
|
15767
15854
|
}) => {
|
|
@@ -15802,12 +15889,12 @@ var init_BookNavBar = __esm({
|
|
|
15802
15889
|
)
|
|
15803
15890
|
] }),
|
|
15804
15891
|
/* @__PURE__ */ jsxs(Box, { className: "flex-1 mx-4 max-w-md", children: [
|
|
15805
|
-
|
|
15892
|
+
chapterTitle2 && /* @__PURE__ */ jsx(
|
|
15806
15893
|
Typography,
|
|
15807
15894
|
{
|
|
15808
15895
|
variant: "caption",
|
|
15809
15896
|
className: "text-center block truncate text-muted-foreground",
|
|
15810
|
-
children:
|
|
15897
|
+
children: chapterTitle2
|
|
15811
15898
|
}
|
|
15812
15899
|
),
|
|
15813
15900
|
/* @__PURE__ */ jsx(ProgressBar, { value: progress, size: "sm", variant: "primary" })
|
|
@@ -15874,31 +15961,35 @@ var init_BookTableOfContents = __esm({
|
|
|
15874
15961
|
style: { direction },
|
|
15875
15962
|
children: [
|
|
15876
15963
|
/* @__PURE__ */ jsx(Typography, { variant: "h1", className: "text-3xl font-bold text-center mb-4", children: t("book.tableOfContents") }),
|
|
15877
|
-
parts.map((part, partIdx) =>
|
|
15878
|
-
|
|
15879
|
-
|
|
15880
|
-
/* @__PURE__ */
|
|
15881
|
-
|
|
15882
|
-
|
|
15883
|
-
|
|
15884
|
-
|
|
15885
|
-
|
|
15886
|
-
|
|
15887
|
-
|
|
15888
|
-
|
|
15889
|
-
|
|
15890
|
-
|
|
15891
|
-
|
|
15892
|
-
|
|
15893
|
-
|
|
15894
|
-
|
|
15895
|
-
|
|
15896
|
-
|
|
15897
|
-
|
|
15898
|
-
|
|
15899
|
-
|
|
15900
|
-
|
|
15901
|
-
|
|
15964
|
+
parts.map((part, partIdx) => {
|
|
15965
|
+
const chapters = Array.isArray(part.chapters) ? part.chapters : [];
|
|
15966
|
+
return /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
|
|
15967
|
+
/* @__PURE__ */ jsxs(HStack, { gap: "sm", align: "center", children: [
|
|
15968
|
+
/* @__PURE__ */ jsx(Badge, { variant: "default", size: "sm", children: t("book.partNumber", { number: String(partIdx + 1) }) }),
|
|
15969
|
+
/* @__PURE__ */ jsx(Typography, { variant: "h3", className: "font-semibold", children: String(part.title ?? "") })
|
|
15970
|
+
] }),
|
|
15971
|
+
/* @__PURE__ */ jsx(VStack, { gap: "xs", className: direction === "rtl" ? "pr-6" : "pl-6", children: chapters.map((chapter) => {
|
|
15972
|
+
const id = chapter.id == null ? "" : String(chapter.id);
|
|
15973
|
+
const isCurrent = id === currentChapterId;
|
|
15974
|
+
return /* @__PURE__ */ jsx(
|
|
15975
|
+
Button,
|
|
15976
|
+
{
|
|
15977
|
+
variant: "ghost",
|
|
15978
|
+
size: "sm",
|
|
15979
|
+
action: "BOOK_NAVIGATE",
|
|
15980
|
+
actionPayload: { chapterId: id },
|
|
15981
|
+
className: cn(
|
|
15982
|
+
"justify-start text-left w-full",
|
|
15983
|
+
direction === "rtl" && "text-right",
|
|
15984
|
+
isCurrent && "bg-blue-50 dark:bg-blue-950 text-blue-600 dark:text-blue-400"
|
|
15985
|
+
),
|
|
15986
|
+
children: /* @__PURE__ */ jsx(Box, { className: "truncate", children: /* @__PURE__ */ jsx(Typography, { variant: "body", children: String(chapter.title ?? "") }) })
|
|
15987
|
+
},
|
|
15988
|
+
id
|
|
15989
|
+
);
|
|
15990
|
+
}) })
|
|
15991
|
+
] }, partIdx);
|
|
15992
|
+
})
|
|
15902
15993
|
]
|
|
15903
15994
|
}
|
|
15904
15995
|
);
|
|
@@ -16020,27 +16111,41 @@ function resolveFieldMap(fieldMap) {
|
|
|
16020
16111
|
function get(obj, key) {
|
|
16021
16112
|
return obj[key];
|
|
16022
16113
|
}
|
|
16114
|
+
function asStr(v) {
|
|
16115
|
+
return v == null ? "" : String(v);
|
|
16116
|
+
}
|
|
16023
16117
|
function mapBookData(raw, fields = IDENTITY_BOOK_FIELDS) {
|
|
16024
16118
|
const rawParts = get(raw, fields.parts) ?? [];
|
|
16025
|
-
|
|
16026
|
-
|
|
16027
|
-
|
|
16028
|
-
|
|
16029
|
-
|
|
16030
|
-
|
|
16031
|
-
|
|
16032
|
-
const rawChapters = get(part, fields.chapters) ?? [];
|
|
16033
|
-
return {
|
|
16034
|
-
title: get(part, fields.partTitle) ?? "",
|
|
16035
|
-
chapters: rawChapters.map((ch) => ({
|
|
16036
|
-
id: get(ch, fields.chapterId) ?? "",
|
|
16037
|
-
title: get(ch, fields.chapterTitle) ?? "",
|
|
16038
|
-
content: get(ch, fields.chapterContent) ?? "",
|
|
16039
|
-
orbitalSchema: get(ch, fields.chapterOrbitalSchema)
|
|
16040
|
-
}))
|
|
16041
|
-
};
|
|
16042
|
-
})
|
|
16119
|
+
const direction = get(raw, fields.direction) ?? "ltr";
|
|
16120
|
+
const cover = {
|
|
16121
|
+
title: asStr(get(raw, fields.title)),
|
|
16122
|
+
subtitle: asStr(get(raw, fields.subtitle)),
|
|
16123
|
+
author: asStr(get(raw, fields.author)),
|
|
16124
|
+
coverImageUrl: asStr(get(raw, fields.coverImageUrl)),
|
|
16125
|
+
direction
|
|
16043
16126
|
};
|
|
16127
|
+
const schemaByChapterId = {};
|
|
16128
|
+
const chapters = [];
|
|
16129
|
+
const parts = rawParts.map((part) => {
|
|
16130
|
+
const rawChapters = get(part, fields.chapters) ?? [];
|
|
16131
|
+
const chapterRows = rawChapters.map((ch) => {
|
|
16132
|
+
const id = asStr(get(ch, fields.chapterId));
|
|
16133
|
+
const schema = get(ch, fields.chapterOrbitalSchema);
|
|
16134
|
+
if (schema) schemaByChapterId[id] = schema;
|
|
16135
|
+
const row = {
|
|
16136
|
+
id,
|
|
16137
|
+
title: asStr(get(ch, fields.chapterTitle)),
|
|
16138
|
+
content: asStr(get(ch, fields.chapterContent))
|
|
16139
|
+
};
|
|
16140
|
+
chapters.push(row);
|
|
16141
|
+
return row;
|
|
16142
|
+
});
|
|
16143
|
+
return {
|
|
16144
|
+
title: asStr(get(part, fields.partTitle)),
|
|
16145
|
+
chapters: chapterRows
|
|
16146
|
+
};
|
|
16147
|
+
});
|
|
16148
|
+
return { cover, direction, parts, chapters, schemaByChapterId };
|
|
16044
16149
|
}
|
|
16045
16150
|
var IDENTITY_BOOK_FIELDS, AR_BOOK_FIELDS, FIELD_MAP_REGISTRY;
|
|
16046
16151
|
var init_types2 = __esm({
|
|
@@ -16078,10 +16183,7 @@ var init_types2 = __esm({
|
|
|
16078
16183
|
};
|
|
16079
16184
|
}
|
|
16080
16185
|
});
|
|
16081
|
-
|
|
16082
|
-
return book.parts.flatMap((part) => part.chapters);
|
|
16083
|
-
}
|
|
16084
|
-
var PRINT_STYLES, BookViewer;
|
|
16186
|
+
var chapterId, chapterTitle, PRINT_STYLES, BookViewer;
|
|
16085
16187
|
var init_BookViewer = __esm({
|
|
16086
16188
|
"components/marketing/organisms/book/BookViewer.tsx"() {
|
|
16087
16189
|
init_Box();
|
|
@@ -16094,6 +16196,8 @@ var init_BookViewer = __esm({
|
|
|
16094
16196
|
init_BookNavBar();
|
|
16095
16197
|
init_EmptyState();
|
|
16096
16198
|
init_types2();
|
|
16199
|
+
chapterId = (ch) => ch?.id == null ? void 0 : String(ch.id);
|
|
16200
|
+
chapterTitle = (ch) => ch?.title == null ? void 0 : String(ch.title);
|
|
16097
16201
|
PRINT_STYLES = `
|
|
16098
16202
|
@media print {
|
|
16099
16203
|
.book-viewer-page {
|
|
@@ -16122,14 +16226,14 @@ var init_BookViewer = __esm({
|
|
|
16122
16226
|
return mapBookData(raw, resolvedFieldMap);
|
|
16123
16227
|
}, [entity, resolvedFieldMap]);
|
|
16124
16228
|
const direction = book?.direction ?? "ltr";
|
|
16125
|
-
const chapters = useMemo(() => book ?
|
|
16229
|
+
const chapters = useMemo(() => book ? book.chapters : [], [book]);
|
|
16126
16230
|
const totalPages = 2 + chapters.length;
|
|
16127
16231
|
const navigateTo = useCallback(
|
|
16128
16232
|
(page) => {
|
|
16129
16233
|
const clamped = Math.max(0, Math.min(page, totalPages - 1));
|
|
16130
16234
|
setCurrentPage(clamped);
|
|
16131
|
-
const
|
|
16132
|
-
eventBus.emit("UI:BOOK_PAGE_CHANGE", { pageIndex: clamped, chapterId });
|
|
16235
|
+
const id = clamped >= 2 ? chapterId(chapters[clamped - 2]) : void 0;
|
|
16236
|
+
eventBus.emit("UI:BOOK_PAGE_CHANGE", { pageIndex: clamped, chapterId: id });
|
|
16133
16237
|
},
|
|
16134
16238
|
[totalPages, chapters, eventBus]
|
|
16135
16239
|
);
|
|
@@ -16141,8 +16245,8 @@ var init_BookViewer = __esm({
|
|
|
16141
16245
|
eventBus.on("UI:BOOK_PAGE_NEXT", () => navigateTo(currentPage + 1)),
|
|
16142
16246
|
eventBus.on("UI:BOOK_PRINT", () => window.print()),
|
|
16143
16247
|
eventBus.on("UI:BOOK_NAVIGATE", (event) => {
|
|
16144
|
-
const
|
|
16145
|
-
const idx = chapters.findIndex((ch) => ch
|
|
16248
|
+
const targetId = event.payload?.chapterId;
|
|
16249
|
+
const idx = chapters.findIndex((ch) => chapterId(ch) === targetId);
|
|
16146
16250
|
if (idx >= 0) navigateTo(idx + 2);
|
|
16147
16251
|
})
|
|
16148
16252
|
];
|
|
@@ -16159,9 +16263,11 @@ var init_BookViewer = __esm({
|
|
|
16159
16263
|
style.remove();
|
|
16160
16264
|
};
|
|
16161
16265
|
}, []);
|
|
16162
|
-
const currentChapterId = currentPage >= 2 ? chapters[currentPage - 2]
|
|
16163
|
-
const currentChapterTitle = currentPage >= 2 ? chapters[currentPage - 2]
|
|
16266
|
+
const currentChapterId = currentPage >= 2 ? chapterId(chapters[currentPage - 2]) : void 0;
|
|
16267
|
+
const currentChapterTitle = currentPage >= 2 ? chapterTitle(chapters[currentPage - 2]) : void 0;
|
|
16164
16268
|
if (!book) return /* @__PURE__ */ jsx(EmptyState, { message: t("book.noData") });
|
|
16269
|
+
const cover = book.cover;
|
|
16270
|
+
const coverTitle = String(cover.title ?? "");
|
|
16165
16271
|
return /* @__PURE__ */ jsxs(VStack, { className: cn("relative h-full overflow-hidden bg-background", className), children: [
|
|
16166
16272
|
/* @__PURE__ */ jsxs(
|
|
16167
16273
|
Box,
|
|
@@ -16173,10 +16279,10 @@ var init_BookViewer = __esm({
|
|
|
16173
16279
|
/* @__PURE__ */ jsx(
|
|
16174
16280
|
BookCoverPage,
|
|
16175
16281
|
{
|
|
16176
|
-
title:
|
|
16177
|
-
subtitle:
|
|
16178
|
-
author:
|
|
16179
|
-
coverImageUrl:
|
|
16282
|
+
title: coverTitle,
|
|
16283
|
+
subtitle: String(cover.subtitle ?? "") || void 0,
|
|
16284
|
+
author: String(cover.author ?? "") || void 0,
|
|
16285
|
+
coverImageUrl: String(cover.coverImageUrl ?? "") || void 0,
|
|
16180
16286
|
direction
|
|
16181
16287
|
}
|
|
16182
16288
|
),
|
|
@@ -16187,23 +16293,27 @@ var init_BookViewer = __esm({
|
|
|
16187
16293
|
direction
|
|
16188
16294
|
}
|
|
16189
16295
|
),
|
|
16190
|
-
chapters.map((chapter) =>
|
|
16191
|
-
|
|
16192
|
-
|
|
16193
|
-
|
|
16194
|
-
|
|
16195
|
-
|
|
16196
|
-
|
|
16197
|
-
|
|
16296
|
+
chapters.map((chapter) => {
|
|
16297
|
+
const id = chapterId(chapter);
|
|
16298
|
+
return /* @__PURE__ */ jsx(
|
|
16299
|
+
BookChapterView,
|
|
16300
|
+
{
|
|
16301
|
+
chapter,
|
|
16302
|
+
orbitalSchema: id ? book.schemaByChapterId[id] : void 0,
|
|
16303
|
+
direction
|
|
16304
|
+
},
|
|
16305
|
+
id
|
|
16306
|
+
);
|
|
16307
|
+
})
|
|
16198
16308
|
] }),
|
|
16199
16309
|
/* @__PURE__ */ jsxs(Box, { className: "print:hidden", children: [
|
|
16200
16310
|
currentPage === 0 && /* @__PURE__ */ jsx(
|
|
16201
16311
|
BookCoverPage,
|
|
16202
16312
|
{
|
|
16203
|
-
title:
|
|
16204
|
-
subtitle:
|
|
16205
|
-
author:
|
|
16206
|
-
coverImageUrl:
|
|
16313
|
+
title: coverTitle,
|
|
16314
|
+
subtitle: String(cover.subtitle ?? "") || void 0,
|
|
16315
|
+
author: String(cover.author ?? "") || void 0,
|
|
16316
|
+
coverImageUrl: String(cover.coverImageUrl ?? "") || void 0,
|
|
16207
16317
|
direction
|
|
16208
16318
|
}
|
|
16209
16319
|
),
|
|
@@ -16219,6 +16329,7 @@ var init_BookViewer = __esm({
|
|
|
16219
16329
|
BookChapterView,
|
|
16220
16330
|
{
|
|
16221
16331
|
chapter: chapters[currentPage - 2],
|
|
16332
|
+
orbitalSchema: currentChapterId ? book.schemaByChapterId[currentChapterId] : void 0,
|
|
16222
16333
|
direction
|
|
16223
16334
|
}
|
|
16224
16335
|
)
|
|
@@ -16231,7 +16342,7 @@ var init_BookViewer = __esm({
|
|
|
16231
16342
|
{
|
|
16232
16343
|
currentPage,
|
|
16233
16344
|
totalPages,
|
|
16234
|
-
chapterTitle: currentPage === 0 ?
|
|
16345
|
+
chapterTitle: currentPage === 0 ? coverTitle : currentPage === 1 ? t("book.tableOfContents") : currentChapterTitle,
|
|
16235
16346
|
direction
|
|
16236
16347
|
}
|
|
16237
16348
|
)
|
|
@@ -16329,7 +16440,7 @@ var init_Grid = __esm({
|
|
|
16329
16440
|
};
|
|
16330
16441
|
Grid = ({
|
|
16331
16442
|
cols = 1,
|
|
16332
|
-
rows,
|
|
16443
|
+
rows: rows2,
|
|
16333
16444
|
gap = "md",
|
|
16334
16445
|
rowGap,
|
|
16335
16446
|
colGap,
|
|
@@ -16341,7 +16452,7 @@ var init_Grid = __esm({
|
|
|
16341
16452
|
children,
|
|
16342
16453
|
as: Component = "div"
|
|
16343
16454
|
}) => {
|
|
16344
|
-
const mergedStyle =
|
|
16455
|
+
const mergedStyle = rows2 ? { gridTemplateRows: `repeat(${rows2}, minmax(0, 1fr))`, ...style } : style;
|
|
16345
16456
|
return React84__default.createElement(
|
|
16346
16457
|
Component,
|
|
16347
16458
|
{
|
|
@@ -17057,14 +17168,14 @@ function BuilderBoard({
|
|
|
17057
17168
|
}) {
|
|
17058
17169
|
const { emit } = useEventBus();
|
|
17059
17170
|
const { t } = useTranslate();
|
|
17060
|
-
const resolved =
|
|
17171
|
+
const resolved = boardEntity(entity);
|
|
17061
17172
|
const [placements, setPlacements] = useState({});
|
|
17062
17173
|
const [headerError, setHeaderError] = useState(false);
|
|
17063
17174
|
const [submitted, setSubmitted] = useState(false);
|
|
17064
17175
|
const [attempts, setAttempts] = useState(0);
|
|
17065
17176
|
const [showHint, setShowHint] = useState(false);
|
|
17066
|
-
const components = resolved?.components
|
|
17067
|
-
const slots = resolved?.slots
|
|
17177
|
+
const components = Array.isArray(resolved?.components) ? resolved.components : [];
|
|
17178
|
+
const slots = Array.isArray(resolved?.slots) ? resolved.slots : [];
|
|
17068
17179
|
const usedComponentIds = new Set(Object.values(placements));
|
|
17069
17180
|
const availableComponents = components.filter((c) => !usedComponentIds.has(c.id));
|
|
17070
17181
|
const [selectedComponent, setSelectedComponent] = useState(null);
|
|
@@ -17098,7 +17209,7 @@ function BuilderBoard({
|
|
|
17098
17209
|
}, [slots, placements, attempts, completeEvent, emit]);
|
|
17099
17210
|
const handleReset = () => {
|
|
17100
17211
|
setSubmitted(false);
|
|
17101
|
-
if (attempts >= 2 && resolved?.hint) {
|
|
17212
|
+
if (attempts >= 2 && str(resolved?.hint)) {
|
|
17102
17213
|
setShowHint(true);
|
|
17103
17214
|
}
|
|
17104
17215
|
};
|
|
@@ -17111,20 +17222,24 @@ function BuilderBoard({
|
|
|
17111
17222
|
};
|
|
17112
17223
|
const getComponentById = (id) => components.find((c) => c.id === id);
|
|
17113
17224
|
if (!resolved) return null;
|
|
17225
|
+
const theme = resolved.theme ?? void 0;
|
|
17226
|
+
const themeBackground = theme?.background;
|
|
17227
|
+
const headerImage = str(resolved.headerImage);
|
|
17228
|
+
const hint = str(resolved.hint);
|
|
17114
17229
|
return /* @__PURE__ */ jsx(
|
|
17115
17230
|
Box,
|
|
17116
17231
|
{
|
|
17117
17232
|
className,
|
|
17118
17233
|
style: {
|
|
17119
|
-
backgroundImage:
|
|
17234
|
+
backgroundImage: themeBackground ? `url(${themeBackground})` : void 0,
|
|
17120
17235
|
backgroundSize: "cover",
|
|
17121
17236
|
backgroundPosition: "center"
|
|
17122
17237
|
},
|
|
17123
17238
|
children: /* @__PURE__ */ jsxs(VStack, { gap: "lg", className: "p-4", children: [
|
|
17124
|
-
|
|
17239
|
+
headerImage && !headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 overflow-hidden rounded-container", children: /* @__PURE__ */ jsx("img", { src: headerImage, alt: "", onError: () => setHeaderError(true), className: "w-full h-full object-cover" }) }) : headerImage && headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 rounded-container bg-gradient-to-br from-muted to-accent opacity-60" }) : null,
|
|
17125
17240
|
/* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
|
|
17126
|
-
/* @__PURE__ */ jsx(Typography, { variant: "h4", weight: "bold", children: resolved.title }),
|
|
17127
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body", children: resolved.description })
|
|
17241
|
+
/* @__PURE__ */ jsx(Typography, { variant: "h4", weight: "bold", children: str(resolved.title) }),
|
|
17242
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body", children: str(resolved.description) })
|
|
17128
17243
|
] }) }),
|
|
17129
17244
|
/* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
|
|
17130
17245
|
/* @__PURE__ */ jsx(Typography, { variant: "small", weight: "bold", className: "uppercase tracking-wider text-muted-foreground", children: t("builder.components") }),
|
|
@@ -17184,9 +17299,9 @@ function BuilderBoard({
|
|
|
17184
17299
|
] }) }),
|
|
17185
17300
|
submitted && /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", align: "center", children: [
|
|
17186
17301
|
/* @__PURE__ */ jsx(Icon, { icon: allCorrect ? CheckCircle : XCircle, size: "lg", className: allCorrect ? "text-success" : "text-error" }),
|
|
17187
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body", weight: "bold", children: allCorrect ? resolved.successMessage
|
|
17302
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body", weight: "bold", children: allCorrect ? str(resolved.successMessage) || t("builder.success") : str(resolved.failMessage) || t("builder.incorrect") })
|
|
17188
17303
|
] }) }),
|
|
17189
|
-
showHint &&
|
|
17304
|
+
showHint && hint && /* @__PURE__ */ jsx(Card, { className: "p-4 border-l-4 border-l-warning", children: /* @__PURE__ */ jsx(Typography, { variant: "body", children: hint }) }),
|
|
17190
17305
|
/* @__PURE__ */ jsxs(HStack, { gap: "sm", justify: "center", children: [
|
|
17191
17306
|
!submitted ? /* @__PURE__ */ jsxs(Button, { variant: "primary", onClick: handleSubmit, disabled: !allPlaced, children: [
|
|
17192
17307
|
/* @__PURE__ */ jsx(Icon, { icon: Wrench, size: "sm" }),
|
|
@@ -17205,6 +17320,7 @@ var init_BuilderBoard = __esm({
|
|
|
17205
17320
|
"components/game/organisms/puzzles/builder/BuilderBoard.tsx"() {
|
|
17206
17321
|
init_atoms2();
|
|
17207
17322
|
init_useEventBus();
|
|
17323
|
+
init_boardEntity();
|
|
17208
17324
|
BuilderBoard.displayName = "BuilderBoard";
|
|
17209
17325
|
}
|
|
17210
17326
|
});
|
|
@@ -17542,21 +17658,24 @@ function CalendarGrid({
|
|
|
17542
17658
|
eventBus.emit(`UI:${longPressEvent}`, { date: day.toISOString(), time, ...longPressPayload });
|
|
17543
17659
|
}, 500);
|
|
17544
17660
|
}, [longPressEvent, longPressPayload, eventBus]);
|
|
17545
|
-
const renderEvent = (event) =>
|
|
17546
|
-
|
|
17547
|
-
|
|
17548
|
-
|
|
17549
|
-
|
|
17550
|
-
|
|
17551
|
-
|
|
17552
|
-
|
|
17553
|
-
|
|
17554
|
-
|
|
17555
|
-
|
|
17556
|
-
|
|
17557
|
-
|
|
17558
|
-
|
|
17559
|
-
|
|
17661
|
+
const renderEvent = (event) => {
|
|
17662
|
+
const color = event.color;
|
|
17663
|
+
return /* @__PURE__ */ jsx(
|
|
17664
|
+
Box,
|
|
17665
|
+
{
|
|
17666
|
+
rounded: "md",
|
|
17667
|
+
padding: "xs",
|
|
17668
|
+
border: true,
|
|
17669
|
+
className: cn(
|
|
17670
|
+
"cursor-pointer hover:shadow-sm transition-shadow text-xs truncate",
|
|
17671
|
+
color ? color : "bg-blue-500/15 border-blue-500/30 text-blue-600"
|
|
17672
|
+
),
|
|
17673
|
+
onClick: (e) => handleEventClick(event, e),
|
|
17674
|
+
children: /* @__PURE__ */ jsx(Typography, { variant: "small", className: "truncate font-medium", children: event.title })
|
|
17675
|
+
},
|
|
17676
|
+
event.id
|
|
17677
|
+
);
|
|
17678
|
+
};
|
|
17560
17679
|
return /* @__PURE__ */ jsxs(
|
|
17561
17680
|
Box,
|
|
17562
17681
|
{
|
|
@@ -19220,7 +19339,6 @@ var init_CardGrid = __esm({
|
|
|
19220
19339
|
alignItems = "stretch",
|
|
19221
19340
|
className,
|
|
19222
19341
|
children,
|
|
19223
|
-
// EntityDisplayProps
|
|
19224
19342
|
entity,
|
|
19225
19343
|
isLoading = false,
|
|
19226
19344
|
error = null,
|
|
@@ -19692,14 +19810,14 @@ var init_CaseStudyOrganism = __esm({
|
|
|
19692
19810
|
/* @__PURE__ */ jsx(SimpleGrid, { cols: cols > 0 ? cols : 1, gap: "lg", children: items.map((study) => /* @__PURE__ */ jsx(
|
|
19693
19811
|
CaseStudyCard,
|
|
19694
19812
|
{
|
|
19695
|
-
title: study.title,
|
|
19696
|
-
description: study.description,
|
|
19697
|
-
category: study.category,
|
|
19698
|
-
categoryColor: study.categoryColor,
|
|
19699
|
-
href: study.href,
|
|
19700
|
-
linkLabel: study.linkLabel
|
|
19813
|
+
title: String(study.title ?? ""),
|
|
19814
|
+
description: String(study.description ?? ""),
|
|
19815
|
+
category: String(study.category ?? ""),
|
|
19816
|
+
categoryColor: study.categoryColor != null ? String(study.categoryColor) : void 0,
|
|
19817
|
+
href: String(study.href ?? ""),
|
|
19818
|
+
linkLabel: study.linkLabel != null ? String(study.linkLabel) : void 0
|
|
19701
19819
|
},
|
|
19702
|
-
study.id
|
|
19820
|
+
String(study.id ?? "")
|
|
19703
19821
|
)) })
|
|
19704
19822
|
] });
|
|
19705
19823
|
};
|
|
@@ -19722,10 +19840,10 @@ function CastleBoard({
|
|
|
19722
19840
|
className
|
|
19723
19841
|
}) {
|
|
19724
19842
|
const eventBus = useEventBus();
|
|
19725
|
-
const resolved =
|
|
19726
|
-
const tiles = resolved?.tiles
|
|
19727
|
-
const features = resolved?.features
|
|
19728
|
-
const units = resolved?.units
|
|
19843
|
+
const resolved = boardEntity(entity);
|
|
19844
|
+
const tiles = Array.isArray(resolved?.tiles) ? resolved.tiles : [];
|
|
19845
|
+
const features = Array.isArray(resolved?.features) ? resolved.features : [];
|
|
19846
|
+
const units = Array.isArray(resolved?.units) ? resolved.units : [];
|
|
19729
19847
|
const assetManifest = resolved?.assetManifest;
|
|
19730
19848
|
const backgroundImage = resolved?.backgroundImage;
|
|
19731
19849
|
const [hoveredTile, setHoveredTile] = useState(null);
|
|
@@ -19753,7 +19871,7 @@ function CastleBoard({
|
|
|
19753
19871
|
onFeatureClick?.(feature);
|
|
19754
19872
|
if (featureClickEvent) {
|
|
19755
19873
|
eventBus.emit(`UI:${featureClickEvent}`, {
|
|
19756
|
-
featureId: feature.id,
|
|
19874
|
+
featureId: feature.id ?? "",
|
|
19757
19875
|
featureType: feature.type,
|
|
19758
19876
|
x: feature.x,
|
|
19759
19877
|
y: feature.y
|
|
@@ -19821,6 +19939,7 @@ var init_CastleBoard = __esm({
|
|
|
19821
19939
|
init_cn();
|
|
19822
19940
|
init_useEventBus();
|
|
19823
19941
|
init_IsometricCanvas2();
|
|
19942
|
+
init_boardEntity();
|
|
19824
19943
|
init_isometric();
|
|
19825
19944
|
CastleBoard.displayName = "CastleBoard";
|
|
19826
19945
|
}
|
|
@@ -20631,14 +20750,14 @@ function ClassifierBoard({
|
|
|
20631
20750
|
}) {
|
|
20632
20751
|
const { emit } = useEventBus();
|
|
20633
20752
|
const { t } = useTranslate();
|
|
20634
|
-
const resolved =
|
|
20753
|
+
const resolved = boardEntity(entity);
|
|
20635
20754
|
const [assignments, setAssignments] = useState({});
|
|
20636
20755
|
const [headerError, setHeaderError] = useState(false);
|
|
20637
20756
|
const [submitted, setSubmitted] = useState(false);
|
|
20638
20757
|
const [attempts, setAttempts] = useState(0);
|
|
20639
20758
|
const [showHint, setShowHint] = useState(false);
|
|
20640
|
-
const items = resolved?.items
|
|
20641
|
-
const categories = resolved?.categories
|
|
20759
|
+
const items = Array.isArray(resolved?.items) ? resolved.items : [];
|
|
20760
|
+
const categories = Array.isArray(resolved?.categories) ? resolved.categories : [];
|
|
20642
20761
|
const unassignedItems = items.filter((item) => !assignments[item.id]);
|
|
20643
20762
|
const allAssigned = Object.keys(assignments).length === items.length;
|
|
20644
20763
|
const results = submitted ? items.map((item) => ({
|
|
@@ -20670,7 +20789,7 @@ function ClassifierBoard({
|
|
|
20670
20789
|
}, [items, assignments, attempts, completeEvent, emit]);
|
|
20671
20790
|
const handleReset = () => {
|
|
20672
20791
|
setSubmitted(false);
|
|
20673
|
-
if (attempts >= 2 && resolved?.hint) {
|
|
20792
|
+
if (attempts >= 2 && str(resolved?.hint)) {
|
|
20674
20793
|
setShowHint(true);
|
|
20675
20794
|
}
|
|
20676
20795
|
};
|
|
@@ -20681,20 +20800,25 @@ function ClassifierBoard({
|
|
|
20681
20800
|
setShowHint(false);
|
|
20682
20801
|
};
|
|
20683
20802
|
if (!resolved) return null;
|
|
20803
|
+
const theme = resolved.theme ?? void 0;
|
|
20804
|
+
const themeBackground = theme?.background;
|
|
20805
|
+
const headerImage = str(resolved.headerImage);
|
|
20806
|
+
const hint = str(resolved.hint);
|
|
20807
|
+
const failMessage = str(resolved.failMessage);
|
|
20684
20808
|
return /* @__PURE__ */ jsx(
|
|
20685
20809
|
Box,
|
|
20686
20810
|
{
|
|
20687
20811
|
className,
|
|
20688
20812
|
style: {
|
|
20689
|
-
backgroundImage:
|
|
20813
|
+
backgroundImage: themeBackground ? `url(${themeBackground})` : void 0,
|
|
20690
20814
|
backgroundSize: "cover",
|
|
20691
20815
|
backgroundPosition: "center"
|
|
20692
20816
|
},
|
|
20693
20817
|
children: /* @__PURE__ */ jsxs(VStack, { gap: "lg", className: "p-4", children: [
|
|
20694
|
-
|
|
20818
|
+
headerImage && !headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 overflow-hidden rounded-container", children: /* @__PURE__ */ jsx("img", { src: headerImage, alt: "", onError: () => setHeaderError(true), className: "w-full h-full object-cover" }) }) : headerImage && headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 rounded-container bg-gradient-to-br from-muted to-accent opacity-60" }) : null,
|
|
20695
20819
|
/* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
|
|
20696
|
-
/* @__PURE__ */ jsx(Typography, { variant: "h4", weight: "bold", children: resolved.title }),
|
|
20697
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body", children: resolved.description })
|
|
20820
|
+
/* @__PURE__ */ jsx(Typography, { variant: "h4", weight: "bold", children: str(resolved.title) }),
|
|
20821
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body", children: str(resolved.description) })
|
|
20698
20822
|
] }) }),
|
|
20699
20823
|
unassignedItems.length > 0 && /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
|
|
20700
20824
|
/* @__PURE__ */ jsx(Typography, { variant: "small", weight: "bold", className: "uppercase tracking-wider text-muted-foreground", children: t("classifier.itemsToSort") }),
|
|
@@ -20746,10 +20870,10 @@ function ClassifierBoard({
|
|
|
20746
20870
|
}) }),
|
|
20747
20871
|
submitted && /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", align: "center", children: [
|
|
20748
20872
|
/* @__PURE__ */ jsx(Icon, { icon: allCorrect ? CheckCircle : XCircle, size: "lg", className: allCorrect ? "text-success" : "text-error" }),
|
|
20749
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body", weight: "bold", children: allCorrect ? resolved.successMessage
|
|
20750
|
-
!allCorrect &&
|
|
20873
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body", weight: "bold", children: allCorrect ? str(resolved.successMessage) || t("classifier.allCorrect") : `${correctCount}/${items.length} ${t("classifier.correct")}` }),
|
|
20874
|
+
!allCorrect && failMessage && /* @__PURE__ */ jsx(Typography, { variant: "body", className: "text-muted-foreground", children: failMessage })
|
|
20751
20875
|
] }) }),
|
|
20752
|
-
showHint &&
|
|
20876
|
+
showHint && hint && /* @__PURE__ */ jsx(Card, { className: "p-4 border-l-4 border-l-warning", children: /* @__PURE__ */ jsx(Typography, { variant: "body", children: hint }) }),
|
|
20753
20877
|
/* @__PURE__ */ jsxs(HStack, { gap: "sm", justify: "center", children: [
|
|
20754
20878
|
!submitted ? /* @__PURE__ */ jsxs(Button, { variant: "primary", onClick: handleSubmit, disabled: !allAssigned, children: [
|
|
20755
20879
|
/* @__PURE__ */ jsx(Icon, { icon: Send, size: "sm" }),
|
|
@@ -20768,6 +20892,7 @@ var init_ClassifierBoard = __esm({
|
|
|
20768
20892
|
"components/game/organisms/puzzles/classifier/ClassifierBoard.tsx"() {
|
|
20769
20893
|
init_atoms2();
|
|
20770
20894
|
init_useEventBus();
|
|
20895
|
+
init_boardEntity();
|
|
20771
20896
|
ClassifierBoard.displayName = "ClassifierBoard";
|
|
20772
20897
|
}
|
|
20773
20898
|
});
|
|
@@ -27138,7 +27263,7 @@ function InventoryPanel({
|
|
|
27138
27263
|
const slotArray = Array.from({ length: safeSlots }, (_, index) => {
|
|
27139
27264
|
return safeItems[index] ?? null;
|
|
27140
27265
|
});
|
|
27141
|
-
const
|
|
27266
|
+
const rows2 = Math.ceil(safeSlots / safeColumns);
|
|
27142
27267
|
const handleSlotClick = useCallback((index) => {
|
|
27143
27268
|
if (selectSlotEvent) eventBus.emit(`UI:${selectSlotEvent}`, { index });
|
|
27144
27269
|
onSelectSlot?.(index);
|
|
@@ -27207,7 +27332,7 @@ function InventoryPanel({
|
|
|
27207
27332
|
className: "grid gap-1 bg-[var(--color-card)] p-2 rounded-container border border-border",
|
|
27208
27333
|
style: {
|
|
27209
27334
|
gridTemplateColumns: `repeat(${safeColumns}, ${slotSize}px)`,
|
|
27210
|
-
gridTemplateRows: `repeat(${
|
|
27335
|
+
gridTemplateRows: `repeat(${rows2}, ${slotSize}px)`
|
|
27211
27336
|
},
|
|
27212
27337
|
children: slotArray.map((item, index) => /* @__PURE__ */ jsx(
|
|
27213
27338
|
"button",
|
|
@@ -31171,11 +31296,11 @@ function LatticeSVG({
|
|
|
31171
31296
|
}) {
|
|
31172
31297
|
const paths = [];
|
|
31173
31298
|
const cols = 5;
|
|
31174
|
-
const
|
|
31299
|
+
const rows2 = Math.ceil(h / (w / cols));
|
|
31175
31300
|
const cellW = w / cols;
|
|
31176
31301
|
const cellH = cellW;
|
|
31177
31302
|
const bulge = cellW * 0.3;
|
|
31178
|
-
for (let row = 0; row <
|
|
31303
|
+
for (let row = 0; row < rows2; row++) {
|
|
31179
31304
|
for (let col = 0; col < cols; col++) {
|
|
31180
31305
|
const cx = col * cellW + cellW / 2;
|
|
31181
31306
|
const cy = row * cellH + cellH / 2;
|
|
@@ -31587,7 +31712,7 @@ var init_MatrixQuestion = __esm({
|
|
|
31587
31712
|
};
|
|
31588
31713
|
MatrixQuestion = ({
|
|
31589
31714
|
title,
|
|
31590
|
-
rows,
|
|
31715
|
+
rows: rows2,
|
|
31591
31716
|
columns = DEFAULT_MATRIX_COLUMNS,
|
|
31592
31717
|
values,
|
|
31593
31718
|
onChange,
|
|
@@ -31597,7 +31722,7 @@ var init_MatrixQuestion = __esm({
|
|
|
31597
31722
|
className
|
|
31598
31723
|
}) => {
|
|
31599
31724
|
const styles = sizeStyles13[size];
|
|
31600
|
-
const safeRows =
|
|
31725
|
+
const safeRows = rows2 ?? [];
|
|
31601
31726
|
const safeValues = values ?? {};
|
|
31602
31727
|
const eventBus = useEventBus();
|
|
31603
31728
|
const handleChange = useCallback(
|
|
@@ -32225,7 +32350,8 @@ var init_PositionedCanvas = __esm({
|
|
|
32225
32350
|
dragRef.current = null;
|
|
32226
32351
|
setDraggingId(null);
|
|
32227
32352
|
if (!wasDrag) {
|
|
32228
|
-
const
|
|
32353
|
+
const itemId = item.id;
|
|
32354
|
+
const next = selectedId === itemId ? null : itemId;
|
|
32229
32355
|
onSelect?.(next);
|
|
32230
32356
|
if (selectEvent) {
|
|
32231
32357
|
eventBus.emit(`UI:${selectEvent}`, { id: next });
|
|
@@ -32260,15 +32386,22 @@ var init_PositionedCanvas = __esm({
|
|
|
32260
32386
|
style: { width, height },
|
|
32261
32387
|
onClick: handleContainerClick,
|
|
32262
32388
|
children: items.map((item) => {
|
|
32389
|
+
const itemId = item.id;
|
|
32390
|
+
const label = item.label;
|
|
32391
|
+
const x = item.x;
|
|
32392
|
+
const y = item.y;
|
|
32393
|
+
const capacity = item.capacity;
|
|
32394
|
+
const partySize = item.partySize;
|
|
32395
|
+
const serverName = item.serverName;
|
|
32263
32396
|
const status = item.status ?? "empty";
|
|
32264
32397
|
const shape = item.shape ?? "round";
|
|
32265
|
-
const isSelected = selectedId ===
|
|
32266
|
-
const isDragging = draggingId ===
|
|
32398
|
+
const isSelected = selectedId === itemId;
|
|
32399
|
+
const isDragging = draggingId === itemId;
|
|
32267
32400
|
const statusBadge = STATUS_BADGE[status];
|
|
32268
32401
|
return /* @__PURE__ */ jsxs(
|
|
32269
32402
|
Box,
|
|
32270
32403
|
{
|
|
32271
|
-
"data-testid": `item-node-${
|
|
32404
|
+
"data-testid": `item-node-${itemId}`,
|
|
32272
32405
|
"data-status": status,
|
|
32273
32406
|
className: cn(
|
|
32274
32407
|
"absolute flex flex-col items-center justify-center gap-1 border-2 select-none",
|
|
@@ -32279,7 +32412,7 @@ var init_PositionedCanvas = __esm({
|
|
|
32279
32412
|
isSelected && "outline outline-2 outline-offset-2 outline-primary shadow-md",
|
|
32280
32413
|
isDragging && "shadow-lg z-10"
|
|
32281
32414
|
),
|
|
32282
|
-
style: { left:
|
|
32415
|
+
style: { left: x, top: y, touchAction: "none" },
|
|
32283
32416
|
onPointerDown: (e) => handlePointerDown(e, item),
|
|
32284
32417
|
onPointerMove: handlePointerMove,
|
|
32285
32418
|
onPointerUp: (e) => handlePointerUp(e, item),
|
|
@@ -32287,10 +32420,10 @@ var init_PositionedCanvas = __esm({
|
|
|
32287
32420
|
children: [
|
|
32288
32421
|
/* @__PURE__ */ jsxs(Box, { className: "flex items-center gap-1", children: [
|
|
32289
32422
|
getStatusIcon(status),
|
|
32290
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body2", weight: "semibold", children:
|
|
32423
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body2", weight: "semibold", children: label })
|
|
32291
32424
|
] }),
|
|
32292
|
-
/* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", children:
|
|
32293
|
-
status === "seated" &&
|
|
32425
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", children: partySize !== void 0 && status === "seated" ? `${partySize}/${capacity}` : `Cap ${capacity}` }),
|
|
32426
|
+
status === "seated" && serverName && /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", className: "truncate max-w-[80%]", children: serverName }),
|
|
32294
32427
|
isSelected && /* @__PURE__ */ jsx(
|
|
32295
32428
|
Badge,
|
|
32296
32429
|
{
|
|
@@ -32302,7 +32435,7 @@ var init_PositionedCanvas = __esm({
|
|
|
32302
32435
|
)
|
|
32303
32436
|
]
|
|
32304
32437
|
},
|
|
32305
|
-
|
|
32438
|
+
itemId
|
|
32306
32439
|
);
|
|
32307
32440
|
})
|
|
32308
32441
|
}
|
|
@@ -33074,9 +33207,10 @@ var init_RichBlockEditor = __esm({
|
|
|
33074
33207
|
});
|
|
33075
33208
|
function collectInitiallyCollapsed(nodes, acc) {
|
|
33076
33209
|
for (const n of nodes) {
|
|
33210
|
+
const replies = n.replies;
|
|
33077
33211
|
if (n.collapsed) acc.add(n.id);
|
|
33078
|
-
if (
|
|
33079
|
-
collectInitiallyCollapsed(
|
|
33212
|
+
if (replies && replies.length > 0) {
|
|
33213
|
+
collectInitiallyCollapsed(replies, acc);
|
|
33080
33214
|
}
|
|
33081
33215
|
}
|
|
33082
33216
|
}
|
|
@@ -33106,44 +33240,52 @@ var init_ReplyTree = __esm({
|
|
|
33106
33240
|
}) => {
|
|
33107
33241
|
const eventBus = useEventBus();
|
|
33108
33242
|
const { t } = useTranslate();
|
|
33109
|
-
const
|
|
33110
|
-
const
|
|
33243
|
+
const nodeId = node.id;
|
|
33244
|
+
const authorName = node.authorName;
|
|
33245
|
+
const authorAvatarUrl = node.authorAvatarUrl;
|
|
33246
|
+
const content = node.content;
|
|
33247
|
+
const postedAt = node.postedAt;
|
|
33248
|
+
const voteCount = node.voteCount;
|
|
33249
|
+
const userVote = node.userVote;
|
|
33250
|
+
const replies = node.replies;
|
|
33251
|
+
const hasReplies = !!replies && replies.length > 0;
|
|
33252
|
+
const isCollapsed = collapsedSet.has(nodeId);
|
|
33111
33253
|
const atMaxDepth = depth >= maxDepth;
|
|
33112
33254
|
const [replyOpen, setReplyOpen] = useState(false);
|
|
33113
33255
|
const [draft, setDraft] = useState("");
|
|
33114
33256
|
const handleVote = useCallback(
|
|
33115
33257
|
(next) => {
|
|
33116
|
-
onVote?.(
|
|
33117
|
-
if (voteEvent) eventBus.emit(`UI:${voteEvent}`, { nodeId
|
|
33258
|
+
onVote?.(nodeId, next);
|
|
33259
|
+
if (voteEvent) eventBus.emit(`UI:${voteEvent}`, { nodeId, vote: next });
|
|
33118
33260
|
},
|
|
33119
|
-
[
|
|
33261
|
+
[nodeId, onVote, voteEvent, eventBus]
|
|
33120
33262
|
);
|
|
33121
33263
|
const handleReply = useCallback(() => {
|
|
33122
|
-
onReply?.(
|
|
33264
|
+
onReply?.(nodeId);
|
|
33123
33265
|
setReplyOpen((open) => !open);
|
|
33124
|
-
}, [
|
|
33266
|
+
}, [nodeId, onReply]);
|
|
33125
33267
|
const handleSubmitReply = useCallback(() => {
|
|
33126
|
-
const
|
|
33127
|
-
if (!
|
|
33128
|
-
if (replyEvent) eventBus.emit(`UI:${replyEvent}`, { parentNodeId:
|
|
33268
|
+
const text = draft.trim();
|
|
33269
|
+
if (!text) return;
|
|
33270
|
+
if (replyEvent) eventBus.emit(`UI:${replyEvent}`, { parentNodeId: nodeId, content: text });
|
|
33129
33271
|
setDraft("");
|
|
33130
33272
|
setReplyOpen(false);
|
|
33131
|
-
}, [
|
|
33273
|
+
}, [nodeId, draft, replyEvent, eventBus]);
|
|
33132
33274
|
const handleCancelReply = useCallback(() => {
|
|
33133
33275
|
setDraft("");
|
|
33134
33276
|
setReplyOpen(false);
|
|
33135
33277
|
}, []);
|
|
33136
33278
|
const handleFlag = useCallback(() => {
|
|
33137
|
-
onFlag?.(
|
|
33138
|
-
if (flagEvent) eventBus.emit(`UI:${flagEvent}`, { nodeId
|
|
33139
|
-
}, [
|
|
33279
|
+
onFlag?.(nodeId);
|
|
33280
|
+
if (flagEvent) eventBus.emit(`UI:${flagEvent}`, { nodeId });
|
|
33281
|
+
}, [nodeId, onFlag, flagEvent, eventBus]);
|
|
33140
33282
|
const handleContinue = useCallback(() => {
|
|
33141
|
-
onContinueThread?.(
|
|
33142
|
-
if (continueThreadEvent) eventBus.emit(`UI:${continueThreadEvent}`, { nodeId
|
|
33143
|
-
}, [
|
|
33283
|
+
onContinueThread?.(nodeId);
|
|
33284
|
+
if (continueThreadEvent) eventBus.emit(`UI:${continueThreadEvent}`, { nodeId });
|
|
33285
|
+
}, [nodeId, onContinueThread, continueThreadEvent, eventBus]);
|
|
33144
33286
|
const handleToggle = useCallback(() => {
|
|
33145
|
-
toggleCollapse(
|
|
33146
|
-
}, [
|
|
33287
|
+
toggleCollapse(nodeId);
|
|
33288
|
+
}, [nodeId, toggleCollapse]);
|
|
33147
33289
|
return /* @__PURE__ */ jsxs(Box, { className: "flex flex-row gap-2 items-stretch min-w-0", children: [
|
|
33148
33290
|
/* @__PURE__ */ jsxs(Box, { className: "flex flex-col items-center flex-shrink-0 w-6", children: [
|
|
33149
33291
|
hasReplies ? /* @__PURE__ */ jsx(
|
|
@@ -33175,25 +33317,25 @@ var init_ReplyTree = __esm({
|
|
|
33175
33317
|
/* @__PURE__ */ jsx(
|
|
33176
33318
|
Avatar,
|
|
33177
33319
|
{
|
|
33178
|
-
src:
|
|
33179
|
-
name:
|
|
33320
|
+
src: authorAvatarUrl,
|
|
33321
|
+
name: authorName,
|
|
33180
33322
|
size: "sm"
|
|
33181
33323
|
}
|
|
33182
33324
|
),
|
|
33183
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body", weight: "semibold", children:
|
|
33184
|
-
/* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", children:
|
|
33325
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body", weight: "semibold", children: authorName }),
|
|
33326
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", children: postedAt })
|
|
33185
33327
|
] }),
|
|
33186
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body", className: "whitespace-pre-wrap break-words", children:
|
|
33328
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body", className: "whitespace-pre-wrap break-words", children: content }),
|
|
33187
33329
|
showActions && /* @__PURE__ */ jsxs(Box, { className: "flex flex-row gap-2 items-center", children: [
|
|
33188
33330
|
/* @__PURE__ */ jsx(
|
|
33189
33331
|
VoteStack,
|
|
33190
33332
|
{
|
|
33191
|
-
count:
|
|
33192
|
-
userVote:
|
|
33333
|
+
count: voteCount ?? 0,
|
|
33334
|
+
userVote: userVote ?? null,
|
|
33193
33335
|
onVote: handleVote,
|
|
33194
33336
|
size: "sm",
|
|
33195
33337
|
variant: "horizontal",
|
|
33196
|
-
label: t("replyTree.voteOnReplyBy", { author:
|
|
33338
|
+
label: t("replyTree.voteOnReplyBy", { author: authorName })
|
|
33197
33339
|
}
|
|
33198
33340
|
),
|
|
33199
33341
|
/* @__PURE__ */ jsx(
|
|
@@ -33203,7 +33345,7 @@ var init_ReplyTree = __esm({
|
|
|
33203
33345
|
size: "sm",
|
|
33204
33346
|
leftIcon: "message-square",
|
|
33205
33347
|
onClick: handleReply,
|
|
33206
|
-
"aria-label": t("replyTree.replyTo", { author:
|
|
33348
|
+
"aria-label": t("replyTree.replyTo", { author: authorName }),
|
|
33207
33349
|
children: t("replyTree.reply")
|
|
33208
33350
|
}
|
|
33209
33351
|
),
|
|
@@ -33214,7 +33356,7 @@ var init_ReplyTree = __esm({
|
|
|
33214
33356
|
size: "sm",
|
|
33215
33357
|
leftIcon: "flag",
|
|
33216
33358
|
onClick: handleFlag,
|
|
33217
|
-
"aria-label": t("replyTree.flagReplyBy", { author:
|
|
33359
|
+
"aria-label": t("replyTree.flagReplyBy", { author: authorName }),
|
|
33218
33360
|
children: t("replyTree.flag")
|
|
33219
33361
|
}
|
|
33220
33362
|
)
|
|
@@ -33226,9 +33368,9 @@ var init_ReplyTree = __esm({
|
|
|
33226
33368
|
inputType: "textarea",
|
|
33227
33369
|
rows: 2,
|
|
33228
33370
|
value: draft,
|
|
33229
|
-
placeholder: t("replyTree.replyToPlaceholder", { author:
|
|
33371
|
+
placeholder: t("replyTree.replyToPlaceholder", { author: authorName }),
|
|
33230
33372
|
onChange: (e) => setDraft(e.target.value),
|
|
33231
|
-
"aria-label": t("replyTree.replyTo", { author:
|
|
33373
|
+
"aria-label": t("replyTree.replyTo", { author: authorName })
|
|
33232
33374
|
}
|
|
33233
33375
|
),
|
|
33234
33376
|
/* @__PURE__ */ jsxs(Box, { className: "flex flex-row gap-2 items-center", children: [
|
|
@@ -33259,7 +33401,7 @@ var init_ReplyTree = __esm({
|
|
|
33259
33401
|
),
|
|
33260
33402
|
children: t("replyTree.continueThread")
|
|
33261
33403
|
}
|
|
33262
|
-
) : /* @__PURE__ */ jsx(Box, { className: "flex flex-col gap-2 mt-1", children:
|
|
33404
|
+
) : /* @__PURE__ */ jsx(Box, { className: "flex flex-col gap-2 mt-1", children: replies.map((child) => /* @__PURE__ */ jsx(
|
|
33263
33405
|
ReplyTreeNode,
|
|
33264
33406
|
{
|
|
33265
33407
|
node: child,
|
|
@@ -35579,8 +35721,8 @@ var init_WizardContainer = __esm({
|
|
|
35579
35721
|
return void 0;
|
|
35580
35722
|
if (typeof controlledStep === "number") return controlledStep;
|
|
35581
35723
|
if (typeof controlledStep === "string") return parseInt(controlledStep, 10);
|
|
35582
|
-
const
|
|
35583
|
-
return isNaN(
|
|
35724
|
+
const num2 = Number(controlledStep);
|
|
35725
|
+
return isNaN(num2) ? void 0 : num2;
|
|
35584
35726
|
})();
|
|
35585
35727
|
const currentStep = normalizedControlledStep !== void 0 ? normalizedControlledStep : internalStep;
|
|
35586
35728
|
const totalSteps = steps.length;
|
|
@@ -37285,7 +37427,7 @@ function DebuggerBoard({
|
|
|
37285
37427
|
}) {
|
|
37286
37428
|
const { emit } = useEventBus();
|
|
37287
37429
|
const { t } = useTranslate();
|
|
37288
|
-
const resolved =
|
|
37430
|
+
const resolved = boardEntity(entity);
|
|
37289
37431
|
const [flaggedLines, setFlaggedLines] = useState(/* @__PURE__ */ new Set());
|
|
37290
37432
|
const [headerError, setHeaderError] = useState(false);
|
|
37291
37433
|
const [submitted, setSubmitted] = useState(false);
|
|
@@ -37303,7 +37445,7 @@ function DebuggerBoard({
|
|
|
37303
37445
|
return next;
|
|
37304
37446
|
});
|
|
37305
37447
|
};
|
|
37306
|
-
const lines = resolved?.lines
|
|
37448
|
+
const lines = Array.isArray(resolved?.lines) ? resolved.lines : [];
|
|
37307
37449
|
const bugLines = lines.filter((l) => l.isBug);
|
|
37308
37450
|
const correctFlags = lines.filter((l) => l.isBug && flaggedLines.has(l.id));
|
|
37309
37451
|
const falseFlags = lines.filter((l) => !l.isBug && flaggedLines.has(l.id));
|
|
@@ -37318,7 +37460,7 @@ function DebuggerBoard({
|
|
|
37318
37460
|
}, [correctFlags.length, bugLines.length, falseFlags.length, attempts, completeEvent, emit]);
|
|
37319
37461
|
const handleReset = () => {
|
|
37320
37462
|
setSubmitted(false);
|
|
37321
|
-
if (attempts >= 2 && resolved?.hint) {
|
|
37463
|
+
if (attempts >= 2 && str(resolved?.hint)) {
|
|
37322
37464
|
setShowHint(true);
|
|
37323
37465
|
}
|
|
37324
37466
|
};
|
|
@@ -37329,24 +37471,28 @@ function DebuggerBoard({
|
|
|
37329
37471
|
setShowHint(false);
|
|
37330
37472
|
};
|
|
37331
37473
|
if (!resolved) return null;
|
|
37474
|
+
const theme = resolved.theme ?? void 0;
|
|
37475
|
+
const themeBackground = theme?.background;
|
|
37476
|
+
const headerImage = str(resolved.headerImage);
|
|
37477
|
+
const hint = str(resolved.hint);
|
|
37332
37478
|
return /* @__PURE__ */ jsx(
|
|
37333
37479
|
Box,
|
|
37334
37480
|
{
|
|
37335
37481
|
className,
|
|
37336
37482
|
style: {
|
|
37337
|
-
backgroundImage:
|
|
37483
|
+
backgroundImage: themeBackground ? `url(${themeBackground})` : void 0,
|
|
37338
37484
|
backgroundSize: "cover",
|
|
37339
37485
|
backgroundPosition: "center"
|
|
37340
37486
|
},
|
|
37341
37487
|
children: /* @__PURE__ */ jsxs(VStack, { gap: "lg", className: "p-4", children: [
|
|
37342
|
-
|
|
37488
|
+
headerImage && !headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 overflow-hidden rounded-container", children: /* @__PURE__ */ jsx("img", { src: headerImage, alt: "", onError: () => setHeaderError(true), className: "w-full h-full object-cover" }) }) : headerImage && headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 rounded-container bg-gradient-to-br from-muted to-accent opacity-60" }) : null,
|
|
37343
37489
|
/* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
|
|
37344
37490
|
/* @__PURE__ */ jsxs(HStack, { gap: "xs", align: "center", children: [
|
|
37345
37491
|
/* @__PURE__ */ jsx(Icon, { icon: Bug, size: "sm" }),
|
|
37346
|
-
/* @__PURE__ */ jsx(Typography, { variant: "h4", weight: "bold", children: resolved.title })
|
|
37492
|
+
/* @__PURE__ */ jsx(Typography, { variant: "h4", weight: "bold", children: str(resolved.title) })
|
|
37347
37493
|
] }),
|
|
37348
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body", children: resolved.description }),
|
|
37349
|
-
/* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-muted-foreground", children: t("debugger.findBugs", { count: String(resolved.bugCount) }) })
|
|
37494
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body", children: str(resolved.description) }),
|
|
37495
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-muted-foreground", children: t("debugger.findBugs", { count: String(num(resolved.bugCount)) }) })
|
|
37350
37496
|
] }) }),
|
|
37351
37497
|
/* @__PURE__ */ jsx(Card, { className: "p-0 overflow-hidden", children: /* @__PURE__ */ jsx(VStack, { gap: "none", children: lines.map((line, i) => {
|
|
37352
37498
|
const isFlagged = flaggedLines.has(line.id);
|
|
@@ -37378,7 +37524,7 @@ function DebuggerBoard({
|
|
|
37378
37524
|
);
|
|
37379
37525
|
}) }) }),
|
|
37380
37526
|
submitted && /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
|
|
37381
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body", weight: "bold", children: allCorrect ? resolved.successMessage
|
|
37527
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body", weight: "bold", children: allCorrect ? str(resolved.successMessage) || t("debugger.allFound") : `${correctFlags.length}/${bugLines.length} ${t("debugger.bugsFound")}` }),
|
|
37382
37528
|
bugLines.map((line) => /* @__PURE__ */ jsxs(HStack, { gap: "xs", align: "start", children: [
|
|
37383
37529
|
/* @__PURE__ */ jsx(
|
|
37384
37530
|
Icon,
|
|
@@ -37394,7 +37540,7 @@ function DebuggerBoard({
|
|
|
37394
37540
|
] })
|
|
37395
37541
|
] }, line.id))
|
|
37396
37542
|
] }) }),
|
|
37397
|
-
showHint &&
|
|
37543
|
+
showHint && hint && /* @__PURE__ */ jsx(Card, { className: "p-4 border-l-4 border-l-warning", children: /* @__PURE__ */ jsx(Typography, { variant: "body", children: hint }) }),
|
|
37398
37544
|
/* @__PURE__ */ jsxs(HStack, { gap: "sm", justify: "center", children: [
|
|
37399
37545
|
!submitted ? /* @__PURE__ */ jsxs(Button, { variant: "primary", onClick: handleSubmit, disabled: flaggedLines.size === 0, children: [
|
|
37400
37546
|
/* @__PURE__ */ jsx(Icon, { icon: Send, size: "sm" }),
|
|
@@ -37413,6 +37559,7 @@ var init_DebuggerBoard = __esm({
|
|
|
37413
37559
|
"components/game/organisms/puzzles/debugger/DebuggerBoard.tsx"() {
|
|
37414
37560
|
init_atoms2();
|
|
37415
37561
|
init_useEventBus();
|
|
37562
|
+
init_boardEntity();
|
|
37416
37563
|
DebuggerBoard.displayName = "DebuggerBoard";
|
|
37417
37564
|
}
|
|
37418
37565
|
});
|
|
@@ -37450,7 +37597,7 @@ function getBadgeVariant(fieldName, value) {
|
|
|
37450
37597
|
return "default";
|
|
37451
37598
|
}
|
|
37452
37599
|
function formatFieldLabel(fieldName) {
|
|
37453
|
-
return fieldName.replace(/([A-Z])/g, " $1").replace(/^./, (
|
|
37600
|
+
return fieldName.replace(/([A-Z])/g, " $1").replace(/^./, (str2) => str2.toUpperCase());
|
|
37454
37601
|
}
|
|
37455
37602
|
function formatFieldValue(value, fieldName) {
|
|
37456
37603
|
if (typeof value === "number") {
|
|
@@ -37469,26 +37616,26 @@ function formatFieldValue(value, fieldName) {
|
|
|
37469
37616
|
}
|
|
37470
37617
|
function renderRichFieldValue(value, fieldName, fieldType) {
|
|
37471
37618
|
if (value === void 0 || value === null) return "\u2014";
|
|
37472
|
-
const
|
|
37619
|
+
const str2 = String(value);
|
|
37473
37620
|
switch (fieldType) {
|
|
37474
37621
|
case "image":
|
|
37475
37622
|
case "url": {
|
|
37476
|
-
if (
|
|
37623
|
+
if (str2.match(/\.(png|jpe?g|gif|svg|webp|avif)(\?|$)/i) || str2.startsWith("data:image/")) {
|
|
37477
37624
|
return /* @__PURE__ */ jsx(Box, { className: "mt-1 max-w-full", children: /* @__PURE__ */ jsx(
|
|
37478
37625
|
"img",
|
|
37479
37626
|
{
|
|
37480
|
-
src:
|
|
37627
|
+
src: str2,
|
|
37481
37628
|
alt: formatFieldLabel(fieldName),
|
|
37482
37629
|
className: "max-w-full max-h-64 rounded-md object-contain",
|
|
37483
37630
|
loading: "lazy"
|
|
37484
37631
|
}
|
|
37485
37632
|
) });
|
|
37486
37633
|
}
|
|
37487
|
-
return
|
|
37634
|
+
return str2;
|
|
37488
37635
|
}
|
|
37489
37636
|
case "markdown":
|
|
37490
37637
|
case "richtext":
|
|
37491
|
-
return /* @__PURE__ */ jsx(Suspense, { fallback: /* @__PURE__ */ jsx(Typography, { variant: "body", className: "break-words", children:
|
|
37638
|
+
return /* @__PURE__ */ jsx(Suspense, { fallback: /* @__PURE__ */ jsx(Typography, { variant: "body", className: "break-words", children: str2 }), children: /* @__PURE__ */ jsx(
|
|
37492
37639
|
Box,
|
|
37493
37640
|
{
|
|
37494
37641
|
className: "prose prose-sm max-w-none",
|
|
@@ -37506,11 +37653,11 @@ function renderRichFieldValue(value, fieldName, fieldType) {
|
|
|
37506
37653
|
"--tw-prose-th-borders": "var(--color-border)",
|
|
37507
37654
|
"--tw-prose-td-borders": "var(--color-border)"
|
|
37508
37655
|
},
|
|
37509
|
-
children: /* @__PURE__ */ jsx(ReactMarkdown2, { children:
|
|
37656
|
+
children: /* @__PURE__ */ jsx(ReactMarkdown2, { children: str2 })
|
|
37510
37657
|
}
|
|
37511
37658
|
) });
|
|
37512
37659
|
case "code":
|
|
37513
|
-
return /* @__PURE__ */ jsx(Box, { className: "mt-1 rounded-md bg-muted p-3 overflow-x-auto", children: /* @__PURE__ */ jsx("pre", { className: "text-sm font-mono whitespace-pre-wrap break-words m-0", children: /* @__PURE__ */ jsx("code", { children:
|
|
37660
|
+
return /* @__PURE__ */ jsx(Box, { className: "mt-1 rounded-md bg-muted p-3 overflow-x-auto", children: /* @__PURE__ */ jsx("pre", { className: "text-sm font-mono whitespace-pre-wrap break-words m-0", children: /* @__PURE__ */ jsx("code", { children: str2 }) }) });
|
|
37514
37661
|
case "html":
|
|
37515
37662
|
return /* @__PURE__ */ jsx(
|
|
37516
37663
|
Box,
|
|
@@ -37530,12 +37677,12 @@ function renderRichFieldValue(value, fieldName, fieldType) {
|
|
|
37530
37677
|
"--tw-prose-th-borders": "var(--color-border)",
|
|
37531
37678
|
"--tw-prose-td-borders": "var(--color-border)"
|
|
37532
37679
|
},
|
|
37533
|
-
children: /* @__PURE__ */ jsx(Typography, { variant: "body", children:
|
|
37680
|
+
children: /* @__PURE__ */ jsx(Typography, { variant: "body", children: str2 })
|
|
37534
37681
|
}
|
|
37535
37682
|
);
|
|
37536
37683
|
case "date":
|
|
37537
37684
|
case "datetime": {
|
|
37538
|
-
const d = new Date(
|
|
37685
|
+
const d = new Date(str2);
|
|
37539
37686
|
if (!isNaN(d.getTime())) {
|
|
37540
37687
|
return d.toLocaleDateString(void 0, {
|
|
37541
37688
|
year: "numeric",
|
|
@@ -37544,7 +37691,7 @@ function renderRichFieldValue(value, fieldName, fieldType) {
|
|
|
37544
37691
|
...fieldType === "datetime" ? { hour: "2-digit", minute: "2-digit" } : {}
|
|
37545
37692
|
});
|
|
37546
37693
|
}
|
|
37547
|
-
return
|
|
37694
|
+
return str2;
|
|
37548
37695
|
}
|
|
37549
37696
|
default:
|
|
37550
37697
|
return formatFieldValue(value, fieldName);
|
|
@@ -38222,6 +38369,40 @@ var init_RuleEditor = __esm({
|
|
|
38222
38369
|
RuleEditor.displayName = "RuleEditor";
|
|
38223
38370
|
}
|
|
38224
38371
|
});
|
|
38372
|
+
|
|
38373
|
+
// components/game/organisms/puzzles/event-handler/puzzleObject.ts
|
|
38374
|
+
function objId(o) {
|
|
38375
|
+
return o.id == null ? "" : String(o.id);
|
|
38376
|
+
}
|
|
38377
|
+
function objName(o) {
|
|
38378
|
+
return o.name == null ? "" : String(o.name);
|
|
38379
|
+
}
|
|
38380
|
+
function objIcon(o) {
|
|
38381
|
+
return o.icon == null ? "" : String(o.icon);
|
|
38382
|
+
}
|
|
38383
|
+
function objStates(o) {
|
|
38384
|
+
return Array.isArray(o.states) ? o.states : [];
|
|
38385
|
+
}
|
|
38386
|
+
function objCurrentState(o) {
|
|
38387
|
+
return o.currentState == null ? "" : String(o.currentState);
|
|
38388
|
+
}
|
|
38389
|
+
function objAvailableEvents(o) {
|
|
38390
|
+
return Array.isArray(o.availableEvents) ? o.availableEvents : [];
|
|
38391
|
+
}
|
|
38392
|
+
function objAvailableActions(o) {
|
|
38393
|
+
return Array.isArray(o.availableActions) ? o.availableActions : [];
|
|
38394
|
+
}
|
|
38395
|
+
function objRules(o) {
|
|
38396
|
+
return Array.isArray(o.rules) ? o.rules : [];
|
|
38397
|
+
}
|
|
38398
|
+
function objMaxRules(o) {
|
|
38399
|
+
const n = Number(o.maxRules);
|
|
38400
|
+
return Number.isFinite(n) && n > 0 ? n : 3;
|
|
38401
|
+
}
|
|
38402
|
+
var init_puzzleObject = __esm({
|
|
38403
|
+
"components/game/organisms/puzzles/event-handler/puzzleObject.ts"() {
|
|
38404
|
+
}
|
|
38405
|
+
});
|
|
38225
38406
|
function ObjectRulePanel({
|
|
38226
38407
|
object,
|
|
38227
38408
|
onRulesChange,
|
|
@@ -38229,55 +38410,63 @@ function ObjectRulePanel({
|
|
|
38229
38410
|
className
|
|
38230
38411
|
}) {
|
|
38231
38412
|
const { t } = useTranslate();
|
|
38232
|
-
const
|
|
38233
|
-
const
|
|
38413
|
+
const id = objId(object);
|
|
38414
|
+
const name = objName(object);
|
|
38415
|
+
const icon = objIcon(object);
|
|
38416
|
+
const states = objStates(object);
|
|
38417
|
+
const currentState = objCurrentState(object);
|
|
38418
|
+
const availableEvents = objAvailableEvents(object);
|
|
38419
|
+
const availableActions = objAvailableActions(object);
|
|
38420
|
+
const rules = objRules(object);
|
|
38421
|
+
const maxRules = objMaxRules(object);
|
|
38422
|
+
const canAdd = rules.length < maxRules;
|
|
38234
38423
|
const handleRuleChange = useCallback((index, updatedRule) => {
|
|
38235
|
-
const newRules = [...
|
|
38424
|
+
const newRules = [...rules];
|
|
38236
38425
|
newRules[index] = updatedRule;
|
|
38237
|
-
onRulesChange(
|
|
38238
|
-
}, [
|
|
38426
|
+
onRulesChange(id, newRules);
|
|
38427
|
+
}, [id, rules, onRulesChange]);
|
|
38239
38428
|
const handleRuleRemove = useCallback((index) => {
|
|
38240
|
-
const newRules =
|
|
38241
|
-
onRulesChange(
|
|
38242
|
-
}, [
|
|
38429
|
+
const newRules = rules.filter((_, i) => i !== index);
|
|
38430
|
+
onRulesChange(id, newRules);
|
|
38431
|
+
}, [id, rules, onRulesChange]);
|
|
38243
38432
|
const handleAddRule = useCallback(() => {
|
|
38244
38433
|
if (!canAdd || disabled) return;
|
|
38245
|
-
const firstEvent =
|
|
38246
|
-
const firstAction =
|
|
38434
|
+
const firstEvent = availableEvents[0]?.value || "";
|
|
38435
|
+
const firstAction = availableActions[0]?.value || "";
|
|
38247
38436
|
const newRule = {
|
|
38248
38437
|
id: `rule-${nextRuleId++}`,
|
|
38249
38438
|
whenEvent: firstEvent,
|
|
38250
38439
|
thenAction: firstAction
|
|
38251
38440
|
};
|
|
38252
|
-
onRulesChange(
|
|
38253
|
-
}, [canAdd, disabled,
|
|
38441
|
+
onRulesChange(id, [...rules, newRule]);
|
|
38442
|
+
}, [canAdd, disabled, id, rules, availableEvents, availableActions, onRulesChange]);
|
|
38254
38443
|
const machine = {
|
|
38255
|
-
name
|
|
38256
|
-
states
|
|
38257
|
-
currentState
|
|
38258
|
-
transitions:
|
|
38259
|
-
from:
|
|
38260
|
-
to:
|
|
38444
|
+
name,
|
|
38445
|
+
states,
|
|
38446
|
+
currentState,
|
|
38447
|
+
transitions: rules.map((r) => ({
|
|
38448
|
+
from: currentState,
|
|
38449
|
+
to: states.find((s) => s !== currentState) || currentState,
|
|
38261
38450
|
event: r.whenEvent
|
|
38262
38451
|
}))
|
|
38263
38452
|
};
|
|
38264
38453
|
return /* @__PURE__ */ jsxs(VStack, { className: cn("p-4 rounded-lg bg-card border border-border", className), gap: "sm", children: [
|
|
38265
38454
|
/* @__PURE__ */ jsxs(HStack, { className: "items-center", gap: "sm", children: [
|
|
38266
|
-
/* @__PURE__ */ jsx(Typography, { variant: "h5", children:
|
|
38455
|
+
/* @__PURE__ */ jsx(Typography, { variant: "h5", children: icon }),
|
|
38267
38456
|
/* @__PURE__ */ jsxs(VStack, { gap: "none", children: [
|
|
38268
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body1", className: "text-foreground font-bold", children:
|
|
38269
|
-
/* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-muted-foreground", children: t("eventHandler.state") + ": " +
|
|
38457
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body1", className: "text-foreground font-bold", children: name }),
|
|
38458
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-muted-foreground", children: t("eventHandler.state") + ": " + currentState })
|
|
38270
38459
|
] })
|
|
38271
38460
|
] }),
|
|
38272
38461
|
/* @__PURE__ */ jsx(TraitStateViewer, { trait: machine, variant: "compact", size: "sm" }),
|
|
38273
38462
|
/* @__PURE__ */ jsxs(VStack, { gap: "xs", children: [
|
|
38274
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground font-medium", children: t("eventHandler.rules", { count:
|
|
38275
|
-
|
|
38463
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground font-medium", children: t("eventHandler.rules", { count: rules.length, max: maxRules }) + ":" }),
|
|
38464
|
+
rules.map((rule, i) => /* @__PURE__ */ jsx(
|
|
38276
38465
|
RuleEditor,
|
|
38277
38466
|
{
|
|
38278
38467
|
rule,
|
|
38279
|
-
availableEvents
|
|
38280
|
-
availableActions
|
|
38468
|
+
availableEvents,
|
|
38469
|
+
availableActions,
|
|
38281
38470
|
onChange: (r) => handleRuleChange(i, r),
|
|
38282
38471
|
onRemove: () => handleRuleRemove(i),
|
|
38283
38472
|
disabled
|
|
@@ -38295,6 +38484,7 @@ var init_ObjectRulePanel = __esm({
|
|
|
38295
38484
|
init_cn();
|
|
38296
38485
|
init_TraitStateViewer();
|
|
38297
38486
|
init_RuleEditor();
|
|
38487
|
+
init_puzzleObject();
|
|
38298
38488
|
nextRuleId = 1;
|
|
38299
38489
|
ObjectRulePanel.displayName = "ObjectRulePanel";
|
|
38300
38490
|
}
|
|
@@ -38361,11 +38551,11 @@ function EventHandlerBoard({
|
|
|
38361
38551
|
}) {
|
|
38362
38552
|
const { emit } = useEventBus();
|
|
38363
38553
|
const { t } = useTranslate();
|
|
38364
|
-
const resolved =
|
|
38365
|
-
const entityObjects = resolved?.objects
|
|
38366
|
-
const [objects, setObjects] = useState(entityObjects);
|
|
38554
|
+
const resolved = boardEntity(entity);
|
|
38555
|
+
const entityObjects = rows(resolved?.objects);
|
|
38556
|
+
const [objects, setObjects] = useState(() => [...entityObjects]);
|
|
38367
38557
|
const [selectedObjectId, setSelectedObjectId] = useState(
|
|
38368
|
-
entityObjects[0]
|
|
38558
|
+
entityObjects[0] ? objId(entityObjects[0]) : null
|
|
38369
38559
|
);
|
|
38370
38560
|
const [headerError, setHeaderError] = useState(false);
|
|
38371
38561
|
const [playState, setPlayState] = useState("editing");
|
|
@@ -38376,10 +38566,10 @@ function EventHandlerBoard({
|
|
|
38376
38566
|
useEffect(() => () => {
|
|
38377
38567
|
if (timerRef.current) clearTimeout(timerRef.current);
|
|
38378
38568
|
}, []);
|
|
38379
|
-
const selectedObject = objects.find((o) => o
|
|
38569
|
+
const selectedObject = objects.find((o) => objId(o) === selectedObjectId) || null;
|
|
38380
38570
|
const handleRulesChange = useCallback((objectId, rules) => {
|
|
38381
38571
|
setObjects((prev) => prev.map(
|
|
38382
|
-
(o) => o
|
|
38572
|
+
(o) => objId(o) === objectId ? { ...o, rules } : o
|
|
38383
38573
|
));
|
|
38384
38574
|
}, []);
|
|
38385
38575
|
const addLogEntry = useCallback((icon, message, status = "done") => {
|
|
@@ -38393,11 +38583,12 @@ function EventHandlerBoard({
|
|
|
38393
38583
|
setEventLog([]);
|
|
38394
38584
|
const allRules = [];
|
|
38395
38585
|
objects.forEach((obj) => {
|
|
38396
|
-
obj.
|
|
38586
|
+
objRules(obj).forEach((rule) => {
|
|
38397
38587
|
allRules.push({ object: obj, rule });
|
|
38398
38588
|
});
|
|
38399
38589
|
});
|
|
38400
|
-
const triggers = resolved?.triggerEvents
|
|
38590
|
+
const triggers = Array.isArray(resolved?.triggerEvents) ? resolved.triggerEvents : [];
|
|
38591
|
+
const goalEvent = str(resolved?.goalEvent);
|
|
38401
38592
|
const eventQueue = [...triggers];
|
|
38402
38593
|
const firedEvents = /* @__PURE__ */ new Set();
|
|
38403
38594
|
let stepIdx = 0;
|
|
@@ -38426,14 +38617,14 @@ function EventHandlerBoard({
|
|
|
38426
38617
|
addLogEntry("\u26A1", t("eventHandler.noListeners", { event: currentEvent }), "done");
|
|
38427
38618
|
} else {
|
|
38428
38619
|
matching.forEach(({ object, rule }) => {
|
|
38429
|
-
addLogEntry(object
|
|
38620
|
+
addLogEntry(objIcon(object), t("eventHandler.heardEvent", { object: objName(object), event: currentEvent, action: rule.thenAction }), "done");
|
|
38430
38621
|
eventQueue.push(rule.thenAction);
|
|
38431
|
-
if (rule.thenAction ===
|
|
38622
|
+
if (rule.thenAction === goalEvent) {
|
|
38432
38623
|
goalReached = true;
|
|
38433
38624
|
}
|
|
38434
38625
|
});
|
|
38435
38626
|
}
|
|
38436
|
-
if (currentEvent ===
|
|
38627
|
+
if (currentEvent === goalEvent) {
|
|
38437
38628
|
goalReached = true;
|
|
38438
38629
|
}
|
|
38439
38630
|
stepIdx++;
|
|
@@ -38451,65 +38642,75 @@ function EventHandlerBoard({
|
|
|
38451
38642
|
}, []);
|
|
38452
38643
|
const handleReset = useCallback(() => {
|
|
38453
38644
|
if (timerRef.current) clearTimeout(timerRef.current);
|
|
38454
|
-
|
|
38645
|
+
const resetObjects = rows(resolved?.objects);
|
|
38646
|
+
setObjects([...resetObjects]);
|
|
38455
38647
|
setPlayState("editing");
|
|
38456
38648
|
setEventLog([]);
|
|
38457
|
-
setSelectedObjectId(
|
|
38649
|
+
setSelectedObjectId(resetObjects[0] ? objId(resetObjects[0]) : null);
|
|
38458
38650
|
setAttempts(0);
|
|
38459
38651
|
}, [resolved?.objects]);
|
|
38460
38652
|
if (!resolved) return null;
|
|
38461
38653
|
const objectViewers = objects.map((obj) => {
|
|
38654
|
+
const states = objStates(obj);
|
|
38655
|
+
const currentState = objCurrentState(obj);
|
|
38462
38656
|
const machine = {
|
|
38463
|
-
name: obj
|
|
38464
|
-
states
|
|
38465
|
-
currentState
|
|
38466
|
-
transitions: obj.
|
|
38467
|
-
from:
|
|
38468
|
-
to:
|
|
38657
|
+
name: objName(obj),
|
|
38658
|
+
states,
|
|
38659
|
+
currentState,
|
|
38660
|
+
transitions: objRules(obj).map((r) => ({
|
|
38661
|
+
from: currentState,
|
|
38662
|
+
to: states.find((s) => s !== currentState) || currentState,
|
|
38469
38663
|
event: r.whenEvent
|
|
38470
38664
|
}))
|
|
38471
38665
|
};
|
|
38472
38666
|
return { obj, machine };
|
|
38473
38667
|
});
|
|
38474
|
-
const
|
|
38668
|
+
const hint = str(resolved.hint);
|
|
38669
|
+
const showHint = attempts >= 3 && hint;
|
|
38670
|
+
const theme = resolved.theme ?? void 0;
|
|
38671
|
+
const themeBackground = theme?.background;
|
|
38672
|
+
const headerImage = str(resolved.headerImage);
|
|
38475
38673
|
const encourageKey = ENCOURAGEMENT_KEYS[Math.min(attempts - 1, ENCOURAGEMENT_KEYS.length - 1)] ?? ENCOURAGEMENT_KEYS[0];
|
|
38476
38674
|
return /* @__PURE__ */ jsxs(
|
|
38477
38675
|
VStack,
|
|
38478
38676
|
{
|
|
38479
38677
|
className: cn("p-4 gap-6", className),
|
|
38480
38678
|
style: {
|
|
38481
|
-
backgroundImage:
|
|
38679
|
+
backgroundImage: themeBackground ? `url(${themeBackground})` : void 0,
|
|
38482
38680
|
backgroundSize: "cover",
|
|
38483
38681
|
backgroundPosition: "center"
|
|
38484
38682
|
},
|
|
38485
38683
|
children: [
|
|
38486
|
-
|
|
38684
|
+
headerImage && !headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 overflow-hidden rounded-container", children: /* @__PURE__ */ jsx("img", { src: headerImage, alt: "", onError: () => setHeaderError(true), className: "w-full h-full object-cover" }) }) : headerImage && headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 rounded-container bg-gradient-to-br from-muted to-accent opacity-60" }) : null,
|
|
38487
38685
|
/* @__PURE__ */ jsxs(VStack, { gap: "xs", children: [
|
|
38488
|
-
/* @__PURE__ */ jsx(Typography, { variant: "h4", className: "text-foreground", children: resolved.title }),
|
|
38489
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground", children: resolved.description }),
|
|
38686
|
+
/* @__PURE__ */ jsx(Typography, { variant: "h4", className: "text-foreground", children: str(resolved.title) }),
|
|
38687
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground", children: str(resolved.description) }),
|
|
38490
38688
|
/* @__PURE__ */ jsxs(HStack, { className: "items-center p-2 rounded bg-primary/10 border border-primary/30", gap: "xs", children: [
|
|
38491
38689
|
/* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-primary font-bold", children: t("game.goal") + ":" }),
|
|
38492
|
-
/* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-foreground", children: resolved.goalCondition })
|
|
38690
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-foreground", children: str(resolved.goalCondition) })
|
|
38493
38691
|
] })
|
|
38494
38692
|
] }),
|
|
38495
38693
|
/* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
|
|
38496
38694
|
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground font-medium", children: t("eventHandler.clickObject") + ":" }),
|
|
38497
|
-
/* @__PURE__ */ jsx(HStack, { className: "flex-wrap", gap: "sm", children: objectViewers.map(({ obj, machine }) =>
|
|
38498
|
-
|
|
38499
|
-
|
|
38500
|
-
|
|
38501
|
-
|
|
38502
|
-
|
|
38503
|
-
|
|
38504
|
-
|
|
38505
|
-
|
|
38506
|
-
|
|
38507
|
-
/* @__PURE__ */
|
|
38508
|
-
|
|
38509
|
-
|
|
38510
|
-
|
|
38511
|
-
|
|
38512
|
-
|
|
38695
|
+
/* @__PURE__ */ jsx(HStack, { className: "flex-wrap", gap: "sm", children: objectViewers.map(({ obj, machine }) => {
|
|
38696
|
+
const oid = objId(obj);
|
|
38697
|
+
return /* @__PURE__ */ jsx(
|
|
38698
|
+
Box,
|
|
38699
|
+
{
|
|
38700
|
+
className: cn(
|
|
38701
|
+
"p-3 rounded-container border-2 cursor-pointer transition-all hover:scale-105",
|
|
38702
|
+
selectedObjectId === oid ? "border-primary bg-primary/10" : "border-border bg-card hover:border-muted-foreground"
|
|
38703
|
+
),
|
|
38704
|
+
onClick: () => setSelectedObjectId(oid),
|
|
38705
|
+
children: /* @__PURE__ */ jsxs(VStack, { gap: "xs", className: "items-center min-w-[120px]", children: [
|
|
38706
|
+
/* @__PURE__ */ jsx(Typography, { variant: "h5", children: objIcon(obj) }),
|
|
38707
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-foreground font-medium", children: objName(obj) }),
|
|
38708
|
+
/* @__PURE__ */ jsx(TraitStateViewer, { trait: machine, variant: "compact", size: "sm" })
|
|
38709
|
+
] })
|
|
38710
|
+
},
|
|
38711
|
+
oid
|
|
38712
|
+
);
|
|
38713
|
+
}) })
|
|
38513
38714
|
] }),
|
|
38514
38715
|
selectedObject && /* @__PURE__ */ jsx(
|
|
38515
38716
|
ObjectRulePanel,
|
|
@@ -38520,12 +38721,12 @@ function EventHandlerBoard({
|
|
|
38520
38721
|
}
|
|
38521
38722
|
),
|
|
38522
38723
|
eventLog.length > 0 && /* @__PURE__ */ jsx(EventLog, { entries: eventLog }),
|
|
38523
|
-
playState === "success" && /* @__PURE__ */ jsx(Box, { className: "p-4 rounded-container bg-success/20 border border-success text-center", children: /* @__PURE__ */ jsx(Typography, { variant: "h5", className: "text-success", children: resolved.successMessage || t("eventHandler.chainComplete") }) }),
|
|
38724
|
+
playState === "success" && /* @__PURE__ */ jsx(Box, { className: "p-4 rounded-container bg-success/20 border border-success text-center", children: /* @__PURE__ */ jsx(Typography, { variant: "h5", className: "text-success", children: str(resolved.successMessage) || t("eventHandler.chainComplete") }) }),
|
|
38524
38725
|
playState === "fail" && /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
|
|
38525
38726
|
/* @__PURE__ */ jsx(Box, { className: "p-4 rounded-container bg-warning/10 border border-warning/30 text-center", children: /* @__PURE__ */ jsx(Typography, { variant: "body1", className: "text-foreground font-medium", children: t(encourageKey) }) }),
|
|
38526
38727
|
showHint && /* @__PURE__ */ jsx(Box, { className: "p-3 rounded-container bg-accent/10 border border-accent/30", children: /* @__PURE__ */ jsxs(HStack, { className: "items-start", gap: "xs", children: [
|
|
38527
38728
|
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-accent font-bold shrink-0", children: "\u{1F4A1} " + t("game.hint") + ":" }),
|
|
38528
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-foreground", children:
|
|
38729
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-foreground", children: hint })
|
|
38529
38730
|
] }) })
|
|
38530
38731
|
] }),
|
|
38531
38732
|
/* @__PURE__ */ jsxs(HStack, { gap: "sm", children: [
|
|
@@ -38553,6 +38754,8 @@ var init_EventHandlerBoard = __esm({
|
|
|
38553
38754
|
init_TraitStateViewer();
|
|
38554
38755
|
init_ObjectRulePanel();
|
|
38555
38756
|
init_EventLog();
|
|
38757
|
+
init_puzzleObject();
|
|
38758
|
+
init_boardEntity();
|
|
38556
38759
|
ENCOURAGEMENT_KEYS = [
|
|
38557
38760
|
"puzzle.tryAgain1",
|
|
38558
38761
|
"puzzle.tryAgain2",
|
|
@@ -38641,7 +38844,10 @@ var init_FeatureGridOrganism = __esm({
|
|
|
38641
38844
|
);
|
|
38642
38845
|
useCallback(
|
|
38643
38846
|
(feature) => {
|
|
38644
|
-
eventBus.emit("UI:FEATURE_CLICK", {
|
|
38847
|
+
eventBus.emit("UI:FEATURE_CLICK", {
|
|
38848
|
+
id: String(feature.id ?? ""),
|
|
38849
|
+
href: String(feature.href ?? "")
|
|
38850
|
+
});
|
|
38645
38851
|
},
|
|
38646
38852
|
[eventBus]
|
|
38647
38853
|
);
|
|
@@ -38651,14 +38857,17 @@ var init_FeatureGridOrganism = __esm({
|
|
|
38651
38857
|
if (error) {
|
|
38652
38858
|
return /* @__PURE__ */ jsx(ErrorState, { message: error.message, className });
|
|
38653
38859
|
}
|
|
38654
|
-
const featureCards = items.map((feature) =>
|
|
38655
|
-
|
|
38656
|
-
|
|
38657
|
-
|
|
38658
|
-
|
|
38659
|
-
|
|
38660
|
-
|
|
38661
|
-
|
|
38860
|
+
const featureCards = items.map((feature) => {
|
|
38861
|
+
const href = feature.href != null ? String(feature.href) : void 0;
|
|
38862
|
+
return {
|
|
38863
|
+
icon: feature.icon != null ? String(feature.icon) : void 0,
|
|
38864
|
+
title: String(feature.title ?? ""),
|
|
38865
|
+
description: String(feature.description ?? ""),
|
|
38866
|
+
href,
|
|
38867
|
+
linkLabel: feature.linkLabel != null ? String(feature.linkLabel) : void 0,
|
|
38868
|
+
variant: href ? "interactive" : "bordered"
|
|
38869
|
+
};
|
|
38870
|
+
});
|
|
38662
38871
|
return /* @__PURE__ */ jsxs(VStack, { gap: "lg", className: cn("w-full", className), children: [
|
|
38663
38872
|
(heading || subtitle) && /* @__PURE__ */ jsxs(VStack, { gap: "sm", align: "center", className: "w-full", children: [
|
|
38664
38873
|
heading && /* @__PURE__ */ jsx(Typography, { variant: "h2", align: "center", children: heading }),
|
|
@@ -39976,22 +40185,24 @@ var init_HeroOrganism = __esm({
|
|
|
39976
40185
|
() => Array.isArray(entity) ? entity[0] : entity && typeof entity === "object" ? entity : void 0,
|
|
39977
40186
|
[entity]
|
|
39978
40187
|
);
|
|
40188
|
+
const primaryAction = resolved?.primaryAction;
|
|
40189
|
+
const secondaryAction = resolved?.secondaryAction;
|
|
39979
40190
|
const handlePrimaryClick = useCallback(() => {
|
|
39980
|
-
if (
|
|
40191
|
+
if (primaryAction) {
|
|
39981
40192
|
eventBus.emit("UI:CTA_PRIMARY", {
|
|
39982
|
-
label:
|
|
39983
|
-
href:
|
|
40193
|
+
label: String(primaryAction.label ?? ""),
|
|
40194
|
+
href: String(primaryAction.href ?? "")
|
|
39984
40195
|
});
|
|
39985
40196
|
}
|
|
39986
|
-
}, [eventBus,
|
|
40197
|
+
}, [eventBus, primaryAction]);
|
|
39987
40198
|
const handleSecondaryClick = useCallback(() => {
|
|
39988
|
-
if (
|
|
40199
|
+
if (secondaryAction) {
|
|
39989
40200
|
eventBus.emit("UI:CTA_SECONDARY", {
|
|
39990
|
-
label:
|
|
39991
|
-
href:
|
|
40201
|
+
label: String(secondaryAction.label ?? ""),
|
|
40202
|
+
href: String(secondaryAction.href ?? "")
|
|
39992
40203
|
});
|
|
39993
40204
|
}
|
|
39994
|
-
}, [eventBus,
|
|
40205
|
+
}, [eventBus, secondaryAction]);
|
|
39995
40206
|
if (isLoading) {
|
|
39996
40207
|
return /* @__PURE__ */ jsx(LoadingState, { message: t("common.loading"), className });
|
|
39997
40208
|
}
|
|
@@ -40001,17 +40212,19 @@ var init_HeroOrganism = __esm({
|
|
|
40001
40212
|
if (!resolved) {
|
|
40002
40213
|
return null;
|
|
40003
40214
|
}
|
|
40215
|
+
const imageRaw = resolved.image;
|
|
40216
|
+
const image = imageRaw ? { src: String(imageRaw.src ?? ""), alt: String(imageRaw.alt ?? "") } : void 0;
|
|
40004
40217
|
return /* @__PURE__ */ jsxs(
|
|
40005
40218
|
HeroSection,
|
|
40006
40219
|
{
|
|
40007
|
-
tag: resolved.tag,
|
|
40008
|
-
title: resolved.title,
|
|
40009
|
-
titleAccent: resolved.titleAccent,
|
|
40010
|
-
subtitle: resolved.subtitle,
|
|
40011
|
-
primaryAction:
|
|
40012
|
-
secondaryAction:
|
|
40013
|
-
installCommand: resolved.installCommand,
|
|
40014
|
-
image
|
|
40220
|
+
tag: resolved.tag != null ? String(resolved.tag) : void 0,
|
|
40221
|
+
title: String(resolved.title ?? ""),
|
|
40222
|
+
titleAccent: resolved.titleAccent != null ? String(resolved.titleAccent) : void 0,
|
|
40223
|
+
subtitle: String(resolved.subtitle ?? ""),
|
|
40224
|
+
primaryAction: primaryAction ? { label: String(primaryAction.label ?? ""), href: String(primaryAction.href ?? "") } : void 0,
|
|
40225
|
+
secondaryAction: secondaryAction ? { label: String(secondaryAction.label ?? ""), href: String(secondaryAction.href ?? "") } : void 0,
|
|
40226
|
+
installCommand: resolved.installCommand != null ? String(resolved.installCommand) : void 0,
|
|
40227
|
+
image,
|
|
40015
40228
|
imagePosition: resolved.imagePosition,
|
|
40016
40229
|
background: resolved.background,
|
|
40017
40230
|
className: cn(className),
|
|
@@ -40020,8 +40233,8 @@ var init_HeroOrganism = __esm({
|
|
|
40020
40233
|
/* @__PURE__ */ jsx(
|
|
40021
40234
|
_HeroClickInterceptor,
|
|
40022
40235
|
{
|
|
40023
|
-
hasPrimary: !!
|
|
40024
|
-
hasSecondary: !!
|
|
40236
|
+
hasPrimary: !!primaryAction,
|
|
40237
|
+
hasSecondary: !!secondaryAction,
|
|
40025
40238
|
onPrimaryClick: handlePrimaryClick,
|
|
40026
40239
|
onSecondaryClick: handleSecondaryClick
|
|
40027
40240
|
}
|
|
@@ -40250,7 +40463,7 @@ function formatValue3(value, fieldName) {
|
|
|
40250
40463
|
return String(value);
|
|
40251
40464
|
}
|
|
40252
40465
|
function formatFieldLabel2(fieldName) {
|
|
40253
|
-
return fieldName.replace(/([A-Z])/g, " $1").replace(/^./, (
|
|
40466
|
+
return fieldName.replace(/([A-Z])/g, " $1").replace(/^./, (str2) => str2.toUpperCase()).replace(/Id$/, "").trim();
|
|
40254
40467
|
}
|
|
40255
40468
|
var STATUS_STYLES2, StatusBadge, ProgressIndicator, List3;
|
|
40256
40469
|
var init_List = __esm({
|
|
@@ -41097,20 +41310,22 @@ function NegotiatorBoard({
|
|
|
41097
41310
|
}) {
|
|
41098
41311
|
const { emit } = useEventBus();
|
|
41099
41312
|
const { t } = useTranslate();
|
|
41100
|
-
const resolved =
|
|
41313
|
+
const resolved = boardEntity(entity);
|
|
41101
41314
|
const [history, setHistory] = useState([]);
|
|
41102
41315
|
const [headerError, setHeaderError] = useState(false);
|
|
41103
41316
|
const [showHint, setShowHint] = useState(false);
|
|
41317
|
+
const totalRounds = num(resolved?.totalRounds);
|
|
41318
|
+
const targetScore = num(resolved?.targetScore);
|
|
41104
41319
|
const currentRound = history.length;
|
|
41105
|
-
const isComplete = currentRound >=
|
|
41320
|
+
const isComplete = currentRound >= totalRounds;
|
|
41106
41321
|
const playerTotal = history.reduce((s, r) => s + r.playerPayoff, 0);
|
|
41107
41322
|
const opponentTotal = history.reduce((s, r) => s + r.opponentPayoff, 0);
|
|
41108
|
-
const won = isComplete && playerTotal >=
|
|
41109
|
-
const actions = resolved?.actions
|
|
41110
|
-
const payoffMatrix = resolved?.payoffMatrix
|
|
41323
|
+
const won = isComplete && playerTotal >= targetScore;
|
|
41324
|
+
const actions = Array.isArray(resolved?.actions) ? resolved.actions : [];
|
|
41325
|
+
const payoffMatrix = Array.isArray(resolved?.payoffMatrix) ? resolved.payoffMatrix : [];
|
|
41111
41326
|
const handleAction = useCallback((actionId) => {
|
|
41112
41327
|
if (isComplete) return;
|
|
41113
|
-
const opponentAction = getOpponentAction(resolved?.opponentStrategy
|
|
41328
|
+
const opponentAction = getOpponentAction(str(resolved?.opponentStrategy) || "random", actions, history);
|
|
41114
41329
|
const payoff = payoffMatrix.find(
|
|
41115
41330
|
(p2) => p2.playerAction === actionId && p2.opponentAction === opponentAction
|
|
41116
41331
|
);
|
|
@@ -41123,42 +41338,46 @@ function NegotiatorBoard({
|
|
|
41123
41338
|
};
|
|
41124
41339
|
const newHistory = [...history, result];
|
|
41125
41340
|
setHistory(newHistory);
|
|
41126
|
-
if (newHistory.length >=
|
|
41341
|
+
if (newHistory.length >= totalRounds) {
|
|
41127
41342
|
const total = newHistory.reduce((s, r) => s + r.playerPayoff, 0);
|
|
41128
|
-
if (total >=
|
|
41343
|
+
if (total >= targetScore) {
|
|
41129
41344
|
emit(`UI:${completeEvent}`, { success: true, score: total });
|
|
41130
41345
|
}
|
|
41131
|
-
if (newHistory.length >= 3 && resolved?.hint) {
|
|
41346
|
+
if (newHistory.length >= 3 && str(resolved?.hint)) {
|
|
41132
41347
|
setShowHint(true);
|
|
41133
41348
|
}
|
|
41134
41349
|
}
|
|
41135
|
-
}, [isComplete, resolved, actions, payoffMatrix, history, currentRound, completeEvent, emit]);
|
|
41350
|
+
}, [isComplete, resolved, totalRounds, targetScore, actions, payoffMatrix, history, currentRound, completeEvent, emit]);
|
|
41136
41351
|
const handleReset = () => {
|
|
41137
41352
|
setHistory([]);
|
|
41138
41353
|
setShowHint(false);
|
|
41139
41354
|
};
|
|
41140
41355
|
const getActionLabel = (id) => actions.find((a) => a.id === id)?.label ?? id;
|
|
41141
41356
|
if (!resolved) return null;
|
|
41357
|
+
const theme = resolved.theme ?? void 0;
|
|
41358
|
+
const themeBackground = theme?.background;
|
|
41359
|
+
const headerImage = str(resolved.headerImage);
|
|
41360
|
+
const hint = str(resolved.hint);
|
|
41142
41361
|
return /* @__PURE__ */ jsx(
|
|
41143
41362
|
Box,
|
|
41144
41363
|
{
|
|
41145
41364
|
className,
|
|
41146
41365
|
style: {
|
|
41147
|
-
backgroundImage:
|
|
41366
|
+
backgroundImage: themeBackground ? `url(${themeBackground})` : void 0,
|
|
41148
41367
|
backgroundSize: "cover",
|
|
41149
41368
|
backgroundPosition: "center"
|
|
41150
41369
|
},
|
|
41151
41370
|
children: /* @__PURE__ */ jsxs(VStack, { gap: "lg", className: "p-4", children: [
|
|
41152
|
-
|
|
41371
|
+
headerImage && !headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 overflow-hidden rounded-container", children: /* @__PURE__ */ jsx("img", { src: headerImage, alt: "", onError: () => setHeaderError(true), className: "w-full h-full object-cover" }) }) : headerImage && headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 rounded-container bg-gradient-to-br from-muted to-accent opacity-60" }) : null,
|
|
41153
41372
|
/* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
|
|
41154
|
-
/* @__PURE__ */ jsx(Typography, { variant: "h4", weight: "bold", children: resolved.title }),
|
|
41155
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body", children: resolved.description }),
|
|
41373
|
+
/* @__PURE__ */ jsx(Typography, { variant: "h4", weight: "bold", children: str(resolved.title) }),
|
|
41374
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body", children: str(resolved.description) }),
|
|
41156
41375
|
/* @__PURE__ */ jsxs(HStack, { gap: "md", children: [
|
|
41157
|
-
/* @__PURE__ */ jsx(Badge, { size: "sm", children: t("negotiator.round", { current: String(currentRound), total: String(
|
|
41376
|
+
/* @__PURE__ */ jsx(Badge, { size: "sm", children: t("negotiator.round", { current: String(currentRound), total: String(totalRounds) }) }),
|
|
41158
41377
|
/* @__PURE__ */ jsxs(Badge, { size: "sm", children: [
|
|
41159
41378
|
t("negotiator.target"),
|
|
41160
41379
|
": ",
|
|
41161
|
-
|
|
41380
|
+
targetScore
|
|
41162
41381
|
] })
|
|
41163
41382
|
] })
|
|
41164
41383
|
] }) }),
|
|
@@ -41207,16 +41426,16 @@ function NegotiatorBoard({
|
|
|
41207
41426
|
] }) }),
|
|
41208
41427
|
isComplete && /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", align: "center", children: [
|
|
41209
41428
|
/* @__PURE__ */ jsx(Icon, { icon: CheckCircle, size: "lg", className: won ? "text-success" : "text-error" }),
|
|
41210
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body", weight: "bold", children: won ? resolved.successMessage
|
|
41429
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body", weight: "bold", children: won ? str(resolved.successMessage) || t("negotiator.success") : str(resolved.failMessage) || t("negotiator.failed") }),
|
|
41211
41430
|
/* @__PURE__ */ jsxs(Typography, { variant: "caption", className: "text-muted-foreground", children: [
|
|
41212
41431
|
t("negotiator.finalScore"),
|
|
41213
41432
|
": ",
|
|
41214
41433
|
playerTotal,
|
|
41215
41434
|
"/",
|
|
41216
|
-
|
|
41435
|
+
targetScore
|
|
41217
41436
|
] })
|
|
41218
41437
|
] }) }),
|
|
41219
|
-
showHint &&
|
|
41438
|
+
showHint && hint && !won && /* @__PURE__ */ jsx(Card, { className: "p-4 border-l-4 border-l-warning", children: /* @__PURE__ */ jsx(Typography, { variant: "body", children: hint }) }),
|
|
41220
41439
|
isComplete && !won && /* @__PURE__ */ jsx(HStack, { justify: "center", children: /* @__PURE__ */ jsx(Button, { variant: "primary", onClick: handleReset, children: t("negotiator.playAgain") }) })
|
|
41221
41440
|
] })
|
|
41222
41441
|
}
|
|
@@ -41226,6 +41445,7 @@ var init_NegotiatorBoard = __esm({
|
|
|
41226
41445
|
"components/game/organisms/puzzles/negotiator/NegotiatorBoard.tsx"() {
|
|
41227
41446
|
init_atoms2();
|
|
41228
41447
|
init_useEventBus();
|
|
41448
|
+
init_boardEntity();
|
|
41229
41449
|
NegotiatorBoard.displayName = "NegotiatorBoard";
|
|
41230
41450
|
}
|
|
41231
41451
|
});
|
|
@@ -41261,13 +41481,13 @@ var init_PricingOrganism = __esm({
|
|
|
41261
41481
|
return /* @__PURE__ */ jsx(ErrorState, { message: error.message, className });
|
|
41262
41482
|
}
|
|
41263
41483
|
const plans = items.map((plan) => ({
|
|
41264
|
-
name: plan.name,
|
|
41265
|
-
price: plan.price,
|
|
41266
|
-
description: plan.description,
|
|
41267
|
-
features: plan.features,
|
|
41268
|
-
action: { label: plan.actionLabel, href: plan.actionHref },
|
|
41269
|
-
highlighted: plan.highlighted,
|
|
41270
|
-
badge: plan.badge
|
|
41484
|
+
name: String(plan.name ?? ""),
|
|
41485
|
+
price: String(plan.price ?? ""),
|
|
41486
|
+
description: plan.description != null ? String(plan.description) : void 0,
|
|
41487
|
+
features: (plan.features ?? []).map((f3) => String(f3)),
|
|
41488
|
+
action: { label: String(plan.actionLabel ?? ""), href: String(plan.actionHref ?? "") },
|
|
41489
|
+
highlighted: Boolean(plan.highlighted),
|
|
41490
|
+
badge: plan.badge != null ? String(plan.badge) : void 0
|
|
41271
41491
|
}));
|
|
41272
41492
|
return /* @__PURE__ */ jsxs(VStack, { gap: "lg", className: cn("w-full", className), children: [
|
|
41273
41493
|
(heading || subtitle) && /* @__PURE__ */ jsxs(VStack, { gap: "sm", align: "center", className: "w-full", children: [
|
|
@@ -43357,16 +43577,20 @@ function SequencerBoard({
|
|
|
43357
43577
|
}) {
|
|
43358
43578
|
const { emit } = useEventBus();
|
|
43359
43579
|
const { t } = useTranslate();
|
|
43360
|
-
const resolved =
|
|
43580
|
+
const resolved = boardEntity(entity);
|
|
43581
|
+
const maxSlots = num(resolved?.maxSlots);
|
|
43582
|
+
const solutions = Array.isArray(resolved?.solutions) ? resolved.solutions : [];
|
|
43583
|
+
const availableActions = Array.isArray(resolved?.availableActions) ? resolved.availableActions : [];
|
|
43584
|
+
const allowDuplicates = resolved?.allowDuplicates !== false;
|
|
43361
43585
|
const [headerError, setHeaderError] = useState(false);
|
|
43362
43586
|
const [slots, setSlots] = useState(
|
|
43363
|
-
() => Array.from({ length:
|
|
43587
|
+
() => Array.from({ length: maxSlots }, () => void 0)
|
|
43364
43588
|
);
|
|
43365
43589
|
const [playState, setPlayState] = useState("idle");
|
|
43366
43590
|
const [currentStep, setCurrentStep] = useState(-1);
|
|
43367
43591
|
const [attempts, setAttempts] = useState(0);
|
|
43368
43592
|
const [slotFeedback, setSlotFeedback] = useState(
|
|
43369
|
-
() => Array.from({ length:
|
|
43593
|
+
() => Array.from({ length: maxSlots }, () => null)
|
|
43370
43594
|
);
|
|
43371
43595
|
const timerRef = useRef(null);
|
|
43372
43596
|
useEffect(() => () => {
|
|
@@ -43400,17 +43624,17 @@ function SequencerBoard({
|
|
|
43400
43624
|
}, [emit]);
|
|
43401
43625
|
const handleReset = useCallback(() => {
|
|
43402
43626
|
if (timerRef.current) clearTimeout(timerRef.current);
|
|
43403
|
-
setSlots(Array.from({ length:
|
|
43627
|
+
setSlots(Array.from({ length: maxSlots }, () => void 0));
|
|
43404
43628
|
setPlayState("idle");
|
|
43405
43629
|
setCurrentStep(-1);
|
|
43406
43630
|
setAttempts(0);
|
|
43407
|
-
setSlotFeedback(Array.from({ length:
|
|
43408
|
-
}, [
|
|
43631
|
+
setSlotFeedback(Array.from({ length: maxSlots }, () => null));
|
|
43632
|
+
}, [maxSlots]);
|
|
43409
43633
|
const filledSlots = slots.filter((s) => !!s);
|
|
43410
43634
|
const canPlay = filledSlots.length > 0 && playState === "idle";
|
|
43411
43635
|
const handlePlay = useCallback(() => {
|
|
43412
43636
|
if (!canPlay) return;
|
|
43413
|
-
setSlotFeedback(Array.from({ length:
|
|
43637
|
+
setSlotFeedback(Array.from({ length: maxSlots }, () => null));
|
|
43414
43638
|
emit("UI:PLAY_SOUND", { key: "confirm" });
|
|
43415
43639
|
const sequence = slots.map((s) => s?.id || "");
|
|
43416
43640
|
if (playEvent) {
|
|
@@ -43421,10 +43645,10 @@ function SequencerBoard({
|
|
|
43421
43645
|
let step = 0;
|
|
43422
43646
|
const advance = () => {
|
|
43423
43647
|
step++;
|
|
43424
|
-
if (step >=
|
|
43648
|
+
if (step >= maxSlots) {
|
|
43425
43649
|
const playerSeq = slots.map((s) => s?.id);
|
|
43426
43650
|
const playerIds = slots.filter(Boolean).map((s) => s?.id || "");
|
|
43427
|
-
const success =
|
|
43651
|
+
const success = solutions.some(
|
|
43428
43652
|
(sol) => sol.length === playerIds.length && sol.every((id, i) => id === playerIds[i])
|
|
43429
43653
|
);
|
|
43430
43654
|
if (success) {
|
|
@@ -43436,7 +43660,7 @@ function SequencerBoard({
|
|
|
43436
43660
|
}
|
|
43437
43661
|
} else {
|
|
43438
43662
|
setAttempts((prev) => prev + 1);
|
|
43439
|
-
const feedback = computeSlotFeedback(playerSeq,
|
|
43663
|
+
const feedback = computeSlotFeedback(playerSeq, solutions);
|
|
43440
43664
|
setSlotFeedback(feedback);
|
|
43441
43665
|
setPlayState("idle");
|
|
43442
43666
|
setCurrentStep(-1);
|
|
@@ -43454,10 +43678,10 @@ function SequencerBoard({
|
|
|
43454
43678
|
}
|
|
43455
43679
|
};
|
|
43456
43680
|
timerRef.current = setTimeout(advance, stepDurationMs);
|
|
43457
|
-
}, [canPlay, slots,
|
|
43681
|
+
}, [canPlay, slots, maxSlots, solutions, stepDurationMs, playEvent, completeEvent, emit]);
|
|
43458
43682
|
const machine = {
|
|
43459
|
-
name: resolved?.title
|
|
43460
|
-
description: resolved?.description
|
|
43683
|
+
name: str(resolved?.title),
|
|
43684
|
+
description: str(resolved?.description),
|
|
43461
43685
|
states: slots.map((s, i) => stepLabel(s, i)),
|
|
43462
43686
|
currentState: currentStep >= 0 ? stepLabel(slots[currentStep], currentStep) : "__idle__",
|
|
43463
43687
|
transitions: slots.slice(0, -1).map((s, i) => ({
|
|
@@ -43466,37 +43690,41 @@ function SequencerBoard({
|
|
|
43466
43690
|
event: "NEXT"
|
|
43467
43691
|
}))
|
|
43468
43692
|
};
|
|
43469
|
-
const usedIds =
|
|
43470
|
-
const
|
|
43693
|
+
const usedIds = !allowDuplicates ? slots.filter(Boolean).map((s) => s?.id || "") : [];
|
|
43694
|
+
const hint = str(resolved?.hint);
|
|
43695
|
+
const showHint = attempts >= 3 && !!hint;
|
|
43471
43696
|
const hasFeedback = slotFeedback.some((f3) => f3 !== null);
|
|
43472
43697
|
const correctCount = slotFeedback.filter((f3) => f3 === "correct").length;
|
|
43473
43698
|
const encourageKey = ENCOURAGEMENT_KEYS2[Math.min(attempts - 1, ENCOURAGEMENT_KEYS2.length - 1)] ?? ENCOURAGEMENT_KEYS2[0];
|
|
43474
43699
|
if (!resolved) return null;
|
|
43700
|
+
const theme = resolved.theme ?? void 0;
|
|
43701
|
+
const themeBackground = theme?.background;
|
|
43702
|
+
const headerImage = str(resolved.headerImage);
|
|
43475
43703
|
return /* @__PURE__ */ jsxs(
|
|
43476
43704
|
VStack,
|
|
43477
43705
|
{
|
|
43478
43706
|
className: cn("p-4 gap-6", className),
|
|
43479
43707
|
style: {
|
|
43480
|
-
backgroundImage:
|
|
43708
|
+
backgroundImage: themeBackground ? `url(${themeBackground})` : void 0,
|
|
43481
43709
|
backgroundSize: "cover",
|
|
43482
43710
|
backgroundPosition: "center"
|
|
43483
43711
|
},
|
|
43484
43712
|
children: [
|
|
43485
|
-
|
|
43713
|
+
headerImage && !headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 overflow-hidden rounded-container", children: /* @__PURE__ */ jsx("img", { src: headerImage, alt: "", onError: () => setHeaderError(true), className: "w-full h-full object-cover" }) }) : headerImage && headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 rounded-container bg-gradient-to-br from-muted to-accent opacity-60" }) : null,
|
|
43486
43714
|
/* @__PURE__ */ jsxs(VStack, { gap: "xs", children: [
|
|
43487
|
-
/* @__PURE__ */ jsx(Typography, { variant: "h4", className: "text-foreground", children: resolved.title }),
|
|
43488
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground", children: resolved.description })
|
|
43715
|
+
/* @__PURE__ */ jsx(Typography, { variant: "h4", className: "text-foreground", children: str(resolved.title) }),
|
|
43716
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground", children: str(resolved.description) })
|
|
43489
43717
|
] }),
|
|
43490
43718
|
showHint && /* @__PURE__ */ jsx(Box, { className: "p-3 rounded-container bg-accent/10 border border-accent/30", children: /* @__PURE__ */ jsxs(HStack, { className: "items-start", gap: "xs", children: [
|
|
43491
43719
|
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-accent font-bold shrink-0", children: "\u{1F4A1} " + t("game.hint") + ":" }),
|
|
43492
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-foreground", children:
|
|
43720
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-foreground", children: hint })
|
|
43493
43721
|
] }) }),
|
|
43494
43722
|
filledSlots.length > 0 && /* @__PURE__ */ jsx(TraitStateViewer, { trait: machine, variant: "linear", size: "md" }),
|
|
43495
43723
|
/* @__PURE__ */ jsxs(VStack, { gap: "xs", children: [
|
|
43496
43724
|
/* @__PURE__ */ jsxs(HStack, { className: "items-center justify-between", children: [
|
|
43497
43725
|
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground font-medium", children: t("sequencer.yourSequence") + ":" }),
|
|
43498
43726
|
hasFeedback && playState === "idle" && /* @__PURE__ */ jsxs(Typography, { variant: "caption", className: "text-muted-foreground", children: [
|
|
43499
|
-
`${correctCount}/${
|
|
43727
|
+
`${correctCount}/${maxSlots} `,
|
|
43500
43728
|
"\u2705"
|
|
43501
43729
|
] })
|
|
43502
43730
|
] }),
|
|
@@ -43504,7 +43732,7 @@ function SequencerBoard({
|
|
|
43504
43732
|
SequenceBar,
|
|
43505
43733
|
{
|
|
43506
43734
|
slots,
|
|
43507
|
-
maxSlots
|
|
43735
|
+
maxSlots,
|
|
43508
43736
|
onSlotDrop: handleSlotDrop,
|
|
43509
43737
|
onSlotRemove: handleSlotRemove,
|
|
43510
43738
|
playing: playState === "playing",
|
|
@@ -43518,15 +43746,15 @@ function SequencerBoard({
|
|
|
43518
43746
|
playState !== "playing" && /* @__PURE__ */ jsx(
|
|
43519
43747
|
ActionPalette,
|
|
43520
43748
|
{
|
|
43521
|
-
actions:
|
|
43749
|
+
actions: availableActions,
|
|
43522
43750
|
usedActionIds: usedIds,
|
|
43523
|
-
allowDuplicates
|
|
43751
|
+
allowDuplicates,
|
|
43524
43752
|
categoryColors,
|
|
43525
43753
|
label: t("sequencer.dragActions")
|
|
43526
43754
|
}
|
|
43527
43755
|
),
|
|
43528
43756
|
hasFeedback && playState === "idle" && attempts > 0 && /* @__PURE__ */ jsx(Box, { className: "p-3 rounded-container bg-warning/10 border border-warning/30 text-center", children: /* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-foreground", children: t(encourageKey) }) }),
|
|
43529
|
-
playState === "success" && /* @__PURE__ */ jsx(Box, { className: "p-4 rounded-container bg-success/20 border border-success text-center", children: /* @__PURE__ */ jsx(Typography, { variant: "h5", className: "text-success", children: resolved.successMessage || t("sequencer.levelComplete") }) }),
|
|
43757
|
+
playState === "success" && /* @__PURE__ */ jsx(Box, { className: "p-4 rounded-container bg-success/20 border border-success text-center", children: /* @__PURE__ */ jsx(Typography, { variant: "h5", className: "text-success", children: str(resolved.successMessage) || t("sequencer.levelComplete") }) }),
|
|
43530
43758
|
/* @__PURE__ */ jsxs(HStack, { gap: "sm", children: [
|
|
43531
43759
|
/* @__PURE__ */ jsx(
|
|
43532
43760
|
Button,
|
|
@@ -43550,6 +43778,7 @@ var init_SequencerBoard = __esm({
|
|
|
43550
43778
|
init_cn();
|
|
43551
43779
|
init_useEventBus();
|
|
43552
43780
|
init_TraitStateViewer();
|
|
43781
|
+
init_boardEntity();
|
|
43553
43782
|
init_SequenceBar();
|
|
43554
43783
|
init_ActionPalette();
|
|
43555
43784
|
ENCOURAGEMENT_KEYS2 = [
|
|
@@ -43599,18 +43828,21 @@ var init_ShowcaseOrganism = __esm({
|
|
|
43599
43828
|
heading && /* @__PURE__ */ jsx(Typography, { variant: "h2", align: "center", children: heading }),
|
|
43600
43829
|
subtitle && /* @__PURE__ */ jsx(Typography, { variant: "body1", color: "muted", align: "center", className: "max-w-2xl", children: subtitle })
|
|
43601
43830
|
] }),
|
|
43602
|
-
/* @__PURE__ */ jsx(SimpleGrid, { cols: columns, gap: "lg", children: items.map((item) =>
|
|
43603
|
-
|
|
43604
|
-
|
|
43605
|
-
|
|
43606
|
-
|
|
43607
|
-
|
|
43608
|
-
|
|
43609
|
-
|
|
43610
|
-
|
|
43611
|
-
|
|
43612
|
-
|
|
43613
|
-
|
|
43831
|
+
/* @__PURE__ */ jsx(SimpleGrid, { cols: columns, gap: "lg", children: items.map((item) => {
|
|
43832
|
+
const imageRaw = item.image;
|
|
43833
|
+
return /* @__PURE__ */ jsx(
|
|
43834
|
+
ShowcaseCard,
|
|
43835
|
+
{
|
|
43836
|
+
title: String(item.title ?? ""),
|
|
43837
|
+
description: item.description != null ? String(item.description) : void 0,
|
|
43838
|
+
image: { src: String(imageRaw?.src ?? ""), alt: String(imageRaw?.alt ?? "") },
|
|
43839
|
+
href: item.href != null ? String(item.href) : void 0,
|
|
43840
|
+
badge: item.badge != null ? String(item.badge) : void 0,
|
|
43841
|
+
accentColor: item.accentColor != null ? String(item.accentColor) : void 0
|
|
43842
|
+
},
|
|
43843
|
+
String(item.id ?? "")
|
|
43844
|
+
);
|
|
43845
|
+
}) })
|
|
43614
43846
|
] });
|
|
43615
43847
|
};
|
|
43616
43848
|
ShowcaseOrganism.displayName = "ShowcaseOrganism";
|
|
@@ -43978,8 +44210,8 @@ function SimulatorBoard({
|
|
|
43978
44210
|
}) {
|
|
43979
44211
|
const { emit } = useEventBus();
|
|
43980
44212
|
const { t } = useTranslate();
|
|
43981
|
-
const resolved =
|
|
43982
|
-
const parameters = resolved?.parameters
|
|
44213
|
+
const resolved = boardEntity(entity);
|
|
44214
|
+
const parameters = Array.isArray(resolved?.parameters) ? resolved.parameters : [];
|
|
43983
44215
|
const [values, setValues] = useState(() => {
|
|
43984
44216
|
const init = {};
|
|
43985
44217
|
for (const p2 of parameters) {
|
|
@@ -43993,15 +44225,15 @@ function SimulatorBoard({
|
|
|
43993
44225
|
const [showHint, setShowHint] = useState(false);
|
|
43994
44226
|
const computeOutput = useCallback((params) => {
|
|
43995
44227
|
try {
|
|
43996
|
-
const fn = new Function("params", `return (${resolved?.computeExpression})`);
|
|
44228
|
+
const fn = new Function("params", `return (${str(resolved?.computeExpression)})`);
|
|
43997
44229
|
return fn(params);
|
|
43998
44230
|
} catch {
|
|
43999
44231
|
return 0;
|
|
44000
44232
|
}
|
|
44001
44233
|
}, [resolved?.computeExpression]);
|
|
44002
44234
|
const output = useMemo(() => computeOutput(values) ?? 0, [computeOutput, values]);
|
|
44003
|
-
const targetValue = resolved?.targetValue
|
|
44004
|
-
const targetTolerance = resolved?.targetTolerance
|
|
44235
|
+
const targetValue = num(resolved?.targetValue);
|
|
44236
|
+
const targetTolerance = num(resolved?.targetTolerance);
|
|
44005
44237
|
const isCorrect = Math.abs(output - targetValue) <= targetTolerance;
|
|
44006
44238
|
const handleParameterChange = (id, value) => {
|
|
44007
44239
|
if (submitted) return;
|
|
@@ -44016,7 +44248,7 @@ function SimulatorBoard({
|
|
|
44016
44248
|
};
|
|
44017
44249
|
const handleReset = () => {
|
|
44018
44250
|
setSubmitted(false);
|
|
44019
|
-
if (attempts >= 2 && resolved?.hint) {
|
|
44251
|
+
if (attempts >= 2 && str(resolved?.hint)) {
|
|
44020
44252
|
setShowHint(true);
|
|
44021
44253
|
}
|
|
44022
44254
|
};
|
|
@@ -44031,20 +44263,26 @@ function SimulatorBoard({
|
|
|
44031
44263
|
setShowHint(false);
|
|
44032
44264
|
};
|
|
44033
44265
|
if (!resolved) return null;
|
|
44266
|
+
const theme = resolved.theme ?? void 0;
|
|
44267
|
+
const themeBackground = theme?.background;
|
|
44268
|
+
const headerImage = str(resolved.headerImage);
|
|
44269
|
+
const hint = str(resolved.hint);
|
|
44270
|
+
const outputLabel = str(resolved.outputLabel);
|
|
44271
|
+
const outputUnit = str(resolved.outputUnit);
|
|
44034
44272
|
return /* @__PURE__ */ jsx(
|
|
44035
44273
|
Box,
|
|
44036
44274
|
{
|
|
44037
44275
|
className,
|
|
44038
44276
|
style: {
|
|
44039
|
-
backgroundImage:
|
|
44277
|
+
backgroundImage: themeBackground ? `url(${themeBackground})` : void 0,
|
|
44040
44278
|
backgroundSize: "cover",
|
|
44041
44279
|
backgroundPosition: "center"
|
|
44042
44280
|
},
|
|
44043
44281
|
children: /* @__PURE__ */ jsxs(VStack, { gap: "lg", className: "p-4", children: [
|
|
44044
|
-
|
|
44282
|
+
headerImage && !headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 overflow-hidden rounded-container", children: /* @__PURE__ */ jsx("img", { src: headerImage, alt: "", onError: () => setHeaderError(true), className: "w-full h-full object-cover" }) }) : headerImage && headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 rounded-container bg-gradient-to-br from-muted to-accent opacity-60" }) : null,
|
|
44045
44283
|
/* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
|
|
44046
|
-
/* @__PURE__ */ jsx(Typography, { variant: "h4", weight: "bold", children: resolved.title }),
|
|
44047
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body", children: resolved.description })
|
|
44284
|
+
/* @__PURE__ */ jsx(Typography, { variant: "h4", weight: "bold", children: str(resolved.title) }),
|
|
44285
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body", children: str(resolved.description) })
|
|
44048
44286
|
] }) }),
|
|
44049
44287
|
/* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "md", children: [
|
|
44050
44288
|
/* @__PURE__ */ jsx(Typography, { variant: "small", weight: "bold", className: "uppercase tracking-wider text-muted-foreground", children: t("simulator.parameters") }),
|
|
@@ -44085,28 +44323,28 @@ function SimulatorBoard({
|
|
|
44085
44323
|
] }, param.id))
|
|
44086
44324
|
] }) }),
|
|
44087
44325
|
/* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", align: "center", children: [
|
|
44088
|
-
/* @__PURE__ */ jsx(Typography, { variant: "small", weight: "bold", className: "uppercase tracking-wider text-muted-foreground", children:
|
|
44326
|
+
/* @__PURE__ */ jsx(Typography, { variant: "small", weight: "bold", className: "uppercase tracking-wider text-muted-foreground", children: outputLabel }),
|
|
44089
44327
|
/* @__PURE__ */ jsxs(Typography, { variant: "h3", weight: "bold", children: [
|
|
44090
44328
|
output.toFixed(2),
|
|
44091
44329
|
" ",
|
|
44092
|
-
|
|
44330
|
+
outputUnit
|
|
44093
44331
|
] }),
|
|
44094
44332
|
submitted && /* @__PURE__ */ jsxs(HStack, { gap: "xs", align: "center", children: [
|
|
44095
44333
|
/* @__PURE__ */ jsx(Icon, { icon: isCorrect ? CheckCircle : XCircle, size: "sm", className: isCorrect ? "text-success" : "text-error" }),
|
|
44096
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body", className: isCorrect ? "text-success" : "text-error", children: isCorrect ? resolved.successMessage
|
|
44334
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body", className: isCorrect ? "text-success" : "text-error", children: isCorrect ? str(resolved.successMessage) || t("simulator.correct") : str(resolved.failMessage) || t("simulator.incorrect") })
|
|
44097
44335
|
] }),
|
|
44098
44336
|
/* @__PURE__ */ jsxs(Typography, { variant: "caption", className: "text-muted-foreground", children: [
|
|
44099
44337
|
t("simulator.target"),
|
|
44100
44338
|
": ",
|
|
44101
44339
|
targetValue,
|
|
44102
44340
|
" ",
|
|
44103
|
-
|
|
44341
|
+
outputUnit,
|
|
44104
44342
|
" (\xB1",
|
|
44105
44343
|
targetTolerance,
|
|
44106
44344
|
")"
|
|
44107
44345
|
] })
|
|
44108
44346
|
] }) }),
|
|
44109
|
-
showHint &&
|
|
44347
|
+
showHint && hint && /* @__PURE__ */ jsx(Card, { className: "p-4 border-l-4 border-l-warning", children: /* @__PURE__ */ jsx(Typography, { variant: "body", children: hint }) }),
|
|
44110
44348
|
/* @__PURE__ */ jsxs(HStack, { gap: "sm", justify: "center", children: [
|
|
44111
44349
|
!submitted ? /* @__PURE__ */ jsxs(Button, { variant: "primary", onClick: handleSubmit, children: [
|
|
44112
44350
|
/* @__PURE__ */ jsx(Icon, { icon: Play, size: "sm" }),
|
|
@@ -44125,6 +44363,7 @@ var init_SimulatorBoard = __esm({
|
|
|
44125
44363
|
"components/game/organisms/puzzles/simulator/SimulatorBoard.tsx"() {
|
|
44126
44364
|
init_atoms2();
|
|
44127
44365
|
init_useEventBus();
|
|
44366
|
+
init_boardEntity();
|
|
44128
44367
|
SimulatorBoard.displayName = "SimulatorBoard";
|
|
44129
44368
|
}
|
|
44130
44369
|
});
|
|
@@ -44550,22 +44789,25 @@ function VariablePanel({
|
|
|
44550
44789
|
return /* @__PURE__ */ jsxs(VStack, { className: cn("p-3 rounded-lg bg-card border border-border", className), gap: "sm", children: [
|
|
44551
44790
|
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground font-medium", children: t("stateArchitect.variables", { name: entityName }) }),
|
|
44552
44791
|
variables.map((v) => {
|
|
44553
|
-
const
|
|
44554
|
-
const
|
|
44555
|
-
const
|
|
44792
|
+
const name = v.name == null ? "" : String(v.name);
|
|
44793
|
+
const value = numField(v.value);
|
|
44794
|
+
const max = numField(v.max, 100);
|
|
44795
|
+
const min = numField(v.min, 0);
|
|
44796
|
+
const unit = v.unit == null ? "" : String(v.unit);
|
|
44797
|
+
const pct = Math.round((value - min) / (max - min) * 100);
|
|
44556
44798
|
const isHigh = pct > 80;
|
|
44557
44799
|
const isLow = pct < 20;
|
|
44558
44800
|
return /* @__PURE__ */ jsxs(VStack, { gap: "none", children: [
|
|
44559
44801
|
/* @__PURE__ */ jsxs(HStack, { className: "items-center justify-between", children: [
|
|
44560
|
-
/* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-foreground font-medium", children:
|
|
44802
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-foreground font-medium", children: name }),
|
|
44561
44803
|
/* @__PURE__ */ jsxs(Typography, { variant: "caption", className: cn(
|
|
44562
44804
|
isHigh ? "text-error" : isLow ? "text-warning" : "text-foreground"
|
|
44563
44805
|
), children: [
|
|
44564
|
-
|
|
44565
|
-
|
|
44806
|
+
value,
|
|
44807
|
+
unit,
|
|
44566
44808
|
" / ",
|
|
44567
44809
|
max,
|
|
44568
|
-
|
|
44810
|
+
unit
|
|
44569
44811
|
] })
|
|
44570
44812
|
] }),
|
|
44571
44813
|
/* @__PURE__ */ jsx(
|
|
@@ -44576,14 +44818,19 @@ function VariablePanel({
|
|
|
44576
44818
|
size: "sm"
|
|
44577
44819
|
}
|
|
44578
44820
|
)
|
|
44579
|
-
] },
|
|
44821
|
+
] }, name);
|
|
44580
44822
|
})
|
|
44581
44823
|
] });
|
|
44582
44824
|
}
|
|
44825
|
+
var numField;
|
|
44583
44826
|
var init_VariablePanel = __esm({
|
|
44584
44827
|
"components/game/organisms/puzzles/state-architect/VariablePanel.tsx"() {
|
|
44585
44828
|
init_atoms2();
|
|
44586
44829
|
init_cn();
|
|
44830
|
+
numField = (v, fallback = 0) => {
|
|
44831
|
+
const n = Number(v);
|
|
44832
|
+
return Number.isFinite(n) ? n : fallback;
|
|
44833
|
+
};
|
|
44587
44834
|
VariablePanel.displayName = "VariablePanel";
|
|
44588
44835
|
}
|
|
44589
44836
|
});
|
|
@@ -44610,14 +44857,21 @@ function StateArchitectBoard({
|
|
|
44610
44857
|
}) {
|
|
44611
44858
|
const { emit } = useEventBus();
|
|
44612
44859
|
const { t } = useTranslate();
|
|
44613
|
-
const resolved =
|
|
44614
|
-
const
|
|
44860
|
+
const resolved = boardEntity(entity);
|
|
44861
|
+
const entityStates = Array.isArray(resolved?.states) ? resolved.states : [];
|
|
44862
|
+
const initialState = str(resolved?.initialState);
|
|
44863
|
+
const entityName = str(resolved?.entityName);
|
|
44864
|
+
const availableEvents = Array.isArray(resolved?.availableEvents) ? resolved.availableEvents : [];
|
|
44865
|
+
const testCases = Array.isArray(resolved?.testCases) ? resolved.testCases : [];
|
|
44866
|
+
const entityTransitions = Array.isArray(resolved?.transitions) ? resolved.transitions : [];
|
|
44867
|
+
const entityVariables = rows(resolved?.variables);
|
|
44868
|
+
const [transitions, setTransitions] = useState(entityTransitions);
|
|
44615
44869
|
const [headerError, setHeaderError] = useState(false);
|
|
44616
44870
|
const [playState, setPlayState] = useState("editing");
|
|
44617
|
-
const [currentState, setCurrentState] = useState(
|
|
44871
|
+
const [currentState, setCurrentState] = useState(initialState);
|
|
44618
44872
|
const [selectedState, setSelectedState] = useState(null);
|
|
44619
44873
|
const [testResults, setTestResults] = useState([]);
|
|
44620
|
-
const [variables, setVariables] = useState(
|
|
44874
|
+
const [variables, setVariables] = useState(() => [...entityVariables]);
|
|
44621
44875
|
const [attempts, setAttempts] = useState(0);
|
|
44622
44876
|
const timerRef = useRef(null);
|
|
44623
44877
|
const [addingFrom, setAddingFrom] = useState(null);
|
|
@@ -44626,12 +44880,12 @@ function StateArchitectBoard({
|
|
|
44626
44880
|
}, []);
|
|
44627
44881
|
const GRAPH_W = 500;
|
|
44628
44882
|
const GRAPH_H = 400;
|
|
44629
|
-
const positions = useMemo(() => layoutStates(
|
|
44883
|
+
const positions = useMemo(() => layoutStates(entityStates, GRAPH_W, GRAPH_H), [entityStates]);
|
|
44630
44884
|
const handleStateClick = useCallback((state) => {
|
|
44631
44885
|
if (playState !== "editing") return;
|
|
44632
44886
|
if (addingFrom) {
|
|
44633
44887
|
if (addingFrom !== state) {
|
|
44634
|
-
const event =
|
|
44888
|
+
const event = availableEvents[0] || "EVENT";
|
|
44635
44889
|
const newTrans = {
|
|
44636
44890
|
id: `t-${nextTransId++}`,
|
|
44637
44891
|
from: addingFrom,
|
|
@@ -44644,7 +44898,7 @@ function StateArchitectBoard({
|
|
|
44644
44898
|
} else {
|
|
44645
44899
|
setSelectedState(state);
|
|
44646
44900
|
}
|
|
44647
|
-
}, [playState, addingFrom,
|
|
44901
|
+
}, [playState, addingFrom, availableEvents]);
|
|
44648
44902
|
const handleStartAddTransition = useCallback(() => {
|
|
44649
44903
|
if (!selectedState) return;
|
|
44650
44904
|
setAddingFrom(selectedState);
|
|
@@ -44653,9 +44907,9 @@ function StateArchitectBoard({
|
|
|
44653
44907
|
setTransitions((prev) => prev.filter((t2) => t2.id !== transId));
|
|
44654
44908
|
}, []);
|
|
44655
44909
|
const machine = useMemo(() => ({
|
|
44656
|
-
name:
|
|
44657
|
-
description: resolved?.description
|
|
44658
|
-
states:
|
|
44910
|
+
name: entityName,
|
|
44911
|
+
description: str(resolved?.description),
|
|
44912
|
+
states: entityStates,
|
|
44659
44913
|
currentState,
|
|
44660
44914
|
transitions: transitions.map((t2) => ({
|
|
44661
44915
|
from: t2.from,
|
|
@@ -44663,7 +44917,7 @@ function StateArchitectBoard({
|
|
|
44663
44917
|
event: t2.event,
|
|
44664
44918
|
guardHint: t2.guardHint
|
|
44665
44919
|
}))
|
|
44666
|
-
}), [resolved, currentState, transitions]);
|
|
44920
|
+
}), [entityName, resolved, entityStates, currentState, transitions]);
|
|
44667
44921
|
const handleTest = useCallback(() => {
|
|
44668
44922
|
if (playState !== "editing") return;
|
|
44669
44923
|
if (testEvent) emit(`UI:${testEvent}`, {});
|
|
@@ -44672,7 +44926,7 @@ function StateArchitectBoard({
|
|
|
44672
44926
|
const results = [];
|
|
44673
44927
|
let testIdx = 0;
|
|
44674
44928
|
const runNextTest = () => {
|
|
44675
|
-
if (testIdx >=
|
|
44929
|
+
if (testIdx >= testCases.length) {
|
|
44676
44930
|
const allPassed = results.every((r) => r.passed);
|
|
44677
44931
|
setPlayState(allPassed ? "success" : "fail");
|
|
44678
44932
|
setTestResults(results);
|
|
@@ -44687,9 +44941,9 @@ function StateArchitectBoard({
|
|
|
44687
44941
|
}
|
|
44688
44942
|
return;
|
|
44689
44943
|
}
|
|
44690
|
-
const testCase =
|
|
44944
|
+
const testCase = testCases[testIdx];
|
|
44691
44945
|
if (!testCase) return;
|
|
44692
|
-
let state =
|
|
44946
|
+
let state = initialState;
|
|
44693
44947
|
for (const event of testCase.events) {
|
|
44694
44948
|
const trans = transitions.find((t2) => t2.from === state && t2.event === event);
|
|
44695
44949
|
if (trans) {
|
|
@@ -44707,53 +44961,57 @@ function StateArchitectBoard({
|
|
|
44707
44961
|
timerRef.current = setTimeout(runNextTest, stepDurationMs);
|
|
44708
44962
|
};
|
|
44709
44963
|
timerRef.current = setTimeout(runNextTest, stepDurationMs);
|
|
44710
|
-
}, [playState, transitions,
|
|
44964
|
+
}, [playState, transitions, testCases, initialState, stepDurationMs, testEvent, completeEvent, emit]);
|
|
44711
44965
|
const handleTryAgain = useCallback(() => {
|
|
44712
44966
|
if (timerRef.current) clearTimeout(timerRef.current);
|
|
44713
44967
|
setPlayState("editing");
|
|
44714
|
-
setCurrentState(
|
|
44968
|
+
setCurrentState(initialState);
|
|
44715
44969
|
setTestResults([]);
|
|
44716
|
-
}, [
|
|
44970
|
+
}, [initialState]);
|
|
44717
44971
|
const handleReset = useCallback(() => {
|
|
44718
44972
|
if (timerRef.current) clearTimeout(timerRef.current);
|
|
44719
|
-
setTransitions(
|
|
44973
|
+
setTransitions(entityTransitions);
|
|
44720
44974
|
setPlayState("editing");
|
|
44721
|
-
setCurrentState(
|
|
44975
|
+
setCurrentState(initialState);
|
|
44722
44976
|
setTestResults([]);
|
|
44723
|
-
setVariables(
|
|
44977
|
+
setVariables([...entityVariables]);
|
|
44724
44978
|
setSelectedState(null);
|
|
44725
44979
|
setAddingFrom(null);
|
|
44726
44980
|
setAttempts(0);
|
|
44727
|
-
}, [
|
|
44981
|
+
}, [entityTransitions, initialState, entityVariables]);
|
|
44728
44982
|
const codeData = useMemo(() => ({
|
|
44729
|
-
name:
|
|
44730
|
-
states:
|
|
44731
|
-
initialState
|
|
44983
|
+
name: entityName,
|
|
44984
|
+
states: entityStates,
|
|
44985
|
+
initialState,
|
|
44732
44986
|
transitions: transitions.map((t2) => ({
|
|
44733
44987
|
from: t2.from,
|
|
44734
44988
|
to: t2.to,
|
|
44735
44989
|
event: t2.event,
|
|
44736
44990
|
...t2.guardHint ? { guard: t2.guardHint } : {}
|
|
44737
44991
|
}))
|
|
44738
|
-
}), [
|
|
44992
|
+
}), [entityName, entityStates, initialState, transitions]);
|
|
44739
44993
|
if (!resolved) return null;
|
|
44994
|
+
const theme = resolved.theme ?? void 0;
|
|
44995
|
+
const themeBackground = theme?.background;
|
|
44996
|
+
const headerImage = str(resolved.headerImage);
|
|
44997
|
+
const hint = str(resolved.hint);
|
|
44740
44998
|
return /* @__PURE__ */ jsxs(
|
|
44741
44999
|
VStack,
|
|
44742
45000
|
{
|
|
44743
45001
|
className: cn("p-4 gap-6", className),
|
|
44744
45002
|
style: {
|
|
44745
|
-
backgroundImage:
|
|
45003
|
+
backgroundImage: themeBackground ? `url(${themeBackground})` : void 0,
|
|
44746
45004
|
backgroundSize: "cover",
|
|
44747
45005
|
backgroundPosition: "center"
|
|
44748
45006
|
},
|
|
44749
45007
|
children: [
|
|
44750
|
-
|
|
45008
|
+
headerImage && !headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 overflow-hidden rounded-container", children: /* @__PURE__ */ jsx("img", { src: headerImage, alt: "", onError: () => setHeaderError(true), className: "w-full h-full object-cover" }) }) : headerImage && headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 rounded-container bg-gradient-to-br from-muted to-accent opacity-60" }) : null,
|
|
44751
45009
|
/* @__PURE__ */ jsxs(VStack, { gap: "xs", children: [
|
|
44752
|
-
/* @__PURE__ */ jsx(Typography, { variant: "h4", className: "text-foreground", children: resolved.title }),
|
|
44753
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground", children: resolved.description }),
|
|
45010
|
+
/* @__PURE__ */ jsx(Typography, { variant: "h4", className: "text-foreground", children: str(resolved.title) }),
|
|
45011
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground", children: str(resolved.description) }),
|
|
44754
45012
|
/* @__PURE__ */ jsxs(HStack, { className: "items-center p-2 rounded bg-warning/10 border border-warning/30", gap: "xs", children: [
|
|
44755
45013
|
/* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-warning font-bold", children: t("game.hint") + ":" }),
|
|
44756
|
-
/* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-foreground", children:
|
|
45014
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-foreground", children: hint })
|
|
44757
45015
|
] })
|
|
44758
45016
|
] }),
|
|
44759
45017
|
/* @__PURE__ */ jsxs(HStack, { className: "flex-wrap items-start", gap: "lg", children: [
|
|
@@ -44801,14 +45059,14 @@ function StateArchitectBoard({
|
|
|
44801
45059
|
]
|
|
44802
45060
|
}
|
|
44803
45061
|
),
|
|
44804
|
-
|
|
45062
|
+
entityStates.map((state) => /* @__PURE__ */ jsx(
|
|
44805
45063
|
StateNode2,
|
|
44806
45064
|
{
|
|
44807
45065
|
name: state,
|
|
44808
45066
|
position: positions[state],
|
|
44809
45067
|
isCurrent: state === currentState,
|
|
44810
45068
|
isSelected: state === selectedState,
|
|
44811
|
-
isInitial: state ===
|
|
45069
|
+
isInitial: state === initialState,
|
|
44812
45070
|
onClick: () => handleStateClick(state)
|
|
44813
45071
|
},
|
|
44814
45072
|
state
|
|
@@ -44855,7 +45113,7 @@ function StateArchitectBoard({
|
|
|
44855
45113
|
/* @__PURE__ */ jsx(
|
|
44856
45114
|
VariablePanel,
|
|
44857
45115
|
{
|
|
44858
|
-
entityName
|
|
45116
|
+
entityName,
|
|
44859
45117
|
variables
|
|
44860
45118
|
}
|
|
44861
45119
|
),
|
|
@@ -44870,12 +45128,12 @@ function StateArchitectBoard({
|
|
|
44870
45128
|
resolved.showCodeView !== false && /* @__PURE__ */ jsx(CodeView, { data: codeData, label: "View Code" })
|
|
44871
45129
|
] })
|
|
44872
45130
|
] }),
|
|
44873
|
-
playState === "success" && /* @__PURE__ */ jsx(Box, { className: "p-4 rounded-container bg-success/20 border border-success text-center", children: /* @__PURE__ */ jsx(Typography, { variant: "h5", className: "text-success", children: resolved.successMessage || t("stateArchitect.allPassed") }) }),
|
|
45131
|
+
playState === "success" && /* @__PURE__ */ jsx(Box, { className: "p-4 rounded-container bg-success/20 border border-success text-center", children: /* @__PURE__ */ jsx(Typography, { variant: "h5", className: "text-success", children: str(resolved.successMessage) || t("stateArchitect.allPassed") }) }),
|
|
44874
45132
|
playState === "fail" && /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
|
|
44875
45133
|
/* @__PURE__ */ jsx(Box, { className: "p-4 rounded-container bg-warning/10 border border-warning/30 text-center", children: /* @__PURE__ */ jsx(Typography, { variant: "body1", className: "text-foreground font-medium", children: t(ENCOURAGEMENT_KEYS3[Math.min(attempts - 1, ENCOURAGEMENT_KEYS3.length - 1)] ?? ENCOURAGEMENT_KEYS3[0]) }) }),
|
|
44876
|
-
attempts >= 3 &&
|
|
45134
|
+
attempts >= 3 && hint && /* @__PURE__ */ jsx(Box, { className: "p-3 rounded-container bg-accent/10 border border-accent/30", children: /* @__PURE__ */ jsxs(HStack, { className: "items-start", gap: "xs", children: [
|
|
44877
45135
|
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-accent font-bold shrink-0", children: "\u{1F4A1} " + t("game.hint") + ":" }),
|
|
44878
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-foreground", children:
|
|
45136
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-foreground", children: hint })
|
|
44879
45137
|
] }) })
|
|
44880
45138
|
] }),
|
|
44881
45139
|
/* @__PURE__ */ jsxs(HStack, { gap: "sm", children: [
|
|
@@ -44905,6 +45163,7 @@ var init_StateArchitectBoard = __esm({
|
|
|
44905
45163
|
init_TransitionArrow();
|
|
44906
45164
|
init_VariablePanel();
|
|
44907
45165
|
init_CodeView();
|
|
45166
|
+
init_boardEntity();
|
|
44908
45167
|
ENCOURAGEMENT_KEYS3 = [
|
|
44909
45168
|
"puzzle.tryAgain1",
|
|
44910
45169
|
"puzzle.tryAgain2",
|
|
@@ -44941,8 +45200,8 @@ var init_StatsOrganism = __esm({
|
|
|
44941
45200
|
return /* @__PURE__ */ jsx(ErrorState, { message: error.message, className });
|
|
44942
45201
|
}
|
|
44943
45202
|
const stats = items.map((item) => ({
|
|
44944
|
-
value: item.value,
|
|
44945
|
-
label: item.label
|
|
45203
|
+
value: String(item.value ?? ""),
|
|
45204
|
+
label: String(item.label ?? "")
|
|
44946
45205
|
}));
|
|
44947
45206
|
return /* @__PURE__ */ jsx(
|
|
44948
45207
|
StatsGrid,
|
|
@@ -44988,10 +45247,10 @@ var init_StepFlowOrganism = __esm({
|
|
|
44988
45247
|
return /* @__PURE__ */ jsx(ErrorState, { message: error.message, className });
|
|
44989
45248
|
}
|
|
44990
45249
|
const steps = items.map((item) => ({
|
|
44991
|
-
number: item.number,
|
|
44992
|
-
title: item.title,
|
|
44993
|
-
description: item.description,
|
|
44994
|
-
icon: item.icon
|
|
45250
|
+
number: item.number != null ? Number(item.number) : void 0,
|
|
45251
|
+
title: String(item.title ?? ""),
|
|
45252
|
+
description: String(item.description ?? ""),
|
|
45253
|
+
icon: item.icon != null ? String(item.icon) : void 0
|
|
44995
45254
|
}));
|
|
44996
45255
|
return /* @__PURE__ */ jsxs(VStack, { gap: "lg", className: cn("w-full", className), children: [
|
|
44997
45256
|
(heading || subtitle) && /* @__PURE__ */ jsxs(VStack, { gap: "sm", align: "center", className: "w-full", children: [
|
|
@@ -45164,13 +45423,13 @@ var init_TeamOrganism = __esm({
|
|
|
45164
45423
|
/* @__PURE__ */ jsx(SimpleGrid, { cols: cols > 0 ? cols : 1, gap: "lg", children: items.map((member) => /* @__PURE__ */ jsx(
|
|
45165
45424
|
TeamCard,
|
|
45166
45425
|
{
|
|
45167
|
-
name: member.name,
|
|
45168
|
-
nameAr: member.nameAr,
|
|
45169
|
-
role: member.role,
|
|
45170
|
-
bio: member.bio,
|
|
45171
|
-
avatar: member.avatar
|
|
45426
|
+
name: String(member.name ?? ""),
|
|
45427
|
+
nameAr: member.nameAr != null ? String(member.nameAr) : void 0,
|
|
45428
|
+
role: String(member.role ?? ""),
|
|
45429
|
+
bio: String(member.bio ?? ""),
|
|
45430
|
+
avatar: member.avatar != null ? String(member.avatar) : void 0
|
|
45172
45431
|
},
|
|
45173
|
-
member.id
|
|
45432
|
+
String(member.id ?? "")
|
|
45174
45433
|
)) })
|
|
45175
45434
|
] });
|
|
45176
45435
|
};
|
|
@@ -45407,8 +45666,8 @@ function useBattleState(initialUnits, eventConfig = {}, callbacks = {}) {
|
|
|
45407
45666
|
const [turn, setTurn] = useState(1);
|
|
45408
45667
|
const [gameResult, setGameResult] = useState(null);
|
|
45409
45668
|
const checkGameEnd = useCallback((currentUnits) => {
|
|
45410
|
-
const pa = currentUnits.filter((u) => u
|
|
45411
|
-
const ea = currentUnits.filter((u) => u
|
|
45669
|
+
const pa = currentUnits.filter((u) => unitTeam(u) === "player" && unitHealth(u) > 0);
|
|
45670
|
+
const ea = currentUnits.filter((u) => unitTeam(u) === "enemy" && unitHealth(u) > 0);
|
|
45412
45671
|
if (pa.length === 0) {
|
|
45413
45672
|
setGameResult("defeat");
|
|
45414
45673
|
setPhase("game_over");
|
|
@@ -45426,34 +45685,36 @@ function useBattleState(initialUnits, eventConfig = {}, callbacks = {}) {
|
|
|
45426
45685
|
}
|
|
45427
45686
|
}, [onGameEnd, gameEndEvent, eventBus]);
|
|
45428
45687
|
const handleUnitClick = useCallback((unitId) => {
|
|
45429
|
-
const unit = units.find((u) => u.id === unitId);
|
|
45688
|
+
const unit = units.find((u) => str(u.id) === unitId);
|
|
45430
45689
|
if (!unit) return;
|
|
45431
45690
|
if (unitClickEvent) {
|
|
45432
45691
|
eventBus.emit(`UI:${unitClickEvent}`, { unitId });
|
|
45433
45692
|
}
|
|
45434
45693
|
if (phase === "observation" || phase === "selection") {
|
|
45435
|
-
if (unit
|
|
45694
|
+
if (unitTeam(unit) === "player") {
|
|
45436
45695
|
setSelectedUnitId(unitId);
|
|
45437
45696
|
setPhase("movement");
|
|
45438
45697
|
}
|
|
45439
45698
|
} else if (phase === "action") {
|
|
45440
|
-
const selectedUnit = units.find((u) => u.id === selectedUnitId);
|
|
45699
|
+
const selectedUnit = units.find((u) => str(u.id) === selectedUnitId);
|
|
45441
45700
|
if (!selectedUnit) return;
|
|
45442
|
-
if (unit
|
|
45443
|
-
const
|
|
45444
|
-
const
|
|
45701
|
+
if (unitTeam(unit) === "enemy") {
|
|
45702
|
+
const up = unitPosition(unit);
|
|
45703
|
+
const sp = unitPosition(selectedUnit);
|
|
45704
|
+
const dx = Math.abs(up.x - sp.x);
|
|
45705
|
+
const dy = Math.abs(up.y - sp.y);
|
|
45445
45706
|
if (dx <= 1 && dy <= 1 && dx + dy > 0) {
|
|
45446
|
-
const damage = calculateDamage ? calculateDamage(selectedUnit, unit) : Math.max(1, selectedUnit.attack - unit.defense);
|
|
45447
|
-
const newHealth = Math.max(0, unit
|
|
45707
|
+
const damage = calculateDamage ? calculateDamage(selectedUnit, unit) : Math.max(1, num(selectedUnit.attack) - num(unit.defense));
|
|
45708
|
+
const newHealth = Math.max(0, unitHealth(unit) - damage);
|
|
45448
45709
|
const updatedUnits = units.map(
|
|
45449
|
-
(u) => u.id === unit.id ? { ...u, health: newHealth } : u
|
|
45710
|
+
(u) => str(u.id) === str(unit.id) ? { ...u, health: newHealth } : u
|
|
45450
45711
|
);
|
|
45451
45712
|
setUnits(updatedUnits);
|
|
45452
45713
|
onAttack?.(selectedUnit, unit, damage);
|
|
45453
45714
|
if (attackEvent) {
|
|
45454
45715
|
eventBus.emit(`UI:${attackEvent}`, {
|
|
45455
|
-
attackerId: selectedUnit.id,
|
|
45456
|
-
targetId: unit.id,
|
|
45716
|
+
attackerId: str(selectedUnit.id),
|
|
45717
|
+
targetId: str(unit.id),
|
|
45457
45718
|
damage
|
|
45458
45719
|
});
|
|
45459
45720
|
}
|
|
@@ -45470,16 +45731,20 @@ function useBattleState(initialUnits, eventConfig = {}, callbacks = {}) {
|
|
|
45470
45731
|
eventBus.emit(`UI:${tileClickEvent}`, { x, y });
|
|
45471
45732
|
}
|
|
45472
45733
|
if (phase === "movement" && selectedUnitId) {
|
|
45473
|
-
const selectedUnit = units.find((u) => u.id === selectedUnitId);
|
|
45734
|
+
const selectedUnit = units.find((u) => str(u.id) === selectedUnitId);
|
|
45474
45735
|
if (!selectedUnit) return;
|
|
45475
|
-
const
|
|
45476
|
-
const
|
|
45736
|
+
const sp = unitPosition(selectedUnit);
|
|
45737
|
+
const dx = Math.abs(x - sp.x);
|
|
45738
|
+
const dy = Math.abs(y - sp.y);
|
|
45477
45739
|
const dist = dx + dy;
|
|
45478
|
-
if (dist > 0 && dist <= selectedUnit.movement) {
|
|
45479
|
-
if (!units.some((u) =>
|
|
45740
|
+
if (dist > 0 && dist <= num(selectedUnit.movement)) {
|
|
45741
|
+
if (!units.some((u) => {
|
|
45742
|
+
const p2 = unitPosition(u);
|
|
45743
|
+
return p2.x === x && p2.y === y && unitHealth(u) > 0;
|
|
45744
|
+
})) {
|
|
45480
45745
|
setUnits(
|
|
45481
45746
|
(prev) => prev.map(
|
|
45482
|
-
(u) => u.id === selectedUnitId ? { ...u, position: { x, y } } : u
|
|
45747
|
+
(u) => str(u.id) === selectedUnitId ? { ...u, position: { x, y } } : u
|
|
45483
45748
|
)
|
|
45484
45749
|
);
|
|
45485
45750
|
setPhase("action");
|
|
@@ -45522,12 +45787,13 @@ var init_useBattleState = __esm({
|
|
|
45522
45787
|
"components/game/organisms/hooks/useBattleState.ts"() {
|
|
45523
45788
|
"use client";
|
|
45524
45789
|
init_useEventBus();
|
|
45790
|
+
init_boardEntity();
|
|
45525
45791
|
}
|
|
45526
45792
|
});
|
|
45527
45793
|
function UncontrolledBattleBoard({ entity, ...rest }) {
|
|
45528
|
-
const resolved =
|
|
45794
|
+
const resolved = boardEntity(entity);
|
|
45529
45795
|
const battleState = useBattleState(
|
|
45530
|
-
resolved?.initialUnits
|
|
45796
|
+
rows(resolved?.initialUnits),
|
|
45531
45797
|
{
|
|
45532
45798
|
tileClickEvent: rest.tileClickEvent,
|
|
45533
45799
|
unitClickEvent: rest.unitClickEvent,
|
|
@@ -45563,10 +45829,23 @@ function UncontrolledBattleBoard({ entity, ...rest }) {
|
|
|
45563
45829
|
var init_UncontrolledBattleBoard = __esm({
|
|
45564
45830
|
"components/game/organisms/UncontrolledBattleBoard.tsx"() {
|
|
45565
45831
|
init_BattleBoard();
|
|
45832
|
+
init_boardEntity();
|
|
45566
45833
|
init_useBattleState();
|
|
45567
45834
|
UncontrolledBattleBoard.displayName = "UncontrolledBattleBoard";
|
|
45568
45835
|
}
|
|
45569
45836
|
});
|
|
45837
|
+
function heroPosition(h) {
|
|
45838
|
+
return vec2(h.position);
|
|
45839
|
+
}
|
|
45840
|
+
function heroOwner(h) {
|
|
45841
|
+
return str(h.owner);
|
|
45842
|
+
}
|
|
45843
|
+
function heroMovement(h) {
|
|
45844
|
+
return num(h.movement);
|
|
45845
|
+
}
|
|
45846
|
+
function hexPassable(h) {
|
|
45847
|
+
return h.passable !== false;
|
|
45848
|
+
}
|
|
45570
45849
|
function defaultIsInRange(from, to, range) {
|
|
45571
45850
|
return Math.abs(from.x - to.x) + Math.abs(from.y - to.y) <= range;
|
|
45572
45851
|
}
|
|
@@ -45597,36 +45876,36 @@ function WorldMapBoard({
|
|
|
45597
45876
|
className
|
|
45598
45877
|
}) {
|
|
45599
45878
|
const eventBus = useEventBus();
|
|
45600
|
-
const resolved =
|
|
45601
|
-
const hexes = resolved?.hexes
|
|
45602
|
-
const heroes = resolved?.heroes
|
|
45603
|
-
const features = resolved?.features
|
|
45604
|
-
const selectedHeroId = resolved?.selectedHeroId;
|
|
45879
|
+
const resolved = boardEntity(entity);
|
|
45880
|
+
const hexes = rows(resolved?.hexes);
|
|
45881
|
+
const heroes = rows(resolved?.heroes);
|
|
45882
|
+
const features = Array.isArray(resolved?.features) ? resolved.features : [];
|
|
45883
|
+
const selectedHeroId = resolved?.selectedHeroId ?? null;
|
|
45605
45884
|
const assetManifest = resolved?.assetManifest;
|
|
45606
45885
|
const backgroundImage = resolved?.backgroundImage;
|
|
45607
45886
|
const [hoveredTile, setHoveredTile] = useState(null);
|
|
45608
45887
|
const selectedHero = useMemo(
|
|
45609
|
-
() => heroes.find((h) => h.id === selectedHeroId) ?? null,
|
|
45888
|
+
() => heroes.find((h) => str(h.id) === selectedHeroId) ?? null,
|
|
45610
45889
|
[heroes, selectedHeroId]
|
|
45611
45890
|
);
|
|
45612
45891
|
const tiles = useMemo(
|
|
45613
45892
|
() => hexes.map((hex) => ({
|
|
45614
|
-
x: hex.x,
|
|
45615
|
-
y: hex.y,
|
|
45616
|
-
terrain: hex.terrain,
|
|
45617
|
-
terrainSprite: hex.terrainSprite
|
|
45893
|
+
x: num(hex.x),
|
|
45894
|
+
y: num(hex.y),
|
|
45895
|
+
terrain: str(hex.terrain),
|
|
45896
|
+
terrainSprite: hex.terrainSprite == null ? void 0 : str(hex.terrainSprite)
|
|
45618
45897
|
})),
|
|
45619
45898
|
[hexes]
|
|
45620
45899
|
);
|
|
45621
45900
|
const baseUnits = useMemo(
|
|
45622
45901
|
() => heroes.map((hero) => ({
|
|
45623
|
-
id: hero.id,
|
|
45624
|
-
position: hero
|
|
45625
|
-
name: hero.name,
|
|
45626
|
-
team: hero
|
|
45902
|
+
id: str(hero.id),
|
|
45903
|
+
position: heroPosition(hero),
|
|
45904
|
+
name: str(hero.name),
|
|
45905
|
+
team: heroOwner(hero) === "enemy" ? "enemy" : "player",
|
|
45627
45906
|
health: 100,
|
|
45628
45907
|
maxHealth: 100,
|
|
45629
|
-
sprite: hero.sprite
|
|
45908
|
+
sprite: hero.sprite == null ? void 0 : str(hero.sprite)
|
|
45630
45909
|
})),
|
|
45631
45910
|
[heroes]
|
|
45632
45911
|
);
|
|
@@ -45667,73 +45946,94 @@ function WorldMapBoard({
|
|
|
45667
45946
|
const isoUnits = useMemo(() => {
|
|
45668
45947
|
if (movingPositions.size === 0) return baseUnits;
|
|
45669
45948
|
return baseUnits.map((u) => {
|
|
45670
|
-
const pos = movingPositions.get(u.id);
|
|
45949
|
+
const pos = u.id == null ? void 0 : movingPositions.get(u.id);
|
|
45671
45950
|
return pos ? { ...u, position: pos } : u;
|
|
45672
45951
|
});
|
|
45673
45952
|
}, [baseUnits, movingPositions]);
|
|
45674
45953
|
const validMoves = useMemo(() => {
|
|
45675
|
-
if (!selectedHero || selectedHero
|
|
45954
|
+
if (!selectedHero || heroMovement(selectedHero) <= 0) return [];
|
|
45955
|
+
const sp = heroPosition(selectedHero);
|
|
45956
|
+
const sOwner = heroOwner(selectedHero);
|
|
45957
|
+
const range = heroMovement(selectedHero);
|
|
45676
45958
|
const moves = [];
|
|
45677
45959
|
hexes.forEach((hex) => {
|
|
45678
|
-
|
|
45679
|
-
|
|
45680
|
-
if (!
|
|
45681
|
-
if (
|
|
45682
|
-
|
|
45960
|
+
const hx = num(hex.x);
|
|
45961
|
+
const hy = num(hex.y);
|
|
45962
|
+
if (!hexPassable(hex)) return;
|
|
45963
|
+
if (hx === sp.x && hy === sp.y) return;
|
|
45964
|
+
if (!isInRange(sp, { x: hx, y: hy }, range)) return;
|
|
45965
|
+
if (heroes.some((h) => {
|
|
45966
|
+
const hp = heroPosition(h);
|
|
45967
|
+
return hp.x === hx && hp.y === hy && heroOwner(h) === sOwner;
|
|
45968
|
+
})) return;
|
|
45969
|
+
moves.push({ x: hx, y: hy });
|
|
45683
45970
|
});
|
|
45684
45971
|
return moves;
|
|
45685
45972
|
}, [selectedHero, hexes, heroes, isInRange]);
|
|
45686
45973
|
const attackTargets = useMemo(() => {
|
|
45687
|
-
if (!selectedHero || selectedHero
|
|
45688
|
-
|
|
45974
|
+
if (!selectedHero || heroMovement(selectedHero) <= 0) return [];
|
|
45975
|
+
const sp = heroPosition(selectedHero);
|
|
45976
|
+
const sOwner = heroOwner(selectedHero);
|
|
45977
|
+
const range = heroMovement(selectedHero);
|
|
45978
|
+
return heroes.filter((h) => heroOwner(h) !== sOwner).filter((h) => isInRange(sp, heroPosition(h), range)).map((h) => heroPosition(h));
|
|
45689
45979
|
}, [selectedHero, heroes, isInRange]);
|
|
45690
|
-
const maxY = Math.max(...hexes.map((h) => h.y), 0);
|
|
45980
|
+
const maxY = Math.max(...hexes.map((h) => num(h.y)), 0);
|
|
45691
45981
|
const baseOffsetX = (maxY + 1) * (TILE_WIDTH * scale / 2);
|
|
45692
45982
|
const tileToScreen = useCallback(
|
|
45693
45983
|
(tx, ty) => isoToScreen(tx, ty, scale, baseOffsetX),
|
|
45694
45984
|
[scale, baseOffsetX]
|
|
45695
45985
|
);
|
|
45696
45986
|
const hoveredHex = useMemo(
|
|
45697
|
-
() => hoveredTile ? hexes.find((h) => h.x === hoveredTile.x && h.y === hoveredTile.y) ?? null : null,
|
|
45987
|
+
() => hoveredTile ? hexes.find((h) => num(h.x) === hoveredTile.x && num(h.y) === hoveredTile.y) ?? null : null,
|
|
45698
45988
|
[hoveredTile, hexes]
|
|
45699
45989
|
);
|
|
45700
45990
|
const hoveredHero = useMemo(
|
|
45701
|
-
() => hoveredTile ? heroes.find((h) =>
|
|
45991
|
+
() => hoveredTile ? heroes.find((h) => {
|
|
45992
|
+
const hp = heroPosition(h);
|
|
45993
|
+
return hp.x === hoveredTile.x && hp.y === hoveredTile.y;
|
|
45994
|
+
}) ?? null : null,
|
|
45702
45995
|
[hoveredTile, heroes]
|
|
45703
45996
|
);
|
|
45704
45997
|
const handleTileClick = useCallback((x, y) => {
|
|
45705
45998
|
if (movementAnimRef.current) return;
|
|
45706
|
-
const hex = hexes.find((h) => h.x === x && h.y === y);
|
|
45999
|
+
const hex = hexes.find((h) => num(h.x) === x && num(h.y) === y);
|
|
45707
46000
|
if (!hex) return;
|
|
45708
46001
|
if (tileClickEvent) {
|
|
45709
46002
|
eventBus.emit(`UI:${tileClickEvent}`, { x, y });
|
|
45710
46003
|
}
|
|
45711
46004
|
if (selectedHero && validMoves.some((m) => m.x === x && m.y === y)) {
|
|
45712
|
-
|
|
45713
|
-
|
|
46005
|
+
const heroId = str(selectedHero.id);
|
|
46006
|
+
startMoveAnimation(heroId, { ...heroPosition(selectedHero) }, { x, y }, () => {
|
|
46007
|
+
onHeroMove?.(heroId, x, y);
|
|
45714
46008
|
if (heroMoveEvent) {
|
|
45715
|
-
eventBus.emit(`UI:${heroMoveEvent}`, { heroId
|
|
46009
|
+
eventBus.emit(`UI:${heroMoveEvent}`, { heroId, toX: x, toY: y });
|
|
45716
46010
|
}
|
|
45717
|
-
|
|
45718
|
-
|
|
46011
|
+
const feature = str(hex.feature);
|
|
46012
|
+
if (feature && feature !== "none") {
|
|
46013
|
+
onFeatureEnter?.(heroId, hex);
|
|
45719
46014
|
if (featureEnterEvent) {
|
|
45720
|
-
eventBus.emit(`UI:${featureEnterEvent}`, { heroId
|
|
46015
|
+
eventBus.emit(`UI:${featureEnterEvent}`, { heroId, feature, hex });
|
|
45721
46016
|
}
|
|
45722
46017
|
}
|
|
45723
46018
|
});
|
|
45724
46019
|
return;
|
|
45725
46020
|
}
|
|
45726
|
-
const enemy = heroes.find((h) =>
|
|
46021
|
+
const enemy = heroes.find((h) => {
|
|
46022
|
+
const hp = heroPosition(h);
|
|
46023
|
+
return hp.x === x && hp.y === y && heroOwner(h) === "enemy";
|
|
46024
|
+
});
|
|
45727
46025
|
if (selectedHero && enemy && attackTargets.some((t) => t.x === x && t.y === y)) {
|
|
45728
|
-
|
|
46026
|
+
const attackerId = str(selectedHero.id);
|
|
46027
|
+
const defenderId = str(enemy.id);
|
|
46028
|
+
onBattleEncounter?.(attackerId, defenderId);
|
|
45729
46029
|
if (battleEncounterEvent) {
|
|
45730
|
-
eventBus.emit(`UI:${battleEncounterEvent}`, { attackerId
|
|
46030
|
+
eventBus.emit(`UI:${battleEncounterEvent}`, { attackerId, defenderId });
|
|
45731
46031
|
}
|
|
45732
46032
|
}
|
|
45733
46033
|
}, [hexes, heroes, selectedHero, validMoves, attackTargets, startMoveAnimation, onHeroMove, onFeatureEnter, onBattleEncounter, eventBus, tileClickEvent, heroMoveEvent, featureEnterEvent, battleEncounterEvent]);
|
|
45734
46034
|
const handleUnitClick = useCallback((unitId) => {
|
|
45735
|
-
const hero = heroes.find((h) => h.id === unitId);
|
|
45736
|
-
if (hero && (hero
|
|
46035
|
+
const hero = heroes.find((h) => str(h.id) === unitId);
|
|
46036
|
+
if (hero && (heroOwner(hero) === "player" || allowMoveAllHeroes)) {
|
|
45737
46037
|
onHeroSelect?.(unitId);
|
|
45738
46038
|
if (heroSelectEvent) {
|
|
45739
46039
|
eventBus.emit(`UI:${heroSelectEvent}`, { heroId: unitId });
|
|
@@ -45806,6 +46106,7 @@ var init_WorldMapBoard = __esm({
|
|
|
45806
46106
|
init_Stack();
|
|
45807
46107
|
init_LoadingState();
|
|
45808
46108
|
init_IsometricCanvas2();
|
|
46109
|
+
init_boardEntity();
|
|
45809
46110
|
init_isometric();
|
|
45810
46111
|
WorldMapBoard.displayName = "WorldMapBoard";
|
|
45811
46112
|
}
|
|
@@ -49034,11 +49335,11 @@ function buildMockData(schema) {
|
|
|
49034
49335
|
result[entityName] = entity.instances;
|
|
49035
49336
|
continue;
|
|
49036
49337
|
}
|
|
49037
|
-
const
|
|
49338
|
+
const rows2 = Array.from(
|
|
49038
49339
|
{ length: 10 },
|
|
49039
49340
|
(_, i) => generateEntityRow(entity, i + 1)
|
|
49040
49341
|
);
|
|
49041
|
-
result[entityName] =
|
|
49342
|
+
result[entityName] = rows2;
|
|
49042
49343
|
}
|
|
49043
49344
|
for (const orbital of schema.orbitals) {
|
|
49044
49345
|
for (const traitRef of orbital.traits ?? []) {
|