@almadar/ui 5.70.0 → 5.72.0

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 (63) hide show
  1. package/dist/avl/index.cjs +2198 -2218
  2. package/dist/avl/index.d.cts +93 -56
  3. package/dist/avl/index.js +931 -951
  4. package/dist/components/avl/molecules/AvlEventWireEdge.d.ts +2 -1
  5. package/dist/components/avl/molecules/AvlTransitionEdge.d.ts +2 -1
  6. package/dist/components/avl/molecules/avl-behavior-compose-converter.d.ts +7 -5
  7. package/dist/components/avl/molecules/avl-behavior-compose-types.d.ts +41 -21
  8. package/dist/components/avl/molecules/avl-canvas-types.d.ts +10 -7
  9. package/dist/components/avl/molecules/avl-preview-converter.d.ts +5 -5
  10. package/dist/components/avl/molecules/avl-preview-types.d.ts +15 -4
  11. package/dist/components/avl/organisms/FlowCanvas.d.ts +2 -2
  12. package/dist/components/avl/organisms/avl-schema-parser.d.ts +18 -16
  13. package/dist/components/core/atoms/Button.d.ts +2 -0
  14. package/dist/components/core/atoms/ConditionalWrapper.d.ts +5 -4
  15. package/dist/components/core/molecules/Carousel.d.ts +2 -2
  16. package/dist/components/core/molecules/OrbitalVisualization.d.ts +4 -3
  17. package/dist/components/core/molecules/PageHeader.d.ts +3 -3
  18. package/dist/components/core/molecules/RepeatableFormSection.d.ts +4 -3
  19. package/dist/components/core/molecules/ViolationAlert.d.ts +2 -0
  20. package/dist/components/core/molecules/WizardContainer.d.ts +23 -22
  21. package/dist/components/core/organisms/CardGrid.d.ts +2 -2
  22. package/dist/components/core/organisms/CustomPattern.d.ts +3 -4
  23. package/dist/components/core/organisms/DataTable.d.ts +2 -2
  24. package/dist/components/core/organisms/DetailPanel.d.ts +1 -1
  25. package/dist/components/core/organisms/Form.d.ts +11 -11
  26. package/dist/components/core/organisms/List.d.ts +3 -5
  27. package/dist/components/core/organisms/StatCard.d.ts +2 -2
  28. package/dist/components/core/organisms/book/types.d.ts +1 -1
  29. package/dist/components/core/organisms/debug/RuntimeDebugger.d.ts +2 -1
  30. package/dist/components/core/organisms/debug/tabs/EventDispatcherTab.d.ts +2 -1
  31. package/dist/components/core/organisms/layout/DashboardGrid.d.ts +0 -2
  32. package/dist/components/core/organisms/types.d.ts +3 -2
  33. package/dist/components/game/atoms/ScoreDisplay.d.ts +3 -3
  34. package/dist/components/game/atoms/Sprite.d.ts +6 -1
  35. package/dist/components/game/atoms/XPBar.d.ts +1 -1
  36. package/dist/components/game/molecules/GameCanvas3D.d.ts +0 -2
  37. package/dist/components/game/molecules/IsometricCanvas.d.ts +4 -2
  38. package/dist/components/game/molecules/PlatformerCanvas.d.ts +4 -1
  39. package/dist/components/game/molecules/StatBadge.d.ts +3 -1
  40. package/dist/components/game/molecules/three/hooks/useSceneGraph.d.ts +2 -1
  41. package/dist/components/game/molecules/three/index.cjs +41 -105
  42. package/dist/components/game/molecules/three/index.js +41 -105
  43. package/dist/components/game/molecules/useUnitSpriteAtlas.d.ts +3 -2
  44. package/dist/components/game/organisms/PinballBoard.d.ts +4 -4
  45. package/dist/components/game/organisms/boardEntity.d.ts +6 -6
  46. package/dist/components/game/organisms/puzzles/debugger/DebuggerBoard.d.ts +16 -2
  47. package/dist/components/game/organisms/puzzles/event-handler/puzzleObject.d.ts +21 -10
  48. package/dist/components/game/organisms/puzzles/state-architect/StateJsonView.d.ts +2 -1
  49. package/dist/components/game/organisms/types/isometric.d.ts +16 -0
  50. package/dist/components/index.cjs +2228 -2251
  51. package/dist/components/index.js +1116 -1139
  52. package/dist/docs/index.cjs +107 -104
  53. package/dist/docs/index.d.cts +2 -0
  54. package/dist/docs/index.js +38 -35
  55. package/dist/lib/getNestedValue.d.ts +2 -13
  56. package/dist/marketing/index.cjs +97 -98
  57. package/dist/marketing/index.d.cts +2 -0
  58. package/dist/marketing/index.js +54 -55
  59. package/dist/providers/index.cjs +1908 -1951
  60. package/dist/providers/index.js +808 -851
  61. package/dist/runtime/index.cjs +1966 -2009
  62. package/dist/runtime/index.js +814 -857
  63. package/package.json +1 -1
