@almadar/ui 5.21.12 → 5.22.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/avl/index.cjs +919 -631
- package/dist/avl/index.js +919 -631
- package/dist/components/core/molecules/CalendarGrid.d.ts +3 -10
- package/dist/components/core/molecules/ContentRenderer.d.ts +2 -2
- package/dist/components/core/molecules/DataGrid.d.ts +11 -20
- package/dist/components/core/molecules/DataList.d.ts +9 -15
- package/dist/components/core/molecules/FormSection.d.ts +4 -4
- package/dist/components/core/molecules/PositionedCanvas.d.ts +4 -17
- package/dist/components/core/molecules/ReplyTree.d.ts +2 -13
- package/dist/components/core/molecules/RichBlockEditor.d.ts +3 -6
- package/dist/components/core/molecules/SortableList.d.ts +7 -5
- package/dist/components/core/molecules/TableView.d.ts +7 -7
- package/dist/components/core/molecules/index.d.ts +3 -3
- package/dist/components/core/molecules/useDataDnd.d.ts +5 -5
- package/dist/components/core/organisms/CardGrid.d.ts +5 -2
- package/dist/components/core/organisms/CaseStudyOrganism.d.ts +4 -3
- package/dist/components/core/organisms/DataTable.d.ts +4 -2
- package/dist/components/core/organisms/DetailPanel.d.ts +6 -6
- package/dist/components/core/organisms/FeatureGridOrganism.d.ts +4 -3
- package/dist/components/core/organisms/HeroOrganism.d.ts +4 -5
- package/dist/components/core/organisms/List.d.ts +5 -2
- package/dist/components/core/organisms/MasterDetail.d.ts +4 -2
- package/dist/components/core/organisms/MediaGallery.d.ts +4 -2
- package/dist/components/core/organisms/ShowcaseOrganism.d.ts +4 -3
- package/dist/components/core/organisms/StatCard.d.ts +5 -2
- package/dist/components/core/organisms/StepFlowOrganism.d.ts +4 -3
- package/dist/components/core/organisms/Timeline.d.ts +2 -2
- package/dist/components/core/organisms/book/index.d.ts +1 -1
- package/dist/components/core/organisms/book/types.d.ts +28 -48
- package/dist/components/core/organisms/index.d.ts +1 -2
- package/dist/components/core/organisms/layout/DashboardGrid.d.ts +2 -2
- package/dist/components/core/organisms/marketing-types.d.ts +5 -94
- package/dist/components/core/organisms/types.d.ts +9 -27
- package/dist/components/core/templates/index.d.ts +6 -6
- package/dist/components/game/organisms/BattleBoard.d.ts +14 -90
- package/dist/components/game/organisms/CastleBoard.d.ts +7 -21
- package/dist/components/game/organisms/UncontrolledBattleBoard.d.ts +2 -7
- package/dist/components/game/organisms/WorldMapBoard.d.ts +13 -59
- package/dist/components/game/organisms/boardEntity.d.ts +44 -0
- package/dist/components/game/organisms/hooks/useBattleState.d.ts +7 -7
- package/dist/components/game/organisms/index.d.ts +3 -3
- package/dist/components/game/organisms/puzzles/builder/BuilderBoard.d.ts +7 -20
- package/dist/components/game/organisms/puzzles/builder/index.d.ts +1 -1
- package/dist/components/game/organisms/puzzles/classifier/ClassifierBoard.d.ts +7 -20
- package/dist/components/game/organisms/puzzles/classifier/index.d.ts +1 -1
- package/dist/components/game/organisms/puzzles/debugger/DebuggerBoard.d.ts +6 -22
- package/dist/components/game/organisms/puzzles/debugger/index.d.ts +1 -1
- package/dist/components/game/organisms/puzzles/event-handler/EventHandlerBoard.d.ts +6 -33
- package/dist/components/game/organisms/puzzles/event-handler/ObjectRulePanel.d.ts +3 -21
- package/dist/components/game/organisms/puzzles/event-handler/index.d.ts +2 -2
- package/dist/components/game/organisms/puzzles/event-handler/puzzleObject.d.ts +21 -0
- package/dist/components/game/organisms/puzzles/negotiator/NegotiatorBoard.d.ts +8 -24
- package/dist/components/game/organisms/puzzles/negotiator/index.d.ts +1 -1
- package/dist/components/game/organisms/puzzles/sequencer/ActionTile.d.ts +2 -2
- package/dist/components/game/organisms/puzzles/sequencer/SequencerBoard.d.ts +7 -36
- package/dist/components/game/organisms/puzzles/sequencer/index.d.ts +1 -1
- package/dist/components/game/organisms/puzzles/simulator/SimulatorBoard.d.ts +6 -25
- package/dist/components/game/organisms/puzzles/simulator/index.d.ts +1 -1
- package/dist/components/game/organisms/puzzles/state-architect/StateArchitectBoard.d.ts +7 -40
- package/dist/components/game/organisms/puzzles/state-architect/VariablePanel.d.ts +3 -9
- package/dist/components/game/organisms/puzzles/state-architect/index.d.ts +2 -2
- package/dist/components/game/organisms/three/index.cjs +35 -21
- package/dist/components/game/organisms/three/index.js +35 -21
- package/dist/components/game/templates/BattleTemplate.d.ts +2 -3
- package/dist/components/game/templates/CastleTemplate.d.ts +2 -3
- package/dist/components/game/templates/GameCanvas3DBattleTemplate.d.ts +1 -16
- package/dist/components/game/templates/GameCanvas3DCastleTemplate.d.ts +1 -18
- package/dist/components/game/templates/GameCanvas3DWorldMapTemplate.d.ts +1 -14
- package/dist/components/game/templates/GameTemplate.d.ts +1 -6
- package/dist/components/game/templates/WorldMapTemplate.d.ts +2 -3
- package/dist/components/index.cjs +2016 -1668
- package/dist/components/index.js +1128 -780
- package/dist/components/marketing/organisms/PricingOrganism.d.ts +4 -3
- package/dist/components/marketing/organisms/StatsOrganism.d.ts +4 -3
- package/dist/components/marketing/organisms/TeamOrganism.d.ts +4 -3
- package/dist/components/marketing/organisms/book/BookChapterView.d.ts +5 -2
- package/dist/components/marketing/organisms/book/BookTableOfContents.d.ts +3 -2
- package/dist/components/marketing/organisms/book/BookViewer.d.ts +4 -4
- package/dist/components/marketing/templates/AboutPageTemplate.d.ts +32 -6
- package/dist/components/marketing/templates/FeatureDetailPageTemplate.d.ts +14 -4
- package/dist/components/marketing/templates/LandingPageTemplate.d.ts +47 -9
- package/dist/components/marketing/templates/PricingPageTemplate.d.ts +23 -5
- package/dist/providers/index.cjs +912 -624
- package/dist/providers/index.js +912 -624
- package/dist/runtime/index.cjs +914 -626
- package/dist/runtime/index.js +914 -626
- package/package.json +2 -2
package/dist/avl/index.js
CHANGED
|
@@ -7130,7 +7130,7 @@ var init_SvgGrid = __esm({
|
|
|
7130
7130
|
x,
|
|
7131
7131
|
y,
|
|
7132
7132
|
cols = 4,
|
|
7133
|
-
rows = 3,
|
|
7133
|
+
rows: rows2 = 3,
|
|
7134
7134
|
spacing = 20,
|
|
7135
7135
|
nodeRadius = 3,
|
|
7136
7136
|
color = "var(--color-primary)",
|
|
@@ -7139,7 +7139,7 @@ var init_SvgGrid = __esm({
|
|
|
7139
7139
|
highlights = []
|
|
7140
7140
|
}) => {
|
|
7141
7141
|
const highlightSet = new Set(highlights);
|
|
7142
|
-
return /* @__PURE__ */ jsx("g", { className, opacity, children: Array.from({ length:
|
|
7142
|
+
return /* @__PURE__ */ jsx("g", { className, opacity, children: Array.from({ length: rows2 }).map(
|
|
7143
7143
|
(_, row) => Array.from({ length: cols }).map((_2, col) => {
|
|
7144
7144
|
const index = row * cols + col;
|
|
7145
7145
|
const isHighlighted = highlightSet.has(index);
|
|
@@ -7799,7 +7799,7 @@ var init_Input = __esm({
|
|
|
7799
7799
|
onClear,
|
|
7800
7800
|
value,
|
|
7801
7801
|
options,
|
|
7802
|
-
rows = 3,
|
|
7802
|
+
rows: rows2 = 3,
|
|
7803
7803
|
onChange,
|
|
7804
7804
|
...props
|
|
7805
7805
|
}, ref) => {
|
|
@@ -7849,7 +7849,7 @@ var init_Input = __esm({
|
|
|
7849
7849
|
ref,
|
|
7850
7850
|
value,
|
|
7851
7851
|
onChange,
|
|
7852
|
-
rows,
|
|
7852
|
+
rows: rows2,
|
|
7853
7853
|
className: baseClassName,
|
|
7854
7854
|
...props
|
|
7855
7855
|
}
|
|
@@ -9844,66 +9844,6 @@ var init_RangeSlider = __esm({
|
|
|
9844
9844
|
RangeSlider.displayName = "RangeSlider";
|
|
9845
9845
|
}
|
|
9846
9846
|
});
|
|
9847
|
-
function easeOut(t) {
|
|
9848
|
-
return t * (2 - t);
|
|
9849
|
-
}
|
|
9850
|
-
var AnimatedCounter;
|
|
9851
|
-
var init_AnimatedCounter = __esm({
|
|
9852
|
-
"components/marketing/atoms/AnimatedCounter.tsx"() {
|
|
9853
|
-
"use client";
|
|
9854
|
-
init_cn();
|
|
9855
|
-
init_Typography();
|
|
9856
|
-
AnimatedCounter = ({
|
|
9857
|
-
value: rawValue,
|
|
9858
|
-
duration = 600,
|
|
9859
|
-
prefix,
|
|
9860
|
-
suffix,
|
|
9861
|
-
className
|
|
9862
|
-
}) => {
|
|
9863
|
-
const numericRaw = typeof rawValue === "number" ? rawValue : Number.parseFloat(String(rawValue ?? ""));
|
|
9864
|
-
const value = !Number.isNaN(numericRaw) ? numericRaw : 0;
|
|
9865
|
-
const [displayValue, setDisplayValue] = useState(value);
|
|
9866
|
-
const previousValueRef = useRef(value);
|
|
9867
|
-
const animationFrameRef = useRef(null);
|
|
9868
|
-
useEffect(() => {
|
|
9869
|
-
const from = previousValueRef.current;
|
|
9870
|
-
const to = value;
|
|
9871
|
-
previousValueRef.current = value;
|
|
9872
|
-
if (from === to) {
|
|
9873
|
-
setDisplayValue(to);
|
|
9874
|
-
return;
|
|
9875
|
-
}
|
|
9876
|
-
const startTime = performance.now();
|
|
9877
|
-
const diff = to - from;
|
|
9878
|
-
function animate(currentTime) {
|
|
9879
|
-
const elapsed = currentTime - startTime;
|
|
9880
|
-
const progress = Math.min(elapsed / duration, 1);
|
|
9881
|
-
const easedProgress = easeOut(progress);
|
|
9882
|
-
setDisplayValue(from + diff * easedProgress);
|
|
9883
|
-
if (progress < 1) {
|
|
9884
|
-
animationFrameRef.current = requestAnimationFrame(animate);
|
|
9885
|
-
} else {
|
|
9886
|
-
setDisplayValue(to);
|
|
9887
|
-
}
|
|
9888
|
-
}
|
|
9889
|
-
animationFrameRef.current = requestAnimationFrame(animate);
|
|
9890
|
-
return () => {
|
|
9891
|
-
if (animationFrameRef.current !== null) {
|
|
9892
|
-
cancelAnimationFrame(animationFrameRef.current);
|
|
9893
|
-
}
|
|
9894
|
-
};
|
|
9895
|
-
}, [value, duration]);
|
|
9896
|
-
const decimalPlaces = Number.isInteger(value) ? 0 : String(value).split(".")[1]?.length ?? 0;
|
|
9897
|
-
const formattedValue = displayValue.toFixed(decimalPlaces);
|
|
9898
|
-
return /* @__PURE__ */ jsxs(Typography, { variant: "h3", className: cn("tabular-nums", className), children: [
|
|
9899
|
-
prefix,
|
|
9900
|
-
formattedValue,
|
|
9901
|
-
suffix
|
|
9902
|
-
] });
|
|
9903
|
-
};
|
|
9904
|
-
AnimatedCounter.displayName = "AnimatedCounter";
|
|
9905
|
-
}
|
|
9906
|
-
});
|
|
9907
9847
|
function useInfiniteScroll(onLoadMore, options = {}) {
|
|
9908
9848
|
const { rootMargin = "200px", hasMore = true, isLoading = false } = options;
|
|
9909
9849
|
const observerRef = useRef(null);
|
|
@@ -12387,15 +12327,15 @@ function HeaderSkeleton({ className }) {
|
|
|
12387
12327
|
] })
|
|
12388
12328
|
] });
|
|
12389
12329
|
}
|
|
12390
|
-
function TableSkeleton({ rows = 5, columns = 4, className }) {
|
|
12330
|
+
function TableSkeleton({ rows: rows2 = 5, columns = 4, className }) {
|
|
12391
12331
|
return /* @__PURE__ */ jsxs(VStack, { gap: "none", className: cn("border border-border rounded-lg overflow-hidden", className), children: [
|
|
12392
12332
|
/* @__PURE__ */ jsx(HStack, { className: "px-4 py-3 bg-muted/30 border-b border-border", children: Array.from({ length: columns }).map((_, i) => /* @__PURE__ */ jsx(SkeletonBlock, { className: "h-4 flex-1 mx-2" }, i)) }),
|
|
12393
|
-
Array.from({ length:
|
|
12333
|
+
Array.from({ length: rows2 }).map((_, rowIdx) => /* @__PURE__ */ jsx(
|
|
12394
12334
|
HStack,
|
|
12395
12335
|
{
|
|
12396
12336
|
className: cn(
|
|
12397
12337
|
"px-4 py-3",
|
|
12398
|
-
rowIdx <
|
|
12338
|
+
rowIdx < rows2 - 1 && "border-b border-border"
|
|
12399
12339
|
),
|
|
12400
12340
|
children: Array.from({ length: columns }).map((_2, colIdx) => /* @__PURE__ */ jsx(SkeletonLine, { className: "flex-1 mx-2" }, colIdx))
|
|
12401
12341
|
},
|
|
@@ -12443,18 +12383,18 @@ function CardSkeleton({ className }) {
|
|
|
12443
12383
|
}
|
|
12444
12384
|
);
|
|
12445
12385
|
}
|
|
12446
|
-
function TextSkeleton({ rows = 3, className }) {
|
|
12447
|
-
return /* @__PURE__ */ jsx(VStack, { gap: "sm", className, children: Array.from({ length:
|
|
12386
|
+
function TextSkeleton({ rows: rows2 = 3, className }) {
|
|
12387
|
+
return /* @__PURE__ */ jsx(VStack, { gap: "sm", className, children: Array.from({ length: rows2 }).map((_, i) => /* @__PURE__ */ jsx(
|
|
12448
12388
|
SkeletonLine,
|
|
12449
12389
|
{
|
|
12450
|
-
className: i ===
|
|
12390
|
+
className: i === rows2 - 1 ? "w-2/3" : "w-full"
|
|
12451
12391
|
},
|
|
12452
12392
|
i
|
|
12453
12393
|
)) });
|
|
12454
12394
|
}
|
|
12455
12395
|
function Skeleton({
|
|
12456
12396
|
variant = "text",
|
|
12457
|
-
rows,
|
|
12397
|
+
rows: rows2,
|
|
12458
12398
|
columns,
|
|
12459
12399
|
fields,
|
|
12460
12400
|
className
|
|
@@ -12464,15 +12404,15 @@ function Skeleton({
|
|
|
12464
12404
|
case "header":
|
|
12465
12405
|
return /* @__PURE__ */ jsx(HeaderSkeleton, { className });
|
|
12466
12406
|
case "table":
|
|
12467
|
-
return /* @__PURE__ */ jsx(TableSkeleton, { rows, columns, className });
|
|
12407
|
+
return /* @__PURE__ */ jsx(TableSkeleton, { rows: rows2, columns, className });
|
|
12468
12408
|
case "form":
|
|
12469
12409
|
return /* @__PURE__ */ jsx(FormSkeleton, { fields, className });
|
|
12470
12410
|
case "card":
|
|
12471
12411
|
return /* @__PURE__ */ jsx(CardSkeleton, { className });
|
|
12472
12412
|
case "text":
|
|
12473
|
-
return /* @__PURE__ */ jsx(TextSkeleton, { rows, className });
|
|
12413
|
+
return /* @__PURE__ */ jsx(TextSkeleton, { rows: rows2, className });
|
|
12474
12414
|
default:
|
|
12475
|
-
return /* @__PURE__ */ jsx(TextSkeleton, { rows, className });
|
|
12415
|
+
return /* @__PURE__ */ jsx(TextSkeleton, { rows: rows2, className });
|
|
12476
12416
|
}
|
|
12477
12417
|
}
|
|
12478
12418
|
var pulseClass;
|
|
@@ -14100,7 +14040,7 @@ var init_MapView = __esm({
|
|
|
14100
14040
|
shadowSize: [41, 41]
|
|
14101
14041
|
});
|
|
14102
14042
|
L.Marker.prototype.options.icon = defaultIcon;
|
|
14103
|
-
const { useEffect: useEffect79, useRef: useRef71, useCallback:
|
|
14043
|
+
const { useEffect: useEffect79, useRef: useRef71, useCallback: useCallback123, useState: useState113 } = React97__default;
|
|
14104
14044
|
const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
|
|
14105
14045
|
const { useEventBus: useEventBus3 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
|
|
14106
14046
|
function MapUpdater({ centerLat, centerLng, zoom }) {
|
|
@@ -14146,7 +14086,7 @@ var init_MapView = __esm({
|
|
|
14146
14086
|
}) {
|
|
14147
14087
|
const eventBus = useEventBus3();
|
|
14148
14088
|
const [clickedPosition, setClickedPosition] = useState113(null);
|
|
14149
|
-
const handleMapClick =
|
|
14089
|
+
const handleMapClick = useCallback123((lat, lng) => {
|
|
14150
14090
|
if (showClickedPin) {
|
|
14151
14091
|
setClickedPosition({ lat, lng });
|
|
14152
14092
|
}
|
|
@@ -14155,7 +14095,7 @@ var init_MapView = __esm({
|
|
|
14155
14095
|
eventBus.emit(`UI:${mapClickEvent}`, { latitude: lat, longitude: lng });
|
|
14156
14096
|
}
|
|
14157
14097
|
}, [onMapClick, mapClickEvent, eventBus, showClickedPin]);
|
|
14158
|
-
const handleMarkerClick =
|
|
14098
|
+
const handleMarkerClick = useCallback123((marker) => {
|
|
14159
14099
|
onMarkerClick?.(marker);
|
|
14160
14100
|
if (markerClickEvent) {
|
|
14161
14101
|
eventBus.emit(`UI:${markerClickEvent}`, { ...marker });
|
|
@@ -14376,7 +14316,7 @@ function InputPattern({
|
|
|
14376
14316
|
function TextareaPattern({
|
|
14377
14317
|
value = "",
|
|
14378
14318
|
placeholder,
|
|
14379
|
-
rows = 4,
|
|
14319
|
+
rows: rows2 = 4,
|
|
14380
14320
|
disabled = false,
|
|
14381
14321
|
fieldError,
|
|
14382
14322
|
onChange,
|
|
@@ -14396,7 +14336,7 @@ function TextareaPattern({
|
|
|
14396
14336
|
{
|
|
14397
14337
|
value: localValue,
|
|
14398
14338
|
placeholder,
|
|
14399
|
-
rows,
|
|
14339
|
+
rows: rows2,
|
|
14400
14340
|
disabled,
|
|
14401
14341
|
error: fieldError,
|
|
14402
14342
|
onChange: handleChange,
|
|
@@ -14881,6 +14821,91 @@ var init_ActionPalette = __esm({
|
|
|
14881
14821
|
ActionPalette.displayName = "ActionPalette";
|
|
14882
14822
|
}
|
|
14883
14823
|
});
|
|
14824
|
+
function parseValue(value) {
|
|
14825
|
+
if (value === "" || value == null) return { num: 0, prefix: "", suffix: "", decimals: 0 };
|
|
14826
|
+
const match = String(value).match(/^([^0-9]*)([0-9]+(?:\.[0-9]+)?)(.*)$/);
|
|
14827
|
+
if (!match) {
|
|
14828
|
+
return { num: 0, prefix: "", suffix: String(value), decimals: 0 };
|
|
14829
|
+
}
|
|
14830
|
+
const numStr = match[2];
|
|
14831
|
+
const decimalIdx = numStr.indexOf(".");
|
|
14832
|
+
const decimals = decimalIdx >= 0 ? numStr.length - decimalIdx - 1 : 0;
|
|
14833
|
+
return {
|
|
14834
|
+
prefix: match[1],
|
|
14835
|
+
num: parseFloat(numStr),
|
|
14836
|
+
suffix: match[3],
|
|
14837
|
+
decimals
|
|
14838
|
+
};
|
|
14839
|
+
}
|
|
14840
|
+
var AnimatedCounter;
|
|
14841
|
+
var init_AnimatedCounter = __esm({
|
|
14842
|
+
"components/core/molecules/AnimatedCounter.tsx"() {
|
|
14843
|
+
"use client";
|
|
14844
|
+
init_cn();
|
|
14845
|
+
init_Box();
|
|
14846
|
+
init_Typography();
|
|
14847
|
+
AnimatedCounter = ({
|
|
14848
|
+
value,
|
|
14849
|
+
label,
|
|
14850
|
+
duration = 1500,
|
|
14851
|
+
className
|
|
14852
|
+
}) => {
|
|
14853
|
+
const ref = useRef(null);
|
|
14854
|
+
const [displayValue, setDisplayValue] = useState("0");
|
|
14855
|
+
const [hasAnimated, setHasAnimated] = useState(false);
|
|
14856
|
+
const animate = useCallback(() => {
|
|
14857
|
+
const { num: num2, prefix, suffix, decimals } = parseValue(value);
|
|
14858
|
+
if (num2 === 0) {
|
|
14859
|
+
setDisplayValue(String(value));
|
|
14860
|
+
return;
|
|
14861
|
+
}
|
|
14862
|
+
const startTime = performance.now();
|
|
14863
|
+
const tick = (now2) => {
|
|
14864
|
+
const elapsed = now2 - startTime;
|
|
14865
|
+
const progress = Math.min(elapsed / duration, 1);
|
|
14866
|
+
const eased = 1 - Math.pow(1 - progress, 3);
|
|
14867
|
+
const current = eased * num2;
|
|
14868
|
+
setDisplayValue(`${prefix}${current.toFixed(decimals)}${suffix}`);
|
|
14869
|
+
if (progress < 1) {
|
|
14870
|
+
requestAnimationFrame(tick);
|
|
14871
|
+
} else {
|
|
14872
|
+
setDisplayValue(String(value));
|
|
14873
|
+
}
|
|
14874
|
+
};
|
|
14875
|
+
requestAnimationFrame(tick);
|
|
14876
|
+
}, [value, duration]);
|
|
14877
|
+
useEffect(() => {
|
|
14878
|
+
if (hasAnimated) return;
|
|
14879
|
+
const el = ref.current;
|
|
14880
|
+
if (!el) return;
|
|
14881
|
+
const observer2 = new IntersectionObserver(
|
|
14882
|
+
(entries) => {
|
|
14883
|
+
if (entries[0].isIntersecting) {
|
|
14884
|
+
setHasAnimated(true);
|
|
14885
|
+
animate();
|
|
14886
|
+
observer2.disconnect();
|
|
14887
|
+
}
|
|
14888
|
+
},
|
|
14889
|
+
{ threshold: 0.3 }
|
|
14890
|
+
);
|
|
14891
|
+
observer2.observe(el);
|
|
14892
|
+
return () => observer2.disconnect();
|
|
14893
|
+
}, [hasAnimated, animate]);
|
|
14894
|
+
return /* @__PURE__ */ jsxs(Box, { ref, className: cn("flex flex-col items-center gap-1 p-4", className), children: [
|
|
14895
|
+
/* @__PURE__ */ jsx(
|
|
14896
|
+
Typography,
|
|
14897
|
+
{
|
|
14898
|
+
variant: "h2",
|
|
14899
|
+
className: "text-primary font-bold tabular-nums",
|
|
14900
|
+
children: hasAnimated ? displayValue : "0"
|
|
14901
|
+
}
|
|
14902
|
+
),
|
|
14903
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body2", color: "muted", className: "text-center", children: label })
|
|
14904
|
+
] });
|
|
14905
|
+
};
|
|
14906
|
+
AnimatedCounter.displayName = "AnimatedCounter";
|
|
14907
|
+
}
|
|
14908
|
+
});
|
|
14884
14909
|
var AuthLayout;
|
|
14885
14910
|
var init_AuthLayout = __esm({
|
|
14886
14911
|
"components/core/templates/AuthLayout.tsx"() {
|
|
@@ -16266,6 +16291,39 @@ var init_IsometricCanvas2 = __esm({
|
|
|
16266
16291
|
init_IsometricCanvas();
|
|
16267
16292
|
}
|
|
16268
16293
|
});
|
|
16294
|
+
|
|
16295
|
+
// components/game/organisms/boardEntity.ts
|
|
16296
|
+
function boardEntity(entity) {
|
|
16297
|
+
if (!entity) return void 0;
|
|
16298
|
+
return Array.isArray(entity) ? entity[0] : entity;
|
|
16299
|
+
}
|
|
16300
|
+
function str(v) {
|
|
16301
|
+
return v == null ? "" : String(v);
|
|
16302
|
+
}
|
|
16303
|
+
function num(v, fallback = 0) {
|
|
16304
|
+
const n = Number(v);
|
|
16305
|
+
return Number.isFinite(n) ? n : fallback;
|
|
16306
|
+
}
|
|
16307
|
+
function rows(v) {
|
|
16308
|
+
return Array.isArray(v) ? v : [];
|
|
16309
|
+
}
|
|
16310
|
+
function vec2(v) {
|
|
16311
|
+
const o = v ?? {};
|
|
16312
|
+
return { x: num(o.x), y: num(o.y) };
|
|
16313
|
+
}
|
|
16314
|
+
function unitPosition(u) {
|
|
16315
|
+
return vec2(u.position);
|
|
16316
|
+
}
|
|
16317
|
+
function unitTeam(u) {
|
|
16318
|
+
return str(u.team);
|
|
16319
|
+
}
|
|
16320
|
+
function unitHealth(u) {
|
|
16321
|
+
return num(u.health);
|
|
16322
|
+
}
|
|
16323
|
+
var init_boardEntity = __esm({
|
|
16324
|
+
"components/game/organisms/boardEntity.ts"() {
|
|
16325
|
+
}
|
|
16326
|
+
});
|
|
16269
16327
|
function BattleBoard({
|
|
16270
16328
|
entity,
|
|
16271
16329
|
scale = 0.45,
|
|
@@ -16292,43 +16350,49 @@ function BattleBoard({
|
|
|
16292
16350
|
attackEvent,
|
|
16293
16351
|
className
|
|
16294
16352
|
}) {
|
|
16295
|
-
const
|
|
16296
|
-
const
|
|
16297
|
-
const
|
|
16298
|
-
const
|
|
16299
|
-
const
|
|
16300
|
-
const
|
|
16301
|
-
const
|
|
16302
|
-
const
|
|
16303
|
-
const
|
|
16304
|
-
const
|
|
16305
|
-
const
|
|
16353
|
+
const board = boardEntity(entity) ?? {};
|
|
16354
|
+
const tiles = Array.isArray(board.tiles) ? board.tiles : [];
|
|
16355
|
+
const features = Array.isArray(board.features) ? board.features : [];
|
|
16356
|
+
const boardWidth = num(board.boardWidth, 8);
|
|
16357
|
+
const boardHeight = num(board.boardHeight, 6);
|
|
16358
|
+
const assetManifest = board.assetManifest;
|
|
16359
|
+
const backgroundImage = board.backgroundImage;
|
|
16360
|
+
const units = rows(board.units);
|
|
16361
|
+
const selectedUnitId = board.selectedUnitId ?? null;
|
|
16362
|
+
const currentPhase = str(board.phase) || "observation";
|
|
16363
|
+
const currentTurn = num(board.turn, 1);
|
|
16364
|
+
const gameResult = board.gameResult ?? null;
|
|
16306
16365
|
const eventBus = useEventBus();
|
|
16307
16366
|
const { t } = useTranslate();
|
|
16308
16367
|
const [hoveredTile, setHoveredTile] = useState(null);
|
|
16309
16368
|
const [isShaking, setIsShaking] = useState(false);
|
|
16310
16369
|
const selectedUnit = useMemo(
|
|
16311
|
-
() => units.find((u) => u.id === selectedUnitId) ?? null,
|
|
16370
|
+
() => units.find((u) => str(u.id) === selectedUnitId) ?? null,
|
|
16312
16371
|
[units, selectedUnitId]
|
|
16313
16372
|
);
|
|
16314
16373
|
const hoveredUnit = useMemo(() => {
|
|
16315
16374
|
if (!hoveredTile) return null;
|
|
16316
|
-
return units.find(
|
|
16317
|
-
|
|
16318
|
-
|
|
16375
|
+
return units.find((u) => {
|
|
16376
|
+
const p2 = unitPosition(u);
|
|
16377
|
+
return p2.x === hoveredTile.x && p2.y === hoveredTile.y && unitHealth(u) > 0;
|
|
16378
|
+
}) ?? null;
|
|
16319
16379
|
}, [hoveredTile, units]);
|
|
16320
|
-
const playerUnits = useMemo(() => units.filter((u) => u
|
|
16321
|
-
const enemyUnits = useMemo(() => units.filter((u) => u
|
|
16380
|
+
const playerUnits = useMemo(() => units.filter((u) => unitTeam(u) === "player" && unitHealth(u) > 0), [units]);
|
|
16381
|
+
const enemyUnits = useMemo(() => units.filter((u) => unitTeam(u) === "enemy" && unitHealth(u) > 0), [units]);
|
|
16322
16382
|
const validMoves = useMemo(() => {
|
|
16323
16383
|
if (!selectedUnit || currentPhase !== "movement") return [];
|
|
16324
16384
|
const moves = [];
|
|
16325
|
-
const range = selectedUnit.movement;
|
|
16385
|
+
const range = num(selectedUnit.movement);
|
|
16386
|
+
const origin = unitPosition(selectedUnit);
|
|
16326
16387
|
for (let dy = -range; dy <= range; dy++) {
|
|
16327
16388
|
for (let dx = -range; dx <= range; dx++) {
|
|
16328
|
-
const nx =
|
|
16329
|
-
const ny =
|
|
16389
|
+
const nx = origin.x + dx;
|
|
16390
|
+
const ny = origin.y + dy;
|
|
16330
16391
|
const dist = Math.abs(dx) + Math.abs(dy);
|
|
16331
|
-
if (dist > 0 && dist <= range && nx >= 0 && nx < boardWidth && ny >= 0 && ny < boardHeight && !units.some((u) =>
|
|
16392
|
+
if (dist > 0 && dist <= range && nx >= 0 && nx < boardWidth && ny >= 0 && ny < boardHeight && !units.some((u) => {
|
|
16393
|
+
const p2 = unitPosition(u);
|
|
16394
|
+
return p2.x === nx && p2.y === ny && unitHealth(u) > 0;
|
|
16395
|
+
})) {
|
|
16332
16396
|
moves.push({ x: nx, y: ny });
|
|
16333
16397
|
}
|
|
16334
16398
|
}
|
|
@@ -16337,11 +16401,14 @@ function BattleBoard({
|
|
|
16337
16401
|
}, [selectedUnit, currentPhase, units, boardWidth, boardHeight]);
|
|
16338
16402
|
const attackTargets = useMemo(() => {
|
|
16339
16403
|
if (!selectedUnit || currentPhase !== "action") return [];
|
|
16340
|
-
|
|
16341
|
-
|
|
16342
|
-
|
|
16404
|
+
const sp = unitPosition(selectedUnit);
|
|
16405
|
+
const sTeam = unitTeam(selectedUnit);
|
|
16406
|
+
return units.filter((u) => unitTeam(u) !== sTeam && unitHealth(u) > 0).filter((u) => {
|
|
16407
|
+
const p2 = unitPosition(u);
|
|
16408
|
+
const dx = Math.abs(p2.x - sp.x);
|
|
16409
|
+
const dy = Math.abs(p2.y - sp.y);
|
|
16343
16410
|
return dx <= 1 && dy <= 1 && dx + dy > 0;
|
|
16344
|
-
}).map((u) => u
|
|
16411
|
+
}).map((u) => unitPosition(u));
|
|
16345
16412
|
}, [selectedUnit, currentPhase, units]);
|
|
16346
16413
|
const MOVE_SPEED_MS_PER_TILE = 300;
|
|
16347
16414
|
const movementAnimRef = useRef(null);
|
|
@@ -16381,23 +16448,25 @@ function BattleBoard({
|
|
|
16381
16448
|
return () => clearInterval(interval);
|
|
16382
16449
|
}, []);
|
|
16383
16450
|
const isoUnits = useMemo(() => {
|
|
16384
|
-
return units.filter((u) => u
|
|
16385
|
-
const
|
|
16451
|
+
return units.filter((u) => unitHealth(u) > 0).map((unit) => {
|
|
16452
|
+
const id = str(unit.id);
|
|
16453
|
+
const pos = movingPositions.get(id) ?? unitPosition(unit);
|
|
16454
|
+
const unitTraits = Array.isArray(unit.traits) ? unit.traits : void 0;
|
|
16386
16455
|
return {
|
|
16387
|
-
id
|
|
16456
|
+
id,
|
|
16388
16457
|
position: pos,
|
|
16389
|
-
name: unit.name,
|
|
16390
|
-
team: unit
|
|
16391
|
-
health: unit
|
|
16392
|
-
maxHealth: unit.maxHealth,
|
|
16393
|
-
unitType: unit.unitType,
|
|
16394
|
-
heroId: unit.heroId,
|
|
16395
|
-
sprite: unit.sprite,
|
|
16396
|
-
traits:
|
|
16397
|
-
name:
|
|
16398
|
-
currentState:
|
|
16399
|
-
states:
|
|
16400
|
-
cooldown:
|
|
16458
|
+
name: str(unit.name),
|
|
16459
|
+
team: unitTeam(unit),
|
|
16460
|
+
health: unitHealth(unit),
|
|
16461
|
+
maxHealth: num(unit.maxHealth),
|
|
16462
|
+
unitType: unit.unitType == null ? void 0 : str(unit.unitType),
|
|
16463
|
+
heroId: unit.heroId == null ? void 0 : str(unit.heroId),
|
|
16464
|
+
sprite: unit.sprite == null ? void 0 : str(unit.sprite),
|
|
16465
|
+
traits: unitTraits?.map((tr) => ({
|
|
16466
|
+
name: tr.name,
|
|
16467
|
+
currentState: tr.currentState,
|
|
16468
|
+
states: tr.states,
|
|
16469
|
+
cooldown: tr.cooldown ?? 0
|
|
16401
16470
|
}))
|
|
16402
16471
|
};
|
|
16403
16472
|
});
|
|
@@ -16409,8 +16478,8 @@ function BattleBoard({
|
|
|
16409
16478
|
[scale, baseOffsetX]
|
|
16410
16479
|
);
|
|
16411
16480
|
const checkGameEnd = useCallback(() => {
|
|
16412
|
-
const pa = units.filter((u) => u
|
|
16413
|
-
const ea = units.filter((u) => u
|
|
16481
|
+
const pa = units.filter((u) => unitTeam(u) === "player" && unitHealth(u) > 0);
|
|
16482
|
+
const ea = units.filter((u) => unitTeam(u) === "enemy" && unitHealth(u) > 0);
|
|
16414
16483
|
if (pa.length === 0) {
|
|
16415
16484
|
onGameEnd?.("defeat");
|
|
16416
16485
|
if (gameEndEvent) {
|
|
@@ -16424,21 +16493,22 @@ function BattleBoard({
|
|
|
16424
16493
|
}
|
|
16425
16494
|
}, [units, onGameEnd, gameEndEvent, eventBus]);
|
|
16426
16495
|
const handleUnitClick = useCallback((unitId) => {
|
|
16427
|
-
const unit = units.find((u) => u.id === unitId);
|
|
16496
|
+
const unit = units.find((u) => str(u.id) === unitId);
|
|
16428
16497
|
if (!unit) return;
|
|
16429
16498
|
if (unitClickEvent) {
|
|
16430
16499
|
eventBus.emit(`UI:${unitClickEvent}`, { unitId });
|
|
16431
16500
|
}
|
|
16432
16501
|
if (currentPhase === "action" && selectedUnit) {
|
|
16433
|
-
|
|
16434
|
-
|
|
16502
|
+
const up = unitPosition(unit);
|
|
16503
|
+
if (unitTeam(unit) === "enemy" && attackTargets.some((t2) => t2.x === up.x && t2.y === up.y)) {
|
|
16504
|
+
const damage = calculateDamage ? calculateDamage(selectedUnit, unit) : Math.max(1, num(selectedUnit.attack) - num(unit.defense));
|
|
16435
16505
|
setIsShaking(true);
|
|
16436
16506
|
setTimeout(() => setIsShaking(false), 300);
|
|
16437
16507
|
onAttack?.(selectedUnit, unit, damage);
|
|
16438
16508
|
if (attackEvent) {
|
|
16439
16509
|
eventBus.emit(`UI:${attackEvent}`, {
|
|
16440
|
-
attackerId: selectedUnit.id,
|
|
16441
|
-
targetId: unit.id,
|
|
16510
|
+
attackerId: str(selectedUnit.id),
|
|
16511
|
+
targetId: str(unit.id),
|
|
16442
16512
|
damage
|
|
16443
16513
|
});
|
|
16444
16514
|
}
|
|
@@ -16453,9 +16523,9 @@ function BattleBoard({
|
|
|
16453
16523
|
if (currentPhase === "movement" && selectedUnit) {
|
|
16454
16524
|
if (movementAnimRef.current) return;
|
|
16455
16525
|
if (validMoves.some((m) => m.x === x && m.y === y)) {
|
|
16456
|
-
const from = { ...selectedUnit
|
|
16526
|
+
const from = { ...unitPosition(selectedUnit) };
|
|
16457
16527
|
const to = { x, y };
|
|
16458
|
-
startMoveAnimation(selectedUnit.id, from, to, () => {
|
|
16528
|
+
startMoveAnimation(str(selectedUnit.id), from, to, () => {
|
|
16459
16529
|
onUnitMove?.(selectedUnit, to);
|
|
16460
16530
|
});
|
|
16461
16531
|
}
|
|
@@ -16613,6 +16683,7 @@ var init_BattleBoard = __esm({
|
|
|
16613
16683
|
init_Typography();
|
|
16614
16684
|
init_Stack();
|
|
16615
16685
|
init_IsometricCanvas2();
|
|
16686
|
+
init_boardEntity();
|
|
16616
16687
|
init_isometric();
|
|
16617
16688
|
BattleBoard.displayName = "BattleBoard";
|
|
16618
16689
|
}
|
|
@@ -17006,24 +17077,24 @@ var init_CodeBlock = __esm({
|
|
|
17006
17077
|
return;
|
|
17007
17078
|
}
|
|
17008
17079
|
lineEls.forEach((el) => {
|
|
17009
|
-
const
|
|
17010
|
-
if (hiddenLines.has(
|
|
17080
|
+
const num2 = parseInt(el.getAttribute("data-line") ?? "-1", 10);
|
|
17081
|
+
if (hiddenLines.has(num2)) {
|
|
17011
17082
|
el.style.display = "none";
|
|
17012
17083
|
return;
|
|
17013
17084
|
}
|
|
17014
17085
|
el.style.display = "";
|
|
17015
17086
|
el.style.position = "relative";
|
|
17016
17087
|
el.style.paddingLeft = "1.2em";
|
|
17017
|
-
const region = foldStartMap.get(
|
|
17088
|
+
const region = foldStartMap.get(num2);
|
|
17018
17089
|
if (!region) return;
|
|
17019
|
-
const isCollapsed = collapsed.has(
|
|
17090
|
+
const isCollapsed = collapsed.has(num2);
|
|
17020
17091
|
const toggle = document.createElement("span");
|
|
17021
17092
|
toggle.className = "fold-toggle";
|
|
17022
17093
|
toggle.textContent = isCollapsed ? "\u25B6" : "\u25BC";
|
|
17023
17094
|
toggle.style.cssText = "position:absolute;left:0;top:0;width:1.2em;text-align:center;cursor:pointer;color:#858585;font-size:10px;user-select:none;line-height:inherit;height:100%";
|
|
17024
17095
|
toggle.addEventListener("click", (e) => {
|
|
17025
17096
|
e.stopPropagation();
|
|
17026
|
-
toggleFoldRef.current(
|
|
17097
|
+
toggleFoldRef.current(num2);
|
|
17027
17098
|
});
|
|
17028
17099
|
el.insertBefore(toggle, el.firstChild);
|
|
17029
17100
|
if (isCollapsed) {
|
|
@@ -19276,10 +19347,13 @@ var init_BookChapterView = __esm({
|
|
|
19276
19347
|
init_cn();
|
|
19277
19348
|
BookChapterView = ({
|
|
19278
19349
|
chapter,
|
|
19350
|
+
orbitalSchema,
|
|
19279
19351
|
direction,
|
|
19280
19352
|
className
|
|
19281
19353
|
}) => {
|
|
19282
19354
|
const { t: _t } = useTranslate();
|
|
19355
|
+
const title = String(chapter.title ?? "");
|
|
19356
|
+
const content = String(chapter.content ?? "");
|
|
19283
19357
|
return /* @__PURE__ */ jsxs(
|
|
19284
19358
|
VStack,
|
|
19285
19359
|
{
|
|
@@ -19287,16 +19361,16 @@ var init_BookChapterView = __esm({
|
|
|
19287
19361
|
className: cn("px-6 py-8 max-w-4xl mx-auto w-full", className),
|
|
19288
19362
|
style: { direction },
|
|
19289
19363
|
children: [
|
|
19290
|
-
/* @__PURE__ */ jsx(Typography, { variant: "h1", className: "text-3xl font-bold", children:
|
|
19364
|
+
/* @__PURE__ */ jsx(Typography, { variant: "h1", className: "text-3xl font-bold", children: title }),
|
|
19291
19365
|
/* @__PURE__ */ jsx(Divider, {}),
|
|
19292
|
-
!!
|
|
19366
|
+
!!orbitalSchema && /* @__PURE__ */ jsx(ScaledDiagram, { children: /* @__PURE__ */ jsx(
|
|
19293
19367
|
JazariStateMachine,
|
|
19294
19368
|
{
|
|
19295
|
-
schema:
|
|
19369
|
+
schema: orbitalSchema,
|
|
19296
19370
|
direction
|
|
19297
19371
|
}
|
|
19298
19372
|
) }),
|
|
19299
|
-
/* @__PURE__ */ jsx(ContentRenderer, { content
|
|
19373
|
+
/* @__PURE__ */ jsx(ContentRenderer, { content, direction })
|
|
19300
19374
|
]
|
|
19301
19375
|
}
|
|
19302
19376
|
);
|
|
@@ -19394,7 +19468,7 @@ var init_BookNavBar = __esm({
|
|
|
19394
19468
|
BookNavBar = ({
|
|
19395
19469
|
currentPage,
|
|
19396
19470
|
totalPages,
|
|
19397
|
-
chapterTitle,
|
|
19471
|
+
chapterTitle: chapterTitle2,
|
|
19398
19472
|
direction,
|
|
19399
19473
|
className
|
|
19400
19474
|
}) => {
|
|
@@ -19435,12 +19509,12 @@ var init_BookNavBar = __esm({
|
|
|
19435
19509
|
)
|
|
19436
19510
|
] }),
|
|
19437
19511
|
/* @__PURE__ */ jsxs(Box, { className: "flex-1 mx-4 max-w-md", children: [
|
|
19438
|
-
|
|
19512
|
+
chapterTitle2 && /* @__PURE__ */ jsx(
|
|
19439
19513
|
Typography,
|
|
19440
19514
|
{
|
|
19441
19515
|
variant: "caption",
|
|
19442
19516
|
className: "text-center block truncate text-muted-foreground",
|
|
19443
|
-
children:
|
|
19517
|
+
children: chapterTitle2
|
|
19444
19518
|
}
|
|
19445
19519
|
),
|
|
19446
19520
|
/* @__PURE__ */ jsx(ProgressBar, { value: progress, size: "sm", variant: "primary" })
|
|
@@ -19507,31 +19581,35 @@ var init_BookTableOfContents = __esm({
|
|
|
19507
19581
|
style: { direction },
|
|
19508
19582
|
children: [
|
|
19509
19583
|
/* @__PURE__ */ jsx(Typography, { variant: "h1", className: "text-3xl font-bold text-center mb-4", children: t("book.tableOfContents") }),
|
|
19510
|
-
parts.map((part, partIdx) =>
|
|
19511
|
-
|
|
19512
|
-
|
|
19513
|
-
/* @__PURE__ */
|
|
19514
|
-
|
|
19515
|
-
|
|
19516
|
-
|
|
19517
|
-
|
|
19518
|
-
|
|
19519
|
-
|
|
19520
|
-
|
|
19521
|
-
|
|
19522
|
-
|
|
19523
|
-
|
|
19524
|
-
|
|
19525
|
-
|
|
19526
|
-
|
|
19527
|
-
|
|
19528
|
-
|
|
19529
|
-
|
|
19530
|
-
|
|
19531
|
-
|
|
19532
|
-
|
|
19533
|
-
|
|
19534
|
-
|
|
19584
|
+
parts.map((part, partIdx) => {
|
|
19585
|
+
const chapters = Array.isArray(part.chapters) ? part.chapters : [];
|
|
19586
|
+
return /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
|
|
19587
|
+
/* @__PURE__ */ jsxs(HStack, { gap: "sm", align: "center", children: [
|
|
19588
|
+
/* @__PURE__ */ jsx(Badge, { variant: "default", size: "sm", children: t("book.partNumber", { number: String(partIdx + 1) }) }),
|
|
19589
|
+
/* @__PURE__ */ jsx(Typography, { variant: "h3", className: "font-semibold", children: String(part.title ?? "") })
|
|
19590
|
+
] }),
|
|
19591
|
+
/* @__PURE__ */ jsx(VStack, { gap: "xs", className: direction === "rtl" ? "pr-6" : "pl-6", children: chapters.map((chapter) => {
|
|
19592
|
+
const id = chapter.id == null ? "" : String(chapter.id);
|
|
19593
|
+
const isCurrent = id === currentChapterId;
|
|
19594
|
+
return /* @__PURE__ */ jsx(
|
|
19595
|
+
Button,
|
|
19596
|
+
{
|
|
19597
|
+
variant: "ghost",
|
|
19598
|
+
size: "sm",
|
|
19599
|
+
action: "BOOK_NAVIGATE",
|
|
19600
|
+
actionPayload: { chapterId: id },
|
|
19601
|
+
className: cn(
|
|
19602
|
+
"justify-start text-left w-full",
|
|
19603
|
+
direction === "rtl" && "text-right",
|
|
19604
|
+
isCurrent && "bg-blue-50 dark:bg-blue-950 text-blue-600 dark:text-blue-400"
|
|
19605
|
+
),
|
|
19606
|
+
children: /* @__PURE__ */ jsx(Box, { className: "truncate", children: /* @__PURE__ */ jsx(Typography, { variant: "body", children: String(chapter.title ?? "") }) })
|
|
19607
|
+
},
|
|
19608
|
+
id
|
|
19609
|
+
);
|
|
19610
|
+
}) })
|
|
19611
|
+
] }, partIdx);
|
|
19612
|
+
})
|
|
19535
19613
|
]
|
|
19536
19614
|
}
|
|
19537
19615
|
);
|
|
@@ -19653,27 +19731,41 @@ function resolveFieldMap(fieldMap) {
|
|
|
19653
19731
|
function get(obj, key) {
|
|
19654
19732
|
return obj[key];
|
|
19655
19733
|
}
|
|
19734
|
+
function asStr(v) {
|
|
19735
|
+
return v == null ? "" : String(v);
|
|
19736
|
+
}
|
|
19656
19737
|
function mapBookData(raw, fields = IDENTITY_BOOK_FIELDS) {
|
|
19657
19738
|
const rawParts = get(raw, fields.parts) ?? [];
|
|
19658
|
-
|
|
19659
|
-
|
|
19660
|
-
|
|
19661
|
-
|
|
19662
|
-
|
|
19663
|
-
|
|
19664
|
-
|
|
19665
|
-
const rawChapters = get(part, fields.chapters) ?? [];
|
|
19666
|
-
return {
|
|
19667
|
-
title: get(part, fields.partTitle) ?? "",
|
|
19668
|
-
chapters: rawChapters.map((ch) => ({
|
|
19669
|
-
id: get(ch, fields.chapterId) ?? "",
|
|
19670
|
-
title: get(ch, fields.chapterTitle) ?? "",
|
|
19671
|
-
content: get(ch, fields.chapterContent) ?? "",
|
|
19672
|
-
orbitalSchema: get(ch, fields.chapterOrbitalSchema)
|
|
19673
|
-
}))
|
|
19674
|
-
};
|
|
19675
|
-
})
|
|
19739
|
+
const direction = get(raw, fields.direction) ?? "ltr";
|
|
19740
|
+
const cover = {
|
|
19741
|
+
title: asStr(get(raw, fields.title)),
|
|
19742
|
+
subtitle: asStr(get(raw, fields.subtitle)),
|
|
19743
|
+
author: asStr(get(raw, fields.author)),
|
|
19744
|
+
coverImageUrl: asStr(get(raw, fields.coverImageUrl)),
|
|
19745
|
+
direction
|
|
19676
19746
|
};
|
|
19747
|
+
const schemaByChapterId = {};
|
|
19748
|
+
const chapters = [];
|
|
19749
|
+
const parts = rawParts.map((part) => {
|
|
19750
|
+
const rawChapters = get(part, fields.chapters) ?? [];
|
|
19751
|
+
const chapterRows = rawChapters.map((ch) => {
|
|
19752
|
+
const id = asStr(get(ch, fields.chapterId));
|
|
19753
|
+
const schema = get(ch, fields.chapterOrbitalSchema);
|
|
19754
|
+
if (schema) schemaByChapterId[id] = schema;
|
|
19755
|
+
const row = {
|
|
19756
|
+
id,
|
|
19757
|
+
title: asStr(get(ch, fields.chapterTitle)),
|
|
19758
|
+
content: asStr(get(ch, fields.chapterContent))
|
|
19759
|
+
};
|
|
19760
|
+
chapters.push(row);
|
|
19761
|
+
return row;
|
|
19762
|
+
});
|
|
19763
|
+
return {
|
|
19764
|
+
title: asStr(get(part, fields.partTitle)),
|
|
19765
|
+
chapters: chapterRows
|
|
19766
|
+
};
|
|
19767
|
+
});
|
|
19768
|
+
return { cover, direction, parts, chapters, schemaByChapterId };
|
|
19677
19769
|
}
|
|
19678
19770
|
var IDENTITY_BOOK_FIELDS, AR_BOOK_FIELDS, FIELD_MAP_REGISTRY;
|
|
19679
19771
|
var init_types2 = __esm({
|
|
@@ -19711,10 +19803,7 @@ var init_types2 = __esm({
|
|
|
19711
19803
|
};
|
|
19712
19804
|
}
|
|
19713
19805
|
});
|
|
19714
|
-
|
|
19715
|
-
return book.parts.flatMap((part) => part.chapters);
|
|
19716
|
-
}
|
|
19717
|
-
var PRINT_STYLES, BookViewer;
|
|
19806
|
+
var chapterId, chapterTitle, PRINT_STYLES, BookViewer;
|
|
19718
19807
|
var init_BookViewer = __esm({
|
|
19719
19808
|
"components/marketing/organisms/book/BookViewer.tsx"() {
|
|
19720
19809
|
init_Box();
|
|
@@ -19727,6 +19816,8 @@ var init_BookViewer = __esm({
|
|
|
19727
19816
|
init_BookNavBar();
|
|
19728
19817
|
init_EmptyState();
|
|
19729
19818
|
init_types2();
|
|
19819
|
+
chapterId = (ch) => ch?.id == null ? void 0 : String(ch.id);
|
|
19820
|
+
chapterTitle = (ch) => ch?.title == null ? void 0 : String(ch.title);
|
|
19730
19821
|
PRINT_STYLES = `
|
|
19731
19822
|
@media print {
|
|
19732
19823
|
.book-viewer-page {
|
|
@@ -19755,14 +19846,14 @@ var init_BookViewer = __esm({
|
|
|
19755
19846
|
return mapBookData(raw, resolvedFieldMap);
|
|
19756
19847
|
}, [entity, resolvedFieldMap]);
|
|
19757
19848
|
const direction = book?.direction ?? "ltr";
|
|
19758
|
-
const chapters = useMemo(() => book ?
|
|
19849
|
+
const chapters = useMemo(() => book ? book.chapters : [], [book]);
|
|
19759
19850
|
const totalPages = 2 + chapters.length;
|
|
19760
19851
|
const navigateTo = useCallback(
|
|
19761
19852
|
(page) => {
|
|
19762
19853
|
const clamped = Math.max(0, Math.min(page, totalPages - 1));
|
|
19763
19854
|
setCurrentPage(clamped);
|
|
19764
|
-
const
|
|
19765
|
-
eventBus.emit("UI:BOOK_PAGE_CHANGE", { pageIndex: clamped, chapterId });
|
|
19855
|
+
const id = clamped >= 2 ? chapterId(chapters[clamped - 2]) : void 0;
|
|
19856
|
+
eventBus.emit("UI:BOOK_PAGE_CHANGE", { pageIndex: clamped, chapterId: id });
|
|
19766
19857
|
},
|
|
19767
19858
|
[totalPages, chapters, eventBus]
|
|
19768
19859
|
);
|
|
@@ -19774,8 +19865,8 @@ var init_BookViewer = __esm({
|
|
|
19774
19865
|
eventBus.on("UI:BOOK_PAGE_NEXT", () => navigateTo(currentPage + 1)),
|
|
19775
19866
|
eventBus.on("UI:BOOK_PRINT", () => window.print()),
|
|
19776
19867
|
eventBus.on("UI:BOOK_NAVIGATE", (event) => {
|
|
19777
|
-
const
|
|
19778
|
-
const idx = chapters.findIndex((ch) => ch
|
|
19868
|
+
const targetId = event.payload?.chapterId;
|
|
19869
|
+
const idx = chapters.findIndex((ch) => chapterId(ch) === targetId);
|
|
19779
19870
|
if (idx >= 0) navigateTo(idx + 2);
|
|
19780
19871
|
})
|
|
19781
19872
|
];
|
|
@@ -19792,9 +19883,11 @@ var init_BookViewer = __esm({
|
|
|
19792
19883
|
style.remove();
|
|
19793
19884
|
};
|
|
19794
19885
|
}, []);
|
|
19795
|
-
const currentChapterId = currentPage >= 2 ? chapters[currentPage - 2]
|
|
19796
|
-
const currentChapterTitle = currentPage >= 2 ? chapters[currentPage - 2]
|
|
19886
|
+
const currentChapterId = currentPage >= 2 ? chapterId(chapters[currentPage - 2]) : void 0;
|
|
19887
|
+
const currentChapterTitle = currentPage >= 2 ? chapterTitle(chapters[currentPage - 2]) : void 0;
|
|
19797
19888
|
if (!book) return /* @__PURE__ */ jsx(EmptyState, { message: t("book.noData") });
|
|
19889
|
+
const cover = book.cover;
|
|
19890
|
+
const coverTitle = String(cover.title ?? "");
|
|
19798
19891
|
return /* @__PURE__ */ jsxs(VStack, { className: cn("relative h-full overflow-hidden bg-background", className), children: [
|
|
19799
19892
|
/* @__PURE__ */ jsxs(
|
|
19800
19893
|
Box,
|
|
@@ -19806,10 +19899,10 @@ var init_BookViewer = __esm({
|
|
|
19806
19899
|
/* @__PURE__ */ jsx(
|
|
19807
19900
|
BookCoverPage,
|
|
19808
19901
|
{
|
|
19809
|
-
title:
|
|
19810
|
-
subtitle:
|
|
19811
|
-
author:
|
|
19812
|
-
coverImageUrl:
|
|
19902
|
+
title: coverTitle,
|
|
19903
|
+
subtitle: String(cover.subtitle ?? "") || void 0,
|
|
19904
|
+
author: String(cover.author ?? "") || void 0,
|
|
19905
|
+
coverImageUrl: String(cover.coverImageUrl ?? "") || void 0,
|
|
19813
19906
|
direction
|
|
19814
19907
|
}
|
|
19815
19908
|
),
|
|
@@ -19820,23 +19913,27 @@ var init_BookViewer = __esm({
|
|
|
19820
19913
|
direction
|
|
19821
19914
|
}
|
|
19822
19915
|
),
|
|
19823
|
-
chapters.map((chapter) =>
|
|
19824
|
-
|
|
19825
|
-
|
|
19826
|
-
|
|
19827
|
-
|
|
19828
|
-
|
|
19829
|
-
|
|
19830
|
-
|
|
19916
|
+
chapters.map((chapter) => {
|
|
19917
|
+
const id = chapterId(chapter);
|
|
19918
|
+
return /* @__PURE__ */ jsx(
|
|
19919
|
+
BookChapterView,
|
|
19920
|
+
{
|
|
19921
|
+
chapter,
|
|
19922
|
+
orbitalSchema: id ? book.schemaByChapterId[id] : void 0,
|
|
19923
|
+
direction
|
|
19924
|
+
},
|
|
19925
|
+
id
|
|
19926
|
+
);
|
|
19927
|
+
})
|
|
19831
19928
|
] }),
|
|
19832
19929
|
/* @__PURE__ */ jsxs(Box, { className: "print:hidden", children: [
|
|
19833
19930
|
currentPage === 0 && /* @__PURE__ */ jsx(
|
|
19834
19931
|
BookCoverPage,
|
|
19835
19932
|
{
|
|
19836
|
-
title:
|
|
19837
|
-
subtitle:
|
|
19838
|
-
author:
|
|
19839
|
-
coverImageUrl:
|
|
19933
|
+
title: coverTitle,
|
|
19934
|
+
subtitle: String(cover.subtitle ?? "") || void 0,
|
|
19935
|
+
author: String(cover.author ?? "") || void 0,
|
|
19936
|
+
coverImageUrl: String(cover.coverImageUrl ?? "") || void 0,
|
|
19840
19937
|
direction
|
|
19841
19938
|
}
|
|
19842
19939
|
),
|
|
@@ -19852,6 +19949,7 @@ var init_BookViewer = __esm({
|
|
|
19852
19949
|
BookChapterView,
|
|
19853
19950
|
{
|
|
19854
19951
|
chapter: chapters[currentPage - 2],
|
|
19952
|
+
orbitalSchema: currentChapterId ? book.schemaByChapterId[currentChapterId] : void 0,
|
|
19855
19953
|
direction
|
|
19856
19954
|
}
|
|
19857
19955
|
)
|
|
@@ -19864,7 +19962,7 @@ var init_BookViewer = __esm({
|
|
|
19864
19962
|
{
|
|
19865
19963
|
currentPage,
|
|
19866
19964
|
totalPages,
|
|
19867
|
-
chapterTitle: currentPage === 0 ?
|
|
19965
|
+
chapterTitle: currentPage === 0 ? coverTitle : currentPage === 1 ? t("book.tableOfContents") : currentChapterTitle,
|
|
19868
19966
|
direction
|
|
19869
19967
|
}
|
|
19870
19968
|
)
|
|
@@ -19962,7 +20060,7 @@ var init_Grid = __esm({
|
|
|
19962
20060
|
};
|
|
19963
20061
|
Grid = ({
|
|
19964
20062
|
cols = 1,
|
|
19965
|
-
rows,
|
|
20063
|
+
rows: rows2,
|
|
19966
20064
|
gap = "md",
|
|
19967
20065
|
rowGap,
|
|
19968
20066
|
colGap,
|
|
@@ -19974,7 +20072,7 @@ var init_Grid = __esm({
|
|
|
19974
20072
|
children,
|
|
19975
20073
|
as: Component = "div"
|
|
19976
20074
|
}) => {
|
|
19977
|
-
const mergedStyle =
|
|
20075
|
+
const mergedStyle = rows2 ? { gridTemplateRows: `repeat(${rows2}, minmax(0, 1fr))`, ...style } : style;
|
|
19978
20076
|
return React97__default.createElement(
|
|
19979
20077
|
Component,
|
|
19980
20078
|
{
|
|
@@ -20690,14 +20788,14 @@ function BuilderBoard({
|
|
|
20690
20788
|
}) {
|
|
20691
20789
|
const { emit } = useEventBus();
|
|
20692
20790
|
const { t } = useTranslate();
|
|
20693
|
-
const resolved =
|
|
20791
|
+
const resolved = boardEntity(entity);
|
|
20694
20792
|
const [placements, setPlacements] = useState({});
|
|
20695
20793
|
const [headerError, setHeaderError] = useState(false);
|
|
20696
20794
|
const [submitted, setSubmitted] = useState(false);
|
|
20697
20795
|
const [attempts, setAttempts] = useState(0);
|
|
20698
20796
|
const [showHint, setShowHint] = useState(false);
|
|
20699
|
-
const components = resolved?.components
|
|
20700
|
-
const slots = resolved?.slots
|
|
20797
|
+
const components = Array.isArray(resolved?.components) ? resolved.components : [];
|
|
20798
|
+
const slots = Array.isArray(resolved?.slots) ? resolved.slots : [];
|
|
20701
20799
|
const usedComponentIds = new Set(Object.values(placements));
|
|
20702
20800
|
const availableComponents = components.filter((c) => !usedComponentIds.has(c.id));
|
|
20703
20801
|
const [selectedComponent, setSelectedComponent] = useState(null);
|
|
@@ -20731,7 +20829,7 @@ function BuilderBoard({
|
|
|
20731
20829
|
}, [slots, placements, attempts, completeEvent, emit]);
|
|
20732
20830
|
const handleReset = () => {
|
|
20733
20831
|
setSubmitted(false);
|
|
20734
|
-
if (attempts >= 2 && resolved?.hint) {
|
|
20832
|
+
if (attempts >= 2 && str(resolved?.hint)) {
|
|
20735
20833
|
setShowHint(true);
|
|
20736
20834
|
}
|
|
20737
20835
|
};
|
|
@@ -20744,20 +20842,24 @@ function BuilderBoard({
|
|
|
20744
20842
|
};
|
|
20745
20843
|
const getComponentById = (id) => components.find((c) => c.id === id);
|
|
20746
20844
|
if (!resolved) return null;
|
|
20845
|
+
const theme = resolved.theme ?? void 0;
|
|
20846
|
+
const themeBackground = theme?.background;
|
|
20847
|
+
const headerImage = str(resolved.headerImage);
|
|
20848
|
+
const hint = str(resolved.hint);
|
|
20747
20849
|
return /* @__PURE__ */ jsx(
|
|
20748
20850
|
Box,
|
|
20749
20851
|
{
|
|
20750
20852
|
className,
|
|
20751
20853
|
style: {
|
|
20752
|
-
backgroundImage:
|
|
20854
|
+
backgroundImage: themeBackground ? `url(${themeBackground})` : void 0,
|
|
20753
20855
|
backgroundSize: "cover",
|
|
20754
20856
|
backgroundPosition: "center"
|
|
20755
20857
|
},
|
|
20756
20858
|
children: /* @__PURE__ */ jsxs(VStack, { gap: "lg", className: "p-4", children: [
|
|
20757
|
-
|
|
20859
|
+
headerImage && !headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 overflow-hidden rounded-container", children: /* @__PURE__ */ jsx("img", { src: headerImage, alt: "", onError: () => setHeaderError(true), className: "w-full h-full object-cover" }) }) : headerImage && headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 rounded-container bg-gradient-to-br from-muted to-accent opacity-60" }) : null,
|
|
20758
20860
|
/* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
|
|
20759
|
-
/* @__PURE__ */ jsx(Typography, { variant: "h4", weight: "bold", children: resolved.title }),
|
|
20760
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body", children: resolved.description })
|
|
20861
|
+
/* @__PURE__ */ jsx(Typography, { variant: "h4", weight: "bold", children: str(resolved.title) }),
|
|
20862
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body", children: str(resolved.description) })
|
|
20761
20863
|
] }) }),
|
|
20762
20864
|
/* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
|
|
20763
20865
|
/* @__PURE__ */ jsx(Typography, { variant: "small", weight: "bold", className: "uppercase tracking-wider text-muted-foreground", children: t("builder.components") }),
|
|
@@ -20817,9 +20919,9 @@ function BuilderBoard({
|
|
|
20817
20919
|
] }) }),
|
|
20818
20920
|
submitted && /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", align: "center", children: [
|
|
20819
20921
|
/* @__PURE__ */ jsx(Icon, { icon: allCorrect ? CheckCircle : XCircle, size: "lg", className: allCorrect ? "text-success" : "text-error" }),
|
|
20820
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body", weight: "bold", children: allCorrect ? resolved.successMessage
|
|
20922
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body", weight: "bold", children: allCorrect ? str(resolved.successMessage) || t("builder.success") : str(resolved.failMessage) || t("builder.incorrect") })
|
|
20821
20923
|
] }) }),
|
|
20822
|
-
showHint &&
|
|
20924
|
+
showHint && hint && /* @__PURE__ */ jsx(Card, { className: "p-4 border-l-4 border-l-warning", children: /* @__PURE__ */ jsx(Typography, { variant: "body", children: hint }) }),
|
|
20823
20925
|
/* @__PURE__ */ jsxs(HStack, { gap: "sm", justify: "center", children: [
|
|
20824
20926
|
!submitted ? /* @__PURE__ */ jsxs(Button, { variant: "primary", onClick: handleSubmit, disabled: !allPlaced, children: [
|
|
20825
20927
|
/* @__PURE__ */ jsx(Icon, { icon: Wrench, size: "sm" }),
|
|
@@ -20838,6 +20940,7 @@ var init_BuilderBoard = __esm({
|
|
|
20838
20940
|
"components/game/organisms/puzzles/builder/BuilderBoard.tsx"() {
|
|
20839
20941
|
init_atoms2();
|
|
20840
20942
|
init_useEventBus();
|
|
20943
|
+
init_boardEntity();
|
|
20841
20944
|
BuilderBoard.displayName = "BuilderBoard";
|
|
20842
20945
|
}
|
|
20843
20946
|
});
|
|
@@ -21175,21 +21278,24 @@ function CalendarGrid({
|
|
|
21175
21278
|
eventBus.emit(`UI:${longPressEvent}`, { date: day.toISOString(), time, ...longPressPayload });
|
|
21176
21279
|
}, 500);
|
|
21177
21280
|
}, [longPressEvent, longPressPayload, eventBus]);
|
|
21178
|
-
const renderEvent = (event) =>
|
|
21179
|
-
|
|
21180
|
-
|
|
21181
|
-
|
|
21182
|
-
|
|
21183
|
-
|
|
21184
|
-
|
|
21185
|
-
|
|
21186
|
-
|
|
21187
|
-
|
|
21188
|
-
|
|
21189
|
-
|
|
21190
|
-
|
|
21191
|
-
|
|
21192
|
-
|
|
21281
|
+
const renderEvent = (event) => {
|
|
21282
|
+
const color = event.color;
|
|
21283
|
+
return /* @__PURE__ */ jsx(
|
|
21284
|
+
Box,
|
|
21285
|
+
{
|
|
21286
|
+
rounded: "md",
|
|
21287
|
+
padding: "xs",
|
|
21288
|
+
border: true,
|
|
21289
|
+
className: cn(
|
|
21290
|
+
"cursor-pointer hover:shadow-sm transition-shadow text-xs truncate",
|
|
21291
|
+
color ? color : "bg-blue-500/15 border-blue-500/30 text-blue-600"
|
|
21292
|
+
),
|
|
21293
|
+
onClick: (e) => handleEventClick(event, e),
|
|
21294
|
+
children: /* @__PURE__ */ jsx(Typography, { variant: "small", className: "truncate font-medium", children: event.title })
|
|
21295
|
+
},
|
|
21296
|
+
event.id
|
|
21297
|
+
);
|
|
21298
|
+
};
|
|
21193
21299
|
return /* @__PURE__ */ jsxs(
|
|
21194
21300
|
Box,
|
|
21195
21301
|
{
|
|
@@ -22853,7 +22959,6 @@ var init_CardGrid = __esm({
|
|
|
22853
22959
|
alignItems = "stretch",
|
|
22854
22960
|
className,
|
|
22855
22961
|
children,
|
|
22856
|
-
// EntityDisplayProps
|
|
22857
22962
|
entity,
|
|
22858
22963
|
isLoading = false,
|
|
22859
22964
|
error = null,
|
|
@@ -23325,14 +23430,14 @@ var init_CaseStudyOrganism = __esm({
|
|
|
23325
23430
|
/* @__PURE__ */ jsx(SimpleGrid, { cols: cols > 0 ? cols : 1, gap: "lg", children: items.map((study) => /* @__PURE__ */ jsx(
|
|
23326
23431
|
CaseStudyCard,
|
|
23327
23432
|
{
|
|
23328
|
-
title: study.title,
|
|
23329
|
-
description: study.description,
|
|
23330
|
-
category: study.category,
|
|
23331
|
-
categoryColor: study.categoryColor,
|
|
23332
|
-
href: study.href,
|
|
23333
|
-
linkLabel: study.linkLabel
|
|
23433
|
+
title: String(study.title ?? ""),
|
|
23434
|
+
description: String(study.description ?? ""),
|
|
23435
|
+
category: String(study.category ?? ""),
|
|
23436
|
+
categoryColor: study.categoryColor != null ? String(study.categoryColor) : void 0,
|
|
23437
|
+
href: String(study.href ?? ""),
|
|
23438
|
+
linkLabel: study.linkLabel != null ? String(study.linkLabel) : void 0
|
|
23334
23439
|
},
|
|
23335
|
-
study.id
|
|
23440
|
+
String(study.id ?? "")
|
|
23336
23441
|
)) })
|
|
23337
23442
|
] });
|
|
23338
23443
|
};
|
|
@@ -23355,10 +23460,10 @@ function CastleBoard({
|
|
|
23355
23460
|
className
|
|
23356
23461
|
}) {
|
|
23357
23462
|
const eventBus = useEventBus();
|
|
23358
|
-
const resolved =
|
|
23359
|
-
const tiles = resolved?.tiles
|
|
23360
|
-
const features = resolved?.features
|
|
23361
|
-
const units = resolved?.units
|
|
23463
|
+
const resolved = boardEntity(entity);
|
|
23464
|
+
const tiles = Array.isArray(resolved?.tiles) ? resolved.tiles : [];
|
|
23465
|
+
const features = Array.isArray(resolved?.features) ? resolved.features : [];
|
|
23466
|
+
const units = Array.isArray(resolved?.units) ? resolved.units : [];
|
|
23362
23467
|
const assetManifest = resolved?.assetManifest;
|
|
23363
23468
|
const backgroundImage = resolved?.backgroundImage;
|
|
23364
23469
|
const [hoveredTile, setHoveredTile] = useState(null);
|
|
@@ -23386,7 +23491,7 @@ function CastleBoard({
|
|
|
23386
23491
|
onFeatureClick?.(feature);
|
|
23387
23492
|
if (featureClickEvent) {
|
|
23388
23493
|
eventBus.emit(`UI:${featureClickEvent}`, {
|
|
23389
|
-
featureId: feature.id,
|
|
23494
|
+
featureId: feature.id ?? "",
|
|
23390
23495
|
featureType: feature.type,
|
|
23391
23496
|
x: feature.x,
|
|
23392
23497
|
y: feature.y
|
|
@@ -23454,6 +23559,7 @@ var init_CastleBoard = __esm({
|
|
|
23454
23559
|
init_cn();
|
|
23455
23560
|
init_useEventBus();
|
|
23456
23561
|
init_IsometricCanvas2();
|
|
23562
|
+
init_boardEntity();
|
|
23457
23563
|
init_isometric();
|
|
23458
23564
|
CastleBoard.displayName = "CastleBoard";
|
|
23459
23565
|
}
|
|
@@ -24264,14 +24370,14 @@ function ClassifierBoard({
|
|
|
24264
24370
|
}) {
|
|
24265
24371
|
const { emit } = useEventBus();
|
|
24266
24372
|
const { t } = useTranslate();
|
|
24267
|
-
const resolved =
|
|
24373
|
+
const resolved = boardEntity(entity);
|
|
24268
24374
|
const [assignments, setAssignments] = useState({});
|
|
24269
24375
|
const [headerError, setHeaderError] = useState(false);
|
|
24270
24376
|
const [submitted, setSubmitted] = useState(false);
|
|
24271
24377
|
const [attempts, setAttempts] = useState(0);
|
|
24272
24378
|
const [showHint, setShowHint] = useState(false);
|
|
24273
|
-
const items = resolved?.items
|
|
24274
|
-
const categories = resolved?.categories
|
|
24379
|
+
const items = Array.isArray(resolved?.items) ? resolved.items : [];
|
|
24380
|
+
const categories = Array.isArray(resolved?.categories) ? resolved.categories : [];
|
|
24275
24381
|
const unassignedItems = items.filter((item) => !assignments[item.id]);
|
|
24276
24382
|
const allAssigned = Object.keys(assignments).length === items.length;
|
|
24277
24383
|
const results = submitted ? items.map((item) => ({
|
|
@@ -24303,7 +24409,7 @@ function ClassifierBoard({
|
|
|
24303
24409
|
}, [items, assignments, attempts, completeEvent, emit]);
|
|
24304
24410
|
const handleReset = () => {
|
|
24305
24411
|
setSubmitted(false);
|
|
24306
|
-
if (attempts >= 2 && resolved?.hint) {
|
|
24412
|
+
if (attempts >= 2 && str(resolved?.hint)) {
|
|
24307
24413
|
setShowHint(true);
|
|
24308
24414
|
}
|
|
24309
24415
|
};
|
|
@@ -24314,20 +24420,25 @@ function ClassifierBoard({
|
|
|
24314
24420
|
setShowHint(false);
|
|
24315
24421
|
};
|
|
24316
24422
|
if (!resolved) return null;
|
|
24423
|
+
const theme = resolved.theme ?? void 0;
|
|
24424
|
+
const themeBackground = theme?.background;
|
|
24425
|
+
const headerImage = str(resolved.headerImage);
|
|
24426
|
+
const hint = str(resolved.hint);
|
|
24427
|
+
const failMessage = str(resolved.failMessage);
|
|
24317
24428
|
return /* @__PURE__ */ jsx(
|
|
24318
24429
|
Box,
|
|
24319
24430
|
{
|
|
24320
24431
|
className,
|
|
24321
24432
|
style: {
|
|
24322
|
-
backgroundImage:
|
|
24433
|
+
backgroundImage: themeBackground ? `url(${themeBackground})` : void 0,
|
|
24323
24434
|
backgroundSize: "cover",
|
|
24324
24435
|
backgroundPosition: "center"
|
|
24325
24436
|
},
|
|
24326
24437
|
children: /* @__PURE__ */ jsxs(VStack, { gap: "lg", className: "p-4", children: [
|
|
24327
|
-
|
|
24438
|
+
headerImage && !headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 overflow-hidden rounded-container", children: /* @__PURE__ */ jsx("img", { src: headerImage, alt: "", onError: () => setHeaderError(true), className: "w-full h-full object-cover" }) }) : headerImage && headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 rounded-container bg-gradient-to-br from-muted to-accent opacity-60" }) : null,
|
|
24328
24439
|
/* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
|
|
24329
|
-
/* @__PURE__ */ jsx(Typography, { variant: "h4", weight: "bold", children: resolved.title }),
|
|
24330
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body", children: resolved.description })
|
|
24440
|
+
/* @__PURE__ */ jsx(Typography, { variant: "h4", weight: "bold", children: str(resolved.title) }),
|
|
24441
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body", children: str(resolved.description) })
|
|
24331
24442
|
] }) }),
|
|
24332
24443
|
unassignedItems.length > 0 && /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
|
|
24333
24444
|
/* @__PURE__ */ jsx(Typography, { variant: "small", weight: "bold", className: "uppercase tracking-wider text-muted-foreground", children: t("classifier.itemsToSort") }),
|
|
@@ -24379,10 +24490,10 @@ function ClassifierBoard({
|
|
|
24379
24490
|
}) }),
|
|
24380
24491
|
submitted && /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", align: "center", children: [
|
|
24381
24492
|
/* @__PURE__ */ jsx(Icon, { icon: allCorrect ? CheckCircle : XCircle, size: "lg", className: allCorrect ? "text-success" : "text-error" }),
|
|
24382
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body", weight: "bold", children: allCorrect ? resolved.successMessage
|
|
24383
|
-
!allCorrect &&
|
|
24493
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body", weight: "bold", children: allCorrect ? str(resolved.successMessage) || t("classifier.allCorrect") : `${correctCount}/${items.length} ${t("classifier.correct")}` }),
|
|
24494
|
+
!allCorrect && failMessage && /* @__PURE__ */ jsx(Typography, { variant: "body", className: "text-muted-foreground", children: failMessage })
|
|
24384
24495
|
] }) }),
|
|
24385
|
-
showHint &&
|
|
24496
|
+
showHint && hint && /* @__PURE__ */ jsx(Card, { className: "p-4 border-l-4 border-l-warning", children: /* @__PURE__ */ jsx(Typography, { variant: "body", children: hint }) }),
|
|
24386
24497
|
/* @__PURE__ */ jsxs(HStack, { gap: "sm", justify: "center", children: [
|
|
24387
24498
|
!submitted ? /* @__PURE__ */ jsxs(Button, { variant: "primary", onClick: handleSubmit, disabled: !allAssigned, children: [
|
|
24388
24499
|
/* @__PURE__ */ jsx(Icon, { icon: Send, size: "sm" }),
|
|
@@ -24401,6 +24512,7 @@ var init_ClassifierBoard = __esm({
|
|
|
24401
24512
|
"components/game/organisms/puzzles/classifier/ClassifierBoard.tsx"() {
|
|
24402
24513
|
init_atoms2();
|
|
24403
24514
|
init_useEventBus();
|
|
24515
|
+
init_boardEntity();
|
|
24404
24516
|
ClassifierBoard.displayName = "ClassifierBoard";
|
|
24405
24517
|
}
|
|
24406
24518
|
});
|
|
@@ -30771,7 +30883,7 @@ function InventoryPanel({
|
|
|
30771
30883
|
const slotArray = Array.from({ length: safeSlots }, (_, index) => {
|
|
30772
30884
|
return safeItems[index] ?? null;
|
|
30773
30885
|
});
|
|
30774
|
-
const
|
|
30886
|
+
const rows2 = Math.ceil(safeSlots / safeColumns);
|
|
30775
30887
|
const handleSlotClick = useCallback((index) => {
|
|
30776
30888
|
if (selectSlotEvent) eventBus.emit(`UI:${selectSlotEvent}`, { index });
|
|
30777
30889
|
onSelectSlot?.(index);
|
|
@@ -30840,7 +30952,7 @@ function InventoryPanel({
|
|
|
30840
30952
|
className: "grid gap-1 bg-[var(--color-card)] p-2 rounded-container border border-border",
|
|
30841
30953
|
style: {
|
|
30842
30954
|
gridTemplateColumns: `repeat(${safeColumns}, ${slotSize}px)`,
|
|
30843
|
-
gridTemplateRows: `repeat(${
|
|
30955
|
+
gridTemplateRows: `repeat(${rows2}, ${slotSize}px)`
|
|
30844
30956
|
},
|
|
30845
30957
|
children: slotArray.map((item, index) => /* @__PURE__ */ jsx(
|
|
30846
30958
|
"button",
|
|
@@ -34804,11 +34916,11 @@ function LatticeSVG({
|
|
|
34804
34916
|
}) {
|
|
34805
34917
|
const paths = [];
|
|
34806
34918
|
const cols = 5;
|
|
34807
|
-
const
|
|
34919
|
+
const rows2 = Math.ceil(h / (w / cols));
|
|
34808
34920
|
const cellW = w / cols;
|
|
34809
34921
|
const cellH = cellW;
|
|
34810
34922
|
const bulge = cellW * 0.3;
|
|
34811
|
-
for (let row = 0; row <
|
|
34923
|
+
for (let row = 0; row < rows2; row++) {
|
|
34812
34924
|
for (let col = 0; col < cols; col++) {
|
|
34813
34925
|
const cx = col * cellW + cellW / 2;
|
|
34814
34926
|
const cy = row * cellH + cellH / 2;
|
|
@@ -35220,7 +35332,7 @@ var init_MatrixQuestion = __esm({
|
|
|
35220
35332
|
};
|
|
35221
35333
|
MatrixQuestion = ({
|
|
35222
35334
|
title,
|
|
35223
|
-
rows,
|
|
35335
|
+
rows: rows2,
|
|
35224
35336
|
columns = DEFAULT_MATRIX_COLUMNS,
|
|
35225
35337
|
values,
|
|
35226
35338
|
onChange,
|
|
@@ -35230,7 +35342,7 @@ var init_MatrixQuestion = __esm({
|
|
|
35230
35342
|
className
|
|
35231
35343
|
}) => {
|
|
35232
35344
|
const styles = sizeStyles13[size];
|
|
35233
|
-
const safeRows =
|
|
35345
|
+
const safeRows = rows2 ?? [];
|
|
35234
35346
|
const safeValues = values ?? {};
|
|
35235
35347
|
const eventBus = useEventBus();
|
|
35236
35348
|
const handleChange = useCallback(
|
|
@@ -35858,7 +35970,8 @@ var init_PositionedCanvas = __esm({
|
|
|
35858
35970
|
dragRef.current = null;
|
|
35859
35971
|
setDraggingId(null);
|
|
35860
35972
|
if (!wasDrag) {
|
|
35861
|
-
const
|
|
35973
|
+
const itemId = item.id;
|
|
35974
|
+
const next = selectedId === itemId ? null : itemId;
|
|
35862
35975
|
onSelect?.(next);
|
|
35863
35976
|
if (selectEvent) {
|
|
35864
35977
|
eventBus.emit(`UI:${selectEvent}`, { id: next });
|
|
@@ -35893,15 +36006,22 @@ var init_PositionedCanvas = __esm({
|
|
|
35893
36006
|
style: { width, height },
|
|
35894
36007
|
onClick: handleContainerClick,
|
|
35895
36008
|
children: items.map((item) => {
|
|
36009
|
+
const itemId = item.id;
|
|
36010
|
+
const label = item.label;
|
|
36011
|
+
const x = item.x;
|
|
36012
|
+
const y = item.y;
|
|
36013
|
+
const capacity = item.capacity;
|
|
36014
|
+
const partySize = item.partySize;
|
|
36015
|
+
const serverName = item.serverName;
|
|
35896
36016
|
const status = item.status ?? "empty";
|
|
35897
36017
|
const shape = item.shape ?? "round";
|
|
35898
|
-
const isSelected = selectedId ===
|
|
35899
|
-
const isDragging = draggingId ===
|
|
36018
|
+
const isSelected = selectedId === itemId;
|
|
36019
|
+
const isDragging = draggingId === itemId;
|
|
35900
36020
|
const statusBadge = STATUS_BADGE[status];
|
|
35901
36021
|
return /* @__PURE__ */ jsxs(
|
|
35902
36022
|
Box,
|
|
35903
36023
|
{
|
|
35904
|
-
"data-testid": `item-node-${
|
|
36024
|
+
"data-testid": `item-node-${itemId}`,
|
|
35905
36025
|
"data-status": status,
|
|
35906
36026
|
className: cn(
|
|
35907
36027
|
"absolute flex flex-col items-center justify-center gap-1 border-2 select-none",
|
|
@@ -35912,7 +36032,7 @@ var init_PositionedCanvas = __esm({
|
|
|
35912
36032
|
isSelected && "outline outline-2 outline-offset-2 outline-primary shadow-md",
|
|
35913
36033
|
isDragging && "shadow-lg z-10"
|
|
35914
36034
|
),
|
|
35915
|
-
style: { left:
|
|
36035
|
+
style: { left: x, top: y, touchAction: "none" },
|
|
35916
36036
|
onPointerDown: (e) => handlePointerDown(e, item),
|
|
35917
36037
|
onPointerMove: handlePointerMove,
|
|
35918
36038
|
onPointerUp: (e) => handlePointerUp(e, item),
|
|
@@ -35920,10 +36040,10 @@ var init_PositionedCanvas = __esm({
|
|
|
35920
36040
|
children: [
|
|
35921
36041
|
/* @__PURE__ */ jsxs(Box, { className: "flex items-center gap-1", children: [
|
|
35922
36042
|
getStatusIcon(status),
|
|
35923
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body2", weight: "semibold", children:
|
|
36043
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body2", weight: "semibold", children: label })
|
|
35924
36044
|
] }),
|
|
35925
|
-
/* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", children:
|
|
35926
|
-
status === "seated" &&
|
|
36045
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", children: partySize !== void 0 && status === "seated" ? `${partySize}/${capacity}` : `Cap ${capacity}` }),
|
|
36046
|
+
status === "seated" && serverName && /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", className: "truncate max-w-[80%]", children: serverName }),
|
|
35927
36047
|
isSelected && /* @__PURE__ */ jsx(
|
|
35928
36048
|
Badge,
|
|
35929
36049
|
{
|
|
@@ -35935,7 +36055,7 @@ var init_PositionedCanvas = __esm({
|
|
|
35935
36055
|
)
|
|
35936
36056
|
]
|
|
35937
36057
|
},
|
|
35938
|
-
|
|
36058
|
+
itemId
|
|
35939
36059
|
);
|
|
35940
36060
|
})
|
|
35941
36061
|
}
|
|
@@ -36707,9 +36827,10 @@ var init_RichBlockEditor = __esm({
|
|
|
36707
36827
|
});
|
|
36708
36828
|
function collectInitiallyCollapsed(nodes, acc) {
|
|
36709
36829
|
for (const n of nodes) {
|
|
36830
|
+
const replies = n.replies;
|
|
36710
36831
|
if (n.collapsed) acc.add(n.id);
|
|
36711
|
-
if (
|
|
36712
|
-
collectInitiallyCollapsed(
|
|
36832
|
+
if (replies && replies.length > 0) {
|
|
36833
|
+
collectInitiallyCollapsed(replies, acc);
|
|
36713
36834
|
}
|
|
36714
36835
|
}
|
|
36715
36836
|
}
|
|
@@ -36739,44 +36860,52 @@ var init_ReplyTree = __esm({
|
|
|
36739
36860
|
}) => {
|
|
36740
36861
|
const eventBus = useEventBus();
|
|
36741
36862
|
const { t } = useTranslate();
|
|
36742
|
-
const
|
|
36743
|
-
const
|
|
36863
|
+
const nodeId = node.id;
|
|
36864
|
+
const authorName = node.authorName;
|
|
36865
|
+
const authorAvatarUrl = node.authorAvatarUrl;
|
|
36866
|
+
const content = node.content;
|
|
36867
|
+
const postedAt = node.postedAt;
|
|
36868
|
+
const voteCount = node.voteCount;
|
|
36869
|
+
const userVote = node.userVote;
|
|
36870
|
+
const replies = node.replies;
|
|
36871
|
+
const hasReplies = !!replies && replies.length > 0;
|
|
36872
|
+
const isCollapsed = collapsedSet.has(nodeId);
|
|
36744
36873
|
const atMaxDepth = depth >= maxDepth;
|
|
36745
36874
|
const [replyOpen, setReplyOpen] = useState(false);
|
|
36746
36875
|
const [draft, setDraft] = useState("");
|
|
36747
36876
|
const handleVote = useCallback(
|
|
36748
36877
|
(next) => {
|
|
36749
|
-
onVote?.(
|
|
36750
|
-
if (voteEvent) eventBus.emit(`UI:${voteEvent}`, { nodeId
|
|
36878
|
+
onVote?.(nodeId, next);
|
|
36879
|
+
if (voteEvent) eventBus.emit(`UI:${voteEvent}`, { nodeId, vote: next });
|
|
36751
36880
|
},
|
|
36752
|
-
[
|
|
36881
|
+
[nodeId, onVote, voteEvent, eventBus]
|
|
36753
36882
|
);
|
|
36754
36883
|
const handleReply = useCallback(() => {
|
|
36755
|
-
onReply?.(
|
|
36884
|
+
onReply?.(nodeId);
|
|
36756
36885
|
setReplyOpen((open) => !open);
|
|
36757
|
-
}, [
|
|
36886
|
+
}, [nodeId, onReply]);
|
|
36758
36887
|
const handleSubmitReply = useCallback(() => {
|
|
36759
|
-
const
|
|
36760
|
-
if (!
|
|
36761
|
-
if (replyEvent) eventBus.emit(`UI:${replyEvent}`, { parentNodeId:
|
|
36888
|
+
const text = draft.trim();
|
|
36889
|
+
if (!text) return;
|
|
36890
|
+
if (replyEvent) eventBus.emit(`UI:${replyEvent}`, { parentNodeId: nodeId, content: text });
|
|
36762
36891
|
setDraft("");
|
|
36763
36892
|
setReplyOpen(false);
|
|
36764
|
-
}, [
|
|
36893
|
+
}, [nodeId, draft, replyEvent, eventBus]);
|
|
36765
36894
|
const handleCancelReply = useCallback(() => {
|
|
36766
36895
|
setDraft("");
|
|
36767
36896
|
setReplyOpen(false);
|
|
36768
36897
|
}, []);
|
|
36769
36898
|
const handleFlag = useCallback(() => {
|
|
36770
|
-
onFlag?.(
|
|
36771
|
-
if (flagEvent) eventBus.emit(`UI:${flagEvent}`, { nodeId
|
|
36772
|
-
}, [
|
|
36899
|
+
onFlag?.(nodeId);
|
|
36900
|
+
if (flagEvent) eventBus.emit(`UI:${flagEvent}`, { nodeId });
|
|
36901
|
+
}, [nodeId, onFlag, flagEvent, eventBus]);
|
|
36773
36902
|
const handleContinue = useCallback(() => {
|
|
36774
|
-
onContinueThread?.(
|
|
36775
|
-
if (continueThreadEvent) eventBus.emit(`UI:${continueThreadEvent}`, { nodeId
|
|
36776
|
-
}, [
|
|
36903
|
+
onContinueThread?.(nodeId);
|
|
36904
|
+
if (continueThreadEvent) eventBus.emit(`UI:${continueThreadEvent}`, { nodeId });
|
|
36905
|
+
}, [nodeId, onContinueThread, continueThreadEvent, eventBus]);
|
|
36777
36906
|
const handleToggle = useCallback(() => {
|
|
36778
|
-
toggleCollapse(
|
|
36779
|
-
}, [
|
|
36907
|
+
toggleCollapse(nodeId);
|
|
36908
|
+
}, [nodeId, toggleCollapse]);
|
|
36780
36909
|
return /* @__PURE__ */ jsxs(Box, { className: "flex flex-row gap-2 items-stretch min-w-0", children: [
|
|
36781
36910
|
/* @__PURE__ */ jsxs(Box, { className: "flex flex-col items-center flex-shrink-0 w-6", children: [
|
|
36782
36911
|
hasReplies ? /* @__PURE__ */ jsx(
|
|
@@ -36808,25 +36937,25 @@ var init_ReplyTree = __esm({
|
|
|
36808
36937
|
/* @__PURE__ */ jsx(
|
|
36809
36938
|
Avatar,
|
|
36810
36939
|
{
|
|
36811
|
-
src:
|
|
36812
|
-
name:
|
|
36940
|
+
src: authorAvatarUrl,
|
|
36941
|
+
name: authorName,
|
|
36813
36942
|
size: "sm"
|
|
36814
36943
|
}
|
|
36815
36944
|
),
|
|
36816
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body", weight: "semibold", children:
|
|
36817
|
-
/* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", children:
|
|
36945
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body", weight: "semibold", children: authorName }),
|
|
36946
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", children: postedAt })
|
|
36818
36947
|
] }),
|
|
36819
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body", className: "whitespace-pre-wrap break-words", children:
|
|
36948
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body", className: "whitespace-pre-wrap break-words", children: content }),
|
|
36820
36949
|
showActions && /* @__PURE__ */ jsxs(Box, { className: "flex flex-row gap-2 items-center", children: [
|
|
36821
36950
|
/* @__PURE__ */ jsx(
|
|
36822
36951
|
VoteStack,
|
|
36823
36952
|
{
|
|
36824
|
-
count:
|
|
36825
|
-
userVote:
|
|
36953
|
+
count: voteCount ?? 0,
|
|
36954
|
+
userVote: userVote ?? null,
|
|
36826
36955
|
onVote: handleVote,
|
|
36827
36956
|
size: "sm",
|
|
36828
36957
|
variant: "horizontal",
|
|
36829
|
-
label: t("replyTree.voteOnReplyBy", { author:
|
|
36958
|
+
label: t("replyTree.voteOnReplyBy", { author: authorName })
|
|
36830
36959
|
}
|
|
36831
36960
|
),
|
|
36832
36961
|
/* @__PURE__ */ jsx(
|
|
@@ -36836,7 +36965,7 @@ var init_ReplyTree = __esm({
|
|
|
36836
36965
|
size: "sm",
|
|
36837
36966
|
leftIcon: "message-square",
|
|
36838
36967
|
onClick: handleReply,
|
|
36839
|
-
"aria-label": t("replyTree.replyTo", { author:
|
|
36968
|
+
"aria-label": t("replyTree.replyTo", { author: authorName }),
|
|
36840
36969
|
children: t("replyTree.reply")
|
|
36841
36970
|
}
|
|
36842
36971
|
),
|
|
@@ -36847,7 +36976,7 @@ var init_ReplyTree = __esm({
|
|
|
36847
36976
|
size: "sm",
|
|
36848
36977
|
leftIcon: "flag",
|
|
36849
36978
|
onClick: handleFlag,
|
|
36850
|
-
"aria-label": t("replyTree.flagReplyBy", { author:
|
|
36979
|
+
"aria-label": t("replyTree.flagReplyBy", { author: authorName }),
|
|
36851
36980
|
children: t("replyTree.flag")
|
|
36852
36981
|
}
|
|
36853
36982
|
)
|
|
@@ -36859,9 +36988,9 @@ var init_ReplyTree = __esm({
|
|
|
36859
36988
|
inputType: "textarea",
|
|
36860
36989
|
rows: 2,
|
|
36861
36990
|
value: draft,
|
|
36862
|
-
placeholder: t("replyTree.replyToPlaceholder", { author:
|
|
36991
|
+
placeholder: t("replyTree.replyToPlaceholder", { author: authorName }),
|
|
36863
36992
|
onChange: (e) => setDraft(e.target.value),
|
|
36864
|
-
"aria-label": t("replyTree.replyTo", { author:
|
|
36993
|
+
"aria-label": t("replyTree.replyTo", { author: authorName })
|
|
36865
36994
|
}
|
|
36866
36995
|
),
|
|
36867
36996
|
/* @__PURE__ */ jsxs(Box, { className: "flex flex-row gap-2 items-center", children: [
|
|
@@ -36892,7 +37021,7 @@ var init_ReplyTree = __esm({
|
|
|
36892
37021
|
),
|
|
36893
37022
|
children: t("replyTree.continueThread")
|
|
36894
37023
|
}
|
|
36895
|
-
) : /* @__PURE__ */ jsx(Box, { className: "flex flex-col gap-2 mt-1", children:
|
|
37024
|
+
) : /* @__PURE__ */ jsx(Box, { className: "flex flex-col gap-2 mt-1", children: replies.map((child) => /* @__PURE__ */ jsx(
|
|
36896
37025
|
ReplyTreeNode,
|
|
36897
37026
|
{
|
|
36898
37027
|
node: child,
|
|
@@ -38803,8 +38932,8 @@ var init_WizardContainer = __esm({
|
|
|
38803
38932
|
return void 0;
|
|
38804
38933
|
if (typeof controlledStep === "number") return controlledStep;
|
|
38805
38934
|
if (typeof controlledStep === "string") return parseInt(controlledStep, 10);
|
|
38806
|
-
const
|
|
38807
|
-
return isNaN(
|
|
38935
|
+
const num2 = Number(controlledStep);
|
|
38936
|
+
return isNaN(num2) ? void 0 : num2;
|
|
38808
38937
|
})();
|
|
38809
38938
|
const currentStep = normalizedControlledStep !== void 0 ? normalizedControlledStep : internalStep;
|
|
38810
38939
|
const totalSteps = steps.length;
|
|
@@ -40509,7 +40638,7 @@ function DebuggerBoard({
|
|
|
40509
40638
|
}) {
|
|
40510
40639
|
const { emit } = useEventBus();
|
|
40511
40640
|
const { t } = useTranslate();
|
|
40512
|
-
const resolved =
|
|
40641
|
+
const resolved = boardEntity(entity);
|
|
40513
40642
|
const [flaggedLines, setFlaggedLines] = useState(/* @__PURE__ */ new Set());
|
|
40514
40643
|
const [headerError, setHeaderError] = useState(false);
|
|
40515
40644
|
const [submitted, setSubmitted] = useState(false);
|
|
@@ -40527,7 +40656,7 @@ function DebuggerBoard({
|
|
|
40527
40656
|
return next;
|
|
40528
40657
|
});
|
|
40529
40658
|
};
|
|
40530
|
-
const lines = resolved?.lines
|
|
40659
|
+
const lines = Array.isArray(resolved?.lines) ? resolved.lines : [];
|
|
40531
40660
|
const bugLines = lines.filter((l) => l.isBug);
|
|
40532
40661
|
const correctFlags = lines.filter((l) => l.isBug && flaggedLines.has(l.id));
|
|
40533
40662
|
const falseFlags = lines.filter((l) => !l.isBug && flaggedLines.has(l.id));
|
|
@@ -40542,7 +40671,7 @@ function DebuggerBoard({
|
|
|
40542
40671
|
}, [correctFlags.length, bugLines.length, falseFlags.length, attempts, completeEvent, emit]);
|
|
40543
40672
|
const handleReset = () => {
|
|
40544
40673
|
setSubmitted(false);
|
|
40545
|
-
if (attempts >= 2 && resolved?.hint) {
|
|
40674
|
+
if (attempts >= 2 && str(resolved?.hint)) {
|
|
40546
40675
|
setShowHint(true);
|
|
40547
40676
|
}
|
|
40548
40677
|
};
|
|
@@ -40553,24 +40682,28 @@ function DebuggerBoard({
|
|
|
40553
40682
|
setShowHint(false);
|
|
40554
40683
|
};
|
|
40555
40684
|
if (!resolved) return null;
|
|
40685
|
+
const theme = resolved.theme ?? void 0;
|
|
40686
|
+
const themeBackground = theme?.background;
|
|
40687
|
+
const headerImage = str(resolved.headerImage);
|
|
40688
|
+
const hint = str(resolved.hint);
|
|
40556
40689
|
return /* @__PURE__ */ jsx(
|
|
40557
40690
|
Box,
|
|
40558
40691
|
{
|
|
40559
40692
|
className,
|
|
40560
40693
|
style: {
|
|
40561
|
-
backgroundImage:
|
|
40694
|
+
backgroundImage: themeBackground ? `url(${themeBackground})` : void 0,
|
|
40562
40695
|
backgroundSize: "cover",
|
|
40563
40696
|
backgroundPosition: "center"
|
|
40564
40697
|
},
|
|
40565
40698
|
children: /* @__PURE__ */ jsxs(VStack, { gap: "lg", className: "p-4", children: [
|
|
40566
|
-
|
|
40699
|
+
headerImage && !headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 overflow-hidden rounded-container", children: /* @__PURE__ */ jsx("img", { src: headerImage, alt: "", onError: () => setHeaderError(true), className: "w-full h-full object-cover" }) }) : headerImage && headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 rounded-container bg-gradient-to-br from-muted to-accent opacity-60" }) : null,
|
|
40567
40700
|
/* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
|
|
40568
40701
|
/* @__PURE__ */ jsxs(HStack, { gap: "xs", align: "center", children: [
|
|
40569
40702
|
/* @__PURE__ */ jsx(Icon, { icon: Bug, size: "sm" }),
|
|
40570
|
-
/* @__PURE__ */ jsx(Typography, { variant: "h4", weight: "bold", children: resolved.title })
|
|
40703
|
+
/* @__PURE__ */ jsx(Typography, { variant: "h4", weight: "bold", children: str(resolved.title) })
|
|
40571
40704
|
] }),
|
|
40572
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body", children: resolved.description }),
|
|
40573
|
-
/* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-muted-foreground", children: t("debugger.findBugs", { count: String(resolved.bugCount) }) })
|
|
40705
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body", children: str(resolved.description) }),
|
|
40706
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-muted-foreground", children: t("debugger.findBugs", { count: String(num(resolved.bugCount)) }) })
|
|
40574
40707
|
] }) }),
|
|
40575
40708
|
/* @__PURE__ */ jsx(Card, { className: "p-0 overflow-hidden", children: /* @__PURE__ */ jsx(VStack, { gap: "none", children: lines.map((line, i) => {
|
|
40576
40709
|
const isFlagged = flaggedLines.has(line.id);
|
|
@@ -40602,7 +40735,7 @@ function DebuggerBoard({
|
|
|
40602
40735
|
);
|
|
40603
40736
|
}) }) }),
|
|
40604
40737
|
submitted && /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
|
|
40605
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body", weight: "bold", children: allCorrect ? resolved.successMessage
|
|
40738
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body", weight: "bold", children: allCorrect ? str(resolved.successMessage) || t("debugger.allFound") : `${correctFlags.length}/${bugLines.length} ${t("debugger.bugsFound")}` }),
|
|
40606
40739
|
bugLines.map((line) => /* @__PURE__ */ jsxs(HStack, { gap: "xs", align: "start", children: [
|
|
40607
40740
|
/* @__PURE__ */ jsx(
|
|
40608
40741
|
Icon,
|
|
@@ -40618,7 +40751,7 @@ function DebuggerBoard({
|
|
|
40618
40751
|
] })
|
|
40619
40752
|
] }, line.id))
|
|
40620
40753
|
] }) }),
|
|
40621
|
-
showHint &&
|
|
40754
|
+
showHint && hint && /* @__PURE__ */ jsx(Card, { className: "p-4 border-l-4 border-l-warning", children: /* @__PURE__ */ jsx(Typography, { variant: "body", children: hint }) }),
|
|
40622
40755
|
/* @__PURE__ */ jsxs(HStack, { gap: "sm", justify: "center", children: [
|
|
40623
40756
|
!submitted ? /* @__PURE__ */ jsxs(Button, { variant: "primary", onClick: handleSubmit, disabled: flaggedLines.size === 0, children: [
|
|
40624
40757
|
/* @__PURE__ */ jsx(Icon, { icon: Send, size: "sm" }),
|
|
@@ -40637,6 +40770,7 @@ var init_DebuggerBoard = __esm({
|
|
|
40637
40770
|
"components/game/organisms/puzzles/debugger/DebuggerBoard.tsx"() {
|
|
40638
40771
|
init_atoms2();
|
|
40639
40772
|
init_useEventBus();
|
|
40773
|
+
init_boardEntity();
|
|
40640
40774
|
DebuggerBoard.displayName = "DebuggerBoard";
|
|
40641
40775
|
}
|
|
40642
40776
|
});
|
|
@@ -40674,7 +40808,7 @@ function getBadgeVariant(fieldName, value) {
|
|
|
40674
40808
|
return "default";
|
|
40675
40809
|
}
|
|
40676
40810
|
function formatFieldLabel(fieldName) {
|
|
40677
|
-
return fieldName.replace(/([A-Z])/g, " $1").replace(/^./, (
|
|
40811
|
+
return fieldName.replace(/([A-Z])/g, " $1").replace(/^./, (str2) => str2.toUpperCase());
|
|
40678
40812
|
}
|
|
40679
40813
|
function formatFieldValue(value, fieldName) {
|
|
40680
40814
|
if (typeof value === "number") {
|
|
@@ -40693,26 +40827,26 @@ function formatFieldValue(value, fieldName) {
|
|
|
40693
40827
|
}
|
|
40694
40828
|
function renderRichFieldValue(value, fieldName, fieldType) {
|
|
40695
40829
|
if (value === void 0 || value === null) return "\u2014";
|
|
40696
|
-
const
|
|
40830
|
+
const str2 = String(value);
|
|
40697
40831
|
switch (fieldType) {
|
|
40698
40832
|
case "image":
|
|
40699
40833
|
case "url": {
|
|
40700
|
-
if (
|
|
40834
|
+
if (str2.match(/\.(png|jpe?g|gif|svg|webp|avif)(\?|$)/i) || str2.startsWith("data:image/")) {
|
|
40701
40835
|
return /* @__PURE__ */ jsx(Box, { className: "mt-1 max-w-full", children: /* @__PURE__ */ jsx(
|
|
40702
40836
|
"img",
|
|
40703
40837
|
{
|
|
40704
|
-
src:
|
|
40838
|
+
src: str2,
|
|
40705
40839
|
alt: formatFieldLabel(fieldName),
|
|
40706
40840
|
className: "max-w-full max-h-64 rounded-md object-contain",
|
|
40707
40841
|
loading: "lazy"
|
|
40708
40842
|
}
|
|
40709
40843
|
) });
|
|
40710
40844
|
}
|
|
40711
|
-
return
|
|
40845
|
+
return str2;
|
|
40712
40846
|
}
|
|
40713
40847
|
case "markdown":
|
|
40714
40848
|
case "richtext":
|
|
40715
|
-
return /* @__PURE__ */ jsx(Suspense, { fallback: /* @__PURE__ */ jsx(Typography, { variant: "body", className: "break-words", children:
|
|
40849
|
+
return /* @__PURE__ */ jsx(Suspense, { fallback: /* @__PURE__ */ jsx(Typography, { variant: "body", className: "break-words", children: str2 }), children: /* @__PURE__ */ jsx(
|
|
40716
40850
|
Box,
|
|
40717
40851
|
{
|
|
40718
40852
|
className: "prose prose-sm max-w-none",
|
|
@@ -40730,11 +40864,11 @@ function renderRichFieldValue(value, fieldName, fieldType) {
|
|
|
40730
40864
|
"--tw-prose-th-borders": "var(--color-border)",
|
|
40731
40865
|
"--tw-prose-td-borders": "var(--color-border)"
|
|
40732
40866
|
},
|
|
40733
|
-
children: /* @__PURE__ */ jsx(ReactMarkdown2, { children:
|
|
40867
|
+
children: /* @__PURE__ */ jsx(ReactMarkdown2, { children: str2 })
|
|
40734
40868
|
}
|
|
40735
40869
|
) });
|
|
40736
40870
|
case "code":
|
|
40737
|
-
return /* @__PURE__ */ jsx(Box, { className: "mt-1 rounded-md bg-muted p-3 overflow-x-auto", children: /* @__PURE__ */ jsx("pre", { className: "text-sm font-mono whitespace-pre-wrap break-words m-0", children: /* @__PURE__ */ jsx("code", { children:
|
|
40871
|
+
return /* @__PURE__ */ jsx(Box, { className: "mt-1 rounded-md bg-muted p-3 overflow-x-auto", children: /* @__PURE__ */ jsx("pre", { className: "text-sm font-mono whitespace-pre-wrap break-words m-0", children: /* @__PURE__ */ jsx("code", { children: str2 }) }) });
|
|
40738
40872
|
case "html":
|
|
40739
40873
|
return /* @__PURE__ */ jsx(
|
|
40740
40874
|
Box,
|
|
@@ -40754,12 +40888,12 @@ function renderRichFieldValue(value, fieldName, fieldType) {
|
|
|
40754
40888
|
"--tw-prose-th-borders": "var(--color-border)",
|
|
40755
40889
|
"--tw-prose-td-borders": "var(--color-border)"
|
|
40756
40890
|
},
|
|
40757
|
-
children: /* @__PURE__ */ jsx(Typography, { variant: "body", children:
|
|
40891
|
+
children: /* @__PURE__ */ jsx(Typography, { variant: "body", children: str2 })
|
|
40758
40892
|
}
|
|
40759
40893
|
);
|
|
40760
40894
|
case "date":
|
|
40761
40895
|
case "datetime": {
|
|
40762
|
-
const d = new Date(
|
|
40896
|
+
const d = new Date(str2);
|
|
40763
40897
|
if (!isNaN(d.getTime())) {
|
|
40764
40898
|
return d.toLocaleDateString(void 0, {
|
|
40765
40899
|
year: "numeric",
|
|
@@ -40768,7 +40902,7 @@ function renderRichFieldValue(value, fieldName, fieldType) {
|
|
|
40768
40902
|
...fieldType === "datetime" ? { hour: "2-digit", minute: "2-digit" } : {}
|
|
40769
40903
|
});
|
|
40770
40904
|
}
|
|
40771
|
-
return
|
|
40905
|
+
return str2;
|
|
40772
40906
|
}
|
|
40773
40907
|
default:
|
|
40774
40908
|
return formatFieldValue(value, fieldName);
|
|
@@ -41446,6 +41580,40 @@ var init_RuleEditor = __esm({
|
|
|
41446
41580
|
RuleEditor.displayName = "RuleEditor";
|
|
41447
41581
|
}
|
|
41448
41582
|
});
|
|
41583
|
+
|
|
41584
|
+
// components/game/organisms/puzzles/event-handler/puzzleObject.ts
|
|
41585
|
+
function objId(o) {
|
|
41586
|
+
return o.id == null ? "" : String(o.id);
|
|
41587
|
+
}
|
|
41588
|
+
function objName(o) {
|
|
41589
|
+
return o.name == null ? "" : String(o.name);
|
|
41590
|
+
}
|
|
41591
|
+
function objIcon(o) {
|
|
41592
|
+
return o.icon == null ? "" : String(o.icon);
|
|
41593
|
+
}
|
|
41594
|
+
function objStates(o) {
|
|
41595
|
+
return Array.isArray(o.states) ? o.states : [];
|
|
41596
|
+
}
|
|
41597
|
+
function objCurrentState(o) {
|
|
41598
|
+
return o.currentState == null ? "" : String(o.currentState);
|
|
41599
|
+
}
|
|
41600
|
+
function objAvailableEvents(o) {
|
|
41601
|
+
return Array.isArray(o.availableEvents) ? o.availableEvents : [];
|
|
41602
|
+
}
|
|
41603
|
+
function objAvailableActions(o) {
|
|
41604
|
+
return Array.isArray(o.availableActions) ? o.availableActions : [];
|
|
41605
|
+
}
|
|
41606
|
+
function objRules(o) {
|
|
41607
|
+
return Array.isArray(o.rules) ? o.rules : [];
|
|
41608
|
+
}
|
|
41609
|
+
function objMaxRules(o) {
|
|
41610
|
+
const n = Number(o.maxRules);
|
|
41611
|
+
return Number.isFinite(n) && n > 0 ? n : 3;
|
|
41612
|
+
}
|
|
41613
|
+
var init_puzzleObject = __esm({
|
|
41614
|
+
"components/game/organisms/puzzles/event-handler/puzzleObject.ts"() {
|
|
41615
|
+
}
|
|
41616
|
+
});
|
|
41449
41617
|
function ObjectRulePanel({
|
|
41450
41618
|
object,
|
|
41451
41619
|
onRulesChange,
|
|
@@ -41453,55 +41621,63 @@ function ObjectRulePanel({
|
|
|
41453
41621
|
className
|
|
41454
41622
|
}) {
|
|
41455
41623
|
const { t } = useTranslate();
|
|
41456
|
-
const
|
|
41457
|
-
const
|
|
41624
|
+
const id = objId(object);
|
|
41625
|
+
const name = objName(object);
|
|
41626
|
+
const icon = objIcon(object);
|
|
41627
|
+
const states = objStates(object);
|
|
41628
|
+
const currentState = objCurrentState(object);
|
|
41629
|
+
const availableEvents = objAvailableEvents(object);
|
|
41630
|
+
const availableActions = objAvailableActions(object);
|
|
41631
|
+
const rules = objRules(object);
|
|
41632
|
+
const maxRules = objMaxRules(object);
|
|
41633
|
+
const canAdd = rules.length < maxRules;
|
|
41458
41634
|
const handleRuleChange = useCallback((index, updatedRule) => {
|
|
41459
|
-
const newRules = [...
|
|
41635
|
+
const newRules = [...rules];
|
|
41460
41636
|
newRules[index] = updatedRule;
|
|
41461
|
-
onRulesChange(
|
|
41462
|
-
}, [
|
|
41637
|
+
onRulesChange(id, newRules);
|
|
41638
|
+
}, [id, rules, onRulesChange]);
|
|
41463
41639
|
const handleRuleRemove = useCallback((index) => {
|
|
41464
|
-
const newRules =
|
|
41465
|
-
onRulesChange(
|
|
41466
|
-
}, [
|
|
41640
|
+
const newRules = rules.filter((_, i) => i !== index);
|
|
41641
|
+
onRulesChange(id, newRules);
|
|
41642
|
+
}, [id, rules, onRulesChange]);
|
|
41467
41643
|
const handleAddRule = useCallback(() => {
|
|
41468
41644
|
if (!canAdd || disabled) return;
|
|
41469
|
-
const firstEvent =
|
|
41470
|
-
const firstAction =
|
|
41645
|
+
const firstEvent = availableEvents[0]?.value || "";
|
|
41646
|
+
const firstAction = availableActions[0]?.value || "";
|
|
41471
41647
|
const newRule = {
|
|
41472
41648
|
id: `rule-${nextRuleId++}`,
|
|
41473
41649
|
whenEvent: firstEvent,
|
|
41474
41650
|
thenAction: firstAction
|
|
41475
41651
|
};
|
|
41476
|
-
onRulesChange(
|
|
41477
|
-
}, [canAdd, disabled,
|
|
41652
|
+
onRulesChange(id, [...rules, newRule]);
|
|
41653
|
+
}, [canAdd, disabled, id, rules, availableEvents, availableActions, onRulesChange]);
|
|
41478
41654
|
const machine = {
|
|
41479
|
-
name
|
|
41480
|
-
states
|
|
41481
|
-
currentState
|
|
41482
|
-
transitions:
|
|
41483
|
-
from:
|
|
41484
|
-
to:
|
|
41655
|
+
name,
|
|
41656
|
+
states,
|
|
41657
|
+
currentState,
|
|
41658
|
+
transitions: rules.map((r2) => ({
|
|
41659
|
+
from: currentState,
|
|
41660
|
+
to: states.find((s) => s !== currentState) || currentState,
|
|
41485
41661
|
event: r2.whenEvent
|
|
41486
41662
|
}))
|
|
41487
41663
|
};
|
|
41488
41664
|
return /* @__PURE__ */ jsxs(VStack, { className: cn("p-4 rounded-lg bg-card border border-border", className), gap: "sm", children: [
|
|
41489
41665
|
/* @__PURE__ */ jsxs(HStack, { className: "items-center", gap: "sm", children: [
|
|
41490
|
-
/* @__PURE__ */ jsx(Typography, { variant: "h5", children:
|
|
41666
|
+
/* @__PURE__ */ jsx(Typography, { variant: "h5", children: icon }),
|
|
41491
41667
|
/* @__PURE__ */ jsxs(VStack, { gap: "none", children: [
|
|
41492
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body1", className: "text-foreground font-bold", children:
|
|
41493
|
-
/* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-muted-foreground", children: t("eventHandler.state") + ": " +
|
|
41668
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body1", className: "text-foreground font-bold", children: name }),
|
|
41669
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-muted-foreground", children: t("eventHandler.state") + ": " + currentState })
|
|
41494
41670
|
] })
|
|
41495
41671
|
] }),
|
|
41496
41672
|
/* @__PURE__ */ jsx(TraitStateViewer, { trait: machine, variant: "compact", size: "sm" }),
|
|
41497
41673
|
/* @__PURE__ */ jsxs(VStack, { gap: "xs", children: [
|
|
41498
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground font-medium", children: t("eventHandler.rules", { count:
|
|
41499
|
-
|
|
41674
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground font-medium", children: t("eventHandler.rules", { count: rules.length, max: maxRules }) + ":" }),
|
|
41675
|
+
rules.map((rule, i) => /* @__PURE__ */ jsx(
|
|
41500
41676
|
RuleEditor,
|
|
41501
41677
|
{
|
|
41502
41678
|
rule,
|
|
41503
|
-
availableEvents
|
|
41504
|
-
availableActions
|
|
41679
|
+
availableEvents,
|
|
41680
|
+
availableActions,
|
|
41505
41681
|
onChange: (r2) => handleRuleChange(i, r2),
|
|
41506
41682
|
onRemove: () => handleRuleRemove(i),
|
|
41507
41683
|
disabled
|
|
@@ -41519,6 +41695,7 @@ var init_ObjectRulePanel = __esm({
|
|
|
41519
41695
|
init_cn();
|
|
41520
41696
|
init_TraitStateViewer();
|
|
41521
41697
|
init_RuleEditor();
|
|
41698
|
+
init_puzzleObject();
|
|
41522
41699
|
nextRuleId = 1;
|
|
41523
41700
|
ObjectRulePanel.displayName = "ObjectRulePanel";
|
|
41524
41701
|
}
|
|
@@ -41585,11 +41762,11 @@ function EventHandlerBoard({
|
|
|
41585
41762
|
}) {
|
|
41586
41763
|
const { emit } = useEventBus();
|
|
41587
41764
|
const { t } = useTranslate();
|
|
41588
|
-
const resolved =
|
|
41589
|
-
const entityObjects = resolved?.objects
|
|
41590
|
-
const [objects, setObjects] = useState(entityObjects);
|
|
41765
|
+
const resolved = boardEntity(entity);
|
|
41766
|
+
const entityObjects = rows(resolved?.objects);
|
|
41767
|
+
const [objects, setObjects] = useState(() => [...entityObjects]);
|
|
41591
41768
|
const [selectedObjectId, setSelectedObjectId] = useState(
|
|
41592
|
-
entityObjects[0]
|
|
41769
|
+
entityObjects[0] ? objId(entityObjects[0]) : null
|
|
41593
41770
|
);
|
|
41594
41771
|
const [headerError, setHeaderError] = useState(false);
|
|
41595
41772
|
const [playState, setPlayState] = useState("editing");
|
|
@@ -41600,10 +41777,10 @@ function EventHandlerBoard({
|
|
|
41600
41777
|
useEffect(() => () => {
|
|
41601
41778
|
if (timerRef.current) clearTimeout(timerRef.current);
|
|
41602
41779
|
}, []);
|
|
41603
|
-
const selectedObject = objects.find((o) => o
|
|
41780
|
+
const selectedObject = objects.find((o) => objId(o) === selectedObjectId) || null;
|
|
41604
41781
|
const handleRulesChange = useCallback((objectId, rules) => {
|
|
41605
41782
|
setObjects((prev) => prev.map(
|
|
41606
|
-
(o) => o
|
|
41783
|
+
(o) => objId(o) === objectId ? { ...o, rules } : o
|
|
41607
41784
|
));
|
|
41608
41785
|
}, []);
|
|
41609
41786
|
const addLogEntry = useCallback((icon, message, status = "done") => {
|
|
@@ -41617,11 +41794,12 @@ function EventHandlerBoard({
|
|
|
41617
41794
|
setEventLog([]);
|
|
41618
41795
|
const allRules = [];
|
|
41619
41796
|
objects.forEach((obj) => {
|
|
41620
|
-
obj.
|
|
41797
|
+
objRules(obj).forEach((rule) => {
|
|
41621
41798
|
allRules.push({ object: obj, rule });
|
|
41622
41799
|
});
|
|
41623
41800
|
});
|
|
41624
|
-
const triggers = resolved?.triggerEvents
|
|
41801
|
+
const triggers = Array.isArray(resolved?.triggerEvents) ? resolved.triggerEvents : [];
|
|
41802
|
+
const goalEvent = str(resolved?.goalEvent);
|
|
41625
41803
|
const eventQueue = [...triggers];
|
|
41626
41804
|
const firedEvents = /* @__PURE__ */ new Set();
|
|
41627
41805
|
let stepIdx = 0;
|
|
@@ -41650,14 +41828,14 @@ function EventHandlerBoard({
|
|
|
41650
41828
|
addLogEntry("\u26A1", t("eventHandler.noListeners", { event: currentEvent }), "done");
|
|
41651
41829
|
} else {
|
|
41652
41830
|
matching.forEach(({ object, rule }) => {
|
|
41653
|
-
addLogEntry(object
|
|
41831
|
+
addLogEntry(objIcon(object), t("eventHandler.heardEvent", { object: objName(object), event: currentEvent, action: rule.thenAction }), "done");
|
|
41654
41832
|
eventQueue.push(rule.thenAction);
|
|
41655
|
-
if (rule.thenAction ===
|
|
41833
|
+
if (rule.thenAction === goalEvent) {
|
|
41656
41834
|
goalReached = true;
|
|
41657
41835
|
}
|
|
41658
41836
|
});
|
|
41659
41837
|
}
|
|
41660
|
-
if (currentEvent ===
|
|
41838
|
+
if (currentEvent === goalEvent) {
|
|
41661
41839
|
goalReached = true;
|
|
41662
41840
|
}
|
|
41663
41841
|
stepIdx++;
|
|
@@ -41675,65 +41853,75 @@ function EventHandlerBoard({
|
|
|
41675
41853
|
}, []);
|
|
41676
41854
|
const handleReset = useCallback(() => {
|
|
41677
41855
|
if (timerRef.current) clearTimeout(timerRef.current);
|
|
41678
|
-
|
|
41856
|
+
const resetObjects = rows(resolved?.objects);
|
|
41857
|
+
setObjects([...resetObjects]);
|
|
41679
41858
|
setPlayState("editing");
|
|
41680
41859
|
setEventLog([]);
|
|
41681
|
-
setSelectedObjectId(
|
|
41860
|
+
setSelectedObjectId(resetObjects[0] ? objId(resetObjects[0]) : null);
|
|
41682
41861
|
setAttempts(0);
|
|
41683
41862
|
}, [resolved?.objects]);
|
|
41684
41863
|
if (!resolved) return null;
|
|
41685
41864
|
const objectViewers = objects.map((obj) => {
|
|
41865
|
+
const states = objStates(obj);
|
|
41866
|
+
const currentState = objCurrentState(obj);
|
|
41686
41867
|
const machine = {
|
|
41687
|
-
name: obj
|
|
41688
|
-
states
|
|
41689
|
-
currentState
|
|
41690
|
-
transitions: obj.
|
|
41691
|
-
from:
|
|
41692
|
-
to:
|
|
41868
|
+
name: objName(obj),
|
|
41869
|
+
states,
|
|
41870
|
+
currentState,
|
|
41871
|
+
transitions: objRules(obj).map((r2) => ({
|
|
41872
|
+
from: currentState,
|
|
41873
|
+
to: states.find((s) => s !== currentState) || currentState,
|
|
41693
41874
|
event: r2.whenEvent
|
|
41694
41875
|
}))
|
|
41695
41876
|
};
|
|
41696
41877
|
return { obj, machine };
|
|
41697
41878
|
});
|
|
41698
|
-
const
|
|
41879
|
+
const hint = str(resolved.hint);
|
|
41880
|
+
const showHint = attempts >= 3 && hint;
|
|
41881
|
+
const theme = resolved.theme ?? void 0;
|
|
41882
|
+
const themeBackground = theme?.background;
|
|
41883
|
+
const headerImage = str(resolved.headerImage);
|
|
41699
41884
|
const encourageKey = ENCOURAGEMENT_KEYS[Math.min(attempts - 1, ENCOURAGEMENT_KEYS.length - 1)] ?? ENCOURAGEMENT_KEYS[0];
|
|
41700
41885
|
return /* @__PURE__ */ jsxs(
|
|
41701
41886
|
VStack,
|
|
41702
41887
|
{
|
|
41703
41888
|
className: cn("p-4 gap-6", className),
|
|
41704
41889
|
style: {
|
|
41705
|
-
backgroundImage:
|
|
41890
|
+
backgroundImage: themeBackground ? `url(${themeBackground})` : void 0,
|
|
41706
41891
|
backgroundSize: "cover",
|
|
41707
41892
|
backgroundPosition: "center"
|
|
41708
41893
|
},
|
|
41709
41894
|
children: [
|
|
41710
|
-
|
|
41895
|
+
headerImage && !headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 overflow-hidden rounded-container", children: /* @__PURE__ */ jsx("img", { src: headerImage, alt: "", onError: () => setHeaderError(true), className: "w-full h-full object-cover" }) }) : headerImage && headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 rounded-container bg-gradient-to-br from-muted to-accent opacity-60" }) : null,
|
|
41711
41896
|
/* @__PURE__ */ jsxs(VStack, { gap: "xs", children: [
|
|
41712
|
-
/* @__PURE__ */ jsx(Typography, { variant: "h4", className: "text-foreground", children: resolved.title }),
|
|
41713
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground", children: resolved.description }),
|
|
41897
|
+
/* @__PURE__ */ jsx(Typography, { variant: "h4", className: "text-foreground", children: str(resolved.title) }),
|
|
41898
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground", children: str(resolved.description) }),
|
|
41714
41899
|
/* @__PURE__ */ jsxs(HStack, { className: "items-center p-2 rounded bg-primary/10 border border-primary/30", gap: "xs", children: [
|
|
41715
41900
|
/* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-primary font-bold", children: t("game.goal") + ":" }),
|
|
41716
|
-
/* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-foreground", children: resolved.goalCondition })
|
|
41901
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-foreground", children: str(resolved.goalCondition) })
|
|
41717
41902
|
] })
|
|
41718
41903
|
] }),
|
|
41719
41904
|
/* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
|
|
41720
41905
|
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground font-medium", children: t("eventHandler.clickObject") + ":" }),
|
|
41721
|
-
/* @__PURE__ */ jsx(HStack, { className: "flex-wrap", gap: "sm", children: objectViewers.map(({ obj, machine }) =>
|
|
41722
|
-
|
|
41723
|
-
|
|
41724
|
-
|
|
41725
|
-
|
|
41726
|
-
|
|
41727
|
-
|
|
41728
|
-
|
|
41729
|
-
|
|
41730
|
-
|
|
41731
|
-
/* @__PURE__ */
|
|
41732
|
-
|
|
41733
|
-
|
|
41734
|
-
|
|
41735
|
-
|
|
41736
|
-
|
|
41906
|
+
/* @__PURE__ */ jsx(HStack, { className: "flex-wrap", gap: "sm", children: objectViewers.map(({ obj, machine }) => {
|
|
41907
|
+
const oid = objId(obj);
|
|
41908
|
+
return /* @__PURE__ */ jsx(
|
|
41909
|
+
Box,
|
|
41910
|
+
{
|
|
41911
|
+
className: cn(
|
|
41912
|
+
"p-3 rounded-container border-2 cursor-pointer transition-all hover:scale-105",
|
|
41913
|
+
selectedObjectId === oid ? "border-primary bg-primary/10" : "border-border bg-card hover:border-muted-foreground"
|
|
41914
|
+
),
|
|
41915
|
+
onClick: () => setSelectedObjectId(oid),
|
|
41916
|
+
children: /* @__PURE__ */ jsxs(VStack, { gap: "xs", className: "items-center min-w-[120px]", children: [
|
|
41917
|
+
/* @__PURE__ */ jsx(Typography, { variant: "h5", children: objIcon(obj) }),
|
|
41918
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-foreground font-medium", children: objName(obj) }),
|
|
41919
|
+
/* @__PURE__ */ jsx(TraitStateViewer, { trait: machine, variant: "compact", size: "sm" })
|
|
41920
|
+
] })
|
|
41921
|
+
},
|
|
41922
|
+
oid
|
|
41923
|
+
);
|
|
41924
|
+
}) })
|
|
41737
41925
|
] }),
|
|
41738
41926
|
selectedObject && /* @__PURE__ */ jsx(
|
|
41739
41927
|
ObjectRulePanel,
|
|
@@ -41744,12 +41932,12 @@ function EventHandlerBoard({
|
|
|
41744
41932
|
}
|
|
41745
41933
|
),
|
|
41746
41934
|
eventLog.length > 0 && /* @__PURE__ */ jsx(EventLog, { entries: eventLog }),
|
|
41747
|
-
playState === "success" && /* @__PURE__ */ jsx(Box, { className: "p-4 rounded-container bg-success/20 border border-success text-center", children: /* @__PURE__ */ jsx(Typography, { variant: "h5", className: "text-success", children: resolved.successMessage || t("eventHandler.chainComplete") }) }),
|
|
41935
|
+
playState === "success" && /* @__PURE__ */ jsx(Box, { className: "p-4 rounded-container bg-success/20 border border-success text-center", children: /* @__PURE__ */ jsx(Typography, { variant: "h5", className: "text-success", children: str(resolved.successMessage) || t("eventHandler.chainComplete") }) }),
|
|
41748
41936
|
playState === "fail" && /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
|
|
41749
41937
|
/* @__PURE__ */ jsx(Box, { className: "p-4 rounded-container bg-warning/10 border border-warning/30 text-center", children: /* @__PURE__ */ jsx(Typography, { variant: "body1", className: "text-foreground font-medium", children: t(encourageKey) }) }),
|
|
41750
41938
|
showHint && /* @__PURE__ */ jsx(Box, { className: "p-3 rounded-container bg-accent/10 border border-accent/30", children: /* @__PURE__ */ jsxs(HStack, { className: "items-start", gap: "xs", children: [
|
|
41751
41939
|
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-accent font-bold shrink-0", children: "\u{1F4A1} " + t("game.hint") + ":" }),
|
|
41752
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-foreground", children:
|
|
41940
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-foreground", children: hint })
|
|
41753
41941
|
] }) })
|
|
41754
41942
|
] }),
|
|
41755
41943
|
/* @__PURE__ */ jsxs(HStack, { gap: "sm", children: [
|
|
@@ -41777,6 +41965,8 @@ var init_EventHandlerBoard = __esm({
|
|
|
41777
41965
|
init_TraitStateViewer();
|
|
41778
41966
|
init_ObjectRulePanel();
|
|
41779
41967
|
init_EventLog();
|
|
41968
|
+
init_puzzleObject();
|
|
41969
|
+
init_boardEntity();
|
|
41780
41970
|
ENCOURAGEMENT_KEYS = [
|
|
41781
41971
|
"puzzle.tryAgain1",
|
|
41782
41972
|
"puzzle.tryAgain2",
|
|
@@ -41865,7 +42055,10 @@ var init_FeatureGridOrganism = __esm({
|
|
|
41865
42055
|
);
|
|
41866
42056
|
useCallback(
|
|
41867
42057
|
(feature) => {
|
|
41868
|
-
eventBus.emit("UI:FEATURE_CLICK", {
|
|
42058
|
+
eventBus.emit("UI:FEATURE_CLICK", {
|
|
42059
|
+
id: String(feature.id ?? ""),
|
|
42060
|
+
href: String(feature.href ?? "")
|
|
42061
|
+
});
|
|
41869
42062
|
},
|
|
41870
42063
|
[eventBus]
|
|
41871
42064
|
);
|
|
@@ -41875,14 +42068,17 @@ var init_FeatureGridOrganism = __esm({
|
|
|
41875
42068
|
if (error) {
|
|
41876
42069
|
return /* @__PURE__ */ jsx(ErrorState, { message: error.message, className });
|
|
41877
42070
|
}
|
|
41878
|
-
const featureCards = items.map((feature) =>
|
|
41879
|
-
|
|
41880
|
-
|
|
41881
|
-
|
|
41882
|
-
|
|
41883
|
-
|
|
41884
|
-
|
|
41885
|
-
|
|
42071
|
+
const featureCards = items.map((feature) => {
|
|
42072
|
+
const href = feature.href != null ? String(feature.href) : void 0;
|
|
42073
|
+
return {
|
|
42074
|
+
icon: feature.icon != null ? String(feature.icon) : void 0,
|
|
42075
|
+
title: String(feature.title ?? ""),
|
|
42076
|
+
description: String(feature.description ?? ""),
|
|
42077
|
+
href,
|
|
42078
|
+
linkLabel: feature.linkLabel != null ? String(feature.linkLabel) : void 0,
|
|
42079
|
+
variant: href ? "interactive" : "bordered"
|
|
42080
|
+
};
|
|
42081
|
+
});
|
|
41886
42082
|
return /* @__PURE__ */ jsxs(VStack, { gap: "lg", className: cn("w-full", className), children: [
|
|
41887
42083
|
(heading || subtitle) && /* @__PURE__ */ jsxs(VStack, { gap: "sm", align: "center", className: "w-full", children: [
|
|
41888
42084
|
heading && /* @__PURE__ */ jsx(Typography, { variant: "h2", align: "center", children: heading }),
|
|
@@ -43200,22 +43396,24 @@ var init_HeroOrganism = __esm({
|
|
|
43200
43396
|
() => Array.isArray(entity) ? entity[0] : entity && typeof entity === "object" ? entity : void 0,
|
|
43201
43397
|
[entity]
|
|
43202
43398
|
);
|
|
43399
|
+
const primaryAction = resolved?.primaryAction;
|
|
43400
|
+
const secondaryAction = resolved?.secondaryAction;
|
|
43203
43401
|
const handlePrimaryClick = useCallback(() => {
|
|
43204
|
-
if (
|
|
43402
|
+
if (primaryAction) {
|
|
43205
43403
|
eventBus.emit("UI:CTA_PRIMARY", {
|
|
43206
|
-
label:
|
|
43207
|
-
href:
|
|
43404
|
+
label: String(primaryAction.label ?? ""),
|
|
43405
|
+
href: String(primaryAction.href ?? "")
|
|
43208
43406
|
});
|
|
43209
43407
|
}
|
|
43210
|
-
}, [eventBus,
|
|
43408
|
+
}, [eventBus, primaryAction]);
|
|
43211
43409
|
const handleSecondaryClick = useCallback(() => {
|
|
43212
|
-
if (
|
|
43410
|
+
if (secondaryAction) {
|
|
43213
43411
|
eventBus.emit("UI:CTA_SECONDARY", {
|
|
43214
|
-
label:
|
|
43215
|
-
href:
|
|
43412
|
+
label: String(secondaryAction.label ?? ""),
|
|
43413
|
+
href: String(secondaryAction.href ?? "")
|
|
43216
43414
|
});
|
|
43217
43415
|
}
|
|
43218
|
-
}, [eventBus,
|
|
43416
|
+
}, [eventBus, secondaryAction]);
|
|
43219
43417
|
if (isLoading) {
|
|
43220
43418
|
return /* @__PURE__ */ jsx(LoadingState, { message: t("common.loading"), className });
|
|
43221
43419
|
}
|
|
@@ -43225,17 +43423,19 @@ var init_HeroOrganism = __esm({
|
|
|
43225
43423
|
if (!resolved) {
|
|
43226
43424
|
return null;
|
|
43227
43425
|
}
|
|
43426
|
+
const imageRaw = resolved.image;
|
|
43427
|
+
const image = imageRaw ? { src: String(imageRaw.src ?? ""), alt: String(imageRaw.alt ?? "") } : void 0;
|
|
43228
43428
|
return /* @__PURE__ */ jsxs(
|
|
43229
43429
|
HeroSection,
|
|
43230
43430
|
{
|
|
43231
|
-
tag: resolved.tag,
|
|
43232
|
-
title: resolved.title,
|
|
43233
|
-
titleAccent: resolved.titleAccent,
|
|
43234
|
-
subtitle: resolved.subtitle,
|
|
43235
|
-
primaryAction:
|
|
43236
|
-
secondaryAction:
|
|
43237
|
-
installCommand: resolved.installCommand,
|
|
43238
|
-
image
|
|
43431
|
+
tag: resolved.tag != null ? String(resolved.tag) : void 0,
|
|
43432
|
+
title: String(resolved.title ?? ""),
|
|
43433
|
+
titleAccent: resolved.titleAccent != null ? String(resolved.titleAccent) : void 0,
|
|
43434
|
+
subtitle: String(resolved.subtitle ?? ""),
|
|
43435
|
+
primaryAction: primaryAction ? { label: String(primaryAction.label ?? ""), href: String(primaryAction.href ?? "") } : void 0,
|
|
43436
|
+
secondaryAction: secondaryAction ? { label: String(secondaryAction.label ?? ""), href: String(secondaryAction.href ?? "") } : void 0,
|
|
43437
|
+
installCommand: resolved.installCommand != null ? String(resolved.installCommand) : void 0,
|
|
43438
|
+
image,
|
|
43239
43439
|
imagePosition: resolved.imagePosition,
|
|
43240
43440
|
background: resolved.background,
|
|
43241
43441
|
className: cn(className),
|
|
@@ -43244,8 +43444,8 @@ var init_HeroOrganism = __esm({
|
|
|
43244
43444
|
/* @__PURE__ */ jsx(
|
|
43245
43445
|
_HeroClickInterceptor,
|
|
43246
43446
|
{
|
|
43247
|
-
hasPrimary: !!
|
|
43248
|
-
hasSecondary: !!
|
|
43447
|
+
hasPrimary: !!primaryAction,
|
|
43448
|
+
hasSecondary: !!secondaryAction,
|
|
43249
43449
|
onPrimaryClick: handlePrimaryClick,
|
|
43250
43450
|
onSecondaryClick: handleSecondaryClick
|
|
43251
43451
|
}
|
|
@@ -43474,7 +43674,7 @@ function formatValue3(value, fieldName) {
|
|
|
43474
43674
|
return String(value);
|
|
43475
43675
|
}
|
|
43476
43676
|
function formatFieldLabel2(fieldName) {
|
|
43477
|
-
return fieldName.replace(/([A-Z])/g, " $1").replace(/^./, (
|
|
43677
|
+
return fieldName.replace(/([A-Z])/g, " $1").replace(/^./, (str2) => str2.toUpperCase()).replace(/Id$/, "").trim();
|
|
43478
43678
|
}
|
|
43479
43679
|
var STATUS_STYLES2, StatusBadge, ProgressIndicator, List3;
|
|
43480
43680
|
var init_List = __esm({
|
|
@@ -44321,20 +44521,22 @@ function NegotiatorBoard({
|
|
|
44321
44521
|
}) {
|
|
44322
44522
|
const { emit } = useEventBus();
|
|
44323
44523
|
const { t } = useTranslate();
|
|
44324
|
-
const resolved =
|
|
44524
|
+
const resolved = boardEntity(entity);
|
|
44325
44525
|
const [history, setHistory] = useState([]);
|
|
44326
44526
|
const [headerError, setHeaderError] = useState(false);
|
|
44327
44527
|
const [showHint, setShowHint] = useState(false);
|
|
44528
|
+
const totalRounds = num(resolved?.totalRounds);
|
|
44529
|
+
const targetScore = num(resolved?.targetScore);
|
|
44328
44530
|
const currentRound = history.length;
|
|
44329
|
-
const isComplete = currentRound >=
|
|
44531
|
+
const isComplete = currentRound >= totalRounds;
|
|
44330
44532
|
const playerTotal = history.reduce((s, r2) => s + r2.playerPayoff, 0);
|
|
44331
44533
|
const opponentTotal = history.reduce((s, r2) => s + r2.opponentPayoff, 0);
|
|
44332
|
-
const won = isComplete && playerTotal >=
|
|
44333
|
-
const actions = resolved?.actions
|
|
44334
|
-
const payoffMatrix = resolved?.payoffMatrix
|
|
44534
|
+
const won = isComplete && playerTotal >= targetScore;
|
|
44535
|
+
const actions = Array.isArray(resolved?.actions) ? resolved.actions : [];
|
|
44536
|
+
const payoffMatrix = Array.isArray(resolved?.payoffMatrix) ? resolved.payoffMatrix : [];
|
|
44335
44537
|
const handleAction = useCallback((actionId) => {
|
|
44336
44538
|
if (isComplete) return;
|
|
44337
|
-
const opponentAction = getOpponentAction(resolved?.opponentStrategy
|
|
44539
|
+
const opponentAction = getOpponentAction(str(resolved?.opponentStrategy) || "random", actions, history);
|
|
44338
44540
|
const payoff = payoffMatrix.find(
|
|
44339
44541
|
(p2) => p2.playerAction === actionId && p2.opponentAction === opponentAction
|
|
44340
44542
|
);
|
|
@@ -44347,42 +44549,46 @@ function NegotiatorBoard({
|
|
|
44347
44549
|
};
|
|
44348
44550
|
const newHistory = [...history, result];
|
|
44349
44551
|
setHistory(newHistory);
|
|
44350
|
-
if (newHistory.length >=
|
|
44552
|
+
if (newHistory.length >= totalRounds) {
|
|
44351
44553
|
const total = newHistory.reduce((s, r2) => s + r2.playerPayoff, 0);
|
|
44352
|
-
if (total >=
|
|
44554
|
+
if (total >= targetScore) {
|
|
44353
44555
|
emit(`UI:${completeEvent}`, { success: true, score: total });
|
|
44354
44556
|
}
|
|
44355
|
-
if (newHistory.length >= 3 && resolved?.hint) {
|
|
44557
|
+
if (newHistory.length >= 3 && str(resolved?.hint)) {
|
|
44356
44558
|
setShowHint(true);
|
|
44357
44559
|
}
|
|
44358
44560
|
}
|
|
44359
|
-
}, [isComplete, resolved, actions, payoffMatrix, history, currentRound, completeEvent, emit]);
|
|
44561
|
+
}, [isComplete, resolved, totalRounds, targetScore, actions, payoffMatrix, history, currentRound, completeEvent, emit]);
|
|
44360
44562
|
const handleReset = () => {
|
|
44361
44563
|
setHistory([]);
|
|
44362
44564
|
setShowHint(false);
|
|
44363
44565
|
};
|
|
44364
44566
|
const getActionLabel = (id) => actions.find((a) => a.id === id)?.label ?? id;
|
|
44365
44567
|
if (!resolved) return null;
|
|
44568
|
+
const theme = resolved.theme ?? void 0;
|
|
44569
|
+
const themeBackground = theme?.background;
|
|
44570
|
+
const headerImage = str(resolved.headerImage);
|
|
44571
|
+
const hint = str(resolved.hint);
|
|
44366
44572
|
return /* @__PURE__ */ jsx(
|
|
44367
44573
|
Box,
|
|
44368
44574
|
{
|
|
44369
44575
|
className,
|
|
44370
44576
|
style: {
|
|
44371
|
-
backgroundImage:
|
|
44577
|
+
backgroundImage: themeBackground ? `url(${themeBackground})` : void 0,
|
|
44372
44578
|
backgroundSize: "cover",
|
|
44373
44579
|
backgroundPosition: "center"
|
|
44374
44580
|
},
|
|
44375
44581
|
children: /* @__PURE__ */ jsxs(VStack, { gap: "lg", className: "p-4", children: [
|
|
44376
|
-
|
|
44582
|
+
headerImage && !headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 overflow-hidden rounded-container", children: /* @__PURE__ */ jsx("img", { src: headerImage, alt: "", onError: () => setHeaderError(true), className: "w-full h-full object-cover" }) }) : headerImage && headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 rounded-container bg-gradient-to-br from-muted to-accent opacity-60" }) : null,
|
|
44377
44583
|
/* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
|
|
44378
|
-
/* @__PURE__ */ jsx(Typography, { variant: "h4", weight: "bold", children: resolved.title }),
|
|
44379
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body", children: resolved.description }),
|
|
44584
|
+
/* @__PURE__ */ jsx(Typography, { variant: "h4", weight: "bold", children: str(resolved.title) }),
|
|
44585
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body", children: str(resolved.description) }),
|
|
44380
44586
|
/* @__PURE__ */ jsxs(HStack, { gap: "md", children: [
|
|
44381
|
-
/* @__PURE__ */ jsx(Badge, { size: "sm", children: t("negotiator.round", { current: String(currentRound), total: String(
|
|
44587
|
+
/* @__PURE__ */ jsx(Badge, { size: "sm", children: t("negotiator.round", { current: String(currentRound), total: String(totalRounds) }) }),
|
|
44382
44588
|
/* @__PURE__ */ jsxs(Badge, { size: "sm", children: [
|
|
44383
44589
|
t("negotiator.target"),
|
|
44384
44590
|
": ",
|
|
44385
|
-
|
|
44591
|
+
targetScore
|
|
44386
44592
|
] })
|
|
44387
44593
|
] })
|
|
44388
44594
|
] }) }),
|
|
@@ -44431,16 +44637,16 @@ function NegotiatorBoard({
|
|
|
44431
44637
|
] }) }),
|
|
44432
44638
|
isComplete && /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", align: "center", children: [
|
|
44433
44639
|
/* @__PURE__ */ jsx(Icon, { icon: CheckCircle, size: "lg", className: won ? "text-success" : "text-error" }),
|
|
44434
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body", weight: "bold", children: won ? resolved.successMessage
|
|
44640
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body", weight: "bold", children: won ? str(resolved.successMessage) || t("negotiator.success") : str(resolved.failMessage) || t("negotiator.failed") }),
|
|
44435
44641
|
/* @__PURE__ */ jsxs(Typography, { variant: "caption", className: "text-muted-foreground", children: [
|
|
44436
44642
|
t("negotiator.finalScore"),
|
|
44437
44643
|
": ",
|
|
44438
44644
|
playerTotal,
|
|
44439
44645
|
"/",
|
|
44440
|
-
|
|
44646
|
+
targetScore
|
|
44441
44647
|
] })
|
|
44442
44648
|
] }) }),
|
|
44443
|
-
showHint &&
|
|
44649
|
+
showHint && hint && !won && /* @__PURE__ */ jsx(Card, { className: "p-4 border-l-4 border-l-warning", children: /* @__PURE__ */ jsx(Typography, { variant: "body", children: hint }) }),
|
|
44444
44650
|
isComplete && !won && /* @__PURE__ */ jsx(HStack, { justify: "center", children: /* @__PURE__ */ jsx(Button, { variant: "primary", onClick: handleReset, children: t("negotiator.playAgain") }) })
|
|
44445
44651
|
] })
|
|
44446
44652
|
}
|
|
@@ -44450,6 +44656,7 @@ var init_NegotiatorBoard = __esm({
|
|
|
44450
44656
|
"components/game/organisms/puzzles/negotiator/NegotiatorBoard.tsx"() {
|
|
44451
44657
|
init_atoms2();
|
|
44452
44658
|
init_useEventBus();
|
|
44659
|
+
init_boardEntity();
|
|
44453
44660
|
NegotiatorBoard.displayName = "NegotiatorBoard";
|
|
44454
44661
|
}
|
|
44455
44662
|
});
|
|
@@ -44485,13 +44692,13 @@ var init_PricingOrganism = __esm({
|
|
|
44485
44692
|
return /* @__PURE__ */ jsx(ErrorState, { message: error.message, className });
|
|
44486
44693
|
}
|
|
44487
44694
|
const plans = items.map((plan) => ({
|
|
44488
|
-
name: plan.name,
|
|
44489
|
-
price: plan.price,
|
|
44490
|
-
description: plan.description,
|
|
44491
|
-
features: plan.features,
|
|
44492
|
-
action: { label: plan.actionLabel, href: plan.actionHref },
|
|
44493
|
-
highlighted: plan.highlighted,
|
|
44494
|
-
badge: plan.badge
|
|
44695
|
+
name: String(plan.name ?? ""),
|
|
44696
|
+
price: String(plan.price ?? ""),
|
|
44697
|
+
description: plan.description != null ? String(plan.description) : void 0,
|
|
44698
|
+
features: (plan.features ?? []).map((f3) => String(f3)),
|
|
44699
|
+
action: { label: String(plan.actionLabel ?? ""), href: String(plan.actionHref ?? "") },
|
|
44700
|
+
highlighted: Boolean(plan.highlighted),
|
|
44701
|
+
badge: plan.badge != null ? String(plan.badge) : void 0
|
|
44495
44702
|
}));
|
|
44496
44703
|
return /* @__PURE__ */ jsxs(VStack, { gap: "lg", className: cn("w-full", className), children: [
|
|
44497
44704
|
(heading || subtitle) && /* @__PURE__ */ jsxs(VStack, { gap: "sm", align: "center", className: "w-full", children: [
|
|
@@ -46581,16 +46788,20 @@ function SequencerBoard({
|
|
|
46581
46788
|
}) {
|
|
46582
46789
|
const { emit } = useEventBus();
|
|
46583
46790
|
const { t } = useTranslate();
|
|
46584
|
-
const resolved =
|
|
46791
|
+
const resolved = boardEntity(entity);
|
|
46792
|
+
const maxSlots = num(resolved?.maxSlots);
|
|
46793
|
+
const solutions = Array.isArray(resolved?.solutions) ? resolved.solutions : [];
|
|
46794
|
+
const availableActions = Array.isArray(resolved?.availableActions) ? resolved.availableActions : [];
|
|
46795
|
+
const allowDuplicates = resolved?.allowDuplicates !== false;
|
|
46585
46796
|
const [headerError, setHeaderError] = useState(false);
|
|
46586
46797
|
const [slots, setSlots] = useState(
|
|
46587
|
-
() => Array.from({ length:
|
|
46798
|
+
() => Array.from({ length: maxSlots }, () => void 0)
|
|
46588
46799
|
);
|
|
46589
46800
|
const [playState, setPlayState] = useState("idle");
|
|
46590
46801
|
const [currentStep, setCurrentStep] = useState(-1);
|
|
46591
46802
|
const [attempts, setAttempts] = useState(0);
|
|
46592
46803
|
const [slotFeedback, setSlotFeedback] = useState(
|
|
46593
|
-
() => Array.from({ length:
|
|
46804
|
+
() => Array.from({ length: maxSlots }, () => null)
|
|
46594
46805
|
);
|
|
46595
46806
|
const timerRef = useRef(null);
|
|
46596
46807
|
useEffect(() => () => {
|
|
@@ -46624,17 +46835,17 @@ function SequencerBoard({
|
|
|
46624
46835
|
}, [emit]);
|
|
46625
46836
|
const handleReset = useCallback(() => {
|
|
46626
46837
|
if (timerRef.current) clearTimeout(timerRef.current);
|
|
46627
|
-
setSlots(Array.from({ length:
|
|
46838
|
+
setSlots(Array.from({ length: maxSlots }, () => void 0));
|
|
46628
46839
|
setPlayState("idle");
|
|
46629
46840
|
setCurrentStep(-1);
|
|
46630
46841
|
setAttempts(0);
|
|
46631
|
-
setSlotFeedback(Array.from({ length:
|
|
46632
|
-
}, [
|
|
46842
|
+
setSlotFeedback(Array.from({ length: maxSlots }, () => null));
|
|
46843
|
+
}, [maxSlots]);
|
|
46633
46844
|
const filledSlots = slots.filter((s) => !!s);
|
|
46634
46845
|
const canPlay = filledSlots.length > 0 && playState === "idle";
|
|
46635
46846
|
const handlePlay = useCallback(() => {
|
|
46636
46847
|
if (!canPlay) return;
|
|
46637
|
-
setSlotFeedback(Array.from({ length:
|
|
46848
|
+
setSlotFeedback(Array.from({ length: maxSlots }, () => null));
|
|
46638
46849
|
emit("UI:PLAY_SOUND", { key: "confirm" });
|
|
46639
46850
|
const sequence = slots.map((s) => s?.id || "");
|
|
46640
46851
|
if (playEvent) {
|
|
@@ -46645,10 +46856,10 @@ function SequencerBoard({
|
|
|
46645
46856
|
let step = 0;
|
|
46646
46857
|
const advance = () => {
|
|
46647
46858
|
step++;
|
|
46648
|
-
if (step >=
|
|
46859
|
+
if (step >= maxSlots) {
|
|
46649
46860
|
const playerSeq = slots.map((s) => s?.id);
|
|
46650
46861
|
const playerIds = slots.filter(Boolean).map((s) => s?.id || "");
|
|
46651
|
-
const success =
|
|
46862
|
+
const success = solutions.some(
|
|
46652
46863
|
(sol) => sol.length === playerIds.length && sol.every((id, i) => id === playerIds[i])
|
|
46653
46864
|
);
|
|
46654
46865
|
if (success) {
|
|
@@ -46660,7 +46871,7 @@ function SequencerBoard({
|
|
|
46660
46871
|
}
|
|
46661
46872
|
} else {
|
|
46662
46873
|
setAttempts((prev) => prev + 1);
|
|
46663
|
-
const feedback = computeSlotFeedback(playerSeq,
|
|
46874
|
+
const feedback = computeSlotFeedback(playerSeq, solutions);
|
|
46664
46875
|
setSlotFeedback(feedback);
|
|
46665
46876
|
setPlayState("idle");
|
|
46666
46877
|
setCurrentStep(-1);
|
|
@@ -46678,10 +46889,10 @@ function SequencerBoard({
|
|
|
46678
46889
|
}
|
|
46679
46890
|
};
|
|
46680
46891
|
timerRef.current = setTimeout(advance, stepDurationMs);
|
|
46681
|
-
}, [canPlay, slots,
|
|
46892
|
+
}, [canPlay, slots, maxSlots, solutions, stepDurationMs, playEvent, completeEvent, emit]);
|
|
46682
46893
|
const machine = {
|
|
46683
|
-
name: resolved?.title
|
|
46684
|
-
description: resolved?.description
|
|
46894
|
+
name: str(resolved?.title),
|
|
46895
|
+
description: str(resolved?.description),
|
|
46685
46896
|
states: slots.map((s, i) => stepLabel(s, i)),
|
|
46686
46897
|
currentState: currentStep >= 0 ? stepLabel(slots[currentStep], currentStep) : "__idle__",
|
|
46687
46898
|
transitions: slots.slice(0, -1).map((s, i) => ({
|
|
@@ -46690,37 +46901,41 @@ function SequencerBoard({
|
|
|
46690
46901
|
event: "NEXT"
|
|
46691
46902
|
}))
|
|
46692
46903
|
};
|
|
46693
|
-
const usedIds =
|
|
46694
|
-
const
|
|
46904
|
+
const usedIds = !allowDuplicates ? slots.filter(Boolean).map((s) => s?.id || "") : [];
|
|
46905
|
+
const hint = str(resolved?.hint);
|
|
46906
|
+
const showHint = attempts >= 3 && !!hint;
|
|
46695
46907
|
const hasFeedback = slotFeedback.some((f3) => f3 !== null);
|
|
46696
46908
|
const correctCount = slotFeedback.filter((f3) => f3 === "correct").length;
|
|
46697
46909
|
const encourageKey = ENCOURAGEMENT_KEYS2[Math.min(attempts - 1, ENCOURAGEMENT_KEYS2.length - 1)] ?? ENCOURAGEMENT_KEYS2[0];
|
|
46698
46910
|
if (!resolved) return null;
|
|
46911
|
+
const theme = resolved.theme ?? void 0;
|
|
46912
|
+
const themeBackground = theme?.background;
|
|
46913
|
+
const headerImage = str(resolved.headerImage);
|
|
46699
46914
|
return /* @__PURE__ */ jsxs(
|
|
46700
46915
|
VStack,
|
|
46701
46916
|
{
|
|
46702
46917
|
className: cn("p-4 gap-6", className),
|
|
46703
46918
|
style: {
|
|
46704
|
-
backgroundImage:
|
|
46919
|
+
backgroundImage: themeBackground ? `url(${themeBackground})` : void 0,
|
|
46705
46920
|
backgroundSize: "cover",
|
|
46706
46921
|
backgroundPosition: "center"
|
|
46707
46922
|
},
|
|
46708
46923
|
children: [
|
|
46709
|
-
|
|
46924
|
+
headerImage && !headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 overflow-hidden rounded-container", children: /* @__PURE__ */ jsx("img", { src: headerImage, alt: "", onError: () => setHeaderError(true), className: "w-full h-full object-cover" }) }) : headerImage && headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 rounded-container bg-gradient-to-br from-muted to-accent opacity-60" }) : null,
|
|
46710
46925
|
/* @__PURE__ */ jsxs(VStack, { gap: "xs", children: [
|
|
46711
|
-
/* @__PURE__ */ jsx(Typography, { variant: "h4", className: "text-foreground", children: resolved.title }),
|
|
46712
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground", children: resolved.description })
|
|
46926
|
+
/* @__PURE__ */ jsx(Typography, { variant: "h4", className: "text-foreground", children: str(resolved.title) }),
|
|
46927
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground", children: str(resolved.description) })
|
|
46713
46928
|
] }),
|
|
46714
46929
|
showHint && /* @__PURE__ */ jsx(Box, { className: "p-3 rounded-container bg-accent/10 border border-accent/30", children: /* @__PURE__ */ jsxs(HStack, { className: "items-start", gap: "xs", children: [
|
|
46715
46930
|
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-accent font-bold shrink-0", children: "\u{1F4A1} " + t("game.hint") + ":" }),
|
|
46716
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-foreground", children:
|
|
46931
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-foreground", children: hint })
|
|
46717
46932
|
] }) }),
|
|
46718
46933
|
filledSlots.length > 0 && /* @__PURE__ */ jsx(TraitStateViewer, { trait: machine, variant: "linear", size: "md" }),
|
|
46719
46934
|
/* @__PURE__ */ jsxs(VStack, { gap: "xs", children: [
|
|
46720
46935
|
/* @__PURE__ */ jsxs(HStack, { className: "items-center justify-between", children: [
|
|
46721
46936
|
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground font-medium", children: t("sequencer.yourSequence") + ":" }),
|
|
46722
46937
|
hasFeedback && playState === "idle" && /* @__PURE__ */ jsxs(Typography, { variant: "caption", className: "text-muted-foreground", children: [
|
|
46723
|
-
`${correctCount}/${
|
|
46938
|
+
`${correctCount}/${maxSlots} `,
|
|
46724
46939
|
"\u2705"
|
|
46725
46940
|
] })
|
|
46726
46941
|
] }),
|
|
@@ -46728,7 +46943,7 @@ function SequencerBoard({
|
|
|
46728
46943
|
SequenceBar,
|
|
46729
46944
|
{
|
|
46730
46945
|
slots,
|
|
46731
|
-
maxSlots
|
|
46946
|
+
maxSlots,
|
|
46732
46947
|
onSlotDrop: handleSlotDrop,
|
|
46733
46948
|
onSlotRemove: handleSlotRemove,
|
|
46734
46949
|
playing: playState === "playing",
|
|
@@ -46742,15 +46957,15 @@ function SequencerBoard({
|
|
|
46742
46957
|
playState !== "playing" && /* @__PURE__ */ jsx(
|
|
46743
46958
|
ActionPalette,
|
|
46744
46959
|
{
|
|
46745
|
-
actions:
|
|
46960
|
+
actions: availableActions,
|
|
46746
46961
|
usedActionIds: usedIds,
|
|
46747
|
-
allowDuplicates
|
|
46962
|
+
allowDuplicates,
|
|
46748
46963
|
categoryColors,
|
|
46749
46964
|
label: t("sequencer.dragActions")
|
|
46750
46965
|
}
|
|
46751
46966
|
),
|
|
46752
46967
|
hasFeedback && playState === "idle" && attempts > 0 && /* @__PURE__ */ jsx(Box, { className: "p-3 rounded-container bg-warning/10 border border-warning/30 text-center", children: /* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-foreground", children: t(encourageKey) }) }),
|
|
46753
|
-
playState === "success" && /* @__PURE__ */ jsx(Box, { className: "p-4 rounded-container bg-success/20 border border-success text-center", children: /* @__PURE__ */ jsx(Typography, { variant: "h5", className: "text-success", children: resolved.successMessage || t("sequencer.levelComplete") }) }),
|
|
46968
|
+
playState === "success" && /* @__PURE__ */ jsx(Box, { className: "p-4 rounded-container bg-success/20 border border-success text-center", children: /* @__PURE__ */ jsx(Typography, { variant: "h5", className: "text-success", children: str(resolved.successMessage) || t("sequencer.levelComplete") }) }),
|
|
46754
46969
|
/* @__PURE__ */ jsxs(HStack, { gap: "sm", children: [
|
|
46755
46970
|
/* @__PURE__ */ jsx(
|
|
46756
46971
|
Button,
|
|
@@ -46774,6 +46989,7 @@ var init_SequencerBoard = __esm({
|
|
|
46774
46989
|
init_cn();
|
|
46775
46990
|
init_useEventBus();
|
|
46776
46991
|
init_TraitStateViewer();
|
|
46992
|
+
init_boardEntity();
|
|
46777
46993
|
init_SequenceBar();
|
|
46778
46994
|
init_ActionPalette();
|
|
46779
46995
|
ENCOURAGEMENT_KEYS2 = [
|
|
@@ -46823,18 +47039,21 @@ var init_ShowcaseOrganism = __esm({
|
|
|
46823
47039
|
heading && /* @__PURE__ */ jsx(Typography, { variant: "h2", align: "center", children: heading }),
|
|
46824
47040
|
subtitle && /* @__PURE__ */ jsx(Typography, { variant: "body1", color: "muted", align: "center", className: "max-w-2xl", children: subtitle })
|
|
46825
47041
|
] }),
|
|
46826
|
-
/* @__PURE__ */ jsx(SimpleGrid, { cols: columns, gap: "lg", children: items.map((item) =>
|
|
46827
|
-
|
|
46828
|
-
|
|
46829
|
-
|
|
46830
|
-
|
|
46831
|
-
|
|
46832
|
-
|
|
46833
|
-
|
|
46834
|
-
|
|
46835
|
-
|
|
46836
|
-
|
|
46837
|
-
|
|
47042
|
+
/* @__PURE__ */ jsx(SimpleGrid, { cols: columns, gap: "lg", children: items.map((item) => {
|
|
47043
|
+
const imageRaw = item.image;
|
|
47044
|
+
return /* @__PURE__ */ jsx(
|
|
47045
|
+
ShowcaseCard,
|
|
47046
|
+
{
|
|
47047
|
+
title: String(item.title ?? ""),
|
|
47048
|
+
description: item.description != null ? String(item.description) : void 0,
|
|
47049
|
+
image: { src: String(imageRaw?.src ?? ""), alt: String(imageRaw?.alt ?? "") },
|
|
47050
|
+
href: item.href != null ? String(item.href) : void 0,
|
|
47051
|
+
badge: item.badge != null ? String(item.badge) : void 0,
|
|
47052
|
+
accentColor: item.accentColor != null ? String(item.accentColor) : void 0
|
|
47053
|
+
},
|
|
47054
|
+
String(item.id ?? "")
|
|
47055
|
+
);
|
|
47056
|
+
}) })
|
|
46838
47057
|
] });
|
|
46839
47058
|
};
|
|
46840
47059
|
ShowcaseOrganism.displayName = "ShowcaseOrganism";
|
|
@@ -47202,8 +47421,8 @@ function SimulatorBoard({
|
|
|
47202
47421
|
}) {
|
|
47203
47422
|
const { emit } = useEventBus();
|
|
47204
47423
|
const { t } = useTranslate();
|
|
47205
|
-
const resolved =
|
|
47206
|
-
const parameters = resolved?.parameters
|
|
47424
|
+
const resolved = boardEntity(entity);
|
|
47425
|
+
const parameters = Array.isArray(resolved?.parameters) ? resolved.parameters : [];
|
|
47207
47426
|
const [values, setValues] = useState(() => {
|
|
47208
47427
|
const init = {};
|
|
47209
47428
|
for (const p2 of parameters) {
|
|
@@ -47217,15 +47436,15 @@ function SimulatorBoard({
|
|
|
47217
47436
|
const [showHint, setShowHint] = useState(false);
|
|
47218
47437
|
const computeOutput = useCallback((params) => {
|
|
47219
47438
|
try {
|
|
47220
|
-
const fn = new Function("params", `return (${resolved?.computeExpression})`);
|
|
47439
|
+
const fn = new Function("params", `return (${str(resolved?.computeExpression)})`);
|
|
47221
47440
|
return fn(params);
|
|
47222
47441
|
} catch {
|
|
47223
47442
|
return 0;
|
|
47224
47443
|
}
|
|
47225
47444
|
}, [resolved?.computeExpression]);
|
|
47226
47445
|
const output = useMemo(() => computeOutput(values) ?? 0, [computeOutput, values]);
|
|
47227
|
-
const targetValue = resolved?.targetValue
|
|
47228
|
-
const targetTolerance = resolved?.targetTolerance
|
|
47446
|
+
const targetValue = num(resolved?.targetValue);
|
|
47447
|
+
const targetTolerance = num(resolved?.targetTolerance);
|
|
47229
47448
|
const isCorrect = Math.abs(output - targetValue) <= targetTolerance;
|
|
47230
47449
|
const handleParameterChange = (id, value) => {
|
|
47231
47450
|
if (submitted) return;
|
|
@@ -47240,7 +47459,7 @@ function SimulatorBoard({
|
|
|
47240
47459
|
};
|
|
47241
47460
|
const handleReset = () => {
|
|
47242
47461
|
setSubmitted(false);
|
|
47243
|
-
if (attempts >= 2 && resolved?.hint) {
|
|
47462
|
+
if (attempts >= 2 && str(resolved?.hint)) {
|
|
47244
47463
|
setShowHint(true);
|
|
47245
47464
|
}
|
|
47246
47465
|
};
|
|
@@ -47255,20 +47474,26 @@ function SimulatorBoard({
|
|
|
47255
47474
|
setShowHint(false);
|
|
47256
47475
|
};
|
|
47257
47476
|
if (!resolved) return null;
|
|
47477
|
+
const theme = resolved.theme ?? void 0;
|
|
47478
|
+
const themeBackground = theme?.background;
|
|
47479
|
+
const headerImage = str(resolved.headerImage);
|
|
47480
|
+
const hint = str(resolved.hint);
|
|
47481
|
+
const outputLabel = str(resolved.outputLabel);
|
|
47482
|
+
const outputUnit = str(resolved.outputUnit);
|
|
47258
47483
|
return /* @__PURE__ */ jsx(
|
|
47259
47484
|
Box,
|
|
47260
47485
|
{
|
|
47261
47486
|
className,
|
|
47262
47487
|
style: {
|
|
47263
|
-
backgroundImage:
|
|
47488
|
+
backgroundImage: themeBackground ? `url(${themeBackground})` : void 0,
|
|
47264
47489
|
backgroundSize: "cover",
|
|
47265
47490
|
backgroundPosition: "center"
|
|
47266
47491
|
},
|
|
47267
47492
|
children: /* @__PURE__ */ jsxs(VStack, { gap: "lg", className: "p-4", children: [
|
|
47268
|
-
|
|
47493
|
+
headerImage && !headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 overflow-hidden rounded-container", children: /* @__PURE__ */ jsx("img", { src: headerImage, alt: "", onError: () => setHeaderError(true), className: "w-full h-full object-cover" }) }) : headerImage && headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 rounded-container bg-gradient-to-br from-muted to-accent opacity-60" }) : null,
|
|
47269
47494
|
/* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
|
|
47270
|
-
/* @__PURE__ */ jsx(Typography, { variant: "h4", weight: "bold", children: resolved.title }),
|
|
47271
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body", children: resolved.description })
|
|
47495
|
+
/* @__PURE__ */ jsx(Typography, { variant: "h4", weight: "bold", children: str(resolved.title) }),
|
|
47496
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body", children: str(resolved.description) })
|
|
47272
47497
|
] }) }),
|
|
47273
47498
|
/* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "md", children: [
|
|
47274
47499
|
/* @__PURE__ */ jsx(Typography, { variant: "small", weight: "bold", className: "uppercase tracking-wider text-muted-foreground", children: t("simulator.parameters") }),
|
|
@@ -47309,28 +47534,28 @@ function SimulatorBoard({
|
|
|
47309
47534
|
] }, param.id))
|
|
47310
47535
|
] }) }),
|
|
47311
47536
|
/* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", align: "center", children: [
|
|
47312
|
-
/* @__PURE__ */ jsx(Typography, { variant: "small", weight: "bold", className: "uppercase tracking-wider text-muted-foreground", children:
|
|
47537
|
+
/* @__PURE__ */ jsx(Typography, { variant: "small", weight: "bold", className: "uppercase tracking-wider text-muted-foreground", children: outputLabel }),
|
|
47313
47538
|
/* @__PURE__ */ jsxs(Typography, { variant: "h3", weight: "bold", children: [
|
|
47314
47539
|
output.toFixed(2),
|
|
47315
47540
|
" ",
|
|
47316
|
-
|
|
47541
|
+
outputUnit
|
|
47317
47542
|
] }),
|
|
47318
47543
|
submitted && /* @__PURE__ */ jsxs(HStack, { gap: "xs", align: "center", children: [
|
|
47319
47544
|
/* @__PURE__ */ jsx(Icon, { icon: isCorrect ? CheckCircle : XCircle, size: "sm", className: isCorrect ? "text-success" : "text-error" }),
|
|
47320
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body", className: isCorrect ? "text-success" : "text-error", children: isCorrect ? resolved.successMessage
|
|
47545
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body", className: isCorrect ? "text-success" : "text-error", children: isCorrect ? str(resolved.successMessage) || t("simulator.correct") : str(resolved.failMessage) || t("simulator.incorrect") })
|
|
47321
47546
|
] }),
|
|
47322
47547
|
/* @__PURE__ */ jsxs(Typography, { variant: "caption", className: "text-muted-foreground", children: [
|
|
47323
47548
|
t("simulator.target"),
|
|
47324
47549
|
": ",
|
|
47325
47550
|
targetValue,
|
|
47326
47551
|
" ",
|
|
47327
|
-
|
|
47552
|
+
outputUnit,
|
|
47328
47553
|
" (\xB1",
|
|
47329
47554
|
targetTolerance,
|
|
47330
47555
|
")"
|
|
47331
47556
|
] })
|
|
47332
47557
|
] }) }),
|
|
47333
|
-
showHint &&
|
|
47558
|
+
showHint && hint && /* @__PURE__ */ jsx(Card, { className: "p-4 border-l-4 border-l-warning", children: /* @__PURE__ */ jsx(Typography, { variant: "body", children: hint }) }),
|
|
47334
47559
|
/* @__PURE__ */ jsxs(HStack, { gap: "sm", justify: "center", children: [
|
|
47335
47560
|
!submitted ? /* @__PURE__ */ jsxs(Button, { variant: "primary", onClick: handleSubmit, children: [
|
|
47336
47561
|
/* @__PURE__ */ jsx(Icon, { icon: Play, size: "sm" }),
|
|
@@ -47349,6 +47574,7 @@ var init_SimulatorBoard = __esm({
|
|
|
47349
47574
|
"components/game/organisms/puzzles/simulator/SimulatorBoard.tsx"() {
|
|
47350
47575
|
init_atoms2();
|
|
47351
47576
|
init_useEventBus();
|
|
47577
|
+
init_boardEntity();
|
|
47352
47578
|
SimulatorBoard.displayName = "SimulatorBoard";
|
|
47353
47579
|
}
|
|
47354
47580
|
});
|
|
@@ -47774,22 +48000,25 @@ function VariablePanel({
|
|
|
47774
48000
|
return /* @__PURE__ */ jsxs(VStack, { className: cn("p-3 rounded-lg bg-card border border-border", className), gap: "sm", children: [
|
|
47775
48001
|
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground font-medium", children: t("stateArchitect.variables", { name: entityName }) }),
|
|
47776
48002
|
variables.map((v) => {
|
|
47777
|
-
const
|
|
47778
|
-
const
|
|
47779
|
-
const
|
|
48003
|
+
const name = v.name == null ? "" : String(v.name);
|
|
48004
|
+
const value = numField(v.value);
|
|
48005
|
+
const max = numField(v.max, 100);
|
|
48006
|
+
const min = numField(v.min, 0);
|
|
48007
|
+
const unit = v.unit == null ? "" : String(v.unit);
|
|
48008
|
+
const pct = Math.round((value - min) / (max - min) * 100);
|
|
47780
48009
|
const isHigh = pct > 80;
|
|
47781
48010
|
const isLow = pct < 20;
|
|
47782
48011
|
return /* @__PURE__ */ jsxs(VStack, { gap: "none", children: [
|
|
47783
48012
|
/* @__PURE__ */ jsxs(HStack, { className: "items-center justify-between", children: [
|
|
47784
|
-
/* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-foreground font-medium", children:
|
|
48013
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-foreground font-medium", children: name }),
|
|
47785
48014
|
/* @__PURE__ */ jsxs(Typography, { variant: "caption", className: cn(
|
|
47786
48015
|
isHigh ? "text-error" : isLow ? "text-warning" : "text-foreground"
|
|
47787
48016
|
), children: [
|
|
47788
|
-
|
|
47789
|
-
|
|
48017
|
+
value,
|
|
48018
|
+
unit,
|
|
47790
48019
|
" / ",
|
|
47791
48020
|
max,
|
|
47792
|
-
|
|
48021
|
+
unit
|
|
47793
48022
|
] })
|
|
47794
48023
|
] }),
|
|
47795
48024
|
/* @__PURE__ */ jsx(
|
|
@@ -47800,14 +48029,19 @@ function VariablePanel({
|
|
|
47800
48029
|
size: "sm"
|
|
47801
48030
|
}
|
|
47802
48031
|
)
|
|
47803
|
-
] },
|
|
48032
|
+
] }, name);
|
|
47804
48033
|
})
|
|
47805
48034
|
] });
|
|
47806
48035
|
}
|
|
48036
|
+
var numField;
|
|
47807
48037
|
var init_VariablePanel = __esm({
|
|
47808
48038
|
"components/game/organisms/puzzles/state-architect/VariablePanel.tsx"() {
|
|
47809
48039
|
init_atoms2();
|
|
47810
48040
|
init_cn();
|
|
48041
|
+
numField = (v, fallback = 0) => {
|
|
48042
|
+
const n = Number(v);
|
|
48043
|
+
return Number.isFinite(n) ? n : fallback;
|
|
48044
|
+
};
|
|
47811
48045
|
VariablePanel.displayName = "VariablePanel";
|
|
47812
48046
|
}
|
|
47813
48047
|
});
|
|
@@ -47834,14 +48068,21 @@ function StateArchitectBoard({
|
|
|
47834
48068
|
}) {
|
|
47835
48069
|
const { emit } = useEventBus();
|
|
47836
48070
|
const { t } = useTranslate();
|
|
47837
|
-
const resolved =
|
|
47838
|
-
const
|
|
48071
|
+
const resolved = boardEntity(entity);
|
|
48072
|
+
const entityStates = Array.isArray(resolved?.states) ? resolved.states : [];
|
|
48073
|
+
const initialState = str(resolved?.initialState);
|
|
48074
|
+
const entityName = str(resolved?.entityName);
|
|
48075
|
+
const availableEvents = Array.isArray(resolved?.availableEvents) ? resolved.availableEvents : [];
|
|
48076
|
+
const testCases = Array.isArray(resolved?.testCases) ? resolved.testCases : [];
|
|
48077
|
+
const entityTransitions = Array.isArray(resolved?.transitions) ? resolved.transitions : [];
|
|
48078
|
+
const entityVariables = rows(resolved?.variables);
|
|
48079
|
+
const [transitions, setTransitions] = useState(entityTransitions);
|
|
47839
48080
|
const [headerError, setHeaderError] = useState(false);
|
|
47840
48081
|
const [playState, setPlayState] = useState("editing");
|
|
47841
|
-
const [currentState, setCurrentState] = useState(
|
|
48082
|
+
const [currentState, setCurrentState] = useState(initialState);
|
|
47842
48083
|
const [selectedState, setSelectedState] = useState(null);
|
|
47843
48084
|
const [testResults, setTestResults] = useState([]);
|
|
47844
|
-
const [variables, setVariables] = useState(
|
|
48085
|
+
const [variables, setVariables] = useState(() => [...entityVariables]);
|
|
47845
48086
|
const [attempts, setAttempts] = useState(0);
|
|
47846
48087
|
const timerRef = useRef(null);
|
|
47847
48088
|
const [addingFrom, setAddingFrom] = useState(null);
|
|
@@ -47850,12 +48091,12 @@ function StateArchitectBoard({
|
|
|
47850
48091
|
}, []);
|
|
47851
48092
|
const GRAPH_W = 500;
|
|
47852
48093
|
const GRAPH_H = 400;
|
|
47853
|
-
const positions = useMemo(() => layoutStates(
|
|
48094
|
+
const positions = useMemo(() => layoutStates(entityStates, GRAPH_W, GRAPH_H), [entityStates]);
|
|
47854
48095
|
const handleStateClick = useCallback((state) => {
|
|
47855
48096
|
if (playState !== "editing") return;
|
|
47856
48097
|
if (addingFrom) {
|
|
47857
48098
|
if (addingFrom !== state) {
|
|
47858
|
-
const event =
|
|
48099
|
+
const event = availableEvents[0] || "EVENT";
|
|
47859
48100
|
const newTrans = {
|
|
47860
48101
|
id: `t-${nextTransId++}`,
|
|
47861
48102
|
from: addingFrom,
|
|
@@ -47868,7 +48109,7 @@ function StateArchitectBoard({
|
|
|
47868
48109
|
} else {
|
|
47869
48110
|
setSelectedState(state);
|
|
47870
48111
|
}
|
|
47871
|
-
}, [playState, addingFrom,
|
|
48112
|
+
}, [playState, addingFrom, availableEvents]);
|
|
47872
48113
|
const handleStartAddTransition = useCallback(() => {
|
|
47873
48114
|
if (!selectedState) return;
|
|
47874
48115
|
setAddingFrom(selectedState);
|
|
@@ -47877,9 +48118,9 @@ function StateArchitectBoard({
|
|
|
47877
48118
|
setTransitions((prev) => prev.filter((t2) => t2.id !== transId));
|
|
47878
48119
|
}, []);
|
|
47879
48120
|
const machine = useMemo(() => ({
|
|
47880
|
-
name:
|
|
47881
|
-
description: resolved?.description
|
|
47882
|
-
states:
|
|
48121
|
+
name: entityName,
|
|
48122
|
+
description: str(resolved?.description),
|
|
48123
|
+
states: entityStates,
|
|
47883
48124
|
currentState,
|
|
47884
48125
|
transitions: transitions.map((t2) => ({
|
|
47885
48126
|
from: t2.from,
|
|
@@ -47887,7 +48128,7 @@ function StateArchitectBoard({
|
|
|
47887
48128
|
event: t2.event,
|
|
47888
48129
|
guardHint: t2.guardHint
|
|
47889
48130
|
}))
|
|
47890
|
-
}), [resolved, currentState, transitions]);
|
|
48131
|
+
}), [entityName, resolved, entityStates, currentState, transitions]);
|
|
47891
48132
|
const handleTest = useCallback(() => {
|
|
47892
48133
|
if (playState !== "editing") return;
|
|
47893
48134
|
if (testEvent) emit(`UI:${testEvent}`, {});
|
|
@@ -47896,7 +48137,7 @@ function StateArchitectBoard({
|
|
|
47896
48137
|
const results = [];
|
|
47897
48138
|
let testIdx = 0;
|
|
47898
48139
|
const runNextTest = () => {
|
|
47899
|
-
if (testIdx >=
|
|
48140
|
+
if (testIdx >= testCases.length) {
|
|
47900
48141
|
const allPassed = results.every((r2) => r2.passed);
|
|
47901
48142
|
setPlayState(allPassed ? "success" : "fail");
|
|
47902
48143
|
setTestResults(results);
|
|
@@ -47911,9 +48152,9 @@ function StateArchitectBoard({
|
|
|
47911
48152
|
}
|
|
47912
48153
|
return;
|
|
47913
48154
|
}
|
|
47914
|
-
const testCase =
|
|
48155
|
+
const testCase = testCases[testIdx];
|
|
47915
48156
|
if (!testCase) return;
|
|
47916
|
-
let state =
|
|
48157
|
+
let state = initialState;
|
|
47917
48158
|
for (const event of testCase.events) {
|
|
47918
48159
|
const trans = transitions.find((t2) => t2.from === state && t2.event === event);
|
|
47919
48160
|
if (trans) {
|
|
@@ -47931,53 +48172,57 @@ function StateArchitectBoard({
|
|
|
47931
48172
|
timerRef.current = setTimeout(runNextTest, stepDurationMs);
|
|
47932
48173
|
};
|
|
47933
48174
|
timerRef.current = setTimeout(runNextTest, stepDurationMs);
|
|
47934
|
-
}, [playState, transitions,
|
|
48175
|
+
}, [playState, transitions, testCases, initialState, stepDurationMs, testEvent, completeEvent, emit]);
|
|
47935
48176
|
const handleTryAgain = useCallback(() => {
|
|
47936
48177
|
if (timerRef.current) clearTimeout(timerRef.current);
|
|
47937
48178
|
setPlayState("editing");
|
|
47938
|
-
setCurrentState(
|
|
48179
|
+
setCurrentState(initialState);
|
|
47939
48180
|
setTestResults([]);
|
|
47940
|
-
}, [
|
|
48181
|
+
}, [initialState]);
|
|
47941
48182
|
const handleReset = useCallback(() => {
|
|
47942
48183
|
if (timerRef.current) clearTimeout(timerRef.current);
|
|
47943
|
-
setTransitions(
|
|
48184
|
+
setTransitions(entityTransitions);
|
|
47944
48185
|
setPlayState("editing");
|
|
47945
|
-
setCurrentState(
|
|
48186
|
+
setCurrentState(initialState);
|
|
47946
48187
|
setTestResults([]);
|
|
47947
|
-
setVariables(
|
|
48188
|
+
setVariables([...entityVariables]);
|
|
47948
48189
|
setSelectedState(null);
|
|
47949
48190
|
setAddingFrom(null);
|
|
47950
48191
|
setAttempts(0);
|
|
47951
|
-
}, [
|
|
48192
|
+
}, [entityTransitions, initialState, entityVariables]);
|
|
47952
48193
|
const codeData = useMemo(() => ({
|
|
47953
|
-
name:
|
|
47954
|
-
states:
|
|
47955
|
-
initialState
|
|
48194
|
+
name: entityName,
|
|
48195
|
+
states: entityStates,
|
|
48196
|
+
initialState,
|
|
47956
48197
|
transitions: transitions.map((t2) => ({
|
|
47957
48198
|
from: t2.from,
|
|
47958
48199
|
to: t2.to,
|
|
47959
48200
|
event: t2.event,
|
|
47960
48201
|
...t2.guardHint ? { guard: t2.guardHint } : {}
|
|
47961
48202
|
}))
|
|
47962
|
-
}), [
|
|
48203
|
+
}), [entityName, entityStates, initialState, transitions]);
|
|
47963
48204
|
if (!resolved) return null;
|
|
48205
|
+
const theme = resolved.theme ?? void 0;
|
|
48206
|
+
const themeBackground = theme?.background;
|
|
48207
|
+
const headerImage = str(resolved.headerImage);
|
|
48208
|
+
const hint = str(resolved.hint);
|
|
47964
48209
|
return /* @__PURE__ */ jsxs(
|
|
47965
48210
|
VStack,
|
|
47966
48211
|
{
|
|
47967
48212
|
className: cn("p-4 gap-6", className),
|
|
47968
48213
|
style: {
|
|
47969
|
-
backgroundImage:
|
|
48214
|
+
backgroundImage: themeBackground ? `url(${themeBackground})` : void 0,
|
|
47970
48215
|
backgroundSize: "cover",
|
|
47971
48216
|
backgroundPosition: "center"
|
|
47972
48217
|
},
|
|
47973
48218
|
children: [
|
|
47974
|
-
|
|
48219
|
+
headerImage && !headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 overflow-hidden rounded-container", children: /* @__PURE__ */ jsx("img", { src: headerImage, alt: "", onError: () => setHeaderError(true), className: "w-full h-full object-cover" }) }) : headerImage && headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 rounded-container bg-gradient-to-br from-muted to-accent opacity-60" }) : null,
|
|
47975
48220
|
/* @__PURE__ */ jsxs(VStack, { gap: "xs", children: [
|
|
47976
|
-
/* @__PURE__ */ jsx(Typography, { variant: "h4", className: "text-foreground", children: resolved.title }),
|
|
47977
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground", children: resolved.description }),
|
|
48221
|
+
/* @__PURE__ */ jsx(Typography, { variant: "h4", className: "text-foreground", children: str(resolved.title) }),
|
|
48222
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground", children: str(resolved.description) }),
|
|
47978
48223
|
/* @__PURE__ */ jsxs(HStack, { className: "items-center p-2 rounded bg-warning/10 border border-warning/30", gap: "xs", children: [
|
|
47979
48224
|
/* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-warning font-bold", children: t("game.hint") + ":" }),
|
|
47980
|
-
/* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-foreground", children:
|
|
48225
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-foreground", children: hint })
|
|
47981
48226
|
] })
|
|
47982
48227
|
] }),
|
|
47983
48228
|
/* @__PURE__ */ jsxs(HStack, { className: "flex-wrap items-start", gap: "lg", children: [
|
|
@@ -48025,14 +48270,14 @@ function StateArchitectBoard({
|
|
|
48025
48270
|
]
|
|
48026
48271
|
}
|
|
48027
48272
|
),
|
|
48028
|
-
|
|
48273
|
+
entityStates.map((state) => /* @__PURE__ */ jsx(
|
|
48029
48274
|
StateNode2,
|
|
48030
48275
|
{
|
|
48031
48276
|
name: state,
|
|
48032
48277
|
position: positions[state],
|
|
48033
48278
|
isCurrent: state === currentState,
|
|
48034
48279
|
isSelected: state === selectedState,
|
|
48035
|
-
isInitial: state ===
|
|
48280
|
+
isInitial: state === initialState,
|
|
48036
48281
|
onClick: () => handleStateClick(state)
|
|
48037
48282
|
},
|
|
48038
48283
|
state
|
|
@@ -48079,7 +48324,7 @@ function StateArchitectBoard({
|
|
|
48079
48324
|
/* @__PURE__ */ jsx(
|
|
48080
48325
|
VariablePanel,
|
|
48081
48326
|
{
|
|
48082
|
-
entityName
|
|
48327
|
+
entityName,
|
|
48083
48328
|
variables
|
|
48084
48329
|
}
|
|
48085
48330
|
),
|
|
@@ -48094,12 +48339,12 @@ function StateArchitectBoard({
|
|
|
48094
48339
|
resolved.showCodeView !== false && /* @__PURE__ */ jsx(CodeView, { data: codeData, label: "View Code" })
|
|
48095
48340
|
] })
|
|
48096
48341
|
] }),
|
|
48097
|
-
playState === "success" && /* @__PURE__ */ jsx(Box, { className: "p-4 rounded-container bg-success/20 border border-success text-center", children: /* @__PURE__ */ jsx(Typography, { variant: "h5", className: "text-success", children: resolved.successMessage || t("stateArchitect.allPassed") }) }),
|
|
48342
|
+
playState === "success" && /* @__PURE__ */ jsx(Box, { className: "p-4 rounded-container bg-success/20 border border-success text-center", children: /* @__PURE__ */ jsx(Typography, { variant: "h5", className: "text-success", children: str(resolved.successMessage) || t("stateArchitect.allPassed") }) }),
|
|
48098
48343
|
playState === "fail" && /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
|
|
48099
48344
|
/* @__PURE__ */ jsx(Box, { className: "p-4 rounded-container bg-warning/10 border border-warning/30 text-center", children: /* @__PURE__ */ jsx(Typography, { variant: "body1", className: "text-foreground font-medium", children: t(ENCOURAGEMENT_KEYS3[Math.min(attempts - 1, ENCOURAGEMENT_KEYS3.length - 1)] ?? ENCOURAGEMENT_KEYS3[0]) }) }),
|
|
48100
|
-
attempts >= 3 &&
|
|
48345
|
+
attempts >= 3 && hint && /* @__PURE__ */ jsx(Box, { className: "p-3 rounded-container bg-accent/10 border border-accent/30", children: /* @__PURE__ */ jsxs(HStack, { className: "items-start", gap: "xs", children: [
|
|
48101
48346
|
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-accent font-bold shrink-0", children: "\u{1F4A1} " + t("game.hint") + ":" }),
|
|
48102
|
-
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-foreground", children:
|
|
48347
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-foreground", children: hint })
|
|
48103
48348
|
] }) })
|
|
48104
48349
|
] }),
|
|
48105
48350
|
/* @__PURE__ */ jsxs(HStack, { gap: "sm", children: [
|
|
@@ -48129,6 +48374,7 @@ var init_StateArchitectBoard = __esm({
|
|
|
48129
48374
|
init_TransitionArrow();
|
|
48130
48375
|
init_VariablePanel();
|
|
48131
48376
|
init_CodeView();
|
|
48377
|
+
init_boardEntity();
|
|
48132
48378
|
ENCOURAGEMENT_KEYS3 = [
|
|
48133
48379
|
"puzzle.tryAgain1",
|
|
48134
48380
|
"puzzle.tryAgain2",
|
|
@@ -48165,8 +48411,8 @@ var init_StatsOrganism = __esm({
|
|
|
48165
48411
|
return /* @__PURE__ */ jsx(ErrorState, { message: error.message, className });
|
|
48166
48412
|
}
|
|
48167
48413
|
const stats = items.map((item) => ({
|
|
48168
|
-
value: item.value,
|
|
48169
|
-
label: item.label
|
|
48414
|
+
value: String(item.value ?? ""),
|
|
48415
|
+
label: String(item.label ?? "")
|
|
48170
48416
|
}));
|
|
48171
48417
|
return /* @__PURE__ */ jsx(
|
|
48172
48418
|
StatsGrid,
|
|
@@ -48212,10 +48458,10 @@ var init_StepFlowOrganism = __esm({
|
|
|
48212
48458
|
return /* @__PURE__ */ jsx(ErrorState, { message: error.message, className });
|
|
48213
48459
|
}
|
|
48214
48460
|
const steps = items.map((item) => ({
|
|
48215
|
-
number: item.number,
|
|
48216
|
-
title: item.title,
|
|
48217
|
-
description: item.description,
|
|
48218
|
-
icon: item.icon
|
|
48461
|
+
number: item.number != null ? Number(item.number) : void 0,
|
|
48462
|
+
title: String(item.title ?? ""),
|
|
48463
|
+
description: String(item.description ?? ""),
|
|
48464
|
+
icon: item.icon != null ? String(item.icon) : void 0
|
|
48219
48465
|
}));
|
|
48220
48466
|
return /* @__PURE__ */ jsxs(VStack, { gap: "lg", className: cn("w-full", className), children: [
|
|
48221
48467
|
(heading || subtitle) && /* @__PURE__ */ jsxs(VStack, { gap: "sm", align: "center", className: "w-full", children: [
|
|
@@ -48388,13 +48634,13 @@ var init_TeamOrganism = __esm({
|
|
|
48388
48634
|
/* @__PURE__ */ jsx(SimpleGrid, { cols: cols > 0 ? cols : 1, gap: "lg", children: items.map((member) => /* @__PURE__ */ jsx(
|
|
48389
48635
|
TeamCard,
|
|
48390
48636
|
{
|
|
48391
|
-
name: member.name,
|
|
48392
|
-
nameAr: member.nameAr,
|
|
48393
|
-
role: member.role,
|
|
48394
|
-
bio: member.bio,
|
|
48395
|
-
avatar: member.avatar
|
|
48637
|
+
name: String(member.name ?? ""),
|
|
48638
|
+
nameAr: member.nameAr != null ? String(member.nameAr) : void 0,
|
|
48639
|
+
role: String(member.role ?? ""),
|
|
48640
|
+
bio: String(member.bio ?? ""),
|
|
48641
|
+
avatar: member.avatar != null ? String(member.avatar) : void 0
|
|
48396
48642
|
},
|
|
48397
|
-
member.id
|
|
48643
|
+
String(member.id ?? "")
|
|
48398
48644
|
)) })
|
|
48399
48645
|
] });
|
|
48400
48646
|
};
|
|
@@ -48631,8 +48877,8 @@ function useBattleState(initialUnits, eventConfig = {}, callbacks = {}) {
|
|
|
48631
48877
|
const [turn, setTurn] = useState(1);
|
|
48632
48878
|
const [gameResult, setGameResult] = useState(null);
|
|
48633
48879
|
const checkGameEnd = useCallback((currentUnits) => {
|
|
48634
|
-
const pa = currentUnits.filter((u) => u
|
|
48635
|
-
const ea = currentUnits.filter((u) => u
|
|
48880
|
+
const pa = currentUnits.filter((u) => unitTeam(u) === "player" && unitHealth(u) > 0);
|
|
48881
|
+
const ea = currentUnits.filter((u) => unitTeam(u) === "enemy" && unitHealth(u) > 0);
|
|
48636
48882
|
if (pa.length === 0) {
|
|
48637
48883
|
setGameResult("defeat");
|
|
48638
48884
|
setPhase("game_over");
|
|
@@ -48650,34 +48896,36 @@ function useBattleState(initialUnits, eventConfig = {}, callbacks = {}) {
|
|
|
48650
48896
|
}
|
|
48651
48897
|
}, [onGameEnd, gameEndEvent, eventBus]);
|
|
48652
48898
|
const handleUnitClick = useCallback((unitId) => {
|
|
48653
|
-
const unit = units.find((u) => u.id === unitId);
|
|
48899
|
+
const unit = units.find((u) => str(u.id) === unitId);
|
|
48654
48900
|
if (!unit) return;
|
|
48655
48901
|
if (unitClickEvent) {
|
|
48656
48902
|
eventBus.emit(`UI:${unitClickEvent}`, { unitId });
|
|
48657
48903
|
}
|
|
48658
48904
|
if (phase === "observation" || phase === "selection") {
|
|
48659
|
-
if (unit
|
|
48905
|
+
if (unitTeam(unit) === "player") {
|
|
48660
48906
|
setSelectedUnitId(unitId);
|
|
48661
48907
|
setPhase("movement");
|
|
48662
48908
|
}
|
|
48663
48909
|
} else if (phase === "action") {
|
|
48664
|
-
const selectedUnit = units.find((u) => u.id === selectedUnitId);
|
|
48910
|
+
const selectedUnit = units.find((u) => str(u.id) === selectedUnitId);
|
|
48665
48911
|
if (!selectedUnit) return;
|
|
48666
|
-
if (unit
|
|
48667
|
-
const
|
|
48668
|
-
const
|
|
48912
|
+
if (unitTeam(unit) === "enemy") {
|
|
48913
|
+
const up = unitPosition(unit);
|
|
48914
|
+
const sp = unitPosition(selectedUnit);
|
|
48915
|
+
const dx = Math.abs(up.x - sp.x);
|
|
48916
|
+
const dy = Math.abs(up.y - sp.y);
|
|
48669
48917
|
if (dx <= 1 && dy <= 1 && dx + dy > 0) {
|
|
48670
|
-
const damage = calculateDamage ? calculateDamage(selectedUnit, unit) : Math.max(1, selectedUnit.attack - unit.defense);
|
|
48671
|
-
const newHealth = Math.max(0, unit
|
|
48918
|
+
const damage = calculateDamage ? calculateDamage(selectedUnit, unit) : Math.max(1, num(selectedUnit.attack) - num(unit.defense));
|
|
48919
|
+
const newHealth = Math.max(0, unitHealth(unit) - damage);
|
|
48672
48920
|
const updatedUnits = units.map(
|
|
48673
|
-
(u) => u.id === unit.id ? { ...u, health: newHealth } : u
|
|
48921
|
+
(u) => str(u.id) === str(unit.id) ? { ...u, health: newHealth } : u
|
|
48674
48922
|
);
|
|
48675
48923
|
setUnits(updatedUnits);
|
|
48676
48924
|
onAttack?.(selectedUnit, unit, damage);
|
|
48677
48925
|
if (attackEvent) {
|
|
48678
48926
|
eventBus.emit(`UI:${attackEvent}`, {
|
|
48679
|
-
attackerId: selectedUnit.id,
|
|
48680
|
-
targetId: unit.id,
|
|
48927
|
+
attackerId: str(selectedUnit.id),
|
|
48928
|
+
targetId: str(unit.id),
|
|
48681
48929
|
damage
|
|
48682
48930
|
});
|
|
48683
48931
|
}
|
|
@@ -48694,16 +48942,20 @@ function useBattleState(initialUnits, eventConfig = {}, callbacks = {}) {
|
|
|
48694
48942
|
eventBus.emit(`UI:${tileClickEvent}`, { x, y });
|
|
48695
48943
|
}
|
|
48696
48944
|
if (phase === "movement" && selectedUnitId) {
|
|
48697
|
-
const selectedUnit = units.find((u) => u.id === selectedUnitId);
|
|
48945
|
+
const selectedUnit = units.find((u) => str(u.id) === selectedUnitId);
|
|
48698
48946
|
if (!selectedUnit) return;
|
|
48699
|
-
const
|
|
48700
|
-
const
|
|
48947
|
+
const sp = unitPosition(selectedUnit);
|
|
48948
|
+
const dx = Math.abs(x - sp.x);
|
|
48949
|
+
const dy = Math.abs(y - sp.y);
|
|
48701
48950
|
const dist = dx + dy;
|
|
48702
|
-
if (dist > 0 && dist <= selectedUnit.movement) {
|
|
48703
|
-
if (!units.some((u) =>
|
|
48951
|
+
if (dist > 0 && dist <= num(selectedUnit.movement)) {
|
|
48952
|
+
if (!units.some((u) => {
|
|
48953
|
+
const p2 = unitPosition(u);
|
|
48954
|
+
return p2.x === x && p2.y === y && unitHealth(u) > 0;
|
|
48955
|
+
})) {
|
|
48704
48956
|
setUnits(
|
|
48705
48957
|
(prev) => prev.map(
|
|
48706
|
-
(u) => u.id === selectedUnitId ? { ...u, position: { x, y } } : u
|
|
48958
|
+
(u) => str(u.id) === selectedUnitId ? { ...u, position: { x, y } } : u
|
|
48707
48959
|
)
|
|
48708
48960
|
);
|
|
48709
48961
|
setPhase("action");
|
|
@@ -48746,12 +48998,13 @@ var init_useBattleState = __esm({
|
|
|
48746
48998
|
"components/game/organisms/hooks/useBattleState.ts"() {
|
|
48747
48999
|
"use client";
|
|
48748
49000
|
init_useEventBus();
|
|
49001
|
+
init_boardEntity();
|
|
48749
49002
|
}
|
|
48750
49003
|
});
|
|
48751
49004
|
function UncontrolledBattleBoard({ entity, ...rest }) {
|
|
48752
|
-
const resolved =
|
|
49005
|
+
const resolved = boardEntity(entity);
|
|
48753
49006
|
const battleState = useBattleState(
|
|
48754
|
-
resolved?.initialUnits
|
|
49007
|
+
rows(resolved?.initialUnits),
|
|
48755
49008
|
{
|
|
48756
49009
|
tileClickEvent: rest.tileClickEvent,
|
|
48757
49010
|
unitClickEvent: rest.unitClickEvent,
|
|
@@ -48787,10 +49040,23 @@ function UncontrolledBattleBoard({ entity, ...rest }) {
|
|
|
48787
49040
|
var init_UncontrolledBattleBoard = __esm({
|
|
48788
49041
|
"components/game/organisms/UncontrolledBattleBoard.tsx"() {
|
|
48789
49042
|
init_BattleBoard();
|
|
49043
|
+
init_boardEntity();
|
|
48790
49044
|
init_useBattleState();
|
|
48791
49045
|
UncontrolledBattleBoard.displayName = "UncontrolledBattleBoard";
|
|
48792
49046
|
}
|
|
48793
49047
|
});
|
|
49048
|
+
function heroPosition(h) {
|
|
49049
|
+
return vec2(h.position);
|
|
49050
|
+
}
|
|
49051
|
+
function heroOwner(h) {
|
|
49052
|
+
return str(h.owner);
|
|
49053
|
+
}
|
|
49054
|
+
function heroMovement(h) {
|
|
49055
|
+
return num(h.movement);
|
|
49056
|
+
}
|
|
49057
|
+
function hexPassable(h) {
|
|
49058
|
+
return h.passable !== false;
|
|
49059
|
+
}
|
|
48794
49060
|
function defaultIsInRange(from, to, range) {
|
|
48795
49061
|
return Math.abs(from.x - to.x) + Math.abs(from.y - to.y) <= range;
|
|
48796
49062
|
}
|
|
@@ -48821,36 +49087,36 @@ function WorldMapBoard({
|
|
|
48821
49087
|
className
|
|
48822
49088
|
}) {
|
|
48823
49089
|
const eventBus = useEventBus();
|
|
48824
|
-
const resolved =
|
|
48825
|
-
const hexes = resolved?.hexes
|
|
48826
|
-
const heroes = resolved?.heroes
|
|
48827
|
-
const features = resolved?.features
|
|
48828
|
-
const selectedHeroId = resolved?.selectedHeroId;
|
|
49090
|
+
const resolved = boardEntity(entity);
|
|
49091
|
+
const hexes = rows(resolved?.hexes);
|
|
49092
|
+
const heroes = rows(resolved?.heroes);
|
|
49093
|
+
const features = Array.isArray(resolved?.features) ? resolved.features : [];
|
|
49094
|
+
const selectedHeroId = resolved?.selectedHeroId ?? null;
|
|
48829
49095
|
const assetManifest = resolved?.assetManifest;
|
|
48830
49096
|
const backgroundImage = resolved?.backgroundImage;
|
|
48831
49097
|
const [hoveredTile, setHoveredTile] = useState(null);
|
|
48832
49098
|
const selectedHero = useMemo(
|
|
48833
|
-
() => heroes.find((h) => h.id === selectedHeroId) ?? null,
|
|
49099
|
+
() => heroes.find((h) => str(h.id) === selectedHeroId) ?? null,
|
|
48834
49100
|
[heroes, selectedHeroId]
|
|
48835
49101
|
);
|
|
48836
49102
|
const tiles = useMemo(
|
|
48837
49103
|
() => hexes.map((hex) => ({
|
|
48838
|
-
x: hex.x,
|
|
48839
|
-
y: hex.y,
|
|
48840
|
-
terrain: hex.terrain,
|
|
48841
|
-
terrainSprite: hex.terrainSprite
|
|
49104
|
+
x: num(hex.x),
|
|
49105
|
+
y: num(hex.y),
|
|
49106
|
+
terrain: str(hex.terrain),
|
|
49107
|
+
terrainSprite: hex.terrainSprite == null ? void 0 : str(hex.terrainSprite)
|
|
48842
49108
|
})),
|
|
48843
49109
|
[hexes]
|
|
48844
49110
|
);
|
|
48845
49111
|
const baseUnits = useMemo(
|
|
48846
49112
|
() => heroes.map((hero) => ({
|
|
48847
|
-
id: hero.id,
|
|
48848
|
-
position: hero
|
|
48849
|
-
name: hero.name,
|
|
48850
|
-
team: hero
|
|
49113
|
+
id: str(hero.id),
|
|
49114
|
+
position: heroPosition(hero),
|
|
49115
|
+
name: str(hero.name),
|
|
49116
|
+
team: heroOwner(hero) === "enemy" ? "enemy" : "player",
|
|
48851
49117
|
health: 100,
|
|
48852
49118
|
maxHealth: 100,
|
|
48853
|
-
sprite: hero.sprite
|
|
49119
|
+
sprite: hero.sprite == null ? void 0 : str(hero.sprite)
|
|
48854
49120
|
})),
|
|
48855
49121
|
[heroes]
|
|
48856
49122
|
);
|
|
@@ -48891,73 +49157,94 @@ function WorldMapBoard({
|
|
|
48891
49157
|
const isoUnits = useMemo(() => {
|
|
48892
49158
|
if (movingPositions.size === 0) return baseUnits;
|
|
48893
49159
|
return baseUnits.map((u) => {
|
|
48894
|
-
const pos = movingPositions.get(u.id);
|
|
49160
|
+
const pos = u.id == null ? void 0 : movingPositions.get(u.id);
|
|
48895
49161
|
return pos ? { ...u, position: pos } : u;
|
|
48896
49162
|
});
|
|
48897
49163
|
}, [baseUnits, movingPositions]);
|
|
48898
49164
|
const validMoves = useMemo(() => {
|
|
48899
|
-
if (!selectedHero || selectedHero
|
|
49165
|
+
if (!selectedHero || heroMovement(selectedHero) <= 0) return [];
|
|
49166
|
+
const sp = heroPosition(selectedHero);
|
|
49167
|
+
const sOwner = heroOwner(selectedHero);
|
|
49168
|
+
const range = heroMovement(selectedHero);
|
|
48900
49169
|
const moves = [];
|
|
48901
49170
|
hexes.forEach((hex) => {
|
|
48902
|
-
|
|
48903
|
-
|
|
48904
|
-
if (!
|
|
48905
|
-
if (
|
|
48906
|
-
|
|
49171
|
+
const hx = num(hex.x);
|
|
49172
|
+
const hy = num(hex.y);
|
|
49173
|
+
if (!hexPassable(hex)) return;
|
|
49174
|
+
if (hx === sp.x && hy === sp.y) return;
|
|
49175
|
+
if (!isInRange(sp, { x: hx, y: hy }, range)) return;
|
|
49176
|
+
if (heroes.some((h) => {
|
|
49177
|
+
const hp = heroPosition(h);
|
|
49178
|
+
return hp.x === hx && hp.y === hy && heroOwner(h) === sOwner;
|
|
49179
|
+
})) return;
|
|
49180
|
+
moves.push({ x: hx, y: hy });
|
|
48907
49181
|
});
|
|
48908
49182
|
return moves;
|
|
48909
49183
|
}, [selectedHero, hexes, heroes, isInRange]);
|
|
48910
49184
|
const attackTargets = useMemo(() => {
|
|
48911
|
-
if (!selectedHero || selectedHero
|
|
48912
|
-
|
|
49185
|
+
if (!selectedHero || heroMovement(selectedHero) <= 0) return [];
|
|
49186
|
+
const sp = heroPosition(selectedHero);
|
|
49187
|
+
const sOwner = heroOwner(selectedHero);
|
|
49188
|
+
const range = heroMovement(selectedHero);
|
|
49189
|
+
return heroes.filter((h) => heroOwner(h) !== sOwner).filter((h) => isInRange(sp, heroPosition(h), range)).map((h) => heroPosition(h));
|
|
48913
49190
|
}, [selectedHero, heroes, isInRange]);
|
|
48914
|
-
const maxY = Math.max(...hexes.map((h) => h.y), 0);
|
|
49191
|
+
const maxY = Math.max(...hexes.map((h) => num(h.y)), 0);
|
|
48915
49192
|
const baseOffsetX = (maxY + 1) * (TILE_WIDTH * scale / 2);
|
|
48916
49193
|
const tileToScreen = useCallback(
|
|
48917
49194
|
(tx, ty) => isoToScreen(tx, ty, scale, baseOffsetX),
|
|
48918
49195
|
[scale, baseOffsetX]
|
|
48919
49196
|
);
|
|
48920
49197
|
const hoveredHex = useMemo(
|
|
48921
|
-
() => hoveredTile ? hexes.find((h) => h.x === hoveredTile.x && h.y === hoveredTile.y) ?? null : null,
|
|
49198
|
+
() => hoveredTile ? hexes.find((h) => num(h.x) === hoveredTile.x && num(h.y) === hoveredTile.y) ?? null : null,
|
|
48922
49199
|
[hoveredTile, hexes]
|
|
48923
49200
|
);
|
|
48924
49201
|
const hoveredHero = useMemo(
|
|
48925
|
-
() => hoveredTile ? heroes.find((h) =>
|
|
49202
|
+
() => hoveredTile ? heroes.find((h) => {
|
|
49203
|
+
const hp = heroPosition(h);
|
|
49204
|
+
return hp.x === hoveredTile.x && hp.y === hoveredTile.y;
|
|
49205
|
+
}) ?? null : null,
|
|
48926
49206
|
[hoveredTile, heroes]
|
|
48927
49207
|
);
|
|
48928
49208
|
const handleTileClick = useCallback((x, y) => {
|
|
48929
49209
|
if (movementAnimRef.current) return;
|
|
48930
|
-
const hex = hexes.find((h) => h.x === x && h.y === y);
|
|
49210
|
+
const hex = hexes.find((h) => num(h.x) === x && num(h.y) === y);
|
|
48931
49211
|
if (!hex) return;
|
|
48932
49212
|
if (tileClickEvent) {
|
|
48933
49213
|
eventBus.emit(`UI:${tileClickEvent}`, { x, y });
|
|
48934
49214
|
}
|
|
48935
49215
|
if (selectedHero && validMoves.some((m) => m.x === x && m.y === y)) {
|
|
48936
|
-
|
|
48937
|
-
|
|
49216
|
+
const heroId = str(selectedHero.id);
|
|
49217
|
+
startMoveAnimation(heroId, { ...heroPosition(selectedHero) }, { x, y }, () => {
|
|
49218
|
+
onHeroMove?.(heroId, x, y);
|
|
48938
49219
|
if (heroMoveEvent) {
|
|
48939
|
-
eventBus.emit(`UI:${heroMoveEvent}`, { heroId
|
|
49220
|
+
eventBus.emit(`UI:${heroMoveEvent}`, { heroId, toX: x, toY: y });
|
|
48940
49221
|
}
|
|
48941
|
-
|
|
48942
|
-
|
|
49222
|
+
const feature = str(hex.feature);
|
|
49223
|
+
if (feature && feature !== "none") {
|
|
49224
|
+
onFeatureEnter?.(heroId, hex);
|
|
48943
49225
|
if (featureEnterEvent) {
|
|
48944
|
-
eventBus.emit(`UI:${featureEnterEvent}`, { heroId
|
|
49226
|
+
eventBus.emit(`UI:${featureEnterEvent}`, { heroId, feature, hex });
|
|
48945
49227
|
}
|
|
48946
49228
|
}
|
|
48947
49229
|
});
|
|
48948
49230
|
return;
|
|
48949
49231
|
}
|
|
48950
|
-
const enemy = heroes.find((h) =>
|
|
49232
|
+
const enemy = heroes.find((h) => {
|
|
49233
|
+
const hp = heroPosition(h);
|
|
49234
|
+
return hp.x === x && hp.y === y && heroOwner(h) === "enemy";
|
|
49235
|
+
});
|
|
48951
49236
|
if (selectedHero && enemy && attackTargets.some((t) => t.x === x && t.y === y)) {
|
|
48952
|
-
|
|
49237
|
+
const attackerId = str(selectedHero.id);
|
|
49238
|
+
const defenderId = str(enemy.id);
|
|
49239
|
+
onBattleEncounter?.(attackerId, defenderId);
|
|
48953
49240
|
if (battleEncounterEvent) {
|
|
48954
|
-
eventBus.emit(`UI:${battleEncounterEvent}`, { attackerId
|
|
49241
|
+
eventBus.emit(`UI:${battleEncounterEvent}`, { attackerId, defenderId });
|
|
48955
49242
|
}
|
|
48956
49243
|
}
|
|
48957
49244
|
}, [hexes, heroes, selectedHero, validMoves, attackTargets, startMoveAnimation, onHeroMove, onFeatureEnter, onBattleEncounter, eventBus, tileClickEvent, heroMoveEvent, featureEnterEvent, battleEncounterEvent]);
|
|
48958
49245
|
const handleUnitClick = useCallback((unitId) => {
|
|
48959
|
-
const hero = heroes.find((h) => h.id === unitId);
|
|
48960
|
-
if (hero && (hero
|
|
49246
|
+
const hero = heroes.find((h) => str(h.id) === unitId);
|
|
49247
|
+
if (hero && (heroOwner(hero) === "player" || allowMoveAllHeroes)) {
|
|
48961
49248
|
onHeroSelect?.(unitId);
|
|
48962
49249
|
if (heroSelectEvent) {
|
|
48963
49250
|
eventBus.emit(`UI:${heroSelectEvent}`, { heroId: unitId });
|
|
@@ -49030,6 +49317,7 @@ var init_WorldMapBoard = __esm({
|
|
|
49030
49317
|
init_Stack();
|
|
49031
49318
|
init_LoadingState();
|
|
49032
49319
|
init_IsometricCanvas2();
|
|
49320
|
+
init_boardEntity();
|
|
49033
49321
|
init_isometric();
|
|
49034
49322
|
WorldMapBoard.displayName = "WorldMapBoard";
|
|
49035
49323
|
}
|
|
@@ -52593,10 +52881,10 @@ function parseApplicationLevel(schema) {
|
|
|
52593
52881
|
}
|
|
52594
52882
|
const count = schema.orbitals.length;
|
|
52595
52883
|
const cols = Math.ceil(Math.sqrt(count));
|
|
52596
|
-
const
|
|
52884
|
+
const rows2 = Math.ceil(count / cols);
|
|
52597
52885
|
const spacing = 200;
|
|
52598
52886
|
const gridW = cols * spacing;
|
|
52599
|
-
const gridH =
|
|
52887
|
+
const gridH = rows2 * spacing;
|
|
52600
52888
|
const originX = (600 - gridW) / 2 + spacing / 2;
|
|
52601
52889
|
const originY = (400 - gridH) / 2 + spacing / 2;
|
|
52602
52890
|
schema.orbitals.forEach((orbital, i) => {
|
|
@@ -55738,11 +56026,11 @@ function buildMockData(schema) {
|
|
|
55738
56026
|
result[entityName] = entity.instances;
|
|
55739
56027
|
continue;
|
|
55740
56028
|
}
|
|
55741
|
-
const
|
|
56029
|
+
const rows2 = Array.from(
|
|
55742
56030
|
{ length: 10 },
|
|
55743
56031
|
(_, i) => generateEntityRow(entity, i + 1)
|
|
55744
56032
|
);
|
|
55745
|
-
result[entityName] =
|
|
56033
|
+
result[entityName] = rows2;
|
|
55746
56034
|
}
|
|
55747
56035
|
for (const orbital of schema.orbitals) {
|
|
55748
56036
|
for (const traitRef of orbital.traits ?? []) {
|
|
@@ -59241,18 +59529,18 @@ function layoutOrbitals(count, containerW, containerH) {
|
|
|
59241
59529
|
if (count === 0) return [];
|
|
59242
59530
|
if (count === 1) return [{ cx: containerW / 2, cy: containerH / 2 }];
|
|
59243
59531
|
const cols = Math.min(count, Math.ceil(Math.sqrt(count)));
|
|
59244
|
-
const
|
|
59532
|
+
const rows2 = Math.ceil(count / cols);
|
|
59245
59533
|
const edgePad = 24;
|
|
59246
59534
|
const fitMinCx = UNIT_DISPLAY_W / 2 + edgePad;
|
|
59247
59535
|
const fitMinCy = UNIT_DISPLAY_H / 2 + edgePad;
|
|
59248
59536
|
const fitMaxCx = Math.max(fitMinCx, containerW - UNIT_DISPLAY_W / 2 - edgePad);
|
|
59249
59537
|
const fitMaxCy = Math.max(fitMinCy, containerH - UNIT_DISPLAY_H / 2 - edgePad);
|
|
59250
59538
|
const fitStepX = cols > 1 ? (fitMaxCx - fitMinCx) / (cols - 1) : 0;
|
|
59251
|
-
const fitStepY =
|
|
59539
|
+
const fitStepY = rows2 > 1 ? (fitMaxCy - fitMinCy) / (rows2 - 1) : 0;
|
|
59252
59540
|
const stepX = Math.min(fitStepX, UNIT_DISPLAY_W * 3.5);
|
|
59253
59541
|
const stepY = Math.min(fitStepY, UNIT_DISPLAY_H * 3.5);
|
|
59254
59542
|
const gridW = (cols - 1) * stepX;
|
|
59255
|
-
const gridH = (
|
|
59543
|
+
const gridH = (rows2 - 1) * stepY;
|
|
59256
59544
|
const originX = (containerW - gridW) / 2;
|
|
59257
59545
|
const originY = (containerH - gridH) / 2;
|
|
59258
59546
|
return Array.from({ length: count }, (_, i) => ({
|