@almadar/ui 5.21.11 → 5.22.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/dist/avl/index.cjs +939 -638
  2. package/dist/avl/index.js +939 -638
  3. package/dist/components/core/molecules/CalendarGrid.d.ts +3 -10
  4. package/dist/components/core/molecules/ContentRenderer.d.ts +2 -2
  5. package/dist/components/core/molecules/DataGrid.d.ts +11 -20
  6. package/dist/components/core/molecules/DataList.d.ts +9 -15
  7. package/dist/components/core/molecules/FormSection.d.ts +4 -4
  8. package/dist/components/core/molecules/PositionedCanvas.d.ts +4 -17
  9. package/dist/components/core/molecules/ReplyTree.d.ts +2 -13
  10. package/dist/components/core/molecules/RichBlockEditor.d.ts +3 -6
  11. package/dist/components/core/molecules/SortableList.d.ts +7 -5
  12. package/dist/components/core/molecules/TableView.d.ts +7 -7
  13. package/dist/components/core/molecules/index.d.ts +3 -3
  14. package/dist/components/core/molecules/useDataDnd.d.ts +5 -5
  15. package/dist/components/core/organisms/CardGrid.d.ts +5 -2
  16. package/dist/components/core/organisms/CaseStudyOrganism.d.ts +4 -3
  17. package/dist/components/core/organisms/DataTable.d.ts +4 -2
  18. package/dist/components/core/organisms/DetailPanel.d.ts +6 -6
  19. package/dist/components/core/organisms/FeatureGridOrganism.d.ts +4 -3
  20. package/dist/components/core/organisms/HeroOrganism.d.ts +4 -5
  21. package/dist/components/core/organisms/List.d.ts +5 -2
  22. package/dist/components/core/organisms/MasterDetail.d.ts +4 -2
  23. package/dist/components/core/organisms/MediaGallery.d.ts +4 -2
  24. package/dist/components/core/organisms/ShowcaseOrganism.d.ts +4 -3
  25. package/dist/components/core/organisms/StatCard.d.ts +5 -2
  26. package/dist/components/core/organisms/StepFlowOrganism.d.ts +4 -3
  27. package/dist/components/core/organisms/Timeline.d.ts +2 -2
  28. package/dist/components/core/organisms/book/index.d.ts +1 -1
  29. package/dist/components/core/organisms/book/types.d.ts +28 -48
  30. package/dist/components/core/organisms/index.d.ts +1 -2
  31. package/dist/components/core/organisms/layout/DashboardGrid.d.ts +2 -2
  32. package/dist/components/core/organisms/marketing-types.d.ts +5 -94
  33. package/dist/components/core/organisms/types.d.ts +9 -27
  34. package/dist/components/core/templates/index.d.ts +6 -6
  35. package/dist/components/game/organisms/BattleBoard.d.ts +14 -90
  36. package/dist/components/game/organisms/CastleBoard.d.ts +7 -21
  37. package/dist/components/game/organisms/UncontrolledBattleBoard.d.ts +2 -7
  38. package/dist/components/game/organisms/WorldMapBoard.d.ts +13 -59
  39. package/dist/components/game/organisms/boardEntity.d.ts +44 -0
  40. package/dist/components/game/organisms/hooks/useBattleState.d.ts +7 -7
  41. package/dist/components/game/organisms/index.d.ts +3 -3
  42. package/dist/components/game/organisms/puzzles/builder/BuilderBoard.d.ts +7 -20
  43. package/dist/components/game/organisms/puzzles/builder/index.d.ts +1 -1
  44. package/dist/components/game/organisms/puzzles/classifier/ClassifierBoard.d.ts +7 -20
  45. package/dist/components/game/organisms/puzzles/classifier/index.d.ts +1 -1
  46. package/dist/components/game/organisms/puzzles/debugger/DebuggerBoard.d.ts +6 -22
  47. package/dist/components/game/organisms/puzzles/debugger/index.d.ts +1 -1
  48. package/dist/components/game/organisms/puzzles/event-handler/EventHandlerBoard.d.ts +6 -33
  49. package/dist/components/game/organisms/puzzles/event-handler/ObjectRulePanel.d.ts +3 -21
  50. package/dist/components/game/organisms/puzzles/event-handler/index.d.ts +2 -2
  51. package/dist/components/game/organisms/puzzles/event-handler/puzzleObject.d.ts +21 -0
  52. package/dist/components/game/organisms/puzzles/negotiator/NegotiatorBoard.d.ts +8 -24
  53. package/dist/components/game/organisms/puzzles/negotiator/index.d.ts +1 -1
  54. package/dist/components/game/organisms/puzzles/sequencer/ActionTile.d.ts +2 -2
  55. package/dist/components/game/organisms/puzzles/sequencer/SequencerBoard.d.ts +7 -36
  56. package/dist/components/game/organisms/puzzles/sequencer/index.d.ts +1 -1
  57. package/dist/components/game/organisms/puzzles/simulator/SimulatorBoard.d.ts +6 -25
  58. package/dist/components/game/organisms/puzzles/simulator/index.d.ts +1 -1
  59. package/dist/components/game/organisms/puzzles/state-architect/StateArchitectBoard.d.ts +7 -40
  60. package/dist/components/game/organisms/puzzles/state-architect/VariablePanel.d.ts +3 -9
  61. package/dist/components/game/organisms/puzzles/state-architect/index.d.ts +2 -2
  62. package/dist/components/game/organisms/three/index.cjs +35 -21
  63. package/dist/components/game/organisms/three/index.js +35 -21
  64. package/dist/components/game/templates/BattleTemplate.d.ts +2 -3
  65. package/dist/components/game/templates/CastleTemplate.d.ts +2 -3
  66. package/dist/components/game/templates/GameCanvas3DBattleTemplate.d.ts +1 -16
  67. package/dist/components/game/templates/GameCanvas3DCastleTemplate.d.ts +1 -18
  68. package/dist/components/game/templates/GameCanvas3DWorldMapTemplate.d.ts +1 -14
  69. package/dist/components/game/templates/GameTemplate.d.ts +1 -6
  70. package/dist/components/game/templates/WorldMapTemplate.d.ts +2 -3
  71. package/dist/components/index.cjs +2036 -1675
  72. package/dist/components/index.js +1148 -787
  73. package/dist/components/marketing/organisms/PricingOrganism.d.ts +4 -3
  74. package/dist/components/marketing/organisms/StatsOrganism.d.ts +4 -3
  75. package/dist/components/marketing/organisms/TeamOrganism.d.ts +4 -3
  76. package/dist/components/marketing/organisms/book/BookChapterView.d.ts +5 -2
  77. package/dist/components/marketing/organisms/book/BookTableOfContents.d.ts +3 -2
  78. package/dist/components/marketing/organisms/book/BookViewer.d.ts +4 -4
  79. package/dist/components/marketing/templates/AboutPageTemplate.d.ts +32 -6
  80. package/dist/components/marketing/templates/FeatureDetailPageTemplate.d.ts +14 -4
  81. package/dist/components/marketing/templates/LandingPageTemplate.d.ts +47 -9
  82. package/dist/components/marketing/templates/PricingPageTemplate.d.ts +23 -5
  83. package/dist/providers/index.cjs +932 -631
  84. package/dist/providers/index.js +932 -631
  85. package/dist/runtime/index.cjs +934 -633
  86. package/dist/runtime/index.js +934 -633
  87. package/package.json +2 -2
@@ -1,6 +1,6 @@
1
1
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
2
- import * as React79 from 'react';
3
- import React79__default, { useContext, useMemo, useRef, useEffect, useCallback, Suspense, useState, lazy, createContext, useLayoutEffect, useId, useSyncExternalStore } from 'react';
2
+ import * as React80 from 'react';
3
+ import React80__default, { useContext, useMemo, useRef, useEffect, useCallback, Suspense, useState, lazy, createContext, useLayoutEffect, useId, useSyncExternalStore } from 'react';
4
4
  import { clsx } from 'clsx';
5
5
  import { twMerge } from 'tailwind-merge';
6
6
  import { EventBusContext, useTraitScope, TraitScopeProvider } from '@almadar/ui/providers';