@@ -1,6 +1,6 @@
1
1
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
2
- import * as React80 from 'react';
3
- import React80__default, { useContext, useMemo, useRef, useEffect, useCallback, useState, Suspense, lazy, createContext, useLayoutEffect, useId, forwardRef, useImperativeHandle, useSyncExternalStore, Component } from 'react';
2
+ import * as React85 from 'react';
3
+ import React85__default, { useContext, useMemo, useRef, useEffect, useCallback, useState, Suspense, lazy, createContext, useLayoutEffect, useId, forwardRef, useImperativeHandle, useSyncExternalStore, Component } 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';
@@ -234,7 +234,7 @@ var init_SvgFlow = __esm({
234
234
  width = 100,
235
235
  height = 100
236
236
  }) => {
237
- const markerId = React80__default.useMemo(() => {
237
+ const markerId = React85__default.useMemo(() => {
238
238
  flowIdCounter += 1;
239
239
  return `almadar-flow-arrow-${flowIdCounter}`;
240
240
  }, []);
@@ -827,7 +827,7 @@ var init_SvgRing = __esm({
827
827
  width = 100,
828
828
  height = 100
829
829
  }) => {
830
- const gradientId = React80__default.useMemo(() => {
830
+ const gradientId = React85__default.useMemo(() => {
831
831
  ringIdCounter += 1;
832
832
  return `almadar-ring-glow-${ringIdCounter}`;
833
833
  }, []);
@@ -1239,7 +1239,7 @@ function loadLib(key, importer) {
1239
1239
  return p2;
1240
1240
  }
1241
1241
  function lazyFamilyIcon(libKey, importer, pick, fallbackName, family) {
1242
- const Lazy = React80__default.lazy(async () => {
1242
+ const Lazy = React85__default.lazy(async () => {
1243
1243
  const lib = await loadLib(libKey, importer);
1244
1244
  const Comp = pick(lib);
1245
1245
  if (!Comp) {
@@ -1249,7 +1249,7 @@ function lazyFamilyIcon(libKey, importer, pick, fallbackName, family) {
1249
1249
  return { default: Comp };
1250
1250
  });
1251
1251
  const Wrapped = (props) => /* @__PURE__ */ jsx(
1252
- React80__default.Suspense,
1252
+ React85__default.Suspense,
1253
1253
  {
1254
1254
  fallback: /* @__PURE__ */ jsx(
1255
1255
  "span",
@@ -1917,9 +1917,10 @@ function resolveIcon(name) {
1917
1917
  function doResolve(name) {
1918
1918
  if (iconAliases[name]) return iconAliases[name];
1919
1919
  const pascalName = kebabToPascal2(name);
1920
- const directLookup = LucideIcons2[pascalName];
1920
+ const lucideMap = LucideIcons2;
1921
+ const directLookup = lucideMap[pascalName];
1921
1922
  if (directLookup && typeof directLookup === "object") return directLookup;
1922
- const asIs = LucideIcons2[name];
1923
+ const asIs = lucideMap[name];
1923
1924
  if (asIs && typeof asIs === "object") return asIs;
1924
1925
  return LucideIcons2.HelpCircle;
1925
1926
  }
@@ -1975,7 +1976,7 @@ var init_Icon = __esm({
1975
1976
  const directIcon = typeof icon === "string" ? void 0 : icon;
1976
1977
  const effectiveName = typeof icon === "string" ? icon : name;
1977
1978
  const family = useIconFamily();
1978
- const RenderedComponent = React80__default.useMemo(() => {
1979
+ const RenderedComponent = React85__default.useMemo(() => {
1979
1980
  if (directIcon) return null;
1980
1981
  return effectiveName ? resolveIconForFamily(effectiveName, family) : null;
1981
1982
  }, [directIcon, effectiveName, family]);
@@ -2025,6 +2026,9 @@ var init_Icon = __esm({
2025
2026
  Icon.displayName = "Icon";
2026
2027
  }
2027
2028
  });
2029
+ function isIconLike(v) {
2030
+ return typeof v.render === "function";
2031
+ }
2028
2032
  function resolveIconProp(value, sizeClass) {
2029
2033
  if (!value) return null;
2030
2034
  if (typeof value === "string") {
@@ -2034,10 +2038,10 @@ function resolveIconProp(value, sizeClass) {
2034
2038
  const IconComp = value;
2035
2039
  return /* @__PURE__ */ jsx(IconComp, { className: sizeClass });
2036
2040
  }
2037
- if (React80__default.isValidElement(value)) {
2041
+ if (React85__default.isValidElement(value)) {
2038
2042
  return value;
2039
2043
  }
2040
- if (typeof value === "object" && value !== null && "render" in value) {
2044
+ if (typeof value === "object" && value !== null && isIconLike(value)) {
2041
2045
  const IconComp = value;
2042
2046
  return /* @__PURE__ */ jsx(IconComp, { className: sizeClass });
2043
2047
  }
@@ -2110,7 +2114,7 @@ var init_Button = __esm({
2110
2114
  md: "h-icon-default w-icon-default",
2111
2115
  lg: "h-icon-default w-icon-default"
2112
2116
  };
2113
- Button = React80__default.forwardRef(
2117
+ Button = React85__default.forwardRef(
2114
2118
  ({
2115
2119
  className,
2116
2120
  variant = "primary",
@@ -2126,6 +2130,7 @@ var init_Button = __esm({
2126
2130
  label,
2127
2131
  children,
2128
2132
  onClick,
2133
+ "data-testid": dataTestId,
2129
2134
  ...props
2130
2135
  }, ref) => {
2131
2136
  const eventBus = useEventBus();
@@ -2158,7 +2163,7 @@ var init_Button = __esm({
2158
2163
  ),
2159
2164
  onClick: handleClick,
2160
2165
  ...props,
2161
- "data-testid": props["data-testid"] ?? (action ? `action-${action}` : void 0),
2166
+ "data-testid": dataTestId ?? (action ? `action-${action}` : void 0),
2162
2167
  children: [
2163
2168
  isLoading ? /* @__PURE__ */ jsx(Loader2, { className: "h-icon-default w-icon-default animate-spin" }) : resolvedLeftIcon && /* @__PURE__ */ jsx("span", { className: "flex-shrink-0", children: resolvedLeftIcon }),
2164
2169
  children || label,
@@ -2177,7 +2182,7 @@ var init_Input = __esm({
2177
2182
  init_cn();
2178
2183
  init_Icon();
2179
2184
  init_useEventBus();
2180
- Input = React80__default.forwardRef(
2185
+ Input = React85__default.forwardRef(
2181
2186
  ({
2182
2187
  className,
2183
2188
  inputType,
@@ -2337,7 +2342,7 @@ var Label;
2337
2342
  var init_Label = __esm({
2338
2343
  "components/core/atoms/Label.tsx"() {
2339
2344
  init_cn();
2340
- Label = React80__default.forwardRef(
2345
+ Label = React85__default.forwardRef(
2341
2346
  ({ className, required, children, ...props }, ref) => {
2342
2347
  return /* @__PURE__ */ jsxs(
2343
2348
  "label",
@@ -2364,7 +2369,7 @@ var init_Textarea = __esm({
2364
2369
  "components/core/atoms/Textarea.tsx"() {
2365
2370
  init_cn();
2366
2371
  init_useEventBus();
2367
- Textarea = React80__default.forwardRef(
2372
+ Textarea = React85__default.forwardRef(
2368
2373
  ({ className, error, onChange, ...props }, ref) => {
2369
2374
  const eventBus = useEventBus();
2370
2375
  const handleChange = (e) => {
@@ -2603,7 +2608,7 @@ var init_Select = __esm({
2603
2608
  init_cn();
2604
2609
  init_Icon();
2605
2610
  init_useEventBus();
2606
- Select = React80__default.forwardRef(
2611
+ Select = React85__default.forwardRef(
2607
2612
  (props, _ref) => {
2608
2613
  const { multiple, searchable, clearable } = props;
2609
2614
  if (multiple || searchable || clearable) {
@@ -2620,7 +2625,7 @@ var init_Checkbox = __esm({
2620
2625
  "components/core/atoms/Checkbox.tsx"() {
2621
2626
  init_cn();
2622
2627
  init_useEventBus();
2623
- Checkbox = React80__default.forwardRef(
2628
+ Checkbox = React85__default.forwardRef(
2624
2629
  ({ className, label, id, onChange, ...props }, ref) => {
2625
2630
  const inputId = id || `checkbox-${Math.random().toString(36).substr(2, 9)}`;
2626
2631
  const eventBus = useEventBus();
@@ -2674,7 +2679,7 @@ var init_Spinner = __esm({
2674
2679
  md: "h-6 w-6",
2675
2680
  lg: "h-8 w-8"
2676
2681
  };
2677
- Spinner = React80__default.forwardRef(
2682
+ Spinner = React85__default.forwardRef(
2678
2683
  ({ className, size = "md", overlay, ...props }, ref) => {
2679
2684
  if (overlay) {
2680
2685
  return /* @__PURE__ */ jsx(
@@ -2764,7 +2769,7 @@ var init_Card = __esm({
2764
2769
  chip: "shadow-none rounded-pill border-[length:var(--border-width)] border-border",
2765
2770
  "tile-image-first": "p-0 overflow-hidden"
2766
2771
  };
2767
- Card = React80__default.forwardRef(
2772
+ Card = React85__default.forwardRef(
2768
2773
  ({
2769
2774
  className,
2770
2775
  variant = "bordered",
@@ -2812,9 +2817,9 @@ var init_Card = __esm({
2812
2817
  }
2813
2818
  );
2814
2819
  Card.displayName = "Card";
2815
- CardHeader = React80__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("mb-4", className), ...props }));
2820
+ CardHeader = React85__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("mb-4", className), ...props }));
2816
2821
  CardHeader.displayName = "CardHeader";
2817
- CardTitle = React80__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
2822
+ CardTitle = React85__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
2818
2823
  "h3",
2819
2824
  {
2820
2825
  ref,
@@ -2827,11 +2832,11 @@ var init_Card = __esm({
2827
2832
  }
2828
2833
  ));
2829
2834
  CardTitle.displayName = "CardTitle";
2830
- CardContent = React80__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("", className), ...props }));
2835
+ CardContent = React85__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("", className), ...props }));
2831
2836
  CardContent.displayName = "CardContent";
2832
2837
  CardBody = CardContent;
2833
2838
  CardBody.displayName = "CardBody";
2834
- CardFooter = React80__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
2839
+ CardFooter = React85__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
2835
2840
  "div",
2836
2841
  {
2837
2842
  ref,
@@ -2884,7 +2889,7 @@ var init_Badge = __esm({
2884
2889
  md: "px-2.5 py-1 text-sm",
2885
2890
  lg: "px-3 py-1.5 text-base"
2886
2891
  };
2887
- Badge = React80__default.forwardRef(
2892
+ Badge = React85__default.forwardRef(
2888
2893
  ({ className, variant = "default", size = "sm", amount, label, icon, children, onRemove, removeLabel, ...props }, ref) => {
2889
2894
  const iconSizes3 = {
2890
2895
  sm: "h-icon-default w-icon-default",
@@ -2977,7 +2982,7 @@ var init_FilterPill = __esm({
2977
2982
  md: "w-3.5 h-3.5",
2978
2983
  lg: "w-4 h-4"
2979
2984
  };
2980
- FilterPill = React80__default.forwardRef(
2985
+ FilterPill = React85__default.forwardRef(
2981
2986
  ({
2982
2987
  className,
2983
2988
  variant = "default",
@@ -3106,8 +3111,8 @@ var init_Avatar = __esm({
3106
3111
  actionPayload
3107
3112
  }) => {
3108
3113
  const eventBus = useEventBus();
3109
- const [imgFailed, setImgFailed] = React80__default.useState(false);
3110
- React80__default.useEffect(() => {
3114
+ const [imgFailed, setImgFailed] = React85__default.useState(false);
3115
+ React85__default.useEffect(() => {
3111
3116
  setImgFailed(false);
3112
3117
  }, [src]);
3113
3118
  const initials = providedInitials ?? (name ? generateInitials(name) : void 0);
@@ -3359,7 +3364,7 @@ var init_Box = __esm({
3359
3364
  fixed: "fixed",
3360
3365
  sticky: "sticky"
3361
3366
  };
3362
- Box = React80__default.forwardRef(
3367
+ Box = React85__default.forwardRef(
3363
3368
  ({
3364
3369
  padding,
3365
3370
  paddingX,
@@ -3424,7 +3429,7 @@ var init_Box = __esm({
3424
3429
  onPointerDown?.(e);
3425
3430
  }, [hoverEvent, tapReveal, triggerProps, onPointerDown]);
3426
3431
  const isClickable = action || onClick;
3427
- return React80__default.createElement(
3432
+ return React85__default.createElement(
3428
3433
  Component2,
3429
3434
  {
3430
3435
  ref,
@@ -3478,22 +3483,18 @@ var init_Center = __esm({
3478
3483
  as: Component2 = "div"
3479
3484
  }) => {
3480
3485
  const mergedStyle = minHeight ? { minHeight, ...style } : style;
3481
- const Comp = Component2;
3482
- return /* @__PURE__ */ jsx(
3483
- Comp,
3484
- {
3485
- className: cn(
3486
- inline ? "inline-flex" : "flex",
3487
- horizontal && "justify-center",
3488
- vertical && "items-center",
3489
- fullHeight && "h-full",
3490
- fullWidth && "w-full",
3491
- className
3492
- ),
3493
- style: mergedStyle,
3494
- children
3495
- }
3496
- );
3486
+ return React85__default.createElement(Component2, {
3487
+ className: cn(
3488
+ inline ? "inline-flex" : "flex",
3489
+ horizontal && "justify-center",
3490
+ vertical && "items-center",
3491
+ fullHeight && "h-full",
3492
+ fullWidth && "w-full",
3493
+ className
3494
+ ),
3495
+ style: mergedStyle,
3496
+ children
3497
+ });
3497
3498
  };
3498
3499
  }
3499
3500
  });
@@ -3750,7 +3751,7 @@ var init_Radio = __esm({
3750
3751
  md: "w-2.5 h-2.5",
3751
3752
  lg: "w-3 h-3"
3752
3753
  };
3753
- Radio = React80__default.forwardRef(
3754
+ Radio = React85__default.forwardRef(
3754
3755
  ({
3755
3756
  label,
3756
3757
  helperText,
@@ -3767,12 +3768,12 @@ var init_Radio = __esm({
3767
3768
  onChange,
3768
3769
  ...props
3769
3770
  }, ref) => {
3770
- const reactId = React80__default.useId();
3771
+ const reactId = React85__default.useId();
3771
3772
  const baseId = id || `radio-${reactId}`;
3772
3773
  const hasError = !!error;
3773
3774
  const eventBus = useEventBus();
3774
- const [selected, setSelected] = React80__default.useState(value);
3775
- React80__default.useEffect(() => {
3775
+ const [selected, setSelected] = React85__default.useState(value);
3776
+ React85__default.useEffect(() => {
3776
3777
  if (value !== void 0) setSelected(value);
3777
3778
  }, [value]);
3778
3779
  const pick = (next, e) => {
@@ -3954,7 +3955,7 @@ var init_Switch = __esm({
3954
3955
  "components/core/atoms/Switch.tsx"() {
3955
3956
  "use client";
3956
3957
  init_cn();
3957
- Switch = React80.forwardRef(
3958
+ Switch = React85.forwardRef(
3958
3959
  ({
3959
3960
  checked,
3960
3961
  defaultChecked = false,
@@ -3965,10 +3966,10 @@ var init_Switch = __esm({
3965
3966
  name,
3966
3967
  className
3967
3968
  }, ref) => {
3968
- const [isChecked, setIsChecked] = React80.useState(
3969
+ const [isChecked, setIsChecked] = React85.useState(
3969
3970
  checked !== void 0 ? checked : defaultChecked
3970
3971
  );
3971
- React80.useEffect(() => {
3972
+ React85.useEffect(() => {
3972
3973
  if (checked !== void 0) {
3973
3974
  setIsChecked(checked);
3974
3975
  }
@@ -4127,9 +4128,8 @@ var init_Stack = __esm({
4127
4128
  };
4128
4129
  const isHorizontal = direction === "horizontal";
4129
4130
  const directionClass = responsive && isHorizontal ? reverse ? "flex-col-reverse md:flex-row-reverse" : "flex-col md:flex-row" : isHorizontal ? reverse ? "flex-row-reverse" : "flex-row" : reverse ? "flex-col-reverse" : "flex-col";
4130
- const Comp = Component2;
4131
- return /* @__PURE__ */ jsx(
4132
- Comp,
4131
+ return React85__default.createElement(
4132
+ Component2,
4133
4133
  {
4134
4134
  className: cn(
4135
4135
  "flex",
@@ -4145,9 +4145,9 @@ var init_Stack = __esm({
4145
4145
  onClick: action || onClick ? handleClick : void 0,
4146
4146
  onKeyDown,
4147
4147
  role,
4148
- tabIndex,
4149
- children
4150
- }
4148
+ tabIndex
4149
+ },
4150
+ children
4151
4151
  );
4152
4152
  };
4153
4153
  VStack = (props) => /* @__PURE__ */ jsx(Stack, { direction: "vertical", ...props });
@@ -4324,9 +4324,8 @@ var init_Typography = __esm({
4324
4324
  }) => {
4325
4325
  const variant = variantProp ?? (level ? `h${level}` : "body1");
4326
4326
  const Component2 = as || defaultElements[variant];
4327
- const Comp = Component2;
4328
- return /* @__PURE__ */ jsx(
4329
- Comp,
4327
+ return React85__default.createElement(
4328
+ Component2,
4330
4329
  {
4331
4330
  id,
4332
4331
  className: cn(
@@ -4339,9 +4338,9 @@ var init_Typography = __esm({
4339
4338
  overflow && overflowStyles2[overflow],
4340
4339
  className
4341
4340
  ),
4342
- style,
4343
- children: children ?? content
4344
- }
4341
+ style
4342
+ },
4343
+ children ?? content
4345
4344
  );
4346
4345
  };
4347
4346
  Typography.displayName = "Typography";
@@ -4625,7 +4624,7 @@ var Dialog;
4625
4624
  var init_Dialog = __esm({
4626
4625
  "components/core/atoms/Dialog.tsx"() {
4627
4626
  init_cn();
4628
- Dialog = React80__default.forwardRef(
4627
+ Dialog = React85__default.forwardRef(
4629
4628
  ({
4630
4629
  role = "dialog",
4631
4630
  "aria-modal": ariaModal = true,
@@ -4651,7 +4650,7 @@ var Aside;
4651
4650
  var init_Aside = __esm({
4652
4651
  "components/core/atoms/Aside.tsx"() {
4653
4652
  init_cn();
4654
- Aside = React80__default.forwardRef(
4653
+ Aside = React85__default.forwardRef(
4655
4654
  ({ className, children, ...rest }, ref) => /* @__PURE__ */ jsx("aside", { ref, className: cn(className), ...rest, children })
4656
4655
  );
4657
4656
  Aside.displayName = "Aside";
@@ -4730,9 +4729,9 @@ var init_LawReferenceTooltip = __esm({
4730
4729
  className
4731
4730
  }) => {
4732
4731
  const { t } = useTranslate();
4733
- const [isVisible, setIsVisible] = React80__default.useState(false);
4734
- const timeoutRef = React80__default.useRef(null);
4735
- const triggerRef = React80__default.useRef(null);
4732
+ const [isVisible, setIsVisible] = React85__default.useState(false);
4733
+ const timeoutRef = React85__default.useRef(null);
4734
+ const triggerRef = React85__default.useRef(null);
4736
4735
  const handleMouseEnter = () => {
4737
4736
  if (timeoutRef.current) clearTimeout(timeoutRef.current);
4738
4737
  timeoutRef.current = setTimeout(() => setIsVisible(true), 200);
@@ -4743,7 +4742,7 @@ var init_LawReferenceTooltip = __esm({
4743
4742
  };
4744
4743
  const { revealed, triggerProps } = useTapReveal({ refs: [triggerRef] });
4745
4744
  const open = isVisible || revealed;
4746
- React80__default.useEffect(() => {
4745
+ React85__default.useEffect(() => {
4747
4746
  return () => {
4748
4747
  if (timeoutRef.current) clearTimeout(timeoutRef.current);
4749
4748
  };
@@ -4955,7 +4954,7 @@ var init_StatusDot = __esm({
4955
4954
  md: "w-2.5 h-2.5",
4956
4955
  lg: "w-3 h-3"
4957
4956
  };
4958
- StatusDot = React80__default.forwardRef(
4957
+ StatusDot = React85__default.forwardRef(
4959
4958
  ({ className, status = "offline", pulse = false, size = "md", label, ...props }, ref) => {
4960
4959
  return /* @__PURE__ */ jsx(
4961
4960
  "span",
@@ -5009,7 +5008,7 @@ var init_TrendIndicator = __esm({
5009
5008
  down: "trending-down",
5010
5009
  flat: "arrow-right"
5011
5010
  };
5012
- TrendIndicator = React80__default.forwardRef(
5011
+ TrendIndicator = React85__default.forwardRef(
5013
5012
  ({
5014
5013
  className,
5015
5014
  value,
@@ -5076,7 +5075,7 @@ var init_RangeSlider = __esm({
5076
5075
  md: "w-4 h-4",
5077
5076
  lg: "w-5 h-5"
5078
5077
  };
5079
- RangeSlider = React80__default.forwardRef(
5078
+ RangeSlider = React85__default.forwardRef(
5080
5079
  ({
5081
5080
  className,
5082
5081
  min = 0,
@@ -5672,7 +5671,7 @@ var init_ContentSection = __esm({
5672
5671
  md: "py-16",
5673
5672
  lg: "py-24"
5674
5673
  };
5675
- ContentSection = React80__default.forwardRef(
5674
+ ContentSection = React85__default.forwardRef(
5676
5675
  ({ children, background = "default", padding = "lg", id, className }, ref) => {
5677
5676
  return /* @__PURE__ */ jsx(
5678
5677
  Box,
@@ -6206,7 +6205,7 @@ var init_AnimatedReveal = __esm({
6206
6205
  "scale-up": { opacity: 1, transform: "scale(1) translateY(0)" },
6207
6206
  "none": {}
6208
6207
  };
6209
- AnimatedReveal = React80__default.forwardRef(
6208
+ AnimatedReveal = React85__default.forwardRef(
6210
6209
  ({
6211
6210
  trigger = "scroll",
6212
6211
  animation = "fade-up",
@@ -6366,7 +6365,7 @@ var init_AnimatedGraphic = __esm({
6366
6365
  "components/marketing/atoms/AnimatedGraphic.tsx"() {
6367
6366
  "use client";
6368
6367
  init_cn();
6369
- AnimatedGraphic = React80__default.forwardRef(
6368
+ AnimatedGraphic = React85__default.forwardRef(
6370
6369
  ({
6371
6370
  src,
6372
6371
  svgContent,
@@ -6389,7 +6388,7 @@ var init_AnimatedGraphic = __esm({
6389
6388
  const fetchedSvg = useFetchedSvg(svgContent ? void 0 : src);
6390
6389
  const resolvedSvg = svgContent ?? fetchedSvg;
6391
6390
  const prevAnimateRef = useRef(animate);
6392
- const setRef = React80__default.useCallback(
6391
+ const setRef = React85__default.useCallback(
6393
6392
  (node) => {
6394
6393
  containerRef.current = node;
6395
6394
  if (typeof ref === "function") ref(node);
@@ -7071,7 +7070,7 @@ var init_ErrorBoundary = __esm({
7071
7070
  }
7072
7071
  );
7073
7072
  };
7074
- ErrorBoundary = class extends React80__default.Component {
7073
+ ErrorBoundary = class extends React85__default.Component {
7075
7074
  constructor(props) {
7076
7075
  super(props);
7077
7076
  __publicField(this, "reset", () => {
@@ -7369,9 +7368,8 @@ var init_Container = __esm({
7369
7368
  as: Component2 = "div"
7370
7369
  }) => {
7371
7370
  const resolvedSize = maxWidth ?? size ?? "lg";
7372
- const Comp = Component2;
7373
- return /* @__PURE__ */ jsx(
7374
- Comp,
7371
+ return React85__default.createElement(
7372
+ Component2,
7375
7373
  {
7376
7374
  className: cn(
7377
7375
  "w-full",
@@ -7379,9 +7377,9 @@ var init_Container = __esm({
7379
7377
  paddingStyles3[padding],
7380
7378
  center && "mx-auto",
7381
7379
  className
7382
- ),
7383
- children
7384
- }
7380
+ )
7381
+ },
7382
+ children
7385
7383
  );
7386
7384
  };
7387
7385
  Container.displayName = "Container";
@@ -8191,9 +8189,9 @@ function ControlButton({
8191
8189
  className
8192
8190
  }) {
8193
8191
  const eventBus = useEventBus();
8194
- const [isPressed, setIsPressed] = React80.useState(false);
8192
+ const [isPressed, setIsPressed] = React85.useState(false);
8195
8193
  const actualPressed = pressed ?? isPressed;
8196
- const handlePointerDown = React80.useCallback(
8194
+ const handlePointerDown = React85.useCallback(
8197
8195
  (e) => {
8198
8196
  e.preventDefault();
8199
8197
  if (disabled) return;
@@ -8203,7 +8201,7 @@ function ControlButton({
8203
8201
  },
8204
8202
  [disabled, pressEvent, eventBus, onPress]
8205
8203
  );
8206
- const handlePointerUp = React80.useCallback(
8204
+ const handlePointerUp = React85.useCallback(
8207
8205
  (e) => {
8208
8206
  e.preventDefault();
8209
8207
  if (disabled) return;
@@ -8213,7 +8211,7 @@ function ControlButton({
8213
8211
  },
8214
8212
  [disabled, releaseEvent, eventBus, onRelease]
8215
8213
  );
8216
- const handlePointerLeave = React80.useCallback(
8214
+ const handlePointerLeave = React85.useCallback(
8217
8215
  (e) => {
8218
8216
  if (isPressed) {
8219
8217
  setIsPressed(false);
@@ -8301,8 +8299,8 @@ function ActionButtons({
8301
8299
  disabled
8302
8300
  }) {
8303
8301
  const eventBus = useEventBus();
8304
- const [activeButtons, setActiveButtons] = React80.useState(/* @__PURE__ */ new Set());
8305
- const handlePress = React80.useCallback(
8302
+ const [activeButtons, setActiveButtons] = React85.useState(/* @__PURE__ */ new Set());
8303
+ const handlePress = React85.useCallback(
8306
8304
  (id) => {
8307
8305
  setActiveButtons((prev) => new Set(prev).add(id));
8308
8306
  if (actionEvent) eventBus.emit(`UI:${actionEvent}`, { id, pressed: true });
@@ -8310,7 +8308,7 @@ function ActionButtons({
8310
8308
  },
8311
8309
  [actionEvent, eventBus, onAction]
8312
8310
  );
8313
- const handleRelease = React80.useCallback(
8311
+ const handleRelease = React85.useCallback(
8314
8312
  (id) => {
8315
8313
  setActiveButtons((prev) => {
8316
8314
  const next = new Set(prev);
@@ -9140,48 +9138,185 @@ var init_AuthLayout = __esm({
9140
9138
  AuthLayout.displayName = "AuthLayout";
9141
9139
  }
9142
9140
  });
9143
- var LoadingState;
9144
- var init_LoadingState = __esm({
9145
- "components/core/molecules/LoadingState.tsx"() {
9146
- "use client";
9147
- init_cn();
9148
- init_atoms2();
9149
- init_Stack();
9150
- init_Typography();
9151
- LoadingState = ({
9152
- title,
9153
- message,
9154
- className
9155
- }) => {
9156
- const { t } = useTranslate();
9157
- const displayMessage = message ?? t("common.loading");
9158
- return /* @__PURE__ */ jsxs(
9159
- VStack,
9141
+ function MiniMap({
9142
+ tiles = DEFAULT_TILES,
9143
+ units = DEFAULT_UNITS,
9144
+ width = 150,
9145
+ height = 150,
9146
+ mapWidth = 100,
9147
+ mapHeight = 100,
9148
+ viewportRect = DEFAULT_VIEWPORT,
9149
+ className
9150
+ }) {
9151
+ const canvasRef = React85.useRef(null);
9152
+ const frameRef = React85.useRef(0);
9153
+ React85.useEffect(() => {
9154
+ const canvas = canvasRef.current;
9155
+ if (!canvas) return;
9156
+ const ctx = canvas.getContext("2d");
9157
+ if (!ctx) return;
9158
+ const scaleX = width / mapWidth;
9159
+ const scaleY = height / mapHeight;
9160
+ let blinkOn = true;
9161
+ let animFrame;
9162
+ function draw() {
9163
+ if (!ctx) return;
9164
+ ctx.clearRect(0, 0, width, height);
9165
+ ctx.fillStyle = "#111";
9166
+ ctx.fillRect(0, 0, width, height);
9167
+ for (const tile of tiles) {
9168
+ ctx.fillStyle = tile.color;
9169
+ ctx.fillRect(
9170
+ Math.floor(tile.x * scaleX),
9171
+ Math.floor(tile.y * scaleY),
9172
+ Math.max(1, Math.ceil(scaleX)),
9173
+ Math.max(1, Math.ceil(scaleY))
9174
+ );
9175
+ }
9176
+ for (const unit of units) {
9177
+ if (unit.isPlayer && !blinkOn) continue;
9178
+ ctx.fillStyle = unit.isPlayer ? "#ffffff" : unit.color;
9179
+ const ux = Math.floor(unit.x * scaleX) - 1;
9180
+ const uy = Math.floor(unit.y * scaleY) - 1;
9181
+ ctx.fillRect(ux, uy, 3, 3);
9182
+ }
9183
+ if (viewportRect) {
9184
+ ctx.strokeStyle = "#ffffff";
9185
+ ctx.lineWidth = 1;
9186
+ ctx.strokeRect(
9187
+ Math.floor(viewportRect.x * scaleX),
9188
+ Math.floor(viewportRect.y * scaleY),
9189
+ Math.floor(viewportRect.w * scaleX),
9190
+ Math.floor(viewportRect.h * scaleY)
9191
+ );
9192
+ }
9193
+ }
9194
+ function tick() {
9195
+ frameRef.current++;
9196
+ if (frameRef.current % 30 === 0) {
9197
+ blinkOn = !blinkOn;
9198
+ }
9199
+ draw();
9200
+ animFrame = requestAnimationFrame(tick);
9201
+ }
9202
+ tick();
9203
+ return () => {
9204
+ cancelAnimationFrame(animFrame);
9205
+ };
9206
+ }, [tiles, units, width, height, mapWidth, mapHeight, viewportRect]);
9207
+ return /* @__PURE__ */ jsx(
9208
+ "div",
9209
+ {
9210
+ className: cn(
9211
+ "relative inline-block border border-border/20 rounded-container",
9212
+ className
9213
+ ),
9214
+ children: /* @__PURE__ */ jsx(
9215
+ "canvas",
9160
9216
  {
9161
- align: "center",
9162
- className: cn(
9163
- "justify-center py-12",
9164
- className
9165
- ),
9166
- children: [
9167
- /* @__PURE__ */ jsx(Spinner, { size: "lg" }),
9168
- title && /* @__PURE__ */ jsx(Typography, { variant: "h3", className: "mt-4 text-lg font-semibold text-foreground", children: title }),
9169
- /* @__PURE__ */ jsx(
9170
- Typography,
9171
- {
9172
- variant: "small",
9173
- className: cn(
9174
- "text-muted-foreground",
9175
- title ? "mt-2" : "mt-4"
9176
- ),
9177
- children: displayMessage
9178
- }
9179
- )
9180
- ]
9217
+ ref: canvasRef,
9218
+ width,
9219
+ height,
9220
+ className: "block",
9221
+ style: { width, height }
9181
9222
  }
9182
- );
9223
+ )
9224
+ }
9225
+ );
9226
+ }
9227
+ var DEFAULT_TILES, DEFAULT_UNITS, DEFAULT_VIEWPORT;
9228
+ var init_MiniMap = __esm({
9229
+ "components/game/atoms/MiniMap.tsx"() {
9230
+ "use client";
9231
+ init_cn();
9232
+ DEFAULT_TILES = [
9233
+ { x: 10, y: 10, color: "#4ade80" },
9234
+ { x: 20, y: 15, color: "#4ade80" },
9235
+ { x: 30, y: 25, color: "#22c55e" },
9236
+ { x: 50, y: 40, color: "#4ade80" },
9237
+ { x: 60, y: 55, color: "#16a34a" },
9238
+ { x: 40, y: 60, color: "#4ade80" },
9239
+ { x: 70, y: 30, color: "#22c55e" },
9240
+ { x: 80, y: 70, color: "#4ade80" }
9241
+ ];
9242
+ DEFAULT_UNITS = [
9243
+ { x: 30, y: 30, color: "#60a5fa", isPlayer: true }
9244
+ ];
9245
+ DEFAULT_VIEWPORT = { x: 20, y: 20, w: 40, h: 40 };
9246
+ MiniMap.displayName = "MiniMap";
9247
+ }
9248
+ });
9249
+ function HealthBar({
9250
+ current = 3,
9251
+ max = 5,
9252
+ format = "hearts",
9253
+ size = "md",
9254
+ className,
9255
+ animated = true
9256
+ }) {
9257
+ const sizes = sizeMap4[size];
9258
+ const percentage = Math.max(0, Math.min(100, current / max * 100));
9259
+ if (format === "hearts") {
9260
+ return /* @__PURE__ */ jsx("div", { className: cn("flex items-center gap-1", className), children: Array.from({ length: max }).map((_, i) => /* @__PURE__ */ jsx(
9261
+ "span",
9262
+ {
9263
+ className: cn(animated && "transition-transform hover:scale-110"),
9264
+ children: heartIcon(i < current, sizes.heart)
9265
+ },
9266
+ i
9267
+ )) });
9268
+ }
9269
+ if (format === "bar") {
9270
+ return /* @__PURE__ */ jsx(
9271
+ "div",
9272
+ {
9273
+ className: cn(
9274
+ "relative overflow-hidden rounded-full bg-muted",
9275
+ sizes.bar,
9276
+ "w-24",
9277
+ className
9278
+ ),
9279
+ children: /* @__PURE__ */ jsx(
9280
+ "div",
9281
+ {
9282
+ className: cn(
9283
+ "absolute inset-y-0 left-0 rounded-full",
9284
+ percentage > 66 ? "bg-success" : percentage > 33 ? "bg-warning" : "bg-error",
9285
+ animated && "transition-all duration-300"
9286
+ ),
9287
+ style: { width: `${percentage}%` }
9288
+ }
9289
+ )
9290
+ }
9291
+ );
9292
+ }
9293
+ return /* @__PURE__ */ jsxs("span", { className: cn("font-mono font-bold", sizes.text, className), children: [
9294
+ current,
9295
+ "/",
9296
+ max
9297
+ ] });
9298
+ }
9299
+ var heartIcon, sizeMap4;
9300
+ var init_HealthBar = __esm({
9301
+ "components/game/atoms/HealthBar.tsx"() {
9302
+ init_cn();
9303
+ heartIcon = (filled, size) => /* @__PURE__ */ jsx(
9304
+ "svg",
9305
+ {
9306
+ className: cn("transition-all duration-200", size, filled ? "text-error" : "text-muted-foreground"),
9307
+ viewBox: "0 0 24 24",
9308
+ fill: filled ? "currentColor" : "none",
9309
+ stroke: "currentColor",
9310
+ strokeWidth: filled ? 0 : 2,
9311
+ children: /* @__PURE__ */ jsx("path", { d: "M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z" })
9312
+ }
9313
+ );
9314
+ sizeMap4 = {
9315
+ sm: { heart: "w-4 h-4", bar: "h-2", text: "text-sm" },
9316
+ md: { heart: "w-6 h-6", bar: "h-3", text: "text-base" },
9317
+ lg: { heart: "w-8 h-8", bar: "h-4", text: "text-lg" }
9183
9318
  };
9184
- LoadingState.displayName = "LoadingState";
9319
+ HealthBar.displayName = "HealthBar";
9185
9320
  }
9186
9321
  });
9187
9322
  function getState() {
@@ -9739,9 +9874,6 @@ function useUnitSpriteAtlas(units) {
9739
9874
  const loadingRef = useRef(/* @__PURE__ */ new Set());
9740
9875
  const [pendingCount, setPendingCount] = useState(0);
9741
9876
  const [, forceTick] = useState(0);
9742
- const animStatesRef = useRef(/* @__PURE__ */ new Map());
9743
- const lastTickRef = useRef(0);
9744
- const rafRef = useRef(0);
9745
9877
  const atlasUrls = useMemo(() => {
9746
9878
  const set = /* @__PURE__ */ new Set();
9747
9879
  for (const unit of units) {
@@ -9787,54 +9919,6 @@ function useUnitSpriteAtlas(units) {
9787
9919
  }
9788
9920
  return [...urls];
9789
9921
  }, [units, pendingCount]);
9790
- useEffect(() => {
9791
- const hasAtlasUnits = units.some((u) => unitAtlasUrl(u) !== null);
9792
- if (!hasAtlasUnits) return;
9793
- let running = true;
9794
- const tick = (ts) => {
9795
- if (!running) return;
9796
- const last = lastTickRef.current || ts;
9797
- const delta = ts - last;
9798
- lastTickRef.current = ts;
9799
- const states = animStatesRef.current;
9800
- const currentIds = /* @__PURE__ */ new Set();
9801
- for (const unit of units) {
9802
- if (unitAtlasUrl(unit) === null) continue;
9803
- currentIds.add(unit.id);
9804
- let state = states.get(unit.id);
9805
- if (!state) {
9806
- state = { animation: "idle", direction: "se", elapsed: 0, walkHold: 0, prev: null };
9807
- states.set(unit.id, state);
9808
- }
9809
- const posX = unit.position?.x ?? unit.x ?? 0;
9810
- const posY = unit.position?.y ?? unit.y ?? 0;
9811
- if (state.prev) {
9812
- const dx = posX - state.prev.x;
9813
- const dy = posY - state.prev.y;
9814
- if (dx !== 0 || dy !== 0) {
9815
- state.animation = "walk";
9816
- state.direction = inferDirection(dx, dy);
9817
- state.walkHold = WALK_HOLD_MS;
9818
- } else if (state.animation === "walk") {
9819
- state.walkHold -= delta;
9820
- if (state.walkHold <= 0) state.animation = "idle";
9821
- }
9822
- }
9823
- state.prev = { x: posX, y: posY };
9824
- state.elapsed += delta;
9825
- }
9826
- for (const id of states.keys()) {
9827
- if (!currentIds.has(id)) states.delete(id);
9828
- }
9829
- rafRef.current = requestAnimationFrame(tick);
9830
- };
9831
- rafRef.current = requestAnimationFrame(tick);
9832
- return () => {
9833
- running = false;
9834
- cancelAnimationFrame(rafRef.current);
9835
- lastTickRef.current = 0;
9836
- };
9837
- }, [units]);
9838
9922
  const resolveUnitFrame = useCallback((unitId) => {
9839
9923
  const unit = units.find((u) => u.id === unitId);
9840
9924
  if (!unit) return null;
@@ -9842,18 +9926,14 @@ function useUnitSpriteAtlas(units) {
9842
9926
  if (!atlasUrl) return null;
9843
9927
  const atlas = atlasCacheRef.current.get(atlasUrl);
9844
9928
  if (!atlas) return null;
9845
- const state = animStatesRef.current.get(unitId);
9846
- const animation = state?.animation ?? "idle";
9847
- const direction = state?.direction ?? "se";
9848
- const elapsed = state?.elapsed ?? 0;
9929
+ const animation = unit.animation ?? "idle";
9930
+ const frame = unit.frame ?? 0;
9849
9931
  const def = atlas.animations[animation] ?? atlas.animations.idle;
9850
9932
  if (!def) return null;
9851
- const { sheetDir, flipX } = resolveSheetDirection(direction);
9933
+ const { sheetDir, flipX } = resolveSheetDirection("se");
9852
9934
  const rel = atlas.sheets[sheetDir] ?? atlas.sheets.se ?? atlas.sheets.sw;
9853
9935
  if (!rel) return null;
9854
9936
  const sheetUrl = resolveSheetUrl(atlasUrl, rel);
9855
- const isIdle = animation === "idle";
9856
- const frame = isIdle ? 0 : getCurrentFrameFromDef(def, elapsed).frame;
9857
9937
  const rect = frameRect(frame, def.row, atlas.columns, atlas.frameWidth, atlas.frameHeight);
9858
9938
  return {
9859
9939
  sheetUrl,
@@ -9862,17 +9942,15 @@ function useUnitSpriteAtlas(units) {
9862
9942
  sw: rect.sw,
9863
9943
  sh: rect.sh,
9864
9944
  flipX,
9865
- applyBreathing: isIdle
9945
+ applyBreathing: animation === "idle"
9866
9946
  };
9867
9947
  }, [units]);
9868
9948
  return { sheetUrls, resolveUnitFrame, pendingCount };
9869
9949
  }
9870
- var WALK_HOLD_MS;
9871
9950
  var init_useUnitSpriteAtlas = __esm({
9872
9951
  "components/game/molecules/useUnitSpriteAtlas.ts"() {
9873
9952
  "use client";
9874
9953
  init_spriteAnimation();
9875
- WALK_HOLD_MS = 600;
9876
9954
  }
9877
9955
  });
9878
9956
 
@@ -9940,6 +10018,7 @@ function IsometricCanvas({
9940
10018
  tiles: _tilesPropRaw = [],
9941
10019
  units: _unitsPropRaw = [],
9942
10020
  features: _featuresPropRaw = [],
10021
+ effects: _effectsPropRaw = [],
9943
10022
  // Interaction state
9944
10023
  selectedUnitId = null,
9945
10024
  validMoves = [],
@@ -9972,7 +10051,7 @@ function IsometricCanvas({
9972
10051
  resolveUnitFrame,
9973
10052
  effectSpriteUrls = [],
9974
10053
  onDrawEffects,
9975
- hasActiveEffects: hasActiveEffects2 = false,
10054
+ hasActiveEffects: _hasActiveEffects = false,
9976
10055
  // Tuning
9977
10056
  diamondTopY: diamondTopYProp,
9978
10057
  // Remote asset loading
@@ -9982,13 +10061,12 @@ function IsometricCanvas({
9982
10061
  const tilesProp = Array.isArray(_tilesPropRaw) ? _tilesPropRaw : [];
9983
10062
  const unitsProp = Array.isArray(_unitsPropRaw) ? _unitsPropRaw : [];
9984
10063
  const featuresProp = Array.isArray(_featuresPropRaw) ? _featuresPropRaw : [];
10064
+ const effects = Array.isArray(_effectsPropRaw) ? _effectsPropRaw : [];
9985
10065
  const eventBus = useEventBus();
9986
10066
  const { t } = useTranslate();
9987
10067
  const canvasRef = useRef(null);
9988
10068
  const containerRef = useRef(null);
9989
- const minimapRef = useRef(null);
9990
- const animTimeRef = useRef(0);
9991
- const rafIdRef = useRef(0);
10069
+ const lerpRafRef = useRef(0);
9992
10070
  const [viewportSize, setViewportSize] = useState({ width: 800, height: 600 });
9993
10071
  useEffect(() => {
9994
10072
  const el = containerRef.current;
@@ -10012,7 +10090,7 @@ function IsometricCanvas({
10012
10090
  () => unitsProp.map((u) => u.position ? u : { ...u, position: { x: u.x ?? 0, y: u.y ?? 0 } }),
10013
10091
  [unitsProp]
10014
10092
  );
10015
- const { sheetUrls: atlasSheetUrls, resolveUnitFrame: resolveUnitFrameInternal, pendingCount: atlasPending } = useUnitSpriteAtlas(units);
10093
+ const { sheetUrls: atlasSheetUrls, resolveUnitFrame: resolveUnitFrameInternal } = useUnitSpriteAtlas(units);
10016
10094
  const resolveFrameForUnit = useCallback((unitId) => {
10017
10095
  return resolveUnitFrame?.(unitId) ?? resolveUnitFrameInternal(unitId);
10018
10096
  }, [resolveUnitFrame, resolveUnitFrameInternal]);
@@ -10107,7 +10185,7 @@ function IsometricCanvas({
10107
10185
  if (backgroundImage) urls.push(backgroundImage);
10108
10186
  return [...new Set(urls.filter(Boolean))];
10109
10187
  }, [sortedTiles, features, units, getTerrainSprite, getFeatureSprite, getUnitSprite, effectSpriteUrls, atlasSheetUrls, backgroundImage, assetManifest, resolveManifestUrl7]);
10110
- const { getImage, pendingCount } = useImageCache(spriteUrls);
10188
+ const { getImage, pendingCount: _imagePendingCount } = useImageCache(spriteUrls);
10111
10189
  useEffect(() => {
10112
10190
  if (typeof window === "undefined") return;
10113
10191
  const canvas = canvasRef.current;
@@ -10139,63 +10217,26 @@ function IsometricCanvas({
10139
10217
  const resolveUnitSpriteUrl = useCallback((unit) => {
10140
10218
  return unit.sprite || getUnitSprite?.(unit) || (unit.unitType ? resolveManifestUrl7(assetManifest?.units?.[unit.unitType]) : void 0);
10141
10219
  }, [getUnitSprite, assetManifest, resolveManifestUrl7]);
10142
- const drawMinimap = useCallback(() => {
10143
- if (!showMinimap) return;
10144
- const miniCanvas = minimapRef.current;
10145
- if (!miniCanvas || sortedTiles.length === 0) return;
10146
- const mCtx = miniCanvas.getContext("2d");
10147
- if (!mCtx) return;
10148
- const mW = 150;
10149
- const mH = 100;
10150
- miniCanvas.width = mW;
10151
- miniCanvas.height = mH;
10152
- mCtx.clearRect(0, 0, mW, mH);
10153
- const allScreenPos = sortedTiles.map((t2) => isoToScreen(t2.x, t2.y, scale, baseOffsetX, tileLayout));
10154
- const minX = Math.min(...allScreenPos.map((p2) => p2.x));
10155
- const maxX = Math.max(...allScreenPos.map((p2) => p2.x + scaledTileWidth));
10156
- const minY = Math.min(...allScreenPos.map((p2) => p2.y));
10157
- const tileBottomExtent = tileLayout === "hex" || tileLayout === "flat" ? scaledTileWidth : scaledTileHeight;
10158
- const maxY = Math.max(...allScreenPos.map((p2) => p2.y + tileBottomExtent));
10159
- const worldW = maxX - minX;
10160
- const worldH = maxY - minY;
10161
- const scaleM = Math.min(mW / worldW, mH / worldH) * 0.9;
10162
- const offsetMx = (mW - worldW * scaleM) / 2;
10163
- const offsetMy = (mH - worldH * scaleM) / 2;
10164
- for (const tile of sortedTiles) {
10165
- const pos = isoToScreen(tile.x, tile.y, scale, baseOffsetX, tileLayout);
10166
- const mx = (pos.x - minX) * scaleM + offsetMx;
10167
- const my = (pos.y - minY) * scaleM + offsetMy;
10168
- const mTileW = scaledTileWidth * scaleM;
10169
- const mFloorH = scaledFloorHeight * scaleM;
10170
- mCtx.fillStyle = tile.terrain === "water" ? "#3b82f6" : tile.terrain === "mountain" ? "#78716c" : "#4ade80";
10171
- mCtx.beginPath();
10172
- mCtx.moveTo(mx + mTileW / 2, my);
10173
- mCtx.lineTo(mx + mTileW, my + mFloorH / 2);
10174
- mCtx.lineTo(mx + mTileW / 2, my + mFloorH);
10175
- mCtx.lineTo(mx, my + mFloorH / 2);
10176
- mCtx.closePath();
10177
- mCtx.fill();
10178
- }
10179
- for (const unit of units) {
10180
- if (!unit.position) continue;
10181
- const pos = isoToScreen(unit.position.x, unit.position.y, scale, baseOffsetX, tileLayout);
10182
- const mx = (pos.x + scaledTileWidth / 2 - minX) * scaleM + offsetMx;
10183
- const my = (pos.y + scaledTileHeight / 2 - minY) * scaleM + offsetMy;
10184
- mCtx.fillStyle = unit.team === "player" ? "#60a5fa" : unit.team === "enemy" ? "#f87171" : "#9ca3af";
10185
- mCtx.beginPath();
10186
- mCtx.arc(mx, my, 3, 0, Math.PI * 2);
10187
- mCtx.fill();
10188
- }
10189
- const cam = cameraRef.current;
10190
- const vLeft = (cam.x - minX) * scaleM + offsetMx;
10191
- const vTop = (cam.y - minY) * scaleM + offsetMy;
10192
- const vW = viewportSize.width / cam.zoom * scaleM;
10193
- const vH = viewportSize.height / cam.zoom * scaleM;
10194
- mCtx.strokeStyle = "rgba(255, 255, 255, 0.8)";
10195
- mCtx.lineWidth = 1;
10196
- mCtx.strokeRect(vLeft, vTop, vW, vH);
10197
- }, [showMinimap, sortedTiles, units, tileLayout, scale, baseOffsetX, scaledTileWidth, scaledTileHeight, scaledFloorHeight, viewportSize, cameraRef]);
10198
- const draw = useCallback((animTime) => {
10220
+ const miniMapTiles = useMemo(() => {
10221
+ if (!showMinimap) return [];
10222
+ return sortedTiles.map((t2) => ({
10223
+ x: t2.x,
10224
+ y: t2.y,
10225
+ color: t2.terrain === "water" ? "#3b82f6" : t2.terrain === "mountain" ? "#78716c" : "#4ade80"
10226
+ }));
10227
+ }, [showMinimap, sortedTiles]);
10228
+ const miniMapUnits = useMemo(() => {
10229
+ if (!showMinimap) return [];
10230
+ return units.filter((u) => u.position).map((u) => ({
10231
+ x: u.position.x,
10232
+ y: u.position.y,
10233
+ color: u.team === "player" ? "#60a5fa" : u.team === "enemy" ? "#f87171" : "#9ca3af",
10234
+ isPlayer: u.team === "player"
10235
+ }));
10236
+ }, [showMinimap, units]);
10237
+ const miniMapWidth = gridWidth || 10;
10238
+ const miniMapHeight = gridHeight || 10;
10239
+ const draw = useCallback(() => {
10199
10240
  const canvas = canvasRef.current;
10200
10241
  if (!canvas) return;
10201
10242
  const ctx = canvas.getContext("2d");
@@ -10281,8 +10322,7 @@ function IsometricCanvas({
10281
10322
  if (validMoveSet.has(tileKey)) {
10282
10323
  const centerX = pos.x + scaledTileWidth / 2;
10283
10324
  const topY = pos.y + scaledDiamondTopY;
10284
- const pulse = 0.15 + 0.1 * Math.sin(animTime * 4e-3);
10285
- ctx.fillStyle = `rgba(74, 222, 128, ${pulse})`;
10325
+ ctx.fillStyle = "rgba(74, 222, 128, 0.25)";
10286
10326
  ctx.beginPath();
10287
10327
  ctx.moveTo(centerX, topY);
10288
10328
  ctx.lineTo(pos.x + scaledTileWidth, topY + scaledFloorHeight / 2);
@@ -10294,8 +10334,7 @@ function IsometricCanvas({
10294
10334
  if (attackTargetSet.has(tileKey)) {
10295
10335
  const centerX = pos.x + scaledTileWidth / 2;
10296
10336
  const topY = pos.y + scaledDiamondTopY;
10297
- const pulse = 0.2 + 0.15 * Math.sin(animTime * 5e-3);
10298
- ctx.fillStyle = `rgba(239, 68, 68, ${pulse})`;
10337
+ ctx.fillStyle = "rgba(239, 68, 68, 0.35)";
10299
10338
  ctx.beginPath();
10300
10339
  ctx.moveTo(centerX, topY);
10301
10340
  ctx.lineTo(pos.x + scaledTileWidth, topY + scaledFloorHeight / 2);
@@ -10368,7 +10407,7 @@ function IsometricCanvas({
10368
10407
  const isSelected = unit.id === selectedUnitId;
10369
10408
  const centerX = pos.x + scaledTileWidth / 2;
10370
10409
  const groundY = pos.y + scaledDiamondTopY + scaledFloorHeight * 0.5;
10371
- const breatheOffset = 0.8 * scale * (1 + Math.sin(animTime * 2e-3 + (unit.position.x * 3.7 + unit.position.y * 5.3)));
10410
+ const breatheOffset = 0;
10372
10411
  const unitSpriteUrl = resolveUnitSpriteUrl(unit);
10373
10412
  const img = unitSpriteUrl ? getImage(unitSpriteUrl) : null;
10374
10413
  const unitDrawH = scaledFloorHeight * spriteHeightRatio * unitScale;
@@ -10408,10 +10447,9 @@ function IsometricCanvas({
10408
10447
  ctx.restore();
10409
10448
  }
10410
10449
  if (isSelected) {
10411
- const ringAlpha = 0.6 + 0.3 * Math.sin(animTime * 4e-3);
10412
10450
  ctx.beginPath();
10413
10451
  ctx.ellipse(centerX, groundY, drawW / 2 + 4 * scale, 12 * scale, 0, 0, Math.PI * 2);
10414
- ctx.strokeStyle = `rgba(0, 200, 255, ${ringAlpha})`;
10452
+ ctx.strokeStyle = "rgba(0, 200, 255, 0.8)";
10415
10453
  ctx.lineWidth = 3;
10416
10454
  ctx.stroke();
10417
10455
  }
@@ -10467,66 +10505,29 @@ function IsometricCanvas({
10467
10505
  ctx.lineWidth = 2;
10468
10506
  ctx.stroke();
10469
10507
  }
10470
- if (unit.name) {
10471
- const labelBg = unit.team === "player" ? "rgba(59, 130, 246, 0.9)" : unit.team === "enemy" ? "rgba(239, 68, 68, 0.9)" : "rgba(107, 114, 128, 0.9)";
10472
- ctx.font = `bold ${10 * scale * 2.5}px system-ui`;
10473
- ctx.textAlign = "center";
10474
- const textWidth = ctx.measureText(unit.name).width;
10475
- const labelY = groundY + 14 * scale - breatheOffset;
10476
- ctx.fillStyle = labelBg;
10477
- ctx.beginPath();
10478
- ctx.roundRect(centerX - textWidth / 2 - 6 * scale, labelY - 8 * scale, textWidth + 12 * scale, 16 * scale, 4 * scale);
10479
- ctx.fill();
10480
- ctx.fillStyle = "white";
10481
- ctx.fillText(unit.name, centerX, labelY + 4 * scale);
10482
- }
10483
- if (unit.health !== void 0 && unit.maxHealth !== void 0) {
10484
- const barWidth = 40 * scale;
10485
- const barHeight = 6 * scale;
10486
- const barX = centerX - barWidth / 2;
10487
- const barY = groundY - drawH - 2 * scale - breatheOffset;
10488
- const healthRatio = unit.health / unit.maxHealth;
10489
- const barRadius = barHeight / 2;
10490
- ctx.fillStyle = "rgba(0, 0, 0, 0.7)";
10491
- ctx.beginPath();
10492
- ctx.roundRect(barX, barY, barWidth, barHeight, barRadius);
10493
- ctx.fill();
10494
- if (healthRatio > 0) {
10495
- const fillWidth = barWidth * healthRatio;
10496
- const gradient = ctx.createLinearGradient(barX, barY, barX, barY + barHeight);
10497
- if (healthRatio > 0.6) {
10498
- gradient.addColorStop(0, "#4ade80");
10499
- gradient.addColorStop(1, "#22c55e");
10500
- } else if (healthRatio > 0.3) {
10501
- gradient.addColorStop(0, "#fde047");
10502
- gradient.addColorStop(1, "#eab308");
10503
- } else {
10504
- gradient.addColorStop(0, "#f87171");
10505
- gradient.addColorStop(1, "#ef4444");
10506
- }
10507
- ctx.fillStyle = gradient;
10508
- ctx.save();
10509
- ctx.beginPath();
10510
- ctx.roundRect(barX, barY, fillWidth, barHeight, barRadius);
10511
- ctx.clip();
10512
- ctx.fillRect(barX, barY, fillWidth, barHeight);
10513
- ctx.restore();
10514
- }
10515
- ctx.strokeStyle = "rgba(255, 255, 255, 0.3)";
10516
- ctx.lineWidth = 1;
10517
- ctx.beginPath();
10518
- ctx.roundRect(barX, barY, barWidth, barHeight, barRadius);
10519
- ctx.stroke();
10520
- }
10521
10508
  }
10522
- onDrawEffects?.(ctx, animTime, getImage);
10509
+ for (const fx of effects) {
10510
+ const spriteUrl = resolveManifestUrl7(assetManifest?.effects?.[fx.key]);
10511
+ if (!spriteUrl) continue;
10512
+ const img = getImage(spriteUrl);
10513
+ if (!img) continue;
10514
+ const pos = isoToScreen(fx.x, fx.y, scale, baseOffsetX, tileLayout);
10515
+ const cx = pos.x + scaledTileWidth / 2;
10516
+ const cy = pos.y + scaledDiamondTopY + scaledFloorHeight * 0.5;
10517
+ const alpha = Math.min(1, fx.ttl / 4);
10518
+ const prev = ctx.globalAlpha;
10519
+ ctx.globalAlpha = alpha;
10520
+ ctx.drawImage(img, cx - img.naturalWidth / 2, cy - img.naturalHeight / 2);
10521
+ ctx.globalAlpha = prev;
10522
+ }
10523
+ onDrawEffects?.(ctx, 0, getImage);
10523
10524
  ctx.restore();
10524
- drawMinimap();
10525
10525
  }, [
10526
10526
  sortedTiles,
10527
10527
  units,
10528
10528
  features,
10529
10529
  selectedUnitId,
10530
+ effects,
10530
10531
  tileLayout,
10531
10532
  scale,
10532
10533
  debug2,
@@ -10546,11 +10547,12 @@ function IsometricCanvas({
10546
10547
  attackTargetSet,
10547
10548
  hoveredTile,
10548
10549
  viewportSize,
10549
- drawMinimap,
10550
10550
  onDrawEffects,
10551
10551
  backgroundImage,
10552
10552
  cameraRef,
10553
- unitScale
10553
+ unitScale,
10554
+ resolveManifestUrl7,
10555
+ assetManifest
10554
10556
  ]);
10555
10557
  useEffect(() => {
10556
10558
  if (!selectedUnitId) return;
@@ -10565,30 +10567,33 @@ function IsometricCanvas({
10565
10567
  };
10566
10568
  }, [selectedUnitId, units, tileLayout, scale, baseOffsetX, scaledTileWidth, scaledDiamondTopY, scaledFloorHeight, viewportSize, targetCameraRef]);
10567
10569
  useEffect(() => {
10568
- const hasAnimations = units.length > 0 || validMoves.length > 0 || attackTargets.length > 0 || selectedUnitId != null || targetCameraRef.current != null || hasActiveEffects2 || pendingCount > 0 || atlasPending > 0;
10569
- draw(animTimeRef.current);
10570
- if (!hasAnimations) return;
10570
+ draw();
10571
+ }, [draw]);
10572
+ useEffect(() => {
10573
+ draw();
10574
+ }, [_imagePendingCount]);
10575
+ useEffect(() => {
10576
+ if (selectedUnitId == null) return;
10571
10577
  let running = true;
10572
- const animate = (timestamp) => {
10578
+ const tick = () => {
10573
10579
  if (!running) return;
10574
- animTimeRef.current = timestamp;
10575
- lerpToTarget();
10576
- draw(timestamp);
10577
- rafIdRef.current = requestAnimationFrame(animate);
10580
+ const stillLerping = lerpToTarget();
10581
+ draw();
10582
+ if (stillLerping) lerpRafRef.current = requestAnimationFrame(tick);
10578
10583
  };
10579
- rafIdRef.current = requestAnimationFrame(animate);
10584
+ lerpRafRef.current = requestAnimationFrame(tick);
10580
10585
  return () => {
10581
10586
  running = false;
10582
- cancelAnimationFrame(rafIdRef.current);
10587
+ cancelAnimationFrame(lerpRafRef.current);
10583
10588
  };
10584
- }, [draw, units.length, validMoves.length, attackTargets.length, selectedUnitId, hasActiveEffects2, pendingCount, atlasPending, lerpToTarget, targetCameraRef]);
10589
+ }, [selectedUnitId, lerpToTarget, draw]);
10585
10590
  const singlePointerActiveRef = useRef(false);
10586
10591
  const handleCanvasPointerDown = useCallback((e) => {
10587
10592
  singlePointerActiveRef.current = true;
10588
10593
  if (enableCamera) handlePointerDown(e);
10589
10594
  }, [enableCamera, handlePointerDown]);
10590
10595
  const handleCanvasPointerMove = useCallback((e) => {
10591
- if (enableCamera) handlePointerMove(e, () => draw(animTimeRef.current));
10596
+ if (enableCamera) handlePointerMove(e, () => draw());
10592
10597
  }, [enableCamera, handlePointerMove, draw]);
10593
10598
  const handleCanvasHover = useCallback((e) => {
10594
10599
  if (singlePointerActiveRef.current) return;
@@ -10630,10 +10635,10 @@ function IsometricCanvas({
10630
10635
  onTileLeave?.();
10631
10636
  }, [handleMouseLeave, onTileLeave, tileLeaveEvent, eventBus]);
10632
10637
  const applyZoom = useCallback((factor, centerX, centerY) => {
10633
- if (enableCamera) zoomAtPoint(factor, centerX, centerY, viewportSize, () => draw(animTimeRef.current));
10638
+ if (enableCamera) zoomAtPoint(factor, centerX, centerY, viewportSize, () => draw());
10634
10639
  }, [enableCamera, zoomAtPoint, viewportSize, draw]);
10635
10640
  const applyPanDelta = useCallback((dx, dy) => {
10636
- if (enableCamera) panBy(dx, dy, () => draw(animTimeRef.current));
10641
+ if (enableCamera) panBy(dx, dy, () => draw());
10637
10642
  }, [enableCamera, panBy, draw]);
10638
10643
  const cancelSinglePointer = useCallback(() => {
10639
10644
  singlePointerActiveRef.current = false;
@@ -10649,11 +10654,27 @@ function IsometricCanvas({
10649
10654
  onPanDelta: applyPanDelta,
10650
10655
  onMultiTouchStart: cancelSinglePointer
10651
10656
  });
10657
+ const unitOverlays = useMemo(() => {
10658
+ if (sortedTiles.length === 0) return [];
10659
+ return units.filter((u) => !!u.position).map((u) => {
10660
+ const pos = isoToScreen(u.position.x, u.position.y, scale, baseOffsetX, tileLayout);
10661
+ const cam = cameraRef.current;
10662
+ const screenX = (pos.x + scaledTileWidth / 2 - (cam.x + viewportSize.width / 2)) * cam.zoom + viewportSize.width / 2;
10663
+ const screenY = (pos.y + scaledDiamondTopY + scaledFloorHeight * 0.5 - (cam.y + viewportSize.height / 2)) * cam.zoom + viewportSize.height / 2;
10664
+ return { unit: u, screenX, screenY };
10665
+ });
10666
+ }, [units, sortedTiles.length, scale, baseOffsetX, tileLayout, scaledTileWidth, scaledDiamondTopY, scaledFloorHeight, viewportSize, cameraRef]);
10652
10667
  if (error) {
10653
- return /* @__PURE__ */ jsx(ErrorState, { title: t("canvas.errorTitle"), message: error.message, className });
10668
+ return /* @__PURE__ */ jsx(Box, { className: cn("flex items-center justify-center w-full h-full bg-[var(--color-card)] rounded-container", className), children: /* @__PURE__ */ jsxs(Stack, { direction: "vertical", gap: "md", align: "center", children: [
10669
+ /* @__PURE__ */ jsx(Icon, { name: "alert-circle", size: "xl" }),
10670
+ /* @__PURE__ */ jsx(Typography, { variant: "body", className: "text-error", children: error.message })
10671
+ ] }) });
10654
10672
  }
10655
10673
  if (isLoading) {
10656
- return /* @__PURE__ */ jsx(LoadingState, { className });
10674
+ return /* @__PURE__ */ jsx(Box, { className: cn("flex items-center justify-center w-full h-full bg-[var(--color-card)] rounded-container", className), children: /* @__PURE__ */ jsxs(Stack, { direction: "vertical", gap: "md", align: "center", children: [
10675
+ /* @__PURE__ */ jsx(Icon, { name: "loader", size: "xl", className: "animate-spin" }),
10676
+ /* @__PURE__ */ jsx(Typography, { variant: "body", className: "text-muted-foreground", children: t("canvas.loadingMessage") || "Loading\u2026" })
10677
+ ] }) });
10657
10678
  }
10658
10679
  if (sortedTiles.length === 0) {
10659
10680
  return /* @__PURE__ */ jsx(
@@ -10718,14 +10739,36 @@ function IsometricCanvas({
10718
10739
  }
10719
10740
  )
10720
10741
  ] }),
10721
- showMinimap && /* @__PURE__ */ jsx(
10722
- "canvas",
10742
+ unitOverlays.map(({ unit, screenX, screenY }) => /* @__PURE__ */ jsxs(
10743
+ "div",
10744
+ {
10745
+ className: "absolute pointer-events-none",
10746
+ style: { left: Math.round(screenX), top: Math.round(screenY), transform: "translate(-50%, 0)", zIndex: 5 },
10747
+ children: [
10748
+ unit.name && /* @__PURE__ */ jsx(
10749
+ "div",
10750
+ {
10751
+ className: "text-white text-xs font-bold px-1.5 py-0.5 rounded mb-0.5 whitespace-nowrap",
10752
+ style: { background: unit.team === "player" ? "rgba(59,130,246,0.9)" : unit.team === "enemy" ? "rgba(239,68,68,0.9)" : "rgba(107,114,128,0.9)" },
10753
+ children: unit.name
10754
+ }
10755
+ ),
10756
+ unit.health !== void 0 && unit.maxHealth !== void 0 && unit.maxHealth > 0 && /* @__PURE__ */ jsx(HealthBar, { current: unit.health, max: unit.maxHealth, format: "bar", size: "sm" })
10757
+ ]
10758
+ },
10759
+ unit.id
10760
+ )),
10761
+ showMinimap && /* @__PURE__ */ jsx("div", { className: "absolute bottom-2 right-2 pointer-events-none", style: { zIndex: 10 }, children: /* @__PURE__ */ jsx(
10762
+ MiniMap,
10723
10763
  {
10724
- ref: minimapRef,
10725
- className: "absolute bottom-2 right-2 border border-border rounded bg-background/80 pointer-events-none",
10726
- style: { width: 150, height: 100, zIndex: 10 }
10764
+ tiles: miniMapTiles,
10765
+ units: miniMapUnits,
10766
+ width: 150,
10767
+ height: 100,
10768
+ mapWidth: miniMapWidth,
10769
+ mapHeight: miniMapHeight
10727
10770
  }
10728
- )
10771
+ ) })
10729
10772
  ]
10730
10773
  }
10731
10774
  );
@@ -10740,8 +10783,8 @@ var init_IsometricCanvas = __esm({
10740
10783
  init_Stack();
10741
10784
  init_Icon();
10742
10785
  init_Typography();
10743
- init_LoadingState();
10744
- init_ErrorState();
10786
+ init_MiniMap();
10787
+ init_HealthBar();
10745
10788
  init_useImageCache();
10746
10789
  init_useCamera();
10747
10790
  init_useCanvasGestures();
@@ -10835,9 +10878,37 @@ function BattleBoard({
10835
10878
  className
10836
10879
  }) {
10837
10880
  const board = boardEntity(entity) ?? {};
10838
- const rawTiles = propTiles ?? (Array.isArray(board.tiles) ? board.tiles : []);
10881
+ function asFieldObj(v) {
10882
+ if (v === null || typeof v !== "object" || Array.isArray(v) || v instanceof Date) return null;
10883
+ return v;
10884
+ }
10885
+ const rawTiles = propTiles ?? (Array.isArray(board.tiles) ? board.tiles.flatMap((v) => {
10886
+ const o = asFieldObj(v);
10887
+ if (o === null || typeof o.x !== "number" || typeof o.y !== "number") return [];
10888
+ const tile = { x: o.x, y: o.y };
10889
+ if (typeof o.terrain === "string") tile.terrain = o.terrain;
10890
+ if (typeof o.terrainSprite === "string") tile.terrainSprite = o.terrainSprite;
10891
+ if (typeof o.passable === "boolean") tile.passable = o.passable;
10892
+ if (typeof o.movementCost === "number") tile.movementCost = o.movementCost;
10893
+ if (typeof o.elevation === "number") tile.elevation = o.elevation;
10894
+ if (typeof o.type === "string") tile.type = o.type;
10895
+ if (typeof o.tileType === "string") tile.tileType = o.tileType;
10896
+ if (typeof o.id === "string") tile.id = o.id;
10897
+ if (typeof o.modelUrl === "string") tile.modelUrl = o.modelUrl;
10898
+ return [tile];
10899
+ }) : []);
10839
10900
  const tiles = rawTiles.length === 0 ? DEFAULT_BATTLE_TILES : rawTiles;
10840
- const features = propFeatures ?? (Array.isArray(board.features) ? board.features : []);
10901
+ const features = propFeatures ?? (Array.isArray(board.features) ? board.features.flatMap((v) => {
10902
+ const o = asFieldObj(v);
10903
+ if (o === null || typeof o.type !== "string" || typeof o.x !== "number" || typeof o.y !== "number") return [];
10904
+ const feat = { type: o.type, x: o.x, y: o.y };
10905
+ if (typeof o.id === "string") feat.id = o.id;
10906
+ if (typeof o.sprite === "string") feat.sprite = o.sprite;
10907
+ if (typeof o.color === "string") feat.color = o.color;
10908
+ if (typeof o.elevation === "number") feat.elevation = o.elevation;
10909
+ if (typeof o.assetUrl === "string") feat.assetUrl = o.assetUrl;
10910
+ return [feat];
10911
+ }) : []);
10841
10912
  const boardWidth = num(board.gridWidth ?? board.boardWidth, BATTLE_GRID_W);
10842
10913
  const boardHeight = num(board.gridHeight ?? board.boardHeight, BATTLE_GRID_H);
10843
10914
  const assetManifest = propAssetManifest ?? board.assetManifest;
@@ -10936,7 +11007,12 @@ function BattleBoard({
10936
11007
  return units.filter((u) => unitHealth(u) > 0).map((unit) => {
10937
11008
  const id = str(unit.id);
10938
11009
  const pos = movingPositions.get(id) ?? unitPosition(unit);
10939
- const unitTraits = Array.isArray(unit.traits) ? unit.traits : void 0;
11010
+ const unitTraits = Array.isArray(unit.traits) ? unit.traits.flatMap((v) => {
11011
+ const o = asFieldObj(v);
11012
+ if (o === null || typeof o.name !== "string" || typeof o.currentState !== "string" || !Array.isArray(o.states)) return [];
11013
+ const stateNames = Array.from(o.states).flatMap((s) => typeof s === "string" ? [s] : []);
11014
+ return [{ name: o.name, currentState: o.currentState, states: stateNames, cooldown: typeof o.cooldown === "number" ? o.cooldown : void 0 }];
11015
+ }) : void 0;
10940
11016
  return {
10941
11017
  id,
10942
11018
  position: pos,
@@ -11932,9 +12008,9 @@ async function computeTraitLayout(data) {
11932
12008
  y: n.y ?? 0,
11933
12009
  width: n.width ?? 110,
11934
12010
  height: n.height ?? STATE_H,
11935
- isInitial: stateInfo?.isInitial,
11936
- isTerminal: stateInfo?.isTerminal,
11937
- role: getStateRole(name, stateInfo?.isInitial, stateInfo?.isTerminal, tc, maxTC),
12011
+ isInitial: stateInfo?.isInitial ?? void 0,
12012
+ isTerminal: stateInfo?.isTerminal ?? void 0,
12013
+ role: getStateRole(name, stateInfo?.isInitial ?? void 0, stateInfo?.isTerminal ?? void 0, tc, maxTC),
11938
12014
  transitionCount: tc
11939
12015
  };
11940
12016
  });
@@ -11945,12 +12021,10 @@ async function computeTraitLayout(data) {
11945
12021
  const sections = e.sections ?? [];
11946
12022
  const points = [];
11947
12023
  for (const section of sections) {
11948
- const startPoint = section.startPoint;
11949
- const endPoint = section.endPoint;
11950
12024
  const bendPoints = section.bendPoints ?? [];
11951
- points.push({ x: startPoint.x, y: startPoint.y });
12025
+ points.push({ x: section.startPoint.x, y: section.startPoint.y });
11952
12026
  for (const bp of bendPoints) points.push({ x: bp.x, y: bp.y });
11953
- points.push({ x: endPoint.x, y: endPoint.y });
12027
+ points.push({ x: section.endPoint.x, y: section.endPoint.y });
11954
12028
  }
11955
12029
  const isSelf = t.from === t.to;
11956
12030
  const isBackward = !isSelf && (nodeXMap[t.to] ?? 0) <= (nodeXMap[t.from] ?? 0);
@@ -12268,6 +12342,50 @@ var init_Tabs = __esm({
12268
12342
  Tabs.displayName = "Tabs";
12269
12343
  }
12270
12344
  });
12345
+ var LoadingState;
12346
+ var init_LoadingState = __esm({
12347
+ "components/core/molecules/LoadingState.tsx"() {
12348
+ "use client";
12349
+ init_cn();
12350
+ init_atoms2();
12351
+ init_Stack();
12352
+ init_Typography();
12353
+ LoadingState = ({
12354
+ title,
12355
+ message,
12356
+ className
12357
+ }) => {
12358
+ const { t } = useTranslate();
12359
+ const displayMessage = message ?? t("common.loading");
12360
+ return /* @__PURE__ */ jsxs(
12361
+ VStack,
12362
+ {
12363
+ align: "center",
12364
+ className: cn(
12365
+ "justify-center py-12",
12366
+ className
12367
+ ),
12368
+ children: [
12369
+ /* @__PURE__ */ jsx(Spinner, { size: "lg" }),
12370
+ title && /* @__PURE__ */ jsx(Typography, { variant: "h3", className: "mt-4 text-lg font-semibold text-foreground", children: title }),
12371
+ /* @__PURE__ */ jsx(
12372
+ Typography,
12373
+ {
12374
+ variant: "small",
12375
+ className: cn(
12376
+ "text-muted-foreground",
12377
+ title ? "mt-2" : "mt-4"
12378
+ ),
12379
+ children: displayMessage
12380
+ }
12381
+ )
12382
+ ]
12383
+ }
12384
+ );
12385
+ };
12386
+ LoadingState.displayName = "LoadingState";
12387
+ }
12388
+ });
12271
12389
  var ICON_NAME_ALIASES, lookStyles3, EmptyState;
12272
12390
  var init_EmptyState = __esm({
12273
12391
  "components/core/molecules/EmptyState.tsx"() {
@@ -12548,7 +12666,7 @@ var init_CodeBlock = __esm({
12548
12666
  };
12549
12667
  LINE_PROPS_FN = (n) => ({ "data-line": String(n - 1) });
12550
12668
  HIDDEN_LINE_NUMBERS = { display: "none" };
12551
- CodeBlock = React80__default.memo(
12669
+ CodeBlock = React85__default.memo(
12552
12670
  ({
12553
12671
  code: rawCode,
12554
12672
  language = "text",
@@ -13135,7 +13253,7 @@ var init_MarkdownContent = __esm({
13135
13253
  init_Box();
13136
13254
  init_CodeBlock();
13137
13255
  init_cn();
13138
- MarkdownContent = React80__default.memo(
13256
+ MarkdownContent = React85__default.memo(
13139
13257
  ({ content, direction = "ltr", className }) => {
13140
13258
  const { t: _t } = useTranslate();
13141
13259
  const safeContent = typeof content === "string" ? content : String(content ?? "");
@@ -14504,7 +14622,7 @@ var init_StateMachineView = __esm({
14504
14622
  style: { top: title ? 30 : 0 },
14505
14623
  children: [
14506
14624
  entity && /* @__PURE__ */ jsx(EntityBox, { entity, config }),
14507
- states.map((state) => renderStateNode ? /* @__PURE__ */ jsx(React80__default.Fragment, { children: renderStateNode(state, config) }, state.id) : /* @__PURE__ */ jsx(
14625
+ states.map((state) => renderStateNode ? /* @__PURE__ */ jsx(React85__default.Fragment, { children: renderStateNode(state, config) }, state.id) : /* @__PURE__ */ jsx(
14508
14626
  StateNode,
14509
14627
  {
14510
14628
  state,
@@ -15323,12 +15441,13 @@ var init_ContentRenderer = __esm({
15323
15441
  );
15324
15442
  case "orbital": {
15325
15443
  const parsed = segment.schema;
15444
+ const isFullSchema = (v) => Array.isArray(v.orbitals);
15326
15445
  const inlineTrait = {
15327
15446
  name: "inline",
15328
15447
  scope: "instance",
15329
15448
  stateMachine: parsed
15330
15449
  };
15331
- const schema = Array.isArray(parsed.orbitals) ? parsed : {
15450
+ const schema = isFullSchema(parsed) ? parsed : {
15332
15451
  name: "inline",
15333
15452
  orbitals: [{
15334
15453
  name: "inline",
@@ -16554,8 +16673,21 @@ function BuilderBoard({
16554
16673
  const resolved = boardEntity(entity);
16555
16674
  const [headerError, setHeaderError] = useState(false);
16556
16675
  const [selectedComponent, setSelectedComponent] = useState(null);
16557
- const components = Array.isArray(resolved?.components) ? resolved.components : [];
16558
- const slots = Array.isArray(resolved?.slots) ? resolved.slots : [];
16676
+ const components = rows(resolved?.components).map((r) => ({
16677
+ id: str(r.id),
16678
+ label: str(r.label),
16679
+ description: str(r.description) || void 0,
16680
+ iconEmoji: str(r.iconEmoji) || void 0,
16681
+ iconUrl: str(r.iconUrl) || void 0,
16682
+ category: str(r.category) || void 0
16683
+ }));
16684
+ const slots = rows(resolved?.slots).map((r) => ({
16685
+ id: str(r.id),
16686
+ label: str(r.label) || void 0,
16687
+ description: str(r.description) || void 0,
16688
+ requiredComponentId: str(r.requiredComponentId),
16689
+ placedComponentId: str(r.placedComponentId) || void 0
16690
+ }));
16559
16691
  const placements = {};
16560
16692
  for (const slot of slots) {
16561
16693
  if (slot.placedComponentId) placements[slot.id] = slot.placedComponentId;
@@ -18459,7 +18591,7 @@ function CardHand({
18459
18591
  className
18460
18592
  }) {
18461
18593
  const eventBus = useEventBus();
18462
- const handleClick = React80.useCallback(
18594
+ const handleClick = React85.useCallback(
18463
18595
  (card) => {
18464
18596
  if (card.disabled) return;
18465
18597
  onCardClick?.(card.id);
@@ -19206,14 +19338,15 @@ var init_CardGrid = __esm({
19206
19338
  bodyFields.length > 0 && /* @__PURE__ */ jsx(Box, { className: "px-4 py-3 flex-1", children: /* @__PURE__ */ jsx(VStack, { gap: "xs", children: bodyFields.map((field) => {
19207
19339
  const value = getNestedValue(itemData, field);
19208
19340
  if (value === void 0 || value === null || value === "") return null;
19209
- const boolVal = asBooleanValue(value);
19341
+ const fieldValue = value;
19342
+ const boolVal = asBooleanValue(fieldValue);
19210
19343
  if (boolVal !== null) {
19211
19344
  return /* @__PURE__ */ jsxs(HStack, { gap: "sm", className: "justify-between", children: [
19212
19345
  /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", children: fieldLabel(field) }),
19213
19346
  boolVal ? /* @__PURE__ */ jsx(Badge, { variant: "success", children: t("common.yes") || "Yes" }) : /* @__PURE__ */ jsx(Badge, { variant: "neutral", children: t("common.no") || "No" })
19214
19347
  ] }, field);
19215
19348
  }
19216
- const displayValue = isDateField(field) ? formatDate(value) : STATUS_FIELDS.has(field.toLowerCase()) ? void 0 : String(value);
19349
+ const displayValue = isDateField(field) ? formatDate(fieldValue) : STATUS_FIELDS.has(field.toLowerCase()) ? void 0 : String(value);
19217
19350
  if (!displayValue) return null;
19218
19351
  return /* @__PURE__ */ jsxs(HStack, { gap: "sm", className: "justify-between", children: [
19219
19352
  /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", children: fieldLabel(field) }),
@@ -19598,9 +19731,9 @@ function CastleBoard({
19598
19731
  const eventBus = useEventBus();
19599
19732
  const { t } = useTranslate();
19600
19733
  const resolved = boardEntity(entity);
19601
- const tiles = propTiles ?? (Array.isArray(resolved?.tiles) ? resolved.tiles : []);
19602
- const features = propFeatures ?? (Array.isArray(resolved?.features) ? resolved.features : []);
19603
- const units = propUnits ?? (Array.isArray(resolved?.units) ? resolved.units : []);
19734
+ const tiles = propTiles ?? (resolved?.tiles ?? []);
19735
+ const features = propFeatures ?? (resolved?.features ?? []);
19736
+ const units = propUnits ?? (resolved?.units ?? []);
19604
19737
  const assetManifest = propAssetManifest ?? resolved?.assetManifest;
19605
19738
  const backgroundImage = resolved?.backgroundImage;
19606
19739
  const gold = num(resolved?.gold);
@@ -21201,8 +21334,8 @@ function ClassifierBoard({
21201
21334
  const { t } = useTranslate();
21202
21335
  const resolved = boardEntity(entity);
21203
21336
  const [headerError, setHeaderError] = useState(false);
21204
- const items = Array.isArray(resolved?.items) ? resolved.items : [];
21205
- const categories = Array.isArray(resolved?.categories) ? resolved.categories : [];
21337
+ const items = rows(resolved?.items);
21338
+ const categories = rows(resolved?.categories);
21206
21339
  const result = str(resolved?.result);
21207
21340
  const submitted = result === "win";
21208
21341
  const attempts = num(resolved?.attempts);
@@ -21513,10 +21646,10 @@ function CombatLog({
21513
21646
  }, [events2, autoScroll]);
21514
21647
  const safeEvents = events2 ?? [];
21515
21648
  const visibleEvents = safeEvents.slice(-maxVisible);
21516
- return /* @__PURE__ */ jsxs(Card, { variant: "default", className: cn("flex flex-col", className), children: [
21649
+ return /* @__PURE__ */ jsxs(Box, { className: cn("flex flex-col rounded-container border border-border bg-card shadow-elevation-card", className), children: [
21517
21650
  /* @__PURE__ */ jsx(Box, { padding: "sm", border: true, className: "border-b-2 border-x-0 border-t-0 border-border", children: /* @__PURE__ */ jsxs(Box, { display: "flex", className: "items-center justify-between", children: [
21518
21651
  /* @__PURE__ */ jsx(Typography, { variant: "body2", className: "font-bold", children: title }),
21519
- /* @__PURE__ */ jsxs(Badge, { variant: "neutral", size: "sm", children: [
21652
+ /* @__PURE__ */ jsxs("span", { className: "text-xs text-muted-foreground bg-muted/60 rounded px-1.5 py-0.5 border border-border/50 font-mono", children: [
21520
21653
  safeEvents.length,
21521
21654
  " events"
21522
21655
  ] })
@@ -21536,7 +21669,7 @@ function CombatLog({
21536
21669
  /* @__PURE__ */ jsx(Box, { className: cn("flex-shrink-0 mt-0.5", colorClass), children: /* @__PURE__ */ jsx(EventIcon, { className: "h-4 w-4" }) }),
21537
21670
  /* @__PURE__ */ jsxs(Box, { className: "flex-1 min-w-0", children: [
21538
21671
  /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "block", children: event.message }),
21539
- event.value !== void 0 && /* @__PURE__ */ jsxs(Badge, { variant: eventBadgeVariants[eventType], size: "sm", className: "mt-1", children: [
21672
+ event.value !== void 0 && /* @__PURE__ */ jsxs("span", { className: cn("inline-block mt-1 text-xs font-bold rounded px-1.5 py-0.5 border", eventValueColors[eventType]), children: [
21540
21673
  eventType === "heal" ? "+" : eventType === "attack" ? "-" : "",
21541
21674
  event.value
21542
21675
  ] })
@@ -21549,7 +21682,7 @@ function CombatLog({
21549
21682
  }) }) })
21550
21683
  ] });
21551
21684
  }
21552
- var eventIcons, eventColors, eventBadgeVariants, DEFAULT_COMBAT_EVENTS;
21685
+ var eventIcons, eventColors, eventValueColors, DEFAULT_COMBAT_EVENTS;
21553
21686
  var init_CombatLog = __esm({
21554
21687
  "components/game/molecules/CombatLog.tsx"() {
21555
21688
  init_atoms2();
@@ -21572,14 +21705,14 @@ var init_CombatLog = __esm({
21572
21705
  death: "text-muted-foreground",
21573
21706
  spawn: "text-accent"
21574
21707
  };
21575
- eventBadgeVariants = {
21576
- attack: "danger",
21577
- defend: "primary",
21578
- heal: "success",
21579
- move: "warning",
21580
- special: "secondary",
21581
- death: "secondary",
21582
- spawn: "secondary"
21708
+ eventValueColors = {
21709
+ attack: "text-error bg-error/10 border-error/30",
21710
+ defend: "text-info bg-info/10 border-info/30",
21711
+ heal: "text-success bg-success/10 border-success/30",
21712
+ move: "text-warning bg-warning/10 border-warning/30",
21713
+ special: "text-accent bg-accent/10 border-accent/30",
21714
+ death: "text-muted-foreground bg-muted/30 border-border",
21715
+ spawn: "text-accent bg-accent/10 border-accent/30"
21583
21716
  };
21584
21717
  DEFAULT_COMBAT_EVENTS = [
21585
21718
  { id: "e1", type: "spawn", message: "Shadow Guard entered the field.", timestamp: 0, turn: 1 },
@@ -21610,7 +21743,7 @@ function ComboCounter({
21610
21743
  size = "md",
21611
21744
  className
21612
21745
  }) {
21613
- const sizes = sizeMap4[size];
21746
+ const sizes = sizeMap5[size];
21614
21747
  if (combo <= 0) return null;
21615
21748
  return /* @__PURE__ */ jsxs(
21616
21749
  "div",
@@ -21648,12 +21781,12 @@ function ComboCounter({
21648
21781
  }
21649
21782
  );
21650
21783
  }
21651
- var DEFAULT_ASSET_URL3, sizeMap4;
21784
+ var DEFAULT_ASSET_URL3, sizeMap5;
21652
21785
  var init_ComboCounter = __esm({
21653
21786
  "components/game/atoms/ComboCounter.tsx"() {
21654
21787
  init_cn();
21655
21788
  DEFAULT_ASSET_URL3 = "https://almadar-kflow-assets.web.app/shared/effects/flash/flash00.png";
21656
- sizeMap4 = {
21789
+ sizeMap5 = {
21657
21790
  sm: { combo: "text-lg", label: "text-xs", multiplier: "text-xs" },
21658
21791
  md: { combo: "text-2xl", label: "text-xs", multiplier: "text-sm" },
21659
21792
  lg: { combo: "text-4xl", label: "text-sm", multiplier: "text-base" }
@@ -22084,7 +22217,7 @@ function ItemSlot({
22084
22217
  className: cn(
22085
22218
  "relative flex items-center justify-center rounded-interactive border-2",
22086
22219
  "bg-card/80 transition-all duration-150",
22087
- sizeMap5[size],
22220
+ sizeMap6[size],
22088
22221
  empty ? "border-border bg-card/50" : rarityBorderMap[rarity],
22089
22222
  !empty && rarityGlowMap[rarity],
22090
22223
  selected && "ring-2 ring-foreground ring-offset-1 ring-offset-background",
@@ -22120,13 +22253,13 @@ function ItemSlot({
22120
22253
  }
22121
22254
  );
22122
22255
  }
22123
- var sizeMap5, rarityBorderMap, rarityGlowMap, DEFAULT_ASSET_URL4, assetSizeMap;
22256
+ var sizeMap6, rarityBorderMap, rarityGlowMap, DEFAULT_ASSET_URL4, assetSizeMap;
22124
22257
  var init_ItemSlot = __esm({
22125
22258
  "components/game/atoms/ItemSlot.tsx"() {
22126
22259
  "use client";
22127
22260
  init_cn();
22128
22261
  init_Icon();
22129
- sizeMap5 = {
22262
+ sizeMap6 = {
22130
22263
  sm: "w-10 h-10 text-lg",
22131
22264
  md: "w-14 h-14 text-2xl",
22132
22265
  lg: "w-18 h-18 text-3xl"
@@ -22167,7 +22300,7 @@ function CraftingRecipe({
22167
22300
  className
22168
22301
  }) {
22169
22302
  const eventBus = useEventBus();
22170
- const handleCraft = React80.useCallback(() => {
22303
+ const handleCraft = React85.useCallback(() => {
22171
22304
  onCraft?.();
22172
22305
  if (craftEvent) {
22173
22306
  eventBus.emit(craftEvent, { output: output.label });
@@ -22184,7 +22317,7 @@ function CraftingRecipe({
22184
22317
  children: [
22185
22318
  /* @__PURE__ */ jsx(HStack, { gap: "xs", className: "flex-wrap items-center", children: inputs.map((ingredient, index) => {
22186
22319
  const hasSufficient = ingredient.available >= ingredient.required;
22187
- return /* @__PURE__ */ jsxs(React80.Fragment, { children: [
22320
+ return /* @__PURE__ */ jsxs(React85.Fragment, { children: [
22188
22321
  /* @__PURE__ */ jsx(Box, { className: "relative", children: /* @__PURE__ */ jsx(
22189
22322
  ItemSlot,
22190
22323
  {
@@ -22209,13 +22342,13 @@ function CraftingRecipe({
22209
22342
  }
22210
22343
  ),
22211
22344
  /* @__PURE__ */ jsx(
22212
- Button,
22345
+ ActionButton,
22213
22346
  {
22347
+ label: "Craft",
22214
22348
  onClick: handleCraft,
22215
22349
  disabled: !canCraft,
22216
22350
  variant: canCraft ? "primary" : "secondary",
22217
- size: "sm",
22218
- children: "Craft"
22351
+ size: "sm"
22219
22352
  }
22220
22353
  )
22221
22354
  ]
@@ -22229,7 +22362,7 @@ var init_CraftingRecipe = __esm({
22229
22362
  init_cn();
22230
22363
  init_useEventBus();
22231
22364
  init_ItemSlot();
22232
- init_Button();
22365
+ init_ActionButton();
22233
22366
  init_Box();
22234
22367
  init_Stack();
22235
22368
  init_Icon();
@@ -22255,9 +22388,9 @@ function DPad({
22255
22388
  disabled
22256
22389
  }) {
22257
22390
  const eventBus = useEventBus();
22258
- const sizes = sizeMap6[size];
22259
- const [activeDirections, setActiveDirections] = React80.useState(/* @__PURE__ */ new Set());
22260
- const handlePress = React80.useCallback(
22391
+ const sizes = sizeMap7[size];
22392
+ const [activeDirections, setActiveDirections] = React85.useState(/* @__PURE__ */ new Set());
22393
+ const handlePress = React85.useCallback(
22261
22394
  (direction) => {
22262
22395
  setActiveDirections((prev) => new Set(prev).add(direction));
22263
22396
  if (directionEvent) eventBus.emit(`UI:${directionEvent}`, { direction, pressed: true });
@@ -22265,7 +22398,7 @@ function DPad({
22265
22398
  },
22266
22399
  [directionEvent, eventBus, onDirection]
22267
22400
  );
22268
- const handleRelease = React80.useCallback(
22401
+ const handleRelease = React85.useCallback(
22269
22402
  (direction) => {
22270
22403
  setActiveDirections((prev) => {
22271
22404
  const next = new Set(prev);
@@ -22302,14 +22435,14 @@ function DPad({
22302
22435
  /* @__PURE__ */ jsx("div", {})
22303
22436
  ] });
22304
22437
  }
22305
- var sizeMap6, arrowIcons;
22438
+ var sizeMap7, arrowIcons;
22306
22439
  var init_DPad = __esm({
22307
22440
  "components/game/molecules/DPad.tsx"() {
22308
22441
  "use client";
22309
22442
  init_cn();
22310
22443
  init_useEventBus();
22311
22444
  init_ControlButton();
22312
- sizeMap6 = {
22445
+ sizeMap7 = {
22313
22446
  sm: { button: "sm", gap: "gap-0.5", container: "w-28" },
22314
22447
  md: { button: "md", gap: "gap-1", container: "w-40" },
22315
22448
  lg: { button: "lg", gap: "gap-1.5", container: "w-52" }
@@ -22338,7 +22471,7 @@ function DamageNumber({
22338
22471
  {
22339
22472
  className: cn(
22340
22473
  "inline-flex items-center gap-0.5 font-mono select-none pointer-events-none",
22341
- sizeMap7[size],
22474
+ sizeMap8[size],
22342
22475
  typeStyles[type],
22343
22476
  className
22344
22477
  ),
@@ -22361,11 +22494,11 @@ function DamageNumber({
22361
22494
  )
22362
22495
  ] });
22363
22496
  }
22364
- var sizeMap7, typeStyles, floatKeyframes, DEFAULT_ASSET_URL5;
22497
+ var sizeMap8, typeStyles, floatKeyframes, DEFAULT_ASSET_URL5;
22365
22498
  var init_DamageNumber = __esm({
22366
22499
  "components/game/atoms/DamageNumber.tsx"() {
22367
22500
  init_cn();
22368
- sizeMap7 = {
22501
+ sizeMap8 = {
22369
22502
  sm: "text-sm",
22370
22503
  md: "text-lg",
22371
22504
  lg: "text-2xl"
@@ -23214,8 +23347,8 @@ var init_Menu = __esm({
23214
23347
  "bottom-end": "bottom-start"
23215
23348
  };
23216
23349
  const effectivePosition = direction === "rtl" ? rtlMirror[position] ?? position : position;
23217
- const triggerChild = React80__default.isValidElement(trigger) ? trigger : /* @__PURE__ */ jsx(Typography, { variant: "small", as: "span", children: trigger });
23218
- const triggerElement = React80__default.cloneElement(
23350
+ const triggerChild = React85__default.isValidElement(trigger) ? trigger : /* @__PURE__ */ jsx(Typography, { variant: "small", as: "span", children: trigger });
23351
+ const triggerElement = React85__default.cloneElement(
23219
23352
  triggerChild,
23220
23353
  {
23221
23354
  ref: triggerRef,
@@ -23310,14 +23443,14 @@ function useDataDnd(args) {
23310
23443
  const isZone = Boolean(dragGroup || accepts || sortable);
23311
23444
  const enabled = isZone || Boolean(dndRoot);
23312
23445
  const eventBus = useEventBus();
23313
- const parentRoot = React80__default.useContext(RootCtx);
23446
+ const parentRoot = React85__default.useContext(RootCtx);
23314
23447
  const isRoot = enabled && parentRoot === null;
23315
- const zoneId = React80__default.useId();
23448
+ const zoneId = React85__default.useId();
23316
23449
  const ownGroup = dragGroup ?? accepts ?? zoneId;
23317
- const [optimisticOrders, setOptimisticOrders] = React80__default.useState(() => /* @__PURE__ */ new Map());
23318
- const optimisticOrdersRef = React80__default.useRef(optimisticOrders);
23450
+ const [optimisticOrders, setOptimisticOrders] = React85__default.useState(() => /* @__PURE__ */ new Map());
23451
+ const optimisticOrdersRef = React85__default.useRef(optimisticOrders);
23319
23452
  optimisticOrdersRef.current = optimisticOrders;
23320
- const clearOptimisticOrder = React80__default.useCallback((group) => {
23453
+ const clearOptimisticOrder = React85__default.useCallback((group) => {
23321
23454
  setOptimisticOrders((prev) => {
23322
23455
  if (!prev.has(group)) return prev;
23323
23456
  const next = new Map(prev);
@@ -23340,17 +23473,20 @@ function useDataDnd(args) {
23340
23473
  }
23341
23474
  const itemIdsSignature = orderedItems.map((it, idx) => {
23342
23475
  const raw = it[dndItemIdField];
23343
- return String(raw ?? `__idx_${idx}`);
23476
+ return raw != null ? String(raw) : `__idx_${idx}`;
23344
23477
  }).join("|");
23345
- const itemIds = React80__default.useMemo(
23478
+ const itemIds = React85__default.useMemo(
23346
23479
  () => orderedItems.map((it, idx) => {
23347
23480
  const raw = it[dndItemIdField];
23348
- return raw ?? `__idx_${idx}`;
23481
+ return raw != null ? String(raw) : `__idx_${idx}`;
23349
23482
  }),
23350
23483
  [itemIdsSignature]
23351
23484
  );
23352
- const itemsContentSig = items.map((it, idx) => String(it[dndItemIdField] ?? `__${idx}`)).join("|");
23353
- React80__default.useEffect(() => {
23485
+ const itemsContentSig = items.map((it, idx) => {
23486
+ const raw = it[dndItemIdField];
23487
+ return raw != null ? String(raw) : `__${idx}`;
23488
+ }).join("|");
23489
+ React85__default.useEffect(() => {
23354
23490
  const root = isRoot ? null : parentRoot;
23355
23491
  if (root) {
23356
23492
  root.clearOptimisticOrder(ownGroup);
@@ -23358,20 +23494,20 @@ function useDataDnd(args) {
23358
23494
  clearOptimisticOrder(ownGroup);
23359
23495
  }
23360
23496
  }, [itemsContentSig, ownGroup]);
23361
- const zonesRef = React80__default.useRef(/* @__PURE__ */ new Map());
23362
- const registerZone = React80__default.useCallback((zoneId2, meta2) => {
23497
+ const zonesRef = React85__default.useRef(/* @__PURE__ */ new Map());
23498
+ const registerZone = React85__default.useCallback((zoneId2, meta2) => {
23363
23499
  zonesRef.current.set(zoneId2, meta2);
23364
23500
  }, []);
23365
- const unregisterZone = React80__default.useCallback((zoneId2) => {
23501
+ const unregisterZone = React85__default.useCallback((zoneId2) => {
23366
23502
  zonesRef.current.delete(zoneId2);
23367
23503
  }, []);
23368
- const [activeDrag, setActiveDrag] = React80__default.useState(null);
23369
- const [overZoneGroup, setOverZoneGroup] = React80__default.useState(null);
23370
- const meta = React80__default.useMemo(
23504
+ const [activeDrag, setActiveDrag] = React85__default.useState(null);
23505
+ const [overZoneGroup, setOverZoneGroup] = React85__default.useState(null);
23506
+ const meta = React85__default.useMemo(
23371
23507
  () => ({ group: ownGroup, dropEvent, reorderEvent, positionEvent, itemIds, rawItems: items, idField: dndItemIdField }),
23372
23508
  [ownGroup, dropEvent, reorderEvent, positionEvent, itemIds, items, dndItemIdField]
23373
23509
  );
23374
- React80__default.useEffect(() => {
23510
+ React85__default.useEffect(() => {
23375
23511
  const target = isRoot ? null : parentRoot;
23376
23512
  if (!target) {
23377
23513
  zonesRef.current.set(zoneId, meta);
@@ -23390,7 +23526,7 @@ function useDataDnd(args) {
23390
23526
  }, [parentRoot, isRoot, zoneId, meta]);
23391
23527
  const sensors = useAlmadarDndSensors(true);
23392
23528
  const collisionDetection = almadarDndCollisionDetection;
23393
- const findZoneByItem = React80__default.useCallback(
23529
+ const findZoneByItem = React85__default.useCallback(
23394
23530
  (id) => {
23395
23531
  for (const z of zonesRef.current.values()) {
23396
23532
  if (z.itemIds.includes(id)) return z;
@@ -23399,7 +23535,7 @@ function useDataDnd(args) {
23399
23535
  },
23400
23536
  []
23401
23537
  );
23402
- React80__default.useCallback(
23538
+ React85__default.useCallback(
23403
23539
  (group) => {
23404
23540
  for (const z of zonesRef.current.values()) {
23405
23541
  if (z.group === group) return z;
@@ -23408,7 +23544,7 @@ function useDataDnd(args) {
23408
23544
  },
23409
23545
  []
23410
23546
  );
23411
- const handleDragEnd = React80__default.useCallback(
23547
+ const handleDragEnd = React85__default.useCallback(
23412
23548
  (event) => {
23413
23549
  const { active, over } = event;
23414
23550
  const activeIdStr = String(active.id);
@@ -23499,8 +23635,8 @@ function useDataDnd(args) {
23499
23635
  },
23500
23636
  [eventBus]
23501
23637
  );
23502
- const sortableData = React80__default.useMemo(() => ({ dndGroup: ownGroup }), [ownGroup]);
23503
- const SortableItem = React80__default.useCallback(
23638
+ const sortableData = React85__default.useMemo(() => ({ dndGroup: ownGroup }), [ownGroup]);
23639
+ const SortableItem = React85__default.useCallback(
23504
23640
  ({ id, children }) => {
23505
23641
  const {
23506
23642
  attributes,
@@ -23540,7 +23676,7 @@ function useDataDnd(args) {
23540
23676
  id: droppableId,
23541
23677
  data: sortableData
23542
23678
  });
23543
- const ctx = React80__default.useContext(RootCtx);
23679
+ const ctx = React85__default.useContext(RootCtx);
23544
23680
  const activeDrag2 = ctx?.activeDrag ?? null;
23545
23681
  const overZoneGroup2 = ctx?.overZoneGroup ?? null;
23546
23682
  const isThisZoneOver = overZoneGroup2 === ownGroup;
@@ -23555,7 +23691,7 @@ function useDataDnd(args) {
23555
23691
  showForeignPlaceholder,
23556
23692
  ctxAvailable: ctx != null
23557
23693
  });
23558
- React80__default.useEffect(() => {
23694
+ React85__default.useEffect(() => {
23559
23695
  dndLog.info("dropzone:isOver:change", { droppableId, group: ownGroup, isOver, isThisZoneOver, showForeignPlaceholder, activeDragSourceGroup: activeDrag2?.sourceGroup ?? null });
23560
23696
  }, [droppableId, isOver, isThisZoneOver, showForeignPlaceholder]);
23561
23697
  return /* @__PURE__ */ jsx(
@@ -23569,11 +23705,11 @@ function useDataDnd(args) {
23569
23705
  }
23570
23706
  );
23571
23707
  };
23572
- const rootContextValue = React80__default.useMemo(
23708
+ const rootContextValue = React85__default.useMemo(
23573
23709
  () => ({ registerZone, unregisterZone, activeDrag, overZoneGroup, optimisticOrders, clearOptimisticOrder }),
23574
23710
  [registerZone, unregisterZone, activeDrag, overZoneGroup, optimisticOrders, clearOptimisticOrder]
23575
23711
  );
23576
- const handleDragStart = React80__default.useCallback((event) => {
23712
+ const handleDragStart = React85__default.useCallback((event) => {
23577
23713
  const sourceZone = findZoneByItem(event.active.id);
23578
23714
  const rect = event.active.rect.current.initial;
23579
23715
  const height = rect?.height && rect.height > 0 ? rect.height : 64;
@@ -23592,7 +23728,7 @@ function useDataDnd(args) {
23592
23728
  isRoot
23593
23729
  });
23594
23730
  }, [findZoneByItem, isRoot, zoneId]);
23595
- const handleDragOver = React80__default.useCallback((event) => {
23731
+ const handleDragOver = React85__default.useCallback((event) => {
23596
23732
  const { active, over } = event;
23597
23733
  const overData = over?.data?.current;
23598
23734
  const overGroup = overData?.dndGroup ?? null;
@@ -23662,7 +23798,7 @@ function useDataDnd(args) {
23662
23798
  return next;
23663
23799
  });
23664
23800
  }, []);
23665
- const handleDragCancel = React80__default.useCallback((event) => {
23801
+ const handleDragCancel = React85__default.useCallback((event) => {
23666
23802
  setActiveDrag(null);
23667
23803
  setOverZoneGroup(null);
23668
23804
  dndLog.warn("dragCancel", {
@@ -23670,12 +23806,12 @@ function useDataDnd(args) {
23670
23806
  reason: "dnd-kit cancelled the drag (escape key, pointer interrupted, or external)"
23671
23807
  });
23672
23808
  }, []);
23673
- const handleDragEndWithCleanup = React80__default.useCallback((event) => {
23809
+ const handleDragEndWithCleanup = React85__default.useCallback((event) => {
23674
23810
  handleDragEnd(event);
23675
23811
  setActiveDrag(null);
23676
23812
  setOverZoneGroup(null);
23677
23813
  }, [handleDragEnd]);
23678
- const wrapContainer = React80__default.useCallback(
23814
+ const wrapContainer = React85__default.useCallback(
23679
23815
  (children) => {
23680
23816
  if (!enabled) return children;
23681
23817
  const strategy = layout === "grid" ? rectSortingStrategy : verticalListSortingStrategy;
@@ -23729,7 +23865,7 @@ var init_useDataDnd = __esm({
23729
23865
  init_useAlmadarDndCollision();
23730
23866
  init_Box();
23731
23867
  dndLog = createLogger("almadar:ui:dnd");
23732
- RootCtx = React80__default.createContext(null);
23868
+ RootCtx = React85__default.createContext(null);
23733
23869
  }
23734
23870
  });
23735
23871
  function renderIconInput(icon, props) {
@@ -23872,8 +24008,8 @@ function DataGrid({
23872
24008
  const hasRenderProp = typeof children === "function";
23873
24009
  useEffect(() => {
23874
24010
  if (data.length > 0 && !hasRenderProp && fieldDefs.length === 0) {
23875
- const renderItemRaw = schemaRenderItem;
23876
- const isFnLambda = Array.isArray(renderItemRaw) && renderItemRaw.length >= 3 && (renderItemRaw[0] === "fn" || renderItemRaw[0] === "lambda");
24011
+ const schemaArr = Array.isArray(schemaRenderItem) ? schemaRenderItem : null;
24012
+ const isFnLambda = schemaArr !== null && schemaArr.length >= 3 && (schemaArr[0] === "fn" || schemaArr[0] === "lambda");
23877
24013
  dataGridLog.warn("renderItem-unresolved", {
23878
24014
  rowCount: data.length,
23879
24015
  renderItemIsFnLambda: isFnLambda
@@ -24255,7 +24391,7 @@ function DataList({
24255
24391
  }) {
24256
24392
  const eventBus = useEventBus();
24257
24393
  const { t } = useTranslate();
24258
- const [visibleCount, setVisibleCount] = React80__default.useState(pageSize || Infinity);
24394
+ const [visibleCount, setVisibleCount] = React85__default.useState(pageSize || Infinity);
24259
24395
  const fieldDefs = fields ?? columns ?? [];
24260
24396
  const allDataRaw = Array.isArray(entity) ? entity : entity ? [entity] : [];
24261
24397
  const dnd = useDataDnd({
@@ -24274,21 +24410,20 @@ function DataList({
24274
24410
  const data = pageSize > 0 ? allData.slice(0, visibleCount) : allData;
24275
24411
  const hasMoreLocal = pageSize > 0 && visibleCount < allData.length;
24276
24412
  const hasRenderProp = typeof children === "function";
24277
- React80__default.useEffect(() => {
24413
+ React85__default.useEffect(() => {
24278
24414
  const renderItemTypeOf = typeof schemaRenderItem;
24279
24415
  const childrenTypeOf = typeof children;
24280
24416
  if (data.length > 0 && !hasRenderProp) {
24281
24417
  const firstRow = data[0];
24282
24418
  const sampleKeys = firstRow ? Object.keys(firstRow).slice(0, 6) : [];
24283
- const renderItemRaw = schemaRenderItem;
24284
- const isFnLambda = Array.isArray(renderItemRaw) && renderItemRaw.length >= 3 && (renderItemRaw[0] === "fn" || renderItemRaw[0] === "lambda");
24419
+ const isFnLambda = Array.isArray(schemaRenderItem) && schemaRenderItem.length >= 3 && (schemaRenderItem[0] === "fn" || schemaRenderItem[0] === "lambda");
24285
24420
  dataListLog.warn("renderItem-unresolved", {
24286
24421
  rowCount: data.length,
24287
24422
  fieldsCount: fieldDefs.length,
24288
24423
  renderItemTypeOf,
24289
- renderItemIsArray: Array.isArray(renderItemRaw),
24424
+ renderItemIsArray: Array.isArray(schemaRenderItem),
24290
24425
  renderItemIsFnLambda: isFnLambda,
24291
- renderItemHead: Array.isArray(renderItemRaw) ? String(renderItemRaw[0]) : void 0,
24426
+ renderItemHead: Array.isArray(schemaRenderItem) ? String(schemaRenderItem[0]) : void 0,
24292
24427
  childrenTypeOf,
24293
24428
  sampleRowKeys: sampleKeys
24294
24429
  });
@@ -24376,10 +24511,10 @@ function DataList({
24376
24511
  const isCompact = variant === "compact";
24377
24512
  const isMessage = variant === "message";
24378
24513
  if (isMessage) {
24379
- const items2 = data.map((item) => item);
24514
+ const items2 = [...data];
24380
24515
  const groups2 = groupBy ? groupData(items2, groupBy) : [{ label: "", items: items2 }];
24381
24516
  const contentField = titleField?.name ?? fieldDefs[0]?.name ?? "";
24382
- return /* @__PURE__ */ jsx(VStack, { gap: "sm", className: cn("py-2", className), children: groups2.map((group, gi) => /* @__PURE__ */ jsxs(React80__default.Fragment, { children: [
24517
+ return /* @__PURE__ */ jsx(VStack, { gap: "sm", className: cn("py-2", className), children: groups2.map((group, gi) => /* @__PURE__ */ jsxs(React85__default.Fragment, { children: [
24383
24518
  group.label && /* @__PURE__ */ jsx(Divider, { label: group.label, className: "my-2" }),
24384
24519
  group.items.map((itemData, index) => {
24385
24520
  const id = itemData.id || `${gi}-${index}`;
@@ -24425,7 +24560,7 @@ function DataList({
24425
24560
  })
24426
24561
  ] }, gi)) });
24427
24562
  }
24428
- const items = data.map((item) => item);
24563
+ const items = [...data];
24429
24564
  const groups = groupBy ? groupData(items, groupBy) : [{ label: "", items }];
24430
24565
  const idFieldName = dndItemIdField ?? "id";
24431
24566
  const renderItem = (itemData, index, isLast) => {
@@ -24520,7 +24655,7 @@ function DataList({
24520
24655
  className
24521
24656
  ),
24522
24657
  children: [
24523
- groups.map((group, gi) => /* @__PURE__ */ jsxs(React80__default.Fragment, { children: [
24658
+ groups.map((group, gi) => /* @__PURE__ */ jsxs(React85__default.Fragment, { children: [
24524
24659
  group.label && /* @__PURE__ */ jsx(Divider, { label: group.label, className: gi > 0 ? "mt-4" : "mt-0" }),
24525
24660
  group.items.map(
24526
24661
  (itemData, index) => renderItem(itemData, index, gi === groups.length - 1 && index === group.items.length - 1)
@@ -24627,8 +24762,8 @@ function ScalarControl({
24627
24762
  }
24628
24763
  const numeric = typeof value === "number";
24629
24764
  const initial = value === null ? "" : String(value);
24630
- const [draft, setDraft] = React80__default.useState(initial);
24631
- React80__default.useEffect(() => setDraft(initial), [initial]);
24765
+ const [draft, setDraft] = React85__default.useState(initial);
24766
+ React85__default.useEffect(() => setDraft(initial), [initial]);
24632
24767
  const commit = () => {
24633
24768
  if (numeric) {
24634
24769
  const n = draft.trim() === "" ? 0 : Number(draft);
@@ -24696,8 +24831,8 @@ function Row({
24696
24831
  onRemove,
24697
24832
  readonly
24698
24833
  }) {
24699
- const [keyDraft, setKeyDraft] = React80__default.useState(rowKey);
24700
- React80__default.useEffect(() => setKeyDraft(rowKey), [rowKey]);
24834
+ const [keyDraft, setKeyDraft] = React85__default.useState(rowKey);
24835
+ React85__default.useEffect(() => setKeyDraft(rowKey), [rowKey]);
24701
24836
  const container = isObj(value) || isArr(value);
24702
24837
  return /* @__PURE__ */ jsxs(VStack, { gap: "none", className: "group w-max min-w-full", children: [
24703
24838
  /* @__PURE__ */ jsxs(HStack, { gap: "xs", align: "center", className: "py-0.5 w-max", children: [
@@ -24740,7 +24875,7 @@ function ContainerNode({
24740
24875
  depth,
24741
24876
  readonly
24742
24877
  }) {
24743
- const [open, setOpen] = React80__default.useState(depth < 2);
24878
+ const [open, setOpen] = React85__default.useState(depth < 2);
24744
24879
  const array = isArr(value);
24745
24880
  const entries = array ? value.map((v, i) => [String(i), v]) : Object.entries(value);
24746
24881
  const setObjValue = (key, next) => {
@@ -24882,7 +25017,7 @@ var init_FormSection = __esm({
24882
25017
  columns = 1,
24883
25018
  className
24884
25019
  }) => {
24885
- const [collapsed, setCollapsed] = React80__default.useState(defaultCollapsed);
25020
+ const [collapsed, setCollapsed] = React85__default.useState(defaultCollapsed);
24886
25021
  const { t } = useTranslate();
24887
25022
  const eventBus = useEventBus();
24888
25023
  const gridClass = {
@@ -24890,7 +25025,7 @@ var init_FormSection = __esm({
24890
25025
  2: "grid-cols-1 md:grid-cols-2",
24891
25026
  3: "grid-cols-1 md:grid-cols-2 lg:grid-cols-3"
24892
25027
  }[columns];
24893
- React80__default.useCallback(() => {
25028
+ React85__default.useCallback(() => {
24894
25029
  if (collapsible) {
24895
25030
  setCollapsed((prev) => !prev);
24896
25031
  eventBus.emit("UI:TOGGLE_COLLAPSE", { collapsed: !collapsed });
@@ -25298,8 +25433,8 @@ function TextLikeControl({
25298
25433
  onCommit
25299
25434
  }) {
25300
25435
  const initial = value === void 0 || value === null ? "" : String(value);
25301
- const [draft, setDraft] = React80__default.useState(initial);
25302
- React80__default.useEffect(() => setDraft(initial), [initial]);
25436
+ const [draft, setDraft] = React85__default.useState(initial);
25437
+ React85__default.useEffect(() => setDraft(initial), [initial]);
25303
25438
  const commit = () => {
25304
25439
  if (numeric) {
25305
25440
  const n = draft.trim() === "" ? 0 : Number(draft);
@@ -25465,14 +25600,14 @@ var init_NodeSlotEditor = __esm({
25465
25600
  isObj2 = (v) => v !== null && v !== void 0 && typeof v === "object" && !Array.isArray(v);
25466
25601
  NodeSlotEditor = ({ value, onChange, className }) => {
25467
25602
  const { type, props, wasArray } = normalize(value);
25468
- const patterns = React80__default.useMemo(() => {
25603
+ const patterns = React85__default.useMemo(() => {
25469
25604
  try {
25470
25605
  return [...getKnownPatterns()].sort();
25471
25606
  } catch {
25472
25607
  return [];
25473
25608
  }
25474
25609
  }, []);
25475
- const options = React80__default.useMemo(
25610
+ const options = React85__default.useMemo(
25476
25611
  () => [{ value: "", label: "\u2014 none \u2014" }, ...patterns.map((p2) => ({ value: p2, label: p2 }))],
25477
25612
  [patterns]
25478
25613
  );
@@ -25484,7 +25619,7 @@ var init_NodeSlotEditor = __esm({
25484
25619
  const pattern = { type: nextType, ...nextProps };
25485
25620
  onChange(wasArray || value === void 0 ? [pattern] : pattern);
25486
25621
  };
25487
- const schemaEntries = React80__default.useMemo(() => {
25622
+ const schemaEntries = React85__default.useMemo(() => {
25488
25623
  if (!type) return [];
25489
25624
  const def = getPatternDefinition(type);
25490
25625
  if (!def?.propsSchema) return [];
@@ -26255,23 +26390,19 @@ var init_Flex = __esm({
26255
26390
  flexStyle.flexBasis = typeof basis === "number" ? `${basis}px` : basis;
26256
26391
  }
26257
26392
  }
26258
- const Comp = Component2;
26259
- return /* @__PURE__ */ jsx(
26260
- Comp,
26261
- {
26262
- className: cn(
26263
- inline ? "inline-flex" : "flex",
26264
- directionStyles[direction],
26265
- wrapStyles[wrap],
26266
- alignStyles3[align],
26267
- justifyStyles2[justify],
26268
- gapStyles6[gap],
26269
- className
26270
- ),
26271
- style: Object.keys(flexStyle).length > 0 ? flexStyle : void 0,
26272
- children
26273
- }
26274
- );
26393
+ return React85__default.createElement(Component2, {
26394
+ className: cn(
26395
+ inline ? "inline-flex" : "flex",
26396
+ directionStyles[direction],
26397
+ wrapStyles[wrap],
26398
+ alignStyles3[align],
26399
+ justifyStyles2[justify],
26400
+ gapStyles6[gap],
26401
+ className
26402
+ ),
26403
+ style: Object.keys(flexStyle).length > 0 ? flexStyle : void 0,
26404
+ children
26405
+ });
26275
26406
  };
26276
26407
  Flex.displayName = "Flex";
26277
26408
  }
@@ -26378,7 +26509,7 @@ var init_Grid = __esm({
26378
26509
  as: Component2 = "div"
26379
26510
  }) => {
26380
26511
  const mergedStyle = rows2 ? { gridTemplateRows: `repeat(${rows2}, minmax(0, 1fr))`, ...style } : style;
26381
- return React80__default.createElement(
26512
+ return React85__default.createElement(
26382
26513
  Component2,
26383
26514
  {
26384
26515
  className: cn(
@@ -26574,9 +26705,9 @@ var init_Popover = __esm({
26574
26705
  onMouseLeave: handleClose,
26575
26706
  onPointerDown: tapTriggerProps.onPointerDown
26576
26707
  };
26577
- const childElement = React80__default.isValidElement(children) ? children : /* @__PURE__ */ jsx("span", { children });
26708
+ const childElement = React85__default.isValidElement(children) ? children : /* @__PURE__ */ jsx("span", { children });
26578
26709
  const childPointerDown = childElement.props.onPointerDown;
26579
- const triggerElement = React80__default.cloneElement(
26710
+ const triggerElement = React85__default.cloneElement(
26580
26711
  childElement,
26581
26712
  {
26582
26713
  ref: triggerRef,
@@ -27428,9 +27559,9 @@ var init_Tooltip = __esm({
27428
27559
  if (hideTimeoutRef.current) clearTimeout(hideTimeoutRef.current);
27429
27560
  };
27430
27561
  }, []);
27431
- const triggerElement = React80__default.isValidElement(children) ? children : /* @__PURE__ */ jsx("span", { children });
27562
+ const triggerElement = React85__default.isValidElement(children) ? children : /* @__PURE__ */ jsx("span", { children });
27432
27563
  const childPointerDown = triggerElement.props.onPointerDown;
27433
- const trigger = React80__default.cloneElement(triggerElement, {
27564
+ const trigger = React85__default.cloneElement(triggerElement, {
27434
27565
  ref: triggerRef,
27435
27566
  onMouseEnter: handleMouseEnter,
27436
27567
  onMouseLeave: handleMouseLeave,
@@ -27520,7 +27651,7 @@ var init_WizardProgress = __esm({
27520
27651
  children: /* @__PURE__ */ jsx("div", { className: "flex items-center gap-2", children: normalizedSteps.map((step, index) => {
27521
27652
  const isActive = index === currentStep;
27522
27653
  const isCompleted = index < currentStep;
27523
- return /* @__PURE__ */ jsxs(React80__default.Fragment, { children: [
27654
+ return /* @__PURE__ */ jsxs(React85__default.Fragment, { children: [
27524
27655
  /* @__PURE__ */ jsx(
27525
27656
  "button",
27526
27657
  {
@@ -27832,13 +27963,14 @@ var init_ViolationAlert = __esm({
27832
27963
  onNavigateToField,
27833
27964
  compact = false,
27834
27965
  className,
27835
- ...flatProps
27966
+ message
27836
27967
  }) => {
27837
27968
  const { t } = useTranslate();
27969
+ const fallbackMessage = message ?? t("violationAlert.fallbackMessage");
27838
27970
  const resolvedViolation = violation ?? {
27839
27971
  law: "",
27840
27972
  article: "",
27841
- message: flatProps.message ?? t("violationAlert.fallbackMessage"),
27973
+ message: fallbackMessage,
27842
27974
  actionType: "measure"
27843
27975
  };
27844
27976
  const effectiveSeverity = severity ?? (resolvedViolation.actionType === "measure" ? "warning" : "error");
@@ -28421,13 +28553,13 @@ var init_LineChart = __esm({
28421
28553
  LineChart2.displayName = "LineChart";
28422
28554
  }
28423
28555
  });
28424
- var sizeMap8, stateColors, ProgressDots;
28556
+ var sizeMap9, stateColors, ProgressDots;
28425
28557
  var init_ProgressDots = __esm({
28426
28558
  "components/core/molecules/ProgressDots.tsx"() {
28427
28559
  "use client";
28428
28560
  init_cn();
28429
28561
  init_atoms2();
28430
- sizeMap8 = {
28562
+ sizeMap9 = {
28431
28563
  sm: { dot: 6, active: 8 },
28432
28564
  md: { dot: 8, active: 10 },
28433
28565
  lg: { dot: 10, active: 14 }
@@ -28453,7 +28585,7 @@ var init_ProgressDots = __esm({
28453
28585
  [currentIndex]
28454
28586
  );
28455
28587
  const resolveState = getState2 ?? defaultGetState;
28456
- const dims = sizeMap8[size];
28588
+ const dims = sizeMap9[size];
28457
28589
  return /* @__PURE__ */ jsx(HStack, { gap: "xs", align: "center", className: cn(className), children: Array.from({ length: count }, (_, index) => {
28458
28590
  const state = resolveState(index);
28459
28591
  const isActive = state === "active";
@@ -28480,124 +28612,24 @@ var init_ProgressDots = __esm({
28480
28612
  ProgressDots.displayName = "ProgressDots";
28481
28613
  }
28482
28614
  });
28483
- function HealthBar({
28484
- current = 3,
28485
- max = 5,
28486
- format = "hearts",
28487
- size = "md",
28488
- className,
28489
- animated = true
28490
- }) {
28491
- const sizes = sizeMap9[size];
28492
- const percentage = Math.max(0, Math.min(100, current / max * 100));
28493
- if (format === "hearts") {
28494
- return /* @__PURE__ */ jsx("div", { className: cn("flex items-center gap-1", className), children: Array.from({ length: max }).map((_, i) => /* @__PURE__ */ jsx(
28495
- "span",
28496
- {
28497
- className: cn(animated && "transition-transform hover:scale-110"),
28498
- children: heartIcon(i < current, sizes.heart)
28499
- },
28500
- i
28501
- )) });
28502
- }
28503
- if (format === "bar") {
28504
- return /* @__PURE__ */ jsx(
28505
- "div",
28506
- {
28507
- className: cn(
28508
- "relative overflow-hidden rounded-full bg-muted",
28509
- sizes.bar,
28510
- "w-24",
28511
- className
28512
- ),
28513
- children: /* @__PURE__ */ jsx(
28514
- "div",
28515
- {
28516
- className: cn(
28517
- "absolute inset-y-0 left-0 rounded-full",
28518
- percentage > 66 ? "bg-success" : percentage > 33 ? "bg-warning" : "bg-error",
28519
- animated && "transition-all duration-300"
28520
- ),
28521
- style: { width: `${percentage}%` }
28522
- }
28523
- )
28524
- }
28525
- );
28526
- }
28527
- return /* @__PURE__ */ jsxs("span", { className: cn("font-mono font-bold", sizes.text, className), children: [
28528
- current,
28529
- "/",
28530
- max
28531
- ] });
28532
- }
28533
- var heartIcon, sizeMap9;
28534
- var init_HealthBar = __esm({
28535
- "components/game/atoms/HealthBar.tsx"() {
28536
- init_cn();
28537
- heartIcon = (filled, size) => /* @__PURE__ */ jsx(
28538
- "svg",
28539
- {
28540
- className: cn("transition-all duration-200", size, filled ? "text-error" : "text-muted-foreground"),
28541
- viewBox: "0 0 24 24",
28542
- fill: filled ? "currentColor" : "none",
28543
- stroke: "currentColor",
28544
- strokeWidth: filled ? 0 : 2,
28545
- children: /* @__PURE__ */ jsx("path", { d: "M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z" })
28546
- }
28547
- );
28548
- sizeMap9 = {
28549
- sm: { heart: "w-4 h-4", bar: "h-2", text: "text-sm" },
28550
- md: { heart: "w-6 h-6", bar: "h-3", text: "text-base" },
28551
- lg: { heart: "w-8 h-8", bar: "h-4", text: "text-lg" }
28552
- };
28553
- HealthBar.displayName = "HealthBar";
28554
- }
28555
- });
28556
28615
  function ScoreDisplay({
28557
28616
  assetUrl = DEFAULT_ASSET_URL6,
28558
28617
  value,
28618
+ score,
28559
28619
  label,
28560
28620
  icon,
28561
28621
  size = "md",
28562
28622
  className,
28563
- animated = true,
28564
- locale = "en-US",
28565
- ...rest
28623
+ locale = "en-US"
28566
28624
  }) {
28567
- const resolvedValue = typeof value === "number" && !Number.isNaN(value) ? value : typeof rest.score === "number" && !Number.isNaN(rest.score) ? rest.score : 0;
28568
- const [displayValue, setDisplayValue] = React80.useState(resolvedValue);
28569
- const [isAnimating, setIsAnimating] = React80.useState(false);
28570
- React80.useEffect(() => {
28571
- if (!animated || displayValue === resolvedValue) {
28572
- setDisplayValue(resolvedValue);
28573
- return;
28574
- }
28575
- setIsAnimating(true);
28576
- const diff = resolvedValue - displayValue;
28577
- const steps = Math.min(Math.abs(diff), 20);
28578
- const increment = diff / steps;
28579
- let current = displayValue;
28580
- let step = 0;
28581
- const timer = setInterval(() => {
28582
- step++;
28583
- current += increment;
28584
- setDisplayValue(Math.round(current));
28585
- if (step >= steps) {
28586
- clearInterval(timer);
28587
- setDisplayValue(resolvedValue);
28588
- setIsAnimating(false);
28589
- }
28590
- }, 50);
28591
- return () => clearInterval(timer);
28592
- }, [resolvedValue, animated]);
28593
- const formattedValue = new Intl.NumberFormat(locale).format(displayValue);
28625
+ const resolvedValue = typeof value === "number" && !Number.isNaN(value) ? value : typeof score === "number" && !Number.isNaN(score) ? score : 0;
28626
+ const formattedValue = new Intl.NumberFormat(locale).format(resolvedValue);
28594
28627
  return /* @__PURE__ */ jsxs(
28595
28628
  "div",
28596
28629
  {
28597
28630
  className: cn(
28598
28631
  "flex items-center gap-2 font-bold",
28599
28632
  sizeMap10[size],
28600
- isAnimating && "animate-pulse",
28601
28633
  className
28602
28634
  ),
28603
28635
  children: [
@@ -28621,7 +28653,6 @@ function ScoreDisplay({
28621
28653
  var sizeMap10, DEFAULT_ASSET_URL6;
28622
28654
  var init_ScoreDisplay = __esm({
28623
28655
  "components/game/atoms/ScoreDisplay.tsx"() {
28624
- "use client";
28625
28656
  init_cn();
28626
28657
  init_Icon();
28627
28658
  sizeMap10 = {
@@ -28636,6 +28667,7 @@ var init_ScoreDisplay = __esm({
28636
28667
  });
28637
28668
  function StatBadge({
28638
28669
  assetUrl,
28670
+ iconUrl,
28639
28671
  label,
28640
28672
  value = 0,
28641
28673
  max,
@@ -28649,6 +28681,7 @@ function StatBadge({
28649
28681
  field: _field
28650
28682
  }) {
28651
28683
  const numValue = typeof value === "number" ? value : parseInt(String(value), 10) || 0;
28684
+ const resolvedAsset = iconUrl ?? assetUrl;
28652
28685
  return /* @__PURE__ */ jsxs(
28653
28686
  "div",
28654
28687
  {
@@ -28659,10 +28692,10 @@ function StatBadge({
28659
28692
  className
28660
28693
  ),
28661
28694
  children: [
28662
- assetUrl ? /* @__PURE__ */ jsx(
28695
+ resolvedAsset ? /* @__PURE__ */ jsx(
28663
28696
  "img",
28664
28697
  {
28665
- src: assetUrl,
28698
+ src: resolvedAsset,
28666
28699
  alt: "",
28667
28700
  width: 16,
28668
28701
  height: 16,
@@ -28693,8 +28726,7 @@ function StatBadge({
28693
28726
  ScoreDisplay,
28694
28727
  {
28695
28728
  value: numValue,
28696
- size: size === "lg" ? "md" : "sm",
28697
- animated: true
28729
+ size: size === "lg" ? "md" : "sm"
28698
28730
  }
28699
28731
  ),
28700
28732
  format === "text" && /* @__PURE__ */ jsx("span", { className: "font-bold text-foreground", children: value })
@@ -28737,7 +28769,7 @@ function InventoryGrid({
28737
28769
  const eventBus = useEventBus();
28738
28770
  const slotCount = totalSlots ?? items.length;
28739
28771
  const emptySlotCount = Math.max(0, slotCount - items.length);
28740
- const handleSelect = React80.useCallback(
28772
+ const handleSelect = React85.useCallback(
28741
28773
  (id) => {
28742
28774
  onSelect?.(id);
28743
28775
  if (selectEvent) {
@@ -28926,12 +28958,14 @@ function QuestTracker({
28926
28958
  }
28927
28959
  ),
28928
28960
  /* @__PURE__ */ jsx(Box, { className: "mt-1.5", children: /* @__PURE__ */ jsx(
28929
- ProgressBar,
28961
+ HealthBar,
28930
28962
  {
28931
- value: quest.progress,
28963
+ current: quest.progress,
28932
28964
  max: quest.maxProgress,
28933
- variant: isCompleted ? "success" : isActive ? "primary" : "default",
28934
- size: "sm"
28965
+ format: "bar",
28966
+ size: "sm",
28967
+ animated: true,
28968
+ className: isCompleted ? "[--health-color:var(--color-success)]" : isActive ? "" : "opacity-60"
28935
28969
  }
28936
28970
  ) }),
28937
28971
  /* @__PURE__ */ jsxs(
@@ -28959,7 +28993,7 @@ var init_QuestTracker = __esm({
28959
28993
  "use client";
28960
28994
  init_cn();
28961
28995
  init_WaypointMarker();
28962
- init_ProgressBar();
28996
+ init_HealthBar();
28963
28997
  init_Typography();
28964
28998
  init_Box();
28965
28999
  init_Stack();
@@ -29054,31 +29088,31 @@ function GameCanvas2D({
29054
29088
  assetBaseUrl,
29055
29089
  className
29056
29090
  }) {
29057
- const canvasRef = React80.useRef(null);
29058
- const rafRef = React80.useRef(0);
29059
- const frameRef = React80.useRef(0);
29060
- const lastTimeRef = React80.useRef(0);
29061
- const imageCache = React80.useRef(/* @__PURE__ */ new Map());
29091
+ const canvasRef = React85.useRef(null);
29092
+ const rafRef = React85.useRef(0);
29093
+ const frameRef = React85.useRef(0);
29094
+ const lastTimeRef = React85.useRef(0);
29095
+ const imageCache = React85.useRef(/* @__PURE__ */ new Map());
29062
29096
  const emit = useEmitEvent();
29063
- const onDrawRef = React80.useRef(onDraw);
29097
+ const onDrawRef = React85.useRef(onDraw);
29064
29098
  onDrawRef.current = onDraw;
29065
- const onTickRef = React80.useRef(onTick);
29099
+ const onTickRef = React85.useRef(onTick);
29066
29100
  onTickRef.current = onTick;
29067
- const tickEventRef = React80.useRef(tickEvent);
29101
+ const tickEventRef = React85.useRef(tickEvent);
29068
29102
  tickEventRef.current = tickEvent;
29069
- const drawEventRef = React80.useRef(drawEvent);
29103
+ const drawEventRef = React85.useRef(drawEvent);
29070
29104
  drawEventRef.current = drawEvent;
29071
- const emitRef = React80.useRef(emit);
29105
+ const emitRef = React85.useRef(emit);
29072
29106
  emitRef.current = emit;
29073
- const assetBaseUrlRef = React80.useRef(assetBaseUrl);
29107
+ const assetBaseUrlRef = React85.useRef(assetBaseUrl);
29074
29108
  assetBaseUrlRef.current = assetBaseUrl;
29075
- const backgroundImageRef = React80.useRef(backgroundImage);
29109
+ const backgroundImageRef = React85.useRef(backgroundImage);
29076
29110
  backgroundImageRef.current = backgroundImage;
29077
- const widthRef = React80.useRef(width);
29111
+ const widthRef = React85.useRef(width);
29078
29112
  widthRef.current = width;
29079
- const heightRef = React80.useRef(height);
29113
+ const heightRef = React85.useRef(height);
29080
29114
  heightRef.current = height;
29081
- const loadImage = React80.useCallback((url) => {
29115
+ const loadImage = React85.useCallback((url) => {
29082
29116
  const base = assetBaseUrlRef.current;
29083
29117
  if (!url.startsWith("http") && !base) return null;
29084
29118
  const fullUrl = url.startsWith("http") ? url : `${base}${url}`;
@@ -29092,7 +29126,7 @@ function GameCanvas2D({
29092
29126
  }
29093
29127
  return null;
29094
29128
  }, []);
29095
- React80.useEffect(() => {
29129
+ React85.useEffect(() => {
29096
29130
  const canvas = canvasRef.current;
29097
29131
  if (!canvas) return;
29098
29132
  const ctx = canvas.getContext("2d");
@@ -29155,6 +29189,90 @@ var init_GameCanvas2D = __esm({
29155
29189
  GameCanvas2D.displayName = "GameCanvas2D";
29156
29190
  }
29157
29191
  });
29192
+ function formatDuration(seconds) {
29193
+ if (seconds >= 60) {
29194
+ return `${Math.floor(seconds / 60)}m`;
29195
+ }
29196
+ return `${Math.round(seconds)}s`;
29197
+ }
29198
+ function StatusEffect({
29199
+ assetUrl = DEFAULT_ASSET_URL8,
29200
+ icon = "shield",
29201
+ label = "Shield",
29202
+ duration = 30,
29203
+ stacks,
29204
+ variant = "buff",
29205
+ size = "md",
29206
+ className
29207
+ }) {
29208
+ const sizes = sizeMap13[size];
29209
+ return /* @__PURE__ */ jsxs("div", { className: cn("relative inline-flex flex-col items-center", className), children: [
29210
+ /* @__PURE__ */ jsxs(
29211
+ "div",
29212
+ {
29213
+ className: cn(
29214
+ "relative flex items-center justify-center rounded-interactive border-2",
29215
+ sizes.container,
29216
+ variantStyles8[variant]
29217
+ ),
29218
+ title: label,
29219
+ children: [
29220
+ /* @__PURE__ */ jsx("span", { className: cn("flex items-center justify-center", sizes.icon), children: assetUrl ? /* @__PURE__ */ jsx(
29221
+ "img",
29222
+ {
29223
+ src: assetUrl,
29224
+ alt: label,
29225
+ width: sizes.img,
29226
+ height: sizes.img,
29227
+ style: { imageRendering: "pixelated", objectFit: "contain" },
29228
+ className: "flex-shrink-0"
29229
+ }
29230
+ ) : typeof icon === "string" ? /* @__PURE__ */ jsx(Icon, { name: icon, size: "sm" }) : /* @__PURE__ */ jsx(Icon, { icon, size: "sm" }) }),
29231
+ duration !== void 0 && /* @__PURE__ */ jsx(
29232
+ "span",
29233
+ {
29234
+ className: cn(
29235
+ "absolute bottom-0 left-0 right-0 text-center font-mono font-bold text-foreground bg-background/60 leading-tight",
29236
+ sizes.timer
29237
+ ),
29238
+ children: formatDuration(duration)
29239
+ }
29240
+ )
29241
+ ]
29242
+ }
29243
+ ),
29244
+ stacks !== void 0 && stacks > 1 && /* @__PURE__ */ jsx(
29245
+ "span",
29246
+ {
29247
+ className: cn(
29248
+ "absolute flex items-center justify-center rounded-full bg-card text-foreground font-bold leading-none",
29249
+ sizes.badge
29250
+ ),
29251
+ children: stacks
29252
+ }
29253
+ ),
29254
+ label && /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground mt-0.5 text-center whitespace-nowrap", children: label })
29255
+ ] });
29256
+ }
29257
+ var DEFAULT_ASSET_URL8, sizeMap13, variantStyles8;
29258
+ var init_StatusEffect = __esm({
29259
+ "components/game/atoms/StatusEffect.tsx"() {
29260
+ init_cn();
29261
+ init_Icon();
29262
+ DEFAULT_ASSET_URL8 = "https://almadar-kflow-assets.web.app/shared/effects/particles/flame_01.png";
29263
+ sizeMap13 = {
29264
+ sm: { container: "w-8 h-8", icon: "text-sm", badge: "text-xs -top-1 -right-1 w-4 h-4", timer: "text-[9px]", img: 20 },
29265
+ md: { container: "w-10 h-10", icon: "text-base", badge: "text-xs -top-1 -right-1 w-5 h-5", timer: "text-xs", img: 28 },
29266
+ lg: { container: "w-12 h-12", icon: "text-lg", badge: "text-sm -top-1.5 -right-1.5 w-6 h-6", timer: "text-xs", img: 36 }
29267
+ };
29268
+ variantStyles8 = {
29269
+ buff: "border-success bg-success/20",
29270
+ debuff: "border-error bg-error/20",
29271
+ neutral: "border-muted bg-muted/20"
29272
+ };
29273
+ StatusEffect.displayName = "StatusEffect";
29274
+ }
29275
+ });
29158
29276
  function HealthPanel({
29159
29277
  current = 75,
29160
29278
  max = 100,
@@ -29165,7 +29283,7 @@ function HealthPanel({
29165
29283
  size = "md",
29166
29284
  className
29167
29285
  }) {
29168
- const sizes = sizeMap13[size];
29286
+ const sizes = sizeMap14[size];
29169
29287
  return /* @__PURE__ */ jsx(
29170
29288
  Box,
29171
29289
  {
@@ -29240,26 +29358,14 @@ function HealthPanel({
29240
29358
  )
29241
29359
  }
29242
29360
  ),
29243
- effects && effects.length > 0 && /* @__PURE__ */ jsx(Box, { className: "flex items-center gap-1 flex-wrap", children: effects.map((effect, i) => /* @__PURE__ */ jsxs(
29244
- Badge,
29361
+ effects && effects.length > 0 && /* @__PURE__ */ jsx(Box, { className: "flex items-center gap-1 flex-wrap", children: effects.map((effect, i) => /* @__PURE__ */ jsx(
29362
+ StatusEffect,
29245
29363
  {
29364
+ assetUrl: effect.assetUrl,
29365
+ icon: effect.icon,
29366
+ label: effect.label,
29246
29367
  variant: effectVariantMap[effect.variant ?? "neutral"],
29247
- size: "sm",
29248
- icon: effect.assetUrl ? void 0 : effect.icon,
29249
- children: [
29250
- effect.assetUrl && /* @__PURE__ */ jsx(
29251
- "img",
29252
- {
29253
- src: effect.assetUrl,
29254
- alt: "",
29255
- width: 12,
29256
- height: 12,
29257
- style: { imageRendering: "pixelated", objectFit: "contain" },
29258
- className: "flex-shrink-0 inline-block"
29259
- }
29260
- ),
29261
- effect.label
29262
- ]
29368
+ size: "sm"
29263
29369
  },
29264
29370
  i
29265
29371
  )) })
@@ -29267,23 +29373,23 @@ function HealthPanel({
29267
29373
  }
29268
29374
  );
29269
29375
  }
29270
- var sizeMap13, effectVariantMap;
29376
+ var sizeMap14, effectVariantMap;
29271
29377
  var init_HealthPanel = __esm({
29272
29378
  "components/game/molecules/HealthPanel.tsx"() {
29273
29379
  "use client";
29274
29380
  init_cn();
29275
29381
  init_HealthBar();
29382
+ init_StatusEffect();
29276
29383
  init_Box();
29277
29384
  init_Typography();
29278
- init_Badge();
29279
- sizeMap13 = {
29385
+ sizeMap14 = {
29280
29386
  sm: { gap: "gap-1", padding: "px-2 py-1.5", text: "text-xs", barSize: "sm" },
29281
29387
  md: { gap: "gap-1.5", padding: "px-3 py-2", text: "text-sm", barSize: "md" },
29282
29388
  lg: { gap: "gap-2", padding: "px-4 py-3", text: "text-base", barSize: "lg" }
29283
29389
  };
29284
29390
  effectVariantMap = {
29285
- buff: "success",
29286
- debuff: "danger",
29391
+ buff: "buff",
29392
+ debuff: "debuff",
29287
29393
  neutral: "neutral"
29288
29394
  };
29289
29395
  HealthPanel.displayName = "HealthPanel";
@@ -29303,13 +29409,13 @@ function ScoreBoard({
29303
29409
  const multiplier = rawMultiplier ?? 1;
29304
29410
  const level = rawLevel ?? 1;
29305
29411
  return /* @__PURE__ */ jsx(
29306
- Card,
29412
+ Box,
29307
29413
  {
29308
29414
  className: cn(
29309
- "bg-[var(--color-card)]/90 border-border backdrop-blur-sm",
29415
+ "rounded-container border border-border bg-[var(--color-card)]/90 backdrop-blur-sm p-3",
29310
29416
  className
29311
29417
  ),
29312
- children: /* @__PURE__ */ jsx(CardContent, { className: "p-3", children: /* @__PURE__ */ jsxs(Box, { className: "flex items-center gap-3 flex-wrap", children: [
29418
+ children: /* @__PURE__ */ jsxs(Box, { className: "flex items-center gap-3 flex-wrap", children: [
29313
29419
  /* @__PURE__ */ jsx(
29314
29420
  StatBadge,
29315
29421
  {
@@ -29351,7 +29457,7 @@ function ScoreBoard({
29351
29457
  }
29352
29458
  ),
29353
29459
  combo != null && combo > 0 && /* @__PURE__ */ jsx(ComboCounter, { combo, multiplier, size: "sm" })
29354
- ] }) })
29460
+ ] })
29355
29461
  }
29356
29462
  );
29357
29463
  }
@@ -29361,7 +29467,6 @@ var init_ScoreBoard = __esm({
29361
29467
  init_cn();
29362
29468
  init_ComboCounter();
29363
29469
  init_StatBadge();
29364
- init_Card();
29365
29470
  init_Box();
29366
29471
  ScoreBoard.displayName = "ScoreBoard";
29367
29472
  }
@@ -29409,7 +29514,7 @@ var init_ResourceBar = __esm({
29409
29514
  }
29410
29515
  });
29411
29516
  function TurnIndicator({
29412
- assetUrl = DEFAULT_ASSET_URL8,
29517
+ assetUrl = DEFAULT_ASSET_URL9,
29413
29518
  currentTurn = 1,
29414
29519
  maxTurns,
29415
29520
  activeTeam,
@@ -29417,7 +29522,7 @@ function TurnIndicator({
29417
29522
  size = "md",
29418
29523
  className
29419
29524
  }) {
29420
- const sizes = sizeMap14[size];
29525
+ const sizes = sizeMap15[size];
29421
29526
  return /* @__PURE__ */ jsxs(
29422
29527
  "div",
29423
29528
  {
@@ -29459,16 +29564,16 @@ function TurnIndicator({
29459
29564
  }
29460
29565
  );
29461
29566
  }
29462
- var sizeMap14, DEFAULT_ASSET_URL8;
29567
+ var sizeMap15, DEFAULT_ASSET_URL9;
29463
29568
  var init_TurnIndicator = __esm({
29464
29569
  "components/game/atoms/TurnIndicator.tsx"() {
29465
29570
  init_cn();
29466
- sizeMap14 = {
29571
+ sizeMap15 = {
29467
29572
  sm: { wrapper: "text-xs gap-1.5 px-2 py-0.5", dot: "w-1.5 h-1.5" },
29468
29573
  md: { wrapper: "text-sm gap-2 px-3 py-1", dot: "w-2 h-2" },
29469
29574
  lg: { wrapper: "text-base gap-2.5 px-4 py-1.5", dot: "w-2.5 h-2.5" }
29470
29575
  };
29471
- DEFAULT_ASSET_URL8 = "https://almadar-kflow-assets.web.app/shared/effects/particles/symbol_01.png";
29576
+ DEFAULT_ASSET_URL9 = "https://almadar-kflow-assets.web.app/shared/effects/particles/symbol_01.png";
29472
29577
  TurnIndicator.displayName = "TurnIndicator";
29473
29578
  }
29474
29579
  });
@@ -29481,7 +29586,7 @@ function TurnPanel({
29481
29586
  className
29482
29587
  }) {
29483
29588
  const eventBus = useEventBus();
29484
- const handleAction = React80.useCallback(
29589
+ const handleAction = React85.useCallback(
29485
29590
  (event) => {
29486
29591
  if (event) {
29487
29592
  eventBus.emit(event, { turn: currentTurn, phase, activeTeam });
@@ -29506,28 +29611,16 @@ function TurnPanel({
29506
29611
  activeTeam
29507
29612
  }
29508
29613
  ),
29509
- actions && actions.length > 0 && /* @__PURE__ */ jsx(Box, { className: "flex items-center gap-1.5 ml-auto", children: actions.map((action, i) => /* @__PURE__ */ jsxs(
29510
- Button,
29614
+ actions && actions.length > 0 && /* @__PURE__ */ jsx(Box, { className: "flex items-center gap-1.5 ml-auto", children: actions.map((action, i) => /* @__PURE__ */ jsx(
29615
+ ActionButton,
29511
29616
  {
29512
- variant: "ghost",
29513
- size: "sm",
29617
+ label: action.label,
29618
+ icon: action.assetUrl ? void 0 : action.icon,
29619
+ assetUrl: action.assetUrl,
29514
29620
  disabled: action.disabled,
29515
- leftIcon: action.assetUrl ? void 0 : action.icon,
29516
- onClick: () => handleAction(action.event),
29517
- children: [
29518
- action.assetUrl && /* @__PURE__ */ jsx(
29519
- "img",
29520
- {
29521
- src: action.assetUrl,
29522
- alt: "",
29523
- width: 14,
29524
- height: 14,
29525
- style: { imageRendering: "pixelated", objectFit: "contain" },
29526
- className: "flex-shrink-0"
29527
- }
29528
- ),
29529
- action.label
29530
- ]
29621
+ variant: "secondary",
29622
+ size: "sm",
29623
+ onClick: () => handleAction(action.event)
29531
29624
  },
29532
29625
  i
29533
29626
  )) })
@@ -29541,7 +29634,7 @@ var init_TurnPanel = __esm({
29541
29634
  "use client";
29542
29635
  init_cn();
29543
29636
  init_TurnIndicator();
29544
- init_Button();
29637
+ init_ActionButton();
29545
29638
  init_Box();
29546
29639
  init_useEventBus();
29547
29640
  DEFAULT_TURN_ACTIONS = [
@@ -29592,7 +29685,7 @@ function EnemyPlate({
29592
29685
  }
29593
29686
  )
29594
29687
  ] }),
29595
- level != null && /* @__PURE__ */ jsxs(Badge, { variant: "neutral", size: "sm", children: [
29688
+ level != null && /* @__PURE__ */ jsxs("span", { className: "text-xs font-bold text-muted-foreground bg-muted/60 rounded px-1.5 py-0.5 border border-border/50 shrink-0", children: [
29596
29689
  "Lv.",
29597
29690
  level
29598
29691
  ] })
@@ -29623,12 +29716,12 @@ function EnemyPlate({
29623
29716
  )
29624
29717
  ] }),
29625
29718
  effects && effects.length > 0 && /* @__PURE__ */ jsx(Box, { className: "flex items-center gap-1 flex-wrap", children: effects.map((effect, i) => /* @__PURE__ */ jsx(
29626
- Badge,
29719
+ StatusEffect,
29627
29720
  {
29628
- variant: effectVariantMap2[effect.variant ?? "neutral"],
29629
- size: "sm",
29630
29721
  icon: effect.icon,
29631
- children: effect.label
29722
+ label: effect.label,
29723
+ variant: effectVariantMap2[effect.variant ?? "neutral"],
29724
+ size: "sm"
29632
29725
  },
29633
29726
  i
29634
29727
  )) })
@@ -29642,12 +29735,12 @@ var init_EnemyPlate = __esm({
29642
29735
  "use client";
29643
29736
  init_cn();
29644
29737
  init_HealthBar();
29738
+ init_StatusEffect();
29645
29739
  init_Box();
29646
29740
  init_Typography();
29647
- init_Badge();
29648
29741
  effectVariantMap2 = {
29649
- buff: "success",
29650
- debuff: "danger",
29742
+ buff: "buff",
29743
+ debuff: "debuff",
29651
29744
  neutral: "neutral"
29652
29745
  };
29653
29746
  DEFAULT_ENEMY_EFFECTS = [
@@ -29662,7 +29755,7 @@ function UnitCommandBar({
29662
29755
  className
29663
29756
  }) {
29664
29757
  const eventBus = useEventBus();
29665
- const handleCommand = React80.useCallback(
29758
+ const handleCommand = React85.useCallback(
29666
29759
  (event) => {
29667
29760
  if (event) {
29668
29761
  eventBus.emit(event, { unitId: selectedUnitId });
@@ -29677,27 +29770,18 @@ function UnitCommandBar({
29677
29770
  "flex items-center gap-1.5 rounded-container bg-[var(--color-card)]/90 border border-border backdrop-blur-sm px-2 py-1.5",
29678
29771
  className
29679
29772
  ),
29680
- children: commands.map((command, i) => /* @__PURE__ */ jsxs(Box, { className: "flex flex-col items-center gap-0.5", children: [
29681
- /* @__PURE__ */ jsx(
29682
- Button,
29683
- {
29684
- variant: "ghost",
29685
- size: "sm",
29686
- disabled: command.disabled,
29687
- leftIcon: command.icon,
29688
- onClick: () => handleCommand(command.event),
29689
- children: command.label
29690
- }
29691
- ),
29692
- command.hotkey && /* @__PURE__ */ jsx(
29693
- Typography,
29694
- {
29695
- variant: "caption",
29696
- className: "text-muted-foreground text-xs font-mono",
29697
- children: command.hotkey
29698
- }
29699
- )
29700
- ] }, i))
29773
+ children: commands.map((command, i) => /* @__PURE__ */ jsx(Box, { className: "flex flex-col items-center gap-0.5", children: /* @__PURE__ */ jsx(
29774
+ ActionButton,
29775
+ {
29776
+ label: command.label,
29777
+ icon: command.icon,
29778
+ disabled: command.disabled,
29779
+ hotkey: command.hotkey,
29780
+ variant: "secondary",
29781
+ size: "sm",
29782
+ onClick: () => handleCommand(command.event)
29783
+ }
29784
+ ) }, i))
29701
29785
  }
29702
29786
  );
29703
29787
  }
@@ -29706,9 +29790,8 @@ var init_UnitCommandBar = __esm({
29706
29790
  "components/game/molecules/UnitCommandBar.tsx"() {
29707
29791
  "use client";
29708
29792
  init_cn();
29709
- init_Button();
29793
+ init_ActionButton();
29710
29794
  init_Box();
29711
- init_Typography();
29712
29795
  init_useEventBus();
29713
29796
  DEFAULT_COMMANDS = [
29714
29797
  { label: "Move", icon: "move", event: "MOVE", hotkey: "M" },
@@ -30213,7 +30296,7 @@ function GameMenu({
30213
30296
  } catch {
30214
30297
  }
30215
30298
  const eventBus = eventBusProp || eventBusFromHook;
30216
- const handleOptionClick = React80.useCallback(
30299
+ const handleOptionClick = React85.useCallback(
30217
30300
  (option) => {
30218
30301
  if (option.event && eventBus) {
30219
30302
  eventBus.emit(`UI:${option.event}`, { option });
@@ -30332,7 +30415,7 @@ function GameOverScreen({
30332
30415
  } catch {
30333
30416
  }
30334
30417
  const eventBus = eventBusProp || eventBusFromHook;
30335
- const handleActionClick = React80.useCallback(
30418
+ const handleActionClick = React85.useCallback(
30336
30419
  (action) => {
30337
30420
  if (action.event && eventBus) {
30338
30421
  eventBus.emit(`UI:${action.event}`, { action });
@@ -30547,6 +30630,7 @@ function PlatformerCanvas({
30547
30630
  rightEvent = "MOVE_RIGHT",
30548
30631
  jumpEvent = "JUMP",
30549
30632
  stopEvent = "STOP",
30633
+ effects = [],
30550
30634
  className
30551
30635
  }) {
30552
30636
  const canvasRef = useRef(null);
@@ -30617,7 +30701,8 @@ function PlatformerCanvas({
30617
30701
  playerSprite,
30618
30702
  tileSprites,
30619
30703
  backgroundImage,
30620
- assetBaseUrl
30704
+ assetBaseUrl,
30705
+ effects
30621
30706
  });
30622
30707
  propsRef.current = {
30623
30708
  platforms,
@@ -30630,7 +30715,8 @@ function PlatformerCanvas({
30630
30715
  playerSprite,
30631
30716
  tileSprites,
30632
30717
  backgroundImage,
30633
- assetBaseUrl
30718
+ assetBaseUrl,
30719
+ effects
30634
30720
  };
30635
30721
  const handleKeyDown = useCallback((e) => {
30636
30722
  if (keysRef.current.has(e.code)) return;
@@ -30697,7 +30783,8 @@ function PlatformerCanvas({
30697
30783
  bgColor: bg,
30698
30784
  playerSprite: pSprite,
30699
30785
  tileSprites: tSprites,
30700
- backgroundImage: bgImg
30786
+ backgroundImage: bgImg,
30787
+ effects: fxList
30701
30788
  } = propsRef.current;
30702
30789
  const auth = playerRef.current;
30703
30790
  const interped = positions.get("player");
@@ -30851,6 +30938,18 @@ function PlatformerCanvas({
30851
30938
  ctx.arc(ppx + eyeOffsetX + 7, eyeY, eyeSize, 0, Math.PI * 2);
30852
30939
  ctx.fill();
30853
30940
  }
30941
+ for (const fx of fxList) {
30942
+ const fxScreenX = fx.x - camX;
30943
+ const fxScreenY = fx.y - camY;
30944
+ const alpha = Math.min(1, fx.ttl / 4);
30945
+ const prev = ctx.globalAlpha;
30946
+ ctx.globalAlpha = alpha;
30947
+ ctx.fillStyle = "#ffe066";
30948
+ ctx.beginPath();
30949
+ ctx.arc(fxScreenX, fxScreenY, 12, 0, Math.PI * 2);
30950
+ ctx.fill();
30951
+ ctx.globalAlpha = prev;
30952
+ }
30854
30953
  };
30855
30954
  return interp.startLoop(drawFrame);
30856
30955
  }, [interp.startLoop, loadImage]);
@@ -31287,13 +31386,13 @@ var init_MapView = __esm({
31287
31386
  shadowSize: [41, 41]
31288
31387
  });
31289
31388
  L.Marker.prototype.options.icon = defaultIcon;
31290
- const { useEffect: useEffect84, useRef: useRef83, useCallback: useCallback128, useState: useState114 } = React80__default;
31389
+ const { useEffect: useEffect82, useRef: useRef83, useCallback: useCallback128, useState: useState112 } = React85__default;
31291
31390
  const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
31292
31391
  const { useEventBus: useEventBus3 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
31293
31392
  function MapUpdater({ centerLat, centerLng, zoom }) {
31294
31393
  const map = useMap();
31295
31394
  const prevRef = useRef83({ centerLat, centerLng, zoom });
31296
- useEffect84(() => {
31395
+ useEffect82(() => {
31297
31396
  const prev = prevRef.current;
31298
31397
  if (prev.centerLat !== centerLat || prev.centerLng !== centerLng || prev.zoom !== zoom) {
31299
31398
  map.setView([centerLat, centerLng], zoom);
@@ -31304,7 +31403,7 @@ var init_MapView = __esm({
31304
31403
  }
31305
31404
  function MapClickHandler({ onMapClick }) {
31306
31405
  const map = useMap();
31307
- useEffect84(() => {
31406
+ useEffect82(() => {
31308
31407
  if (!onMapClick) return;
31309
31408
  const handler = (e) => {
31310
31409
  onMapClick(e.latlng.lat, e.latlng.lng);
@@ -31332,7 +31431,7 @@ var init_MapView = __esm({
31332
31431
  showAttribution = true
31333
31432
  }) {
31334
31433
  const eventBus = useEventBus3();
31335
- const [clickedPosition, setClickedPosition] = useState114(null);
31434
+ const [clickedPosition, setClickedPosition] = useState112(null);
31336
31435
  const handleMapClick = useCallback128((lat, lng) => {
31337
31436
  if (showClickedPin) {
31338
31437
  setClickedPosition({ lat, lng });
@@ -32123,6 +32222,15 @@ function renderIconInput3(icon, props) {
32123
32222
  function columnLabel(col) {
32124
32223
  return col.header ?? col.label ?? col.key.replace(/([a-z])([A-Z])/g, "$1 $2").replace(/[_-]/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
32125
32224
  }
32225
+ function asFieldValue(v) {
32226
+ if (v === void 0 || v === null) return v;
32227
+ const t = typeof v;
32228
+ if (t === "string" || t === "number" || t === "boolean") return v;
32229
+ if (v instanceof Date) return v;
32230
+ if (Array.isArray(v)) return v;
32231
+ if (t === "object") return v;
32232
+ return void 0;
32233
+ }
32126
32234
  function statusVariant4(value) {
32127
32235
  const v = value.toLowerCase();
32128
32236
  if (["active", "completed", "done", "approved", "published", "resolved", "open", "online", "ok"].includes(v)) return "success";
@@ -32193,8 +32301,8 @@ function TableView({
32193
32301
  }) {
32194
32302
  const eventBus = useEventBus();
32195
32303
  const { t } = useTranslate();
32196
- const [visibleCount, setVisibleCount] = React80__default.useState(pageSize > 0 ? pageSize : Infinity);
32197
- const [localSelected, setLocalSelected] = React80__default.useState(/* @__PURE__ */ new Set());
32304
+ const [visibleCount, setVisibleCount] = React85__default.useState(pageSize > 0 ? pageSize : Infinity);
32305
+ const [localSelected, setLocalSelected] = React85__default.useState(/* @__PURE__ */ new Set());
32198
32306
  const colDefs = columns ?? fields ?? [];
32199
32307
  const allDataRaw = Array.isArray(entity) ? entity : entity ? [entity] : [];
32200
32308
  const dnd = useDataDnd({
@@ -32339,7 +32447,7 @@ function TableView({
32339
32447
  }
32340
32448
  ) }),
32341
32449
  hasRenderProp ? /* @__PURE__ */ jsx(Box, { className: "flex-1 min-w-0", children: children(row, index) }) : colDefs.map((col) => {
32342
- const raw = getNestedValue(row, col.field ?? col.key);
32450
+ const raw = asFieldValue(getNestedValue(row, col.field ?? col.key));
32343
32451
  const cellBase = cn(
32344
32452
  "flex items-center min-w-0",
32345
32453
  alignClass[col.align ?? "left"],
@@ -32389,12 +32497,12 @@ function TableView({
32389
32497
  ]
32390
32498
  }
32391
32499
  );
32392
- return dnd.isZone ? /* @__PURE__ */ jsx(dnd.SortableItem, { id: row[idField] ?? id, children: rowInner }, id) : /* @__PURE__ */ jsx(React80__default.Fragment, { children: rowInner }, id);
32500
+ return dnd.isZone ? /* @__PURE__ */ jsx(dnd.SortableItem, { id: row[idField] ?? id, children: rowInner }, id) : /* @__PURE__ */ jsx(React85__default.Fragment, { children: rowInner }, id);
32393
32501
  };
32394
- const items = data.map((row) => row);
32502
+ const items = Array.from(data);
32395
32503
  const groups = groupBy ? groupData2(items, groupBy) : [{ label: "", items }];
32396
32504
  let runningIndex = 0;
32397
- const body = /* @__PURE__ */ jsx(Box, { role: "rowgroup", children: groups.map((group, gi) => /* @__PURE__ */ jsxs(React80__default.Fragment, { children: [
32505
+ const body = /* @__PURE__ */ jsx(Box, { role: "rowgroup", children: groups.map((group, gi) => /* @__PURE__ */ jsxs(React85__default.Fragment, { children: [
32398
32506
  group.label && /* @__PURE__ */ jsx(Divider, { label: group.label, className: gi > 0 ? "mt-3" : "mt-0" }),
32399
32507
  group.items.map((row) => renderRow(row, runningIndex++))
32400
32508
  ] }, gi)) });
@@ -33751,7 +33859,7 @@ var init_StepFlow = __esm({
33751
33859
  className
33752
33860
  }) => {
33753
33861
  if (orientation === "vertical") {
33754
- 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: [
33862
+ return /* @__PURE__ */ jsx(VStack, { gap: "none", className: cn("w-full", className), children: steps.map((step, index) => /* @__PURE__ */ jsx(React85__default.Fragment, { children: /* @__PURE__ */ jsxs(HStack, { gap: "md", align: "start", className: "w-full", children: [
33755
33863
  /* @__PURE__ */ jsxs(VStack, { gap: "none", align: "center", children: [
33756
33864
  /* @__PURE__ */ jsx(StepCircle, { step, index }),
33757
33865
  showConnectors && index < steps.length - 1 && /* @__PURE__ */ jsx(Box, { className: "w-px h-8 bg-border" })
@@ -33762,7 +33870,7 @@ var init_StepFlow = __esm({
33762
33870
  ] })
33763
33871
  ] }) }, index)) });
33764
33872
  }
33765
- 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: [
33873
+ 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(React85__default.Fragment, { children: [
33766
33874
  /* @__PURE__ */ jsxs(VStack, { gap: "sm", align: "center", className: "flex-1 w-full md:w-auto", children: [
33767
33875
  /* @__PURE__ */ jsx(StepCircle, { step, index }),
33768
33876
  /* @__PURE__ */ jsx(Typography, { variant: "h4", className: "text-center", children: step.title }),
@@ -34747,7 +34855,7 @@ var init_LikertScale = __esm({
34747
34855
  md: "text-base",
34748
34856
  lg: "text-lg"
34749
34857
  };
34750
- LikertScale = React80__default.forwardRef(
34858
+ LikertScale = React85__default.forwardRef(
34751
34859
  ({
34752
34860
  question,
34753
34861
  options = DEFAULT_LIKERT_OPTIONS,
@@ -34759,7 +34867,7 @@ var init_LikertScale = __esm({
34759
34867
  variant = "radios",
34760
34868
  className
34761
34869
  }, ref) => {
34762
- const groupId = React80__default.useId();
34870
+ const groupId = React85__default.useId();
34763
34871
  const eventBus = useEventBus();
34764
34872
  const handleSelect = useCallback(
34765
34873
  (next) => {
@@ -35654,11 +35762,11 @@ function nextBlockId(prefix = "blk") {
35654
35762
  function normalizeBlocks(raw) {
35655
35763
  if (!Array.isArray(raw) || raw.length === 0) return [createBlock("paragraph")];
35656
35764
  return raw.map((row) => {
35657
- const r = row;
35658
- const rawType = r.type;
35765
+ const entity = row;
35766
+ const rawType = entity.type;
35659
35767
  const type = typeof rawType === "string" && BLOCK_TYPES.has(rawType) ? rawType : "paragraph";
35660
- const id = typeof r.id === "string" && r.id ? r.id : nextBlockId(type);
35661
- return { ...r, id, type };
35768
+ const id = typeof entity.id === "string" && entity.id ? entity.id : nextBlockId(type);
35769
+ return { ...entity, id, type };
35662
35770
  });
35663
35771
  }
35664
35772
  function createBlock(type) {
@@ -37041,7 +37149,7 @@ var init_DocBreadcrumb = __esm({
37041
37149
  "aria-label": t("aria.breadcrumb"),
37042
37150
  children: /* @__PURE__ */ jsx(HStack, { gap: "xs", align: "center", wrap: true, children: items.map((item, idx) => {
37043
37151
  const isLast = idx === items.length - 1;
37044
- return /* @__PURE__ */ jsxs(React80__default.Fragment, { children: [
37152
+ return /* @__PURE__ */ jsxs(React85__default.Fragment, { children: [
37045
37153
  idx > 0 && /* @__PURE__ */ jsx(
37046
37154
  Icon,
37047
37155
  {
@@ -37909,8 +38017,8 @@ var init_MiniStateMachine = __esm({
37909
38017
  states.map((s, i) => {
37910
38018
  const x = 2 + i * (NODE_W + GAP2 + ARROW_W + GAP2);
37911
38019
  const tc = transitionCounts[s.name] ?? 0;
37912
- const role = getStateRole(s.name, s.isInitial, s.isTerminal, tc, maxTC);
37913
- return /* @__PURE__ */ jsxs(React80__default.Fragment, { children: [
38020
+ const role = getStateRole(s.name, s.isInitial ?? void 0, s.isTerminal ?? void 0, tc, maxTC);
38021
+ return /* @__PURE__ */ jsxs(React85__default.Fragment, { children: [
37914
38022
  /* @__PURE__ */ jsx(
37915
38023
  AvlState,
37916
38024
  {
@@ -37920,8 +38028,8 @@ var init_MiniStateMachine = __esm({
37920
38028
  height: NODE_H,
37921
38029
  name: "",
37922
38030
  role,
37923
- isInitial: s.isInitial,
37924
- isTerminal: s.isTerminal
38031
+ isInitial: s.isInitial ?? void 0,
38032
+ isTerminal: s.isTerminal ?? void 0
37925
38033
  }
37926
38034
  ),
37927
38035
  i < states.length - 1 && /* @__PURE__ */ jsxs("g", { children: [
@@ -38114,7 +38222,7 @@ var init_PageHeader = __esm({
38114
38222
  info: "bg-info/10 text-info"
38115
38223
  };
38116
38224
  return /* @__PURE__ */ jsxs(Box, { className: cn("mb-6", className), children: [
38117
- 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: [
38225
+ 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(React85__default.Fragment, { children: [
38118
38226
  idx > 0 && /* @__PURE__ */ jsx(Typography, { variant: "small", color: "muted", children: "/" }),
38119
38227
  crumb.href ? /* @__PURE__ */ jsx(
38120
38228
  "a",
@@ -38431,7 +38539,7 @@ var init_Navigation = __esm({
38431
38539
  Navigation.displayName = "Navigation";
38432
38540
  }
38433
38541
  });
38434
- var paddingStyles4, variantStyles8, Section;
38542
+ var paddingStyles4, variantStyles9, Section;
38435
38543
  var init_Section = __esm({
38436
38544
  "components/core/molecules/Section.tsx"() {
38437
38545
  init_cn();
@@ -38444,7 +38552,7 @@ var init_Section = __esm({
38444
38552
  lg: "p-6",
38445
38553
  xl: "p-8"
38446
38554
  };
38447
- variantStyles8 = {
38555
+ variantStyles9 = {
38448
38556
  default: "",
38449
38557
  card: [
38450
38558
  "bg-card",
@@ -38472,52 +38580,49 @@ var init_Section = __esm({
38472
38580
  as: Component2 = "section"
38473
38581
  }) => {
38474
38582
  const hasHeader = title || description || action;
38475
- const Comp = Component2;
38476
- return /* @__PURE__ */ jsxs(
38477
- Comp,
38583
+ return React85__default.createElement(
38584
+ Component2,
38478
38585
  {
38479
38586
  className: cn(
38480
38587
  paddingStyles4[padding],
38481
- variantStyles8[variant],
38588
+ variantStyles9[variant],
38482
38589
  className
38483
- ),
38484
- children: [
38485
- hasHeader && /* @__PURE__ */ jsxs(
38486
- Box,
38487
- {
38488
- className: cn(
38489
- "flex flex-col sm:flex-row sm:items-start sm:justify-between gap-2 sm:gap-4",
38490
- divider && "pb-4 mb-4 border-b-[length:var(--border-width)] border-border",
38491
- !divider && "mb-4",
38492
- headerClassName
38493
- ),
38494
- children: [
38495
- /* @__PURE__ */ jsxs(Box, { className: "flex-1 min-w-0", children: [
38496
- title && /* @__PURE__ */ jsx(
38497
- Typography,
38498
- {
38499
- variant: "h4",
38500
- className: "text-foreground font-semibold",
38501
- children: title
38502
- }
38503
- ),
38504
- description && /* @__PURE__ */ jsx(
38505
- Typography,
38506
- {
38507
- variant: "body",
38508
- color: "muted",
38509
- className: "mt-1",
38510
- children: description
38511
- }
38512
- )
38513
- ] }),
38514
- action && /* @__PURE__ */ jsx(Box, { className: "flex-shrink-0 flex items-center gap-2", children: action })
38515
- ]
38516
- }
38590
+ )
38591
+ },
38592
+ hasHeader && /* @__PURE__ */ jsxs(
38593
+ Box,
38594
+ {
38595
+ className: cn(
38596
+ "flex flex-col sm:flex-row sm:items-start sm:justify-between gap-2 sm:gap-4",
38597
+ divider && "pb-4 mb-4 border-b-[length:var(--border-width)] border-border",
38598
+ !divider && "mb-4",
38599
+ headerClassName
38517
38600
  ),
38518
- /* @__PURE__ */ jsx(Box, { className: contentClassName, children })
38519
- ]
38520
- }
38601
+ children: [
38602
+ /* @__PURE__ */ jsxs(Box, { className: "flex-1 min-w-0", children: [
38603
+ title && /* @__PURE__ */ jsx(
38604
+ Typography,
38605
+ {
38606
+ variant: "h4",
38607
+ className: "text-foreground font-semibold",
38608
+ children: title
38609
+ }
38610
+ ),
38611
+ description && /* @__PURE__ */ jsx(
38612
+ Typography,
38613
+ {
38614
+ variant: "body",
38615
+ color: "muted",
38616
+ className: "mt-1",
38617
+ children: description
38618
+ }
38619
+ )
38620
+ ] }),
38621
+ action && /* @__PURE__ */ jsx(Box, { className: "flex-shrink-0 flex items-center gap-2", children: action })
38622
+ ]
38623
+ }
38624
+ ),
38625
+ /* @__PURE__ */ jsx(Box, { className: contentClassName, children })
38521
38626
  );
38522
38627
  };
38523
38628
  Section.displayName = "Section";
@@ -38843,7 +38948,7 @@ var init_WizardContainer = __esm({
38843
38948
  const isCompleted = index < currentStep;
38844
38949
  const stepKey = step.id ?? step.tabId ?? `step-${index}`;
38845
38950
  const stepTitle = step.title ?? step.name ?? `Step ${index + 1}`;
38846
- return /* @__PURE__ */ jsxs(React80__default.Fragment, { children: [
38951
+ return /* @__PURE__ */ jsxs(React85__default.Fragment, { children: [
38847
38952
  /* @__PURE__ */ jsx(
38848
38953
  Button,
38849
38954
  {
@@ -40998,6 +41103,22 @@ var init_DataTable = __esm({
40998
41103
  DataTable.displayName = "DataTable";
40999
41104
  }
41000
41105
  });
41106
+ function toDebuggerLine(v) {
41107
+ if (v === null || typeof v !== "object" || Array.isArray(v) || v instanceof Date) return null;
41108
+ const id = v["id"];
41109
+ const content = v["content"];
41110
+ const isBug = v["isBug"];
41111
+ if (typeof id !== "string" || typeof content !== "string" || typeof isBug !== "boolean") return null;
41112
+ const isFlagged = v["isFlagged"];
41113
+ const explanation = v["explanation"];
41114
+ return {
41115
+ id,
41116
+ content,
41117
+ isBug,
41118
+ isFlagged: typeof isFlagged === "boolean" ? isFlagged : void 0,
41119
+ explanation: typeof explanation === "string" ? explanation : void 0
41120
+ };
41121
+ }
41001
41122
  function DebuggerBoard({
41002
41123
  entity,
41003
41124
  completeEvent = "PUZZLE_COMPLETE",
@@ -41010,7 +41131,10 @@ function DebuggerBoard({
41010
41131
  const { t } = useTranslate();
41011
41132
  const resolved = boardEntity(entity);
41012
41133
  const [headerError, setHeaderError] = useState(false);
41013
- const lines = Array.isArray(resolved?.lines) ? resolved.lines : [];
41134
+ const lines = Array.isArray(resolved?.lines) ? resolved.lines.flatMap((v) => {
41135
+ const l = toDebuggerLine(v);
41136
+ return l ? [l] : [];
41137
+ }) : [];
41014
41138
  const result = str(resolved?.result) || "none";
41015
41139
  const attempts = num(resolved?.attempts);
41016
41140
  const submitted = result === "win";
@@ -41653,7 +41777,7 @@ var init_DialogueBubble = __esm({
41653
41777
  }
41654
41778
  });
41655
41779
  function extractTitle(children) {
41656
- if (!React80__default.isValidElement(children)) return void 0;
41780
+ if (!React85__default.isValidElement(children)) return void 0;
41657
41781
  const props = children.props;
41658
41782
  if (typeof props.title === "string") {
41659
41783
  return props.title;
@@ -41698,7 +41822,7 @@ var init_DrawerSlot = __esm({
41698
41822
  }
41699
41823
  });
41700
41824
  function StateIndicator({
41701
- assetUrl = DEFAULT_ASSET_URL9,
41825
+ assetUrl = DEFAULT_ASSET_URL10,
41702
41826
  state = "idle",
41703
41827
  label,
41704
41828
  size = "md",
@@ -41737,13 +41861,13 @@ function StateIndicator({
41737
41861
  }
41738
41862
  );
41739
41863
  }
41740
- var DEFAULT_ASSET_URL9, DEFAULT_STATE_STYLES, DEFAULT_STYLE, SIZE_CLASSES;
41864
+ var DEFAULT_ASSET_URL10, DEFAULT_STATE_STYLES, DEFAULT_STYLE, SIZE_CLASSES;
41741
41865
  var init_StateIndicator = __esm({
41742
41866
  "components/game/atoms/StateIndicator.tsx"() {
41743
41867
  init_Box();
41744
41868
  init_Icon();
41745
41869
  init_cn();
41746
- DEFAULT_ASSET_URL9 = "https://almadar-kflow-assets.web.app/shared/isometric-dungeon/Isometric/chestClosed_E.png";
41870
+ DEFAULT_ASSET_URL10 = "https://almadar-kflow-assets.web.app/shared/isometric-dungeon/Isometric/chestClosed_E.png";
41747
41871
  DEFAULT_STATE_STYLES = {
41748
41872
  idle: { icon: "\u23F8", bgClass: "bg-muted" },
41749
41873
  active: { icon: "\u25B6", bgClass: "bg-success" },
@@ -41778,7 +41902,7 @@ function LinearView({
41778
41902
  /* @__PURE__ */ jsx(HStack, { className: "flex-wrap items-center", gap: "xs", children: trait.states.map((state, i) => {
41779
41903
  const isDone = i < currentIdx;
41780
41904
  const isCurrent = i === currentIdx;
41781
- return /* @__PURE__ */ jsxs(React80__default.Fragment, { children: [
41905
+ return /* @__PURE__ */ jsxs(React85__default.Fragment, { children: [
41782
41906
  i > 0 && /* @__PURE__ */ jsx(
41783
41907
  Typography,
41784
41908
  {
@@ -42600,12 +42724,12 @@ function evaluateFormExpression(expr, formCtx) {
42600
42724
  return evaluate(expr, ctx);
42601
42725
  }
42602
42726
  function isOrbitalEntitySchema(value) {
42603
- if (value === null || typeof value !== "object" || Array.isArray(value)) return false;
42727
+ if (value === null || value === void 0 || typeof value !== "object" || Array.isArray(value)) return false;
42604
42728
  const fields = value.fields;
42605
42729
  return Array.isArray(fields);
42606
42730
  }
42607
42731
  function isPlainEntityRow(value) {
42608
- if (value === null || typeof value !== "object" || Array.isArray(value)) return false;
42732
+ if (value === null || value === void 0 || typeof value !== "object" || Array.isArray(value)) return false;
42609
42733
  const fields = value.fields;
42610
42734
  return !Array.isArray(fields);
42611
42735
  }
@@ -42764,12 +42888,12 @@ var init_Form = __esm({
42764
42888
  const isSchemaEntity = isOrbitalEntitySchema(entity);
42765
42889
  const resolvedEntity = isSchemaEntity ? entity : void 0;
42766
42890
  const entityName = typeof entity === "string" ? entity : resolvedEntity?.name;
42767
- const normalizedInitialData = React80__default.useMemo(() => {
42891
+ const normalizedInitialData = React85__default.useMemo(() => {
42768
42892
  const entityRowAsInitial = isPlainEntityRow(entity) ? entity : void 0;
42769
42893
  const callerInitial = initialData !== null && typeof initialData === "object" && !Array.isArray(initialData) ? initialData : {};
42770
42894
  return entityRowAsInitial !== void 0 ? { ...entityRowAsInitial, ...callerInitial } : callerInitial;
42771
42895
  }, [entity, initialData]);
42772
- const entityDerivedFields = React80__default.useMemo(() => {
42896
+ const entityDerivedFields = React85__default.useMemo(() => {
42773
42897
  if (fields && fields.length > 0) return void 0;
42774
42898
  if (!resolvedEntity) return void 0;
42775
42899
  return resolvedEntity.fields.map(
@@ -42777,6 +42901,7 @@ var init_Form = __esm({
42777
42901
  name: f3.name,
42778
42902
  type: f3.type,
42779
42903
  required: f3.required,
42904
+ // EntityField.default is typed `unknown` upstream — safe cast: schema defaults are always FieldValues.
42780
42905
  defaultValue: f3.default,
42781
42906
  // EntityField is a discriminated union — `values` lives on Scalar/Enum, `relation` lives on Relation.
42782
42907
  values: "values" in f3 ? f3.values : void 0,
@@ -42789,16 +42914,16 @@ var init_Form = __esm({
42789
42914
  const conditionalFields = typeof conditionalFieldsRaw === "boolean" ? {} : conditionalFieldsRaw;
42790
42915
  const hiddenCalculations = typeof hiddenCalculationsRaw === "boolean" ? [] : hiddenCalculationsRaw;
42791
42916
  const violationTriggers = typeof violationTriggersRaw === "boolean" ? [] : violationTriggersRaw;
42792
- const [formData, setFormData] = React80__default.useState(
42917
+ const [formData, setFormData] = React85__default.useState(
42793
42918
  normalizedInitialData
42794
42919
  );
42795
- const [collapsedSections, setCollapsedSections] = React80__default.useState(
42920
+ const [collapsedSections, setCollapsedSections] = React85__default.useState(
42796
42921
  /* @__PURE__ */ new Set()
42797
42922
  );
42798
- const [submitError, setSubmitError] = React80__default.useState(null);
42799
- const formRef = React80__default.useRef(null);
42923
+ const [submitError, setSubmitError] = React85__default.useState(null);
42924
+ const formRef = React85__default.useRef(null);
42800
42925
  const formMode = props.mode;
42801
- const mountedRef = React80__default.useRef(false);
42926
+ const mountedRef = React85__default.useRef(false);
42802
42927
  if (!mountedRef.current) {
42803
42928
  mountedRef.current = true;
42804
42929
  debug("forms", "mount", {
@@ -42811,7 +42936,7 @@ var init_Form = __esm({
42811
42936
  });
42812
42937
  }
42813
42938
  const shouldShowCancel = showCancel ?? (fields && fields.length > 0);
42814
- const evalContext = React80__default.useMemo(
42939
+ const evalContext = React85__default.useMemo(
42815
42940
  () => ({
42816
42941
  formValues: formData,
42817
42942
  globalVariables: externalContext?.globalVariables ?? {},
@@ -42820,7 +42945,7 @@ var init_Form = __esm({
42820
42945
  }),
42821
42946
  [formData, externalContext]
42822
42947
  );
42823
- React80__default.useEffect(() => {
42948
+ React85__default.useEffect(() => {
42824
42949
  debug("forms", "initialData-sync", {
42825
42950
  mode: formMode,
42826
42951
  normalizedInitialData,
@@ -42831,7 +42956,7 @@ var init_Form = __esm({
42831
42956
  setFormData(normalizedInitialData);
42832
42957
  }
42833
42958
  }, [normalizedInitialData]);
42834
- const processCalculations = React80__default.useCallback(
42959
+ const processCalculations = React85__default.useCallback(
42835
42960
  (changedFieldId, newFormData) => {
42836
42961
  if (!hiddenCalculations.length) return;
42837
42962
  const context = {
@@ -42856,7 +42981,7 @@ var init_Form = __esm({
42856
42981
  },
42857
42982
  [hiddenCalculations, externalContext, eventBus]
42858
42983
  );
42859
- const checkViolations = React80__default.useCallback(
42984
+ const checkViolations = React85__default.useCallback(
42860
42985
  (changedFieldId, newFormData) => {
42861
42986
  if (!violationTriggers.length) return;
42862
42987
  const context = {
@@ -42894,7 +43019,7 @@ var init_Form = __esm({
42894
43019
  processCalculations(name, newFormData);
42895
43020
  checkViolations(name, newFormData);
42896
43021
  };
42897
- const isFieldVisible = React80__default.useCallback(
43022
+ const isFieldVisible = React85__default.useCallback(
42898
43023
  (fieldName) => {
42899
43024
  const condition = conditionalFields[fieldName];
42900
43025
  if (!condition) return true;
@@ -42902,7 +43027,7 @@ var init_Form = __esm({
42902
43027
  },
42903
43028
  [conditionalFields, evalContext]
42904
43029
  );
42905
- const isSectionVisible = React80__default.useCallback(
43030
+ const isSectionVisible = React85__default.useCallback(
42906
43031
  (section) => {
42907
43032
  if (!section.condition) return true;
42908
43033
  return Boolean(evaluateFormExpression(section.condition, evalContext));
@@ -42978,7 +43103,7 @@ var init_Form = __esm({
42978
43103
  eventBus.emit(`UI:${onCancel}`);
42979
43104
  }
42980
43105
  };
42981
- const renderField = React80__default.useCallback(
43106
+ const renderField = React85__default.useCallback(
42982
43107
  (field) => {
42983
43108
  const fieldName = field.name || field.field;
42984
43109
  if (!fieldName) return null;
@@ -42999,7 +43124,7 @@ var init_Form = __esm({
42999
43124
  [formData, isFieldVisible, relationsData, relationsLoading, isLoading]
43000
43125
  );
43001
43126
  const effectiveFields = entityDerivedFields ?? fields;
43002
- const normalizedFields = React80__default.useMemo(() => {
43127
+ const normalizedFields = React85__default.useMemo(() => {
43003
43128
  if (!effectiveFields || effectiveFields.length === 0) return [];
43004
43129
  return effectiveFields.map((field) => {
43005
43130
  if (typeof field === "string") {
@@ -43009,6 +43134,7 @@ var init_Form = __esm({
43009
43134
  name: field,
43010
43135
  type: entityField.type,
43011
43136
  required: entityField.required,
43137
+ // EntityField.default is typed `unknown` upstream — safe cast: schema defaults are always FieldValues.
43012
43138
  defaultValue: entityField.default,
43013
43139
  // EntityField is a discriminated union — `values` lives on Scalar/Enum, `relation` lives on Relation.
43014
43140
  values: "values" in entityField ? entityField.values : void 0,
@@ -43022,7 +43148,7 @@ var init_Form = __esm({
43022
43148
  return field;
43023
43149
  });
43024
43150
  }, [effectiveFields, resolvedEntity]);
43025
- const schemaFields = React80__default.useMemo(() => {
43151
+ const schemaFields = React85__default.useMemo(() => {
43026
43152
  if (normalizedFields.length === 0) return null;
43027
43153
  if (isDebugEnabled()) {
43028
43154
  debugGroup(`Form: ${entityName || "unknown"}`);
@@ -43032,7 +43158,7 @@ var init_Form = __esm({
43032
43158
  }
43033
43159
  return normalizedFields.map(renderField).filter(Boolean);
43034
43160
  }, [normalizedFields, renderField, entityName, conditionalFields]);
43035
- const sectionElements = React80__default.useMemo(() => {
43161
+ const sectionElements = React85__default.useMemo(() => {
43036
43162
  if (!sections || sections.length === 0) return null;
43037
43163
  return sections.map((section) => {
43038
43164
  if (!isSectionVisible(section)) {
@@ -44560,7 +44686,6 @@ var init_GameCanvas3D2 = __esm({
44560
44686
  className,
44561
44687
  isLoading: externalLoading,
44562
44688
  error: externalError,
44563
- entity,
44564
44689
  preloadAssets = [],
44565
44690
  tileClickEvent,
44566
44691
  unitClickEvent,
@@ -45295,6 +45420,14 @@ var init_GameBoard3D = __esm({
45295
45420
  GameBoard3D.displayName = "GameBoard3D";
45296
45421
  }
45297
45422
  });
45423
+ function asDescriptor(v) {
45424
+ if (Array.isArray(v) || React85__default.isValidElement(v)) return null;
45425
+ const o = v;
45426
+ if (typeof o.type !== "string") return null;
45427
+ const props = o.props !== void 0 && typeof o.props === "object" && !Array.isArray(o.props) && o.props !== null ? o.props : void 0;
45428
+ const _id = typeof o._id === "string" ? o._id : void 0;
45429
+ return { type: o.type, props, _id };
45430
+ }
45298
45431
  function getSlotContentRenderer() {
45299
45432
  if (_scr) return _scr;
45300
45433
  const mod = (init_UISlotRenderer(), __toCommonJS(UISlotRenderer_exports));
@@ -45303,17 +45436,16 @@ function getSlotContentRenderer() {
45303
45436
  }
45304
45437
  function resolveDescriptor(value, idPrefix) {
45305
45438
  if (value === null || value === void 0) return value;
45306
- if (React80__default.isValidElement(value)) return value;
45439
+ if (React85__default.isValidElement(value)) return value;
45307
45440
  if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") return value;
45308
45441
  if (Array.isArray(value)) {
45309
- return value.map((item, i) => /* @__PURE__ */ jsx(React80__default.Fragment, { children: resolveDescriptor(item, `${idPrefix}-${i}`) }, i));
45442
+ return value.map((item, i) => /* @__PURE__ */ jsx(React85__default.Fragment, { children: resolveDescriptor(item, `${idPrefix}-${i}`) }, i));
45310
45443
  }
45311
- if (typeof value === "object") {
45312
- const rec = value;
45313
- if (typeof rec.type === "string" && getComponentForPattern(rec.type) !== null) {
45314
- const { type, props: nestedProps, _id, ...flatProps } = rec;
45315
- const resolvedProps = nestedProps !== void 0 ? nestedProps : flatProps;
45316
- const content = { id: _id ?? idPrefix, pattern: type, props: resolvedProps, priority: 0 };
45444
+ if (typeof value === "object" && value !== null) {
45445
+ const desc = asDescriptor(value);
45446
+ if (desc !== null && getComponentForPattern(desc.type) !== null) {
45447
+ const resolvedProps = desc.props ?? {};
45448
+ const content = { id: desc._id ?? idPrefix, pattern: desc.type, props: resolvedProps, priority: 0 };
45317
45449
  const SCR = getSlotContentRenderer();
45318
45450
  return /* @__PURE__ */ jsx(SCR, { content, onDismiss: () => void 0 });
45319
45451
  }
@@ -45407,16 +45539,19 @@ function getSlotContentRenderer2() {
45407
45539
  }
45408
45540
  function resolveDescriptor2(value, idPrefix) {
45409
45541
  if (value === null || value === void 0) return value;
45410
- if (React80__default.isValidElement(value)) return value;
45542
+ if (React85__default.isValidElement(value)) return value;
45411
45543
  if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") return value;
45412
45544
  if (Array.isArray(value)) {
45413
- return value.map((item, i) => /* @__PURE__ */ jsx(React80__default.Fragment, { children: resolveDescriptor2(item, `${idPrefix}-${i}`) }, i));
45545
+ return value.map((item, i) => /* @__PURE__ */ jsx(React85__default.Fragment, { children: resolveDescriptor2(item, `${idPrefix}-${i}`) }, i));
45414
45546
  }
45415
45547
  if (typeof value === "object") {
45416
45548
  const rec = value;
45417
45549
  if (typeof rec.type === "string" && getComponentForPattern(rec.type) !== null) {
45418
- const { type, props: nestedProps, _id, ...flatProps } = rec;
45419
- const resolvedProps = nestedProps !== void 0 ? nestedProps : flatProps;
45550
+ const type = rec.type;
45551
+ const _id = typeof rec._id === "string" ? rec._id : void 0;
45552
+ const nestedProps = rec.props !== void 0 && typeof rec.props === "object" && !Array.isArray(rec.props) && rec.props !== null ? rec.props : void 0;
45553
+ const { type: _t, props: _p, _id: _d, ...flatRest } = rec;
45554
+ const resolvedProps = nestedProps !== void 0 ? nestedProps : flatRest;
45420
45555
  const content = { id: _id ?? idPrefix, pattern: type, props: resolvedProps, priority: 0 };
45421
45556
  const SCR = getSlotContentRenderer2();
45422
45557
  return /* @__PURE__ */ jsx(SCR, { content, onDismiss: () => void 0 });
@@ -46120,7 +46255,7 @@ var init_List = __esm({
46120
46255
  if (entity && typeof entity === "object" && "id" in entity) return [entity];
46121
46256
  return [];
46122
46257
  }, [entity]);
46123
- const getItemActions = React80__default.useCallback(
46258
+ const getItemActions = React85__default.useCallback(
46124
46259
  (item) => {
46125
46260
  if (!itemActions) return [];
46126
46261
  if (typeof itemActions === "function") {
@@ -46177,15 +46312,14 @@ var init_List = __esm({
46177
46312
  };
46178
46313
  if (effectiveFieldNames && effectiveFieldNames.length > 0) {
46179
46314
  const firstField = effectiveFieldNames[0];
46180
- const itemRecord = item;
46181
- if (!normalizedItem.title && getNestedValue(itemRecord, firstField)) {
46315
+ if (!normalizedItem.title && getNestedValue(item, firstField)) {
46182
46316
  normalizedItem.title = String(
46183
- getNestedValue(itemRecord, firstField)
46317
+ getNestedValue(item, firstField)
46184
46318
  );
46185
46319
  }
46186
46320
  normalizedItem._fields = effectiveFieldNames.reduce(
46187
46321
  (acc, field) => {
46188
- const value = getNestedValue(itemRecord, field);
46322
+ const value = getNestedValue(item, field);
46189
46323
  if (value !== void 0 && value !== null) {
46190
46324
  acc[field] = value;
46191
46325
  }
@@ -46638,16 +46772,18 @@ var init_MediaGallery = __esm({
46638
46772
  [selectable, selectedItems, selectionEvent, eventBus]
46639
46773
  );
46640
46774
  const entityData = Array.isArray(entity) ? entity : [];
46641
- const items = React80__default.useMemo(() => {
46775
+ const items = React85__default.useMemo(() => {
46642
46776
  if (propItems) return propItems;
46643
46777
  if (entityData.length === 0) return [];
46644
- return entityData.map((record, idx) => ({
46645
- id: String(record.id ?? idx),
46646
- src: String(record.src ?? record.url ?? record.image ?? ""),
46647
- alt: record.alt ? String(record.alt) : void 0,
46648
- thumbnail: record.thumbnail ? String(record.thumbnail) : void 0,
46649
- caption: record.caption ? String(record.caption) : record.title ? String(record.title) : void 0
46650
- }));
46778
+ return entityData.map((record, idx) => {
46779
+ return {
46780
+ id: String(record.id ?? idx),
46781
+ src: String(record.src ?? ("url" in record ? record.url : "") ?? ("image" in record ? record.image : "") ?? ""),
46782
+ alt: record.alt ? String(record.alt) : void 0,
46783
+ thumbnail: record.thumbnail ? String(record.thumbnail) : void 0,
46784
+ caption: record.caption ? String(record.caption) : "title" in record ? String(record.title) : void 0
46785
+ };
46786
+ });
46651
46787
  }, [propItems, entityData]);
46652
46788
  if (isLoading) {
46653
46789
  return /* @__PURE__ */ jsx(LoadingState, { message: t("common.loading"), className });
@@ -46798,114 +46934,6 @@ var init_MediaGallery = __esm({
46798
46934
  MediaGallery.displayName = "MediaGallery";
46799
46935
  }
46800
46936
  });
46801
- function MiniMap({
46802
- tiles = DEFAULT_TILES,
46803
- units = DEFAULT_UNITS,
46804
- width = 150,
46805
- height = 150,
46806
- mapWidth = 100,
46807
- mapHeight = 100,
46808
- viewportRect = DEFAULT_VIEWPORT,
46809
- className
46810
- }) {
46811
- const canvasRef = React80.useRef(null);
46812
- const frameRef = React80.useRef(0);
46813
- React80.useEffect(() => {
46814
- const canvas = canvasRef.current;
46815
- if (!canvas) return;
46816
- const ctx = canvas.getContext("2d");
46817
- if (!ctx) return;
46818
- const scaleX = width / mapWidth;
46819
- const scaleY = height / mapHeight;
46820
- let blinkOn = true;
46821
- let animFrame;
46822
- function draw() {
46823
- if (!ctx) return;
46824
- ctx.clearRect(0, 0, width, height);
46825
- ctx.fillStyle = "#111";
46826
- ctx.fillRect(0, 0, width, height);
46827
- for (const tile of tiles) {
46828
- ctx.fillStyle = tile.color;
46829
- ctx.fillRect(
46830
- Math.floor(tile.x * scaleX),
46831
- Math.floor(tile.y * scaleY),
46832
- Math.max(1, Math.ceil(scaleX)),
46833
- Math.max(1, Math.ceil(scaleY))
46834
- );
46835
- }
46836
- for (const unit of units) {
46837
- if (unit.isPlayer && !blinkOn) continue;
46838
- ctx.fillStyle = unit.isPlayer ? "#ffffff" : unit.color;
46839
- const ux = Math.floor(unit.x * scaleX) - 1;
46840
- const uy = Math.floor(unit.y * scaleY) - 1;
46841
- ctx.fillRect(ux, uy, 3, 3);
46842
- }
46843
- if (viewportRect) {
46844
- ctx.strokeStyle = "#ffffff";
46845
- ctx.lineWidth = 1;
46846
- ctx.strokeRect(
46847
- Math.floor(viewportRect.x * scaleX),
46848
- Math.floor(viewportRect.y * scaleY),
46849
- Math.floor(viewportRect.w * scaleX),
46850
- Math.floor(viewportRect.h * scaleY)
46851
- );
46852
- }
46853
- }
46854
- function tick() {
46855
- frameRef.current++;
46856
- if (frameRef.current % 30 === 0) {
46857
- blinkOn = !blinkOn;
46858
- }
46859
- draw();
46860
- animFrame = requestAnimationFrame(tick);
46861
- }
46862
- tick();
46863
- return () => {
46864
- cancelAnimationFrame(animFrame);
46865
- };
46866
- }, [tiles, units, width, height, mapWidth, mapHeight, viewportRect]);
46867
- return /* @__PURE__ */ jsx(
46868
- "div",
46869
- {
46870
- className: cn(
46871
- "relative inline-block border border-border/20 rounded-container",
46872
- className
46873
- ),
46874
- children: /* @__PURE__ */ jsx(
46875
- "canvas",
46876
- {
46877
- ref: canvasRef,
46878
- width,
46879
- height,
46880
- className: "block",
46881
- style: { width, height }
46882
- }
46883
- )
46884
- }
46885
- );
46886
- }
46887
- var DEFAULT_TILES, DEFAULT_UNITS, DEFAULT_VIEWPORT;
46888
- var init_MiniMap = __esm({
46889
- "components/game/atoms/MiniMap.tsx"() {
46890
- "use client";
46891
- init_cn();
46892
- DEFAULT_TILES = [
46893
- { x: 10, y: 10, color: "#4ade80" },
46894
- { x: 20, y: 15, color: "#4ade80" },
46895
- { x: 30, y: 25, color: "#22c55e" },
46896
- { x: 50, y: 40, color: "#4ade80" },
46897
- { x: 60, y: 55, color: "#16a34a" },
46898
- { x: 40, y: 60, color: "#4ade80" },
46899
- { x: 70, y: 30, color: "#22c55e" },
46900
- { x: 80, y: 70, color: "#4ade80" }
46901
- ];
46902
- DEFAULT_UNITS = [
46903
- { x: 30, y: 30, color: "#60a5fa", isPlayer: true }
46904
- ];
46905
- DEFAULT_VIEWPORT = { x: 20, y: 20, w: 40, h: 40 };
46906
- MiniMap.displayName = "MiniMap";
46907
- }
46908
- });
46909
46937
  function MinigolfBoard({
46910
46938
  tiles,
46911
46939
  units,
@@ -46949,7 +46977,7 @@ var init_MinigolfBoard = __esm({
46949
46977
  }
46950
46978
  });
46951
46979
  function extractTitle2(children) {
46952
- if (!React80__default.isValidElement(children)) return void 0;
46980
+ if (!React85__default.isValidElement(children)) return void 0;
46953
46981
  const props = children.props;
46954
46982
  if (typeof props.title === "string") {
46955
46983
  return props.title;
@@ -47015,8 +47043,16 @@ function NegotiatorBoard({
47015
47043
  const lastPlayerAction = str(resolved?.lastPlayerAction);
47016
47044
  const lastOpponentAction = str(resolved?.lastOpponentAction);
47017
47045
  const lastPayoff = num(resolved?.lastPayoff);
47018
- const actions = Array.isArray(resolved?.actions) ? resolved.actions : [];
47019
- const payoffMatrix = Array.isArray(resolved?.payoffMatrix) ? resolved.payoffMatrix : [];
47046
+ const actions = Array.isArray(resolved?.actions) ? resolved.actions.flatMap((item) => {
47047
+ if (item !== null && typeof item === "object" && !Array.isArray(item) && !(item instanceof Date) && typeof item.id === "string" && typeof item.label === "string")
47048
+ return [{ id: item.id, label: item.label, description: typeof item.description === "string" ? item.description : void 0 }];
47049
+ return [];
47050
+ }) : [];
47051
+ const payoffMatrix = Array.isArray(resolved?.payoffMatrix) ? resolved.payoffMatrix.flatMap((item) => {
47052
+ if (item !== null && typeof item === "object" && !Array.isArray(item) && !(item instanceof Date) && typeof item.playerAction === "string" && typeof item.opponentAction === "string")
47053
+ return [{ playerAction: item.playerAction, opponentAction: item.opponentAction, playerPayoff: typeof item.playerPayoff === "number" ? item.playerPayoff : 0, opponentPayoff: typeof item.opponentPayoff === "number" ? item.opponentPayoff : 0 }];
47054
+ return [];
47055
+ }) : [];
47020
47056
  const prevRoundRef = useRef(currentRound);
47021
47057
  useEffect(() => {
47022
47058
  if (currentRound > prevRoundRef.current && lastPlayerAction) {
@@ -47649,7 +47685,7 @@ var init_RacingBoard = __esm({
47649
47685
  }
47650
47686
  });
47651
47687
  function ResourceCounter({
47652
- assetUrl = DEFAULT_ASSET_URL10,
47688
+ assetUrl = DEFAULT_ASSET_URL11,
47653
47689
  icon,
47654
47690
  label = "Gold",
47655
47691
  value = 250,
@@ -47658,7 +47694,7 @@ function ResourceCounter({
47658
47694
  size = "md",
47659
47695
  className
47660
47696
  }) {
47661
- const sizes = sizeMap15[size];
47697
+ const sizes = sizeMap16[size];
47662
47698
  return /* @__PURE__ */ jsxs(
47663
47699
  "div",
47664
47700
  {
@@ -47692,7 +47728,7 @@ function ResourceCounter({
47692
47728
  }
47693
47729
  );
47694
47730
  }
47695
- var colorTokenClasses2, DEFAULT_ASSET_URL10, sizeMap15;
47731
+ var colorTokenClasses2, DEFAULT_ASSET_URL11, sizeMap16;
47696
47732
  var init_ResourceCounter = __esm({
47697
47733
  "components/game/atoms/ResourceCounter.tsx"() {
47698
47734
  init_cn();
@@ -47705,8 +47741,8 @@ var init_ResourceCounter = __esm({
47705
47741
  error: "text-error",
47706
47742
  muted: "text-muted-foreground"
47707
47743
  };
47708
- DEFAULT_ASSET_URL10 = "https://almadar-kflow-assets.web.app/shared/world-map/gold_mine.png";
47709
- sizeMap15 = {
47744
+ DEFAULT_ASSET_URL11 = "https://almadar-kflow-assets.web.app/shared/world-map/gold_mine.png";
47745
+ sizeMap16 = {
47710
47746
  sm: { wrapper: "text-xs gap-1 px-1.5 py-0.5", icon: "text-sm", img: 16 },
47711
47747
  md: { wrapper: "text-sm gap-1.5 px-2 py-1", icon: "text-base", img: 20 },
47712
47748
  lg: { wrapper: "text-base gap-2 px-3 py-1.5", icon: "text-lg", img: 28 }
@@ -48189,7 +48225,7 @@ var init_debugRegistry = __esm({
48189
48225
  }
48190
48226
  });
48191
48227
  function useDebugData() {
48192
- const [data, setData] = React80.useState(() => ({
48228
+ const [data, setData] = React85.useState(() => ({
48193
48229
  traits: [],
48194
48230
  ticks: [],
48195
48231
  guards: [],
@@ -48203,7 +48239,7 @@ function useDebugData() {
48203
48239
  },
48204
48240
  lastUpdate: Date.now()
48205
48241
  }));
48206
- React80.useEffect(() => {
48242
+ React85.useEffect(() => {
48207
48243
  const updateData = () => {
48208
48244
  setData({
48209
48245
  traits: getAllTraits(),
@@ -48312,12 +48348,12 @@ function layoutGraph(states, transitions, initialState, width, height) {
48312
48348
  return positions;
48313
48349
  }
48314
48350
  function WalkMinimap() {
48315
- const [walkStep, setWalkStep] = React80.useState(null);
48316
- const [traits2, setTraits] = React80.useState([]);
48317
- const [coveredEdges, setCoveredEdges] = React80.useState([]);
48318
- const [completedTraits, setCompletedTraits] = React80.useState(/* @__PURE__ */ new Set());
48319
- const prevTraitRef = React80.useRef(null);
48320
- React80.useEffect(() => {
48351
+ const [walkStep, setWalkStep] = React85.useState(null);
48352
+ const [traits2, setTraits] = React85.useState([]);
48353
+ const [coveredEdges, setCoveredEdges] = React85.useState([]);
48354
+ const [completedTraits, setCompletedTraits] = React85.useState(/* @__PURE__ */ new Set());
48355
+ const prevTraitRef = React85.useRef(null);
48356
+ React85.useEffect(() => {
48321
48357
  const interval = setInterval(() => {
48322
48358
  const w = window;
48323
48359
  const step = w.__orbitalWalkStep;
@@ -48753,15 +48789,15 @@ var init_EntitiesTab = __esm({
48753
48789
  });
48754
48790
  function EventFlowTab({ events: events2 }) {
48755
48791
  const { t } = useTranslate();
48756
- const [filter, setFilter] = React80.useState("all");
48757
- const containerRef = React80.useRef(null);
48758
- const [autoScroll, setAutoScroll] = React80.useState(true);
48759
- React80.useEffect(() => {
48792
+ const [filter, setFilter] = React85.useState("all");
48793
+ const containerRef = React85.useRef(null);
48794
+ const [autoScroll, setAutoScroll] = React85.useState(true);
48795
+ React85.useEffect(() => {
48760
48796
  if (autoScroll && containerRef.current) {
48761
48797
  containerRef.current.scrollTop = containerRef.current.scrollHeight;
48762
48798
  }
48763
48799
  }, [events2.length, autoScroll]);
48764
- const filteredEvents = React80.useMemo(() => {
48800
+ const filteredEvents = React85.useMemo(() => {
48765
48801
  if (filter === "all") return events2;
48766
48802
  return events2.filter((e) => e.type === filter);
48767
48803
  }, [events2, filter]);
@@ -48877,7 +48913,7 @@ var init_EventFlowTab = __esm({
48877
48913
  });
48878
48914
  function GuardsPanel({ guards }) {
48879
48915
  const { t } = useTranslate();
48880
- const [filter, setFilter] = React80.useState("all");
48916
+ const [filter, setFilter] = React85.useState("all");
48881
48917
  if (guards.length === 0) {
48882
48918
  return /* @__PURE__ */ jsx(
48883
48919
  EmptyState,
@@ -48890,7 +48926,7 @@ function GuardsPanel({ guards }) {
48890
48926
  }
48891
48927
  const passedCount = guards.filter((g) => g.result).length;
48892
48928
  const failedCount = guards.length - passedCount;
48893
- const filteredGuards = React80.useMemo(() => {
48929
+ const filteredGuards = React85.useMemo(() => {
48894
48930
  if (filter === "all") return guards;
48895
48931
  if (filter === "passed") return guards.filter((g) => g.result);
48896
48932
  return guards.filter((g) => !g.result);
@@ -49053,10 +49089,10 @@ function EffectBadge({ effect }) {
49053
49089
  }
49054
49090
  function TransitionTimeline({ transitions }) {
49055
49091
  const { t } = useTranslate();
49056
- const containerRef = React80.useRef(null);
49057
- const [autoScroll, setAutoScroll] = React80.useState(true);
49058
- const [expandedId, setExpandedId] = React80.useState(null);
49059
- React80.useEffect(() => {
49092
+ const containerRef = React85.useRef(null);
49093
+ const [autoScroll, setAutoScroll] = React85.useState(true);
49094
+ const [expandedId, setExpandedId] = React85.useState(null);
49095
+ React85.useEffect(() => {
49060
49096
  if (autoScroll && containerRef.current) {
49061
49097
  containerRef.current.scrollTop = containerRef.current.scrollHeight;
49062
49098
  }
@@ -49262,18 +49298,18 @@ var init_ServerBridgeTab = __esm({
49262
49298
  });
49263
49299
  function extractPayloadFields(schema, eventName) {
49264
49300
  if (!schema) return [];
49265
- const orbitals = schema.orbitals;
49266
- if (!orbitals) return [];
49267
- for (const orbital of orbitals) {
49268
- const traits2 = orbital.traits ?? [];
49269
- for (const trait of traits2) {
49270
- const sm = trait.stateMachine;
49301
+ for (const orbital of schema.orbitals) {
49302
+ const traitRefs = orbital.traits ?? [];
49303
+ for (const traitRef of traitRefs) {
49304
+ if (!isInlineTrait(traitRef)) continue;
49305
+ const inlineTrait = traitRef;
49306
+ const sm = inlineTrait.stateMachine;
49271
49307
  if (!sm) continue;
49272
49308
  const events2 = sm.events ?? [];
49273
49309
  for (const evt of events2) {
49274
49310
  if (evt.name !== eventName) continue;
49275
- const payload = evt.payload ?? [];
49276
- return payload.map((f3) => ({
49311
+ const payloadFields = evt.payloadSchema ?? [];
49312
+ return payloadFields.map((f3) => ({
49277
49313
  name: f3.name,
49278
49314
  type: f3.type ?? "string"
49279
49315
  }));
@@ -49336,9 +49372,9 @@ function getAllEvents(traits2) {
49336
49372
  function EventDispatcherTab({ traits: traits2, schema }) {
49337
49373
  const eventBus = useEventBus();
49338
49374
  const { t } = useTranslate();
49339
- const [log10, setLog] = React80.useState([]);
49340
- const prevStatesRef = React80.useRef(/* @__PURE__ */ new Map());
49341
- React80.useEffect(() => {
49375
+ const [log10, setLog] = React85.useState([]);
49376
+ const prevStatesRef = React85.useRef(/* @__PURE__ */ new Map());
49377
+ React85.useEffect(() => {
49342
49378
  for (const trait of traits2) {
49343
49379
  const prev = prevStatesRef.current.get(trait.id);
49344
49380
  if (prev && prev !== trait.currentState) {
@@ -49507,10 +49543,10 @@ function VerifyModePanel({
49507
49543
  localCount
49508
49544
  }) {
49509
49545
  const { t } = useTranslate();
49510
- const [expanded, setExpanded] = React80.useState(true);
49511
- const scrollRef = React80.useRef(null);
49512
- const prevCountRef = React80.useRef(0);
49513
- React80.useEffect(() => {
49546
+ const [expanded, setExpanded] = React85.useState(true);
49547
+ const scrollRef = React85.useRef(null);
49548
+ const prevCountRef = React85.useRef(0);
49549
+ React85.useEffect(() => {
49514
49550
  if (expanded && transitions.length > prevCountRef.current && scrollRef.current) {
49515
49551
  scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
49516
49552
  }
@@ -49567,10 +49603,10 @@ function RuntimeDebugger({
49567
49603
  schema
49568
49604
  }) {
49569
49605
  const { t } = useTranslate();
49570
- const [isCollapsed, setIsCollapsed] = React80.useState(mode === "verify" ? true : defaultCollapsed);
49571
- const [isVisible, setIsVisible] = React80.useState(mode === "inline" || mode === "verify" || isDebugEnabled2());
49606
+ const [isCollapsed, setIsCollapsed] = React85.useState(mode === "verify" ? true : defaultCollapsed);
49607
+ const [isVisible, setIsVisible] = React85.useState(mode === "inline" || mode === "verify" || isDebugEnabled2());
49572
49608
  const debugData = useDebugData();
49573
- React80.useEffect(() => {
49609
+ React85.useEffect(() => {
49574
49610
  if (mode === "inline") return;
49575
49611
  return onDebugToggle((enabled) => {
49576
49612
  setIsVisible(enabled);
@@ -49579,7 +49615,7 @@ function RuntimeDebugger({
49579
49615
  }
49580
49616
  });
49581
49617
  }, [mode]);
49582
- React80.useEffect(() => {
49618
+ React85.useEffect(() => {
49583
49619
  if (mode === "inline") return;
49584
49620
  const handleKeyDown = (e) => {
49585
49621
  if (e.key === "`" && isVisible) {
@@ -50139,7 +50175,7 @@ function SequenceBar({
50139
50175
  onSlotRemove(index);
50140
50176
  }, [onSlotRemove, playing]);
50141
50177
  const paddedSlots = Array.from({ length: maxSlots }, (_, i) => slots[i]);
50142
- return /* @__PURE__ */ jsx(HStack, { className: cn("items-center", className), gap: "sm", children: paddedSlots.map((slot, i) => /* @__PURE__ */ jsxs(React80__default.Fragment, { children: [
50178
+ return /* @__PURE__ */ jsx(HStack, { className: cn("items-center", className), gap: "sm", children: paddedSlots.map((slot, i) => /* @__PURE__ */ jsxs(React85__default.Fragment, { children: [
50143
50179
  i > 0 && /* @__PURE__ */ jsx(
50144
50180
  Typography,
50145
50181
  {
@@ -50754,6 +50790,29 @@ var init_SimulationCanvas = __esm({
50754
50790
  SimulationCanvas.displayName = "SimulationCanvas";
50755
50791
  }
50756
50792
  });
50793
+ function readSimulatorParameters(v) {
50794
+ if (!Array.isArray(v)) return [];
50795
+ const result = [];
50796
+ for (const item of v) {
50797
+ if (typeof item === "object" && item !== null && !Array.isArray(item) && !(item instanceof Date)) {
50798
+ const param = item;
50799
+ if ("id" in item && "label" in item && "unit" in item && "min" in item && "max" in item && "step" in item) {
50800
+ result.push({
50801
+ id: str(param.id),
50802
+ label: str(param.label),
50803
+ unit: str(param.unit),
50804
+ min: num(param.min),
50805
+ max: num(param.max),
50806
+ step: num(param.step),
50807
+ initial: num(param.initial),
50808
+ correct: num(param.correct),
50809
+ tolerance: num(param.tolerance)
50810
+ });
50811
+ }
50812
+ }
50813
+ }
50814
+ return result;
50815
+ }
50757
50816
  function SimulatorBoard({
50758
50817
  entity,
50759
50818
  completeEvent = "PUZZLE_COMPLETE",
@@ -50766,7 +50825,7 @@ function SimulatorBoard({
50766
50825
  const { emit } = useEventBus();
50767
50826
  const { t } = useTranslate();
50768
50827
  const resolved = boardEntity(entity);
50769
- const parameters = Array.isArray(resolved?.parameters) ? resolved.parameters : [];
50828
+ const parameters = readSimulatorParameters(resolved?.parameters);
50770
50829
  const [headerError, setHeaderError] = useState(false);
50771
50830
  if (!resolved) return null;
50772
50831
  const paramA = num(resolved.paramA);
@@ -50793,8 +50852,14 @@ function SimulatorBoard({
50793
50852
  const handlePlayAgain = () => {
50794
50853
  if (playAgainEvent) emit(`UI:${playAgainEvent}`, {});
50795
50854
  };
50796
- const theme = resolved.theme ?? void 0;
50797
- const themeBackground = theme?.background;
50855
+ const themeBackground = (() => {
50856
+ const t2 = resolved.theme;
50857
+ if (typeof t2 === "object" && t2 !== null && !Array.isArray(t2) && !(t2 instanceof Date)) {
50858
+ const bg = t2.background;
50859
+ return str(bg);
50860
+ }
50861
+ return "";
50862
+ })();
50798
50863
  const headerImage = str(resolved.headerImage);
50799
50864
  const hint = str(resolved.hint);
50800
50865
  const showHint = isComplete && !isWin && attempts >= 2 && Boolean(hint);
@@ -51175,6 +51240,8 @@ function Sprite({
51175
51240
  opacity = 1,
51176
51241
  zIndex = 0,
51177
51242
  columns = 16,
51243
+ animState: _animState,
51244
+ frameRate: _frameRate,
51178
51245
  className,
51179
51246
  onClick,
51180
51247
  action
@@ -51306,7 +51373,7 @@ var init_StatCard = __esm({
51306
51373
  const labelToUse = propLabel ?? propTitle;
51307
51374
  const eventBus = useEventBus();
51308
51375
  const { t } = useTranslate();
51309
- const handleActionClick = React80__default.useCallback(() => {
51376
+ const handleActionClick = React85__default.useCallback(() => {
51310
51377
  if (action?.event) {
51311
51378
  eventBus.emit(`UI:${action.event}`, {});
51312
51379
  }
@@ -51317,7 +51384,7 @@ var init_StatCard = __esm({
51317
51384
  const data = Array.isArray(entity) ? entity : entity ? [entity] : [];
51318
51385
  const isLoading = externalLoading ?? false;
51319
51386
  const error = externalError;
51320
- const computeMetricValue = React80__default.useCallback(
51387
+ const computeMetricValue = React85__default.useCallback(
51321
51388
  (metric, items) => {
51322
51389
  if (metric.value !== void 0) {
51323
51390
  return metric.value;
@@ -51356,7 +51423,7 @@ var init_StatCard = __esm({
51356
51423
  },
51357
51424
  []
51358
51425
  );
51359
- const schemaStats = React80__default.useMemo(() => {
51426
+ const schemaStats = React85__default.useMemo(() => {
51360
51427
  if (!metrics || metrics.length === 0) return null;
51361
51428
  return metrics.map((metric) => ({
51362
51429
  label: metric.label,
@@ -51364,7 +51431,7 @@ var init_StatCard = __esm({
51364
51431
  format: metric.format
51365
51432
  }));
51366
51433
  }, [metrics, data, computeMetricValue]);
51367
- const calculatedTrend = React80__default.useMemo(() => {
51434
+ const calculatedTrend = React85__default.useMemo(() => {
51368
51435
  if (manualTrend !== void 0) return manualTrend;
51369
51436
  if (previousValue === void 0 || currentValue2 === void 0)
51370
51437
  return void 0;
@@ -51707,8 +51774,25 @@ function StateArchitectBoard({
51707
51774
  const initialState = str(resolved?.initialState);
51708
51775
  const entityName = str(resolved?.entityName);
51709
51776
  const availableEvents = Array.isArray(resolved?.availableEvents) ? resolved.availableEvents : [];
51710
- const testCases = Array.isArray(resolved?.testCases) ? resolved.testCases : [];
51711
- const entityTransitions = Array.isArray(resolved?.transitions) ? resolved.transitions : [];
51777
+ const testCases = (Array.isArray(resolved?.testCases) ? resolved.testCases : []).map((item) => {
51778
+ const o = typeof item === "object" && item !== null && !Array.isArray(item) ? item : {};
51779
+ const eventsField = o["events"];
51780
+ return {
51781
+ events: Array.isArray(eventsField) ? eventsField : [],
51782
+ expectedState: str(o["expectedState"]),
51783
+ label: str(o["label"])
51784
+ };
51785
+ });
51786
+ const entityTransitions = (Array.isArray(resolved?.transitions) ? resolved.transitions : []).map((item) => {
51787
+ const o = typeof item === "object" && item !== null && !Array.isArray(item) ? item : {};
51788
+ return {
51789
+ id: str(o["id"]),
51790
+ from: str(o["from"]),
51791
+ to: str(o["to"]),
51792
+ event: str(o["event"]),
51793
+ ...o["guardHint"] ? { guardHint: str(o["guardHint"]) } : {}
51794
+ };
51795
+ });
51712
51796
  const entityVariables = rows(resolved?.variables);
51713
51797
  const transitions = entityTransitions;
51714
51798
  const attempts = typeof resolved?.attempts === "number" ? resolved.attempts : 0;
@@ -52058,90 +52142,6 @@ var init_StatsOrganism = __esm({
52058
52142
  StatsOrganism.displayName = "StatsOrganism";
52059
52143
  }
52060
52144
  });
52061
- function formatDuration(seconds) {
52062
- if (seconds >= 60) {
52063
- return `${Math.floor(seconds / 60)}m`;
52064
- }
52065
- return `${Math.round(seconds)}s`;
52066
- }
52067
- function StatusEffect({
52068
- assetUrl = DEFAULT_ASSET_URL11,
52069
- icon = "shield",
52070
- label = "Shield",
52071
- duration = 30,
52072
- stacks,
52073
- variant = "buff",
52074
- size = "md",
52075
- className
52076
- }) {
52077
- const sizes = sizeMap16[size];
52078
- return /* @__PURE__ */ jsxs("div", { className: cn("relative inline-flex flex-col items-center", className), children: [
52079
- /* @__PURE__ */ jsxs(
52080
- "div",
52081
- {
52082
- className: cn(
52083
- "relative flex items-center justify-center rounded-interactive border-2",
52084
- sizes.container,
52085
- variantStyles9[variant]
52086
- ),
52087
- title: label,
52088
- children: [
52089
- /* @__PURE__ */ jsx("span", { className: cn("flex items-center justify-center", sizes.icon), children: assetUrl ? /* @__PURE__ */ jsx(
52090
- "img",
52091
- {
52092
- src: assetUrl,
52093
- alt: label,
52094
- width: sizes.img,
52095
- height: sizes.img,
52096
- style: { imageRendering: "pixelated", objectFit: "contain" },
52097
- className: "flex-shrink-0"
52098
- }
52099
- ) : typeof icon === "string" ? /* @__PURE__ */ jsx(Icon, { name: icon, size: "sm" }) : /* @__PURE__ */ jsx(Icon, { icon, size: "sm" }) }),
52100
- duration !== void 0 && /* @__PURE__ */ jsx(
52101
- "span",
52102
- {
52103
- className: cn(
52104
- "absolute bottom-0 left-0 right-0 text-center font-mono font-bold text-foreground bg-background/60 leading-tight",
52105
- sizes.timer
52106
- ),
52107
- children: formatDuration(duration)
52108
- }
52109
- )
52110
- ]
52111
- }
52112
- ),
52113
- stacks !== void 0 && stacks > 1 && /* @__PURE__ */ jsx(
52114
- "span",
52115
- {
52116
- className: cn(
52117
- "absolute flex items-center justify-center rounded-full bg-card text-foreground font-bold leading-none",
52118
- sizes.badge
52119
- ),
52120
- children: stacks
52121
- }
52122
- ),
52123
- label && /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground mt-0.5 text-center whitespace-nowrap", children: label })
52124
- ] });
52125
- }
52126
- var DEFAULT_ASSET_URL11, sizeMap16, variantStyles9;
52127
- var init_StatusEffect = __esm({
52128
- "components/game/atoms/StatusEffect.tsx"() {
52129
- init_cn();
52130
- init_Icon();
52131
- DEFAULT_ASSET_URL11 = "https://almadar-kflow-assets.web.app/shared/effects/particles/flame_01.png";
52132
- sizeMap16 = {
52133
- sm: { container: "w-8 h-8", icon: "text-sm", badge: "text-xs -top-1 -right-1 w-4 h-4", timer: "text-[9px]", img: 20 },
52134
- md: { container: "w-10 h-10", icon: "text-base", badge: "text-xs -top-1 -right-1 w-5 h-5", timer: "text-xs", img: 28 },
52135
- lg: { container: "w-12 h-12", icon: "text-lg", badge: "text-sm -top-1.5 -right-1.5 w-6 h-6", timer: "text-xs", img: 36 }
52136
- };
52137
- variantStyles9 = {
52138
- buff: "border-success bg-success/20",
52139
- debuff: "border-error bg-error/20",
52140
- neutral: "border-muted bg-muted/20"
52141
- };
52142
- StatusEffect.displayName = "StatusEffect";
52143
- }
52144
- });
52145
52145
  var StepFlowOrganism;
52146
52146
  var init_StepFlowOrganism = __esm({
52147
52147
  "components/marketing/organisms/StepFlowOrganism.tsx"() {
@@ -52637,8 +52637,8 @@ var init_SubagentTracePanel = __esm({
52637
52637
  ] });
52638
52638
  };
52639
52639
  InlineActivityStream = ({ activities, autoScroll = true, className }) => {
52640
- const endRef = React80__default.useRef(null);
52641
- React80__default.useEffect(() => {
52640
+ const endRef = React85__default.useRef(null);
52641
+ React85__default.useEffect(() => {
52642
52642
  if (!autoScroll) return;
52643
52643
  endRef.current?.scrollIntoView({ behavior: "smooth", block: "end" });
52644
52644
  }, [activities.length, autoScroll]);
@@ -52732,7 +52732,7 @@ var init_SubagentTracePanel = __esm({
52732
52732
  };
52733
52733
  SubagentRichCard = ({ subagent }) => {
52734
52734
  const { t } = useTranslate();
52735
- const activities = React80__default.useMemo(
52735
+ const activities = React85__default.useMemo(
52736
52736
  () => subagentMessagesToActivities(subagent.messages),
52737
52737
  [subagent.messages]
52738
52738
  );
@@ -52809,8 +52809,8 @@ var init_SubagentTracePanel = __esm({
52809
52809
  ] });
52810
52810
  };
52811
52811
  CoordinatorConversation = ({ messages, autoScroll = true, className }) => {
52812
- const endRef = React80__default.useRef(null);
52813
- React80__default.useEffect(() => {
52812
+ const endRef = React85__default.useRef(null);
52813
+ React85__default.useEffect(() => {
52814
52814
  if (!autoScroll) return;
52815
52815
  endRef.current?.scrollIntoView({ behavior: "smooth", block: "end" });
52816
52816
  }, [messages.length, autoScroll]);
@@ -53281,17 +53281,12 @@ var init_Timeline = __esm({
53281
53281
  look = "vertical-spacious"
53282
53282
  }) => {
53283
53283
  const { t } = useTranslate();
53284
- const entityData = Array.isArray(entity) ? entity : [];
53285
- const items = React80__default.useMemo(() => {
53284
+ const entityData = entity ?? [];
53285
+ const items = React85__default.useMemo(() => {
53286
53286
  if (propItems) return propItems;
53287
53287
  if (entityData.length === 0) return [];
53288
53288
  return entityData.map((record, idx) => {
53289
- const resolveField = (f3) => {
53290
- if (typeof f3 === "string") return f3;
53291
- if (f3 && typeof f3 === "object" && "name" in f3) return String(f3.name);
53292
- return "";
53293
- };
53294
- const resolvedFields = fields?.map(resolveField) ?? [];
53289
+ const resolvedFields = fields ?? [];
53295
53290
  const titleField = resolvedFields[0] || "title";
53296
53291
  const descField = resolvedFields[1] || "description";
53297
53292
  const dateField = resolvedFields.find(
@@ -53439,7 +53434,7 @@ var init_TimerDisplay = __esm({
53439
53434
  }
53440
53435
  });
53441
53436
  function extractToastProps(children) {
53442
- if (!React80__default.isValidElement(children)) {
53437
+ if (!React85__default.isValidElement(children)) {
53443
53438
  if (typeof children === "string") {
53444
53439
  return { message: children };
53445
53440
  }
@@ -53477,7 +53472,7 @@ var init_ToastSlot = __esm({
53477
53472
  eventBus.emit("UI:CLOSE");
53478
53473
  };
53479
53474
  if (!isVisible) return null;
53480
- const isCustomContent = React80__default.isValidElement(children) && !message;
53475
+ const isCustomContent = React85__default.isValidElement(children) && !message;
53481
53476
  return /* @__PURE__ */ jsx(Box, { className: "fixed bottom-4 right-4 z-50", children: isCustomContent ? children : /* @__PURE__ */ jsx(
53482
53477
  Toast,
53483
53478
  {
@@ -54749,7 +54744,7 @@ function WorldMapBoard({
54749
54744
  const resolved = boardEntity(entity);
54750
54745
  const entityUnits = rows(resolved?.units);
54751
54746
  const entityTiles = rows(resolved?.tiles);
54752
- const features = propFeatures ?? (Array.isArray(resolved?.features) ? resolved.features : []);
54747
+ const features = propFeatures ?? rows(resolved?.features);
54753
54748
  const selectedHeroId = resolved?.selectedHeroId ?? null;
54754
54749
  const assetManifest = propAssetManifest ?? resolved?.assetManifest;
54755
54750
  const backgroundImage = resolved?.backgroundImage;
@@ -54882,7 +54877,8 @@ function WorldMapBoard({
54882
54877
  if (heroMoveEvent) {
54883
54878
  eventBus.emit(`UI:${heroMoveEvent}`, { heroId, toX: x, toY: y });
54884
54879
  }
54885
- const feature = tile ? str(tile.feature) : "";
54880
+ const tileWithFeature = tile;
54881
+ const feature = tileWithFeature ? str(tileWithFeature.feature) : "";
54886
54882
  if (feature && feature !== "none") {
54887
54883
  const tileRow = tile;
54888
54884
  onFeatureEnter?.(heroId, tileRow);
@@ -55103,21 +55099,6 @@ function XPBar({
55103
55099
  }) {
55104
55100
  const sizes = sizeMap18[size];
55105
55101
  const percentage = max > 0 ? Math.max(0, Math.min(100, current / max * 100)) : 0;
55106
- const [fillWidth, setFillWidth] = React80.useState(animated ? 0 : percentage);
55107
- React80.useEffect(() => {
55108
- if (!animated) {
55109
- setFillWidth(percentage);
55110
- return;
55111
- }
55112
- let frame2;
55113
- const frame1 = requestAnimationFrame(() => {
55114
- frame2 = requestAnimationFrame(() => setFillWidth(percentage));
55115
- });
55116
- return () => {
55117
- cancelAnimationFrame(frame1);
55118
- cancelAnimationFrame(frame2);
55119
- };
55120
- }, [animated, percentage]);
55121
55102
  return /* @__PURE__ */ jsxs("div", { className: cn("flex items-center gap-2", className), children: [
55122
55103
  level != null && /* @__PURE__ */ jsxs(
55123
55104
  "span",
@@ -55149,7 +55130,7 @@ function XPBar({
55149
55130
  "bg-gradient-to-r from-accent to-info",
55150
55131
  animated && "transition-all duration-500 ease-out"
55151
55132
  ),
55152
- style: { width: `${fillWidth}%` }
55133
+ style: { width: `${percentage}%` }
55153
55134
  }
55154
55135
  )
55155
55136
  }
@@ -55166,7 +55147,6 @@ function XPBar({
55166
55147
  var sizeMap18;
55167
55148
  var init_XPBar = __esm({
55168
55149
  "components/game/atoms/XPBar.tsx"() {
55169
- "use client";
55170
55150
  init_cn();
55171
55151
  sizeMap18 = {
55172
55152
  sm: { bar: "h-2", text: "text-xs", badge: "text-xs px-1.5 py-0.5" },
@@ -55177,7 +55157,7 @@ var init_XPBar = __esm({
55177
55157
  }
55178
55158
  });
55179
55159
  function lazyThree(name, loader) {
55180
- const Lazy = React80__default.lazy(
55160
+ const Lazy = React85__default.lazy(
55181
55161
  () => loader().then((m) => {
55182
55162
  const Resolved = m[name];
55183
55163
  if (!Resolved) {
@@ -55189,13 +55169,13 @@ function lazyThree(name, loader) {
55189
55169
  })
55190
55170
  );
55191
55171
  function ThreeWrapper(props) {
55192
- return React80__default.createElement(
55172
+ return React85__default.createElement(
55193
55173
  ThreeBoundary,
55194
55174
  { name },
55195
- React80__default.createElement(
55196
- React80__default.Suspense,
55175
+ React85__default.createElement(
55176
+ React85__default.Suspense,
55197
55177
  { fallback: null },
55198
- React80__default.createElement(Lazy, props)
55178
+ React85__default.createElement(Lazy, props)
55199
55179
  )
55200
55180
  );
55201
55181
  }
@@ -55518,7 +55498,7 @@ var init_component_registry_generated = __esm({
55518
55498
  init_WorldMapBoard();
55519
55499
  init_WorldMapTemplate();
55520
55500
  init_XPBar();
55521
- ThreeBoundary = class extends React80__default.Component {
55501
+ ThreeBoundary = class extends React85__default.Component {
55522
55502
  constructor() {
55523
55503
  super(...arguments);
55524
55504
  __publicField(this, "state", { failed: false });
@@ -55528,7 +55508,7 @@ var init_component_registry_generated = __esm({
55528
55508
  }
55529
55509
  render() {
55530
55510
  if (this.state.failed) {
55531
- return React80__default.createElement(
55511
+ return React85__default.createElement(
55532
55512
  "div",
55533
55513
  {
55534
55514
  "data-testid": "three-unavailable",
@@ -55894,7 +55874,7 @@ function SuspenseConfigProvider({
55894
55874
  config,
55895
55875
  children
55896
55876
  }) {
55897
- return React80__default.createElement(
55877
+ return React85__default.createElement(
55898
55878
  SuspenseConfigContext.Provider,
55899
55879
  { value: config },
55900
55880
  children
@@ -55910,9 +55890,7 @@ function getComponentForPattern3(patternType) {
55910
55890
  if (!mapping) {
55911
55891
  return null;
55912
55892
  }
55913
- const name = typeof mapping === "string" ? mapping : mapping.component;
55914
- if (!name) return null;
55915
- return COMPONENT_REGISTRY[name] ?? null;
55893
+ return COMPONENT_REGISTRY[mapping] ?? null;
55916
55894
  }
55917
55895
  function enrichFormFields(fields, entityDef) {
55918
55896
  const fieldMap = new Map(entityDef.fields.map((f3) => [f3.name, f3]));
@@ -55924,7 +55902,7 @@ function enrichFormFields(fields, entityDef) {
55924
55902
  name: field,
55925
55903
  label: field.replace(/([a-z])([A-Z])/g, "$1 $2").replace(/\b\w/g, (c) => c.toUpperCase()),
55926
55904
  type: entityField.type,
55927
- required: entityField.required
55905
+ required: entityField.required ?? false
55928
55906
  };
55929
55907
  if (entityField.values && entityField.values.length > 0) {
55930
55908
  enriched.values = entityField.values;
@@ -55932,15 +55910,15 @@ function enrichFormFields(fields, entityDef) {
55932
55910
  enriched.values = entityField.enumValues;
55933
55911
  }
55934
55912
  if (entityField.relation) {
55935
- enriched.relation = entityField.relation;
55913
+ enriched.relation = entityField.relation.entity;
55936
55914
  }
55937
55915
  return enriched;
55938
55916
  }
55939
55917
  return { name: field, label: field.replace(/([a-z])([A-Z])/g, "$1 $2").replace(/\b\w/g, (c) => c.toUpperCase()) };
55940
55918
  }
55941
- if (field && typeof field === "object" && !Array.isArray(field)) {
55919
+ if (field && typeof field === "object" && !Array.isArray(field) && !React85__default.isValidElement(field) && !(field instanceof Date)) {
55942
55920
  const obj = field;
55943
- const fieldName = obj.name ?? obj.field;
55921
+ const fieldName = typeof obj.name === "string" ? obj.name : typeof obj.field === "string" ? obj.field : void 0;
55944
55922
  if (!fieldName) return field;
55945
55923
  if (obj.type || obj.inputType) return field;
55946
55924
  const entityField = fieldMap.get(fieldName);
@@ -55957,7 +55935,7 @@ function enrichFormFields(fields, entityDef) {
55957
55935
  }
55958
55936
  }
55959
55937
  if (!obj.relation && entityField.relation) {
55960
- enriched.relation = entityField.relation;
55938
+ enriched.relation = entityField.relation.entity;
55961
55939
  }
55962
55940
  return enriched;
55963
55941
  }
@@ -56384,7 +56362,7 @@ function renderPatternChildren(children, onDismiss, parentId = "root", parentPat
56384
56362
  const key = `${parentId}-${index}-trait:${traitName}`;
56385
56363
  return /* @__PURE__ */ jsx(TraitFrame, { traitName }, key);
56386
56364
  }
56387
- return /* @__PURE__ */ jsx(React80__default.Fragment, { children: child }, `${parentId}-${index}`);
56365
+ return /* @__PURE__ */ jsx(React85__default.Fragment, { children: child }, `${parentId}-${index}`);
56388
56366
  }
56389
56367
  if (!child || typeof child !== "object") return null;
56390
56368
  const childId = `${parentId}-${index}`;
@@ -56424,14 +56402,14 @@ function isPatternConfig(value) {
56424
56402
  if (value === null || value === void 0) return false;
56425
56403
  if (typeof value !== "object") return false;
56426
56404
  if (Array.isArray(value)) return false;
56427
- if (React80__default.isValidElement(value)) return false;
56405
+ if (React85__default.isValidElement(value)) return false;
56428
56406
  if (value instanceof Date) return false;
56429
56407
  if (typeof value === "function") return false;
56430
56408
  const record = value;
56431
56409
  return "type" in record && typeof record.type === "string" && getComponentForPattern(record.type) !== null;
56432
56410
  }
56433
56411
  function isPlainConfigObject(value) {
56434
- if (React80__default.isValidElement(value)) return false;
56412
+ if (React85__default.isValidElement(value)) return false;
56435
56413
  if (value instanceof Date) return false;
56436
56414
  const proto = Object.getPrototypeOf(value);
56437
56415
  return proto === Object.prototype || proto === null;
@@ -56557,7 +56535,7 @@ function SlotContentRenderer({
56557
56535
  for (const slotKey of CONTENT_NODE_SLOTS) {
56558
56536
  const slotVal = restProps[slotKey];
56559
56537
  if (slotVal === void 0 || slotVal === null) continue;
56560
- if (React80__default.isValidElement(slotVal) || typeof slotVal === "string" || typeof slotVal === "number" || typeof slotVal === "boolean") continue;
56538
+ if (React85__default.isValidElement(slotVal) || typeof slotVal === "string" || typeof slotVal === "number" || typeof slotVal === "boolean") continue;
56561
56539
  if (Array.isArray(slotVal) || typeof slotVal === "object" && "type" in slotVal) {
56562
56540
  nodeSlotOverrides[slotKey] = renderPatternChildren(
56563
56541
  slotVal,
@@ -56602,19 +56580,18 @@ function SlotContentRenderer({
56602
56580
  for (const [k, v] of Object.entries(nodeSlotOverrides)) {
56603
56581
  finalProps[k] = v;
56604
56582
  }
56605
- const resolvedItems = Array.isArray(
56606
- finalProps.entity
56607
- ) ? finalProps.entity : null;
56583
+ const entityVal = finalProps.entity;
56584
+ const resolvedItems = Array.isArray(entityVal) && entityVal[0] !== "fn" ? entityVal : null;
56608
56585
  if (resolvedItems && resolvedItems.length > 0 && !finalProps.fields && !finalProps.columns) {
56609
56586
  const sample = resolvedItems[0];
56610
- if (sample && typeof sample === "object") {
56587
+ if (sample && typeof sample === "object" && !Array.isArray(sample) && !React85__default.isValidElement(sample) && !(sample instanceof Date)) {
56611
56588
  const keys = Object.keys(sample).filter((k) => k !== "id" && k !== "_id");
56612
56589
  finalProps.fields = keys.map((k, i) => ({ name: k, variant: i === 0 ? "h4" : "body" }));
56613
56590
  }
56614
56591
  }
56615
56592
  const isFormPattern = FORM_PATTERNS.has(content.pattern) || content.pattern.includes("form");
56616
- if (isFormPattern && entityDef && Array.isArray(finalProps.fields)) {
56617
- finalProps.fields = enrichFormFields(finalProps.fields, entityDef);
56593
+ if (isFormPattern && entityDef && Array.isArray(finalProps.fields) && finalProps.fields[0] !== "fn") {
56594
+ finalProps.fields = enrichFormFields([...finalProps.fields], entityDef);
56618
56595
  }
56619
56596
  const acceptsChildren = PATTERNS_WITH_CHILDREN.has(content.pattern);
56620
56597
  return /* @__PURE__ */ jsx(
@@ -56978,7 +56955,7 @@ function useSpriteAnimations(getSheetUrls, getFrameDims, options = {}) {
56978
56955
  const prevPositionsRef = useRef(/* @__PURE__ */ new Map());
56979
56956
  const unitDataRef = useRef(/* @__PURE__ */ new Map());
56980
56957
  const walkHoldRef = useRef(/* @__PURE__ */ new Map());
56981
- const WALK_HOLD_MS2 = 600;
56958
+ const WALK_HOLD_MS = 600;
56982
56959
  const syncUnits = useCallback((units, deltaMs) => {
56983
56960
  const scaledDelta = deltaMs * speed;
56984
56961
  const states = animStatesRef.current;
@@ -57004,7 +56981,7 @@ function useSpriteAnimations(getSheetUrls, getFrameDims, options = {}) {
57004
56981
  const dir = inferDirection(dx, dy);
57005
56982
  if (state.animation !== "attack" && state.animation !== "hit" && state.animation !== "death") {
57006
56983
  state = transitionAnimation(state, "walk", dir);
57007
- walkHold.set(unit.id, WALK_HOLD_MS2);
56984
+ walkHold.set(unit.id, WALK_HOLD_MS);
57008
56985
  }
57009
56986
  } else if (state.animation === "walk") {
57010
56987
  const remaining = (walkHold.get(unit.id) ?? 0) - scaledDelta;
@@ -57876,15 +57853,15 @@ function NotifyListener() {
57876
57853
  }, []);
57877
57854
  useEffect(() => {
57878
57855
  const unsubscribe = eventBus.on("UI:NOTIFY", (event) => {
57879
- const payload = event.payload ?? event;
57880
- const message = typeof payload.message === "string" ? payload.message : "Notification";
57856
+ const payload = event.payload;
57857
+ const message = payload && typeof payload.message === "string" ? payload.message : "Notification";
57881
57858
  const severityMap = {
57882
57859
  success: "success",
57883
57860
  error: "error",
57884
57861
  warning: "warning",
57885
57862
  info: "info"
57886
57863
  };
57887
- const variant = severityMap[String(payload.severity)] || "info";
57864
+ const variant = payload && String(payload.severity) in severityMap ? severityMap[String(payload.severity)] : "info";
57888
57865
  const id = ++nextId;
57889
57866
  setItems((prev) => {
57890
57867
  const last = prev[prev.length - 1];