@@ -211,7 +211,7 @@ var init_SvgFlow = __esm({
211
211
  opacity = 1,
212
212
  className
213
213
  }) => {
214
- const markerId = React79__default.useMemo(() => {
214
+ const markerId = React80__default.useMemo(() => {
215
215
  flowIdCounter += 1;
216
216
  return `almadar-flow-arrow-${flowIdCounter}`;
217
217
  }, []);
@@ -260,7 +260,7 @@ var init_SvgGrid = __esm({
260
260
  x,
261
261
  y,
262
262
  cols = 4,
263
- rows = 3,
263
+ rows: rows2 = 3,
264
264
  spacing = 20,
265
265
  nodeRadius = 3,
266
266
  color = "var(--color-primary)",
@@ -269,7 +269,7 @@ var init_SvgGrid = __esm({
269
269
  highlights = []
270
270
  }) => {
271
271
  const highlightSet = new Set(highlights);
272
- return /* @__PURE__ */ jsx("g", { className, opacity, children: Array.from({ length: rows }).map(
272
+ return /* @__PURE__ */ jsx("g", { className, opacity, children: Array.from({ length: rows2 }).map(
273
273
  (_, row) => Array.from({ length: cols }).map((_2, col) => {
274
274
  const index = row * cols + col;
275
275
  const isHighlighted = highlightSet.has(index);
@@ -754,7 +754,7 @@ var init_SvgRing = __esm({
754
754
  className,
755
755
  label
756
756
  }) => {
757
- const gradientId = React79__default.useMemo(() => {
757
+ const gradientId = React80__default.useMemo(() => {
758
758
  ringIdCounter += 1;
759
759
  return `almadar-ring-glow-${ringIdCounter}`;
760
760
  }, []);
@@ -1836,7 +1836,7 @@ var init_Icon = __esm({
1836
1836
  const directIcon = typeof icon === "string" ? void 0 : icon;
1837
1837
  const effectiveName = typeof icon === "string" ? icon : name;
1838
1838
  const family = useIconFamily();
1839
- const RenderedComponent = React79__default.useMemo(() => {
1839
+ const RenderedComponent = React80__default.useMemo(() => {
1840
1840
  if (directIcon) return null;
1841
1841
  return effectiveName ? resolveIconForFamily(effectiveName, family) : null;
1842
1842
  }, [directIcon, effectiveName, family]);
@@ -1894,7 +1894,7 @@ function resolveIconProp(value, sizeClass) {
1894
1894
  const IconComp = value;
1895
1895
  return /* @__PURE__ */ jsx(IconComp, { className: sizeClass });
1896
1896
  }
1897
- if (React79__default.isValidElement(value)) {
1897
+ if (React80__default.isValidElement(value)) {
1898
1898
  return value;
1899
1899
  }
1900
1900
  if (typeof value === "object" && value !== null && "render" in value) {
@@ -1970,7 +1970,7 @@ var init_Button = __esm({
1970
1970
  md: "h-icon-default w-icon-default",
1971
1971
  lg: "h-icon-default w-icon-default"
1972
1972
  };
1973
- Button = React79__default.forwardRef(
1973
+ Button = React80__default.forwardRef(
1974
1974
  ({
1975
1975
  className,
1976
1976
  variant = "primary",
@@ -2036,7 +2036,7 @@ var init_Input = __esm({
2036
2036
  "components/core/atoms/Input.tsx"() {
2037
2037
  init_cn();
2038
2038
  init_Icon();
2039
- Input = React79__default.forwardRef(
2039
+ Input = React80__default.forwardRef(
2040
2040
  ({
2041
2041
  className,
2042
2042
  inputType,
@@ -2049,7 +2049,7 @@ var init_Input = __esm({
2049
2049
  onClear,
2050
2050
  value,
2051
2051
  options,
2052
- rows = 3,
2052
+ rows: rows2 = 3,
2053
2053
  onChange,
2054
2054
  ...props
2055
2055
  }, ref) => {
@@ -2099,7 +2099,7 @@ var init_Input = __esm({
2099
2099
  ref,
2100
2100
  value,
2101
2101
  onChange,
2102
- rows,
2102
+ rows: rows2,
2103
2103
  className: baseClassName,
2104
2104
  ...props
2105
2105
  }
@@ -2157,7 +2157,7 @@ var Label;
2157
2157
  var init_Label = __esm({
2158
2158
  "components/core/atoms/Label.tsx"() {
2159
2159
  init_cn();
2160
- Label = React79__default.forwardRef(
2160
+ Label = React80__default.forwardRef(
2161
2161
  ({ className, required, children, ...props }, ref) => {
2162
2162
  return /* @__PURE__ */ jsxs(
2163
2163
  "label",
@@ -2183,7 +2183,7 @@ var Textarea;
2183
2183
  var init_Textarea = __esm({
2184
2184
  "components/core/atoms/Textarea.tsx"() {
2185
2185
  init_cn();
2186
- Textarea = React79__default.forwardRef(
2186
+ Textarea = React80__default.forwardRef(
2187
2187
  ({ className, error, ...props }, ref) => {
2188
2188
  return /* @__PURE__ */ jsx(
2189
2189
  "textarea",
@@ -2213,7 +2213,7 @@ var init_Select = __esm({
2213
2213
  "components/core/atoms/Select.tsx"() {
2214
2214
  init_cn();
2215
2215
  init_Icon();
2216
- Select = React79__default.forwardRef(
2216
+ Select = React80__default.forwardRef(
2217
2217
  ({ className, options, placeholder, error, ...props }, ref) => {
2218
2218
  return /* @__PURE__ */ jsxs("div", { className: "relative", children: [
2219
2219
  /* @__PURE__ */ jsxs(
@@ -2255,7 +2255,7 @@ var Checkbox;
2255
2255
  var init_Checkbox = __esm({
2256
2256
  "components/core/atoms/Checkbox.tsx"() {
2257
2257
  init_cn();
2258
- Checkbox = React79__default.forwardRef(
2258
+ Checkbox = React80__default.forwardRef(
2259
2259
  ({ className, label, id, ...props }, ref) => {
2260
2260
  const inputId = id || `checkbox-${Math.random().toString(36).substr(2, 9)}`;
2261
2261
  return /* @__PURE__ */ jsxs("div", { className: "flex items-center", children: [
@@ -2346,7 +2346,7 @@ var init_Card = __esm({
2346
2346
  chip: "shadow-none rounded-pill border-[length:var(--border-width)] border-border",
2347
2347
  "tile-image-first": "p-0 overflow-hidden"
2348
2348
  };
2349
- Card = React79__default.forwardRef(
2349
+ Card = React80__default.forwardRef(
2350
2350
  ({
2351
2351
  className,
2352
2352
  variant = "bordered",
@@ -2384,9 +2384,9 @@ var init_Card = __esm({
2384
2384
  }
2385
2385
  );
2386
2386
  Card.displayName = "Card";
2387
- CardHeader = React79__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("mb-4", className), ...props }));
2387
+ CardHeader = React80__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("mb-4", className), ...props }));
2388
2388
  CardHeader.displayName = "CardHeader";
2389
- CardTitle = React79__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
2389
+ CardTitle = React80__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
2390
2390
  "h3",
2391
2391
  {
2392
2392
  ref,
@@ -2399,11 +2399,11 @@ var init_Card = __esm({
2399
2399
  }
2400
2400
  ));
2401
2401
  CardTitle.displayName = "CardTitle";
2402
- CardContent = React79__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("", className), ...props }));
2402
+ CardContent = React80__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("", className), ...props }));
2403
2403
  CardContent.displayName = "CardContent";
2404
2404
  CardBody = CardContent;
2405
2405
  CardBody.displayName = "CardBody";
2406
- CardFooter = React79__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
2406
+ CardFooter = React80__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
2407
2407
  "div",
2408
2408
  {
2409
2409
  ref,
@@ -2456,7 +2456,7 @@ var init_Badge = __esm({
2456
2456
  md: "px-2.5 py-1 text-sm",
2457
2457
  lg: "px-3 py-1.5 text-base"
2458
2458
  };
2459
- Badge = React79__default.forwardRef(
2459
+ Badge = React80__default.forwardRef(
2460
2460
  ({ className, variant = "default", size = "sm", amount, label, icon, children, onRemove, removeLabel, ...props }, ref) => {
2461
2461
  const iconSizes3 = {
2462
2462
  sm: "h-icon-default w-icon-default",
@@ -2549,7 +2549,7 @@ var init_FilterPill = __esm({
2549
2549
  md: "w-3.5 h-3.5",
2550
2550
  lg: "w-4 h-4"
2551
2551
  };
2552
- FilterPill = React79__default.forwardRef(
2552
+ FilterPill = React80__default.forwardRef(
2553
2553
  ({
2554
2554
  className,
2555
2555
  variant = "default",
@@ -2626,7 +2626,7 @@ var init_Spinner = __esm({
2626
2626
  md: "h-6 w-6",
2627
2627
  lg: "h-8 w-8"
2628
2628
  };
2629
- Spinner = React79__default.forwardRef(
2629
+ Spinner = React80__default.forwardRef(
2630
2630
  ({ className, size = "md", ...props }, ref) => {
2631
2631
  return /* @__PURE__ */ jsx(
2632
2632
  "div",
@@ -2910,7 +2910,7 @@ var init_Box = __esm({
2910
2910
  fixed: "fixed",
2911
2911
  sticky: "sticky"
2912
2912
  };
2913
- Box = React79__default.forwardRef(
2913
+ Box = React80__default.forwardRef(
2914
2914
  ({
2915
2915
  padding,
2916
2916
  paddingX,
@@ -2960,7 +2960,7 @@ var init_Box = __esm({
2960
2960
  onMouseLeave?.(e);
2961
2961
  }, [hoverEvent, eventBus, onMouseLeave]);
2962
2962
  const isClickable = action || onClick;
2963
- return React79__default.createElement(
2963
+ return React80__default.createElement(
2964
2964
  Component,
2965
2965
  {
2966
2966
  ref,
@@ -3282,7 +3282,7 @@ var init_Radio = __esm({
3282
3282
  md: "w-2.5 h-2.5",
3283
3283
  lg: "w-3 h-3"
3284
3284
  };
3285
- Radio = React79__default.forwardRef(
3285
+ Radio = React80__default.forwardRef(
3286
3286
  ({
3287
3287
  label,
3288
3288
  helperText,
@@ -3299,12 +3299,12 @@ var init_Radio = __esm({
3299
3299
  onChange,
3300
3300
  ...props
3301
3301
  }, ref) => {
3302
- const reactId = React79__default.useId();
3302
+ const reactId = React80__default.useId();
3303
3303
  const baseId = id || `radio-${reactId}`;
3304
3304
  const hasError = !!error;
3305
3305
  const eventBus = useEventBus();
3306
- const [selected, setSelected] = React79__default.useState(value);
3307
- React79__default.useEffect(() => {
3306
+ const [selected, setSelected] = React80__default.useState(value);
3307
+ React80__default.useEffect(() => {
3308
3308
  if (value !== void 0) setSelected(value);
3309
3309
  }, [value]);
3310
3310
  const pick = (next, e) => {
@@ -3486,7 +3486,7 @@ var init_Switch = __esm({
3486
3486
  "components/core/atoms/Switch.tsx"() {
3487
3487
  "use client";
3488
3488
  init_cn();
3489
- Switch = React79.forwardRef(
3489
+ Switch = React80.forwardRef(
3490
3490
  ({
3491
3491
  checked,
3492
3492
  defaultChecked = false,
@@ -3497,10 +3497,10 @@ var init_Switch = __esm({
3497
3497
  name,
3498
3498
  className
3499
3499
  }, ref) => {
3500
- const [isChecked, setIsChecked] = React79.useState(
3500
+ const [isChecked, setIsChecked] = React80.useState(
3501
3501
  checked !== void 0 ? checked : defaultChecked
3502
3502
  );
3503
- React79.useEffect(() => {
3503
+ React80.useEffect(() => {
3504
3504
  if (checked !== void 0) {
3505
3505
  setIsChecked(checked);
3506
3506
  }
@@ -4371,7 +4371,7 @@ var Dialog;
4371
4371
  var init_Dialog = __esm({
4372
4372
  "components/core/atoms/Dialog.tsx"() {
4373
4373
  init_cn();
4374
- Dialog = React79__default.forwardRef(
4374
+ Dialog = React80__default.forwardRef(
4375
4375
  ({
4376
4376
  role = "dialog",
4377
4377
  "aria-modal": ariaModal = true,
@@ -4397,7 +4397,7 @@ var Aside;
4397
4397
  var init_Aside = __esm({
4398
4398
  "components/core/atoms/Aside.tsx"() {
4399
4399
  init_cn();
4400
- Aside = React79__default.forwardRef(
4400
+ Aside = React80__default.forwardRef(
4401
4401
  ({ className, children, ...rest }, ref) => /* @__PURE__ */ jsx("aside", { ref, className: cn(className), ...rest, children })
4402
4402
  );
4403
4403
  Aside.displayName = "Aside";
@@ -4475,8 +4475,8 @@ var init_LawReferenceTooltip = __esm({
4475
4475
  className
4476
4476
  }) => {
4477
4477
  const { t } = useTranslate();
4478
- const [isVisible, setIsVisible] = React79__default.useState(false);
4479
- const timeoutRef = React79__default.useRef(null);
4478
+ const [isVisible, setIsVisible] = React80__default.useState(false);
4479
+ const timeoutRef = React80__default.useRef(null);
4480
4480
  const handleMouseEnter = () => {
4481
4481
  if (timeoutRef.current) clearTimeout(timeoutRef.current);
4482
4482
  timeoutRef.current = setTimeout(() => setIsVisible(true), 200);
@@ -4485,7 +4485,7 @@ var init_LawReferenceTooltip = __esm({
4485
4485
  if (timeoutRef.current) clearTimeout(timeoutRef.current);
4486
4486
  setIsVisible(false);
4487
4487
  };
4488
- React79__default.useEffect(() => {
4488
+ React80__default.useEffect(() => {
4489
4489
  return () => {
4490
4490
  if (timeoutRef.current) clearTimeout(timeoutRef.current);
4491
4491
  };
@@ -4695,7 +4695,7 @@ var init_StatusDot = __esm({
4695
4695
  md: "w-2.5 h-2.5",
4696
4696
  lg: "w-3 h-3"
4697
4697
  };
4698
- StatusDot = React79__default.forwardRef(
4698
+ StatusDot = React80__default.forwardRef(
4699
4699
  ({ className, status = "offline", pulse = false, size = "md", label, ...props }, ref) => {
4700
4700
  return /* @__PURE__ */ jsx(
4701
4701
  "span",
@@ -4749,7 +4749,7 @@ var init_TrendIndicator = __esm({
4749
4749
  down: "trending-down",
4750
4750
  flat: "arrow-right"
4751
4751
  };
4752
- TrendIndicator = React79__default.forwardRef(
4752
+ TrendIndicator = React80__default.forwardRef(
4753
4753
  ({
4754
4754
  className,
4755
4755
  value,
@@ -4816,7 +4816,7 @@ var init_RangeSlider = __esm({
4816
4816
  md: "w-4 h-4",
4817
4817
  lg: "w-5 h-5"
4818
4818
  };
4819
- RangeSlider = React79__default.forwardRef(
4819
+ RangeSlider = React80__default.forwardRef(
4820
4820
  ({
4821
4821
  className,
4822
4822
  min = 0,
@@ -5412,7 +5412,7 @@ var init_ContentSection = __esm({
5412
5412
  md: "py-16",
5413
5413
  lg: "py-24"
5414
5414
  };
5415
- ContentSection = React79__default.forwardRef(
5415
+ ContentSection = React80__default.forwardRef(
5416
5416
  ({ children, background = "default", padding = "lg", id, className }, ref) => {
5417
5417
  return /* @__PURE__ */ jsx(
5418
5418
  Box,
@@ -5946,7 +5946,7 @@ var init_AnimatedReveal = __esm({
5946
5946
  "scale-up": { opacity: 1, transform: "scale(1) translateY(0)" },
5947
5947
  "none": {}
5948
5948
  };
5949
- AnimatedReveal = React79__default.forwardRef(
5949
+ AnimatedReveal = React80__default.forwardRef(
5950
5950
  ({
5951
5951
  trigger = "scroll",
5952
5952
  animation = "fade-up",
@@ -6106,7 +6106,7 @@ var init_AnimatedGraphic = __esm({
6106
6106
  "components/marketing/atoms/AnimatedGraphic.tsx"() {
6107
6107
  "use client";
6108
6108
  init_cn();
6109
- AnimatedGraphic = React79__default.forwardRef(
6109
+ AnimatedGraphic = React80__default.forwardRef(
6110
6110
  ({
6111
6111
  src,
6112
6112
  svgContent,
@@ -6129,7 +6129,7 @@ var init_AnimatedGraphic = __esm({
6129
6129
  const fetchedSvg = useFetchedSvg(svgContent ? void 0 : src);
6130
6130
  const resolvedSvg = svgContent ?? fetchedSvg;
6131
6131
  const prevAnimateRef = useRef(animate);
6132
- const setRef = React79__default.useCallback(
6132
+ const setRef = React80__default.useCallback(
6133
6133
  (node) => {
6134
6134
  containerRef.current = node;
6135
6135
  if (typeof ref === "function") ref(node);
@@ -6819,7 +6819,7 @@ var init_ErrorBoundary = __esm({
6819
6819
  }
6820
6820
  );
6821
6821
  };
6822
- ErrorBoundary = class extends React79__default.Component {
6822
+ ErrorBoundary = class extends React80__default.Component {
6823
6823
  constructor(props) {
6824
6824
  super(props);
6825
6825
  __publicField(this, "reset", () => {
@@ -6864,15 +6864,15 @@ function HeaderSkeleton({ className }) {
6864
6864
  ] })
6865
6865
  ] });
6866
6866
  }
6867
- function TableSkeleton({ rows = 5, columns = 4, className }) {
6867
+ function TableSkeleton({ rows: rows2 = 5, columns = 4, className }) {
6868
6868
  return /* @__PURE__ */ jsxs(VStack, { gap: "none", className: cn("border border-border rounded-lg overflow-hidden", className), children: [
6869
6869
  /* @__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)) }),
6870
- Array.from({ length: rows }).map((_, rowIdx) => /* @__PURE__ */ jsx(
6870
+ Array.from({ length: rows2 }).map((_, rowIdx) => /* @__PURE__ */ jsx(
6871
6871
  HStack,
6872
6872
  {
6873
6873
  className: cn(
6874
6874
  "px-4 py-3",
6875
- rowIdx < rows - 1 && "border-b border-border"
6875
+ rowIdx < rows2 - 1 && "border-b border-border"
6876
6876
  ),
6877
6877
  children: Array.from({ length: columns }).map((_2, colIdx) => /* @__PURE__ */ jsx(SkeletonLine, { className: "flex-1 mx-2" }, colIdx))
6878
6878
  },
@@ -6920,18 +6920,18 @@ function CardSkeleton({ className }) {
6920
6920
  }
6921
6921
  );
6922
6922
  }
6923
- function TextSkeleton({ rows = 3, className }) {
6924
- return /* @__PURE__ */ jsx(VStack, { gap: "sm", className, children: Array.from({ length: rows }).map((_, i) => /* @__PURE__ */ jsx(
6923
+ function TextSkeleton({ rows: rows2 = 3, className }) {
6924
+ return /* @__PURE__ */ jsx(VStack, { gap: "sm", className, children: Array.from({ length: rows2 }).map((_, i) => /* @__PURE__ */ jsx(
6925
6925
  SkeletonLine,
6926
6926
  {
6927
- className: i === rows - 1 ? "w-2/3" : "w-full"
6927
+ className: i === rows2 - 1 ? "w-2/3" : "w-full"
6928
6928
  },
6929
6929
  i
6930
6930
  )) });
6931
6931
  }
6932
6932
  function Skeleton({
6933
6933
  variant = "text",
6934
- rows,
6934
+ rows: rows2,
6935
6935
  columns,
6936
6936
  fields,
6937
6937
  className
@@ -6941,15 +6941,15 @@ function Skeleton({
6941
6941
  case "header":
6942
6942
  return /* @__PURE__ */ jsx(HeaderSkeleton, { className });
6943
6943
  case "table":
6944
- return /* @__PURE__ */ jsx(TableSkeleton, { rows, columns, className });
6944
+ return /* @__PURE__ */ jsx(TableSkeleton, { rows: rows2, columns, className });
6945
6945
  case "form":
6946
6946
  return /* @__PURE__ */ jsx(FormSkeleton, { fields, className });
6947
6947
  case "card":
6948
6948
  return /* @__PURE__ */ jsx(CardSkeleton, { className });
6949
6949
  case "text":
6950
- return /* @__PURE__ */ jsx(TextSkeleton, { rows, className });
6950
+ return /* @__PURE__ */ jsx(TextSkeleton, { rows: rows2, className });
6951
6951
  default:
6952
- return /* @__PURE__ */ jsx(TextSkeleton, { rows, className });
6952
+ return /* @__PURE__ */ jsx(TextSkeleton, { rows: rows2, className });
6953
6953
  }
6954
6954
  }
6955
6955
  var pulseClass;
@@ -7858,8 +7858,8 @@ var init_Tooltip = __esm({
7858
7858
  if (hideTimeoutRef.current) clearTimeout(hideTimeoutRef.current);
7859
7859
  };
7860
7860
  }, []);
7861
- const triggerElement = React79__default.isValidElement(children) ? children : /* @__PURE__ */ jsx("span", { children });
7862
- const trigger = React79__default.cloneElement(triggerElement, {
7861
+ const triggerElement = React80__default.isValidElement(children) ? children : /* @__PURE__ */ jsx("span", { children });
7862
+ const trigger = React80__default.cloneElement(triggerElement, {
7863
7863
  ref: triggerRef,
7864
7864
  onMouseEnter: handleMouseEnter,
7865
7865
  onMouseLeave: handleMouseLeave,
@@ -8014,8 +8014,8 @@ var init_Popover = __esm({
8014
8014
  onMouseEnter: handleOpen,
8015
8015
  onMouseLeave: handleClose
8016
8016
  };
8017
- const childElement = React79__default.isValidElement(children) ? children : /* @__PURE__ */ jsx("span", { children });
8018
- const triggerElement = React79__default.cloneElement(
8017
+ const childElement = React80__default.isValidElement(children) ? children : /* @__PURE__ */ jsx("span", { children });
8018
+ const triggerElement = React80__default.cloneElement(
8019
8019
  childElement,
8020
8020
  {
8021
8021
  ref: triggerRef,
@@ -8076,7 +8076,7 @@ var init_Menu = __esm({
8076
8076
  className
8077
8077
  }) => {
8078
8078
  const eventBus = useEventBus();
8079
- const { t } = useTranslate();
8079
+ const { t, direction } = useTranslate();
8080
8080
  const [isOpen, setIsOpen] = useState(false);
8081
8081
  const [activeSubMenu, setActiveSubMenu] = useState(null);
8082
8082
  const [triggerRect, setTriggerRect] = useState(null);
@@ -8130,8 +8130,20 @@ var init_Menu = __esm({
8130
8130
  "bottom-start": "top-full left-0 mt-2",
8131
8131
  "bottom-end": "top-full right-0 mt-2"
8132
8132
  };
8133
- const triggerChild = React79__default.isValidElement(trigger) ? trigger : /* @__PURE__ */ jsx(Typography, { variant: "small", as: "span", children: trigger });
8134
- const triggerElement = React79__default.cloneElement(
8133
+ const rtlMirror = {
8134
+ "top-left": "top-right",
8135
+ "top-right": "top-left",
8136
+ "bottom-left": "bottom-right",
8137
+ "bottom-right": "bottom-left",
8138
+ "top-start": "top-end",
8139
+ "top-end": "top-start",
8140
+ "bottom-start": "bottom-end",
8141
+ "bottom-end": "bottom-start"
8142
+ };
8143
+ const effectivePosition = direction === "rtl" ? rtlMirror[position] ?? position : position;
8144
+ const subMenuSideClass = direction === "rtl" ? "right-full mr-2" : "left-full ml-2";
8145
+ const triggerChild = React80__default.isValidElement(trigger) ? trigger : /* @__PURE__ */ jsx(Typography, { variant: "small", as: "span", children: trigger });
8146
+ const triggerElement = React80__default.cloneElement(
8135
8147
  triggerChild,
8136
8148
  {
8137
8149
  ref: triggerRef,
@@ -8157,7 +8169,7 @@ var init_Menu = __esm({
8157
8169
  onMouseEnter: () => hasSubMenu && setActiveSubMenu(itemId),
8158
8170
  "data-testid": item.event ? `action-${item.event}` : void 0,
8159
8171
  className: cn(
8160
- "w-full flex items-center justify-between gap-3 px-4 py-2 text-left",
8172
+ "w-full flex items-center justify-between gap-3 px-4 py-2 text-start",
8161
8173
  "text-sm transition-colors",
8162
8174
  "hover:bg-muted",
8163
8175
  "focus:outline-none focus:bg-muted",
@@ -8176,7 +8188,7 @@ var init_Menu = __esm({
8176
8188
  }
8177
8189
  ),
8178
8190
  item.badge !== void 0 && /* @__PURE__ */ jsx(Badge, { variant: "default", size: "sm", children: item.badge }),
8179
- hasSubMenu && /* @__PURE__ */ jsx(Icon, { name: "chevron-right", size: "sm", className: "flex-shrink-0" })
8191
+ hasSubMenu && /* @__PURE__ */ jsx(Icon, { name: direction === "rtl" ? "chevron-left" : "chevron-right", size: "sm", className: "flex-shrink-0" })
8180
8192
  ] })
8181
8193
  },
8182
8194
  itemId
@@ -8196,7 +8208,8 @@ var init_Menu = __esm({
8196
8208
  Box,
8197
8209
  {
8198
8210
  className: cn(
8199
- "absolute left-full top-0 ml-2 z-50",
8211
+ "absolute top-0 z-50",
8212
+ subMenuSideClass,
8200
8213
  menuContainerStyles
8201
8214
  ),
8202
8215
  children: renderMenuItems(item.subMenu)
@@ -8214,12 +8227,12 @@ var init_Menu = __esm({
8214
8227
  className: cn(
8215
8228
  "absolute z-50",
8216
8229
  menuContainerStyles,
8217
- positionClasses3[position],
8230
+ positionClasses3[effectivePosition],
8218
8231
  className
8219
8232
  ),
8220
8233
  style: {
8221
- left: position.includes("left") ? 0 : "auto",
8222
- right: position.includes("right") ? 0 : "auto"
8234
+ left: effectivePosition.includes("left") ? 0 : "auto",
8235
+ right: effectivePosition.includes("right") ? 0 : "auto"
8223
8236
  },
8224
8237
  role: "menu",
8225
8238
  children: renderMenuItems(items)
@@ -8537,13 +8550,13 @@ var init_MapView = __esm({
8537
8550
  shadowSize: [41, 41]
8538
8551
  });
8539
8552
  L.Marker.prototype.options.icon = defaultIcon;
8540
- const { useEffect: useEffect69, useRef: useRef66, useCallback: useCallback113, useState: useState99 } = React79__default;
8553
+ const { useEffect: useEffect70, useRef: useRef67, useCallback: useCallback114, useState: useState100 } = React80__default;
8541
8554
  const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
8542
8555
  const { useEventBus: useEventBus2 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
8543
8556
  function MapUpdater({ centerLat, centerLng, zoom }) {
8544
8557
  const map = useMap();
8545
- const prevRef = useRef66({ centerLat, centerLng, zoom });
8546
- useEffect69(() => {
8558
+ const prevRef = useRef67({ centerLat, centerLng, zoom });
8559
+ useEffect70(() => {
8547
8560
  const prev = prevRef.current;
8548
8561
  if (prev.centerLat !== centerLat || prev.centerLng !== centerLng || prev.zoom !== zoom) {
8549
8562
  map.setView([centerLat, centerLng], zoom);
@@ -8554,7 +8567,7 @@ var init_MapView = __esm({
8554
8567
  }
8555
8568
  function MapClickHandler({ onMapClick }) {
8556
8569
  const map = useMap();
8557
- useEffect69(() => {
8570
+ useEffect70(() => {
8558
8571
  if (!onMapClick) return;
8559
8572
  const handler = (e) => {
8560
8573
  onMapClick(e.latlng.lat, e.latlng.lng);
@@ -8582,8 +8595,8 @@ var init_MapView = __esm({
8582
8595
  showAttribution = true
8583
8596
  }) {
8584
8597
  const eventBus = useEventBus2();
8585
- const [clickedPosition, setClickedPosition] = useState99(null);
8586
- const handleMapClick = useCallback113((lat, lng) => {
8598
+ const [clickedPosition, setClickedPosition] = useState100(null);
8599
+ const handleMapClick = useCallback114((lat, lng) => {
8587
8600
  if (showClickedPin) {
8588
8601
  setClickedPosition({ lat, lng });
8589
8602
  }
@@ -8592,7 +8605,7 @@ var init_MapView = __esm({
8592
8605
  eventBus.emit(`UI:${mapClickEvent}`, { latitude: lat, longitude: lng });
8593
8606
  }
8594
8607
  }, [onMapClick, mapClickEvent, eventBus, showClickedPin]);
8595
- const handleMarkerClick = useCallback113((marker) => {
8608
+ const handleMarkerClick = useCallback114((marker) => {
8596
8609
  onMarkerClick?.(marker);
8597
8610
  if (markerClickEvent) {
8598
8611
  eventBus.emit(`UI:${markerClickEvent}`, { ...marker });
@@ -8783,7 +8796,7 @@ function InputPattern({
8783
8796
  fieldName
8784
8797
  }) {
8785
8798
  const { emit } = useEventBus();
8786
- const [localValue, setLocalValue] = React79__default.useState(value);
8799
+ const [localValue, setLocalValue] = React80__default.useState(value);
8787
8800
  const handleChange = (e) => {
8788
8801
  setLocalValue(e.target.value);
8789
8802
  if (onChange) {
@@ -8813,7 +8826,7 @@ function InputPattern({
8813
8826
  function TextareaPattern({
8814
8827
  value = "",
8815
8828
  placeholder,
8816
- rows = 4,
8829
+ rows: rows2 = 4,
8817
8830
  disabled = false,
8818
8831
  fieldError,
8819
8832
  onChange,
@@ -8821,7 +8834,7 @@ function TextareaPattern({
8821
8834
  fieldName
8822
8835
  }) {
8823
8836
  const { emit } = useEventBus();
8824
- const [localValue, setLocalValue] = React79__default.useState(value);
8837
+ const [localValue, setLocalValue] = React80__default.useState(value);
8825
8838
  const handleChange = (e) => {
8826
8839
  setLocalValue(e.target.value);
8827
8840
  if (onChange) {
@@ -8833,7 +8846,7 @@ function TextareaPattern({
8833
8846
  {
8834
8847
  value: localValue,
8835
8848
  placeholder,
8836
- rows,
8849
+ rows: rows2,
8837
8850
  disabled,
8838
8851
  error: fieldError,
8839
8852
  onChange: handleChange,
@@ -8853,7 +8866,7 @@ function SelectPattern({
8853
8866
  fieldName
8854
8867
  }) {
8855
8868
  const { emit } = useEventBus();
8856
- const [localValue, setLocalValue] = React79__default.useState(value);
8869
+ const [localValue, setLocalValue] = React80__default.useState(value);
8857
8870
  const handleChange = (e) => {
8858
8871
  setLocalValue(e.target.value);
8859
8872
  if (onChange) {
@@ -8882,7 +8895,7 @@ function CheckboxPattern({
8882
8895
  className
8883
8896
  }) {
8884
8897
  const { emit } = useEventBus();
8885
- const [localChecked, setLocalChecked] = React79__default.useState(checked);
8898
+ const [localChecked, setLocalChecked] = React80__default.useState(checked);
8886
8899
  const handleChange = (e) => {
8887
8900
  setLocalChecked(e.target.checked);
8888
8901
  if (onChange) {
@@ -9195,9 +9208,9 @@ function ControlButton({
9195
9208
  className
9196
9209
  }) {
9197
9210
  const eventBus = useEventBus();
9198
- const [isPressed, setIsPressed] = React79.useState(false);
9211
+ const [isPressed, setIsPressed] = React80.useState(false);
9199
9212
  const actualPressed = pressed ?? isPressed;
9200
- const handlePointerDown = React79.useCallback(
9213
+ const handlePointerDown = React80.useCallback(
9201
9214
  (e) => {
9202
9215
  e.preventDefault();
9203
9216
  if (disabled) return;
@@ -9207,7 +9220,7 @@ function ControlButton({
9207
9220
  },
9208
9221
  [disabled, pressEvent, eventBus, onPress]
9209
9222
  );
9210
- const handlePointerUp = React79.useCallback(
9223
+ const handlePointerUp = React80.useCallback(
9211
9224
  (e) => {
9212
9225
  e.preventDefault();
9213
9226
  if (disabled) return;
@@ -9217,7 +9230,7 @@ function ControlButton({
9217
9230
  },
9218
9231
  [disabled, releaseEvent, eventBus, onRelease]
9219
9232
  );
9220
- const handlePointerLeave = React79.useCallback(
9233
+ const handlePointerLeave = React80.useCallback(
9221
9234
  (e) => {
9222
9235
  if (isPressed) {
9223
9236
  setIsPressed(false);
@@ -9294,8 +9307,8 @@ function ActionButtons({
9294
9307
  disabled
9295
9308
  }) {
9296
9309
  const eventBus = useEventBus();
9297
- const [activeButtons, setActiveButtons] = React79.useState(/* @__PURE__ */ new Set());
9298
- const handlePress = React79.useCallback(
9310
+ const [activeButtons, setActiveButtons] = React80.useState(/* @__PURE__ */ new Set());
9311
+ const handlePress = React80.useCallback(
9299
9312
  (id) => {
9300
9313
  setActiveButtons((prev) => new Set(prev).add(id));
9301
9314
  if (actionEvent) eventBus.emit(`UI:${actionEvent}`, { id, pressed: true });
@@ -9303,7 +9316,7 @@ function ActionButtons({
9303
9316
  },
9304
9317
  [actionEvent, eventBus, onAction]
9305
9318
  );
9306
- const handleRelease = React79.useCallback(
9319
+ const handleRelease = React80.useCallback(
9307
9320
  (id) => {
9308
9321
  setActiveButtons((prev) => {
9309
9322
  const next = new Set(prev);
@@ -9499,6 +9512,91 @@ var init_ActionPalette = __esm({
9499
9512
  ActionPalette.displayName = "ActionPalette";
9500
9513
  }
9501
9514
  });
9515
+ function parseValue(value) {
9516
+ if (value === "" || value == null) return { num: 0, prefix: "", suffix: "", decimals: 0 };
9517
+ const match = String(value).match(/^([^0-9]*)([0-9]+(?:\.[0-9]+)?)(.*)$/);
9518
+ if (!match) {
9519
+ return { num: 0, prefix: "", suffix: String(value), decimals: 0 };
9520
+ }
9521
+ const numStr = match[2];
9522
+ const decimalIdx = numStr.indexOf(".");
9523
+ const decimals = decimalIdx >= 0 ? numStr.length - decimalIdx - 1 : 0;
9524
+ return {
9525
+ prefix: match[1],
9526
+ num: parseFloat(numStr),
9527
+ suffix: match[3],
9528
+ decimals
9529
+ };
9530
+ }
9531
+ var AnimatedCounter2;
9532
+ var init_AnimatedCounter2 = __esm({
9533
+ "components/core/molecules/AnimatedCounter.tsx"() {
9534
+ "use client";
9535
+ init_cn();
9536
+ init_Box();
9537
+ init_Typography();
9538
+ AnimatedCounter2 = ({
9539
+ value,
9540
+ label,
9541
+ duration = 1500,
9542
+ className
9543
+ }) => {
9544
+ const ref = useRef(null);
9545
+ const [displayValue, setDisplayValue] = useState("0");
9546
+ const [hasAnimated, setHasAnimated] = useState(false);
9547
+ const animate = useCallback(() => {
9548
+ const { num: num2, prefix, suffix, decimals } = parseValue(value);
9549
+ if (num2 === 0) {
9550
+ setDisplayValue(String(value));
9551
+ return;
9552
+ }
9553
+ const startTime = performance.now();
9554
+ const tick = (now) => {
9555
+ const elapsed = now - startTime;
9556
+ const progress = Math.min(elapsed / duration, 1);
9557
+ const eased = 1 - Math.pow(1 - progress, 3);
9558
+ const current = eased * num2;
9559
+ setDisplayValue(`${prefix}${current.toFixed(decimals)}${suffix}`);
9560
+ if (progress < 1) {
9561
+ requestAnimationFrame(tick);
9562
+ } else {
9563
+ setDisplayValue(String(value));
9564
+ }
9565
+ };
9566
+ requestAnimationFrame(tick);
9567
+ }, [value, duration]);
9568
+ useEffect(() => {
9569
+ if (hasAnimated) return;
9570
+ const el = ref.current;
9571
+ if (!el) return;
9572
+ const observer2 = new IntersectionObserver(
9573
+ (entries) => {
9574
+ if (entries[0].isIntersecting) {
9575
+ setHasAnimated(true);
9576
+ animate();
9577
+ observer2.disconnect();
9578
+ }
9579
+ },
9580
+ { threshold: 0.3 }
9581
+ );
9582
+ observer2.observe(el);
9583
+ return () => observer2.disconnect();
9584
+ }, [hasAnimated, animate]);
9585
+ return /* @__PURE__ */ jsxs(Box, { ref, className: cn("flex flex-col items-center gap-1 p-4", className), children: [
9586
+ /* @__PURE__ */ jsx(
9587
+ Typography,
9588
+ {
9589
+ variant: "h2",
9590
+ className: "text-primary font-bold tabular-nums",
9591
+ children: hasAnimated ? displayValue : "0"
9592
+ }
9593
+ ),
9594
+ /* @__PURE__ */ jsx(Typography, { variant: "body2", color: "muted", className: "text-center", children: label })
9595
+ ] });
9596
+ };
9597
+ AnimatedCounter2.displayName = "AnimatedCounter";
9598
+ }
9599
+ });
9502
9600
  var AuthLayout;
9503
9601
  var init_AuthLayout = __esm({
9504
9602
  "components/core/templates/AuthLayout.tsx"() {
@@ -10751,6 +10849,39 @@ var init_IsometricCanvas2 = __esm({
10751
10849
  init_IsometricCanvas();
10752
10850
  }
10753
10851
  });
10852
+
10853
+ // components/game/organisms/boardEntity.ts
10854
+ function boardEntity(entity) {
10855
+ if (!entity) return void 0;
10856
+ return Array.isArray(entity) ? entity[0] : entity;
10857
+ }
10858
+ function str(v) {
10859
+ return v == null ? "" : String(v);
10860
+ }
10861
+ function num(v, fallback = 0) {
10862
+ const n = Number(v);
10863
+ return Number.isFinite(n) ? n : fallback;
10864
+ }
10865
+ function rows(v) {
10866
+ return Array.isArray(v) ? v : [];
10867
+ }
10868
+ function vec2(v) {
10869
+ const o = v ?? {};
10870
+ return { x: num(o.x), y: num(o.y) };
10871
+ }
10872
+ function unitPosition(u) {
10873
+ return vec2(u.position);
10874
+ }
10875
+ function unitTeam(u) {
10876
+ return str(u.team);
10877
+ }
10878
+ function unitHealth(u) {
10879
+ return num(u.health);
10880
+ }
10881
+ var init_boardEntity = __esm({
10882
+ "components/game/organisms/boardEntity.ts"() {
10883
+ }
10884
+ });
10754
10885
  function BattleBoard({
10755
10886
  entity,
10756
10887
  scale = 0.45,
@@ -10777,43 +10908,49 @@ function BattleBoard({
10777
10908
  attackEvent,
10778
10909
  className
10779
10910
  }) {
10780
- const tiles = entity.tiles;
10781
- const features = entity.features ?? [];
10782
- const boardWidth = entity.boardWidth ?? 8;
10783
- const boardHeight = entity.boardHeight ?? 6;
10784
- const assetManifest = entity.assetManifest;
10785
- const backgroundImage = entity.backgroundImage;
10786
- const units = entity.units;
10787
- const selectedUnitId = entity.selectedUnitId;
10788
- const currentPhase = entity.phase;
10789
- const currentTurn = entity.turn;
10790
- const gameResult = entity.gameResult;
10911
+ const board = boardEntity(entity) ?? {};
10912
+ const tiles = Array.isArray(board.tiles) ? board.tiles : [];
10913
+ const features = Array.isArray(board.features) ? board.features : [];
10914
+ const boardWidth = num(board.boardWidth, 8);
10915
+ const boardHeight = num(board.boardHeight, 6);
10916
+ const assetManifest = board.assetManifest;
10917
+ const backgroundImage = board.backgroundImage;
10918
+ const units = rows(board.units);
10919
+ const selectedUnitId = board.selectedUnitId ?? null;
10920
+ const currentPhase = str(board.phase) || "observation";
10921
+ const currentTurn = num(board.turn, 1);
10922
+ const gameResult = board.gameResult ?? null;
10791
10923
  const eventBus = useEventBus();
10792
10924
  const { t } = useTranslate();
10793
10925
  const [hoveredTile, setHoveredTile] = useState(null);
10794
10926
  const [isShaking, setIsShaking] = useState(false);
10795
10927
  const selectedUnit = useMemo(
10796
- () => units.find((u) => u.id === selectedUnitId) ?? null,
10928
+ () => units.find((u) => str(u.id) === selectedUnitId) ?? null,
10797
10929
  [units, selectedUnitId]
10798
10930
  );
10799
10931
  const hoveredUnit = useMemo(() => {
10800
10932
  if (!hoveredTile) return null;
10801
- return units.find(
10802
- (u) => u.position.x === hoveredTile.x && u.position.y === hoveredTile.y && u.health > 0
10803
- ) ?? null;
10933
+ return units.find((u) => {
10934
+ const p2 = unitPosition(u);
10935
+ return p2.x === hoveredTile.x && p2.y === hoveredTile.y && unitHealth(u) > 0;
10936
+ }) ?? null;
10804
10937
  }, [hoveredTile, units]);
10805
- const playerUnits = useMemo(() => units.filter((u) => u.team === "player" && u.health > 0), [units]);
10806
- const enemyUnits = useMemo(() => units.filter((u) => u.team === "enemy" && u.health > 0), [units]);
10938
+ const playerUnits = useMemo(() => units.filter((u) => unitTeam(u) === "player" && unitHealth(u) > 0), [units]);
10939
+ const enemyUnits = useMemo(() => units.filter((u) => unitTeam(u) === "enemy" && unitHealth(u) > 0), [units]);
10807
10940
  const validMoves = useMemo(() => {
10808
10941
  if (!selectedUnit || currentPhase !== "movement") return [];
10809
10942
  const moves = [];
10810
- const range = selectedUnit.movement;
10943
+ const range = num(selectedUnit.movement);
10944
+ const origin = unitPosition(selectedUnit);
10811
10945
  for (let dy = -range; dy <= range; dy++) {
10812
10946
  for (let dx = -range; dx <= range; dx++) {
10813
- const nx = selectedUnit.position.x + dx;
10814
- const ny = selectedUnit.position.y + dy;
10947
+ const nx = origin.x + dx;
10948
+ const ny = origin.y + dy;
10815
10949
  const dist = Math.abs(dx) + Math.abs(dy);
10816
- if (dist > 0 && dist <= range && nx >= 0 && nx < boardWidth && ny >= 0 && ny < boardHeight && !units.some((u) => u.position.x === nx && u.position.y === ny && u.health > 0)) {
10950
+ if (dist > 0 && dist <= range && nx >= 0 && nx < boardWidth && ny >= 0 && ny < boardHeight && !units.some((u) => {
10951
+ const p2 = unitPosition(u);
10952
+ return p2.x === nx && p2.y === ny && unitHealth(u) > 0;
10953
+ })) {
10817
10954
  moves.push({ x: nx, y: ny });
10818
10955
  }
10819
10956
  }
@@ -10822,11 +10959,14 @@ function BattleBoard({
10822
10959
  }, [selectedUnit, currentPhase, units, boardWidth, boardHeight]);
10823
10960
  const attackTargets = useMemo(() => {
10824
10961
  if (!selectedUnit || currentPhase !== "action") return [];
10825
- return units.filter((u) => u.team !== selectedUnit.team && u.health > 0).filter((u) => {
10826
- const dx = Math.abs(u.position.x - selectedUnit.position.x);
10827
- const dy = Math.abs(u.position.y - selectedUnit.position.y);
10962
+ const sp = unitPosition(selectedUnit);
10963
+ const sTeam = unitTeam(selectedUnit);
10964
+ return units.filter((u) => unitTeam(u) !== sTeam && unitHealth(u) > 0).filter((u) => {
10965
+ const p2 = unitPosition(u);
10966
+ const dx = Math.abs(p2.x - sp.x);
10967
+ const dy = Math.abs(p2.y - sp.y);
10828
10968
  return dx <= 1 && dy <= 1 && dx + dy > 0;
10829
- }).map((u) => u.position);
10969
+ }).map((u) => unitPosition(u));
10830
10970
  }, [selectedUnit, currentPhase, units]);
10831
10971
  const MOVE_SPEED_MS_PER_TILE = 300;
10832
10972
  const movementAnimRef = useRef(null);
@@ -10866,23 +11006,25 @@ function BattleBoard({
10866
11006
  return () => clearInterval(interval);
10867
11007
  }, []);
10868
11008
  const isoUnits = useMemo(() => {
10869
- return units.filter((u) => u.health > 0).map((unit) => {
10870
- const pos = movingPositions.get(unit.id) ?? unit.position;
11009
+ return units.filter((u) => unitHealth(u) > 0).map((unit) => {
11010
+ const id = str(unit.id);
11011
+ const pos = movingPositions.get(id) ?? unitPosition(unit);
11012
+ const unitTraits = Array.isArray(unit.traits) ? unit.traits : void 0;
10871
11013
  return {
10872
- id: unit.id,
11014
+ id,
10873
11015
  position: pos,
10874
- name: unit.name,
10875
- team: unit.team,
10876
- health: unit.health,
10877
- maxHealth: unit.maxHealth,
10878
- unitType: unit.unitType,
10879
- heroId: unit.heroId,
10880
- sprite: unit.sprite,
10881
- traits: unit.traits?.map((t2) => ({
10882
- name: t2.name,
10883
- currentState: t2.currentState,
10884
- states: t2.states,
10885
- cooldown: t2.cooldown ?? 0
11016
+ name: str(unit.name),
11017
+ team: unitTeam(unit),
11018
+ health: unitHealth(unit),
11019
+ maxHealth: num(unit.maxHealth),
11020
+ unitType: unit.unitType == null ? void 0 : str(unit.unitType),
11021
+ heroId: unit.heroId == null ? void 0 : str(unit.heroId),
11022
+ sprite: unit.sprite == null ? void 0 : str(unit.sprite),
11023
+ traits: unitTraits?.map((tr) => ({
11024
+ name: tr.name,
11025
+ currentState: tr.currentState,
11026
+ states: tr.states,
11027
+ cooldown: tr.cooldown ?? 0
10886
11028
  }))
10887
11029
  };
10888
11030
  });
@@ -10894,8 +11036,8 @@ function BattleBoard({
10894
11036
  [scale, baseOffsetX]
10895
11037
  );
10896
11038
  const checkGameEnd = useCallback(() => {
10897
- const pa = units.filter((u) => u.team === "player" && u.health > 0);
10898
- const ea = units.filter((u) => u.team === "enemy" && u.health > 0);
11039
+ const pa = units.filter((u) => unitTeam(u) === "player" && unitHealth(u) > 0);
11040
+ const ea = units.filter((u) => unitTeam(u) === "enemy" && unitHealth(u) > 0);
10899
11041
  if (pa.length === 0) {
10900
11042
  onGameEnd?.("defeat");
10901
11043
  if (gameEndEvent) {
@@ -10909,21 +11051,22 @@ function BattleBoard({
10909
11051
  }
10910
11052
  }, [units, onGameEnd, gameEndEvent, eventBus]);
10911
11053
  const handleUnitClick = useCallback((unitId) => {
10912
- const unit = units.find((u) => u.id === unitId);
11054
+ const unit = units.find((u) => str(u.id) === unitId);
10913
11055
  if (!unit) return;
10914
11056
  if (unitClickEvent) {
10915
11057
  eventBus.emit(`UI:${unitClickEvent}`, { unitId });
10916
11058
  }
10917
11059
  if (currentPhase === "action" && selectedUnit) {
10918
- if (unit.team === "enemy" && attackTargets.some((t2) => t2.x === unit.position.x && t2.y === unit.position.y)) {
10919
- const damage = calculateDamage2 ? calculateDamage2(selectedUnit, unit) : Math.max(1, selectedUnit.attack - unit.defense);
11060
+ const up = unitPosition(unit);
11061
+ if (unitTeam(unit) === "enemy" && attackTargets.some((t2) => t2.x === up.x && t2.y === up.y)) {
11062
+ const damage = calculateDamage2 ? calculateDamage2(selectedUnit, unit) : Math.max(1, num(selectedUnit.attack) - num(unit.defense));
10920
11063
  setIsShaking(true);
10921
11064
  setTimeout(() => setIsShaking(false), 300);
10922
11065
  onAttack?.(selectedUnit, unit, damage);
10923
11066
  if (attackEvent) {
10924
11067
  eventBus.emit(`UI:${attackEvent}`, {
10925
- attackerId: selectedUnit.id,
10926
- targetId: unit.id,
11068
+ attackerId: str(selectedUnit.id),
11069
+ targetId: str(unit.id),
10927
11070
  damage
10928
11071
  });
10929
11072
  }
@@ -10938,9 +11081,9 @@ function BattleBoard({
10938
11081
  if (currentPhase === "movement" && selectedUnit) {
10939
11082
  if (movementAnimRef.current) return;
10940
11083
  if (validMoves.some((m) => m.x === x && m.y === y)) {
10941
- const from = { ...selectedUnit.position };
11084
+ const from = { ...unitPosition(selectedUnit) };
10942
11085
  const to = { x, y };
10943
- startMoveAnimation(selectedUnit.id, from, to, () => {
11086
+ startMoveAnimation(str(selectedUnit.id), from, to, () => {
10944
11087
  onUnitMove?.(selectedUnit, to);
10945
11088
  });
10946
11089
  }
@@ -11098,6 +11241,7 @@ var init_BattleBoard = __esm({
11098
11241
  init_Typography();
11099
11242
  init_Stack();
11100
11243
  init_IsometricCanvas2();
11244
+ init_boardEntity();
11101
11245
  init_isometric();
11102
11246
  BattleBoard.displayName = "BattleBoard";
11103
11247
  }
@@ -12178,7 +12322,7 @@ var init_CodeBlock = __esm({
12178
12322
  log5 = createLogger("almadar:ui:markdown-code");
12179
12323
  LINE_PROPS_FN = (n) => ({ "data-line": String(n - 1) });
12180
12324
  HIDDEN_LINE_NUMBERS = { display: "none" };
12181
- CodeBlock = React79__default.memo(
12325
+ CodeBlock = React80__default.memo(
12182
12326
  ({
12183
12327
  code: rawCode,
12184
12328
  language = "text",
@@ -12320,24 +12464,24 @@ var init_CodeBlock = __esm({
12320
12464
  return;
12321
12465
  }
12322
12466
  lineEls.forEach((el) => {
12323
- const num = parseInt(el.getAttribute("data-line") ?? "-1", 10);
12324
- if (hiddenLines.has(num)) {
12467
+ const num2 = parseInt(el.getAttribute("data-line") ?? "-1", 10);
12468
+ if (hiddenLines.has(num2)) {
12325
12469
  el.style.display = "none";
12326
12470
  return;
12327
12471
  }
12328
12472
  el.style.display = "";
12329
12473
  el.style.position = "relative";
12330
12474
  el.style.paddingLeft = "1.2em";
12331
- const region = foldStartMap.get(num);
12475
+ const region = foldStartMap.get(num2);
12332
12476
  if (!region) return;
12333
- const isCollapsed = collapsed.has(num);
12477
+ const isCollapsed = collapsed.has(num2);
12334
12478
  const toggle = document.createElement("span");
12335
12479
  toggle.className = "fold-toggle";
12336
12480
  toggle.textContent = isCollapsed ? "\u25B6" : "\u25BC";
12337
12481
  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%";
12338
12482
  toggle.addEventListener("click", (e) => {
12339
12483
  e.stopPropagation();
12340
- toggleFoldRef.current(num);
12484
+ toggleFoldRef.current(num2);
12341
12485
  });
12342
12486
  el.insertBefore(toggle, el.firstChild);
12343
12487
  if (isCollapsed) {
@@ -12615,7 +12759,7 @@ var init_MarkdownContent = __esm({
12615
12759
  init_Box();
12616
12760
  init_CodeBlock();
12617
12761
  init_cn();
12618
- MarkdownContent = React79__default.memo(
12762
+ MarkdownContent = React80__default.memo(
12619
12763
  ({ content, direction, className }) => {
12620
12764
  const { t: _t } = useTranslate();
12621
12765
  const safeContent = typeof content === "string" ? content : String(content ?? "");
@@ -13711,7 +13855,7 @@ var init_StateMachineView = __esm({
13711
13855
  style: { top: title ? 30 : 0 },
13712
13856
  children: [
13713
13857
  entity && /* @__PURE__ */ jsx(EntityBox, { entity, config }),
13714
- states.map((state) => renderStateNode ? /* @__PURE__ */ jsx(React79__default.Fragment, { children: renderStateNode(state, config) }, state.id) : /* @__PURE__ */ jsx(
13858
+ states.map((state) => renderStateNode ? /* @__PURE__ */ jsx(React80__default.Fragment, { children: renderStateNode(state, config) }, state.id) : /* @__PURE__ */ jsx(
13715
13859
  StateNode,
13716
13860
  {
13717
13861
  state,
@@ -14590,10 +14734,13 @@ var init_BookChapterView = __esm({
14590
14734
  init_cn();
14591
14735
  BookChapterView = ({
14592
14736
  chapter,
14737
+ orbitalSchema,
14593
14738
  direction,
14594
14739
  className
14595
14740
  }) => {
14596
14741
  const { t: _t } = useTranslate();
14742
+ const title = String(chapter.title ?? "");
14743
+ const content = String(chapter.content ?? "");
14597
14744
  return /* @__PURE__ */ jsxs(
14598
14745
  VStack,
14599
14746
  {
@@ -14601,16 +14748,16 @@ var init_BookChapterView = __esm({
14601
14748
  className: cn("px-6 py-8 max-w-4xl mx-auto w-full", className),
14602
14749
  style: { direction },
14603
14750
  children: [
14604
- /* @__PURE__ */ jsx(Typography, { variant: "h1", className: "text-3xl font-bold", children: chapter.title }),
14751
+ /* @__PURE__ */ jsx(Typography, { variant: "h1", className: "text-3xl font-bold", children: title }),
14605
14752
  /* @__PURE__ */ jsx(Divider, {}),
14606
- !!chapter.orbitalSchema && /* @__PURE__ */ jsx(ScaledDiagram, { children: /* @__PURE__ */ jsx(
14753
+ !!orbitalSchema && /* @__PURE__ */ jsx(ScaledDiagram, { children: /* @__PURE__ */ jsx(
14607
14754
  JazariStateMachine,
14608
14755
  {
14609
- schema: chapter.orbitalSchema,
14756
+ schema: orbitalSchema,
14610
14757
  direction
14611
14758
  }
14612
14759
  ) }),
14613
- /* @__PURE__ */ jsx(ContentRenderer, { content: chapter.content, direction })
14760
+ /* @__PURE__ */ jsx(ContentRenderer, { content, direction })
14614
14761
  ]
14615
14762
  }
14616
14763
  );
@@ -14708,7 +14855,7 @@ var init_BookNavBar = __esm({
14708
14855
  BookNavBar = ({
14709
14856
  currentPage,
14710
14857
  totalPages,
14711
- chapterTitle,
14858
+ chapterTitle: chapterTitle2,
14712
14859
  direction,
14713
14860
  className
14714
14861
  }) => {
@@ -14749,12 +14896,12 @@ var init_BookNavBar = __esm({
14749
14896
  )
14750
14897
  ] }),
14751
14898
  /* @__PURE__ */ jsxs(Box, { className: "flex-1 mx-4 max-w-md", children: [
14752
- chapterTitle && /* @__PURE__ */ jsx(
14899
+ chapterTitle2 && /* @__PURE__ */ jsx(
14753
14900
  Typography,
14754
14901
  {
14755
14902
  variant: "caption",
14756
14903
  className: "text-center block truncate text-muted-foreground",
14757
- children: chapterTitle
14904
+ children: chapterTitle2
14758
14905
  }
14759
14906
  ),
14760
14907
  /* @__PURE__ */ jsx(ProgressBar, { value: progress, size: "sm", variant: "primary" })
@@ -14821,31 +14968,35 @@ var init_BookTableOfContents = __esm({
14821
14968
  style: { direction },
14822
14969
  children: [
14823
14970
  /* @__PURE__ */ jsx(Typography, { variant: "h1", className: "text-3xl font-bold text-center mb-4", children: t("book.tableOfContents") }),
14824
- parts.map((part, partIdx) => /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
14825
- /* @__PURE__ */ jsxs(HStack, { gap: "sm", align: "center", children: [
14826
- /* @__PURE__ */ jsx(Badge, { variant: "default", size: "sm", children: t("book.partNumber", { number: String(partIdx + 1) }) }),
14827
- /* @__PURE__ */ jsx(Typography, { variant: "h3", className: "font-semibold", children: part.title })
14828
- ] }),
14829
- /* @__PURE__ */ jsx(VStack, { gap: "xs", className: direction === "rtl" ? "pr-6" : "pl-6", children: part.chapters.map((chapter) => {
14830
- const isCurrent = chapter.id === currentChapterId;
14831
- return /* @__PURE__ */ jsx(
14832
- Button,
14833
- {
14834
- variant: "ghost",
14835
- size: "sm",
14836
- action: "BOOK_NAVIGATE",
14837
- actionPayload: { chapterId: chapter.id },
14838
- className: cn(
14839
- "justify-start text-left w-full",
14840
- direction === "rtl" && "text-right",
14841
- isCurrent && "bg-blue-50 dark:bg-blue-950 text-blue-600 dark:text-blue-400"
14842
- ),
14843
- children: /* @__PURE__ */ jsx(Box, { className: "truncate", children: /* @__PURE__ */ jsx(Typography, { variant: "body", children: chapter.title }) })
14844
- },
14845
- chapter.id
14846
- );
14847
- }) })
14848
- ] }, partIdx))
14971
+ parts.map((part, partIdx) => {
14972
+ const chapters = Array.isArray(part.chapters) ? part.chapters : [];
14973
+ return /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
14974
+ /* @__PURE__ */ jsxs(HStack, { gap: "sm", align: "center", children: [
14975
+ /* @__PURE__ */ jsx(Badge, { variant: "default", size: "sm", children: t("book.partNumber", { number: String(partIdx + 1) }) }),
14976
+ /* @__PURE__ */ jsx(Typography, { variant: "h3", className: "font-semibold", children: String(part.title ?? "") })
14977
+ ] }),
14978
+ /* @__PURE__ */ jsx(VStack, { gap: "xs", className: direction === "rtl" ? "pr-6" : "pl-6", children: chapters.map((chapter) => {
14979
+ const id = chapter.id == null ? "" : String(chapter.id);
14980
+ const isCurrent = id === currentChapterId;
14981
+ return /* @__PURE__ */ jsx(
14982
+ Button,
14983
+ {
14984
+ variant: "ghost",
14985
+ size: "sm",
14986
+ action: "BOOK_NAVIGATE",
14987
+ actionPayload: { chapterId: id },
14988
+ className: cn(
14989
+ "justify-start text-left w-full",
14990
+ direction === "rtl" && "text-right",
14991
+ isCurrent && "bg-blue-50 dark:bg-blue-950 text-blue-600 dark:text-blue-400"
14992
+ ),
14993
+ children: /* @__PURE__ */ jsx(Box, { className: "truncate", children: /* @__PURE__ */ jsx(Typography, { variant: "body", children: String(chapter.title ?? "") }) })
14994
+ },
14995
+ id
14996
+ );
14997
+ }) })
14998
+ ] }, partIdx);
14999
+ })
14849
15000
  ]
14850
15001
  }
14851
15002
  );
@@ -14967,27 +15118,41 @@ function resolveFieldMap(fieldMap) {
14967
15118
  function get(obj, key) {
14968
15119
  return obj[key];
14969
15120
  }
15121
+ function asStr(v) {
15122
+ return v == null ? "" : String(v);
15123
+ }
14970
15124
  function mapBookData(raw, fields = IDENTITY_BOOK_FIELDS) {
14971
15125
  const rawParts = get(raw, fields.parts) ?? [];
14972
- return {
14973
- title: get(raw, fields.title) ?? "",
14974
- subtitle: get(raw, fields.subtitle),
14975
- author: get(raw, fields.author),
14976
- coverImageUrl: get(raw, fields.coverImageUrl),
14977
- direction: get(raw, fields.direction) ?? void 0,
14978
- parts: rawParts.map((part) => {
14979
- const rawChapters = get(part, fields.chapters) ?? [];
14980
- return {
14981
- title: get(part, fields.partTitle) ?? "",
14982
- chapters: rawChapters.map((ch) => ({
14983
- id: get(ch, fields.chapterId) ?? "",
14984
- title: get(ch, fields.chapterTitle) ?? "",
14985
- content: get(ch, fields.chapterContent) ?? "",
14986
- orbitalSchema: get(ch, fields.chapterOrbitalSchema)
14987
- }))
14988
- };
14989
- })
15126
+ const direction = get(raw, fields.direction) ?? "ltr";
15127
+ const cover = {
15128
+ title: asStr(get(raw, fields.title)),
15129
+ subtitle: asStr(get(raw, fields.subtitle)),
15130
+ author: asStr(get(raw, fields.author)),
15131
+ coverImageUrl: asStr(get(raw, fields.coverImageUrl)),
15132
+ direction
14990
15133
  };
15134
+ const schemaByChapterId = {};
15135
+ const chapters = [];
15136
+ const parts = rawParts.map((part) => {
15137
+ const rawChapters = get(part, fields.chapters) ?? [];
15138
+ const chapterRows = rawChapters.map((ch) => {
15139
+ const id = asStr(get(ch, fields.chapterId));
15140
+ const schema = get(ch, fields.chapterOrbitalSchema);
15141
+ if (schema) schemaByChapterId[id] = schema;
15142
+ const row = {
15143
+ id,
15144
+ title: asStr(get(ch, fields.chapterTitle)),
15145
+ content: asStr(get(ch, fields.chapterContent))
15146
+ };
15147
+ chapters.push(row);
15148
+ return row;
15149
+ });
15150
+ return {
15151
+ title: asStr(get(part, fields.partTitle)),
15152
+ chapters: chapterRows
15153
+ };
15154
+ });
15155
+ return { cover, direction, parts, chapters, schemaByChapterId };
14991
15156
  }
14992
15157
  var IDENTITY_BOOK_FIELDS, AR_BOOK_FIELDS, FIELD_MAP_REGISTRY;
14993
15158
  var init_types2 = __esm({
@@ -15025,10 +15190,7 @@ var init_types2 = __esm({
15025
15190
  };
15026
15191
  }
15027
15192
  });
15028
- function flattenChapters(book) {
15029
- return book.parts.flatMap((part) => part.chapters);
15030
- }
15031
- var PRINT_STYLES, BookViewer;
15193
+ var chapterId, chapterTitle, PRINT_STYLES, BookViewer;
15032
15194
  var init_BookViewer = __esm({
15033
15195
  "components/marketing/organisms/book/BookViewer.tsx"() {
15034
15196
  init_Box();
@@ -15041,6 +15203,8 @@ var init_BookViewer = __esm({
15041
15203
  init_BookNavBar();
15042
15204
  init_EmptyState();
15043
15205
  init_types2();
15206
+ chapterId = (ch) => ch?.id == null ? void 0 : String(ch.id);
15207
+ chapterTitle = (ch) => ch?.title == null ? void 0 : String(ch.title);
15044
15208
  PRINT_STYLES = `
15045
15209
  @media print {
15046
15210
  .book-viewer-page {
@@ -15069,14 +15233,14 @@ var init_BookViewer = __esm({
15069
15233
  return mapBookData(raw, resolvedFieldMap);
15070
15234
  }, [entity, resolvedFieldMap]);
15071
15235
  const direction = book?.direction ?? "ltr";
15072
- const chapters = useMemo(() => book ? flattenChapters(book) : [], [book]);
15236
+ const chapters = useMemo(() => book ? book.chapters : [], [book]);
15073
15237
  const totalPages = 2 + chapters.length;
15074
15238
  const navigateTo = useCallback(
15075
15239
  (page) => {
15076
15240
  const clamped = Math.max(0, Math.min(page, totalPages - 1));
15077
15241
  setCurrentPage(clamped);
15078
- const chapterId = clamped >= 2 ? chapters[clamped - 2]?.id : void 0;
15079
- eventBus.emit("UI:BOOK_PAGE_CHANGE", { pageIndex: clamped, chapterId });
15242
+ const id = clamped >= 2 ? chapterId(chapters[clamped - 2]) : void 0;
15243
+ eventBus.emit("UI:BOOK_PAGE_CHANGE", { pageIndex: clamped, chapterId: id });
15080
15244
  },
15081
15245
  [totalPages, chapters, eventBus]
15082
15246
  );
@@ -15088,8 +15252,8 @@ var init_BookViewer = __esm({
15088
15252
  eventBus.on("UI:BOOK_PAGE_NEXT", () => navigateTo(currentPage + 1)),
15089
15253
  eventBus.on("UI:BOOK_PRINT", () => window.print()),
15090
15254
  eventBus.on("UI:BOOK_NAVIGATE", (event) => {
15091
- const chapterId = event.payload?.chapterId;
15092
- const idx = chapters.findIndex((ch) => ch.id === chapterId);
15255
+ const targetId = event.payload?.chapterId;
15256
+ const idx = chapters.findIndex((ch) => chapterId(ch) === targetId);
15093
15257
  if (idx >= 0) navigateTo(idx + 2);
15094
15258
  })
15095
15259
  ];
@@ -15106,9 +15270,11 @@ var init_BookViewer = __esm({
15106
15270
  style.remove();
15107
15271
  };
15108
15272
  }, []);
15109
- const currentChapterId = currentPage >= 2 ? chapters[currentPage - 2]?.id : void 0;
15110
- const currentChapterTitle = currentPage >= 2 ? chapters[currentPage - 2]?.title : void 0;
15273
+ const currentChapterId = currentPage >= 2 ? chapterId(chapters[currentPage - 2]) : void 0;
15274
+ const currentChapterTitle = currentPage >= 2 ? chapterTitle(chapters[currentPage - 2]) : void 0;
15111
15275
  if (!book) return /* @__PURE__ */ jsx(EmptyState, { message: t("book.noData") });
15276
+ const cover = book.cover;
15277
+ const coverTitle = String(cover.title ?? "");
15112
15278
  return /* @__PURE__ */ jsxs(VStack, { className: cn("relative h-full overflow-hidden bg-background", className), children: [
15113
15279
  /* @__PURE__ */ jsxs(
15114
15280
  Box,
@@ -15120,10 +15286,10 @@ var init_BookViewer = __esm({
15120
15286
  /* @__PURE__ */ jsx(
15121
15287
  BookCoverPage,
15122
15288
  {
15123
- title: book.title,
15124
- subtitle: book.subtitle,
15125
- author: book.author,
15126
- coverImageUrl: book.coverImageUrl,
15289
+ title: coverTitle,
15290
+ subtitle: String(cover.subtitle ?? "") || void 0,
15291
+ author: String(cover.author ?? "") || void 0,
15292
+ coverImageUrl: String(cover.coverImageUrl ?? "") || void 0,
15127
15293
  direction
15128
15294
  }
15129
15295
  ),
@@ -15134,23 +15300,27 @@ var init_BookViewer = __esm({
15134
15300
  direction
15135
15301
  }
15136
15302
  ),
15137
- chapters.map((chapter) => /* @__PURE__ */ jsx(
15138
- BookChapterView,
15139
- {
15140
- chapter,
15141
- direction
15142
- },
15143
- chapter.id
15144
- ))
15303
+ chapters.map((chapter) => {
15304
+ const id = chapterId(chapter);
15305
+ return /* @__PURE__ */ jsx(
15306
+ BookChapterView,
15307
+ {
15308
+ chapter,
15309
+ orbitalSchema: id ? book.schemaByChapterId[id] : void 0,
15310
+ direction
15311
+ },
15312
+ id
15313
+ );
15314
+ })
15145
15315
  ] }),
15146
15316
  /* @__PURE__ */ jsxs(Box, { className: "print:hidden", children: [
15147
15317
  currentPage === 0 && /* @__PURE__ */ jsx(
15148
15318
  BookCoverPage,
15149
15319
  {
15150
- title: book.title,
15151
- subtitle: book.subtitle,
15152
- author: book.author,
15153
- coverImageUrl: book.coverImageUrl,
15320
+ title: coverTitle,
15321
+ subtitle: String(cover.subtitle ?? "") || void 0,
15322
+ author: String(cover.author ?? "") || void 0,
15323
+ coverImageUrl: String(cover.coverImageUrl ?? "") || void 0,
15154
15324
  direction
15155
15325
  }
15156
15326
  ),
@@ -15166,6 +15336,7 @@ var init_BookViewer = __esm({
15166
15336
  BookChapterView,
15167
15337
  {
15168
15338
  chapter: chapters[currentPage - 2],
15339
+ orbitalSchema: currentChapterId ? book.schemaByChapterId[currentChapterId] : void 0,
15169
15340
  direction
15170
15341
  }
15171
15342
  )
@@ -15178,7 +15349,7 @@ var init_BookViewer = __esm({
15178
15349
  {
15179
15350
  currentPage,
15180
15351
  totalPages,
15181
- chapterTitle: currentPage === 0 ? book.title : currentPage === 1 ? t("book.tableOfContents") : currentChapterTitle,
15352
+ chapterTitle: currentPage === 0 ? coverTitle : currentPage === 1 ? t("book.tableOfContents") : currentChapterTitle,
15182
15353
  direction
15183
15354
  }
15184
15355
  )
@@ -15276,7 +15447,7 @@ var init_Grid = __esm({
15276
15447
  };
15277
15448
  Grid = ({
15278
15449
  cols = 1,
15279
- rows,
15450
+ rows: rows2,
15280
15451
  gap = "md",
15281
15452
  rowGap,
15282
15453
  colGap,
@@ -15288,8 +15459,8 @@ var init_Grid = __esm({
15288
15459
  children,
15289
15460
  as: Component = "div"
15290
15461
  }) => {
15291
- const mergedStyle = rows ? { gridTemplateRows: `repeat(${rows}, minmax(0, 1fr))`, ...style } : style;
15292
- return React79__default.createElement(
15462
+ const mergedStyle = rows2 ? { gridTemplateRows: `repeat(${rows2}, minmax(0, 1fr))`, ...style } : style;
15463
+ return React80__default.createElement(
15293
15464
  Component,
15294
15465
  {
15295
15466
  className: cn(
@@ -16004,14 +16175,14 @@ function BuilderBoard({
16004
16175
  }) {
16005
16176
  const { emit } = useEventBus();
16006
16177
  const { t } = useTranslate();
16007
- const resolved = Array.isArray(entity) ? entity[0] : entity;
16178
+ const resolved = boardEntity(entity);
16008
16179
  const [placements, setPlacements] = useState({});
16009
16180
  const [headerError, setHeaderError] = useState(false);
16010
16181
  const [submitted, setSubmitted] = useState(false);
16011
16182
  const [attempts, setAttempts] = useState(0);
16012
16183
  const [showHint, setShowHint] = useState(false);
16013
- const components = resolved?.components ?? [];
16014
- const slots = resolved?.slots ?? [];
16184
+ const components = Array.isArray(resolved?.components) ? resolved.components : [];
16185
+ const slots = Array.isArray(resolved?.slots) ? resolved.slots : [];
16015
16186
  const usedComponentIds = new Set(Object.values(placements));
16016
16187
  const availableComponents = components.filter((c) => !usedComponentIds.has(c.id));
16017
16188
  const [selectedComponent, setSelectedComponent] = useState(null);
@@ -16045,7 +16216,7 @@ function BuilderBoard({
16045
16216
  }, [slots, placements, attempts, completeEvent, emit]);
16046
16217
  const handleReset = () => {
16047
16218
  setSubmitted(false);
16048
- if (attempts >= 2 && resolved?.hint) {
16219
+ if (attempts >= 2 && str(resolved?.hint)) {
16049
16220
  setShowHint(true);
16050
16221
  }
16051
16222
  };
@@ -16058,20 +16229,24 @@ function BuilderBoard({
16058
16229
  };
16059
16230
  const getComponentById = (id) => components.find((c) => c.id === id);
16060
16231
  if (!resolved) return null;
16232
+ const theme = resolved.theme ?? void 0;
16233
+ const themeBackground = theme?.background;
16234
+ const headerImage = str(resolved.headerImage);
16235
+ const hint = str(resolved.hint);
16061
16236
  return /* @__PURE__ */ jsx(
16062
16237
  Box,
16063
16238
  {
16064
16239
  className,
16065
16240
  style: {
16066
- backgroundImage: resolved.theme?.background ? `url(${resolved.theme.background})` : void 0,
16241
+ backgroundImage: themeBackground ? `url(${themeBackground})` : void 0,
16067
16242
  backgroundSize: "cover",
16068
16243
  backgroundPosition: "center"
16069
16244
  },
16070
16245
  children: /* @__PURE__ */ jsxs(VStack, { gap: "lg", className: "p-4", children: [
16071
- resolved.headerImage && !headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 overflow-hidden rounded-container", children: /* @__PURE__ */ jsx("img", { src: resolved.headerImage, alt: "", onError: () => setHeaderError(true), className: "w-full h-full object-cover" }) }) : resolved.headerImage && headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 rounded-container bg-gradient-to-br from-muted to-accent opacity-60" }) : null,
16246
+ 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,
16072
16247
  /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
16073
- /* @__PURE__ */ jsx(Typography, { variant: "h4", weight: "bold", children: resolved.title }),
16074
- /* @__PURE__ */ jsx(Typography, { variant: "body", children: resolved.description })
16248
+ /* @__PURE__ */ jsx(Typography, { variant: "h4", weight: "bold", children: str(resolved.title) }),
16249
+ /* @__PURE__ */ jsx(Typography, { variant: "body", children: str(resolved.description) })
16075
16250
  ] }) }),
16076
16251
  /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
16077
16252
  /* @__PURE__ */ jsx(Typography, { variant: "small", weight: "bold", className: "uppercase tracking-wider text-muted-foreground", children: t("builder.components") }),
@@ -16131,9 +16306,9 @@ function BuilderBoard({
16131
16306
  ] }) }),
16132
16307
  submitted && /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", align: "center", children: [
16133
16308
  /* @__PURE__ */ jsx(Icon, { icon: allCorrect ? CheckCircle : XCircle, size: "lg", className: allCorrect ? "text-success" : "text-error" }),
16134
- /* @__PURE__ */ jsx(Typography, { variant: "body", weight: "bold", children: allCorrect ? resolved.successMessage ?? t("builder.success") : resolved.failMessage ?? t("builder.incorrect") })
16309
+ /* @__PURE__ */ jsx(Typography, { variant: "body", weight: "bold", children: allCorrect ? str(resolved.successMessage) || t("builder.success") : str(resolved.failMessage) || t("builder.incorrect") })
16135
16310
  ] }) }),
16136
- showHint && resolved.hint && /* @__PURE__ */ jsx(Card, { className: "p-4 border-l-4 border-l-warning", children: /* @__PURE__ */ jsx(Typography, { variant: "body", children: resolved.hint }) }),
16311
+ showHint && hint && /* @__PURE__ */ jsx(Card, { className: "p-4 border-l-4 border-l-warning", children: /* @__PURE__ */ jsx(Typography, { variant: "body", children: hint }) }),
16137
16312
  /* @__PURE__ */ jsxs(HStack, { gap: "sm", justify: "center", children: [
16138
16313
  !submitted ? /* @__PURE__ */ jsxs(Button, { variant: "primary", onClick: handleSubmit, disabled: !allPlaced, children: [
16139
16314
  /* @__PURE__ */ jsx(Icon, { icon: Wrench, size: "sm" }),
@@ -16152,6 +16327,7 @@ var init_BuilderBoard = __esm({
16152
16327
  "components/game/organisms/puzzles/builder/BuilderBoard.tsx"() {
16153
16328
  init_atoms2();
16154
16329
  init_useEventBus();
16330
+ init_boardEntity();
16155
16331
  BuilderBoard.displayName = "BuilderBoard";
16156
16332
  }
16157
16333
  });
@@ -16489,21 +16665,24 @@ function CalendarGrid({
16489
16665
  eventBus.emit(`UI:${longPressEvent}`, { date: day.toISOString(), time, ...longPressPayload });
16490
16666
  }, 500);
16491
16667
  }, [longPressEvent, longPressPayload, eventBus]);
16492
- const renderEvent = (event) => /* @__PURE__ */ jsx(
16493
- Box,
16494
- {
16495
- rounded: "md",
16496
- padding: "xs",
16497
- border: true,
16498
- className: cn(
16499
- "cursor-pointer hover:shadow-sm transition-shadow text-xs truncate",
16500
- event.color ? event.color : "bg-blue-500/15 border-blue-500/30 text-blue-600"
16501
- ),
16502
- onClick: (e) => handleEventClick(event, e),
16503
- children: /* @__PURE__ */ jsx(Typography, { variant: "small", className: "truncate font-medium", children: event.title })
16504
- },
16505
- event.id
16506
- );
16668
+ const renderEvent = (event) => {
16669
+ const color = event.color;
16670
+ return /* @__PURE__ */ jsx(
16671
+ Box,
16672
+ {
16673
+ rounded: "md",
16674
+ padding: "xs",
16675
+ border: true,
16676
+ className: cn(
16677
+ "cursor-pointer hover:shadow-sm transition-shadow text-xs truncate",
16678
+ color ? color : "bg-blue-500/15 border-blue-500/30 text-blue-600"
16679
+ ),
16680
+ onClick: (e) => handleEventClick(event, e),
16681
+ children: /* @__PURE__ */ jsx(Typography, { variant: "small", className: "truncate font-medium", children: event.title })
16682
+ },
16683
+ event.id
16684
+ );
16685
+ };
16507
16686
  return /* @__PURE__ */ jsxs(
16508
16687
  Box,
16509
16688
  {
@@ -18167,7 +18346,6 @@ var init_CardGrid = __esm({
18167
18346
  alignItems = "stretch",
18168
18347
  className,
18169
18348
  children,
18170
- // EntityDisplayProps
18171
18349
  entity,
18172
18350
  isLoading = false,
18173
18351
  error = null,
@@ -18639,14 +18817,14 @@ var init_CaseStudyOrganism = __esm({
18639
18817
  /* @__PURE__ */ jsx(SimpleGrid, { cols: cols > 0 ? cols : 1, gap: "lg", children: items.map((study) => /* @__PURE__ */ jsx(
18640
18818
  CaseStudyCard,
18641
18819
  {
18642
- title: study.title,
18643
- description: study.description,
18644
- category: study.category,
18645
- categoryColor: study.categoryColor,
18646
- href: study.href,
18647
- linkLabel: study.linkLabel
18820
+ title: String(study.title ?? ""),
18821
+ description: String(study.description ?? ""),
18822
+ category: String(study.category ?? ""),
18823
+ categoryColor: study.categoryColor != null ? String(study.categoryColor) : void 0,
18824
+ href: String(study.href ?? ""),
18825
+ linkLabel: study.linkLabel != null ? String(study.linkLabel) : void 0
18648
18826
  },
18649
- study.id
18827
+ String(study.id ?? "")
18650
18828
  )) })
18651
18829
  ] });
18652
18830
  };
@@ -18669,10 +18847,10 @@ function CastleBoard({
18669
18847
  className
18670
18848
  }) {
18671
18849
  const eventBus = useEventBus();
18672
- const resolved = Array.isArray(entity) ? entity[0] : entity;
18673
- const tiles = resolved?.tiles ?? [];
18674
- const features = resolved?.features ?? [];
18675
- const units = resolved?.units ?? [];
18850
+ const resolved = boardEntity(entity);
18851
+ const tiles = Array.isArray(resolved?.tiles) ? resolved.tiles : [];
18852
+ const features = Array.isArray(resolved?.features) ? resolved.features : [];
18853
+ const units = Array.isArray(resolved?.units) ? resolved.units : [];
18676
18854
  const assetManifest = resolved?.assetManifest;
18677
18855
  const backgroundImage = resolved?.backgroundImage;
18678
18856
  const [hoveredTile, setHoveredTile] = useState(null);
@@ -18700,7 +18878,7 @@ function CastleBoard({
18700
18878
  onFeatureClick?.(feature);
18701
18879
  if (featureClickEvent) {
18702
18880
  eventBus.emit(`UI:${featureClickEvent}`, {
18703
- featureId: feature.id,
18881
+ featureId: feature.id ?? "",
18704
18882
  featureType: feature.type,
18705
18883
  x: feature.x,
18706
18884
  y: feature.y
@@ -18768,6 +18946,7 @@ var init_CastleBoard = __esm({
18768
18946
  init_cn();
18769
18947
  init_useEventBus();
18770
18948
  init_IsometricCanvas2();
18949
+ init_boardEntity();
18771
18950
  init_isometric();
18772
18951
  CastleBoard.displayName = "CastleBoard";
18773
18952
  }
@@ -19624,14 +19803,14 @@ function ClassifierBoard({
19624
19803
  }) {
19625
19804
  const { emit } = useEventBus();
19626
19805
  const { t } = useTranslate();
19627
- const resolved = Array.isArray(entity) ? entity[0] : entity;
19806
+ const resolved = boardEntity(entity);
19628
19807
  const [assignments, setAssignments] = useState({});
19629
19808
  const [headerError, setHeaderError] = useState(false);
19630
19809
  const [submitted, setSubmitted] = useState(false);
19631
19810
  const [attempts, setAttempts] = useState(0);
19632
19811
  const [showHint, setShowHint] = useState(false);
19633
- const items = resolved?.items ?? [];
19634
- const categories = resolved?.categories ?? [];
19812
+ const items = Array.isArray(resolved?.items) ? resolved.items : [];
19813
+ const categories = Array.isArray(resolved?.categories) ? resolved.categories : [];
19635
19814
  const unassignedItems = items.filter((item) => !assignments[item.id]);
19636
19815
  const allAssigned = Object.keys(assignments).length === items.length;
19637
19816
  const results = submitted ? items.map((item) => ({
@@ -19663,7 +19842,7 @@ function ClassifierBoard({
19663
19842
  }, [items, assignments, attempts, completeEvent, emit]);
19664
19843
  const handleReset = () => {
19665
19844
  setSubmitted(false);
19666
- if (attempts >= 2 && resolved?.hint) {
19845
+ if (attempts >= 2 && str(resolved?.hint)) {
19667
19846
  setShowHint(true);
19668
19847
  }
19669
19848
  };
@@ -19674,20 +19853,25 @@ function ClassifierBoard({
19674
19853
  setShowHint(false);
19675
19854
  };
19676
19855
  if (!resolved) return null;
19856
+ const theme = resolved.theme ?? void 0;
19857
+ const themeBackground = theme?.background;
19858
+ const headerImage = str(resolved.headerImage);
19859
+ const hint = str(resolved.hint);
19860
+ const failMessage = str(resolved.failMessage);
19677
19861
  return /* @__PURE__ */ jsx(
19678
19862
  Box,
19679
19863
  {
19680
19864
  className,
19681
19865
  style: {
19682
- backgroundImage: resolved.theme?.background ? `url(${resolved.theme.background})` : void 0,
19866
+ backgroundImage: themeBackground ? `url(${themeBackground})` : void 0,
19683
19867
  backgroundSize: "cover",
19684
19868
  backgroundPosition: "center"
19685
19869
  },
19686
19870
  children: /* @__PURE__ */ jsxs(VStack, { gap: "lg", className: "p-4", children: [
19687
- resolved.headerImage && !headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 overflow-hidden rounded-container", children: /* @__PURE__ */ jsx("img", { src: resolved.headerImage, alt: "", onError: () => setHeaderError(true), className: "w-full h-full object-cover" }) }) : resolved.headerImage && headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 rounded-container bg-gradient-to-br from-muted to-accent opacity-60" }) : null,
19871
+ 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,
19688
19872
  /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
19689
- /* @__PURE__ */ jsx(Typography, { variant: "h4", weight: "bold", children: resolved.title }),
19690
- /* @__PURE__ */ jsx(Typography, { variant: "body", children: resolved.description })
19873
+ /* @__PURE__ */ jsx(Typography, { variant: "h4", weight: "bold", children: str(resolved.title) }),
19874
+ /* @__PURE__ */ jsx(Typography, { variant: "body", children: str(resolved.description) })
19691
19875
  ] }) }),
19692
19876
  unassignedItems.length > 0 && /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
19693
19877
  /* @__PURE__ */ jsx(Typography, { variant: "small", weight: "bold", className: "uppercase tracking-wider text-muted-foreground", children: t("classifier.itemsToSort") }),
@@ -19739,10 +19923,10 @@ function ClassifierBoard({
19739
19923
  }) }),
19740
19924
  submitted && /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", align: "center", children: [
19741
19925
  /* @__PURE__ */ jsx(Icon, { icon: allCorrect ? CheckCircle : XCircle, size: "lg", className: allCorrect ? "text-success" : "text-error" }),
19742
- /* @__PURE__ */ jsx(Typography, { variant: "body", weight: "bold", children: allCorrect ? resolved.successMessage ?? t("classifier.allCorrect") : `${correctCount}/${items.length} ${t("classifier.correct")}` }),
19743
- !allCorrect && resolved.failMessage && /* @__PURE__ */ jsx(Typography, { variant: "body", className: "text-muted-foreground", children: resolved.failMessage })
19926
+ /* @__PURE__ */ jsx(Typography, { variant: "body", weight: "bold", children: allCorrect ? str(resolved.successMessage) || t("classifier.allCorrect") : `${correctCount}/${items.length} ${t("classifier.correct")}` }),
19927
+ !allCorrect && failMessage && /* @__PURE__ */ jsx(Typography, { variant: "body", className: "text-muted-foreground", children: failMessage })
19744
19928
  ] }) }),
19745
- showHint && resolved.hint && /* @__PURE__ */ jsx(Card, { className: "p-4 border-l-4 border-l-warning", children: /* @__PURE__ */ jsx(Typography, { variant: "body", children: resolved.hint }) }),
19929
+ showHint && hint && /* @__PURE__ */ jsx(Card, { className: "p-4 border-l-4 border-l-warning", children: /* @__PURE__ */ jsx(Typography, { variant: "body", children: hint }) }),
19746
19930
  /* @__PURE__ */ jsxs(HStack, { gap: "sm", justify: "center", children: [
19747
19931
  !submitted ? /* @__PURE__ */ jsxs(Button, { variant: "primary", onClick: handleSubmit, disabled: !allAssigned, children: [
19748
19932
  /* @__PURE__ */ jsx(Icon, { icon: Send, size: "sm" }),
@@ -19761,6 +19945,7 @@ var init_ClassifierBoard = __esm({
19761
19945
  "components/game/organisms/puzzles/classifier/ClassifierBoard.tsx"() {
19762
19946
  init_atoms2();
19763
19947
  init_useEventBus();
19948
+ init_boardEntity();
19764
19949
  ClassifierBoard.displayName = "ClassifierBoard";
19765
19950
  }
19766
19951
  });
@@ -20813,7 +20998,7 @@ function CraftingRecipe({
20813
20998
  className
20814
20999
  }) {
20815
21000
  const eventBus = useEventBus();
20816
- const handleCraft = React79.useCallback(() => {
21001
+ const handleCraft = React80.useCallback(() => {
20817
21002
  onCraft?.();
20818
21003
  if (craftEvent) {
20819
21004
  eventBus.emit(craftEvent, { output: output.label });
@@ -20830,7 +21015,7 @@ function CraftingRecipe({
20830
21015
  children: [
20831
21016
  /* @__PURE__ */ jsx(HStack, { gap: "xs", className: "flex-wrap items-center", children: inputs.map((ingredient, index) => {
20832
21017
  const hasSufficient = ingredient.available >= ingredient.required;
20833
- return /* @__PURE__ */ jsxs(React79.Fragment, { children: [
21018
+ return /* @__PURE__ */ jsxs(React80.Fragment, { children: [
20834
21019
  /* @__PURE__ */ jsx(Box, { className: "relative", children: /* @__PURE__ */ jsx(
20835
21020
  ItemSlot,
20836
21021
  {
@@ -20893,8 +21078,8 @@ function DPad({
20893
21078
  }) {
20894
21079
  const eventBus = useEventBus();
20895
21080
  const sizes = sizeMap6[size];
20896
- const [activeDirections, setActiveDirections] = React79.useState(/* @__PURE__ */ new Set());
20897
- const handlePress = React79.useCallback(
21081
+ const [activeDirections, setActiveDirections] = React80.useState(/* @__PURE__ */ new Set());
21082
+ const handlePress = React80.useCallback(
20898
21083
  (direction) => {
20899
21084
  setActiveDirections((prev) => new Set(prev).add(direction));
20900
21085
  if (directionEvent) eventBus.emit(`UI:${directionEvent}`, { direction, pressed: true });
@@ -20902,7 +21087,7 @@ function DPad({
20902
21087
  },
20903
21088
  [directionEvent, eventBus, onDirection]
20904
21089
  );
20905
- const handleRelease = React79.useCallback(
21090
+ const handleRelease = React80.useCallback(
20906
21091
  (direction) => {
20907
21092
  setActiveDirections((prev) => {
20908
21093
  const next = new Set(prev);
@@ -21637,14 +21822,14 @@ function useDataDnd(args) {
21637
21822
  const isZone = Boolean(dragGroup || accepts || sortable);
21638
21823
  const enabled = isZone || Boolean(dndRoot);
21639
21824
  const eventBus = useEventBus();
21640
- const parentRoot = React79__default.useContext(RootCtx);
21825
+ const parentRoot = React80__default.useContext(RootCtx);
21641
21826
  const isRoot = enabled && parentRoot === null;
21642
- const zoneId = React79__default.useId();
21827
+ const zoneId = React80__default.useId();
21643
21828
  const ownGroup = dragGroup ?? accepts ?? zoneId;
21644
- const [optimisticOrders, setOptimisticOrders] = React79__default.useState(() => /* @__PURE__ */ new Map());
21645
- const optimisticOrdersRef = React79__default.useRef(optimisticOrders);
21829
+ const [optimisticOrders, setOptimisticOrders] = React80__default.useState(() => /* @__PURE__ */ new Map());
21830
+ const optimisticOrdersRef = React80__default.useRef(optimisticOrders);
21646
21831
  optimisticOrdersRef.current = optimisticOrders;
21647
- const clearOptimisticOrder = React79__default.useCallback((group) => {
21832
+ const clearOptimisticOrder = React80__default.useCallback((group) => {
21648
21833
  setOptimisticOrders((prev) => {
21649
21834
  if (!prev.has(group)) return prev;
21650
21835
  const next = new Map(prev);
@@ -21669,7 +21854,7 @@ function useDataDnd(args) {
21669
21854
  const raw = it[dndItemIdField];
21670
21855
  return String(raw ?? `__idx_${idx}`);
21671
21856
  }).join("|");
21672
- const itemIds = React79__default.useMemo(
21857
+ const itemIds = React80__default.useMemo(
21673
21858
  () => orderedItems.map((it, idx) => {
21674
21859
  const raw = it[dndItemIdField];
21675
21860
  return raw ?? `__idx_${idx}`;
@@ -21677,7 +21862,7 @@ function useDataDnd(args) {
21677
21862
  [itemIdsSignature]
21678
21863
  );
21679
21864
  const itemsContentSig = items.map((it, idx) => String(it[dndItemIdField] ?? `__${idx}`)).join("|");
21680
- React79__default.useEffect(() => {
21865
+ React80__default.useEffect(() => {
21681
21866
  const root = isRoot ? null : parentRoot;
21682
21867
  if (root) {
21683
21868
  root.clearOptimisticOrder(ownGroup);
@@ -21685,20 +21870,20 @@ function useDataDnd(args) {
21685
21870
  clearOptimisticOrder(ownGroup);
21686
21871
  }
21687
21872
  }, [itemsContentSig, ownGroup]);
21688
- const zonesRef = React79__default.useRef(/* @__PURE__ */ new Map());
21689
- const registerZone = React79__default.useCallback((zoneId2, meta2) => {
21873
+ const zonesRef = React80__default.useRef(/* @__PURE__ */ new Map());
21874
+ const registerZone = React80__default.useCallback((zoneId2, meta2) => {
21690
21875
  zonesRef.current.set(zoneId2, meta2);
21691
21876
  }, []);
21692
- const unregisterZone = React79__default.useCallback((zoneId2) => {
21877
+ const unregisterZone = React80__default.useCallback((zoneId2) => {
21693
21878
  zonesRef.current.delete(zoneId2);
21694
21879
  }, []);
21695
- const [activeDrag, setActiveDrag] = React79__default.useState(null);
21696
- const [overZoneGroup, setOverZoneGroup] = React79__default.useState(null);
21697
- const meta = React79__default.useMemo(
21880
+ const [activeDrag, setActiveDrag] = React80__default.useState(null);
21881
+ const [overZoneGroup, setOverZoneGroup] = React80__default.useState(null);
21882
+ const meta = React80__default.useMemo(
21698
21883
  () => ({ group: ownGroup, dropEvent, reorderEvent, positionEvent, itemIds, rawItems: items, idField: dndItemIdField }),
21699
21884
  [ownGroup, dropEvent, reorderEvent, positionEvent, itemIds, items, dndItemIdField]
21700
21885
  );
21701
- React79__default.useEffect(() => {
21886
+ React80__default.useEffect(() => {
21702
21887
  const target = isRoot ? null : parentRoot;
21703
21888
  if (!target) {
21704
21889
  zonesRef.current.set(zoneId, meta);
@@ -21717,7 +21902,7 @@ function useDataDnd(args) {
21717
21902
  }, [parentRoot, isRoot, zoneId, meta]);
21718
21903
  const sensors = useAlmadarDndSensors(true);
21719
21904
  const collisionDetection = almadarDndCollisionDetection;
21720
- const findZoneByItem = React79__default.useCallback(
21905
+ const findZoneByItem = React80__default.useCallback(
21721
21906
  (id) => {
21722
21907
  for (const z of zonesRef.current.values()) {
21723
21908
  if (z.itemIds.includes(id)) return z;
@@ -21726,7 +21911,7 @@ function useDataDnd(args) {
21726
21911
  },
21727
21912
  []
21728
21913
  );
21729
- React79__default.useCallback(
21914
+ React80__default.useCallback(
21730
21915
  (group) => {
21731
21916
  for (const z of zonesRef.current.values()) {
21732
21917
  if (z.group === group) return z;
@@ -21735,7 +21920,7 @@ function useDataDnd(args) {
21735
21920
  },
21736
21921
  []
21737
21922
  );
21738
- const handleDragEnd = React79__default.useCallback(
21923
+ const handleDragEnd = React80__default.useCallback(
21739
21924
  (event) => {
21740
21925
  const { active, over } = event;
21741
21926
  const activeIdStr = String(active.id);
@@ -21826,8 +22011,8 @@ function useDataDnd(args) {
21826
22011
  },
21827
22012
  [eventBus]
21828
22013
  );
21829
- const sortableData = React79__default.useMemo(() => ({ dndGroup: ownGroup }), [ownGroup]);
21830
- const SortableItem = React79__default.useCallback(
22014
+ const sortableData = React80__default.useMemo(() => ({ dndGroup: ownGroup }), [ownGroup]);
22015
+ const SortableItem = React80__default.useCallback(
21831
22016
  ({ id, children }) => {
21832
22017
  const {
21833
22018
  attributes,
@@ -21867,7 +22052,7 @@ function useDataDnd(args) {
21867
22052
  id: droppableId,
21868
22053
  data: sortableData
21869
22054
  });
21870
- const ctx = React79__default.useContext(RootCtx);
22055
+ const ctx = React80__default.useContext(RootCtx);
21871
22056
  const activeDrag2 = ctx?.activeDrag ?? null;
21872
22057
  const overZoneGroup2 = ctx?.overZoneGroup ?? null;
21873
22058
  const isThisZoneOver = overZoneGroup2 === ownGroup;
@@ -21882,7 +22067,7 @@ function useDataDnd(args) {
21882
22067
  showForeignPlaceholder,
21883
22068
  ctxAvailable: ctx != null
21884
22069
  });
21885
- React79__default.useEffect(() => {
22070
+ React80__default.useEffect(() => {
21886
22071
  dndLog.info("dropzone:isOver:change", { droppableId, group: ownGroup, isOver, isThisZoneOver, showForeignPlaceholder, activeDragSourceGroup: activeDrag2?.sourceGroup ?? null });
21887
22072
  }, [droppableId, isOver, isThisZoneOver, showForeignPlaceholder]);
21888
22073
  return /* @__PURE__ */ jsx(
@@ -21896,11 +22081,11 @@ function useDataDnd(args) {
21896
22081
  }
21897
22082
  );
21898
22083
  };
21899
- const rootContextValue = React79__default.useMemo(
22084
+ const rootContextValue = React80__default.useMemo(
21900
22085
  () => ({ registerZone, unregisterZone, activeDrag, overZoneGroup, optimisticOrders, clearOptimisticOrder }),
21901
22086
  [registerZone, unregisterZone, activeDrag, overZoneGroup, optimisticOrders, clearOptimisticOrder]
21902
22087
  );
21903
- const handleDragStart = React79__default.useCallback((event) => {
22088
+ const handleDragStart = React80__default.useCallback((event) => {
21904
22089
  const sourceZone = findZoneByItem(event.active.id);
21905
22090
  const rect = event.active.rect.current.initial;
21906
22091
  const height = rect?.height && rect.height > 0 ? rect.height : 64;
@@ -21919,7 +22104,7 @@ function useDataDnd(args) {
21919
22104
  isRoot
21920
22105
  });
21921
22106
  }, [findZoneByItem, isRoot, zoneId]);
21922
- const handleDragOver = React79__default.useCallback((event) => {
22107
+ const handleDragOver = React80__default.useCallback((event) => {
21923
22108
  const { active, over } = event;
21924
22109
  const overData = over?.data?.current;
21925
22110
  const overGroup = overData?.dndGroup ?? null;
@@ -21989,7 +22174,7 @@ function useDataDnd(args) {
21989
22174
  return next;
21990
22175
  });
21991
22176
  }, []);
21992
- const handleDragCancel = React79__default.useCallback((event) => {
22177
+ const handleDragCancel = React80__default.useCallback((event) => {
21993
22178
  setActiveDrag(null);
21994
22179
  setOverZoneGroup(null);
21995
22180
  dndLog.warn("dragCancel", {
@@ -21997,12 +22182,12 @@ function useDataDnd(args) {
21997
22182
  reason: "dnd-kit cancelled the drag (escape key, pointer interrupted, or external)"
21998
22183
  });
21999
22184
  }, []);
22000
- const handleDragEndWithCleanup = React79__default.useCallback((event) => {
22185
+ const handleDragEndWithCleanup = React80__default.useCallback((event) => {
22001
22186
  handleDragEnd(event);
22002
22187
  setActiveDrag(null);
22003
22188
  setOverZoneGroup(null);
22004
22189
  }, [handleDragEnd]);
22005
- const wrapContainer = React79__default.useCallback(
22190
+ const wrapContainer = React80__default.useCallback(
22006
22191
  (children) => {
22007
22192
  if (!enabled) return children;
22008
22193
  const strategy = layout === "grid" ? rectSortingStrategy : verticalListSortingStrategy;
@@ -22056,7 +22241,7 @@ var init_useDataDnd = __esm({
22056
22241
  init_useAlmadarDndCollision();
22057
22242
  init_Box();
22058
22243
  dndLog = createLogger("almadar:ui:dnd");
22059
- RootCtx = React79__default.createContext(null);
22244
+ RootCtx = React80__default.createContext(null);
22060
22245
  }
22061
22246
  });
22062
22247
  function fieldLabel2(key) {
@@ -22576,7 +22761,7 @@ function DataList({
22576
22761
  }) {
22577
22762
  const eventBus = useEventBus();
22578
22763
  const { t } = useTranslate();
22579
- const [visibleCount, setVisibleCount] = React79__default.useState(pageSize || Infinity);
22764
+ const [visibleCount, setVisibleCount] = React80__default.useState(pageSize || Infinity);
22580
22765
  const fieldDefs = fields ?? columns ?? [];
22581
22766
  const allDataRaw = Array.isArray(entity) ? entity : entity ? [entity] : [];
22582
22767
  const dnd = useDataDnd({
@@ -22595,7 +22780,7 @@ function DataList({
22595
22780
  const data = pageSize > 0 ? allData.slice(0, visibleCount) : allData;
22596
22781
  const hasMoreLocal = pageSize > 0 && visibleCount < allData.length;
22597
22782
  const hasRenderProp = typeof children === "function";
22598
- React79__default.useEffect(() => {
22783
+ React80__default.useEffect(() => {
22599
22784
  const renderItemTypeOf = typeof schemaRenderItem;
22600
22785
  const childrenTypeOf = typeof children;
22601
22786
  if (data.length > 0 && !hasRenderProp) {
@@ -22700,7 +22885,7 @@ function DataList({
22700
22885
  const items2 = data.map((item) => item);
22701
22886
  const groups2 = groupBy ? groupData(items2, groupBy) : [{ label: "", items: items2 }];
22702
22887
  const contentField = titleField?.name ?? fieldDefs[0]?.name ?? "";
22703
- return /* @__PURE__ */ jsx(VStack, { gap: "sm", className: cn("py-2", className), children: groups2.map((group, gi) => /* @__PURE__ */ jsxs(React79__default.Fragment, { children: [
22888
+ return /* @__PURE__ */ jsx(VStack, { gap: "sm", className: cn("py-2", className), children: groups2.map((group, gi) => /* @__PURE__ */ jsxs(React80__default.Fragment, { children: [
22704
22889
  group.label && /* @__PURE__ */ jsx(Divider, { label: group.label, className: "my-2" }),
22705
22890
  group.items.map((itemData, index) => {
22706
22891
  const id = itemData.id || `${gi}-${index}`;
@@ -22848,7 +23033,7 @@ function DataList({
22848
23033
  className
22849
23034
  ),
22850
23035
  children: [
22851
- groups.map((group, gi) => /* @__PURE__ */ jsxs(React79__default.Fragment, { children: [
23036
+ groups.map((group, gi) => /* @__PURE__ */ jsxs(React80__default.Fragment, { children: [
22852
23037
  group.label && /* @__PURE__ */ jsx(Divider, { label: group.label, className: gi > 0 ? "mt-4" : "mt-0" }),
22853
23038
  group.items.map(
22854
23039
  (itemData, index) => renderItem(itemData, index, gi === groups.length - 1 && index === group.items.length - 1)
@@ -24472,7 +24657,7 @@ var init_WizardProgress = __esm({
24472
24657
  children: /* @__PURE__ */ jsx("div", { className: "flex items-center gap-2", children: normalizedSteps.map((step, index) => {
24473
24658
  const isActive = index === currentStep;
24474
24659
  const isCompleted = index < currentStep;
24475
- return /* @__PURE__ */ jsxs(React79__default.Fragment, { children: [
24660
+ return /* @__PURE__ */ jsxs(React80__default.Fragment, { children: [
24476
24661
  /* @__PURE__ */ jsx(
24477
24662
  "button",
24478
24663
  {
@@ -25519,9 +25704,9 @@ function ScoreDisplay({
25519
25704
  ...rest
25520
25705
  }) {
25521
25706
  const resolvedValue = typeof value === "number" && !Number.isNaN(value) ? value : typeof rest.score === "number" && !Number.isNaN(rest.score) ? rest.score : 0;
25522
- const [displayValue, setDisplayValue] = React79.useState(resolvedValue);
25523
- const [isAnimating, setIsAnimating] = React79.useState(false);
25524
- React79.useEffect(() => {
25707
+ const [displayValue, setDisplayValue] = React80.useState(resolvedValue);
25708
+ const [isAnimating, setIsAnimating] = React80.useState(false);
25709
+ React80.useEffect(() => {
25525
25710
  if (!animated || displayValue === resolvedValue) {
25526
25711
  setDisplayValue(resolvedValue);
25527
25712
  return;
@@ -25668,7 +25853,7 @@ function InventoryGrid({
25668
25853
  const eventBus = useEventBus();
25669
25854
  const slotCount = totalSlots ?? items.length;
25670
25855
  const emptySlotCount = Math.max(0, slotCount - items.length);
25671
- const handleSelect = React79.useCallback(
25856
+ const handleSelect = React80.useCallback(
25672
25857
  (id) => {
25673
25858
  onSelect?.(id);
25674
25859
  if (selectEvent) {
@@ -25954,31 +26139,31 @@ function GameCanvas2D({
25954
26139
  assetBaseUrl = "",
25955
26140
  className
25956
26141
  }) {
25957
- const canvasRef = React79.useRef(null);
25958
- const rafRef = React79.useRef(0);
25959
- const frameRef = React79.useRef(0);
25960
- const lastTimeRef = React79.useRef(0);
25961
- const imageCache = React79.useRef(/* @__PURE__ */ new Map());
26142
+ const canvasRef = React80.useRef(null);
26143
+ const rafRef = React80.useRef(0);
26144
+ const frameRef = React80.useRef(0);
26145
+ const lastTimeRef = React80.useRef(0);
26146
+ const imageCache = React80.useRef(/* @__PURE__ */ new Map());
25962
26147
  const emit = useEmitEvent();
25963
- const onDrawRef = React79.useRef(onDraw);
26148
+ const onDrawRef = React80.useRef(onDraw);
25964
26149
  onDrawRef.current = onDraw;
25965
- const onTickRef = React79.useRef(onTick);
26150
+ const onTickRef = React80.useRef(onTick);
25966
26151
  onTickRef.current = onTick;
25967
- const tickEventRef = React79.useRef(tickEvent);
26152
+ const tickEventRef = React80.useRef(tickEvent);
25968
26153
  tickEventRef.current = tickEvent;
25969
- const drawEventRef = React79.useRef(drawEvent);
26154
+ const drawEventRef = React80.useRef(drawEvent);
25970
26155
  drawEventRef.current = drawEvent;
25971
- const emitRef = React79.useRef(emit);
26156
+ const emitRef = React80.useRef(emit);
25972
26157
  emitRef.current = emit;
25973
- const assetBaseUrlRef = React79.useRef(assetBaseUrl);
26158
+ const assetBaseUrlRef = React80.useRef(assetBaseUrl);
25974
26159
  assetBaseUrlRef.current = assetBaseUrl;
25975
- const backgroundImageRef = React79.useRef(backgroundImage);
26160
+ const backgroundImageRef = React80.useRef(backgroundImage);
25976
26161
  backgroundImageRef.current = backgroundImage;
25977
- const widthRef = React79.useRef(width);
26162
+ const widthRef = React80.useRef(width);
25978
26163
  widthRef.current = width;
25979
- const heightRef = React79.useRef(height);
26164
+ const heightRef = React80.useRef(height);
25980
26165
  heightRef.current = height;
25981
- const loadImage = React79.useCallback((url) => {
26166
+ const loadImage = React80.useCallback((url) => {
25982
26167
  const fullUrl = url.startsWith("http") ? url : `${assetBaseUrlRef.current}${url}`;
25983
26168
  const cached = imageCache.current.get(fullUrl);
25984
26169
  if (cached?.complete && cached.naturalWidth > 0) return cached;
@@ -25990,7 +26175,7 @@ function GameCanvas2D({
25990
26175
  }
25991
26176
  return null;
25992
26177
  }, []);
25993
- React79.useEffect(() => {
26178
+ React80.useEffect(() => {
25994
26179
  const canvas = canvasRef.current;
25995
26180
  if (!canvas) return;
25996
26181
  const ctx = canvas.getContext("2d");
@@ -26345,7 +26530,7 @@ function TurnPanel({
26345
26530
  className
26346
26531
  }) {
26347
26532
  const eventBus = useEventBus();
26348
- const handleAction = React79.useCallback(
26533
+ const handleAction = React80.useCallback(
26349
26534
  (event) => {
26350
26535
  if (event) {
26351
26536
  eventBus.emit(event, { turn: currentTurn, phase, activeTeam });
@@ -26491,7 +26676,7 @@ function UnitCommandBar({
26491
26676
  className
26492
26677
  }) {
26493
26678
  const eventBus = useEventBus();
26494
- const handleCommand = React79.useCallback(
26679
+ const handleCommand = React80.useCallback(
26495
26680
  (event) => {
26496
26681
  if (event) {
26497
26682
  eventBus.emit(event, { unitId: selectedUnitId });
@@ -26824,7 +27009,7 @@ function InventoryPanel({
26824
27009
  const slotArray = Array.from({ length: safeSlots }, (_, index) => {
26825
27010
  return safeItems[index] ?? null;
26826
27011
  });
26827
- const rows = Math.ceil(safeSlots / safeColumns);
27012
+ const rows2 = Math.ceil(safeSlots / safeColumns);
26828
27013
  const handleSlotClick = useCallback((index) => {
26829
27014
  if (selectSlotEvent) eventBus.emit(`UI:${selectSlotEvent}`, { index });
26830
27015
  onSelectSlot?.(index);
@@ -26893,7 +27078,7 @@ function InventoryPanel({
26893
27078
  className: "grid gap-1 bg-[var(--color-card)] p-2 rounded-container border border-border",
26894
27079
  style: {
26895
27080
  gridTemplateColumns: `repeat(${safeColumns}, ${slotSize}px)`,
26896
- gridTemplateRows: `repeat(${rows}, ${slotSize}px)`
27081
+ gridTemplateRows: `repeat(${rows2}, ${slotSize}px)`
26897
27082
  },
26898
27083
  children: slotArray.map((item, index) => /* @__PURE__ */ jsx(
26899
27084
  "button",
@@ -26976,7 +27161,7 @@ function GameMenu({
26976
27161
  } catch {
26977
27162
  }
26978
27163
  const eventBus = eventBusProp || eventBusFromHook;
26979
- const handleOptionClick = React79.useCallback(
27164
+ const handleOptionClick = React80.useCallback(
26980
27165
  (option) => {
26981
27166
  if (option.event && eventBus) {
26982
27167
  eventBus.emit(`UI:${option.event}`, { option });
@@ -27090,7 +27275,7 @@ function GameOverScreen({
27090
27275
  } catch {
27091
27276
  }
27092
27277
  const eventBus = eventBusProp || eventBusFromHook;
27093
- const handleActionClick = React79.useCallback(
27278
+ const handleActionClick = React80.useCallback(
27094
27279
  (action) => {
27095
27280
  if (action.event && eventBus) {
27096
27281
  eventBus.emit(`UI:${action.event}`, { action });
@@ -28589,8 +28774,8 @@ function TableView({
28589
28774
  }) {
28590
28775
  const eventBus = useEventBus();
28591
28776
  const { t } = useTranslate();
28592
- const [visibleCount, setVisibleCount] = React79__default.useState(pageSize > 0 ? pageSize : Infinity);
28593
- const [localSelected, setLocalSelected] = React79__default.useState(/* @__PURE__ */ new Set());
28777
+ const [visibleCount, setVisibleCount] = React80__default.useState(pageSize > 0 ? pageSize : Infinity);
28778
+ const [localSelected, setLocalSelected] = React80__default.useState(/* @__PURE__ */ new Set());
28594
28779
  const colDefs = columns ?? fields ?? [];
28595
28780
  const allDataRaw = Array.isArray(entity) ? entity : entity ? [entity] : [];
28596
28781
  const dnd = useDataDnd({
@@ -28785,12 +28970,12 @@ function TableView({
28785
28970
  ]
28786
28971
  }
28787
28972
  );
28788
- return dnd.isZone ? /* @__PURE__ */ jsx(dnd.SortableItem, { id: row[idField] ?? id, children: rowInner }, id) : /* @__PURE__ */ jsx(React79__default.Fragment, { children: rowInner }, id);
28973
+ return dnd.isZone ? /* @__PURE__ */ jsx(dnd.SortableItem, { id: row[idField] ?? id, children: rowInner }, id) : /* @__PURE__ */ jsx(React80__default.Fragment, { children: rowInner }, id);
28789
28974
  };
28790
28975
  const items = data.map((row) => row);
28791
28976
  const groups = groupBy ? groupData2(items, groupBy) : [{ label: "", items }];
28792
28977
  let runningIndex = 0;
28793
- const body = /* @__PURE__ */ jsx(Box, { role: "rowgroup", children: groups.map((group, gi) => /* @__PURE__ */ jsxs(React79__default.Fragment, { children: [
28978
+ const body = /* @__PURE__ */ jsx(Box, { role: "rowgroup", children: groups.map((group, gi) => /* @__PURE__ */ jsxs(React80__default.Fragment, { children: [
28794
28979
  group.label && /* @__PURE__ */ jsx(Divider, { label: group.label, className: gi > 0 ? "mt-3" : "mt-0" }),
28795
28980
  group.items.map((row) => renderRow(row, runningIndex++))
28796
28981
  ] }, gi)) });
@@ -30142,7 +30327,7 @@ var init_StepFlow = __esm({
30142
30327
  className
30143
30328
  }) => {
30144
30329
  if (orientation === "vertical") {
30145
- return /* @__PURE__ */ jsx(VStack, { gap: "none", className: cn("w-full", className), children: steps.map((step, index) => /* @__PURE__ */ jsx(React79__default.Fragment, { children: /* @__PURE__ */ jsxs(HStack, { gap: "md", align: "start", className: "w-full", children: [
30330
+ return /* @__PURE__ */ jsx(VStack, { gap: "none", className: cn("w-full", className), children: steps.map((step, index) => /* @__PURE__ */ jsx(React80__default.Fragment, { children: /* @__PURE__ */ jsxs(HStack, { gap: "md", align: "start", className: "w-full", children: [
30146
30331
  /* @__PURE__ */ jsxs(VStack, { gap: "none", align: "center", children: [
30147
30332
  /* @__PURE__ */ jsx(StepCircle, { step, index }),
30148
30333
  showConnectors && index < steps.length - 1 && /* @__PURE__ */ jsx(Box, { className: "w-px h-8 bg-border" })
@@ -30153,7 +30338,7 @@ var init_StepFlow = __esm({
30153
30338
  ] })
30154
30339
  ] }) }, index)) });
30155
30340
  }
30156
- return /* @__PURE__ */ jsx(Box, { className: cn("w-full flex flex-col md:flex-row items-start gap-0", className), children: steps.map((step, index) => /* @__PURE__ */ jsxs(React79__default.Fragment, { children: [
30341
+ return /* @__PURE__ */ jsx(Box, { className: cn("w-full flex flex-col md:flex-row items-start gap-0", className), children: steps.map((step, index) => /* @__PURE__ */ jsxs(React80__default.Fragment, { children: [
30157
30342
  /* @__PURE__ */ jsxs(VStack, { gap: "sm", align: "center", className: "flex-1 w-full md:w-auto", children: [
30158
30343
  /* @__PURE__ */ jsx(StepCircle, { step, index }),
30159
30344
  /* @__PURE__ */ jsx(Typography, { variant: "h4", className: "text-center", children: step.title }),
@@ -30879,11 +31064,11 @@ function LatticeSVG({
30879
31064
  }) {
30880
31065
  const paths = [];
30881
31066
  const cols = 5;
30882
- const rows = Math.ceil(h / (w / cols));
31067
+ const rows2 = Math.ceil(h / (w / cols));
30883
31068
  const cellW = w / cols;
30884
31069
  const cellH = cellW;
30885
31070
  const bulge = cellW * 0.3;
30886
- for (let row = 0; row < rows; row++) {
31071
+ for (let row = 0; row < rows2; row++) {
30887
31072
  for (let col = 0; col < cols; col++) {
30888
31073
  const cx = col * cellW + cellW / 2;
30889
31074
  const cy = row * cellH + cellH / 2;
@@ -31129,7 +31314,7 @@ var init_LikertScale = __esm({
31129
31314
  md: "text-base",
31130
31315
  lg: "text-lg"
31131
31316
  };
31132
- LikertScale = React79__default.forwardRef(
31317
+ LikertScale = React80__default.forwardRef(
31133
31318
  ({
31134
31319
  question,
31135
31320
  options = DEFAULT_LIKERT_OPTIONS,
@@ -31141,7 +31326,7 @@ var init_LikertScale = __esm({
31141
31326
  variant = "radios",
31142
31327
  className
31143
31328
  }, ref) => {
31144
- const groupId = React79__default.useId();
31329
+ const groupId = React80__default.useId();
31145
31330
  const eventBus = useEventBus();
31146
31331
  const handleSelect = useCallback(
31147
31332
  (next) => {
@@ -31295,7 +31480,7 @@ var init_MatrixQuestion = __esm({
31295
31480
  };
31296
31481
  MatrixQuestion = ({
31297
31482
  title,
31298
- rows,
31483
+ rows: rows2,
31299
31484
  columns = DEFAULT_MATRIX_COLUMNS,
31300
31485
  values,
31301
31486
  onChange,
@@ -31305,7 +31490,7 @@ var init_MatrixQuestion = __esm({
31305
31490
  className
31306
31491
  }) => {
31307
31492
  const styles = sizeStyles13[size];
31308
- const safeRows = rows ?? [];
31493
+ const safeRows = rows2 ?? [];
31309
31494
  const safeValues = values ?? {};
31310
31495
  const eventBus = useEventBus();
31311
31496
  const handleChange = useCallback(
@@ -31933,7 +32118,8 @@ var init_PositionedCanvas = __esm({
31933
32118
  dragRef.current = null;
31934
32119
  setDraggingId(null);
31935
32120
  if (!wasDrag) {
31936
- const next = selectedId === item.id ? null : item.id;
32121
+ const itemId = item.id;
32122
+ const next = selectedId === itemId ? null : itemId;
31937
32123
  onSelect?.(next);
31938
32124
  if (selectEvent) {
31939
32125
  eventBus.emit(`UI:${selectEvent}`, { id: next });
@@ -31968,15 +32154,22 @@ var init_PositionedCanvas = __esm({
31968
32154
  style: { width, height },
31969
32155
  onClick: handleContainerClick,
31970
32156
  children: items.map((item) => {
32157
+ const itemId = item.id;
32158
+ const label = item.label;
32159
+ const x = item.x;
32160
+ const y = item.y;
32161
+ const capacity = item.capacity;
32162
+ const partySize = item.partySize;
32163
+ const serverName = item.serverName;
31971
32164
  const status = item.status ?? "empty";
31972
32165
  const shape = item.shape ?? "round";
31973
- const isSelected = selectedId === item.id;
31974
- const isDragging = draggingId === item.id;
32166
+ const isSelected = selectedId === itemId;
32167
+ const isDragging = draggingId === itemId;
31975
32168
  const statusBadge = STATUS_BADGE[status];
31976
32169
  return /* @__PURE__ */ jsxs(
31977
32170
  Box,
31978
32171
  {
31979
- "data-testid": `item-node-${item.id}`,
32172
+ "data-testid": `item-node-${itemId}`,
31980
32173
  "data-status": status,
31981
32174
  className: cn(
31982
32175
  "absolute flex flex-col items-center justify-center gap-1 border-2 select-none",
@@ -31987,7 +32180,7 @@ var init_PositionedCanvas = __esm({
31987
32180
  isSelected && "outline outline-2 outline-offset-2 outline-primary shadow-md",
31988
32181
  isDragging && "shadow-lg z-10"
31989
32182
  ),
31990
- style: { left: item.x, top: item.y, touchAction: "none" },
32183
+ style: { left: x, top: y, touchAction: "none" },
31991
32184
  onPointerDown: (e) => handlePointerDown(e, item),
31992
32185
  onPointerMove: handlePointerMove,
31993
32186
  onPointerUp: (e) => handlePointerUp(e, item),
@@ -31995,10 +32188,10 @@ var init_PositionedCanvas = __esm({
31995
32188
  children: [
31996
32189
  /* @__PURE__ */ jsxs(Box, { className: "flex items-center gap-1", children: [
31997
32190
  getStatusIcon(status),
31998
- /* @__PURE__ */ jsx(Typography, { variant: "body2", weight: "semibold", children: item.label })
32191
+ /* @__PURE__ */ jsx(Typography, { variant: "body2", weight: "semibold", children: label })
31999
32192
  ] }),
32000
- /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", children: item.partySize !== void 0 && status === "seated" ? `${item.partySize}/${item.capacity}` : `Cap ${item.capacity}` }),
32001
- status === "seated" && item.serverName && /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", className: "truncate max-w-[80%]", children: item.serverName }),
32193
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", children: partySize !== void 0 && status === "seated" ? `${partySize}/${capacity}` : `Cap ${capacity}` }),
32194
+ status === "seated" && serverName && /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", className: "truncate max-w-[80%]", children: serverName }),
32002
32195
  isSelected && /* @__PURE__ */ jsx(
32003
32196
  Badge,
32004
32197
  {
@@ -32010,7 +32203,7 @@ var init_PositionedCanvas = __esm({
32010
32203
  )
32011
32204
  ]
32012
32205
  },
32013
- item.id
32206
+ itemId
32014
32207
  );
32015
32208
  })
32016
32209
  }
@@ -32782,9 +32975,10 @@ var init_RichBlockEditor = __esm({
32782
32975
  });
32783
32976
  function collectInitiallyCollapsed(nodes, acc) {
32784
32977
  for (const n of nodes) {
32978
+ const replies = n.replies;
32785
32979
  if (n.collapsed) acc.add(n.id);
32786
- if (n.replies && n.replies.length > 0) {
32787
- collectInitiallyCollapsed(n.replies, acc);
32980
+ if (replies && replies.length > 0) {
32981
+ collectInitiallyCollapsed(replies, acc);
32788
32982
  }
32789
32983
  }
32790
32984
  }
@@ -32814,44 +33008,52 @@ var init_ReplyTree = __esm({
32814
33008
  }) => {
32815
33009
  const eventBus = useEventBus();
32816
33010
  const { t } = useTranslate();
32817
- const hasReplies = !!node.replies && node.replies.length > 0;
32818
- const isCollapsed = collapsedSet.has(node.id);
33011
+ const nodeId = node.id;
33012
+ const authorName = node.authorName;
33013
+ const authorAvatarUrl = node.authorAvatarUrl;
33014
+ const content = node.content;
33015
+ const postedAt = node.postedAt;
33016
+ const voteCount = node.voteCount;
33017
+ const userVote = node.userVote;
33018
+ const replies = node.replies;
33019
+ const hasReplies = !!replies && replies.length > 0;
33020
+ const isCollapsed = collapsedSet.has(nodeId);
32819
33021
  const atMaxDepth = depth >= maxDepth;
32820
33022
  const [replyOpen, setReplyOpen] = useState(false);
32821
33023
  const [draft, setDraft] = useState("");
32822
33024
  const handleVote = useCallback(
32823
33025
  (next) => {
32824
- onVote?.(node.id, next);
32825
- if (voteEvent) eventBus.emit(`UI:${voteEvent}`, { nodeId: node.id, vote: next });
33026
+ onVote?.(nodeId, next);
33027
+ if (voteEvent) eventBus.emit(`UI:${voteEvent}`, { nodeId, vote: next });
32826
33028
  },
32827
- [node.id, onVote, voteEvent, eventBus]
33029
+ [nodeId, onVote, voteEvent, eventBus]
32828
33030
  );
32829
33031
  const handleReply = useCallback(() => {
32830
- onReply?.(node.id);
33032
+ onReply?.(nodeId);
32831
33033
  setReplyOpen((open) => !open);
32832
- }, [node.id, onReply]);
33034
+ }, [nodeId, onReply]);
32833
33035
  const handleSubmitReply = useCallback(() => {
32834
- const content = draft.trim();
32835
- if (!content) return;
32836
- if (replyEvent) eventBus.emit(`UI:${replyEvent}`, { parentNodeId: node.id, content });
33036
+ const text = draft.trim();
33037
+ if (!text) return;
33038
+ if (replyEvent) eventBus.emit(`UI:${replyEvent}`, { parentNodeId: nodeId, content: text });
32837
33039
  setDraft("");
32838
33040
  setReplyOpen(false);
32839
- }, [node.id, draft, replyEvent, eventBus]);
33041
+ }, [nodeId, draft, replyEvent, eventBus]);
32840
33042
  const handleCancelReply = useCallback(() => {
32841
33043
  setDraft("");
32842
33044
  setReplyOpen(false);
32843
33045
  }, []);
32844
33046
  const handleFlag = useCallback(() => {
32845
- onFlag?.(node.id);
32846
- if (flagEvent) eventBus.emit(`UI:${flagEvent}`, { nodeId: node.id });
32847
- }, [node.id, onFlag, flagEvent, eventBus]);
33047
+ onFlag?.(nodeId);
33048
+ if (flagEvent) eventBus.emit(`UI:${flagEvent}`, { nodeId });
33049
+ }, [nodeId, onFlag, flagEvent, eventBus]);
32848
33050
  const handleContinue = useCallback(() => {
32849
- onContinueThread?.(node.id);
32850
- if (continueThreadEvent) eventBus.emit(`UI:${continueThreadEvent}`, { nodeId: node.id });
32851
- }, [node.id, onContinueThread, continueThreadEvent, eventBus]);
33051
+ onContinueThread?.(nodeId);
33052
+ if (continueThreadEvent) eventBus.emit(`UI:${continueThreadEvent}`, { nodeId });
33053
+ }, [nodeId, onContinueThread, continueThreadEvent, eventBus]);
32852
33054
  const handleToggle = useCallback(() => {
32853
- toggleCollapse(node.id);
32854
- }, [node.id, toggleCollapse]);
33055
+ toggleCollapse(nodeId);
33056
+ }, [nodeId, toggleCollapse]);
32855
33057
  return /* @__PURE__ */ jsxs(Box, { className: "flex flex-row gap-2 items-stretch min-w-0", children: [
32856
33058
  /* @__PURE__ */ jsxs(Box, { className: "flex flex-col items-center flex-shrink-0 w-6", children: [
32857
33059
  hasReplies ? /* @__PURE__ */ jsx(
@@ -32883,25 +33085,25 @@ var init_ReplyTree = __esm({
32883
33085
  /* @__PURE__ */ jsx(
32884
33086
  Avatar,
32885
33087
  {
32886
- src: node.authorAvatarUrl,
32887
- name: node.authorName,
33088
+ src: authorAvatarUrl,
33089
+ name: authorName,
32888
33090
  size: "sm"
32889
33091
  }
32890
33092
  ),
32891
- /* @__PURE__ */ jsx(Typography, { variant: "body", weight: "semibold", children: node.authorName }),
32892
- /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", children: node.postedAt })
33093
+ /* @__PURE__ */ jsx(Typography, { variant: "body", weight: "semibold", children: authorName }),
33094
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", children: postedAt })
32893
33095
  ] }),
32894
- /* @__PURE__ */ jsx(Typography, { variant: "body", className: "whitespace-pre-wrap break-words", children: node.content }),
33096
+ /* @__PURE__ */ jsx(Typography, { variant: "body", className: "whitespace-pre-wrap break-words", children: content }),
32895
33097
  showActions && /* @__PURE__ */ jsxs(Box, { className: "flex flex-row gap-2 items-center", children: [
32896
33098
  /* @__PURE__ */ jsx(
32897
33099
  VoteStack,
32898
33100
  {
32899
- count: node.voteCount ?? 0,
32900
- userVote: node.userVote ?? null,
33101
+ count: voteCount ?? 0,
33102
+ userVote: userVote ?? null,
32901
33103
  onVote: handleVote,
32902
33104
  size: "sm",
32903
33105
  variant: "horizontal",
32904
- label: t("replyTree.voteOnReplyBy", { author: node.authorName })
33106
+ label: t("replyTree.voteOnReplyBy", { author: authorName })
32905
33107
  }
32906
33108
  ),
32907
33109
  /* @__PURE__ */ jsx(
@@ -32911,7 +33113,7 @@ var init_ReplyTree = __esm({
32911
33113
  size: "sm",
32912
33114
  leftIcon: "message-square",
32913
33115
  onClick: handleReply,
32914
- "aria-label": t("replyTree.replyTo", { author: node.authorName }),
33116
+ "aria-label": t("replyTree.replyTo", { author: authorName }),
32915
33117
  children: t("replyTree.reply")
32916
33118
  }
32917
33119
  ),
@@ -32922,7 +33124,7 @@ var init_ReplyTree = __esm({
32922
33124
  size: "sm",
32923
33125
  leftIcon: "flag",
32924
33126
  onClick: handleFlag,
32925
- "aria-label": t("replyTree.flagReplyBy", { author: node.authorName }),
33127
+ "aria-label": t("replyTree.flagReplyBy", { author: authorName }),
32926
33128
  children: t("replyTree.flag")
32927
33129
  }
32928
33130
  )
@@ -32934,9 +33136,9 @@ var init_ReplyTree = __esm({
32934
33136
  inputType: "textarea",
32935
33137
  rows: 2,
32936
33138
  value: draft,
32937
- placeholder: t("replyTree.replyToPlaceholder", { author: node.authorName }),
33139
+ placeholder: t("replyTree.replyToPlaceholder", { author: authorName }),
32938
33140
  onChange: (e) => setDraft(e.target.value),
32939
- "aria-label": t("replyTree.replyTo", { author: node.authorName })
33141
+ "aria-label": t("replyTree.replyTo", { author: authorName })
32940
33142
  }
32941
33143
  ),
32942
33144
  /* @__PURE__ */ jsxs(Box, { className: "flex flex-row gap-2 items-center", children: [
@@ -32967,7 +33169,7 @@ var init_ReplyTree = __esm({
32967
33169
  ),
32968
33170
  children: t("replyTree.continueThread")
32969
33171
  }
32970
- ) : /* @__PURE__ */ jsx(Box, { className: "flex flex-col gap-2 mt-1", children: node.replies.map((child) => /* @__PURE__ */ jsx(
33172
+ ) : /* @__PURE__ */ jsx(Box, { className: "flex flex-col gap-2 mt-1", children: replies.map((child) => /* @__PURE__ */ jsx(
32971
33173
  ReplyTreeNode,
32972
33174
  {
32973
33175
  node: child,
@@ -33429,7 +33631,7 @@ var init_DocBreadcrumb = __esm({
33429
33631
  "aria-label": t("aria.breadcrumb"),
33430
33632
  children: /* @__PURE__ */ jsx(HStack, { gap: "xs", align: "center", wrap: true, children: items.map((item, idx) => {
33431
33633
  const isLast = idx === items.length - 1;
33432
- return /* @__PURE__ */ jsxs(React79__default.Fragment, { children: [
33634
+ return /* @__PURE__ */ jsxs(React80__default.Fragment, { children: [
33433
33635
  idx > 0 && /* @__PURE__ */ jsx(
33434
33636
  Icon,
33435
33637
  {
@@ -34393,7 +34595,7 @@ var init_MiniStateMachine = __esm({
34393
34595
  const x = 2 + i * (NODE_W + GAP2 + ARROW_W + GAP2);
34394
34596
  const tc = transitionCounts[s.name] ?? 0;
34395
34597
  const role = getStateRole(s.name, s.isInitial, s.isTerminal, tc, maxTC);
34396
- return /* @__PURE__ */ jsxs(React79__default.Fragment, { children: [
34598
+ return /* @__PURE__ */ jsxs(React80__default.Fragment, { children: [
34397
34599
  /* @__PURE__ */ jsx(
34398
34600
  AvlState,
34399
34601
  {
@@ -34597,7 +34799,7 @@ var init_PageHeader = __esm({
34597
34799
  info: "bg-info/10 text-info"
34598
34800
  };
34599
34801
  return /* @__PURE__ */ jsxs(Box, { className: cn("mb-6", className), children: [
34600
- breadcrumbs && breadcrumbs.length > 0 && /* @__PURE__ */ jsx(Box, { as: "nav", className: "mb-4", children: /* @__PURE__ */ jsx(Box, { as: "ol", className: "flex items-center gap-2 text-sm", children: breadcrumbs.map((crumb, idx) => /* @__PURE__ */ jsxs(React79__default.Fragment, { children: [
34802
+ breadcrumbs && breadcrumbs.length > 0 && /* @__PURE__ */ jsx(Box, { as: "nav", className: "mb-4", children: /* @__PURE__ */ jsx(Box, { as: "ol", className: "flex items-center gap-2 text-sm", children: breadcrumbs.map((crumb, idx) => /* @__PURE__ */ jsxs(React80__default.Fragment, { children: [
34601
34803
  idx > 0 && /* @__PURE__ */ jsx(Typography, { variant: "small", color: "muted", children: "/" }),
34602
34804
  crumb.href ? /* @__PURE__ */ jsx(
34603
34805
  "a",
@@ -34706,7 +34908,7 @@ var init_FormSection = __esm({
34706
34908
  columns = 1,
34707
34909
  className
34708
34910
  }) => {
34709
- const [collapsed, setCollapsed] = React79__default.useState(defaultCollapsed);
34911
+ const [collapsed, setCollapsed] = React80__default.useState(defaultCollapsed);
34710
34912
  const { t } = useTranslate();
34711
34913
  const eventBus = useEventBus();
34712
34914
  const gridClass = {
@@ -34714,7 +34916,7 @@ var init_FormSection = __esm({
34714
34916
  2: "grid-cols-1 md:grid-cols-2",
34715
34917
  3: "grid-cols-1 md:grid-cols-2 lg:grid-cols-3"
34716
34918
  }[columns];
34717
- React79__default.useCallback(() => {
34919
+ React80__default.useCallback(() => {
34718
34920
  if (collapsible) {
34719
34921
  setCollapsed((prev) => !prev);
34720
34922
  eventBus.emit("UI:TOGGLE_COLLAPSE", { collapsed: !collapsed });
@@ -35414,8 +35616,8 @@ var init_WizardContainer = __esm({
35414
35616
  return void 0;
35415
35617
  if (typeof controlledStep === "number") return controlledStep;
35416
35618
  if (typeof controlledStep === "string") return parseInt(controlledStep, 10);
35417
- const num = Number(controlledStep);
35418
- return isNaN(num) ? void 0 : num;
35619
+ const num2 = Number(controlledStep);
35620
+ return isNaN(num2) ? void 0 : num2;
35419
35621
  })();
35420
35622
  const currentStep = normalizedControlledStep !== void 0 ? normalizedControlledStep : internalStep;
35421
35623
  const totalSteps = steps.length;
@@ -35461,7 +35663,7 @@ var init_WizardContainer = __esm({
35461
35663
  const isCompleted = index < currentStep;
35462
35664
  const stepKey = step.id ?? step.tabId ?? `step-${index}`;
35463
35665
  const stepTitle = step.title ?? step.name ?? `Step ${index + 1}`;
35464
- return /* @__PURE__ */ jsxs(React79__default.Fragment, { children: [
35666
+ return /* @__PURE__ */ jsxs(React80__default.Fragment, { children: [
35465
35667
  /* @__PURE__ */ jsx(
35466
35668
  Button,
35467
35669
  {
@@ -37240,7 +37442,7 @@ function DebuggerBoard({
37240
37442
  }) {
37241
37443
  const { emit } = useEventBus();
37242
37444
  const { t } = useTranslate();
37243
- const resolved = Array.isArray(entity) ? entity[0] : entity;
37445
+ const resolved = boardEntity(entity);
37244
37446
  const [flaggedLines, setFlaggedLines] = useState(/* @__PURE__ */ new Set());
37245
37447
  const [headerError, setHeaderError] = useState(false);
37246
37448
  const [submitted, setSubmitted] = useState(false);
@@ -37258,7 +37460,7 @@ function DebuggerBoard({
37258
37460
  return next;
37259
37461
  });
37260
37462
  };
37261
- const lines = resolved?.lines ?? [];
37463
+ const lines = Array.isArray(resolved?.lines) ? resolved.lines : [];
37262
37464
  const bugLines = lines.filter((l) => l.isBug);
37263
37465
  const correctFlags = lines.filter((l) => l.isBug && flaggedLines.has(l.id));
37264
37466
  const falseFlags = lines.filter((l) => !l.isBug && flaggedLines.has(l.id));
@@ -37273,7 +37475,7 @@ function DebuggerBoard({
37273
37475
  }, [correctFlags.length, bugLines.length, falseFlags.length, attempts, completeEvent, emit]);
37274
37476
  const handleReset = () => {
37275
37477
  setSubmitted(false);
37276
- if (attempts >= 2 && resolved?.hint) {
37478
+ if (attempts >= 2 && str(resolved?.hint)) {
37277
37479
  setShowHint(true);
37278
37480
  }
37279
37481
  };
@@ -37284,24 +37486,28 @@ function DebuggerBoard({
37284
37486
  setShowHint(false);
37285
37487
  };
37286
37488
  if (!resolved) return null;
37489
+ const theme = resolved.theme ?? void 0;
37490
+ const themeBackground = theme?.background;
37491
+ const headerImage = str(resolved.headerImage);
37492
+ const hint = str(resolved.hint);
37287
37493
  return /* @__PURE__ */ jsx(
37288
37494
  Box,
37289
37495
  {
37290
37496
  className,
37291
37497
  style: {
37292
- backgroundImage: resolved.theme?.background ? `url(${resolved.theme.background})` : void 0,
37498
+ backgroundImage: themeBackground ? `url(${themeBackground})` : void 0,
37293
37499
  backgroundSize: "cover",
37294
37500
  backgroundPosition: "center"
37295
37501
  },
37296
37502
  children: /* @__PURE__ */ jsxs(VStack, { gap: "lg", className: "p-4", children: [
37297
- resolved.headerImage && !headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 overflow-hidden rounded-container", children: /* @__PURE__ */ jsx("img", { src: resolved.headerImage, alt: "", onError: () => setHeaderError(true), className: "w-full h-full object-cover" }) }) : resolved.headerImage && headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 rounded-container bg-gradient-to-br from-muted to-accent opacity-60" }) : null,
37503
+ 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,
37298
37504
  /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
37299
37505
  /* @__PURE__ */ jsxs(HStack, { gap: "xs", align: "center", children: [
37300
37506
  /* @__PURE__ */ jsx(Icon, { icon: Bug, size: "sm" }),
37301
- /* @__PURE__ */ jsx(Typography, { variant: "h4", weight: "bold", children: resolved.title })
37507
+ /* @__PURE__ */ jsx(Typography, { variant: "h4", weight: "bold", children: str(resolved.title) })
37302
37508
  ] }),
37303
- /* @__PURE__ */ jsx(Typography, { variant: "body", children: resolved.description }),
37304
- /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-muted-foreground", children: t("debugger.findBugs", { count: String(resolved.bugCount) }) })
37509
+ /* @__PURE__ */ jsx(Typography, { variant: "body", children: str(resolved.description) }),
37510
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-muted-foreground", children: t("debugger.findBugs", { count: String(num(resolved.bugCount)) }) })
37305
37511
  ] }) }),
37306
37512
  /* @__PURE__ */ jsx(Card, { className: "p-0 overflow-hidden", children: /* @__PURE__ */ jsx(VStack, { gap: "none", children: lines.map((line, i) => {
37307
37513
  const isFlagged = flaggedLines.has(line.id);
@@ -37333,7 +37539,7 @@ function DebuggerBoard({
37333
37539
  );
37334
37540
  }) }) }),
37335
37541
  submitted && /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
37336
- /* @__PURE__ */ jsx(Typography, { variant: "body", weight: "bold", children: allCorrect ? resolved.successMessage ?? t("debugger.allFound") : `${correctFlags.length}/${bugLines.length} ${t("debugger.bugsFound")}` }),
37542
+ /* @__PURE__ */ jsx(Typography, { variant: "body", weight: "bold", children: allCorrect ? str(resolved.successMessage) || t("debugger.allFound") : `${correctFlags.length}/${bugLines.length} ${t("debugger.bugsFound")}` }),
37337
37543
  bugLines.map((line) => /* @__PURE__ */ jsxs(HStack, { gap: "xs", align: "start", children: [
37338
37544
  /* @__PURE__ */ jsx(
37339
37545
  Icon,
@@ -37349,7 +37555,7 @@ function DebuggerBoard({
37349
37555
  ] })
37350
37556
  ] }, line.id))
37351
37557
  ] }) }),
37352
- showHint && resolved.hint && /* @__PURE__ */ jsx(Card, { className: "p-4 border-l-4 border-l-warning", children: /* @__PURE__ */ jsx(Typography, { variant: "body", children: resolved.hint }) }),
37558
+ showHint && hint && /* @__PURE__ */ jsx(Card, { className: "p-4 border-l-4 border-l-warning", children: /* @__PURE__ */ jsx(Typography, { variant: "body", children: hint }) }),
37353
37559
  /* @__PURE__ */ jsxs(HStack, { gap: "sm", justify: "center", children: [
37354
37560
  !submitted ? /* @__PURE__ */ jsxs(Button, { variant: "primary", onClick: handleSubmit, disabled: flaggedLines.size === 0, children: [
37355
37561
  /* @__PURE__ */ jsx(Icon, { icon: Send, size: "sm" }),
@@ -37368,6 +37574,7 @@ var init_DebuggerBoard = __esm({
37368
37574
  "components/game/organisms/puzzles/debugger/DebuggerBoard.tsx"() {
37369
37575
  init_atoms2();
37370
37576
  init_useEventBus();
37577
+ init_boardEntity();
37371
37578
  DebuggerBoard.displayName = "DebuggerBoard";
37372
37579
  }
37373
37580
  });
@@ -37405,7 +37612,7 @@ function getBadgeVariant(fieldName, value) {
37405
37612
  return "default";
37406
37613
  }
37407
37614
  function formatFieldLabel(fieldName) {
37408
- return fieldName.replace(/([A-Z])/g, " $1").replace(/^./, (str) => str.toUpperCase());
37615
+ return fieldName.replace(/([A-Z])/g, " $1").replace(/^./, (str2) => str2.toUpperCase());
37409
37616
  }
37410
37617
  function formatFieldValue(value, fieldName) {
37411
37618
  if (typeof value === "number") {
@@ -37424,26 +37631,26 @@ function formatFieldValue(value, fieldName) {
37424
37631
  }
37425
37632
  function renderRichFieldValue(value, fieldName, fieldType) {
37426
37633
  if (value === void 0 || value === null) return "\u2014";
37427
- const str = String(value);
37634
+ const str2 = String(value);
37428
37635
  switch (fieldType) {
37429
37636
  case "image":
37430
37637
  case "url": {
37431
- if (str.match(/\.(png|jpe?g|gif|svg|webp|avif)(\?|$)/i) || str.startsWith("data:image/")) {
37638
+ if (str2.match(/\.(png|jpe?g|gif|svg|webp|avif)(\?|$)/i) || str2.startsWith("data:image/")) {
37432
37639
  return /* @__PURE__ */ jsx(Box, { className: "mt-1 max-w-full", children: /* @__PURE__ */ jsx(
37433
37640
  "img",
37434
37641
  {
37435
- src: str,
37642
+ src: str2,
37436
37643
  alt: formatFieldLabel(fieldName),
37437
37644
  className: "max-w-full max-h-64 rounded-md object-contain",
37438
37645
  loading: "lazy"
37439
37646
  }
37440
37647
  ) });
37441
37648
  }
37442
- return str;
37649
+ return str2;
37443
37650
  }
37444
37651
  case "markdown":
37445
37652
  case "richtext":
37446
- return /* @__PURE__ */ jsx(Suspense, { fallback: /* @__PURE__ */ jsx(Typography, { variant: "body", className: "break-words", children: str }), children: /* @__PURE__ */ jsx(
37653
+ return /* @__PURE__ */ jsx(Suspense, { fallback: /* @__PURE__ */ jsx(Typography, { variant: "body", className: "break-words", children: str2 }), children: /* @__PURE__ */ jsx(
37447
37654
  Box,
37448
37655
  {
37449
37656
  className: "prose prose-sm max-w-none",
@@ -37461,11 +37668,11 @@ function renderRichFieldValue(value, fieldName, fieldType) {
37461
37668
  "--tw-prose-th-borders": "var(--color-border)",
37462
37669
  "--tw-prose-td-borders": "var(--color-border)"
37463
37670
  },
37464
- children: /* @__PURE__ */ jsx(ReactMarkdown2, { children: str })
37671
+ children: /* @__PURE__ */ jsx(ReactMarkdown2, { children: str2 })
37465
37672
  }
37466
37673
  ) });
37467
37674
  case "code":
37468
- 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: str }) }) });
37675
+ 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 }) }) });
37469
37676
  case "html":
37470
37677
  return /* @__PURE__ */ jsx(
37471
37678
  Box,
@@ -37485,12 +37692,12 @@ function renderRichFieldValue(value, fieldName, fieldType) {
37485
37692
  "--tw-prose-th-borders": "var(--color-border)",
37486
37693
  "--tw-prose-td-borders": "var(--color-border)"
37487
37694
  },
37488
- children: /* @__PURE__ */ jsx(Typography, { variant: "body", children: str })
37695
+ children: /* @__PURE__ */ jsx(Typography, { variant: "body", children: str2 })
37489
37696
  }
37490
37697
  );
37491
37698
  case "date":
37492
37699
  case "datetime": {
37493
- const d = new Date(str);
37700
+ const d = new Date(str2);
37494
37701
  if (!isNaN(d.getTime())) {
37495
37702
  return d.toLocaleDateString(void 0, {
37496
37703
  year: "numeric",
@@ -37499,7 +37706,7 @@ function renderRichFieldValue(value, fieldName, fieldType) {
37499
37706
  ...fieldType === "datetime" ? { hour: "2-digit", minute: "2-digit" } : {}
37500
37707
  });
37501
37708
  }
37502
- return str;
37709
+ return str2;
37503
37710
  }
37504
37711
  default:
37505
37712
  return formatFieldValue(value, fieldName);
@@ -37899,7 +38106,7 @@ var init_DialogueBubble = __esm({
37899
38106
  }
37900
38107
  });
37901
38108
  function extractTitle(children) {
37902
- if (!React79__default.isValidElement(children)) return void 0;
38109
+ if (!React80__default.isValidElement(children)) return void 0;
37903
38110
  const props = children.props;
37904
38111
  if (typeof props.title === "string") {
37905
38112
  return props.title;
@@ -38011,7 +38218,7 @@ function LinearView({
38011
38218
  /* @__PURE__ */ jsx(HStack, { className: "flex-wrap items-center", gap: "xs", children: trait.states.map((state, i) => {
38012
38219
  const isDone = i < currentIdx;
38013
38220
  const isCurrent = i === currentIdx;
38014
- return /* @__PURE__ */ jsxs(React79__default.Fragment, { children: [
38221
+ return /* @__PURE__ */ jsxs(React80__default.Fragment, { children: [
38015
38222
  i > 0 && /* @__PURE__ */ jsx(
38016
38223
  Typography,
38017
38224
  {
@@ -38272,6 +38479,40 @@ var init_RuleEditor = __esm({
38272
38479
  RuleEditor.displayName = "RuleEditor";
38273
38480
  }
38274
38481
  });
38482
+
38483
+ // components/game/organisms/puzzles/event-handler/puzzleObject.ts
38484
+ function objId(o) {
38485
+ return o.id == null ? "" : String(o.id);
38486
+ }
38487
+ function objName(o) {
38488
+ return o.name == null ? "" : String(o.name);
38489
+ }
38490
+ function objIcon(o) {
38491
+ return o.icon == null ? "" : String(o.icon);
38492
+ }
38493
+ function objStates(o) {
38494
+ return Array.isArray(o.states) ? o.states : [];
38495
+ }
38496
+ function objCurrentState(o) {
38497
+ return o.currentState == null ? "" : String(o.currentState);
38498
+ }
38499
+ function objAvailableEvents(o) {
38500
+ return Array.isArray(o.availableEvents) ? o.availableEvents : [];
38501
+ }
38502
+ function objAvailableActions(o) {
38503
+ return Array.isArray(o.availableActions) ? o.availableActions : [];
38504
+ }
38505
+ function objRules(o) {
38506
+ return Array.isArray(o.rules) ? o.rules : [];
38507
+ }
38508
+ function objMaxRules(o) {
38509
+ const n = Number(o.maxRules);
38510
+ return Number.isFinite(n) && n > 0 ? n : 3;
38511
+ }
38512
+ var init_puzzleObject = __esm({
38513
+ "components/game/organisms/puzzles/event-handler/puzzleObject.ts"() {
38514
+ }
38515
+ });
38275
38516
  function ObjectRulePanel({
38276
38517
  object,
38277
38518
  onRulesChange,
@@ -38279,55 +38520,63 @@ function ObjectRulePanel({
38279
38520
  className
38280
38521
  }) {
38281
38522
  const { t } = useTranslate();
38282
- const maxRules = object.maxRules || 3;
38283
- const canAdd = object.rules.length < maxRules;
38523
+ const id = objId(object);
38524
+ const name = objName(object);
38525
+ const icon = objIcon(object);
38526
+ const states = objStates(object);
38527
+ const currentState = objCurrentState(object);
38528
+ const availableEvents = objAvailableEvents(object);
38529
+ const availableActions = objAvailableActions(object);
38530
+ const rules = objRules(object);
38531
+ const maxRules = objMaxRules(object);
38532
+ const canAdd = rules.length < maxRules;
38284
38533
  const handleRuleChange = useCallback((index, updatedRule) => {
38285
- const newRules = [...object.rules];
38534
+ const newRules = [...rules];
38286
38535
  newRules[index] = updatedRule;
38287
- onRulesChange(object.id, newRules);
38288
- }, [object.id, object.rules, onRulesChange]);
38536
+ onRulesChange(id, newRules);
38537
+ }, [id, rules, onRulesChange]);
38289
38538
  const handleRuleRemove = useCallback((index) => {
38290
- const newRules = object.rules.filter((_, i) => i !== index);
38291
- onRulesChange(object.id, newRules);
38292
- }, [object.id, object.rules, onRulesChange]);
38539
+ const newRules = rules.filter((_, i) => i !== index);
38540
+ onRulesChange(id, newRules);
38541
+ }, [id, rules, onRulesChange]);
38293
38542
  const handleAddRule = useCallback(() => {
38294
38543
  if (!canAdd || disabled) return;
38295
- const firstEvent = object.availableEvents[0]?.value || "";
38296
- const firstAction = object.availableActions[0]?.value || "";
38544
+ const firstEvent = availableEvents[0]?.value || "";
38545
+ const firstAction = availableActions[0]?.value || "";
38297
38546
  const newRule = {
38298
38547
  id: `rule-${nextRuleId++}`,
38299
38548
  whenEvent: firstEvent,
38300
38549
  thenAction: firstAction
38301
38550
  };
38302
- onRulesChange(object.id, [...object.rules, newRule]);
38303
- }, [canAdd, disabled, object, onRulesChange]);
38551
+ onRulesChange(id, [...rules, newRule]);
38552
+ }, [canAdd, disabled, id, rules, availableEvents, availableActions, onRulesChange]);
38304
38553
  const machine = {
38305
- name: object.name,
38306
- states: object.states,
38307
- currentState: object.currentState,
38308
- transitions: object.rules.map((r) => ({
38309
- from: object.currentState,
38310
- to: object.states.find((s) => s !== object.currentState) || object.currentState,
38554
+ name,
38555
+ states,
38556
+ currentState,
38557
+ transitions: rules.map((r) => ({
38558
+ from: currentState,
38559
+ to: states.find((s) => s !== currentState) || currentState,
38311
38560
  event: r.whenEvent
38312
38561
  }))
38313
38562
  };
38314
38563
  return /* @__PURE__ */ jsxs(VStack, { className: cn("p-4 rounded-lg bg-card border border-border", className), gap: "sm", children: [
38315
38564
  /* @__PURE__ */ jsxs(HStack, { className: "items-center", gap: "sm", children: [
38316
- /* @__PURE__ */ jsx(Typography, { variant: "h5", children: object.icon }),
38565
+ /* @__PURE__ */ jsx(Typography, { variant: "h5", children: icon }),
38317
38566
  /* @__PURE__ */ jsxs(VStack, { gap: "none", children: [
38318
- /* @__PURE__ */ jsx(Typography, { variant: "body1", className: "text-foreground font-bold", children: object.name }),
38319
- /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-muted-foreground", children: t("eventHandler.state") + ": " + object.currentState })
38567
+ /* @__PURE__ */ jsx(Typography, { variant: "body1", className: "text-foreground font-bold", children: name }),
38568
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-muted-foreground", children: t("eventHandler.state") + ": " + currentState })
38320
38569
  ] })
38321
38570
  ] }),
38322
38571
  /* @__PURE__ */ jsx(TraitStateViewer, { trait: machine, variant: "compact", size: "sm" }),
38323
38572
  /* @__PURE__ */ jsxs(VStack, { gap: "xs", children: [
38324
- /* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground font-medium", children: t("eventHandler.rules", { count: object.rules.length, max: maxRules }) + ":" }),
38325
- object.rules.map((rule, i) => /* @__PURE__ */ jsx(
38573
+ /* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground font-medium", children: t("eventHandler.rules", { count: rules.length, max: maxRules }) + ":" }),
38574
+ rules.map((rule, i) => /* @__PURE__ */ jsx(
38326
38575
  RuleEditor,
38327
38576
  {
38328
38577
  rule,
38329
- availableEvents: object.availableEvents,
38330
- availableActions: object.availableActions,
38578
+ availableEvents,
38579
+ availableActions,
38331
38580
  onChange: (r) => handleRuleChange(i, r),
38332
38581
  onRemove: () => handleRuleRemove(i),
38333
38582
  disabled
@@ -38345,6 +38594,7 @@ var init_ObjectRulePanel = __esm({
38345
38594
  init_cn();
38346
38595
  init_TraitStateViewer();
38347
38596
  init_RuleEditor();
38597
+ init_puzzleObject();
38348
38598
  nextRuleId = 1;
38349
38599
  ObjectRulePanel.displayName = "ObjectRulePanel";
38350
38600
  }
@@ -38411,11 +38661,11 @@ function EventHandlerBoard({
38411
38661
  }) {
38412
38662
  const { emit } = useEventBus();
38413
38663
  const { t } = useTranslate();
38414
- const resolved = Array.isArray(entity) ? entity[0] : entity;
38415
- const entityObjects = resolved?.objects ?? [];
38416
- const [objects, setObjects] = useState(entityObjects);
38664
+ const resolved = boardEntity(entity);
38665
+ const entityObjects = rows(resolved?.objects);
38666
+ const [objects, setObjects] = useState(() => [...entityObjects]);
38417
38667
  const [selectedObjectId, setSelectedObjectId] = useState(
38418
- entityObjects[0]?.id || null
38668
+ entityObjects[0] ? objId(entityObjects[0]) : null
38419
38669
  );
38420
38670
  const [headerError, setHeaderError] = useState(false);
38421
38671
  const [playState, setPlayState] = useState("editing");
@@ -38426,10 +38676,10 @@ function EventHandlerBoard({
38426
38676
  useEffect(() => () => {
38427
38677
  if (timerRef.current) clearTimeout(timerRef.current);
38428
38678
  }, []);
38429
- const selectedObject = objects.find((o) => o.id === selectedObjectId) || null;
38679
+ const selectedObject = objects.find((o) => objId(o) === selectedObjectId) || null;
38430
38680
  const handleRulesChange = useCallback((objectId, rules) => {
38431
38681
  setObjects((prev) => prev.map(
38432
- (o) => o.id === objectId ? { ...o, rules } : o
38682
+ (o) => objId(o) === objectId ? { ...o, rules } : o
38433
38683
  ));
38434
38684
  }, []);
38435
38685
  const addLogEntry = useCallback((icon, message, status = "done") => {
@@ -38443,11 +38693,12 @@ function EventHandlerBoard({
38443
38693
  setEventLog([]);
38444
38694
  const allRules = [];
38445
38695
  objects.forEach((obj) => {
38446
- obj.rules.forEach((rule) => {
38696
+ objRules(obj).forEach((rule) => {
38447
38697
  allRules.push({ object: obj, rule });
38448
38698
  });
38449
38699
  });
38450
- const triggers = resolved?.triggerEvents || [];
38700
+ const triggers = Array.isArray(resolved?.triggerEvents) ? resolved.triggerEvents : [];
38701
+ const goalEvent = str(resolved?.goalEvent);
38451
38702
  const eventQueue = [...triggers];
38452
38703
  const firedEvents = /* @__PURE__ */ new Set();
38453
38704
  let stepIdx = 0;
@@ -38476,14 +38727,14 @@ function EventHandlerBoard({
38476
38727
  addLogEntry("\u26A1", t("eventHandler.noListeners", { event: currentEvent }), "done");
38477
38728
  } else {
38478
38729
  matching.forEach(({ object, rule }) => {
38479
- addLogEntry(object.icon, t("eventHandler.heardEvent", { object: object.name, event: currentEvent, action: rule.thenAction }), "done");
38730
+ addLogEntry(objIcon(object), t("eventHandler.heardEvent", { object: objName(object), event: currentEvent, action: rule.thenAction }), "done");
38480
38731
  eventQueue.push(rule.thenAction);
38481
- if (rule.thenAction === resolved?.goalEvent) {
38732
+ if (rule.thenAction === goalEvent) {
38482
38733
  goalReached = true;
38483
38734
  }
38484
38735
  });
38485
38736
  }
38486
- if (currentEvent === resolved?.goalEvent) {
38737
+ if (currentEvent === goalEvent) {
38487
38738
  goalReached = true;
38488
38739
  }
38489
38740
  stepIdx++;
@@ -38501,65 +38752,75 @@ function EventHandlerBoard({
38501
38752
  }, []);
38502
38753
  const handleReset = useCallback(() => {
38503
38754
  if (timerRef.current) clearTimeout(timerRef.current);
38504
- setObjects(resolved?.objects ?? []);
38755
+ const resetObjects = rows(resolved?.objects);
38756
+ setObjects([...resetObjects]);
38505
38757
  setPlayState("editing");
38506
38758
  setEventLog([]);
38507
- setSelectedObjectId((resolved?.objects ?? [])[0]?.id || null);
38759
+ setSelectedObjectId(resetObjects[0] ? objId(resetObjects[0]) : null);
38508
38760
  setAttempts(0);
38509
38761
  }, [resolved?.objects]);
38510
38762
  if (!resolved) return null;
38511
38763
  const objectViewers = objects.map((obj) => {
38764
+ const states = objStates(obj);
38765
+ const currentState = objCurrentState(obj);
38512
38766
  const machine = {
38513
- name: obj.name,
38514
- states: obj.states,
38515
- currentState: obj.currentState,
38516
- transitions: obj.rules.map((r) => ({
38517
- from: obj.currentState,
38518
- to: obj.states.find((s) => s !== obj.currentState) || obj.currentState,
38767
+ name: objName(obj),
38768
+ states,
38769
+ currentState,
38770
+ transitions: objRules(obj).map((r) => ({
38771
+ from: currentState,
38772
+ to: states.find((s) => s !== currentState) || currentState,
38519
38773
  event: r.whenEvent
38520
38774
  }))
38521
38775
  };
38522
38776
  return { obj, machine };
38523
38777
  });
38524
- const showHint = attempts >= 3 && resolved.hint;
38778
+ const hint = str(resolved.hint);
38779
+ const showHint = attempts >= 3 && hint;
38780
+ const theme = resolved.theme ?? void 0;
38781
+ const themeBackground = theme?.background;
38782
+ const headerImage = str(resolved.headerImage);
38525
38783
  const encourageKey = ENCOURAGEMENT_KEYS[Math.min(attempts - 1, ENCOURAGEMENT_KEYS.length - 1)] ?? ENCOURAGEMENT_KEYS[0];
38526
38784
  return /* @__PURE__ */ jsxs(
38527
38785
  VStack,
38528
38786
  {
38529
38787
  className: cn("p-4 gap-6", className),
38530
38788
  style: {
38531
- backgroundImage: resolved.theme?.background ? `url(${resolved.theme.background})` : void 0,
38789
+ backgroundImage: themeBackground ? `url(${themeBackground})` : void 0,
38532
38790
  backgroundSize: "cover",
38533
38791
  backgroundPosition: "center"
38534
38792
  },
38535
38793
  children: [
38536
- resolved.headerImage && !headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 overflow-hidden rounded-container", children: /* @__PURE__ */ jsx("img", { src: resolved.headerImage, alt: "", onError: () => setHeaderError(true), className: "w-full h-full object-cover" }) }) : resolved.headerImage && headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 rounded-container bg-gradient-to-br from-muted to-accent opacity-60" }) : null,
38794
+ 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,
38537
38795
  /* @__PURE__ */ jsxs(VStack, { gap: "xs", children: [
38538
- /* @__PURE__ */ jsx(Typography, { variant: "h4", className: "text-foreground", children: resolved.title }),
38539
- /* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground", children: resolved.description }),
38796
+ /* @__PURE__ */ jsx(Typography, { variant: "h4", className: "text-foreground", children: str(resolved.title) }),
38797
+ /* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground", children: str(resolved.description) }),
38540
38798
  /* @__PURE__ */ jsxs(HStack, { className: "items-center p-2 rounded bg-primary/10 border border-primary/30", gap: "xs", children: [
38541
38799
  /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-primary font-bold", children: t("game.goal") + ":" }),
38542
- /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-foreground", children: resolved.goalCondition })
38800
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-foreground", children: str(resolved.goalCondition) })
38543
38801
  ] })
38544
38802
  ] }),
38545
38803
  /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
38546
38804
  /* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground font-medium", children: t("eventHandler.clickObject") + ":" }),
38547
- /* @__PURE__ */ jsx(HStack, { className: "flex-wrap", gap: "sm", children: objectViewers.map(({ obj, machine }) => /* @__PURE__ */ jsx(
38548
- Box,
38549
- {
38550
- className: cn(
38551
- "p-3 rounded-container border-2 cursor-pointer transition-all hover:scale-105",
38552
- selectedObjectId === obj.id ? "border-primary bg-primary/10" : "border-border bg-card hover:border-muted-foreground"
38553
- ),
38554
- onClick: () => setSelectedObjectId(obj.id),
38555
- children: /* @__PURE__ */ jsxs(VStack, { gap: "xs", className: "items-center min-w-[120px]", children: [
38556
- /* @__PURE__ */ jsx(Typography, { variant: "h5", children: obj.icon }),
38557
- /* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-foreground font-medium", children: obj.name }),
38558
- /* @__PURE__ */ jsx(TraitStateViewer, { trait: machine, variant: "compact", size: "sm" })
38559
- ] })
38560
- },
38561
- obj.id
38562
- )) })
38805
+ /* @__PURE__ */ jsx(HStack, { className: "flex-wrap", gap: "sm", children: objectViewers.map(({ obj, machine }) => {
38806
+ const oid = objId(obj);
38807
+ return /* @__PURE__ */ jsx(
38808
+ Box,
38809
+ {
38810
+ className: cn(
38811
+ "p-3 rounded-container border-2 cursor-pointer transition-all hover:scale-105",
38812
+ selectedObjectId === oid ? "border-primary bg-primary/10" : "border-border bg-card hover:border-muted-foreground"
38813
+ ),
38814
+ onClick: () => setSelectedObjectId(oid),
38815
+ children: /* @__PURE__ */ jsxs(VStack, { gap: "xs", className: "items-center min-w-[120px]", children: [
38816
+ /* @__PURE__ */ jsx(Typography, { variant: "h5", children: objIcon(obj) }),
38817
+ /* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-foreground font-medium", children: objName(obj) }),
38818
+ /* @__PURE__ */ jsx(TraitStateViewer, { trait: machine, variant: "compact", size: "sm" })
38819
+ ] })
38820
+ },
38821
+ oid
38822
+ );
38823
+ }) })
38563
38824
  ] }),
38564
38825
  selectedObject && /* @__PURE__ */ jsx(
38565
38826
  ObjectRulePanel,
@@ -38570,12 +38831,12 @@ function EventHandlerBoard({
38570
38831
  }
38571
38832
  ),
38572
38833
  eventLog.length > 0 && /* @__PURE__ */ jsx(EventLog, { entries: eventLog }),
38573
- 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") }) }),
38834
+ 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") }) }),
38574
38835
  playState === "fail" && /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
38575
38836
  /* @__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) }) }),
38576
38837
  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: [
38577
38838
  /* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-accent font-bold shrink-0", children: "\u{1F4A1} " + t("game.hint") + ":" }),
38578
- /* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-foreground", children: resolved.hint })
38839
+ /* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-foreground", children: hint })
38579
38840
  ] }) })
38580
38841
  ] }),
38581
38842
  /* @__PURE__ */ jsxs(HStack, { gap: "sm", children: [
@@ -38603,6 +38864,8 @@ var init_EventHandlerBoard = __esm({
38603
38864
  init_TraitStateViewer();
38604
38865
  init_ObjectRulePanel();
38605
38866
  init_EventLog();
38867
+ init_puzzleObject();
38868
+ init_boardEntity();
38606
38869
  ENCOURAGEMENT_KEYS = [
38607
38870
  "puzzle.tryAgain1",
38608
38871
  "puzzle.tryAgain2",
@@ -38691,7 +38954,10 @@ var init_FeatureGridOrganism = __esm({
38691
38954
  );
38692
38955
  useCallback(
38693
38956
  (feature) => {
38694
- eventBus.emit("UI:FEATURE_CLICK", { id: feature.id, href: feature.href ?? "" });
38957
+ eventBus.emit("UI:FEATURE_CLICK", {
38958
+ id: String(feature.id ?? ""),
38959
+ href: String(feature.href ?? "")
38960
+ });
38695
38961
  },
38696
38962
  [eventBus]
38697
38963
  );
@@ -38701,14 +38967,17 @@ var init_FeatureGridOrganism = __esm({
38701
38967
  if (error) {
38702
38968
  return /* @__PURE__ */ jsx(ErrorState, { message: error.message, className });
38703
38969
  }
38704
- const featureCards = items.map((feature) => ({
38705
- icon: feature.icon,
38706
- title: feature.title,
38707
- description: feature.description,
38708
- href: feature.href,
38709
- linkLabel: feature.linkLabel,
38710
- variant: feature.href ? "interactive" : "bordered"
38711
- }));
38970
+ const featureCards = items.map((feature) => {
38971
+ const href = feature.href != null ? String(feature.href) : void 0;
38972
+ return {
38973
+ icon: feature.icon != null ? String(feature.icon) : void 0,
38974
+ title: String(feature.title ?? ""),
38975
+ description: String(feature.description ?? ""),
38976
+ href,
38977
+ linkLabel: feature.linkLabel != null ? String(feature.linkLabel) : void 0,
38978
+ variant: href ? "interactive" : "bordered"
38979
+ };
38980
+ });
38712
38981
  return /* @__PURE__ */ jsxs(VStack, { gap: "lg", className: cn("w-full", className), children: [
38713
38982
  (heading || subtitle) && /* @__PURE__ */ jsxs(VStack, { gap: "sm", align: "center", className: "w-full", children: [
38714
38983
  heading && /* @__PURE__ */ jsx(Typography, { variant: "h2", align: "center", children: heading }),
@@ -38907,12 +39176,12 @@ var init_Form = __esm({
38907
39176
  const isSchemaEntity = isOrbitalEntitySchema(entity);
38908
39177
  const resolvedEntity = isSchemaEntity ? entity : void 0;
38909
39178
  const entityName = typeof entity === "string" ? entity : resolvedEntity?.name;
38910
- const normalizedInitialData = React79__default.useMemo(() => {
39179
+ const normalizedInitialData = React80__default.useMemo(() => {
38911
39180
  const entityRowAsInitial = isPlainEntityRow(entity) ? entity : void 0;
38912
39181
  const callerInitial = initialData !== null && typeof initialData === "object" && !Array.isArray(initialData) ? initialData : {};
38913
39182
  return entityRowAsInitial !== void 0 ? { ...entityRowAsInitial, ...callerInitial } : callerInitial;
38914
39183
  }, [entity, initialData]);
38915
- const entityDerivedFields = React79__default.useMemo(() => {
39184
+ const entityDerivedFields = React80__default.useMemo(() => {
38916
39185
  if (fields && fields.length > 0) return void 0;
38917
39186
  if (!resolvedEntity) return void 0;
38918
39187
  return resolvedEntity.fields.map(
@@ -38932,16 +39201,16 @@ var init_Form = __esm({
38932
39201
  const conditionalFields = typeof conditionalFieldsRaw === "boolean" ? {} : conditionalFieldsRaw;
38933
39202
  const hiddenCalculations = typeof hiddenCalculationsRaw === "boolean" ? [] : hiddenCalculationsRaw;
38934
39203
  const violationTriggers = typeof violationTriggersRaw === "boolean" ? [] : violationTriggersRaw;
38935
- const [formData, setFormData] = React79__default.useState(
39204
+ const [formData, setFormData] = React80__default.useState(
38936
39205
  normalizedInitialData
38937
39206
  );
38938
- const [collapsedSections, setCollapsedSections] = React79__default.useState(
39207
+ const [collapsedSections, setCollapsedSections] = React80__default.useState(
38939
39208
  /* @__PURE__ */ new Set()
38940
39209
  );
38941
- const [submitError, setSubmitError] = React79__default.useState(null);
38942
- const formRef = React79__default.useRef(null);
39210
+ const [submitError, setSubmitError] = React80__default.useState(null);
39211
+ const formRef = React80__default.useRef(null);
38943
39212
  const formMode = props.mode;
38944
- const mountedRef = React79__default.useRef(false);
39213
+ const mountedRef = React80__default.useRef(false);
38945
39214
  if (!mountedRef.current) {
38946
39215
  mountedRef.current = true;
38947
39216
  debug("forms", "mount", {
@@ -38954,7 +39223,7 @@ var init_Form = __esm({
38954
39223
  });
38955
39224
  }
38956
39225
  const shouldShowCancel = showCancel ?? (fields && fields.length > 0);
38957
- const evalContext = React79__default.useMemo(
39226
+ const evalContext = React80__default.useMemo(
38958
39227
  () => ({
38959
39228
  formValues: formData,
38960
39229
  globalVariables: externalContext?.globalVariables ?? {},
@@ -38963,7 +39232,7 @@ var init_Form = __esm({
38963
39232
  }),
38964
39233
  [formData, externalContext]
38965
39234
  );
38966
- React79__default.useEffect(() => {
39235
+ React80__default.useEffect(() => {
38967
39236
  debug("forms", "initialData-sync", {
38968
39237
  mode: formMode,
38969
39238
  normalizedInitialData,
@@ -38974,7 +39243,7 @@ var init_Form = __esm({
38974
39243
  setFormData(normalizedInitialData);
38975
39244
  }
38976
39245
  }, [normalizedInitialData]);
38977
- const processCalculations = React79__default.useCallback(
39246
+ const processCalculations = React80__default.useCallback(
38978
39247
  (changedFieldId, newFormData) => {
38979
39248
  if (!hiddenCalculations.length) return;
38980
39249
  const context = {
@@ -38999,7 +39268,7 @@ var init_Form = __esm({
38999
39268
  },
39000
39269
  [hiddenCalculations, externalContext, eventBus]
39001
39270
  );
39002
- const checkViolations = React79__default.useCallback(
39271
+ const checkViolations = React80__default.useCallback(
39003
39272
  (changedFieldId, newFormData) => {
39004
39273
  if (!violationTriggers.length) return;
39005
39274
  const context = {
@@ -39037,7 +39306,7 @@ var init_Form = __esm({
39037
39306
  processCalculations(name, newFormData);
39038
39307
  checkViolations(name, newFormData);
39039
39308
  };
39040
- const isFieldVisible = React79__default.useCallback(
39309
+ const isFieldVisible = React80__default.useCallback(
39041
39310
  (fieldName) => {
39042
39311
  const condition = conditionalFields[fieldName];
39043
39312
  if (!condition) return true;
@@ -39045,7 +39314,7 @@ var init_Form = __esm({
39045
39314
  },
39046
39315
  [conditionalFields, evalContext]
39047
39316
  );
39048
- const isSectionVisible = React79__default.useCallback(
39317
+ const isSectionVisible = React80__default.useCallback(
39049
39318
  (section) => {
39050
39319
  if (!section.condition) return true;
39051
39320
  return Boolean(evaluateFormExpression(section.condition, evalContext));
@@ -39121,7 +39390,7 @@ var init_Form = __esm({
39121
39390
  eventBus.emit(`UI:${onCancel}`);
39122
39391
  }
39123
39392
  };
39124
- const renderField = React79__default.useCallback(
39393
+ const renderField = React80__default.useCallback(
39125
39394
  (field) => {
39126
39395
  const fieldName = field.name || field.field;
39127
39396
  if (!fieldName) return null;
@@ -39142,7 +39411,7 @@ var init_Form = __esm({
39142
39411
  [formData, isFieldVisible, relationsData, relationsLoading, isLoading]
39143
39412
  );
39144
39413
  const effectiveFields = entityDerivedFields ?? fields;
39145
- const normalizedFields = React79__default.useMemo(() => {
39414
+ const normalizedFields = React80__default.useMemo(() => {
39146
39415
  if (!effectiveFields || effectiveFields.length === 0) return [];
39147
39416
  return effectiveFields.map((field) => {
39148
39417
  if (typeof field === "string") {
@@ -39165,7 +39434,7 @@ var init_Form = __esm({
39165
39434
  return field;
39166
39435
  });
39167
39436
  }, [effectiveFields, resolvedEntity]);
39168
- const schemaFields = React79__default.useMemo(() => {
39437
+ const schemaFields = React80__default.useMemo(() => {
39169
39438
  if (normalizedFields.length === 0) return null;
39170
39439
  if (isDebugEnabled()) {
39171
39440
  debugGroup(`Form: ${entityName || "unknown"}`);
@@ -39175,7 +39444,7 @@ var init_Form = __esm({
39175
39444
  }
39176
39445
  return normalizedFields.map(renderField).filter(Boolean);
39177
39446
  }, [normalizedFields, renderField, entityName, conditionalFields]);
39178
- const sectionElements = React79__default.useMemo(() => {
39447
+ const sectionElements = React80__default.useMemo(() => {
39179
39448
  if (!sections || sections.length === 0) return null;
39180
39449
  return sections.map((section) => {
39181
39450
  if (!isSectionVisible(section)) {
@@ -40033,22 +40302,24 @@ var init_HeroOrganism = __esm({
40033
40302
  () => Array.isArray(entity) ? entity[0] : entity && typeof entity === "object" ? entity : void 0,
40034
40303
  [entity]
40035
40304
  );
40305
+ const primaryAction = resolved?.primaryAction;
40306
+ const secondaryAction = resolved?.secondaryAction;
40036
40307
  const handlePrimaryClick = useCallback(() => {
40037
- if (resolved?.primaryAction) {
40308
+ if (primaryAction) {
40038
40309
  eventBus.emit("UI:CTA_PRIMARY", {
40039
- label: resolved.primaryAction.label,
40040
- href: resolved.primaryAction.href
40310
+ label: String(primaryAction.label ?? ""),
40311
+ href: String(primaryAction.href ?? "")
40041
40312
  });
40042
40313
  }
40043
- }, [eventBus, resolved]);
40314
+ }, [eventBus, primaryAction]);
40044
40315
  const handleSecondaryClick = useCallback(() => {
40045
- if (resolved?.secondaryAction) {
40316
+ if (secondaryAction) {
40046
40317
  eventBus.emit("UI:CTA_SECONDARY", {
40047
- label: resolved.secondaryAction.label,
40048
- href: resolved.secondaryAction.href
40318
+ label: String(secondaryAction.label ?? ""),
40319
+ href: String(secondaryAction.href ?? "")
40049
40320
  });
40050
40321
  }
40051
- }, [eventBus, resolved]);
40322
+ }, [eventBus, secondaryAction]);
40052
40323
  if (isLoading) {
40053
40324
  return /* @__PURE__ */ jsx(LoadingState, { message: t("common.loading"), className });
40054
40325
  }
@@ -40058,17 +40329,19 @@ var init_HeroOrganism = __esm({
40058
40329
  if (!resolved) {
40059
40330
  return null;
40060
40331
  }
40332
+ const imageRaw = resolved.image;
40333
+ const image = imageRaw ? { src: String(imageRaw.src ?? ""), alt: String(imageRaw.alt ?? "") } : void 0;
40061
40334
  return /* @__PURE__ */ jsxs(
40062
40335
  HeroSection,
40063
40336
  {
40064
- tag: resolved.tag,
40065
- title: resolved.title,
40066
- titleAccent: resolved.titleAccent,
40067
- subtitle: resolved.subtitle,
40068
- primaryAction: resolved.primaryAction ? { label: resolved.primaryAction.label, href: resolved.primaryAction.href } : void 0,
40069
- secondaryAction: resolved.secondaryAction ? { label: resolved.secondaryAction.label, href: resolved.secondaryAction.href } : void 0,
40070
- installCommand: resolved.installCommand,
40071
- image: resolved.image,
40337
+ tag: resolved.tag != null ? String(resolved.tag) : void 0,
40338
+ title: String(resolved.title ?? ""),
40339
+ titleAccent: resolved.titleAccent != null ? String(resolved.titleAccent) : void 0,
40340
+ subtitle: String(resolved.subtitle ?? ""),
40341
+ primaryAction: primaryAction ? { label: String(primaryAction.label ?? ""), href: String(primaryAction.href ?? "") } : void 0,
40342
+ secondaryAction: secondaryAction ? { label: String(secondaryAction.label ?? ""), href: String(secondaryAction.href ?? "") } : void 0,
40343
+ installCommand: resolved.installCommand != null ? String(resolved.installCommand) : void 0,
40344
+ image,
40072
40345
  imagePosition: resolved.imagePosition,
40073
40346
  background: resolved.background,
40074
40347
  className: cn(className),
@@ -40077,8 +40350,8 @@ var init_HeroOrganism = __esm({
40077
40350
  /* @__PURE__ */ jsx(
40078
40351
  _HeroClickInterceptor,
40079
40352
  {
40080
- hasPrimary: !!resolved.primaryAction,
40081
- hasSecondary: !!resolved.secondaryAction,
40353
+ hasPrimary: !!primaryAction,
40354
+ hasSecondary: !!secondaryAction,
40082
40355
  onPrimaryClick: handlePrimaryClick,
40083
40356
  onSecondaryClick: handleSecondaryClick
40084
40357
  }
@@ -40307,7 +40580,7 @@ function formatValue3(value, fieldName) {
40307
40580
  return String(value);
40308
40581
  }
40309
40582
  function formatFieldLabel2(fieldName) {
40310
- return fieldName.replace(/([A-Z])/g, " $1").replace(/^./, (str) => str.toUpperCase()).replace(/Id$/, "").trim();
40583
+ return fieldName.replace(/([A-Z])/g, " $1").replace(/^./, (str2) => str2.toUpperCase()).replace(/Id$/, "").trim();
40311
40584
  }
40312
40585
  var STATUS_STYLES2, StatusBadge, ProgressIndicator, List3;
40313
40586
  var init_List = __esm({
@@ -40453,7 +40726,7 @@ var init_List = __esm({
40453
40726
  if (entity && typeof entity === "object" && "id" in entity) return [entity];
40454
40727
  return [];
40455
40728
  }, [entity]);
40456
- const getItemActions = React79__default.useCallback(
40729
+ const getItemActions = React80__default.useCallback(
40457
40730
  (item) => {
40458
40731
  if (!itemActions) return [];
40459
40732
  if (typeof itemActions === "function") {
@@ -40929,7 +41202,7 @@ var init_MediaGallery = __esm({
40929
41202
  [selectable, selectedItems, selectionEvent, eventBus]
40930
41203
  );
40931
41204
  const entityData = Array.isArray(entity) ? entity : [];
40932
- const items = React79__default.useMemo(() => {
41205
+ const items = React80__default.useMemo(() => {
40933
41206
  if (propItems) return propItems;
40934
41207
  if (entityData.length === 0) return [];
40935
41208
  return entityData.map((record, idx) => ({
@@ -41099,9 +41372,9 @@ function MiniMap({
41099
41372
  viewportRect,
41100
41373
  className
41101
41374
  }) {
41102
- const canvasRef = React79.useRef(null);
41103
- const frameRef = React79.useRef(0);
41104
- React79.useEffect(() => {
41375
+ const canvasRef = React80.useRef(null);
41376
+ const frameRef = React80.useRef(0);
41377
+ React80.useEffect(() => {
41105
41378
  const canvas = canvasRef.current;
41106
41379
  if (!canvas) return;
41107
41380
  const ctx = canvas.getContext("2d");
@@ -41183,7 +41456,7 @@ var init_MiniMap = __esm({
41183
41456
  }
41184
41457
  });
41185
41458
  function extractTitle2(children) {
41186
- if (!React79__default.isValidElement(children)) return void 0;
41459
+ if (!React80__default.isValidElement(children)) return void 0;
41187
41460
  const props = children.props;
41188
41461
  if (typeof props.title === "string") {
41189
41462
  return props.title;
@@ -41247,20 +41520,22 @@ function NegotiatorBoard({
41247
41520
  }) {
41248
41521
  const { emit } = useEventBus();
41249
41522
  const { t } = useTranslate();
41250
- const resolved = Array.isArray(entity) ? entity[0] : entity;
41523
+ const resolved = boardEntity(entity);
41251
41524
  const [history, setHistory] = useState([]);
41252
41525
  const [headerError, setHeaderError] = useState(false);
41253
41526
  const [showHint, setShowHint] = useState(false);
41527
+ const totalRounds = num(resolved?.totalRounds);
41528
+ const targetScore = num(resolved?.targetScore);
41254
41529
  const currentRound = history.length;
41255
- const isComplete = currentRound >= (resolved?.totalRounds ?? 0);
41530
+ const isComplete = currentRound >= totalRounds;
41256
41531
  const playerTotal = history.reduce((s, r) => s + r.playerPayoff, 0);
41257
41532
  const opponentTotal = history.reduce((s, r) => s + r.opponentPayoff, 0);
41258
- const won = isComplete && playerTotal >= (resolved?.targetScore ?? 0);
41259
- const actions = resolved?.actions ?? [];
41260
- const payoffMatrix = resolved?.payoffMatrix ?? [];
41533
+ const won = isComplete && playerTotal >= targetScore;
41534
+ const actions = Array.isArray(resolved?.actions) ? resolved.actions : [];
41535
+ const payoffMatrix = Array.isArray(resolved?.payoffMatrix) ? resolved.payoffMatrix : [];
41261
41536
  const handleAction = useCallback((actionId) => {
41262
41537
  if (isComplete) return;
41263
- const opponentAction = getOpponentAction(resolved?.opponentStrategy ?? "random", actions, history);
41538
+ const opponentAction = getOpponentAction(str(resolved?.opponentStrategy) || "random", actions, history);
41264
41539
  const payoff = payoffMatrix.find(
41265
41540
  (p2) => p2.playerAction === actionId && p2.opponentAction === opponentAction
41266
41541
  );
@@ -41273,42 +41548,46 @@ function NegotiatorBoard({
41273
41548
  };
41274
41549
  const newHistory = [...history, result];
41275
41550
  setHistory(newHistory);
41276
- if (newHistory.length >= (resolved?.totalRounds ?? 0)) {
41551
+ if (newHistory.length >= totalRounds) {
41277
41552
  const total = newHistory.reduce((s, r) => s + r.playerPayoff, 0);
41278
- if (total >= (resolved?.targetScore ?? 0)) {
41553
+ if (total >= targetScore) {
41279
41554
  emit(`UI:${completeEvent}`, { success: true, score: total });
41280
41555
  }
41281
- if (newHistory.length >= 3 && resolved?.hint) {
41556
+ if (newHistory.length >= 3 && str(resolved?.hint)) {
41282
41557
  setShowHint(true);
41283
41558
  }
41284
41559
  }
41285
- }, [isComplete, resolved, actions, payoffMatrix, history, currentRound, completeEvent, emit]);
41560
+ }, [isComplete, resolved, totalRounds, targetScore, actions, payoffMatrix, history, currentRound, completeEvent, emit]);
41286
41561
  const handleReset = () => {
41287
41562
  setHistory([]);
41288
41563
  setShowHint(false);
41289
41564
  };
41290
41565
  const getActionLabel = (id) => actions.find((a) => a.id === id)?.label ?? id;
41291
41566
  if (!resolved) return null;
41567
+ const theme = resolved.theme ?? void 0;
41568
+ const themeBackground = theme?.background;
41569
+ const headerImage = str(resolved.headerImage);
41570
+ const hint = str(resolved.hint);
41292
41571
  return /* @__PURE__ */ jsx(
41293
41572
  Box,
41294
41573
  {
41295
41574
  className,
41296
41575
  style: {
41297
- backgroundImage: resolved.theme?.background ? `url(${resolved.theme.background})` : void 0,
41576
+ backgroundImage: themeBackground ? `url(${themeBackground})` : void 0,
41298
41577
  backgroundSize: "cover",
41299
41578
  backgroundPosition: "center"
41300
41579
  },
41301
41580
  children: /* @__PURE__ */ jsxs(VStack, { gap: "lg", className: "p-4", children: [
41302
- resolved.headerImage && !headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 overflow-hidden rounded-container", children: /* @__PURE__ */ jsx("img", { src: resolved.headerImage, alt: "", onError: () => setHeaderError(true), className: "w-full h-full object-cover" }) }) : resolved.headerImage && headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 rounded-container bg-gradient-to-br from-muted to-accent opacity-60" }) : null,
41581
+ 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,
41303
41582
  /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
41304
- /* @__PURE__ */ jsx(Typography, { variant: "h4", weight: "bold", children: resolved.title }),
41305
- /* @__PURE__ */ jsx(Typography, { variant: "body", children: resolved.description }),
41583
+ /* @__PURE__ */ jsx(Typography, { variant: "h4", weight: "bold", children: str(resolved.title) }),
41584
+ /* @__PURE__ */ jsx(Typography, { variant: "body", children: str(resolved.description) }),
41306
41585
  /* @__PURE__ */ jsxs(HStack, { gap: "md", children: [
41307
- /* @__PURE__ */ jsx(Badge, { size: "sm", children: t("negotiator.round", { current: String(currentRound), total: String(resolved.totalRounds) }) }),
41586
+ /* @__PURE__ */ jsx(Badge, { size: "sm", children: t("negotiator.round", { current: String(currentRound), total: String(totalRounds) }) }),
41308
41587
  /* @__PURE__ */ jsxs(Badge, { size: "sm", children: [
41309
41588
  t("negotiator.target"),
41310
41589
  ": ",
41311
- resolved.targetScore
41590
+ targetScore
41312
41591
  ] })
41313
41592
  ] })
41314
41593
  ] }) }),
@@ -41357,16 +41636,16 @@ function NegotiatorBoard({
41357
41636
  ] }) }),
41358
41637
  isComplete && /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", align: "center", children: [
41359
41638
  /* @__PURE__ */ jsx(Icon, { icon: CheckCircle, size: "lg", className: won ? "text-success" : "text-error" }),
41360
- /* @__PURE__ */ jsx(Typography, { variant: "body", weight: "bold", children: won ? resolved.successMessage ?? t("negotiator.success") : resolved.failMessage ?? t("negotiator.failed") }),
41639
+ /* @__PURE__ */ jsx(Typography, { variant: "body", weight: "bold", children: won ? str(resolved.successMessage) || t("negotiator.success") : str(resolved.failMessage) || t("negotiator.failed") }),
41361
41640
  /* @__PURE__ */ jsxs(Typography, { variant: "caption", className: "text-muted-foreground", children: [
41362
41641
  t("negotiator.finalScore"),
41363
41642
  ": ",
41364
41643
  playerTotal,
41365
41644
  "/",
41366
- resolved.targetScore
41645
+ targetScore
41367
41646
  ] })
41368
41647
  ] }) }),
41369
- showHint && resolved.hint && !won && /* @__PURE__ */ jsx(Card, { className: "p-4 border-l-4 border-l-warning", children: /* @__PURE__ */ jsx(Typography, { variant: "body", children: resolved.hint }) }),
41648
+ showHint && hint && !won && /* @__PURE__ */ jsx(Card, { className: "p-4 border-l-4 border-l-warning", children: /* @__PURE__ */ jsx(Typography, { variant: "body", children: hint }) }),
41370
41649
  isComplete && !won && /* @__PURE__ */ jsx(HStack, { justify: "center", children: /* @__PURE__ */ jsx(Button, { variant: "primary", onClick: handleReset, children: t("negotiator.playAgain") }) })
41371
41650
  ] })
41372
41651
  }
@@ -41376,6 +41655,7 @@ var init_NegotiatorBoard = __esm({
41376
41655
  "components/game/organisms/puzzles/negotiator/NegotiatorBoard.tsx"() {
41377
41656
  init_atoms2();
41378
41657
  init_useEventBus();
41658
+ init_boardEntity();
41379
41659
  NegotiatorBoard.displayName = "NegotiatorBoard";
41380
41660
  }
41381
41661
  });
@@ -41411,13 +41691,13 @@ var init_PricingOrganism = __esm({
41411
41691
  return /* @__PURE__ */ jsx(ErrorState, { message: error.message, className });
41412
41692
  }
41413
41693
  const plans = items.map((plan) => ({
41414
- name: plan.name,
41415
- price: plan.price,
41416
- description: plan.description,
41417
- features: plan.features,
41418
- action: { label: plan.actionLabel, href: plan.actionHref },
41419
- highlighted: plan.highlighted,
41420
- badge: plan.badge
41694
+ name: String(plan.name ?? ""),
41695
+ price: String(plan.price ?? ""),
41696
+ description: plan.description != null ? String(plan.description) : void 0,
41697
+ features: (plan.features ?? []).map((f3) => String(f3)),
41698
+ action: { label: String(plan.actionLabel ?? ""), href: String(plan.actionHref ?? "") },
41699
+ highlighted: Boolean(plan.highlighted),
41700
+ badge: plan.badge != null ? String(plan.badge) : void 0
41421
41701
  }));
41422
41702
  return /* @__PURE__ */ jsxs(VStack, { gap: "lg", className: cn("w-full", className), children: [
41423
41703
  (heading || subtitle) && /* @__PURE__ */ jsxs(VStack, { gap: "sm", align: "center", className: "w-full", children: [
@@ -41633,7 +41913,7 @@ var init_debugRegistry = __esm({
41633
41913
  }
41634
41914
  });
41635
41915
  function useDebugData() {
41636
- const [data, setData] = React79.useState(() => ({
41916
+ const [data, setData] = React80.useState(() => ({
41637
41917
  traits: [],
41638
41918
  ticks: [],
41639
41919
  guards: [],
@@ -41647,7 +41927,7 @@ function useDebugData() {
41647
41927
  },
41648
41928
  lastUpdate: Date.now()
41649
41929
  }));
41650
- React79.useEffect(() => {
41930
+ React80.useEffect(() => {
41651
41931
  const updateData = () => {
41652
41932
  setData({
41653
41933
  traits: getAllTraits(),
@@ -41756,12 +42036,12 @@ function layoutGraph(states, transitions, initialState, width, height) {
41756
42036
  return positions;
41757
42037
  }
41758
42038
  function WalkMinimap() {
41759
- const [walkStep, setWalkStep] = React79.useState(null);
41760
- const [traits2, setTraits] = React79.useState([]);
41761
- const [coveredEdges, setCoveredEdges] = React79.useState([]);
41762
- const [completedTraits, setCompletedTraits] = React79.useState(/* @__PURE__ */ new Set());
41763
- const prevTraitRef = React79.useRef(null);
41764
- React79.useEffect(() => {
42039
+ const [walkStep, setWalkStep] = React80.useState(null);
42040
+ const [traits2, setTraits] = React80.useState([]);
42041
+ const [coveredEdges, setCoveredEdges] = React80.useState([]);
42042
+ const [completedTraits, setCompletedTraits] = React80.useState(/* @__PURE__ */ new Set());
42043
+ const prevTraitRef = React80.useRef(null);
42044
+ React80.useEffect(() => {
41765
42045
  const interval = setInterval(() => {
41766
42046
  const w = window;
41767
42047
  const step = w.__orbitalWalkStep;
@@ -42197,15 +42477,15 @@ var init_EntitiesTab = __esm({
42197
42477
  });
42198
42478
  function EventFlowTab({ events: events2 }) {
42199
42479
  const { t } = useTranslate();
42200
- const [filter, setFilter] = React79.useState("all");
42201
- const containerRef = React79.useRef(null);
42202
- const [autoScroll, setAutoScroll] = React79.useState(true);
42203
- React79.useEffect(() => {
42480
+ const [filter, setFilter] = React80.useState("all");
42481
+ const containerRef = React80.useRef(null);
42482
+ const [autoScroll, setAutoScroll] = React80.useState(true);
42483
+ React80.useEffect(() => {
42204
42484
  if (autoScroll && containerRef.current) {
42205
42485
  containerRef.current.scrollTop = containerRef.current.scrollHeight;
42206
42486
  }
42207
42487
  }, [events2.length, autoScroll]);
42208
- const filteredEvents = React79.useMemo(() => {
42488
+ const filteredEvents = React80.useMemo(() => {
42209
42489
  if (filter === "all") return events2;
42210
42490
  return events2.filter((e) => e.type === filter);
42211
42491
  }, [events2, filter]);
@@ -42321,7 +42601,7 @@ var init_EventFlowTab = __esm({
42321
42601
  });
42322
42602
  function GuardsPanel({ guards }) {
42323
42603
  const { t } = useTranslate();
42324
- const [filter, setFilter] = React79.useState("all");
42604
+ const [filter, setFilter] = React80.useState("all");
42325
42605
  if (guards.length === 0) {
42326
42606
  return /* @__PURE__ */ jsx(
42327
42607
  EmptyState,
@@ -42334,7 +42614,7 @@ function GuardsPanel({ guards }) {
42334
42614
  }
42335
42615
  const passedCount = guards.filter((g) => g.result).length;
42336
42616
  const failedCount = guards.length - passedCount;
42337
- const filteredGuards = React79.useMemo(() => {
42617
+ const filteredGuards = React80.useMemo(() => {
42338
42618
  if (filter === "all") return guards;
42339
42619
  if (filter === "passed") return guards.filter((g) => g.result);
42340
42620
  return guards.filter((g) => !g.result);
@@ -42497,10 +42777,10 @@ function EffectBadge({ effect }) {
42497
42777
  }
42498
42778
  function TransitionTimeline({ transitions }) {
42499
42779
  const { t } = useTranslate();
42500
- const containerRef = React79.useRef(null);
42501
- const [autoScroll, setAutoScroll] = React79.useState(true);
42502
- const [expandedId, setExpandedId] = React79.useState(null);
42503
- React79.useEffect(() => {
42780
+ const containerRef = React80.useRef(null);
42781
+ const [autoScroll, setAutoScroll] = React80.useState(true);
42782
+ const [expandedId, setExpandedId] = React80.useState(null);
42783
+ React80.useEffect(() => {
42504
42784
  if (autoScroll && containerRef.current) {
42505
42785
  containerRef.current.scrollTop = containerRef.current.scrollHeight;
42506
42786
  }
@@ -42780,9 +43060,9 @@ function getAllEvents(traits2) {
42780
43060
  function EventDispatcherTab({ traits: traits2, schema }) {
42781
43061
  const eventBus = useEventBus();
42782
43062
  const { t } = useTranslate();
42783
- const [log8, setLog] = React79.useState([]);
42784
- const prevStatesRef = React79.useRef(/* @__PURE__ */ new Map());
42785
- React79.useEffect(() => {
43063
+ const [log8, setLog] = React80.useState([]);
43064
+ const prevStatesRef = React80.useRef(/* @__PURE__ */ new Map());
43065
+ React80.useEffect(() => {
42786
43066
  for (const trait of traits2) {
42787
43067
  const prev = prevStatesRef.current.get(trait.id);
42788
43068
  if (prev && prev !== trait.currentState) {
@@ -42951,10 +43231,10 @@ function VerifyModePanel({
42951
43231
  localCount
42952
43232
  }) {
42953
43233
  const { t } = useTranslate();
42954
- const [expanded, setExpanded] = React79.useState(true);
42955
- const scrollRef = React79.useRef(null);
42956
- const prevCountRef = React79.useRef(0);
42957
- React79.useEffect(() => {
43234
+ const [expanded, setExpanded] = React80.useState(true);
43235
+ const scrollRef = React80.useRef(null);
43236
+ const prevCountRef = React80.useRef(0);
43237
+ React80.useEffect(() => {
42958
43238
  if (expanded && transitions.length > prevCountRef.current && scrollRef.current) {
42959
43239
  scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
42960
43240
  }
@@ -43011,10 +43291,10 @@ function RuntimeDebugger({
43011
43291
  schema
43012
43292
  }) {
43013
43293
  const { t } = useTranslate();
43014
- const [isCollapsed, setIsCollapsed] = React79.useState(mode === "verify" ? true : defaultCollapsed);
43015
- const [isVisible, setIsVisible] = React79.useState(mode === "inline" || mode === "verify" || isDebugEnabled2());
43294
+ const [isCollapsed, setIsCollapsed] = React80.useState(mode === "verify" ? true : defaultCollapsed);
43295
+ const [isVisible, setIsVisible] = React80.useState(mode === "inline" || mode === "verify" || isDebugEnabled2());
43016
43296
  const debugData = useDebugData();
43017
- React79.useEffect(() => {
43297
+ React80.useEffect(() => {
43018
43298
  if (mode === "inline") return;
43019
43299
  return onDebugToggle((enabled) => {
43020
43300
  setIsVisible(enabled);
@@ -43023,7 +43303,7 @@ function RuntimeDebugger({
43023
43303
  }
43024
43304
  });
43025
43305
  }, [mode]);
43026
- React79.useEffect(() => {
43306
+ React80.useEffect(() => {
43027
43307
  if (mode === "inline") return;
43028
43308
  const handleKeyDown = (e) => {
43029
43309
  if (e.key === "`" && isVisible) {
@@ -43472,7 +43752,7 @@ function SequenceBar({
43472
43752
  onSlotRemove(index);
43473
43753
  }, [onSlotRemove, playing]);
43474
43754
  const paddedSlots = Array.from({ length: maxSlots }, (_, i) => slots[i]);
43475
- return /* @__PURE__ */ jsx(HStack, { className: cn("items-center", className), gap: "sm", children: paddedSlots.map((slot, i) => /* @__PURE__ */ jsxs(React79__default.Fragment, { children: [
43755
+ return /* @__PURE__ */ jsx(HStack, { className: cn("items-center", className), gap: "sm", children: paddedSlots.map((slot, i) => /* @__PURE__ */ jsxs(React80__default.Fragment, { children: [
43476
43756
  i > 0 && /* @__PURE__ */ jsx(
43477
43757
  Typography,
43478
43758
  {
@@ -43533,16 +43813,20 @@ function SequencerBoard({
43533
43813
  }) {
43534
43814
  const { emit } = useEventBus();
43535
43815
  const { t } = useTranslate();
43536
- const resolved = Array.isArray(entity) ? entity[0] : entity;
43816
+ const resolved = boardEntity(entity);
43817
+ const maxSlots = num(resolved?.maxSlots);
43818
+ const solutions = Array.isArray(resolved?.solutions) ? resolved.solutions : [];
43819
+ const availableActions = Array.isArray(resolved?.availableActions) ? resolved.availableActions : [];
43820
+ const allowDuplicates = resolved?.allowDuplicates !== false;
43537
43821
  const [headerError, setHeaderError] = useState(false);
43538
43822
  const [slots, setSlots] = useState(
43539
- () => Array.from({ length: resolved?.maxSlots ?? 0 }, () => void 0)
43823
+ () => Array.from({ length: maxSlots }, () => void 0)
43540
43824
  );
43541
43825
  const [playState, setPlayState] = useState("idle");
43542
43826
  const [currentStep, setCurrentStep] = useState(-1);
43543
43827
  const [attempts, setAttempts] = useState(0);
43544
43828
  const [slotFeedback, setSlotFeedback] = useState(
43545
- () => Array.from({ length: resolved?.maxSlots ?? 0 }, () => null)
43829
+ () => Array.from({ length: maxSlots }, () => null)
43546
43830
  );
43547
43831
  const timerRef = useRef(null);
43548
43832
  useEffect(() => () => {
@@ -43576,17 +43860,17 @@ function SequencerBoard({
43576
43860
  }, [emit]);
43577
43861
  const handleReset = useCallback(() => {
43578
43862
  if (timerRef.current) clearTimeout(timerRef.current);
43579
- setSlots(Array.from({ length: resolved?.maxSlots ?? 0 }, () => void 0));
43863
+ setSlots(Array.from({ length: maxSlots }, () => void 0));
43580
43864
  setPlayState("idle");
43581
43865
  setCurrentStep(-1);
43582
43866
  setAttempts(0);
43583
- setSlotFeedback(Array.from({ length: resolved?.maxSlots ?? 0 }, () => null));
43584
- }, [resolved?.maxSlots]);
43867
+ setSlotFeedback(Array.from({ length: maxSlots }, () => null));
43868
+ }, [maxSlots]);
43585
43869
  const filledSlots = slots.filter((s) => !!s);
43586
43870
  const canPlay = filledSlots.length > 0 && playState === "idle";
43587
43871
  const handlePlay = useCallback(() => {
43588
43872
  if (!canPlay) return;
43589
- setSlotFeedback(Array.from({ length: resolved?.maxSlots ?? 0 }, () => null));
43873
+ setSlotFeedback(Array.from({ length: maxSlots }, () => null));
43590
43874
  emit("UI:PLAY_SOUND", { key: "confirm" });
43591
43875
  const sequence = slots.map((s) => s?.id || "");
43592
43876
  if (playEvent) {
@@ -43597,10 +43881,10 @@ function SequencerBoard({
43597
43881
  let step = 0;
43598
43882
  const advance = () => {
43599
43883
  step++;
43600
- if (step >= (resolved?.maxSlots ?? 0)) {
43884
+ if (step >= maxSlots) {
43601
43885
  const playerSeq = slots.map((s) => s?.id);
43602
43886
  const playerIds = slots.filter(Boolean).map((s) => s?.id || "");
43603
- const success = (resolved?.solutions ?? []).some(
43887
+ const success = solutions.some(
43604
43888
  (sol) => sol.length === playerIds.length && sol.every((id, i) => id === playerIds[i])
43605
43889
  );
43606
43890
  if (success) {
@@ -43612,7 +43896,7 @@ function SequencerBoard({
43612
43896
  }
43613
43897
  } else {
43614
43898
  setAttempts((prev) => prev + 1);
43615
- const feedback = computeSlotFeedback(playerSeq, resolved?.solutions ?? []);
43899
+ const feedback = computeSlotFeedback(playerSeq, solutions);
43616
43900
  setSlotFeedback(feedback);
43617
43901
  setPlayState("idle");
43618
43902
  setCurrentStep(-1);
@@ -43630,10 +43914,10 @@ function SequencerBoard({
43630
43914
  }
43631
43915
  };
43632
43916
  timerRef.current = setTimeout(advance, stepDurationMs);
43633
- }, [canPlay, slots, resolved?.maxSlots, resolved?.solutions, stepDurationMs, playEvent, completeEvent, emit]);
43917
+ }, [canPlay, slots, maxSlots, solutions, stepDurationMs, playEvent, completeEvent, emit]);
43634
43918
  const machine = {
43635
- name: resolved?.title ?? "",
43636
- description: resolved?.description ?? "",
43919
+ name: str(resolved?.title),
43920
+ description: str(resolved?.description),
43637
43921
  states: slots.map((s, i) => stepLabel(s, i)),
43638
43922
  currentState: currentStep >= 0 ? stepLabel(slots[currentStep], currentStep) : "__idle__",
43639
43923
  transitions: slots.slice(0, -1).map((s, i) => ({
@@ -43642,37 +43926,41 @@ function SequencerBoard({
43642
43926
  event: "NEXT"
43643
43927
  }))
43644
43928
  };
43645
- const usedIds = resolved?.allowDuplicates === false ? slots.filter(Boolean).map((s) => s?.id || "") : [];
43646
- const showHint = attempts >= 3 && !!resolved?.hint;
43929
+ const usedIds = !allowDuplicates ? slots.filter(Boolean).map((s) => s?.id || "") : [];
43930
+ const hint = str(resolved?.hint);
43931
+ const showHint = attempts >= 3 && !!hint;
43647
43932
  const hasFeedback = slotFeedback.some((f3) => f3 !== null);
43648
43933
  const correctCount = slotFeedback.filter((f3) => f3 === "correct").length;
43649
43934
  const encourageKey = ENCOURAGEMENT_KEYS2[Math.min(attempts - 1, ENCOURAGEMENT_KEYS2.length - 1)] ?? ENCOURAGEMENT_KEYS2[0];
43650
43935
  if (!resolved) return null;
43936
+ const theme = resolved.theme ?? void 0;
43937
+ const themeBackground = theme?.background;
43938
+ const headerImage = str(resolved.headerImage);
43651
43939
  return /* @__PURE__ */ jsxs(
43652
43940
  VStack,
43653
43941
  {
43654
43942
  className: cn("p-4 gap-6", className),
43655
43943
  style: {
43656
- backgroundImage: resolved.theme?.background ? `url(${resolved.theme.background})` : void 0,
43944
+ backgroundImage: themeBackground ? `url(${themeBackground})` : void 0,
43657
43945
  backgroundSize: "cover",
43658
43946
  backgroundPosition: "center"
43659
43947
  },
43660
43948
  children: [
43661
- resolved.headerImage && !headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 overflow-hidden rounded-container", children: /* @__PURE__ */ jsx("img", { src: resolved.headerImage, alt: "", onError: () => setHeaderError(true), className: "w-full h-full object-cover" }) }) : resolved.headerImage && headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 rounded-container bg-gradient-to-br from-muted to-accent opacity-60" }) : null,
43949
+ 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,
43662
43950
  /* @__PURE__ */ jsxs(VStack, { gap: "xs", children: [
43663
- /* @__PURE__ */ jsx(Typography, { variant: "h4", className: "text-foreground", children: resolved.title }),
43664
- /* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground", children: resolved.description })
43951
+ /* @__PURE__ */ jsx(Typography, { variant: "h4", className: "text-foreground", children: str(resolved.title) }),
43952
+ /* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground", children: str(resolved.description) })
43665
43953
  ] }),
43666
43954
  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: [
43667
43955
  /* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-accent font-bold shrink-0", children: "\u{1F4A1} " + t("game.hint") + ":" }),
43668
- /* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-foreground", children: resolved.hint })
43956
+ /* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-foreground", children: hint })
43669
43957
  ] }) }),
43670
43958
  filledSlots.length > 0 && /* @__PURE__ */ jsx(TraitStateViewer, { trait: machine, variant: "linear", size: "md" }),
43671
43959
  /* @__PURE__ */ jsxs(VStack, { gap: "xs", children: [
43672
43960
  /* @__PURE__ */ jsxs(HStack, { className: "items-center justify-between", children: [
43673
43961
  /* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground font-medium", children: t("sequencer.yourSequence") + ":" }),
43674
43962
  hasFeedback && playState === "idle" && /* @__PURE__ */ jsxs(Typography, { variant: "caption", className: "text-muted-foreground", children: [
43675
- `${correctCount}/${resolved.maxSlots} `,
43963
+ `${correctCount}/${maxSlots} `,
43676
43964
  "\u2705"
43677
43965
  ] })
43678
43966
  ] }),
@@ -43680,7 +43968,7 @@ function SequencerBoard({
43680
43968
  SequenceBar,
43681
43969
  {
43682
43970
  slots,
43683
- maxSlots: resolved.maxSlots,
43971
+ maxSlots,
43684
43972
  onSlotDrop: handleSlotDrop,
43685
43973
  onSlotRemove: handleSlotRemove,
43686
43974
  playing: playState === "playing",
@@ -43694,15 +43982,15 @@ function SequencerBoard({
43694
43982
  playState !== "playing" && /* @__PURE__ */ jsx(
43695
43983
  ActionPalette,
43696
43984
  {
43697
- actions: resolved.availableActions,
43985
+ actions: availableActions,
43698
43986
  usedActionIds: usedIds,
43699
- allowDuplicates: resolved.allowDuplicates !== false,
43987
+ allowDuplicates,
43700
43988
  categoryColors,
43701
43989
  label: t("sequencer.dragActions")
43702
43990
  }
43703
43991
  ),
43704
43992
  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) }) }),
43705
- 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") }) }),
43993
+ 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") }) }),
43706
43994
  /* @__PURE__ */ jsxs(HStack, { gap: "sm", children: [
43707
43995
  /* @__PURE__ */ jsx(
43708
43996
  Button,
@@ -43726,6 +44014,7 @@ var init_SequencerBoard = __esm({
43726
44014
  init_cn();
43727
44015
  init_useEventBus();
43728
44016
  init_TraitStateViewer();
44017
+ init_boardEntity();
43729
44018
  init_SequenceBar();
43730
44019
  init_ActionPalette();
43731
44020
  ENCOURAGEMENT_KEYS2 = [
@@ -43775,18 +44064,21 @@ var init_ShowcaseOrganism = __esm({
43775
44064
  heading && /* @__PURE__ */ jsx(Typography, { variant: "h2", align: "center", children: heading }),
43776
44065
  subtitle && /* @__PURE__ */ jsx(Typography, { variant: "body1", color: "muted", align: "center", className: "max-w-2xl", children: subtitle })
43777
44066
  ] }),
43778
- /* @__PURE__ */ jsx(SimpleGrid, { cols: columns, gap: "lg", children: items.map((item) => /* @__PURE__ */ jsx(
43779
- ShowcaseCard,
43780
- {
43781
- title: item.title,
43782
- description: item.description,
43783
- image: item.image,
43784
- href: item.href,
43785
- badge: item.badge,
43786
- accentColor: item.accentColor
43787
- },
43788
- item.id
43789
- )) })
44067
+ /* @__PURE__ */ jsx(SimpleGrid, { cols: columns, gap: "lg", children: items.map((item) => {
44068
+ const imageRaw = item.image;
44069
+ return /* @__PURE__ */ jsx(
44070
+ ShowcaseCard,
44071
+ {
44072
+ title: String(item.title ?? ""),
44073
+ description: item.description != null ? String(item.description) : void 0,
44074
+ image: { src: String(imageRaw?.src ?? ""), alt: String(imageRaw?.alt ?? "") },
44075
+ href: item.href != null ? String(item.href) : void 0,
44076
+ badge: item.badge != null ? String(item.badge) : void 0,
44077
+ accentColor: item.accentColor != null ? String(item.accentColor) : void 0
44078
+ },
44079
+ String(item.id ?? "")
44080
+ );
44081
+ }) })
43790
44082
  ] });
43791
44083
  };
43792
44084
  ShowcaseOrganism.displayName = "ShowcaseOrganism";
@@ -44154,8 +44446,8 @@ function SimulatorBoard({
44154
44446
  }) {
44155
44447
  const { emit } = useEventBus();
44156
44448
  const { t } = useTranslate();
44157
- const resolved = Array.isArray(entity) ? entity[0] : entity;
44158
- const parameters = resolved?.parameters ?? [];
44449
+ const resolved = boardEntity(entity);
44450
+ const parameters = Array.isArray(resolved?.parameters) ? resolved.parameters : [];
44159
44451
  const [values, setValues] = useState(() => {
44160
44452
  const init = {};
44161
44453
  for (const p2 of parameters) {
@@ -44169,15 +44461,15 @@ function SimulatorBoard({
44169
44461
  const [showHint, setShowHint] = useState(false);
44170
44462
  const computeOutput = useCallback((params) => {
44171
44463
  try {
44172
- const fn = new Function("params", `return (${resolved?.computeExpression})`);
44464
+ const fn = new Function("params", `return (${str(resolved?.computeExpression)})`);
44173
44465
  return fn(params);
44174
44466
  } catch {
44175
44467
  return 0;
44176
44468
  }
44177
44469
  }, [resolved?.computeExpression]);
44178
44470
  const output = useMemo(() => computeOutput(values) ?? 0, [computeOutput, values]);
44179
- const targetValue = resolved?.targetValue ?? 0;
44180
- const targetTolerance = resolved?.targetTolerance ?? 0;
44471
+ const targetValue = num(resolved?.targetValue);
44472
+ const targetTolerance = num(resolved?.targetTolerance);
44181
44473
  const isCorrect = Math.abs(output - targetValue) <= targetTolerance;
44182
44474
  const handleParameterChange = (id, value) => {
44183
44475
  if (submitted) return;
@@ -44192,7 +44484,7 @@ function SimulatorBoard({
44192
44484
  };
44193
44485
  const handleReset = () => {
44194
44486
  setSubmitted(false);
44195
- if (attempts >= 2 && resolved?.hint) {
44487
+ if (attempts >= 2 && str(resolved?.hint)) {
44196
44488
  setShowHint(true);
44197
44489
  }
44198
44490
  };
@@ -44207,20 +44499,26 @@ function SimulatorBoard({
44207
44499
  setShowHint(false);
44208
44500
  };
44209
44501
  if (!resolved) return null;
44502
+ const theme = resolved.theme ?? void 0;
44503
+ const themeBackground = theme?.background;
44504
+ const headerImage = str(resolved.headerImage);
44505
+ const hint = str(resolved.hint);
44506
+ const outputLabel = str(resolved.outputLabel);
44507
+ const outputUnit = str(resolved.outputUnit);
44210
44508
  return /* @__PURE__ */ jsx(
44211
44509
  Box,
44212
44510
  {
44213
44511
  className,
44214
44512
  style: {
44215
- backgroundImage: resolved.theme?.background ? `url(${resolved.theme.background})` : void 0,
44513
+ backgroundImage: themeBackground ? `url(${themeBackground})` : void 0,
44216
44514
  backgroundSize: "cover",
44217
44515
  backgroundPosition: "center"
44218
44516
  },
44219
44517
  children: /* @__PURE__ */ jsxs(VStack, { gap: "lg", className: "p-4", children: [
44220
- resolved.headerImage && !headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 overflow-hidden rounded-container", children: /* @__PURE__ */ jsx("img", { src: resolved.headerImage, alt: "", onError: () => setHeaderError(true), className: "w-full h-full object-cover" }) }) : resolved.headerImage && headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 rounded-container bg-gradient-to-br from-muted to-accent opacity-60" }) : null,
44518
+ 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,
44221
44519
  /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
44222
- /* @__PURE__ */ jsx(Typography, { variant: "h4", weight: "bold", children: resolved.title }),
44223
- /* @__PURE__ */ jsx(Typography, { variant: "body", children: resolved.description })
44520
+ /* @__PURE__ */ jsx(Typography, { variant: "h4", weight: "bold", children: str(resolved.title) }),
44521
+ /* @__PURE__ */ jsx(Typography, { variant: "body", children: str(resolved.description) })
44224
44522
  ] }) }),
44225
44523
  /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "md", children: [
44226
44524
  /* @__PURE__ */ jsx(Typography, { variant: "small", weight: "bold", className: "uppercase tracking-wider text-muted-foreground", children: t("simulator.parameters") }),
@@ -44261,28 +44559,28 @@ function SimulatorBoard({
44261
44559
  ] }, param.id))
44262
44560
  ] }) }),
44263
44561
  /* @__PURE__ */ jsx(Card, { className: "p-4", children: /* @__PURE__ */ jsxs(VStack, { gap: "sm", align: "center", children: [
44264
- /* @__PURE__ */ jsx(Typography, { variant: "small", weight: "bold", className: "uppercase tracking-wider text-muted-foreground", children: resolved.outputLabel }),
44562
+ /* @__PURE__ */ jsx(Typography, { variant: "small", weight: "bold", className: "uppercase tracking-wider text-muted-foreground", children: outputLabel }),
44265
44563
  /* @__PURE__ */ jsxs(Typography, { variant: "h3", weight: "bold", children: [
44266
44564
  output.toFixed(2),
44267
44565
  " ",
44268
- resolved.outputUnit
44566
+ outputUnit
44269
44567
  ] }),
44270
44568
  submitted && /* @__PURE__ */ jsxs(HStack, { gap: "xs", align: "center", children: [
44271
44569
  /* @__PURE__ */ jsx(Icon, { icon: isCorrect ? CheckCircle : XCircle, size: "sm", className: isCorrect ? "text-success" : "text-error" }),
44272
- /* @__PURE__ */ jsx(Typography, { variant: "body", className: isCorrect ? "text-success" : "text-error", children: isCorrect ? resolved.successMessage ?? t("simulator.correct") : resolved.failMessage ?? t("simulator.incorrect") })
44570
+ /* @__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") })
44273
44571
  ] }),
44274
44572
  /* @__PURE__ */ jsxs(Typography, { variant: "caption", className: "text-muted-foreground", children: [
44275
44573
  t("simulator.target"),
44276
44574
  ": ",
44277
44575
  targetValue,
44278
44576
  " ",
44279
- resolved.outputUnit,
44577
+ outputUnit,
44280
44578
  " (\xB1",
44281
44579
  targetTolerance,
44282
44580
  ")"
44283
44581
  ] })
44284
44582
  ] }) }),
44285
- showHint && resolved.hint && /* @__PURE__ */ jsx(Card, { className: "p-4 border-l-4 border-l-warning", children: /* @__PURE__ */ jsx(Typography, { variant: "body", children: resolved.hint }) }),
44583
+ showHint && hint && /* @__PURE__ */ jsx(Card, { className: "p-4 border-l-4 border-l-warning", children: /* @__PURE__ */ jsx(Typography, { variant: "body", children: hint }) }),
44286
44584
  /* @__PURE__ */ jsxs(HStack, { gap: "sm", justify: "center", children: [
44287
44585
  !submitted ? /* @__PURE__ */ jsxs(Button, { variant: "primary", onClick: handleSubmit, children: [
44288
44586
  /* @__PURE__ */ jsx(Icon, { icon: Play, size: "sm" }),
@@ -44301,6 +44599,7 @@ var init_SimulatorBoard = __esm({
44301
44599
  "components/game/organisms/puzzles/simulator/SimulatorBoard.tsx"() {
44302
44600
  init_atoms2();
44303
44601
  init_useEventBus();
44602
+ init_boardEntity();
44304
44603
  SimulatorBoard.displayName = "SimulatorBoard";
44305
44604
  }
44306
44605
  });
@@ -44543,7 +44842,7 @@ var init_StatCard = __esm({
44543
44842
  const labelToUse = propLabel ?? propTitle;
44544
44843
  const eventBus = useEventBus();
44545
44844
  const { t } = useTranslate();
44546
- const handleActionClick = React79__default.useCallback(() => {
44845
+ const handleActionClick = React80__default.useCallback(() => {
44547
44846
  if (action?.event) {
44548
44847
  eventBus.emit(`UI:${action.event}`, {});
44549
44848
  }
@@ -44554,7 +44853,7 @@ var init_StatCard = __esm({
44554
44853
  const data = Array.isArray(entity) ? entity : entity ? [entity] : [];
44555
44854
  const isLoading = externalLoading ?? false;
44556
44855
  const error = externalError;
44557
- const computeMetricValue = React79__default.useCallback(
44856
+ const computeMetricValue = React80__default.useCallback(
44558
44857
  (metric, items) => {
44559
44858
  if (metric.value !== void 0) {
44560
44859
  return metric.value;
@@ -44593,7 +44892,7 @@ var init_StatCard = __esm({
44593
44892
  },
44594
44893
  []
44595
44894
  );
44596
- const schemaStats = React79__default.useMemo(() => {
44895
+ const schemaStats = React80__default.useMemo(() => {
44597
44896
  if (!metrics || metrics.length === 0) return null;
44598
44897
  return metrics.map((metric) => ({
44599
44898
  label: metric.label,
@@ -44601,7 +44900,7 @@ var init_StatCard = __esm({
44601
44900
  format: metric.format
44602
44901
  }));
44603
44902
  }, [metrics, data, computeMetricValue]);
44604
- const calculatedTrend = React79__default.useMemo(() => {
44903
+ const calculatedTrend = React80__default.useMemo(() => {
44605
44904
  if (manualTrend !== void 0) return manualTrend;
44606
44905
  if (previousValue === void 0 || currentValue === void 0)
44607
44906
  return void 0;
@@ -44837,22 +45136,25 @@ function VariablePanel({
44837
45136
  return /* @__PURE__ */ jsxs(VStack, { className: cn("p-3 rounded-lg bg-card border border-border", className), gap: "sm", children: [
44838
45137
  /* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground font-medium", children: t("stateArchitect.variables", { name: entityName }) }),
44839
45138
  variables.map((v) => {
44840
- const max = v.max ?? 100;
44841
- const min = v.min ?? 0;
44842
- const pct = Math.round((v.value - min) / (max - min) * 100);
45139
+ const name = v.name == null ? "" : String(v.name);
45140
+ const value = numField(v.value);
45141
+ const max = numField(v.max, 100);
45142
+ const min = numField(v.min, 0);
45143
+ const unit = v.unit == null ? "" : String(v.unit);
45144
+ const pct = Math.round((value - min) / (max - min) * 100);
44843
45145
  const isHigh = pct > 80;
44844
45146
  const isLow = pct < 20;
44845
45147
  return /* @__PURE__ */ jsxs(VStack, { gap: "none", children: [
44846
45148
  /* @__PURE__ */ jsxs(HStack, { className: "items-center justify-between", children: [
44847
- /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-foreground font-medium", children: v.name }),
45149
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-foreground font-medium", children: name }),
44848
45150
  /* @__PURE__ */ jsxs(Typography, { variant: "caption", className: cn(
44849
45151
  isHigh ? "text-error" : isLow ? "text-warning" : "text-foreground"
44850
45152
  ), children: [
44851
- v.value,
44852
- v.unit || "",
45153
+ value,
45154
+ unit,
44853
45155
  " / ",
44854
45156
  max,
44855
- v.unit || ""
45157
+ unit
44856
45158
  ] })
44857
45159
  ] }),
44858
45160
  /* @__PURE__ */ jsx(
@@ -44863,14 +45165,19 @@ function VariablePanel({
44863
45165
  size: "sm"
44864
45166
  }
44865
45167
  )
44866
- ] }, v.name);
45168
+ ] }, name);
44867
45169
  })
44868
45170
  ] });
44869
45171
  }
45172
+ var numField;
44870
45173
  var init_VariablePanel = __esm({
44871
45174
  "components/game/organisms/puzzles/state-architect/VariablePanel.tsx"() {
44872
45175
  init_atoms2();
44873
45176
  init_cn();
45177
+ numField = (v, fallback = 0) => {
45178
+ const n = Number(v);
45179
+ return Number.isFinite(n) ? n : fallback;
45180
+ };
44874
45181
  VariablePanel.displayName = "VariablePanel";
44875
45182
  }
44876
45183
  });
@@ -44897,14 +45204,21 @@ function StateArchitectBoard({
44897
45204
  }) {
44898
45205
  const { emit } = useEventBus();
44899
45206
  const { t } = useTranslate();
44900
- const resolved = Array.isArray(entity) ? entity[0] : entity;
44901
- const [transitions, setTransitions] = useState(resolved?.transitions ?? []);
45207
+ const resolved = boardEntity(entity);
45208
+ const entityStates = Array.isArray(resolved?.states) ? resolved.states : [];
45209
+ const initialState = str(resolved?.initialState);
45210
+ const entityName = str(resolved?.entityName);
45211
+ const availableEvents = Array.isArray(resolved?.availableEvents) ? resolved.availableEvents : [];
45212
+ const testCases = Array.isArray(resolved?.testCases) ? resolved.testCases : [];
45213
+ const entityTransitions = Array.isArray(resolved?.transitions) ? resolved.transitions : [];
45214
+ const entityVariables = rows(resolved?.variables);
45215
+ const [transitions, setTransitions] = useState(entityTransitions);
44902
45216
  const [headerError, setHeaderError] = useState(false);
44903
45217
  const [playState, setPlayState] = useState("editing");
44904
- const [currentState, setCurrentState] = useState(resolved?.initialState ?? "");
45218
+ const [currentState, setCurrentState] = useState(initialState);
44905
45219
  const [selectedState, setSelectedState] = useState(null);
44906
45220
  const [testResults, setTestResults] = useState([]);
44907
- const [variables, setVariables] = useState(resolved?.variables ?? []);
45221
+ const [variables, setVariables] = useState(() => [...entityVariables]);
44908
45222
  const [attempts, setAttempts] = useState(0);
44909
45223
  const timerRef = useRef(null);
44910
45224
  const [addingFrom, setAddingFrom] = useState(null);
@@ -44913,12 +45227,12 @@ function StateArchitectBoard({
44913
45227
  }, []);
44914
45228
  const GRAPH_W = 500;
44915
45229
  const GRAPH_H = 400;
44916
- const positions = useMemo(() => layoutStates(resolved?.states ?? [], GRAPH_W, GRAPH_H), [resolved?.states]);
45230
+ const positions = useMemo(() => layoutStates(entityStates, GRAPH_W, GRAPH_H), [entityStates]);
44917
45231
  const handleStateClick = useCallback((state) => {
44918
45232
  if (playState !== "editing") return;
44919
45233
  if (addingFrom) {
44920
45234
  if (addingFrom !== state) {
44921
- const event = resolved?.availableEvents[0] || "EVENT";
45235
+ const event = availableEvents[0] || "EVENT";
44922
45236
  const newTrans = {
44923
45237
  id: `t-${nextTransId++}`,
44924
45238
  from: addingFrom,
@@ -44931,7 +45245,7 @@ function StateArchitectBoard({
44931
45245
  } else {
44932
45246
  setSelectedState(state);
44933
45247
  }
44934
- }, [playState, addingFrom, resolved?.availableEvents]);
45248
+ }, [playState, addingFrom, availableEvents]);
44935
45249
  const handleStartAddTransition = useCallback(() => {
44936
45250
  if (!selectedState) return;
44937
45251
  setAddingFrom(selectedState);
@@ -44940,9 +45254,9 @@ function StateArchitectBoard({
44940
45254
  setTransitions((prev) => prev.filter((t2) => t2.id !== transId));
44941
45255
  }, []);
44942
45256
  const machine = useMemo(() => ({
44943
- name: resolved?.entityName ?? "",
44944
- description: resolved?.description ?? "",
44945
- states: resolved?.states ?? [],
45257
+ name: entityName,
45258
+ description: str(resolved?.description),
45259
+ states: entityStates,
44946
45260
  currentState,
44947
45261
  transitions: transitions.map((t2) => ({
44948
45262
  from: t2.from,
@@ -44950,7 +45264,7 @@ function StateArchitectBoard({
44950
45264
  event: t2.event,
44951
45265
  guardHint: t2.guardHint
44952
45266
  }))
44953
- }), [resolved, currentState, transitions]);
45267
+ }), [entityName, resolved, entityStates, currentState, transitions]);
44954
45268
  const handleTest = useCallback(() => {
44955
45269
  if (playState !== "editing") return;
44956
45270
  if (testEvent) emit(`UI:${testEvent}`, {});
@@ -44959,7 +45273,7 @@ function StateArchitectBoard({
44959
45273
  const results = [];
44960
45274
  let testIdx = 0;
44961
45275
  const runNextTest = () => {
44962
- if (testIdx >= (resolved?.testCases.length ?? 0)) {
45276
+ if (testIdx >= testCases.length) {
44963
45277
  const allPassed = results.every((r) => r.passed);
44964
45278
  setPlayState(allPassed ? "success" : "fail");
44965
45279
  setTestResults(results);
@@ -44974,9 +45288,9 @@ function StateArchitectBoard({
44974
45288
  }
44975
45289
  return;
44976
45290
  }
44977
- const testCase = resolved?.testCases[testIdx];
45291
+ const testCase = testCases[testIdx];
44978
45292
  if (!testCase) return;
44979
- let state = resolved.initialState;
45293
+ let state = initialState;
44980
45294
  for (const event of testCase.events) {
44981
45295
  const trans = transitions.find((t2) => t2.from === state && t2.event === event);
44982
45296
  if (trans) {
@@ -44994,53 +45308,57 @@ function StateArchitectBoard({
44994
45308
  timerRef.current = setTimeout(runNextTest, stepDurationMs);
44995
45309
  };
44996
45310
  timerRef.current = setTimeout(runNextTest, stepDurationMs);
44997
- }, [playState, transitions, resolved, stepDurationMs, testEvent, completeEvent, emit]);
45311
+ }, [playState, transitions, testCases, initialState, stepDurationMs, testEvent, completeEvent, emit]);
44998
45312
  const handleTryAgain = useCallback(() => {
44999
45313
  if (timerRef.current) clearTimeout(timerRef.current);
45000
45314
  setPlayState("editing");
45001
- setCurrentState(resolved?.initialState ?? "");
45315
+ setCurrentState(initialState);
45002
45316
  setTestResults([]);
45003
- }, [resolved?.initialState]);
45317
+ }, [initialState]);
45004
45318
  const handleReset = useCallback(() => {
45005
45319
  if (timerRef.current) clearTimeout(timerRef.current);
45006
- setTransitions(resolved?.transitions ?? []);
45320
+ setTransitions(entityTransitions);
45007
45321
  setPlayState("editing");
45008
- setCurrentState(resolved?.initialState ?? "");
45322
+ setCurrentState(initialState);
45009
45323
  setTestResults([]);
45010
- setVariables(resolved?.variables ?? []);
45324
+ setVariables([...entityVariables]);
45011
45325
  setSelectedState(null);
45012
45326
  setAddingFrom(null);
45013
45327
  setAttempts(0);
45014
- }, [resolved]);
45328
+ }, [entityTransitions, initialState, entityVariables]);
45015
45329
  const codeData = useMemo(() => ({
45016
- name: resolved?.entityName ?? "",
45017
- states: resolved?.states ?? [],
45018
- initialState: resolved?.initialState ?? "",
45330
+ name: entityName,
45331
+ states: entityStates,
45332
+ initialState,
45019
45333
  transitions: transitions.map((t2) => ({
45020
45334
  from: t2.from,
45021
45335
  to: t2.to,
45022
45336
  event: t2.event,
45023
45337
  ...t2.guardHint ? { guard: t2.guardHint } : {}
45024
45338
  }))
45025
- }), [resolved, transitions]);
45339
+ }), [entityName, entityStates, initialState, transitions]);
45026
45340
  if (!resolved) return null;
45341
+ const theme = resolved.theme ?? void 0;
45342
+ const themeBackground = theme?.background;
45343
+ const headerImage = str(resolved.headerImage);
45344
+ const hint = str(resolved.hint);
45027
45345
  return /* @__PURE__ */ jsxs(
45028
45346
  VStack,
45029
45347
  {
45030
45348
  className: cn("p-4 gap-6", className),
45031
45349
  style: {
45032
- backgroundImage: resolved.theme?.background ? `url(${resolved.theme.background})` : void 0,
45350
+ backgroundImage: themeBackground ? `url(${themeBackground})` : void 0,
45033
45351
  backgroundSize: "cover",
45034
45352
  backgroundPosition: "center"
45035
45353
  },
45036
45354
  children: [
45037
- resolved.headerImage && !headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 overflow-hidden rounded-container", children: /* @__PURE__ */ jsx("img", { src: resolved.headerImage, alt: "", onError: () => setHeaderError(true), className: "w-full h-full object-cover" }) }) : resolved.headerImage && headerError ? /* @__PURE__ */ jsx(Box, { className: "w-full h-32 rounded-container bg-gradient-to-br from-muted to-accent opacity-60" }) : null,
45355
+ 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,
45038
45356
  /* @__PURE__ */ jsxs(VStack, { gap: "xs", children: [
45039
- /* @__PURE__ */ jsx(Typography, { variant: "h4", className: "text-foreground", children: resolved.title }),
45040
- /* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground", children: resolved.description }),
45357
+ /* @__PURE__ */ jsx(Typography, { variant: "h4", className: "text-foreground", children: str(resolved.title) }),
45358
+ /* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-muted-foreground", children: str(resolved.description) }),
45041
45359
  /* @__PURE__ */ jsxs(HStack, { className: "items-center p-2 rounded bg-warning/10 border border-warning/30", gap: "xs", children: [
45042
45360
  /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-warning font-bold", children: t("game.hint") + ":" }),
45043
- /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-foreground", children: resolved.hint })
45361
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-foreground", children: hint })
45044
45362
  ] })
45045
45363
  ] }),
45046
45364
  /* @__PURE__ */ jsxs(HStack, { className: "flex-wrap items-start", gap: "lg", children: [
@@ -45088,14 +45406,14 @@ function StateArchitectBoard({
45088
45406
  ]
45089
45407
  }
45090
45408
  ),
45091
- resolved.states.map((state) => /* @__PURE__ */ jsx(
45409
+ entityStates.map((state) => /* @__PURE__ */ jsx(
45092
45410
  StateNode2,
45093
45411
  {
45094
45412
  name: state,
45095
45413
  position: positions[state],
45096
45414
  isCurrent: state === currentState,
45097
45415
  isSelected: state === selectedState,
45098
- isInitial: state === resolved.initialState,
45416
+ isInitial: state === initialState,
45099
45417
  onClick: () => handleStateClick(state)
45100
45418
  },
45101
45419
  state
@@ -45142,7 +45460,7 @@ function StateArchitectBoard({
45142
45460
  /* @__PURE__ */ jsx(
45143
45461
  VariablePanel,
45144
45462
  {
45145
- entityName: resolved.entityName,
45463
+ entityName,
45146
45464
  variables
45147
45465
  }
45148
45466
  ),
@@ -45157,12 +45475,12 @@ function StateArchitectBoard({
45157
45475
  resolved.showCodeView !== false && /* @__PURE__ */ jsx(CodeView, { data: codeData, label: "View Code" })
45158
45476
  ] })
45159
45477
  ] }),
45160
- 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") }) }),
45478
+ 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") }) }),
45161
45479
  playState === "fail" && /* @__PURE__ */ jsxs(VStack, { gap: "sm", children: [
45162
45480
  /* @__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]) }) }),
45163
- attempts >= 3 && resolved.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: [
45481
+ 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: [
45164
45482
  /* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-accent font-bold shrink-0", children: "\u{1F4A1} " + t("game.hint") + ":" }),
45165
- /* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-foreground", children: resolved.hint })
45483
+ /* @__PURE__ */ jsx(Typography, { variant: "body2", className: "text-foreground", children: hint })
45166
45484
  ] }) })
45167
45485
  ] }),
45168
45486
  /* @__PURE__ */ jsxs(HStack, { gap: "sm", children: [
@@ -45192,6 +45510,7 @@ var init_StateArchitectBoard = __esm({
45192
45510
  init_TransitionArrow();
45193
45511
  init_VariablePanel();
45194
45512
  init_CodeView();
45513
+ init_boardEntity();
45195
45514
  ENCOURAGEMENT_KEYS3 = [
45196
45515
  "puzzle.tryAgain1",
45197
45516
  "puzzle.tryAgain2",
@@ -45228,8 +45547,8 @@ var init_StatsOrganism = __esm({
45228
45547
  return /* @__PURE__ */ jsx(ErrorState, { message: error.message, className });
45229
45548
  }
45230
45549
  const stats = items.map((item) => ({
45231
- value: item.value,
45232
- label: item.label
45550
+ value: String(item.value ?? ""),
45551
+ label: String(item.label ?? "")
45233
45552
  }));
45234
45553
  return /* @__PURE__ */ jsx(
45235
45554
  StatsGrid,
@@ -45346,10 +45665,10 @@ var init_StepFlowOrganism = __esm({
45346
45665
  return /* @__PURE__ */ jsx(ErrorState, { message: error.message, className });
45347
45666
  }
45348
45667
  const steps = items.map((item) => ({
45349
- number: item.number,
45350
- title: item.title,
45351
- description: item.description,
45352
- icon: item.icon
45668
+ number: item.number != null ? Number(item.number) : void 0,
45669
+ title: String(item.title ?? ""),
45670
+ description: String(item.description ?? ""),
45671
+ icon: item.icon != null ? String(item.icon) : void 0
45353
45672
  }));
45354
45673
  return /* @__PURE__ */ jsxs(VStack, { gap: "lg", className: cn("w-full", className), children: [
45355
45674
  (heading || subtitle) && /* @__PURE__ */ jsxs(VStack, { gap: "sm", align: "center", className: "w-full", children: [
@@ -45522,13 +45841,13 @@ var init_TeamOrganism = __esm({
45522
45841
  /* @__PURE__ */ jsx(SimpleGrid, { cols: cols > 0 ? cols : 1, gap: "lg", children: items.map((member) => /* @__PURE__ */ jsx(
45523
45842
  TeamCard,
45524
45843
  {
45525
- name: member.name,
45526
- nameAr: member.nameAr,
45527
- role: member.role,
45528
- bio: member.bio,
45529
- avatar: member.avatar
45844
+ name: String(member.name ?? ""),
45845
+ nameAr: member.nameAr != null ? String(member.nameAr) : void 0,
45846
+ role: String(member.role ?? ""),
45847
+ bio: String(member.bio ?? ""),
45848
+ avatar: member.avatar != null ? String(member.avatar) : void 0
45530
45849
  },
45531
- member.id
45850
+ String(member.id ?? "")
45532
45851
  )) })
45533
45852
  ] });
45534
45853
  };
@@ -45586,7 +45905,7 @@ var init_Timeline = __esm({
45586
45905
  }) => {
45587
45906
  const { t } = useTranslate();
45588
45907
  const entityData = Array.isArray(entity) ? entity : [];
45589
- const items = React79__default.useMemo(() => {
45908
+ const items = React80__default.useMemo(() => {
45590
45909
  if (propItems) return propItems;
45591
45910
  if (entityData.length === 0) return [];
45592
45911
  return entityData.map((record, idx) => {
@@ -45743,7 +46062,7 @@ var init_TimerDisplay = __esm({
45743
46062
  }
45744
46063
  });
45745
46064
  function extractToastProps(children) {
45746
- if (!React79__default.isValidElement(children)) {
46065
+ if (!React80__default.isValidElement(children)) {
45747
46066
  if (typeof children === "string") {
45748
46067
  return { message: children };
45749
46068
  }
@@ -45781,7 +46100,7 @@ var init_ToastSlot = __esm({
45781
46100
  eventBus.emit("UI:CLOSE");
45782
46101
  };
45783
46102
  if (!isVisible) return null;
45784
- const isCustomContent = React79__default.isValidElement(children) && !message;
46103
+ const isCustomContent = React80__default.isValidElement(children) && !message;
45785
46104
  return /* @__PURE__ */ jsx(Box, { className: "fixed bottom-4 right-4 z-50", children: isCustomContent ? children : /* @__PURE__ */ jsx(
45786
46105
  Toast,
45787
46106
  {
@@ -45815,8 +46134,8 @@ function useBattleState(initialUnits, eventConfig = {}, callbacks = {}) {
45815
46134
  const [turn, setTurn] = useState(1);
45816
46135
  const [gameResult, setGameResult] = useState(null);
45817
46136
  const checkGameEnd = useCallback((currentUnits) => {
45818
- const pa = currentUnits.filter((u) => u.team === "player" && u.health > 0);
45819
- const ea = currentUnits.filter((u) => u.team === "enemy" && u.health > 0);
46137
+ const pa = currentUnits.filter((u) => unitTeam(u) === "player" && unitHealth(u) > 0);
46138
+ const ea = currentUnits.filter((u) => unitTeam(u) === "enemy" && unitHealth(u) > 0);
45820
46139
  if (pa.length === 0) {
45821
46140
  setGameResult("defeat");
45822
46141
  setPhase("game_over");
@@ -45834,34 +46153,36 @@ function useBattleState(initialUnits, eventConfig = {}, callbacks = {}) {
45834
46153
  }
45835
46154
  }, [onGameEnd, gameEndEvent, eventBus]);
45836
46155
  const handleUnitClick = useCallback((unitId) => {
45837
- const unit = units.find((u) => u.id === unitId);
46156
+ const unit = units.find((u) => str(u.id) === unitId);
45838
46157
  if (!unit) return;
45839
46158
  if (unitClickEvent) {
45840
46159
  eventBus.emit(`UI:${unitClickEvent}`, { unitId });
45841
46160
  }
45842
46161
  if (phase === "observation" || phase === "selection") {
45843
- if (unit.team === "player") {
46162
+ if (unitTeam(unit) === "player") {
45844
46163
  setSelectedUnitId(unitId);
45845
46164
  setPhase("movement");
45846
46165
  }
45847
46166
  } else if (phase === "action") {
45848
- const selectedUnit = units.find((u) => u.id === selectedUnitId);
46167
+ const selectedUnit = units.find((u) => str(u.id) === selectedUnitId);
45849
46168
  if (!selectedUnit) return;
45850
- if (unit.team === "enemy") {
45851
- const dx = Math.abs(unit.position.x - selectedUnit.position.x);
45852
- const dy = Math.abs(unit.position.y - selectedUnit.position.y);
46169
+ if (unitTeam(unit) === "enemy") {
46170
+ const up = unitPosition(unit);
46171
+ const sp = unitPosition(selectedUnit);
46172
+ const dx = Math.abs(up.x - sp.x);
46173
+ const dy = Math.abs(up.y - sp.y);
45853
46174
  if (dx <= 1 && dy <= 1 && dx + dy > 0) {
45854
- const damage = calculateDamage2 ? calculateDamage2(selectedUnit, unit) : Math.max(1, selectedUnit.attack - unit.defense);
45855
- const newHealth = Math.max(0, unit.health - damage);
46175
+ const damage = calculateDamage2 ? calculateDamage2(selectedUnit, unit) : Math.max(1, num(selectedUnit.attack) - num(unit.defense));
46176
+ const newHealth = Math.max(0, unitHealth(unit) - damage);
45856
46177
  const updatedUnits = units.map(
45857
- (u) => u.id === unit.id ? { ...u, health: newHealth } : u
46178
+ (u) => str(u.id) === str(unit.id) ? { ...u, health: newHealth } : u
45858
46179
  );
45859
46180
  setUnits(updatedUnits);
45860
46181
  onAttack?.(selectedUnit, unit, damage);
45861
46182
  if (attackEvent) {
45862
46183
  eventBus.emit(`UI:${attackEvent}`, {
45863
- attackerId: selectedUnit.id,
45864
- targetId: unit.id,
46184
+ attackerId: str(selectedUnit.id),
46185
+ targetId: str(unit.id),
45865
46186
  damage
45866
46187
  });
45867
46188
  }
@@ -45878,16 +46199,20 @@ function useBattleState(initialUnits, eventConfig = {}, callbacks = {}) {
45878
46199
  eventBus.emit(`UI:${tileClickEvent}`, { x, y });
45879
46200
  }
45880
46201
  if (phase === "movement" && selectedUnitId) {
45881
- const selectedUnit = units.find((u) => u.id === selectedUnitId);
46202
+ const selectedUnit = units.find((u) => str(u.id) === selectedUnitId);
45882
46203
  if (!selectedUnit) return;
45883
- const dx = Math.abs(x - selectedUnit.position.x);
45884
- const dy = Math.abs(y - selectedUnit.position.y);
46204
+ const sp = unitPosition(selectedUnit);
46205
+ const dx = Math.abs(x - sp.x);
46206
+ const dy = Math.abs(y - sp.y);
45885
46207
  const dist = dx + dy;
45886
- if (dist > 0 && dist <= selectedUnit.movement) {
45887
- if (!units.some((u) => u.position.x === x && u.position.y === y && u.health > 0)) {
46208
+ if (dist > 0 && dist <= num(selectedUnit.movement)) {
46209
+ if (!units.some((u) => {
46210
+ const p2 = unitPosition(u);
46211
+ return p2.x === x && p2.y === y && unitHealth(u) > 0;
46212
+ })) {
45888
46213
  setUnits(
45889
46214
  (prev) => prev.map(
45890
- (u) => u.id === selectedUnitId ? { ...u, position: { x, y } } : u
46215
+ (u) => str(u.id) === selectedUnitId ? { ...u, position: { x, y } } : u
45891
46216
  )
45892
46217
  );
45893
46218
  setPhase("action");
@@ -45930,12 +46255,13 @@ var init_useBattleState = __esm({
45930
46255
  "components/game/organisms/hooks/useBattleState.ts"() {
45931
46256
  "use client";
45932
46257
  init_useEventBus();
46258
+ init_boardEntity();
45933
46259
  }
45934
46260
  });
45935
46261
  function UncontrolledBattleBoard({ entity, ...rest }) {
45936
- const resolved = Array.isArray(entity) ? entity[0] : entity;
46262
+ const resolved = boardEntity(entity);
45937
46263
  const battleState = useBattleState(
45938
- resolved?.initialUnits ?? [],
46264
+ rows(resolved?.initialUnits),
45939
46265
  {
45940
46266
  tileClickEvent: rest.tileClickEvent,
45941
46267
  unitClickEvent: rest.unitClickEvent,
@@ -45971,10 +46297,23 @@ function UncontrolledBattleBoard({ entity, ...rest }) {
45971
46297
  var init_UncontrolledBattleBoard = __esm({
45972
46298
  "components/game/organisms/UncontrolledBattleBoard.tsx"() {
45973
46299
  init_BattleBoard();
46300
+ init_boardEntity();
45974
46301
  init_useBattleState();
45975
46302
  UncontrolledBattleBoard.displayName = "UncontrolledBattleBoard";
45976
46303
  }
45977
46304
  });
46305
+ function heroPosition(h) {
46306
+ return vec2(h.position);
46307
+ }
46308
+ function heroOwner(h) {
46309
+ return str(h.owner);
46310
+ }
46311
+ function heroMovement(h) {
46312
+ return num(h.movement);
46313
+ }
46314
+ function hexPassable(h) {
46315
+ return h.passable !== false;
46316
+ }
45978
46317
  function defaultIsInRange(from, to, range) {
45979
46318
  return Math.abs(from.x - to.x) + Math.abs(from.y - to.y) <= range;
45980
46319
  }
@@ -46005,36 +46344,36 @@ function WorldMapBoard({
46005
46344
  className
46006
46345
  }) {
46007
46346
  const eventBus = useEventBus();
46008
- const resolved = Array.isArray(entity) ? entity[0] : entity;
46009
- const hexes = resolved?.hexes ?? [];
46010
- const heroes = resolved?.heroes ?? [];
46011
- const features = resolved?.features ?? [];
46012
- const selectedHeroId = resolved?.selectedHeroId;
46347
+ const resolved = boardEntity(entity);
46348
+ const hexes = rows(resolved?.hexes);
46349
+ const heroes = rows(resolved?.heroes);
46350
+ const features = Array.isArray(resolved?.features) ? resolved.features : [];
46351
+ const selectedHeroId = resolved?.selectedHeroId ?? null;
46013
46352
  const assetManifest = resolved?.assetManifest;
46014
46353
  const backgroundImage = resolved?.backgroundImage;
46015
46354
  const [hoveredTile, setHoveredTile] = useState(null);
46016
46355
  const selectedHero = useMemo(
46017
- () => heroes.find((h) => h.id === selectedHeroId) ?? null,
46356
+ () => heroes.find((h) => str(h.id) === selectedHeroId) ?? null,
46018
46357
  [heroes, selectedHeroId]
46019
46358
  );
46020
46359
  const tiles = useMemo(
46021
46360
  () => hexes.map((hex) => ({
46022
- x: hex.x,
46023
- y: hex.y,
46024
- terrain: hex.terrain,
46025
- terrainSprite: hex.terrainSprite
46361
+ x: num(hex.x),
46362
+ y: num(hex.y),
46363
+ terrain: str(hex.terrain),
46364
+ terrainSprite: hex.terrainSprite == null ? void 0 : str(hex.terrainSprite)
46026
46365
  })),
46027
46366
  [hexes]
46028
46367
  );
46029
46368
  const baseUnits = useMemo(
46030
46369
  () => heroes.map((hero) => ({
46031
- id: hero.id,
46032
- position: hero.position,
46033
- name: hero.name,
46034
- team: hero.owner === "enemy" ? "enemy" : "player",
46370
+ id: str(hero.id),
46371
+ position: heroPosition(hero),
46372
+ name: str(hero.name),
46373
+ team: heroOwner(hero) === "enemy" ? "enemy" : "player",
46035
46374
  health: 100,
46036
46375
  maxHealth: 100,
46037
- sprite: hero.sprite
46376
+ sprite: hero.sprite == null ? void 0 : str(hero.sprite)
46038
46377
  })),
46039
46378
  [heroes]
46040
46379
  );
@@ -46075,73 +46414,94 @@ function WorldMapBoard({
46075
46414
  const isoUnits = useMemo(() => {
46076
46415
  if (movingPositions.size === 0) return baseUnits;
46077
46416
  return baseUnits.map((u) => {
46078
- const pos = movingPositions.get(u.id);
46417
+ const pos = u.id == null ? void 0 : movingPositions.get(u.id);
46079
46418
  return pos ? { ...u, position: pos } : u;
46080
46419
  });
46081
46420
  }, [baseUnits, movingPositions]);
46082
46421
  const validMoves = useMemo(() => {
46083
- if (!selectedHero || selectedHero.movement <= 0) return [];
46422
+ if (!selectedHero || heroMovement(selectedHero) <= 0) return [];
46423
+ const sp = heroPosition(selectedHero);
46424
+ const sOwner = heroOwner(selectedHero);
46425
+ const range = heroMovement(selectedHero);
46084
46426
  const moves = [];
46085
46427
  hexes.forEach((hex) => {
46086
- if (hex.passable === false) return;
46087
- if (hex.x === selectedHero.position.x && hex.y === selectedHero.position.y) return;
46088
- if (!isInRange(selectedHero.position, { x: hex.x, y: hex.y }, selectedHero.movement)) return;
46089
- if (heroes.some((h) => h.position.x === hex.x && h.position.y === hex.y && h.owner === selectedHero.owner)) return;
46090
- moves.push({ x: hex.x, y: hex.y });
46428
+ const hx = num(hex.x);
46429
+ const hy = num(hex.y);
46430
+ if (!hexPassable(hex)) return;
46431
+ if (hx === sp.x && hy === sp.y) return;
46432
+ if (!isInRange(sp, { x: hx, y: hy }, range)) return;
46433
+ if (heroes.some((h) => {
46434
+ const hp = heroPosition(h);
46435
+ return hp.x === hx && hp.y === hy && heroOwner(h) === sOwner;
46436
+ })) return;
46437
+ moves.push({ x: hx, y: hy });
46091
46438
  });
46092
46439
  return moves;
46093
46440
  }, [selectedHero, hexes, heroes, isInRange]);
46094
46441
  const attackTargets = useMemo(() => {
46095
- if (!selectedHero || selectedHero.movement <= 0) return [];
46096
- return heroes.filter((h) => h.owner !== selectedHero.owner).filter((h) => isInRange(selectedHero.position, h.position, selectedHero.movement)).map((h) => h.position);
46442
+ if (!selectedHero || heroMovement(selectedHero) <= 0) return [];
46443
+ const sp = heroPosition(selectedHero);
46444
+ const sOwner = heroOwner(selectedHero);
46445
+ const range = heroMovement(selectedHero);
46446
+ return heroes.filter((h) => heroOwner(h) !== sOwner).filter((h) => isInRange(sp, heroPosition(h), range)).map((h) => heroPosition(h));
46097
46447
  }, [selectedHero, heroes, isInRange]);
46098
- const maxY = Math.max(...hexes.map((h) => h.y), 0);
46448
+ const maxY = Math.max(...hexes.map((h) => num(h.y)), 0);
46099
46449
  const baseOffsetX = (maxY + 1) * (TILE_WIDTH * scale / 2);
46100
46450
  const tileToScreen = useCallback(
46101
46451
  (tx, ty) => isoToScreen(tx, ty, scale, baseOffsetX),
46102
46452
  [scale, baseOffsetX]
46103
46453
  );
46104
46454
  const hoveredHex = useMemo(
46105
- () => hoveredTile ? hexes.find((h) => h.x === hoveredTile.x && h.y === hoveredTile.y) ?? null : null,
46455
+ () => hoveredTile ? hexes.find((h) => num(h.x) === hoveredTile.x && num(h.y) === hoveredTile.y) ?? null : null,
46106
46456
  [hoveredTile, hexes]
46107
46457
  );
46108
46458
  const hoveredHero = useMemo(
46109
- () => hoveredTile ? heroes.find((h) => h.position.x === hoveredTile.x && h.position.y === hoveredTile.y) ?? null : null,
46459
+ () => hoveredTile ? heroes.find((h) => {
46460
+ const hp = heroPosition(h);
46461
+ return hp.x === hoveredTile.x && hp.y === hoveredTile.y;
46462
+ }) ?? null : null,
46110
46463
  [hoveredTile, heroes]
46111
46464
  );
46112
46465
  const handleTileClick = useCallback((x, y) => {
46113
46466
  if (movementAnimRef.current) return;
46114
- const hex = hexes.find((h) => h.x === x && h.y === y);
46467
+ const hex = hexes.find((h) => num(h.x) === x && num(h.y) === y);
46115
46468
  if (!hex) return;
46116
46469
  if (tileClickEvent) {
46117
46470
  eventBus.emit(`UI:${tileClickEvent}`, { x, y });
46118
46471
  }
46119
46472
  if (selectedHero && validMoves.some((m) => m.x === x && m.y === y)) {
46120
- startMoveAnimation(selectedHero.id, { ...selectedHero.position }, { x, y }, () => {
46121
- onHeroMove?.(selectedHero.id, x, y);
46473
+ const heroId = str(selectedHero.id);
46474
+ startMoveAnimation(heroId, { ...heroPosition(selectedHero) }, { x, y }, () => {
46475
+ onHeroMove?.(heroId, x, y);
46122
46476
  if (heroMoveEvent) {
46123
- eventBus.emit(`UI:${heroMoveEvent}`, { heroId: selectedHero.id, toX: x, toY: y });
46477
+ eventBus.emit(`UI:${heroMoveEvent}`, { heroId, toX: x, toY: y });
46124
46478
  }
46125
- if (hex.feature && hex.feature !== "none") {
46126
- onFeatureEnter?.(selectedHero.id, hex);
46479
+ const feature = str(hex.feature);
46480
+ if (feature && feature !== "none") {
46481
+ onFeatureEnter?.(heroId, hex);
46127
46482
  if (featureEnterEvent) {
46128
- eventBus.emit(`UI:${featureEnterEvent}`, { heroId: selectedHero.id, feature: hex.feature, hex });
46483
+ eventBus.emit(`UI:${featureEnterEvent}`, { heroId, feature, hex });
46129
46484
  }
46130
46485
  }
46131
46486
  });
46132
46487
  return;
46133
46488
  }
46134
- const enemy = heroes.find((h) => h.position.x === x && h.position.y === y && h.owner === "enemy");
46489
+ const enemy = heroes.find((h) => {
46490
+ const hp = heroPosition(h);
46491
+ return hp.x === x && hp.y === y && heroOwner(h) === "enemy";
46492
+ });
46135
46493
  if (selectedHero && enemy && attackTargets.some((t) => t.x === x && t.y === y)) {
46136
- onBattleEncounter?.(selectedHero.id, enemy.id);
46494
+ const attackerId = str(selectedHero.id);
46495
+ const defenderId = str(enemy.id);
46496
+ onBattleEncounter?.(attackerId, defenderId);
46137
46497
  if (battleEncounterEvent) {
46138
- eventBus.emit(`UI:${battleEncounterEvent}`, { attackerId: selectedHero.id, defenderId: enemy.id });
46498
+ eventBus.emit(`UI:${battleEncounterEvent}`, { attackerId, defenderId });
46139
46499
  }
46140
46500
  }
46141
46501
  }, [hexes, heroes, selectedHero, validMoves, attackTargets, startMoveAnimation, onHeroMove, onFeatureEnter, onBattleEncounter, eventBus, tileClickEvent, heroMoveEvent, featureEnterEvent, battleEncounterEvent]);
46142
46502
  const handleUnitClick = useCallback((unitId) => {
46143
- const hero = heroes.find((h) => h.id === unitId);
46144
- if (hero && (hero.owner === "player" || allowMoveAllHeroes)) {
46503
+ const hero = heroes.find((h) => str(h.id) === unitId);
46504
+ if (hero && (heroOwner(hero) === "player" || allowMoveAllHeroes)) {
46145
46505
  onHeroSelect?.(unitId);
46146
46506
  if (heroSelectEvent) {
46147
46507
  eventBus.emit(`UI:${heroSelectEvent}`, { heroId: unitId });
@@ -46214,6 +46574,7 @@ var init_WorldMapBoard = __esm({
46214
46574
  init_Stack();
46215
46575
  init_LoadingState();
46216
46576
  init_IsometricCanvas2();
46577
+ init_boardEntity();
46217
46578
  init_isometric();
46218
46579
  WorldMapBoard.displayName = "WorldMapBoard";
46219
46580
  }
@@ -46317,12 +46678,12 @@ var init_XPBar = __esm({
46317
46678
  }
46318
46679
  });
46319
46680
  function lazyThree(name, loader) {
46320
- const Lazy = React79__default.lazy(() => loader().then((m) => ({ default: m[name] })));
46681
+ const Lazy = React80__default.lazy(() => loader().then((m) => ({ default: m[name] })));
46321
46682
  function ThreeWrapper(props) {
46322
- return React79__default.createElement(
46323
- React79__default.Suspense,
46683
+ return React80__default.createElement(
46684
+ React80__default.Suspense,
46324
46685
  { fallback: null },
46325
- React79__default.createElement(Lazy, props)
46686
+ React80__default.createElement(Lazy, props)
46326
46687
  );
46327
46688
  }
46328
46689
  ThreeWrapper.displayName = `Lazy(${name})`;
@@ -46337,7 +46698,7 @@ var init_component_registry_generated = __esm({
46337
46698
  init_ActionButtons();
46338
46699
  init_ActionPalette();
46339
46700
  init_ActionTile();
46340
- init_AnimatedCounter();
46701
+ init_AnimatedCounter2();
46341
46702
  init_AnimatedGraphic();
46342
46703
  init_AnimatedReveal();
46343
46704
  init_ArticleSection();
@@ -46608,7 +46969,7 @@ var init_component_registry_generated = __esm({
46608
46969
  "ActionTile": ActionTile,
46609
46970
  "Alert": AlertPattern,
46610
46971
  "AlertPattern": AlertPattern,
46611
- "AnimatedCounter": AnimatedCounter,
46972
+ "AnimatedCounter": AnimatedCounter2,
46612
46973
  "AnimatedGraphic": AnimatedGraphic,
46613
46974
  "AnimatedReveal": AnimatedReveal,
46614
46975
  "ArticleSection": ArticleSection,
@@ -46938,7 +47299,7 @@ function SuspenseConfigProvider({
46938
47299
  config,
46939
47300
  children
46940
47301
  }) {
46941
- return React79__default.createElement(
47302
+ return React80__default.createElement(
46942
47303
  SuspenseConfigContext.Provider,
46943
47304
  { value: config },
46944
47305
  children
@@ -47423,7 +47784,7 @@ function renderPatternChildren(children, onDismiss, parentId = "root", parentPat
47423
47784
  const key = `${parentId}-${index}-trait:${traitName}`;
47424
47785
  return /* @__PURE__ */ jsx(TraitFrame, { traitName }, key);
47425
47786
  }
47426
- return /* @__PURE__ */ jsx(React79__default.Fragment, { children: child }, `${parentId}-${index}`);
47787
+ return /* @__PURE__ */ jsx(React80__default.Fragment, { children: child }, `${parentId}-${index}`);
47427
47788
  }
47428
47789
  if (!child || typeof child !== "object") return null;
47429
47790
  const childId = `${parentId}-${index}`;
@@ -47463,14 +47824,14 @@ function isPatternConfig(value) {
47463
47824
  if (value === null || value === void 0) return false;
47464
47825
  if (typeof value !== "object") return false;
47465
47826
  if (Array.isArray(value)) return false;
47466
- if (React79__default.isValidElement(value)) return false;
47827
+ if (React80__default.isValidElement(value)) return false;
47467
47828
  if (value instanceof Date) return false;
47468
47829
  if (typeof value === "function") return false;
47469
47830
  const record = value;
47470
47831
  return "type" in record && typeof record.type === "string";
47471
47832
  }
47472
47833
  function isPlainConfigObject(value) {
47473
- if (React79__default.isValidElement(value)) return false;
47834
+ if (React80__default.isValidElement(value)) return false;
47474
47835
  if (value instanceof Date) return false;
47475
47836
  const proto = Object.getPrototypeOf(value);
47476
47837
  return proto === Object.prototype || proto === null;