@almadar/ui 5.71.0 → 5.73.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 (55) hide show
  1. package/dist/avl/index.cjs +2178 -2309
  2. package/dist/avl/index.js +912 -1043
  3. package/dist/components/game/atoms/ActionButton.d.ts +3 -3
  4. package/dist/components/game/atoms/ChoiceButton.d.ts +3 -3
  5. package/dist/components/game/atoms/ComboCounter.d.ts +3 -3
  6. package/dist/components/game/atoms/ControlButton.d.ts +3 -3
  7. package/dist/components/game/atoms/DamageNumber.d.ts +3 -3
  8. package/dist/components/game/atoms/DialogueBubble.d.ts +3 -3
  9. package/dist/components/game/atoms/ItemSlot.d.ts +3 -3
  10. package/dist/components/game/atoms/ResourceCounter.d.ts +3 -3
  11. package/dist/components/game/atoms/ScoreDisplay.d.ts +4 -6
  12. package/dist/components/game/atoms/Sprite.d.ts +9 -21
  13. package/dist/components/game/atoms/StateIndicator.d.ts +2 -2
  14. package/dist/components/game/atoms/StatusEffect.d.ts +3 -3
  15. package/dist/components/game/atoms/TurnIndicator.d.ts +3 -3
  16. package/dist/components/game/atoms/WaypointMarker.d.ts +3 -3
  17. package/dist/components/game/atoms/XPBar.d.ts +1 -1
  18. package/dist/components/game/molecules/CardHand.d.ts +2 -2
  19. package/dist/components/game/molecules/DialogueBox.d.ts +3 -3
  20. package/dist/components/game/molecules/EnemyPlate.d.ts +3 -3
  21. package/dist/components/game/molecules/GameCanvas2D.d.ts +3 -3
  22. package/dist/components/game/molecules/GameCanvas3D.d.ts +0 -2
  23. package/dist/components/game/molecules/HealthPanel.d.ts +3 -3
  24. package/dist/components/game/molecules/IsometricCanvas.d.ts +11 -13
  25. package/dist/components/game/molecules/PlatformerCanvas.d.ts +4 -1
  26. package/dist/components/game/molecules/PowerupSlots.d.ts +3 -3
  27. package/dist/components/game/molecules/StatBadge.d.ts +6 -4
  28. package/dist/components/game/molecules/TurnPanel.d.ts +3 -3
  29. package/dist/components/game/molecules/three/index.cjs +55 -109
  30. package/dist/components/game/molecules/three/index.js +55 -109
  31. package/dist/components/game/molecules/useUnitSpriteAtlas.d.ts +6 -12
  32. package/dist/components/game/organisms/BattleBoard.d.ts +5 -6
  33. package/dist/components/game/organisms/CardBattlerBoard.d.ts +3 -4
  34. package/dist/components/game/organisms/CastleBoard.d.ts +5 -6
  35. package/dist/components/game/organisms/CityBuilderBoard.d.ts +6 -7
  36. package/dist/components/game/organisms/FishingBoard.d.ts +4 -6
  37. package/dist/components/game/organisms/PlatformerBoard.d.ts +5 -5
  38. package/dist/components/game/organisms/RoguelikeBoard.d.ts +4 -5
  39. package/dist/components/game/organisms/TopDownShooterBoard.d.ts +5 -6
  40. package/dist/components/game/organisms/TowerDefenseBoard.d.ts +5 -6
  41. package/dist/components/game/organisms/VisualNovelBoard.d.ts +4 -5
  42. package/dist/components/game/organisms/WorldMapBoard.d.ts +5 -6
  43. package/dist/components/game/organisms/types/effects.d.ts +7 -8
  44. package/dist/components/game/organisms/types/isometric.d.ts +24 -8
  45. package/dist/components/game/organisms/types/spriteAnimation.d.ts +3 -4
  46. package/dist/components/game/organisms/utils/makeAsset.d.ts +5 -0
  47. package/dist/components/game/templates/PlatformerTemplate.d.ts +5 -4
  48. package/dist/components/game/templates/game3dAssetManifest.d.ts +6 -8
  49. package/dist/components/index.cjs +2314 -2411
  50. package/dist/components/index.js +1203 -1300
  51. package/dist/providers/index.cjs +1987 -2118
  52. package/dist/providers/index.js +888 -1019
  53. package/dist/runtime/index.cjs +2043 -2174
  54. package/dist/runtime/index.js +892 -1023
  55. package/package.json +2 -2
@@ -1,5 +1,5 @@
1
- import * as React89 from 'react';
2
- import React89__default, { createContext, useMemo, useContext, useRef, useEffect, useCallback, Suspense, useState, useSyncExternalStore, useLayoutEffect, lazy, useId, forwardRef, useImperativeHandle, Component } from 'react';
1
+ import * as React87 from 'react';
2
+ import React87__default, { createContext, useMemo, useContext, useRef, useEffect, useCallback, Suspense, useState, useSyncExternalStore, useLayoutEffect, lazy, useId, forwardRef, useImperativeHandle, Component } from 'react';
3
3
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
4
4
  import { clsx } from 'clsx';
5
5
  import { twMerge } from 'tailwind-merge';
@@ -445,7 +445,7 @@ var init_Box = __esm({
445
445
  fixed: "fixed",
446
446
  sticky: "sticky"
447
447
  };
448
- Box = React89__default.forwardRef(
448
+ Box = React87__default.forwardRef(
449
449
  ({
450
450
  padding,
451
451
  paddingX,
@@ -510,7 +510,7 @@ var init_Box = __esm({
510
510
  onPointerDown?.(e);
511
511
  }, [hoverEvent, tapReveal, triggerProps, onPointerDown]);
512
512
  const isClickable = action || onClick;
513
- return React89__default.createElement(
513
+ return React87__default.createElement(
514
514
  Component2,
515
515
  {
516
516
  ref,
@@ -606,7 +606,7 @@ function loadLib(key, importer) {
606
606
  return p2;
607
607
  }
608
608
  function lazyFamilyIcon(libKey, importer, pick, fallbackName, family) {
609
- const Lazy = React89__default.lazy(async () => {
609
+ const Lazy = React87__default.lazy(async () => {
610
610
  const lib = await loadLib(libKey, importer);
611
611
  const Comp = pick(lib);
612
612
  if (!Comp) {
@@ -616,7 +616,7 @@ function lazyFamilyIcon(libKey, importer, pick, fallbackName, family) {
616
616
  return { default: Comp };
617
617
  });
618
618
  const Wrapped = (props) => /* @__PURE__ */ jsx(
619
- React89__default.Suspense,
619
+ React87__default.Suspense,
620
620
  {
621
621
  fallback: /* @__PURE__ */ jsx(
622
622
  "span",
@@ -1343,7 +1343,7 @@ var init_Icon = __esm({
1343
1343
  const directIcon = typeof icon === "string" ? void 0 : icon;
1344
1344
  const effectiveName = typeof icon === "string" ? icon : name;
1345
1345
  const family = useIconFamily();
1346
- const RenderedComponent = React89__default.useMemo(() => {
1346
+ const RenderedComponent = React87__default.useMemo(() => {
1347
1347
  if (directIcon) return null;
1348
1348
  return effectiveName ? resolveIconForFamily(effectiveName, family) : null;
1349
1349
  }, [directIcon, effectiveName, family]);
@@ -1405,7 +1405,7 @@ function resolveIconProp(value, sizeClass) {
1405
1405
  const IconComp = value;
1406
1406
  return /* @__PURE__ */ jsx(IconComp, { className: sizeClass });
1407
1407
  }
1408
- if (React89__default.isValidElement(value)) {
1408
+ if (React87__default.isValidElement(value)) {
1409
1409
  return value;
1410
1410
  }
1411
1411
  if (typeof value === "object" && value !== null && isIconLike(value)) {
@@ -1481,7 +1481,7 @@ var init_Button = __esm({
1481
1481
  md: "h-icon-default w-icon-default",
1482
1482
  lg: "h-icon-default w-icon-default"
1483
1483
  };
1484
- Button = React89__default.forwardRef(
1484
+ Button = React87__default.forwardRef(
1485
1485
  ({
1486
1486
  className,
1487
1487
  variant = "primary",
@@ -1547,7 +1547,7 @@ var Dialog;
1547
1547
  var init_Dialog = __esm({
1548
1548
  "components/core/atoms/Dialog.tsx"() {
1549
1549
  init_cn();
1550
- Dialog = React89__default.forwardRef(
1550
+ Dialog = React87__default.forwardRef(
1551
1551
  ({
1552
1552
  role = "dialog",
1553
1553
  "aria-modal": ariaModal = true,
@@ -1665,7 +1665,7 @@ var init_Typography = __esm({
1665
1665
  }) => {
1666
1666
  const variant = variantProp ?? (level ? `h${level}` : "body1");
1667
1667
  const Component2 = as || defaultElements[variant];
1668
- return React89__default.createElement(
1668
+ return React87__default.createElement(
1669
1669
  Component2,
1670
1670
  {
1671
1671
  id,
@@ -2160,7 +2160,7 @@ var init_Badge = __esm({
2160
2160
  md: "px-2.5 py-1 text-sm",
2161
2161
  lg: "px-3 py-1.5 text-base"
2162
2162
  };
2163
- Badge = React89__default.forwardRef(
2163
+ Badge = React87__default.forwardRef(
2164
2164
  ({ className, variant = "default", size = "sm", amount, label, icon, children, onRemove, removeLabel, ...props }, ref) => {
2165
2165
  const iconSizes3 = {
2166
2166
  sm: "h-icon-default w-icon-default",
@@ -2496,7 +2496,7 @@ var init_SvgFlow = __esm({
2496
2496
  width = 100,
2497
2497
  height = 100
2498
2498
  }) => {
2499
- const markerId = React89__default.useMemo(() => {
2499
+ const markerId = React87__default.useMemo(() => {
2500
2500
  flowIdCounter += 1;
2501
2501
  return `almadar-flow-arrow-${flowIdCounter}`;
2502
2502
  }, []);
@@ -3089,7 +3089,7 @@ var init_SvgRing = __esm({
3089
3089
  width = 100,
3090
3090
  height = 100
3091
3091
  }) => {
3092
- const gradientId = React89__default.useMemo(() => {
3092
+ const gradientId = React87__default.useMemo(() => {
3093
3093
  ringIdCounter += 1;
3094
3094
  return `almadar-ring-glow-${ringIdCounter}`;
3095
3095
  }, []);
@@ -3270,7 +3270,7 @@ var init_Input = __esm({
3270
3270
  init_cn();
3271
3271
  init_Icon();
3272
3272
  init_useEventBus();
3273
- Input = React89__default.forwardRef(
3273
+ Input = React87__default.forwardRef(
3274
3274
  ({
3275
3275
  className,
3276
3276
  inputType,
@@ -3430,7 +3430,7 @@ var Label;
3430
3430
  var init_Label = __esm({
3431
3431
  "components/core/atoms/Label.tsx"() {
3432
3432
  init_cn();
3433
- Label = React89__default.forwardRef(
3433
+ Label = React87__default.forwardRef(
3434
3434
  ({ className, required, children, ...props }, ref) => {
3435
3435
  return /* @__PURE__ */ jsxs(
3436
3436
  "label",
@@ -3457,7 +3457,7 @@ var init_Textarea = __esm({
3457
3457
  "components/core/atoms/Textarea.tsx"() {
3458
3458
  init_cn();
3459
3459
  init_useEventBus();
3460
- Textarea = React89__default.forwardRef(
3460
+ Textarea = React87__default.forwardRef(
3461
3461
  ({ className, error, onChange, ...props }, ref) => {
3462
3462
  const eventBus = useEventBus();
3463
3463
  const handleChange = (e) => {
@@ -3696,7 +3696,7 @@ var init_Select = __esm({
3696
3696
  init_cn();
3697
3697
  init_Icon();
3698
3698
  init_useEventBus();
3699
- Select = React89__default.forwardRef(
3699
+ Select = React87__default.forwardRef(
3700
3700
  (props, _ref) => {
3701
3701
  const { multiple, searchable, clearable } = props;
3702
3702
  if (multiple || searchable || clearable) {
@@ -3713,7 +3713,7 @@ var init_Checkbox = __esm({
3713
3713
  "components/core/atoms/Checkbox.tsx"() {
3714
3714
  init_cn();
3715
3715
  init_useEventBus();
3716
- Checkbox = React89__default.forwardRef(
3716
+ Checkbox = React87__default.forwardRef(
3717
3717
  ({ className, label, id, onChange, ...props }, ref) => {
3718
3718
  const inputId = id || `checkbox-${Math.random().toString(36).substr(2, 9)}`;
3719
3719
  const eventBus = useEventBus();
@@ -3767,7 +3767,7 @@ var init_Spinner = __esm({
3767
3767
  md: "h-6 w-6",
3768
3768
  lg: "h-8 w-8"
3769
3769
  };
3770
- Spinner = React89__default.forwardRef(
3770
+ Spinner = React87__default.forwardRef(
3771
3771
  ({ className, size = "md", overlay, ...props }, ref) => {
3772
3772
  if (overlay) {
3773
3773
  return /* @__PURE__ */ jsx(
@@ -3857,7 +3857,7 @@ var init_Card = __esm({
3857
3857
  chip: "shadow-none rounded-pill border-[length:var(--border-width)] border-border",
3858
3858
  "tile-image-first": "p-0 overflow-hidden"
3859
3859
  };
3860
- Card = React89__default.forwardRef(
3860
+ Card = React87__default.forwardRef(
3861
3861
  ({
3862
3862
  className,
3863
3863
  variant = "bordered",
@@ -3905,9 +3905,9 @@ var init_Card = __esm({
3905
3905
  }
3906
3906
  );
3907
3907
  Card.displayName = "Card";
3908
- CardHeader = React89__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("mb-4", className), ...props }));
3908
+ CardHeader = React87__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("mb-4", className), ...props }));
3909
3909
  CardHeader.displayName = "CardHeader";
3910
- CardTitle = React89__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
3910
+ CardTitle = React87__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
3911
3911
  "h3",
3912
3912
  {
3913
3913
  ref,
@@ -3920,11 +3920,11 @@ var init_Card = __esm({
3920
3920
  }
3921
3921
  ));
3922
3922
  CardTitle.displayName = "CardTitle";
3923
- CardContent = React89__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("", className), ...props }));
3923
+ CardContent = React87__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("", className), ...props }));
3924
3924
  CardContent.displayName = "CardContent";
3925
3925
  CardBody = CardContent;
3926
3926
  CardBody.displayName = "CardBody";
3927
- CardFooter = React89__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
3927
+ CardFooter = React87__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
3928
3928
  "div",
3929
3929
  {
3930
3930
  ref,
@@ -3979,7 +3979,7 @@ var init_FilterPill = __esm({
3979
3979
  md: "w-3.5 h-3.5",
3980
3980
  lg: "w-4 h-4"
3981
3981
  };
3982
- FilterPill = React89__default.forwardRef(
3982
+ FilterPill = React87__default.forwardRef(
3983
3983
  ({
3984
3984
  className,
3985
3985
  variant = "default",
@@ -4108,8 +4108,8 @@ var init_Avatar = __esm({
4108
4108
  actionPayload
4109
4109
  }) => {
4110
4110
  const eventBus = useEventBus();
4111
- const [imgFailed, setImgFailed] = React89__default.useState(false);
4112
- React89__default.useEffect(() => {
4111
+ const [imgFailed, setImgFailed] = React87__default.useState(false);
4112
+ React87__default.useEffect(() => {
4113
4113
  setImgFailed(false);
4114
4114
  }, [src]);
4115
4115
  const initials = providedInitials ?? (name ? generateInitials(name) : void 0);
@@ -4222,7 +4222,7 @@ var init_Center = __esm({
4222
4222
  as: Component2 = "div"
4223
4223
  }) => {
4224
4224
  const mergedStyle = minHeight ? { minHeight, ...style } : style;
4225
- return React89__default.createElement(Component2, {
4225
+ return React87__default.createElement(Component2, {
4226
4226
  className: cn(
4227
4227
  inline ? "inline-flex" : "flex",
4228
4228
  horizontal && "justify-center",
@@ -4490,7 +4490,7 @@ var init_Radio = __esm({
4490
4490
  md: "w-2.5 h-2.5",
4491
4491
  lg: "w-3 h-3"
4492
4492
  };
4493
- Radio = React89__default.forwardRef(
4493
+ Radio = React87__default.forwardRef(
4494
4494
  ({
4495
4495
  label,
4496
4496
  helperText,
@@ -4507,12 +4507,12 @@ var init_Radio = __esm({
4507
4507
  onChange,
4508
4508
  ...props
4509
4509
  }, ref) => {
4510
- const reactId = React89__default.useId();
4510
+ const reactId = React87__default.useId();
4511
4511
  const baseId = id || `radio-${reactId}`;
4512
4512
  const hasError = !!error;
4513
4513
  const eventBus = useEventBus();
4514
- const [selected, setSelected] = React89__default.useState(value);
4515
- React89__default.useEffect(() => {
4514
+ const [selected, setSelected] = React87__default.useState(value);
4515
+ React87__default.useEffect(() => {
4516
4516
  if (value !== void 0) setSelected(value);
4517
4517
  }, [value]);
4518
4518
  const pick = (next, e) => {
@@ -4694,7 +4694,7 @@ var init_Switch = __esm({
4694
4694
  "components/core/atoms/Switch.tsx"() {
4695
4695
  "use client";
4696
4696
  init_cn();
4697
- Switch = React89.forwardRef(
4697
+ Switch = React87.forwardRef(
4698
4698
  ({
4699
4699
  checked,
4700
4700
  defaultChecked = false,
@@ -4705,10 +4705,10 @@ var init_Switch = __esm({
4705
4705
  name,
4706
4706
  className
4707
4707
  }, ref) => {
4708
- const [isChecked, setIsChecked] = React89.useState(
4708
+ const [isChecked, setIsChecked] = React87.useState(
4709
4709
  checked !== void 0 ? checked : defaultChecked
4710
4710
  );
4711
- React89.useEffect(() => {
4711
+ React87.useEffect(() => {
4712
4712
  if (checked !== void 0) {
4713
4713
  setIsChecked(checked);
4714
4714
  }
@@ -4867,7 +4867,7 @@ var init_Stack = __esm({
4867
4867
  };
4868
4868
  const isHorizontal = direction === "horizontal";
4869
4869
  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";
4870
- return React89__default.createElement(
4870
+ return React87__default.createElement(
4871
4871
  Component2,
4872
4872
  {
4873
4873
  className: cn(
@@ -5067,7 +5067,7 @@ var Aside;
5067
5067
  var init_Aside = __esm({
5068
5068
  "components/core/atoms/Aside.tsx"() {
5069
5069
  init_cn();
5070
- Aside = React89__default.forwardRef(
5070
+ Aside = React87__default.forwardRef(
5071
5071
  ({ className, children, ...rest }, ref) => /* @__PURE__ */ jsx("aside", { ref, className: cn(className), ...rest, children })
5072
5072
  );
5073
5073
  Aside.displayName = "Aside";
@@ -5146,9 +5146,9 @@ var init_LawReferenceTooltip = __esm({
5146
5146
  className
5147
5147
  }) => {
5148
5148
  const { t } = useTranslate();
5149
- const [isVisible, setIsVisible] = React89__default.useState(false);
5150
- const timeoutRef = React89__default.useRef(null);
5151
- const triggerRef = React89__default.useRef(null);
5149
+ const [isVisible, setIsVisible] = React87__default.useState(false);
5150
+ const timeoutRef = React87__default.useRef(null);
5151
+ const triggerRef = React87__default.useRef(null);
5152
5152
  const handleMouseEnter = () => {
5153
5153
  if (timeoutRef.current) clearTimeout(timeoutRef.current);
5154
5154
  timeoutRef.current = setTimeout(() => setIsVisible(true), 200);
@@ -5159,7 +5159,7 @@ var init_LawReferenceTooltip = __esm({
5159
5159
  };
5160
5160
  const { revealed, triggerProps } = useTapReveal({ refs: [triggerRef] });
5161
5161
  const open = isVisible || revealed;
5162
- React89__default.useEffect(() => {
5162
+ React87__default.useEffect(() => {
5163
5163
  return () => {
5164
5164
  if (timeoutRef.current) clearTimeout(timeoutRef.current);
5165
5165
  };
@@ -5371,7 +5371,7 @@ var init_StatusDot = __esm({
5371
5371
  md: "w-2.5 h-2.5",
5372
5372
  lg: "w-3 h-3"
5373
5373
  };
5374
- StatusDot = React89__default.forwardRef(
5374
+ StatusDot = React87__default.forwardRef(
5375
5375
  ({ className, status = "offline", pulse = false, size = "md", label, ...props }, ref) => {
5376
5376
  return /* @__PURE__ */ jsx(
5377
5377
  "span",
@@ -5425,7 +5425,7 @@ var init_TrendIndicator = __esm({
5425
5425
  down: "trending-down",
5426
5426
  flat: "arrow-right"
5427
5427
  };
5428
- TrendIndicator = React89__default.forwardRef(
5428
+ TrendIndicator = React87__default.forwardRef(
5429
5429
  ({
5430
5430
  className,
5431
5431
  value,
@@ -5492,7 +5492,7 @@ var init_RangeSlider = __esm({
5492
5492
  md: "w-4 h-4",
5493
5493
  lg: "w-5 h-5"
5494
5494
  };
5495
- RangeSlider = React89__default.forwardRef(
5495
+ RangeSlider = React87__default.forwardRef(
5496
5496
  ({
5497
5497
  className,
5498
5498
  min = 0,
@@ -6000,7 +6000,7 @@ var init_ContentSection = __esm({
6000
6000
  md: "py-16",
6001
6001
  lg: "py-24"
6002
6002
  };
6003
- ContentSection = React89__default.forwardRef(
6003
+ ContentSection = React87__default.forwardRef(
6004
6004
  ({ children, background = "default", padding = "lg", id, className }, ref) => {
6005
6005
  return /* @__PURE__ */ jsx(
6006
6006
  Box,
@@ -6534,7 +6534,7 @@ var init_AnimatedReveal = __esm({
6534
6534
  "scale-up": { opacity: 1, transform: "scale(1) translateY(0)" },
6535
6535
  "none": {}
6536
6536
  };
6537
- AnimatedReveal = React89__default.forwardRef(
6537
+ AnimatedReveal = React87__default.forwardRef(
6538
6538
  ({
6539
6539
  trigger = "scroll",
6540
6540
  animation = "fade-up",
@@ -6694,7 +6694,7 @@ var init_AnimatedGraphic = __esm({
6694
6694
  "components/marketing/atoms/AnimatedGraphic.tsx"() {
6695
6695
  "use client";
6696
6696
  init_cn();
6697
- AnimatedGraphic = React89__default.forwardRef(
6697
+ AnimatedGraphic = React87__default.forwardRef(
6698
6698
  ({
6699
6699
  src,
6700
6700
  svgContent,
@@ -6717,7 +6717,7 @@ var init_AnimatedGraphic = __esm({
6717
6717
  const fetchedSvg = useFetchedSvg(svgContent ? void 0 : src);
6718
6718
  const resolvedSvg = svgContent ?? fetchedSvg;
6719
6719
  const prevAnimateRef = useRef(animate);
6720
- const setRef = React89__default.useCallback(
6720
+ const setRef = React87__default.useCallback(
6721
6721
  (node) => {
6722
6722
  containerRef.current = node;
6723
6723
  if (typeof ref === "function") ref(node);
@@ -6939,50 +6939,23 @@ function ScoreDisplay({
6939
6939
  icon,
6940
6940
  size = "md",
6941
6941
  className,
6942
- animated = true,
6943
6942
  locale = "en-US"
6944
6943
  }) {
6945
6944
  const resolvedValue = typeof value === "number" && !Number.isNaN(value) ? value : typeof score === "number" && !Number.isNaN(score) ? score : 0;
6946
- const [displayValue, setDisplayValue] = React89.useState(resolvedValue);
6947
- const [isAnimating, setIsAnimating] = React89.useState(false);
6948
- React89.useEffect(() => {
6949
- if (!animated || displayValue === resolvedValue) {
6950
- setDisplayValue(resolvedValue);
6951
- return;
6952
- }
6953
- setIsAnimating(true);
6954
- const diff = resolvedValue - displayValue;
6955
- const steps = Math.min(Math.abs(diff), 20);
6956
- const increment = diff / steps;
6957
- let current = displayValue;
6958
- let step = 0;
6959
- const timer = setInterval(() => {
6960
- step++;
6961
- current += increment;
6962
- setDisplayValue(Math.round(current));
6963
- if (step >= steps) {
6964
- clearInterval(timer);
6965
- setDisplayValue(resolvedValue);
6966
- setIsAnimating(false);
6967
- }
6968
- }, 50);
6969
- return () => clearInterval(timer);
6970
- }, [resolvedValue, animated]);
6971
- const formattedValue = new Intl.NumberFormat(locale).format(displayValue);
6945
+ const formattedValue = new Intl.NumberFormat(locale).format(resolvedValue);
6972
6946
  return /* @__PURE__ */ jsxs(
6973
6947
  "div",
6974
6948
  {
6975
6949
  className: cn(
6976
6950
  "flex items-center gap-2 font-bold",
6977
6951
  sizeMap2[size],
6978
- isAnimating && "animate-pulse",
6979
6952
  className
6980
6953
  ),
6981
6954
  children: [
6982
6955
  assetUrl ? /* @__PURE__ */ jsx(
6983
6956
  "img",
6984
6957
  {
6985
- src: assetUrl,
6958
+ src: assetUrl.url,
6986
6959
  alt: "",
6987
6960
  width: 20,
6988
6961
  height: 20,
@@ -6999,7 +6972,6 @@ function ScoreDisplay({
6999
6972
  var sizeMap2, DEFAULT_ASSET_URL;
7000
6973
  var init_ScoreDisplay = __esm({
7001
6974
  "components/game/atoms/ScoreDisplay.tsx"() {
7002
- "use client";
7003
6975
  init_cn();
7004
6976
  init_Icon();
7005
6977
  sizeMap2 = {
@@ -7008,7 +6980,11 @@ var init_ScoreDisplay = __esm({
7008
6980
  lg: "text-2xl",
7009
6981
  xl: "text-4xl"
7010
6982
  };
7011
- DEFAULT_ASSET_URL = "https://almadar-kflow-assets.web.app/shared/effects/particles/star_01.png";
6983
+ DEFAULT_ASSET_URL = {
6984
+ url: "https://almadar-kflow-assets.web.app/shared/effects/particles/star_01.png",
6985
+ role: "effect",
6986
+ category: "effect"
6987
+ };
7012
6988
  ScoreDisplay.displayName = "ScoreDisplay";
7013
6989
  }
7014
6990
  });
@@ -7028,9 +7004,9 @@ function ControlButton({
7028
7004
  className
7029
7005
  }) {
7030
7006
  const eventBus = useEventBus();
7031
- const [isPressed, setIsPressed] = React89.useState(false);
7007
+ const [isPressed, setIsPressed] = React87.useState(false);
7032
7008
  const actualPressed = pressed ?? isPressed;
7033
- const handlePointerDown = React89.useCallback(
7009
+ const handlePointerDown = React87.useCallback(
7034
7010
  (e) => {
7035
7011
  e.preventDefault();
7036
7012
  if (disabled) return;
@@ -7040,7 +7016,7 @@ function ControlButton({
7040
7016
  },
7041
7017
  [disabled, pressEvent, eventBus, onPress]
7042
7018
  );
7043
- const handlePointerUp = React89.useCallback(
7019
+ const handlePointerUp = React87.useCallback(
7044
7020
  (e) => {
7045
7021
  e.preventDefault();
7046
7022
  if (disabled) return;
@@ -7050,7 +7026,7 @@ function ControlButton({
7050
7026
  },
7051
7027
  [disabled, releaseEvent, eventBus, onRelease]
7052
7028
  );
7053
- const handlePointerLeave = React89.useCallback(
7029
+ const handlePointerLeave = React87.useCallback(
7054
7030
  (e) => {
7055
7031
  if (isPressed) {
7056
7032
  setIsPressed(false);
@@ -7084,7 +7060,7 @@ function ControlButton({
7084
7060
  children: assetUrl ? /* @__PURE__ */ jsx(
7085
7061
  "img",
7086
7062
  {
7087
- src: assetUrl,
7063
+ src: assetUrl.url,
7088
7064
  alt: "",
7089
7065
  width: 24,
7090
7066
  height: 24,
@@ -7124,7 +7100,11 @@ var init_ControlButton = __esm({
7124
7100
  secondary: "bg-secondary text-secondary-foreground border-border hover:bg-secondary-hover",
7125
7101
  ghost: "bg-transparent text-foreground border-border hover:bg-muted"
7126
7102
  };
7127
- DEFAULT_ASSET_URL2 = "https://almadar-kflow-assets.web.app/shared/effects/particles/circle_01.png";
7103
+ DEFAULT_ASSET_URL2 = {
7104
+ url: "https://almadar-kflow-assets.web.app/shared/effects/particles/circle_01.png",
7105
+ role: "effect",
7106
+ category: "effect"
7107
+ };
7128
7108
  ControlButton.displayName = "ControlButton";
7129
7109
  }
7130
7110
  });
@@ -7138,13 +7118,6 @@ var init_spriteSheetConstants = __esm({
7138
7118
  });
7139
7119
 
7140
7120
  // components/game/organisms/utils/spriteAnimation.ts
7141
- function inferDirection(dx, dy) {
7142
- if (dx === 0 && dy === 0) return "se";
7143
- if (dx >= 0 && dy >= 0) return "se";
7144
- if (dx <= 0 && dy >= 0) return "sw";
7145
- if (dx >= 0 && dy <= 0) return "ne";
7146
- return "nw";
7147
- }
7148
7121
  function resolveSheetDirection(facing) {
7149
7122
  switch (facing) {
7150
7123
  case "se":
@@ -7165,25 +7138,12 @@ function frameRect(frame, row, columns, frameWidth, frameHeight) {
7165
7138
  sh: frameHeight
7166
7139
  };
7167
7140
  }
7168
- function getCurrentFrameFromDef(def, elapsed) {
7169
- const frameDuration = 1e3 / def.frameRate;
7170
- const totalDuration = def.frames * frameDuration;
7171
- if (def.loop) {
7172
- const frame2 = Math.floor(elapsed % totalDuration / frameDuration);
7173
- return { frame: frame2, finished: false };
7174
- }
7175
- if (elapsed >= totalDuration) {
7176
- return { frame: def.frames - 1, finished: true };
7177
- }
7178
- const frame = Math.floor(elapsed / frameDuration);
7179
- return { frame, finished: false };
7180
- }
7181
7141
  var init_spriteAnimation = __esm({
7182
7142
  "components/game/organisms/utils/spriteAnimation.ts"() {
7183
7143
  }
7184
7144
  });
7185
7145
  function Sprite({
7186
- spritesheet = "https://almadar-kflow-assets.web.app/shared/isometric-blocks/Spritesheet/allTiles_sheet.png",
7146
+ spritesheet = DEFAULT_SPRITESHEET,
7187
7147
  frameWidth = 64,
7188
7148
  frameHeight = 64,
7189
7149
  frame = 0,
@@ -7196,6 +7156,8 @@ function Sprite({
7196
7156
  opacity = 1,
7197
7157
  zIndex = 0,
7198
7158
  columns = 16,
7159
+ animState: _animState,
7160
+ frameRate: _frameRate,
7199
7161
  className,
7200
7162
  onClick,
7201
7163
  action
@@ -7234,7 +7196,7 @@ function Sprite({
7234
7196
  position: "absolute",
7235
7197
  width: frameWidth,
7236
7198
  height: frameHeight,
7237
- backgroundImage: `url(${spritesheet})`,
7199
+ backgroundImage: `url(${spritesheet.url})`,
7238
7200
  backgroundPosition,
7239
7201
  backgroundRepeat: "no-repeat",
7240
7202
  imageRendering: "pixelated",
@@ -7247,11 +7209,17 @@ function Sprite({
7247
7209
  }
7248
7210
  );
7249
7211
  }
7212
+ var DEFAULT_SPRITESHEET;
7250
7213
  var init_Sprite = __esm({
7251
7214
  "components/game/atoms/Sprite.tsx"() {
7252
7215
  "use client";
7253
7216
  init_useEventBus();
7254
7217
  init_spriteAnimation();
7218
+ DEFAULT_SPRITESHEET = {
7219
+ url: "https://almadar-kflow-assets.web.app/shared/isometric-blocks/Spritesheet/allTiles_sheet.png",
7220
+ role: "tile",
7221
+ category: "tile"
7222
+ };
7255
7223
  }
7256
7224
  });
7257
7225
  function StateIndicator({
@@ -7281,7 +7249,7 @@ function StateIndicator({
7281
7249
  /* @__PURE__ */ jsx(Box, { as: "span", children: assetUrl ? /* @__PURE__ */ jsx(
7282
7250
  "img",
7283
7251
  {
7284
- src: assetUrl,
7252
+ src: assetUrl.url,
7285
7253
  alt: displayLabel,
7286
7254
  width: 16,
7287
7255
  height: 16,
@@ -7300,7 +7268,11 @@ var init_StateIndicator = __esm({
7300
7268
  init_Box();
7301
7269
  init_Icon();
7302
7270
  init_cn();
7303
- DEFAULT_ASSET_URL3 = "https://almadar-kflow-assets.web.app/shared/isometric-dungeon/Isometric/chestClosed_E.png";
7271
+ DEFAULT_ASSET_URL3 = {
7272
+ url: "https://almadar-kflow-assets.web.app/shared/isometric-dungeon/Isometric/chestClosed_E.png",
7273
+ role: "effect",
7274
+ category: "item"
7275
+ };
7304
7276
  DEFAULT_STATE_STYLES = {
7305
7277
  idle: { icon: "\u23F8", bgClass: "bg-muted" },
7306
7278
  active: { icon: "\u25B6", bgClass: "bg-success" },
@@ -7398,7 +7370,7 @@ function ResourceCounter({
7398
7370
  assetUrl ? /* @__PURE__ */ jsx(
7399
7371
  "img",
7400
7372
  {
7401
- src: assetUrl,
7373
+ src: assetUrl.url,
7402
7374
  alt: label,
7403
7375
  width: sizes.img,
7404
7376
  height: sizes.img,
@@ -7431,7 +7403,11 @@ var init_ResourceCounter = __esm({
7431
7403
  error: "text-error",
7432
7404
  muted: "text-muted-foreground"
7433
7405
  };
7434
- DEFAULT_ASSET_URL4 = "https://almadar-kflow-assets.web.app/shared/world-map/gold_mine.png";
7406
+ DEFAULT_ASSET_URL4 = {
7407
+ url: "https://almadar-kflow-assets.web.app/shared/world-map/gold_mine.png",
7408
+ role: "effect",
7409
+ category: "world"
7410
+ };
7435
7411
  sizeMap5 = {
7436
7412
  sm: { wrapper: "text-xs gap-1 px-1.5 py-0.5", icon: "text-sm", img: 16 },
7437
7413
  md: { wrapper: "text-sm gap-1.5 px-2 py-1", icon: "text-base", img: 20 },
@@ -7477,7 +7453,7 @@ function ItemSlot({
7477
7453
  assetUrl ? /* @__PURE__ */ jsx(
7478
7454
  "img",
7479
7455
  {
7480
- src: assetUrl,
7456
+ src: assetUrl?.url,
7481
7457
  alt: label,
7482
7458
  width: px,
7483
7459
  height: px,
@@ -7525,7 +7501,11 @@ var init_ItemSlot = __esm({
7525
7501
  epic: "shadow-lg",
7526
7502
  legendary: "shadow-lg"
7527
7503
  };
7528
- DEFAULT_ASSET_URL5 = "https://almadar-kflow-assets.web.app/shared/isometric-dungeon/Isometric/chestClosed_E.png";
7504
+ DEFAULT_ASSET_URL5 = {
7505
+ url: "https://almadar-kflow-assets.web.app/shared/isometric-dungeon/Isometric/chestClosed_E.png",
7506
+ role: "effect",
7507
+ category: "item"
7508
+ };
7529
7509
  assetSizeMap = {
7530
7510
  sm: 28,
7531
7511
  md: 40,
@@ -7571,7 +7551,7 @@ function TurnIndicator({
7571
7551
  assetUrl ? /* @__PURE__ */ jsx(
7572
7552
  "img",
7573
7553
  {
7574
- src: assetUrl,
7554
+ src: assetUrl.url,
7575
7555
  alt: "",
7576
7556
  width: 12,
7577
7557
  height: 12,
@@ -7594,7 +7574,11 @@ var init_TurnIndicator = __esm({
7594
7574
  md: { wrapper: "text-sm gap-2 px-3 py-1", dot: "w-2 h-2" },
7595
7575
  lg: { wrapper: "text-base gap-2.5 px-4 py-1.5", dot: "w-2.5 h-2.5" }
7596
7576
  };
7597
- DEFAULT_ASSET_URL6 = "https://almadar-kflow-assets.web.app/shared/effects/particles/symbol_01.png";
7577
+ DEFAULT_ASSET_URL6 = {
7578
+ url: "https://almadar-kflow-assets.web.app/shared/effects/particles/symbol_01.png",
7579
+ role: "effect",
7580
+ category: "effect"
7581
+ };
7598
7582
  TurnIndicator.displayName = "TurnIndicator";
7599
7583
  }
7600
7584
  });
@@ -7633,7 +7617,7 @@ function ComboCounter({
7633
7617
  assetUrl && /* @__PURE__ */ jsx(
7634
7618
  "img",
7635
7619
  {
7636
- src: assetUrl,
7620
+ src: assetUrl.url,
7637
7621
  alt: "combo",
7638
7622
  width: 24,
7639
7623
  height: 24,
@@ -7659,7 +7643,11 @@ var DEFAULT_ASSET_URL7, sizeMap8;
7659
7643
  var init_ComboCounter = __esm({
7660
7644
  "components/game/atoms/ComboCounter.tsx"() {
7661
7645
  init_cn();
7662
- DEFAULT_ASSET_URL7 = "https://almadar-kflow-assets.web.app/shared/effects/flash/flash00.png";
7646
+ DEFAULT_ASSET_URL7 = {
7647
+ url: "https://almadar-kflow-assets.web.app/shared/effects/flash/flash00.png",
7648
+ role: "effect",
7649
+ category: "effect"
7650
+ };
7663
7651
  sizeMap8 = {
7664
7652
  sm: { combo: "text-lg", label: "text-xs", multiplier: "text-xs" },
7665
7653
  md: { combo: "text-2xl", label: "text-xs", multiplier: "text-sm" },
@@ -7679,21 +7667,6 @@ function XPBar({
7679
7667
  }) {
7680
7668
  const sizes = sizeMap9[size];
7681
7669
  const percentage = max > 0 ? Math.max(0, Math.min(100, current / max * 100)) : 0;
7682
- const [fillWidth, setFillWidth] = React89.useState(animated ? 0 : percentage);
7683
- React89.useEffect(() => {
7684
- if (!animated) {
7685
- setFillWidth(percentage);
7686
- return;
7687
- }
7688
- let frame2;
7689
- const frame1 = requestAnimationFrame(() => {
7690
- frame2 = requestAnimationFrame(() => setFillWidth(percentage));
7691
- });
7692
- return () => {
7693
- cancelAnimationFrame(frame1);
7694
- cancelAnimationFrame(frame2);
7695
- };
7696
- }, [animated, percentage]);
7697
7670
  return /* @__PURE__ */ jsxs("div", { className: cn("flex items-center gap-2", className), children: [
7698
7671
  level != null && /* @__PURE__ */ jsxs(
7699
7672
  "span",
@@ -7725,7 +7698,7 @@ function XPBar({
7725
7698
  "bg-gradient-to-r from-accent to-info",
7726
7699
  animated && "transition-all duration-500 ease-out"
7727
7700
  ),
7728
- style: { width: `${fillWidth}%` }
7701
+ style: { width: `${percentage}%` }
7729
7702
  }
7730
7703
  )
7731
7704
  }
@@ -7742,7 +7715,6 @@ function XPBar({
7742
7715
  var sizeMap9;
7743
7716
  var init_XPBar = __esm({
7744
7717
  "components/game/atoms/XPBar.tsx"() {
7745
- "use client";
7746
7718
  init_cn();
7747
7719
  sizeMap9 = {
7748
7720
  sm: { bar: "h-2", text: "text-xs", badge: "text-xs px-1.5 py-0.5" },
@@ -7795,7 +7767,7 @@ function WaypointMarker({
7795
7767
  children: completed ? checkIcon : assetUrl ? /* @__PURE__ */ jsx(
7796
7768
  "img",
7797
7769
  {
7798
- src: assetUrl,
7770
+ src: assetUrl.url,
7799
7771
  alt: label,
7800
7772
  width: sizes.img,
7801
7773
  height: sizes.img,
@@ -7824,7 +7796,11 @@ var init_WaypointMarker = __esm({
7824
7796
  "components/game/atoms/WaypointMarker.tsx"() {
7825
7797
  init_cn();
7826
7798
  init_Icon();
7827
- DEFAULT_ASSET_URL8 = "https://almadar-kflow-assets.web.app/shared/world-map/battle_marker.png";
7799
+ DEFAULT_ASSET_URL8 = {
7800
+ url: "https://almadar-kflow-assets.web.app/shared/world-map/battle_marker.png",
7801
+ role: "effect",
7802
+ category: "world"
7803
+ };
7828
7804
  sizeMap10 = {
7829
7805
  sm: { dot: "w-4 h-4", ring: "w-6 h-6", label: "text-xs mt-1", img: 12 },
7830
7806
  md: { dot: "w-6 h-6", ring: "w-8 h-8", label: "text-sm mt-1.5", img: 18 },
@@ -7865,7 +7841,7 @@ function StatusEffect({
7865
7841
  /* @__PURE__ */ jsx("span", { className: cn("flex items-center justify-center", sizes.icon), children: assetUrl ? /* @__PURE__ */ jsx(
7866
7842
  "img",
7867
7843
  {
7868
- src: assetUrl,
7844
+ src: assetUrl.url,
7869
7845
  alt: label,
7870
7846
  width: sizes.img,
7871
7847
  height: sizes.img,
@@ -7904,7 +7880,11 @@ var init_StatusEffect = __esm({
7904
7880
  "components/game/atoms/StatusEffect.tsx"() {
7905
7881
  init_cn();
7906
7882
  init_Icon();
7907
- DEFAULT_ASSET_URL9 = "https://almadar-kflow-assets.web.app/shared/effects/particles/flame_01.png";
7883
+ DEFAULT_ASSET_URL9 = {
7884
+ url: "https://almadar-kflow-assets.web.app/shared/effects/particles/flame_01.png",
7885
+ role: "effect",
7886
+ category: "effect"
7887
+ };
7908
7888
  sizeMap11 = {
7909
7889
  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 },
7910
7890
  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 },
@@ -7942,7 +7922,7 @@ function DamageNumber({
7942
7922
  assetUrl && /* @__PURE__ */ jsx(
7943
7923
  "img",
7944
7924
  {
7945
- src: assetUrl,
7925
+ src: assetUrl.url,
7946
7926
  alt: "",
7947
7927
  width: 14,
7948
7928
  height: 14,
@@ -7978,14 +7958,18 @@ var init_DamageNumber = __esm({
7978
7958
  100% { opacity: 0; transform: translateY(-32px) scale(0.8); }
7979
7959
  }
7980
7960
  `;
7981
- DEFAULT_ASSET_URL10 = "https://almadar-kflow-assets.web.app/shared/effects/particles/spark_01.png";
7961
+ DEFAULT_ASSET_URL10 = {
7962
+ url: "https://almadar-kflow-assets.web.app/shared/effects/particles/spark_01.png",
7963
+ role: "effect",
7964
+ category: "effect"
7965
+ };
7982
7966
  DamageNumber.displayName = "DamageNumber";
7983
7967
  }
7984
7968
  });
7985
7969
  function DialogueBubble({
7986
7970
  speaker = "Hero",
7987
7971
  text = "The dungeon awaits. Choose your path wisely.",
7988
- portrait = "https://almadar-kflow-assets.web.app/shared/characters/archetypes/04_hero.png",
7972
+ portrait = DEFAULT_PORTRAIT,
7989
7973
  position = "bottom",
7990
7974
  className
7991
7975
  }) {
@@ -8001,7 +7985,7 @@ function DialogueBubble({
8001
7985
  portrait && /* @__PURE__ */ jsx("div", { className: "flex-shrink-0 w-12 h-12 rounded-full overflow-hidden border-2 border-warning/60", children: /* @__PURE__ */ jsx(
8002
7986
  "img",
8003
7987
  {
8004
- src: portrait,
7988
+ src: portrait?.url,
8005
7989
  alt: speaker ?? "speaker",
8006
7990
  className: "w-full h-full object-cover"
8007
7991
  }
@@ -8014,9 +7998,15 @@ function DialogueBubble({
8014
7998
  }
8015
7999
  );
8016
8000
  }
8001
+ var DEFAULT_PORTRAIT;
8017
8002
  var init_DialogueBubble = __esm({
8018
8003
  "components/game/atoms/DialogueBubble.tsx"() {
8019
8004
  init_cn();
8005
+ DEFAULT_PORTRAIT = {
8006
+ url: "https://almadar-kflow-assets.web.app/shared/characters/archetypes/04_hero.png",
8007
+ role: "effect",
8008
+ category: "character"
8009
+ };
8020
8010
  DialogueBubble.displayName = "DialogueBubble";
8021
8011
  }
8022
8012
  });
@@ -8060,7 +8050,7 @@ function ChoiceButton({
8060
8050
  assetUrl ? /* @__PURE__ */ jsx(
8061
8051
  "img",
8062
8052
  {
8063
- src: assetUrl,
8053
+ src: assetUrl.url,
8064
8054
  alt: "",
8065
8055
  width: 16,
8066
8056
  height: 16,
@@ -8130,7 +8120,7 @@ function ActionButton({
8130
8120
  assetUrl ? /* @__PURE__ */ jsx(
8131
8121
  "img",
8132
8122
  {
8133
- src: assetUrl,
8123
+ src: assetUrl.url,
8134
8124
  alt: "",
8135
8125
  width: 16,
8136
8126
  height: 16,
@@ -8174,7 +8164,11 @@ var init_ActionButton = __esm({
8174
8164
  secondary: "bg-secondary text-secondary-foreground hover:bg-secondary-hover border-border",
8175
8165
  danger: "bg-error text-error-foreground hover:bg-error/90 border-error"
8176
8166
  };
8177
- DEFAULT_ASSET_URL11 = "https://almadar-kflow-assets.web.app/shared/effects/particles/slash_01.png";
8167
+ DEFAULT_ASSET_URL11 = {
8168
+ url: "https://almadar-kflow-assets.web.app/shared/effects/particles/slash_01.png",
8169
+ role: "effect",
8170
+ category: "effect"
8171
+ };
8178
8172
  ActionButton.displayName = "ActionButton";
8179
8173
  }
8180
8174
  });
@@ -8188,9 +8182,9 @@ function MiniMap({
8188
8182
  viewportRect = DEFAULT_VIEWPORT,
8189
8183
  className
8190
8184
  }) {
8191
- const canvasRef = React89.useRef(null);
8192
- const frameRef = React89.useRef(0);
8193
- React89.useEffect(() => {
8185
+ const canvasRef = React87.useRef(null);
8186
+ const frameRef = React87.useRef(0);
8187
+ React87.useEffect(() => {
8194
8188
  const canvas = canvasRef.current;
8195
8189
  if (!canvas) return;
8196
8190
  const ctx = canvas.getContext("2d");
@@ -8379,7 +8373,7 @@ var init_ErrorBoundary = __esm({
8379
8373
  }
8380
8374
  );
8381
8375
  };
8382
- ErrorBoundary = class extends React89__default.Component {
8376
+ ErrorBoundary = class extends React87__default.Component {
8383
8377
  constructor(props) {
8384
8378
  super(props);
8385
8379
  __publicField(this, "reset", () => {
@@ -8690,7 +8684,7 @@ var init_Container = __esm({
8690
8684
  as: Component2 = "div"
8691
8685
  }) => {
8692
8686
  const resolvedSize = maxWidth ?? size ?? "lg";
8693
- return React89__default.createElement(
8687
+ return React87__default.createElement(
8694
8688
  Component2,
8695
8689
  {
8696
8690
  className: cn(
@@ -9413,8 +9407,8 @@ function ActionButtons({
9413
9407
  disabled
9414
9408
  }) {
9415
9409
  const eventBus = useEventBus();
9416
- const [activeButtons, setActiveButtons] = React89.useState(/* @__PURE__ */ new Set());
9417
- const handlePress = React89.useCallback(
9410
+ const [activeButtons, setActiveButtons] = React87.useState(/* @__PURE__ */ new Set());
9411
+ const handlePress = React87.useCallback(
9418
9412
  (id) => {
9419
9413
  setActiveButtons((prev) => new Set(prev).add(id));
9420
9414
  if (actionEvent) eventBus.emit(`UI:${actionEvent}`, { id, pressed: true });
@@ -9422,7 +9416,7 @@ function ActionButtons({
9422
9416
  },
9423
9417
  [actionEvent, eventBus, onAction]
9424
9418
  );
9425
- const handleRelease = React89.useCallback(
9419
+ const handleRelease = React87.useCallback(
9426
9420
  (id) => {
9427
9421
  setActiveButtons((prev) => {
9428
9422
  const next = new Set(prev);
@@ -10252,50 +10246,6 @@ var init_AuthLayout = __esm({
10252
10246
  AuthLayout.displayName = "AuthLayout";
10253
10247
  }
10254
10248
  });
10255
- var LoadingState;
10256
- var init_LoadingState = __esm({
10257
- "components/core/molecules/LoadingState.tsx"() {
10258
- "use client";
10259
- init_cn();
10260
- init_atoms2();
10261
- init_Stack();
10262
- init_Typography();
10263
- LoadingState = ({
10264
- title,
10265
- message,
10266
- className
10267
- }) => {
10268
- const { t } = useTranslate();
10269
- const displayMessage = message ?? t("common.loading");
10270
- return /* @__PURE__ */ jsxs(
10271
- VStack,
10272
- {
10273
- align: "center",
10274
- className: cn(
10275
- "justify-center py-12",
10276
- className
10277
- ),
10278
- children: [
10279
- /* @__PURE__ */ jsx(Spinner, { size: "lg" }),
10280
- title && /* @__PURE__ */ jsx(Typography, { variant: "h3", className: "mt-4 text-lg font-semibold text-foreground", children: title }),
10281
- /* @__PURE__ */ jsx(
10282
- Typography,
10283
- {
10284
- variant: "small",
10285
- className: cn(
10286
- "text-muted-foreground",
10287
- title ? "mt-2" : "mt-4"
10288
- ),
10289
- children: displayMessage
10290
- }
10291
- )
10292
- ]
10293
- }
10294
- );
10295
- };
10296
- LoadingState.displayName = "LoadingState";
10297
- }
10298
- });
10299
10249
  function getState() {
10300
10250
  if (typeof window !== "undefined") {
10301
10251
  const w = window;
@@ -10805,12 +10755,7 @@ var init_useCanvasGestures = __esm({
10805
10755
  }
10806
10756
  });
10807
10757
  function unitAtlasUrl(unit) {
10808
- if (unit.spriteSheet) return unit.spriteSheet;
10809
- const sprite = unit.sprite;
10810
- if (!sprite) return null;
10811
- const match = /^(.*-sprite-sheet)(?:-(?:se|sw))?(?:-v\d+)?\.png$/.exec(sprite);
10812
- if (!match) return null;
10813
- return `${match[1]}.json`;
10758
+ return unit.spriteSheet?.url ?? null;
10814
10759
  }
10815
10760
  function resolveSheetUrl(atlasUrl, relativeSheetPath) {
10816
10761
  try {
@@ -10825,9 +10770,6 @@ function useUnitSpriteAtlas(units) {
10825
10770
  const loadingRef = useRef(/* @__PURE__ */ new Set());
10826
10771
  const [pendingCount, setPendingCount] = useState(0);
10827
10772
  const [, forceTick] = useState(0);
10828
- const animStatesRef = useRef(/* @__PURE__ */ new Map());
10829
- const lastTickRef = useRef(0);
10830
- const rafRef = useRef(0);
10831
10773
  const atlasUrls = useMemo(() => {
10832
10774
  const set = /* @__PURE__ */ new Set();
10833
10775
  for (const unit of units) {
@@ -10873,54 +10815,6 @@ function useUnitSpriteAtlas(units) {
10873
10815
  }
10874
10816
  return [...urls];
10875
10817
  }, [units, pendingCount]);
10876
- useEffect(() => {
10877
- const hasAtlasUnits = units.some((u) => unitAtlasUrl(u) !== null);
10878
- if (!hasAtlasUnits) return;
10879
- let running = true;
10880
- const tick = (ts) => {
10881
- if (!running) return;
10882
- const last = lastTickRef.current || ts;
10883
- const delta = ts - last;
10884
- lastTickRef.current = ts;
10885
- const states = animStatesRef.current;
10886
- const currentIds = /* @__PURE__ */ new Set();
10887
- for (const unit of units) {
10888
- if (unitAtlasUrl(unit) === null) continue;
10889
- currentIds.add(unit.id);
10890
- let state = states.get(unit.id);
10891
- if (!state) {
10892
- state = { animation: "idle", direction: "se", elapsed: 0, walkHold: 0, prev: null };
10893
- states.set(unit.id, state);
10894
- }
10895
- const posX = unit.position?.x ?? unit.x ?? 0;
10896
- const posY = unit.position?.y ?? unit.y ?? 0;
10897
- if (state.prev) {
10898
- const dx = posX - state.prev.x;
10899
- const dy = posY - state.prev.y;
10900
- if (dx !== 0 || dy !== 0) {
10901
- state.animation = "walk";
10902
- state.direction = inferDirection(dx, dy);
10903
- state.walkHold = WALK_HOLD_MS;
10904
- } else if (state.animation === "walk") {
10905
- state.walkHold -= delta;
10906
- if (state.walkHold <= 0) state.animation = "idle";
10907
- }
10908
- }
10909
- state.prev = { x: posX, y: posY };
10910
- state.elapsed += delta;
10911
- }
10912
- for (const id of states.keys()) {
10913
- if (!currentIds.has(id)) states.delete(id);
10914
- }
10915
- rafRef.current = requestAnimationFrame(tick);
10916
- };
10917
- rafRef.current = requestAnimationFrame(tick);
10918
- return () => {
10919
- running = false;
10920
- cancelAnimationFrame(rafRef.current);
10921
- lastTickRef.current = 0;
10922
- };
10923
- }, [units]);
10924
10818
  const resolveUnitFrame = useCallback((unitId) => {
10925
10819
  const unit = units.find((u) => u.id === unitId);
10926
10820
  if (!unit) return null;
@@ -10928,18 +10822,14 @@ function useUnitSpriteAtlas(units) {
10928
10822
  if (!atlasUrl) return null;
10929
10823
  const atlas = atlasCacheRef.current.get(atlasUrl);
10930
10824
  if (!atlas) return null;
10931
- const state = animStatesRef.current.get(unitId);
10932
- const animation = state?.animation ?? "idle";
10933
- const direction = state?.direction ?? "se";
10934
- const elapsed = state?.elapsed ?? 0;
10825
+ const animation = unit.animation ?? "idle";
10826
+ const frame = unit.frame ?? 0;
10935
10827
  const def = atlas.animations[animation] ?? atlas.animations.idle;
10936
10828
  if (!def) return null;
10937
- const { sheetDir, flipX } = resolveSheetDirection(direction);
10829
+ const { sheetDir, flipX } = resolveSheetDirection("se");
10938
10830
  const rel = atlas.sheets[sheetDir] ?? atlas.sheets.se ?? atlas.sheets.sw;
10939
10831
  if (!rel) return null;
10940
10832
  const sheetUrl = resolveSheetUrl(atlasUrl, rel);
10941
- const isIdle = animation === "idle";
10942
- const frame = isIdle ? 0 : getCurrentFrameFromDef(def, elapsed).frame;
10943
10833
  const rect = frameRect(frame, def.row, atlas.columns, atlas.frameWidth, atlas.frameHeight);
10944
10834
  return {
10945
10835
  sheetUrl,
@@ -10948,17 +10838,15 @@ function useUnitSpriteAtlas(units) {
10948
10838
  sw: rect.sw,
10949
10839
  sh: rect.sh,
10950
10840
  flipX,
10951
- applyBreathing: isIdle
10841
+ applyBreathing: animation === "idle"
10952
10842
  };
10953
10843
  }, [units]);
10954
10844
  return { sheetUrls, resolveUnitFrame, pendingCount };
10955
10845
  }
10956
- var WALK_HOLD_MS;
10957
10846
  var init_useUnitSpriteAtlas = __esm({
10958
10847
  "components/game/molecules/useUnitSpriteAtlas.ts"() {
10959
10848
  "use client";
10960
10849
  init_spriteAnimation();
10961
- WALK_HOLD_MS = 600;
10962
10850
  }
10963
10851
  });
10964
10852
 
@@ -11026,6 +10914,7 @@ function IsometricCanvas({
11026
10914
  tiles: _tilesPropRaw = [],
11027
10915
  units: _unitsPropRaw = [],
11028
10916
  features: _featuresPropRaw = [],
10917
+ effects: _effectsPropRaw = [],
11029
10918
  // Interaction state
11030
10919
  selectedUnitId = null,
11031
10920
  validMoves = [],
@@ -11058,23 +10947,21 @@ function IsometricCanvas({
11058
10947
  resolveUnitFrame,
11059
10948
  effectSpriteUrls = [],
11060
10949
  onDrawEffects,
11061
- hasActiveEffects: hasActiveEffects2 = false,
10950
+ hasActiveEffects: _hasActiveEffects = false,
11062
10951
  // Tuning
11063
10952
  diamondTopY: diamondTopYProp,
11064
10953
  // Remote asset loading
11065
- assetBaseUrl,
11066
10954
  assetManifest
11067
10955
  }) {
11068
10956
  const tilesProp = Array.isArray(_tilesPropRaw) ? _tilesPropRaw : [];
11069
10957
  const unitsProp = Array.isArray(_unitsPropRaw) ? _unitsPropRaw : [];
11070
10958
  const featuresProp = Array.isArray(_featuresPropRaw) ? _featuresPropRaw : [];
10959
+ const effects = Array.isArray(_effectsPropRaw) ? _effectsPropRaw : [];
11071
10960
  const eventBus = useEventBus();
11072
10961
  const { t } = useTranslate();
11073
10962
  const canvasRef = useRef(null);
11074
10963
  const containerRef = useRef(null);
11075
- const minimapRef = useRef(null);
11076
- const animTimeRef = useRef(0);
11077
- const rafIdRef = useRef(0);
10964
+ const lerpRafRef = useRef(0);
11078
10965
  const [viewportSize, setViewportSize] = useState({ width: 800, height: 600 });
11079
10966
  useEffect(() => {
11080
10967
  const el = containerRef.current;
@@ -11098,7 +10985,7 @@ function IsometricCanvas({
11098
10985
  () => unitsProp.map((u) => u.position ? u : { ...u, position: { x: u.x ?? 0, y: u.y ?? 0 } }),
11099
10986
  [unitsProp]
11100
10987
  );
11101
- const { sheetUrls: atlasSheetUrls, resolveUnitFrame: resolveUnitFrameInternal, pendingCount: atlasPending } = useUnitSpriteAtlas(units);
10988
+ const { sheetUrls: atlasSheetUrls, resolveUnitFrame: resolveUnitFrameInternal } = useUnitSpriteAtlas(units);
11102
10989
  const resolveFrameForUnit = useCallback((unitId) => {
11103
10990
  return resolveUnitFrame?.(unitId) ?? resolveUnitFrameInternal(unitId);
11104
10991
  }, [resolveUnitFrame, resolveUnitFrameInternal]);
@@ -11145,55 +11032,49 @@ function IsometricCanvas({
11145
11032
  const attackTargetSet = useMemo(() => {
11146
11033
  return new Set(attackTargets.map((p2) => `${p2.x},${p2.y}`));
11147
11034
  }, [attackTargets]);
11148
- const resolveManifestUrl7 = useCallback((relativePath) => {
11149
- if (!relativePath) return void 0;
11150
- if (assetBaseUrl) return `${assetBaseUrl.replace(/\/$/, "")}${relativePath.startsWith("/") ? "" : "/"}${relativePath}`;
11151
- return relativePath;
11152
- }, [assetBaseUrl]);
11153
11035
  const spriteUrls = useMemo(() => {
11154
11036
  const urls = [];
11155
11037
  for (const tile of sortedTiles) {
11156
- if (tile.terrainSprite) urls.push(tile.terrainSprite);
11038
+ if (tile.terrainSprite) urls.push(tile.terrainSprite.url);
11157
11039
  else if (getTerrainSprite) {
11158
11040
  const url = getTerrainSprite(tile.terrain ?? "");
11159
11041
  if (url) urls.push(url);
11160
11042
  } else {
11161
- const url = resolveManifestUrl7(assetManifest?.terrains?.[tile.terrain ?? ""]);
11043
+ const url = assetManifest?.terrains?.[tile.terrain ?? ""]?.url;
11162
11044
  if (url) urls.push(url);
11163
11045
  }
11164
11046
  }
11165
11047
  for (const feature of features) {
11166
- if (feature.sprite) urls.push(feature.sprite);
11048
+ if (feature.sprite) urls.push(feature.sprite.url);
11167
11049
  else if (getFeatureSprite) {
11168
11050
  const url = getFeatureSprite(feature.type);
11169
11051
  if (url) urls.push(url);
11170
11052
  } else {
11171
- const url = resolveManifestUrl7(assetManifest?.features?.[feature.type]);
11053
+ const url = assetManifest?.features?.[feature.type]?.url;
11172
11054
  if (url) urls.push(url);
11173
11055
  }
11174
11056
  }
11175
11057
  for (const unit of units) {
11176
- if (unit.sprite) urls.push(unit.sprite);
11058
+ if (unit.sprite) urls.push(unit.sprite.url);
11177
11059
  else if (getUnitSprite) {
11178
11060
  const url = getUnitSprite(unit);
11179
11061
  if (url) urls.push(url);
11180
11062
  } else if (unit.unitType) {
11181
- const url = resolveManifestUrl7(assetManifest?.units?.[unit.unitType]);
11063
+ const url = assetManifest?.units?.[unit.unitType]?.url;
11182
11064
  if (url) urls.push(url);
11183
11065
  }
11184
11066
  }
11185
11067
  if (assetManifest?.effects) {
11186
- for (const path of Object.values(assetManifest.effects)) {
11187
- const url = resolveManifestUrl7(path);
11188
- if (url) urls.push(url);
11068
+ for (const asset of Object.values(assetManifest.effects)) {
11069
+ if (asset.url) urls.push(asset.url);
11189
11070
  }
11190
11071
  }
11191
11072
  if (effectSpriteUrls) urls.push(...effectSpriteUrls);
11192
11073
  if (atlasSheetUrls.length) urls.push(...atlasSheetUrls);
11193
11074
  if (backgroundImage) urls.push(backgroundImage);
11194
11075
  return [...new Set(urls.filter(Boolean))];
11195
- }, [sortedTiles, features, units, getTerrainSprite, getFeatureSprite, getUnitSprite, effectSpriteUrls, atlasSheetUrls, backgroundImage, assetManifest, resolveManifestUrl7]);
11196
- const { getImage, pendingCount } = useImageCache(spriteUrls);
11076
+ }, [sortedTiles, features, units, getTerrainSprite, getFeatureSprite, getUnitSprite, effectSpriteUrls, atlasSheetUrls, backgroundImage, assetManifest]);
11077
+ const { getImage, pendingCount: _imagePendingCount } = useImageCache(spriteUrls);
11197
11078
  useEffect(() => {
11198
11079
  if (typeof window === "undefined") return;
11199
11080
  const canvas = canvasRef.current;
@@ -11217,71 +11098,34 @@ function IsometricCanvas({
11217
11098
  lerpToTarget
11218
11099
  } = useCamera();
11219
11100
  const resolveTerrainSpriteUrl = useCallback((tile) => {
11220
- return tile.terrainSprite || getTerrainSprite?.(tile.terrain ?? "") || resolveManifestUrl7(assetManifest?.terrains?.[tile.terrain ?? ""]);
11221
- }, [getTerrainSprite, assetManifest, resolveManifestUrl7]);
11101
+ return tile.terrainSprite?.url || getTerrainSprite?.(tile.terrain ?? "") || assetManifest?.terrains?.[tile.terrain ?? ""]?.url;
11102
+ }, [getTerrainSprite, assetManifest]);
11222
11103
  const resolveFeatureSpriteUrl = useCallback((featureType) => {
11223
- return getFeatureSprite?.(featureType) || resolveManifestUrl7(assetManifest?.features?.[featureType]);
11224
- }, [getFeatureSprite, assetManifest, resolveManifestUrl7]);
11104
+ return getFeatureSprite?.(featureType) || assetManifest?.features?.[featureType]?.url;
11105
+ }, [getFeatureSprite, assetManifest]);
11225
11106
  const resolveUnitSpriteUrl = useCallback((unit) => {
11226
- return unit.sprite || getUnitSprite?.(unit) || (unit.unitType ? resolveManifestUrl7(assetManifest?.units?.[unit.unitType]) : void 0);
11227
- }, [getUnitSprite, assetManifest, resolveManifestUrl7]);
11228
- const drawMinimap = useCallback(() => {
11229
- if (!showMinimap) return;
11230
- const miniCanvas = minimapRef.current;
11231
- if (!miniCanvas || sortedTiles.length === 0) return;
11232
- const mCtx = miniCanvas.getContext("2d");
11233
- if (!mCtx) return;
11234
- const mW = 150;
11235
- const mH = 100;
11236
- miniCanvas.width = mW;
11237
- miniCanvas.height = mH;
11238
- mCtx.clearRect(0, 0, mW, mH);
11239
- const allScreenPos = sortedTiles.map((t2) => isoToScreen(t2.x, t2.y, scale, baseOffsetX, tileLayout));
11240
- const minX = Math.min(...allScreenPos.map((p2) => p2.x));
11241
- const maxX = Math.max(...allScreenPos.map((p2) => p2.x + scaledTileWidth));
11242
- const minY = Math.min(...allScreenPos.map((p2) => p2.y));
11243
- const tileBottomExtent = tileLayout === "hex" || tileLayout === "flat" ? scaledTileWidth : scaledTileHeight;
11244
- const maxY = Math.max(...allScreenPos.map((p2) => p2.y + tileBottomExtent));
11245
- const worldW = maxX - minX;
11246
- const worldH = maxY - minY;
11247
- const scaleM = Math.min(mW / worldW, mH / worldH) * 0.9;
11248
- const offsetMx = (mW - worldW * scaleM) / 2;
11249
- const offsetMy = (mH - worldH * scaleM) / 2;
11250
- for (const tile of sortedTiles) {
11251
- const pos = isoToScreen(tile.x, tile.y, scale, baseOffsetX, tileLayout);
11252
- const mx = (pos.x - minX) * scaleM + offsetMx;
11253
- const my = (pos.y - minY) * scaleM + offsetMy;
11254
- const mTileW = scaledTileWidth * scaleM;
11255
- const mFloorH = scaledFloorHeight * scaleM;
11256
- mCtx.fillStyle = tile.terrain === "water" ? "#3b82f6" : tile.terrain === "mountain" ? "#78716c" : "#4ade80";
11257
- mCtx.beginPath();
11258
- mCtx.moveTo(mx + mTileW / 2, my);
11259
- mCtx.lineTo(mx + mTileW, my + mFloorH / 2);
11260
- mCtx.lineTo(mx + mTileW / 2, my + mFloorH);
11261
- mCtx.lineTo(mx, my + mFloorH / 2);
11262
- mCtx.closePath();
11263
- mCtx.fill();
11264
- }
11265
- for (const unit of units) {
11266
- if (!unit.position) continue;
11267
- const pos = isoToScreen(unit.position.x, unit.position.y, scale, baseOffsetX, tileLayout);
11268
- const mx = (pos.x + scaledTileWidth / 2 - minX) * scaleM + offsetMx;
11269
- const my = (pos.y + scaledTileHeight / 2 - minY) * scaleM + offsetMy;
11270
- mCtx.fillStyle = unit.team === "player" ? "#60a5fa" : unit.team === "enemy" ? "#f87171" : "#9ca3af";
11271
- mCtx.beginPath();
11272
- mCtx.arc(mx, my, 3, 0, Math.PI * 2);
11273
- mCtx.fill();
11274
- }
11275
- const cam = cameraRef.current;
11276
- const vLeft = (cam.x - minX) * scaleM + offsetMx;
11277
- const vTop = (cam.y - minY) * scaleM + offsetMy;
11278
- const vW = viewportSize.width / cam.zoom * scaleM;
11279
- const vH = viewportSize.height / cam.zoom * scaleM;
11280
- mCtx.strokeStyle = "rgba(255, 255, 255, 0.8)";
11281
- mCtx.lineWidth = 1;
11282
- mCtx.strokeRect(vLeft, vTop, vW, vH);
11283
- }, [showMinimap, sortedTiles, units, tileLayout, scale, baseOffsetX, scaledTileWidth, scaledTileHeight, scaledFloorHeight, viewportSize, cameraRef]);
11284
- const draw = useCallback((animTime) => {
11107
+ return unit.sprite?.url || getUnitSprite?.(unit) || (unit.unitType ? assetManifest?.units?.[unit.unitType]?.url : void 0);
11108
+ }, [getUnitSprite, assetManifest]);
11109
+ const miniMapTiles = useMemo(() => {
11110
+ if (!showMinimap) return [];
11111
+ return sortedTiles.map((t2) => ({
11112
+ x: t2.x,
11113
+ y: t2.y,
11114
+ color: t2.terrain === "water" ? "#3b82f6" : t2.terrain === "mountain" ? "#78716c" : "#4ade80"
11115
+ }));
11116
+ }, [showMinimap, sortedTiles]);
11117
+ const miniMapUnits = useMemo(() => {
11118
+ if (!showMinimap) return [];
11119
+ return units.filter((u) => u.position).map((u) => ({
11120
+ x: u.position.x,
11121
+ y: u.position.y,
11122
+ color: u.team === "player" ? "#60a5fa" : u.team === "enemy" ? "#f87171" : "#9ca3af",
11123
+ isPlayer: u.team === "player"
11124
+ }));
11125
+ }, [showMinimap, units]);
11126
+ const miniMapWidth = gridWidth || 10;
11127
+ const miniMapHeight = gridHeight || 10;
11128
+ const draw = useCallback(() => {
11285
11129
  const canvas = canvasRef.current;
11286
11130
  if (!canvas) return;
11287
11131
  const ctx = canvas.getContext("2d");
@@ -11367,8 +11211,7 @@ function IsometricCanvas({
11367
11211
  if (validMoveSet.has(tileKey)) {
11368
11212
  const centerX = pos.x + scaledTileWidth / 2;
11369
11213
  const topY = pos.y + scaledDiamondTopY;
11370
- const pulse = 0.15 + 0.1 * Math.sin(animTime * 4e-3);
11371
- ctx.fillStyle = `rgba(74, 222, 128, ${pulse})`;
11214
+ ctx.fillStyle = "rgba(74, 222, 128, 0.25)";
11372
11215
  ctx.beginPath();
11373
11216
  ctx.moveTo(centerX, topY);
11374
11217
  ctx.lineTo(pos.x + scaledTileWidth, topY + scaledFloorHeight / 2);
@@ -11380,8 +11223,7 @@ function IsometricCanvas({
11380
11223
  if (attackTargetSet.has(tileKey)) {
11381
11224
  const centerX = pos.x + scaledTileWidth / 2;
11382
11225
  const topY = pos.y + scaledDiamondTopY;
11383
- const pulse = 0.2 + 0.15 * Math.sin(animTime * 5e-3);
11384
- ctx.fillStyle = `rgba(239, 68, 68, ${pulse})`;
11226
+ ctx.fillStyle = "rgba(239, 68, 68, 0.35)";
11385
11227
  ctx.beginPath();
11386
11228
  ctx.moveTo(centerX, topY);
11387
11229
  ctx.lineTo(pos.x + scaledTileWidth, topY + scaledFloorHeight / 2);
@@ -11410,7 +11252,7 @@ function IsometricCanvas({
11410
11252
  if (pos.x + scaledTileWidth < visLeft || pos.x > visRight || pos.y + scaledTileHeight < visTop || pos.y > visBottom) {
11411
11253
  continue;
11412
11254
  }
11413
- const spriteUrl = feature.sprite || resolveFeatureSpriteUrl(feature.type);
11255
+ const spriteUrl = feature.sprite?.url || resolveFeatureSpriteUrl(feature.type);
11414
11256
  const img = spriteUrl ? getImage(spriteUrl) : null;
11415
11257
  const centerX = pos.x + scaledTileWidth / 2;
11416
11258
  const featureGroundY = pos.y + scaledDiamondTopY + scaledFloorHeight * 0.5;
@@ -11454,17 +11296,17 @@ function IsometricCanvas({
11454
11296
  const isSelected = unit.id === selectedUnitId;
11455
11297
  const centerX = pos.x + scaledTileWidth / 2;
11456
11298
  const groundY = pos.y + scaledDiamondTopY + scaledFloorHeight * 0.5;
11457
- const breatheOffset = 0.8 * scale * (1 + Math.sin(animTime * 2e-3 + (unit.position.x * 3.7 + unit.position.y * 5.3)));
11299
+ const breatheOffset = 0;
11458
11300
  const unitSpriteUrl = resolveUnitSpriteUrl(unit);
11459
11301
  const img = unitSpriteUrl ? getImage(unitSpriteUrl) : null;
11460
11302
  const unitDrawH = scaledFloorHeight * spriteHeightRatio * unitScale;
11461
11303
  const maxUnitW = scaledTileWidth * spriteMaxWidthRatio * unitScale;
11304
+ const unitIsSheet = unit.sprite?.dimension === "2d" && (unit.sprite?.animations?.length ?? 0) > 0;
11462
11305
  const SHEET_ROWS = 5;
11463
11306
  const sheetFrameW = img ? img.naturalWidth / SHEET_COLUMNS : 0;
11464
11307
  const sheetFrameH = img ? img.naturalHeight / SHEET_ROWS : 0;
11465
- const imgIsSheet = img ? img.naturalWidth % SHEET_COLUMNS === 0 && img.naturalHeight % SHEET_ROWS === 0 && Math.abs(sheetFrameW - sheetFrameH) < 2 : false;
11466
- const frameW = imgIsSheet ? sheetFrameW : img?.naturalWidth ?? 1;
11467
- const frameH = imgIsSheet ? sheetFrameH : img?.naturalHeight ?? 1;
11308
+ const frameW = unitIsSheet ? sheetFrameW : img?.naturalWidth ?? 1;
11309
+ const frameH = unitIsSheet ? sheetFrameH : img?.naturalHeight ?? 1;
11468
11310
  const ar = frameW / (frameH || 1);
11469
11311
  let drawH = unitDrawH;
11470
11312
  let drawW = unitDrawH * ar;
@@ -11479,7 +11321,7 @@ function IsometricCanvas({
11479
11321
  ctx.save();
11480
11322
  ctx.globalAlpha = 0.25;
11481
11323
  if (img) {
11482
- if (imgIsSheet) {
11324
+ if (unitIsSheet) {
11483
11325
  ctx.drawImage(img, 0, 0, sheetFrameW, sheetFrameH, ghostCenterX - drawW / 2, ghostGroundY - drawH, drawW, drawH);
11484
11326
  } else {
11485
11327
  ctx.drawImage(img, ghostCenterX - drawW / 2, ghostGroundY - drawH, drawW, drawH);
@@ -11494,10 +11336,9 @@ function IsometricCanvas({
11494
11336
  ctx.restore();
11495
11337
  }
11496
11338
  if (isSelected) {
11497
- const ringAlpha = 0.6 + 0.3 * Math.sin(animTime * 4e-3);
11498
11339
  ctx.beginPath();
11499
11340
  ctx.ellipse(centerX, groundY, drawW / 2 + 4 * scale, 12 * scale, 0, 0, Math.PI * 2);
11500
- ctx.strokeStyle = `rgba(0, 200, 255, ${ringAlpha})`;
11341
+ ctx.strokeStyle = "rgba(0, 200, 255, 0.8)";
11501
11342
  ctx.lineWidth = 3;
11502
11343
  ctx.stroke();
11503
11344
  }
@@ -11528,7 +11369,7 @@ function IsometricCanvas({
11528
11369
  } else if (img) {
11529
11370
  const spriteY = groundY - drawH - breatheOffset;
11530
11371
  const drawUnit = (x) => {
11531
- if (imgIsSheet) {
11372
+ if (unitIsSheet) {
11532
11373
  ctx.drawImage(img, 0, 0, sheetFrameW, sheetFrameH, x, spriteY, drawW, drawH);
11533
11374
  } else {
11534
11375
  ctx.drawImage(img, x, spriteY, drawW, drawH);
@@ -11553,66 +11394,29 @@ function IsometricCanvas({
11553
11394
  ctx.lineWidth = 2;
11554
11395
  ctx.stroke();
11555
11396
  }
11556
- if (unit.name) {
11557
- 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)";
11558
- ctx.font = `bold ${10 * scale * 2.5}px system-ui`;
11559
- ctx.textAlign = "center";
11560
- const textWidth = ctx.measureText(unit.name).width;
11561
- const labelY = groundY + 14 * scale - breatheOffset;
11562
- ctx.fillStyle = labelBg;
11563
- ctx.beginPath();
11564
- ctx.roundRect(centerX - textWidth / 2 - 6 * scale, labelY - 8 * scale, textWidth + 12 * scale, 16 * scale, 4 * scale);
11565
- ctx.fill();
11566
- ctx.fillStyle = "white";
11567
- ctx.fillText(unit.name, centerX, labelY + 4 * scale);
11568
- }
11569
- if (unit.health !== void 0 && unit.maxHealth !== void 0) {
11570
- const barWidth = 40 * scale;
11571
- const barHeight = 6 * scale;
11572
- const barX = centerX - barWidth / 2;
11573
- const barY = groundY - drawH - 2 * scale - breatheOffset;
11574
- const healthRatio = unit.health / unit.maxHealth;
11575
- const barRadius = barHeight / 2;
11576
- ctx.fillStyle = "rgba(0, 0, 0, 0.7)";
11577
- ctx.beginPath();
11578
- ctx.roundRect(barX, barY, barWidth, barHeight, barRadius);
11579
- ctx.fill();
11580
- if (healthRatio > 0) {
11581
- const fillWidth = barWidth * healthRatio;
11582
- const gradient = ctx.createLinearGradient(barX, barY, barX, barY + barHeight);
11583
- if (healthRatio > 0.6) {
11584
- gradient.addColorStop(0, "#4ade80");
11585
- gradient.addColorStop(1, "#22c55e");
11586
- } else if (healthRatio > 0.3) {
11587
- gradient.addColorStop(0, "#fde047");
11588
- gradient.addColorStop(1, "#eab308");
11589
- } else {
11590
- gradient.addColorStop(0, "#f87171");
11591
- gradient.addColorStop(1, "#ef4444");
11592
- }
11593
- ctx.fillStyle = gradient;
11594
- ctx.save();
11595
- ctx.beginPath();
11596
- ctx.roundRect(barX, barY, fillWidth, barHeight, barRadius);
11597
- ctx.clip();
11598
- ctx.fillRect(barX, barY, fillWidth, barHeight);
11599
- ctx.restore();
11600
- }
11601
- ctx.strokeStyle = "rgba(255, 255, 255, 0.3)";
11602
- ctx.lineWidth = 1;
11603
- ctx.beginPath();
11604
- ctx.roundRect(barX, barY, barWidth, barHeight, barRadius);
11605
- ctx.stroke();
11606
- }
11607
11397
  }
11608
- onDrawEffects?.(ctx, animTime, getImage);
11398
+ for (const fx of effects) {
11399
+ const spriteUrl = assetManifest?.effects?.[fx.key]?.url;
11400
+ if (!spriteUrl) continue;
11401
+ const img = getImage(spriteUrl);
11402
+ if (!img) continue;
11403
+ const pos = isoToScreen(fx.x, fx.y, scale, baseOffsetX, tileLayout);
11404
+ const cx = pos.x + scaledTileWidth / 2;
11405
+ const cy = pos.y + scaledDiamondTopY + scaledFloorHeight * 0.5;
11406
+ const alpha = Math.min(1, fx.ttl / 4);
11407
+ const prev = ctx.globalAlpha;
11408
+ ctx.globalAlpha = alpha;
11409
+ ctx.drawImage(img, cx - img.naturalWidth / 2, cy - img.naturalHeight / 2);
11410
+ ctx.globalAlpha = prev;
11411
+ }
11412
+ onDrawEffects?.(ctx, 0, getImage);
11609
11413
  ctx.restore();
11610
- drawMinimap();
11611
11414
  }, [
11612
11415
  sortedTiles,
11613
11416
  units,
11614
11417
  features,
11615
11418
  selectedUnitId,
11419
+ effects,
11616
11420
  tileLayout,
11617
11421
  scale,
11618
11422
  debug2,
@@ -11632,11 +11436,11 @@ function IsometricCanvas({
11632
11436
  attackTargetSet,
11633
11437
  hoveredTile,
11634
11438
  viewportSize,
11635
- drawMinimap,
11636
11439
  onDrawEffects,
11637
11440
  backgroundImage,
11638
11441
  cameraRef,
11639
- unitScale
11442
+ unitScale,
11443
+ assetManifest
11640
11444
  ]);
11641
11445
  useEffect(() => {
11642
11446
  if (!selectedUnitId) return;
@@ -11651,30 +11455,33 @@ function IsometricCanvas({
11651
11455
  };
11652
11456
  }, [selectedUnitId, units, tileLayout, scale, baseOffsetX, scaledTileWidth, scaledDiamondTopY, scaledFloorHeight, viewportSize, targetCameraRef]);
11653
11457
  useEffect(() => {
11654
- const hasAnimations = units.length > 0 || validMoves.length > 0 || attackTargets.length > 0 || selectedUnitId != null || targetCameraRef.current != null || hasActiveEffects2 || pendingCount > 0 || atlasPending > 0;
11655
- draw(animTimeRef.current);
11656
- if (!hasAnimations) return;
11458
+ draw();
11459
+ }, [draw]);
11460
+ useEffect(() => {
11461
+ draw();
11462
+ }, [_imagePendingCount]);
11463
+ useEffect(() => {
11464
+ if (selectedUnitId == null) return;
11657
11465
  let running = true;
11658
- const animate = (timestamp) => {
11466
+ const tick = () => {
11659
11467
  if (!running) return;
11660
- animTimeRef.current = timestamp;
11661
- lerpToTarget();
11662
- draw(timestamp);
11663
- rafIdRef.current = requestAnimationFrame(animate);
11468
+ const stillLerping = lerpToTarget();
11469
+ draw();
11470
+ if (stillLerping) lerpRafRef.current = requestAnimationFrame(tick);
11664
11471
  };
11665
- rafIdRef.current = requestAnimationFrame(animate);
11472
+ lerpRafRef.current = requestAnimationFrame(tick);
11666
11473
  return () => {
11667
11474
  running = false;
11668
- cancelAnimationFrame(rafIdRef.current);
11475
+ cancelAnimationFrame(lerpRafRef.current);
11669
11476
  };
11670
- }, [draw, units.length, validMoves.length, attackTargets.length, selectedUnitId, hasActiveEffects2, pendingCount, atlasPending, lerpToTarget, targetCameraRef]);
11477
+ }, [selectedUnitId, lerpToTarget, draw]);
11671
11478
  const singlePointerActiveRef = useRef(false);
11672
11479
  const handleCanvasPointerDown = useCallback((e) => {
11673
11480
  singlePointerActiveRef.current = true;
11674
11481
  if (enableCamera) handlePointerDown(e);
11675
11482
  }, [enableCamera, handlePointerDown]);
11676
11483
  const handleCanvasPointerMove = useCallback((e) => {
11677
- if (enableCamera) handlePointerMove(e, () => draw(animTimeRef.current));
11484
+ if (enableCamera) handlePointerMove(e, () => draw());
11678
11485
  }, [enableCamera, handlePointerMove, draw]);
11679
11486
  const handleCanvasHover = useCallback((e) => {
11680
11487
  if (singlePointerActiveRef.current) return;
@@ -11716,10 +11523,10 @@ function IsometricCanvas({
11716
11523
  onTileLeave?.();
11717
11524
  }, [handleMouseLeave, onTileLeave, tileLeaveEvent, eventBus]);
11718
11525
  const applyZoom = useCallback((factor, centerX, centerY) => {
11719
- if (enableCamera) zoomAtPoint(factor, centerX, centerY, viewportSize, () => draw(animTimeRef.current));
11526
+ if (enableCamera) zoomAtPoint(factor, centerX, centerY, viewportSize, () => draw());
11720
11527
  }, [enableCamera, zoomAtPoint, viewportSize, draw]);
11721
11528
  const applyPanDelta = useCallback((dx, dy) => {
11722
- if (enableCamera) panBy(dx, dy, () => draw(animTimeRef.current));
11529
+ if (enableCamera) panBy(dx, dy, () => draw());
11723
11530
  }, [enableCamera, panBy, draw]);
11724
11531
  const cancelSinglePointer = useCallback(() => {
11725
11532
  singlePointerActiveRef.current = false;
@@ -11735,11 +11542,27 @@ function IsometricCanvas({
11735
11542
  onPanDelta: applyPanDelta,
11736
11543
  onMultiTouchStart: cancelSinglePointer
11737
11544
  });
11545
+ const unitOverlays = useMemo(() => {
11546
+ if (sortedTiles.length === 0) return [];
11547
+ return units.filter((u) => !!u.position).map((u) => {
11548
+ const pos = isoToScreen(u.position.x, u.position.y, scale, baseOffsetX, tileLayout);
11549
+ const cam = cameraRef.current;
11550
+ const screenX = (pos.x + scaledTileWidth / 2 - (cam.x + viewportSize.width / 2)) * cam.zoom + viewportSize.width / 2;
11551
+ const screenY = (pos.y + scaledDiamondTopY + scaledFloorHeight * 0.5 - (cam.y + viewportSize.height / 2)) * cam.zoom + viewportSize.height / 2;
11552
+ return { unit: u, screenX, screenY };
11553
+ });
11554
+ }, [units, sortedTiles.length, scale, baseOffsetX, tileLayout, scaledTileWidth, scaledDiamondTopY, scaledFloorHeight, viewportSize, cameraRef]);
11738
11555
  if (error) {
11739
- return /* @__PURE__ */ jsx(ErrorState, { title: t("canvas.errorTitle"), message: error.message, className });
11556
+ 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: [
11557
+ /* @__PURE__ */ jsx(Icon, { name: "alert-circle", size: "xl" }),
11558
+ /* @__PURE__ */ jsx(Typography, { variant: "body", className: "text-error", children: error.message })
11559
+ ] }) });
11740
11560
  }
11741
11561
  if (isLoading) {
11742
- return /* @__PURE__ */ jsx(LoadingState, { className });
11562
+ 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: [
11563
+ /* @__PURE__ */ jsx(Icon, { name: "loader", size: "xl", className: "animate-spin" }),
11564
+ /* @__PURE__ */ jsx(Typography, { variant: "body", className: "text-muted-foreground", children: t("canvas.loadingMessage") || "Loading\u2026" })
11565
+ ] }) });
11743
11566
  }
11744
11567
  if (sortedTiles.length === 0) {
11745
11568
  return /* @__PURE__ */ jsx(
@@ -11804,14 +11627,36 @@ function IsometricCanvas({
11804
11627
  }
11805
11628
  )
11806
11629
  ] }),
11807
- showMinimap && /* @__PURE__ */ jsx(
11808
- "canvas",
11630
+ unitOverlays.map(({ unit, screenX, screenY }) => /* @__PURE__ */ jsxs(
11631
+ "div",
11809
11632
  {
11810
- ref: minimapRef,
11811
- className: "absolute bottom-2 right-2 border border-border rounded bg-background/80 pointer-events-none",
11812
- style: { width: 150, height: 100, zIndex: 10 }
11633
+ className: "absolute pointer-events-none",
11634
+ style: { left: Math.round(screenX), top: Math.round(screenY), transform: "translate(-50%, 0)", zIndex: 5 },
11635
+ children: [
11636
+ unit.name && /* @__PURE__ */ jsx(
11637
+ "div",
11638
+ {
11639
+ className: "text-white text-xs font-bold px-1.5 py-0.5 rounded mb-0.5 whitespace-nowrap",
11640
+ 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)" },
11641
+ children: unit.name
11642
+ }
11643
+ ),
11644
+ unit.health !== void 0 && unit.maxHealth !== void 0 && unit.maxHealth > 0 && /* @__PURE__ */ jsx(HealthBar, { current: unit.health, max: unit.maxHealth, format: "bar", size: "sm" })
11645
+ ]
11646
+ },
11647
+ unit.id
11648
+ )),
11649
+ showMinimap && /* @__PURE__ */ jsx("div", { className: "absolute bottom-2 right-2 pointer-events-none", style: { zIndex: 10 }, children: /* @__PURE__ */ jsx(
11650
+ MiniMap,
11651
+ {
11652
+ tiles: miniMapTiles,
11653
+ units: miniMapUnits,
11654
+ width: 150,
11655
+ height: 100,
11656
+ mapWidth: miniMapWidth,
11657
+ mapHeight: miniMapHeight
11813
11658
  }
11814
- )
11659
+ ) })
11815
11660
  ]
11816
11661
  }
11817
11662
  );
@@ -11826,8 +11671,8 @@ var init_IsometricCanvas = __esm({
11826
11671
  init_Stack();
11827
11672
  init_Icon();
11828
11673
  init_Typography();
11829
- init_LoadingState();
11830
- init_ErrorState();
11674
+ init_MiniMap();
11675
+ init_HealthBar();
11831
11676
  init_useImageCache();
11832
11677
  init_useCamera();
11833
11678
  init_useCanvasGestures();
@@ -11872,6 +11717,42 @@ var init_boardEntity = __esm({
11872
11717
  "components/game/organisms/boardEntity.ts"() {
11873
11718
  }
11874
11719
  });
11720
+
11721
+ // components/game/organisms/utils/makeAsset.ts
11722
+ function makeAsset(url, role, overrides = {}) {
11723
+ const defaults = ROLE_DEFAULTS[role] ?? { dimension: "2d", animations: ["static"], aspect: "1:1" };
11724
+ return {
11725
+ url,
11726
+ role,
11727
+ category: url.split("/").pop()?.replace(/\.[^.]+$/, "") ?? role,
11728
+ ...defaults,
11729
+ ...overrides
11730
+ };
11731
+ }
11732
+ function makeAssetMap(record, role, overrides = {}) {
11733
+ const result = {};
11734
+ for (const [key, url] of Object.entries(record)) {
11735
+ result[key] = makeAsset(url, role, overrides);
11736
+ }
11737
+ return result;
11738
+ }
11739
+ var ROLE_DEFAULTS;
11740
+ var init_makeAsset = __esm({
11741
+ "components/game/organisms/utils/makeAsset.ts"() {
11742
+ ROLE_DEFAULTS = {
11743
+ tile: { dimension: "2d", animations: ["static"], aspect: "1:1" },
11744
+ decoration: { dimension: "2d", animations: ["static"], aspect: "1:1" },
11745
+ effect: { dimension: "2d", animations: ["static"], aspect: "1:1" },
11746
+ item: { dimension: "2d", animations: ["static"], aspect: "5:7" },
11747
+ player: { dimension: "2d", animations: ["idle", "walk", "attack", "hit", "death"], aspect: "1:1" },
11748
+ enemy: { dimension: "2d", animations: ["idle", "walk", "attack", "hit", "death"], aspect: "1:1" },
11749
+ npc: { dimension: "2d", animations: ["idle", "walk", "attack", "hit", "death"], aspect: "1:1" },
11750
+ projectile: { dimension: "2d", animations: ["static"], aspect: "1:1" },
11751
+ vehicle: { dimension: "2d", animations: ["idle", "walk"], aspect: "1:1" },
11752
+ ui: { dimension: "2d", animations: ["static"], aspect: "1:1" }
11753
+ };
11754
+ }
11755
+ });
11875
11756
  function buildDefaultBattleTiles() {
11876
11757
  const tiles = [];
11877
11758
  for (let y = 0; y < BATTLE_GRID_H; y++) {
@@ -11930,14 +11811,14 @@ function BattleBoard({
11930
11811
  if (o === null || typeof o.x !== "number" || typeof o.y !== "number") return [];
11931
11812
  const tile = { x: o.x, y: o.y };
11932
11813
  if (typeof o.terrain === "string") tile.terrain = o.terrain;
11933
- if (typeof o.terrainSprite === "string") tile.terrainSprite = o.terrainSprite;
11814
+ if (typeof o.terrainSprite === "string") tile.terrainSprite = makeAsset(o.terrainSprite, "tile");
11934
11815
  if (typeof o.passable === "boolean") tile.passable = o.passable;
11935
11816
  if (typeof o.movementCost === "number") tile.movementCost = o.movementCost;
11936
11817
  if (typeof o.elevation === "number") tile.elevation = o.elevation;
11937
11818
  if (typeof o.type === "string") tile.type = o.type;
11938
11819
  if (typeof o.tileType === "string") tile.tileType = o.tileType;
11939
11820
  if (typeof o.id === "string") tile.id = o.id;
11940
- if (typeof o.modelUrl === "string") tile.modelUrl = o.modelUrl;
11821
+ if (typeof o.modelUrl === "string") tile.modelUrl = makeAsset(o.modelUrl, "decoration", { dimension: "3d" });
11941
11822
  return [tile];
11942
11823
  }) : []);
11943
11824
  const tiles = rawTiles.length === 0 ? DEFAULT_BATTLE_TILES : rawTiles;
@@ -11946,10 +11827,10 @@ function BattleBoard({
11946
11827
  if (o === null || typeof o.type !== "string" || typeof o.x !== "number" || typeof o.y !== "number") return [];
11947
11828
  const feat = { type: o.type, x: o.x, y: o.y };
11948
11829
  if (typeof o.id === "string") feat.id = o.id;
11949
- if (typeof o.sprite === "string") feat.sprite = o.sprite;
11830
+ if (typeof o.sprite === "string") feat.sprite = makeAsset(o.sprite, "decoration");
11950
11831
  if (typeof o.color === "string") feat.color = o.color;
11951
11832
  if (typeof o.elevation === "number") feat.elevation = o.elevation;
11952
- if (typeof o.assetUrl === "string") feat.assetUrl = o.assetUrl;
11833
+ if (typeof o.assetUrl === "string") feat.assetUrl = makeAsset(o.assetUrl, "decoration", { dimension: "3d" });
11953
11834
  return [feat];
11954
11835
  }) : []);
11955
11836
  const boardWidth = num(board.gridWidth ?? board.boardWidth, BATTLE_GRID_W);
@@ -12065,7 +11946,7 @@ function BattleBoard({
12065
11946
  maxHealth: num(unit.maxHealth),
12066
11947
  unitType: unit.unitType == null ? void 0 : str(unit.unitType),
12067
11948
  heroId: unit.heroId == null ? void 0 : str(unit.heroId),
12068
- sprite: unit.sprite == null ? void 0 : str(unit.sprite),
11949
+ sprite: unit.sprite == null ? void 0 : makeAsset(str(unit.sprite), "npc"),
12069
11950
  traits: unitTraits?.map((tr) => ({
12070
11951
  name: tr.name,
12071
11952
  currentState: tr.currentState,
@@ -12215,7 +12096,6 @@ function BattleBoard({
12215
12096
  onTileHover: (x, y) => setHoveredTile({ x, y }),
12216
12097
  onTileLeave: () => setHoveredTile(null),
12217
12098
  scale,
12218
- assetBaseUrl: assetManifest?.baseUrl,
12219
12099
  assetManifest,
12220
12100
  backgroundImage,
12221
12101
  onDrawEffects,
@@ -12293,15 +12173,16 @@ var init_BattleBoard = __esm({
12293
12173
  init_IsometricCanvas();
12294
12174
  init_boardEntity();
12295
12175
  init_isometric();
12176
+ init_makeAsset();
12296
12177
  BATTLE_CDN = "https://almadar-kflow-assets.web.app/shared";
12297
12178
  BATTLE_GRID_W = 16;
12298
12179
  BATTLE_GRID_H = 16;
12299
12180
  BATTLE_TERRAIN_SPRITES = [
12300
- `${BATTLE_CDN}/isometric-dungeon/Isometric/dirt_E.png`,
12301
- `${BATTLE_CDN}/isometric-dungeon/Isometric/dirtTiles_E.png`,
12302
- `${BATTLE_CDN}/isometric-dungeon/Isometric/planks_E.png`,
12303
- `${BATTLE_CDN}/isometric-dungeon/Isometric/stoneTile_E.png`,
12304
- `${BATTLE_CDN}/isometric-dungeon/Isometric/stoneInset_E.png`
12181
+ makeAsset(`${BATTLE_CDN}/isometric-dungeon/Isometric/dirt_E.png`, "tile"),
12182
+ makeAsset(`${BATTLE_CDN}/isometric-dungeon/Isometric/dirtTiles_E.png`, "tile"),
12183
+ makeAsset(`${BATTLE_CDN}/isometric-dungeon/Isometric/planks_E.png`, "tile"),
12184
+ makeAsset(`${BATTLE_CDN}/isometric-dungeon/Isometric/stoneTile_E.png`, "tile"),
12185
+ makeAsset(`${BATTLE_CDN}/isometric-dungeon/Isometric/stoneInset_E.png`, "tile")
12305
12186
  ];
12306
12187
  DEFAULT_BATTLE_TILES = buildDefaultBattleTiles();
12307
12188
  BattleBoard.displayName = "BattleBoard";
@@ -12340,61 +12221,64 @@ function BattleTemplate({
12340
12221
  }
12341
12222
  );
12342
12223
  }
12343
- var CDN, DEFAULT_BATTLE_TILES2, DEFAULT_BATTLE_UNITS, DEFAULT_BATTLE_FEATURES, DEFAULT_BATTLE_MANIFEST;
12224
+ var CDN, STONE, DIRT, GRASS, DEFAULT_BATTLE_TILES2, DEFAULT_BATTLE_UNITS, DEFAULT_BATTLE_FEATURES, DEFAULT_BATTLE_MANIFEST;
12344
12225
  var init_BattleTemplate = __esm({
12345
12226
  "components/game/templates/BattleTemplate.tsx"() {
12346
12227
  init_BattleBoard();
12228
+ init_makeAsset();
12347
12229
  CDN = "https://almadar-kflow-assets.web.app/shared";
12230
+ STONE = makeAsset(`${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png`, "tile");
12231
+ DIRT = makeAsset(`${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_01.png`, "tile");
12232
+ GRASS = makeAsset(`${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_13.png`, "tile");
12348
12233
  DEFAULT_BATTLE_TILES2 = [
12349
- { x: 0, y: 0, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
12350
- { x: 1, y: 0, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
12351
- { x: 2, y: 0, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
12352
- { x: 3, y: 0, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
12353
- { x: 4, y: 0, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
12354
- { x: 0, y: 1, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
12355
- { x: 1, y: 1, terrain: "dirt", passable: true, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_01.png` },
12356
- { x: 2, y: 1, terrain: "grass", passable: true, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_13.png` },
12357
- { x: 3, y: 1, terrain: "grass", passable: true, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_13.png` },
12358
- { x: 4, y: 1, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
12359
- { x: 0, y: 2, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
12360
- { x: 1, y: 2, terrain: "grass", passable: true, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_13.png` },
12361
- { x: 2, y: 2, terrain: "dirt", passable: true, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_01.png` },
12362
- { x: 3, y: 2, terrain: "grass", passable: true, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_13.png` },
12363
- { x: 4, y: 2, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
12364
- { x: 0, y: 3, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
12365
- { x: 1, y: 3, terrain: "grass", passable: true, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_13.png` },
12366
- { x: 2, y: 3, terrain: "grass", passable: true, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_13.png` },
12367
- { x: 3, y: 3, terrain: "dirt", passable: true, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_01.png` },
12368
- { x: 4, y: 3, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
12369
- { x: 0, y: 4, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
12370
- { x: 1, y: 4, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
12371
- { x: 2, y: 4, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
12372
- { x: 3, y: 4, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` },
12373
- { x: 4, y: 4, terrain: "stone", passable: false, terrainSprite: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png` }
12234
+ { x: 0, y: 0, terrain: "stone", passable: false, terrainSprite: STONE },
12235
+ { x: 1, y: 0, terrain: "stone", passable: false, terrainSprite: STONE },
12236
+ { x: 2, y: 0, terrain: "stone", passable: false, terrainSprite: STONE },
12237
+ { x: 3, y: 0, terrain: "stone", passable: false, terrainSprite: STONE },
12238
+ { x: 4, y: 0, terrain: "stone", passable: false, terrainSprite: STONE },
12239
+ { x: 0, y: 1, terrain: "stone", passable: false, terrainSprite: STONE },
12240
+ { x: 1, y: 1, terrain: "dirt", passable: true, terrainSprite: DIRT },
12241
+ { x: 2, y: 1, terrain: "grass", passable: true, terrainSprite: GRASS },
12242
+ { x: 3, y: 1, terrain: "grass", passable: true, terrainSprite: GRASS },
12243
+ { x: 4, y: 1, terrain: "stone", passable: false, terrainSprite: STONE },
12244
+ { x: 0, y: 2, terrain: "stone", passable: false, terrainSprite: STONE },
12245
+ { x: 1, y: 2, terrain: "grass", passable: true, terrainSprite: GRASS },
12246
+ { x: 2, y: 2, terrain: "dirt", passable: true, terrainSprite: DIRT },
12247
+ { x: 3, y: 2, terrain: "grass", passable: true, terrainSprite: GRASS },
12248
+ { x: 4, y: 2, terrain: "stone", passable: false, terrainSprite: STONE },
12249
+ { x: 0, y: 3, terrain: "stone", passable: false, terrainSprite: STONE },
12250
+ { x: 1, y: 3, terrain: "grass", passable: true, terrainSprite: GRASS },
12251
+ { x: 2, y: 3, terrain: "grass", passable: true, terrainSprite: GRASS },
12252
+ { x: 3, y: 3, terrain: "dirt", passable: true, terrainSprite: DIRT },
12253
+ { x: 4, y: 3, terrain: "stone", passable: false, terrainSprite: STONE },
12254
+ { x: 0, y: 4, terrain: "stone", passable: false, terrainSprite: STONE },
12255
+ { x: 1, y: 4, terrain: "stone", passable: false, terrainSprite: STONE },
12256
+ { x: 2, y: 4, terrain: "stone", passable: false, terrainSprite: STONE },
12257
+ { x: 3, y: 4, terrain: "stone", passable: false, terrainSprite: STONE },
12258
+ { x: 4, y: 4, terrain: "stone", passable: false, terrainSprite: STONE }
12374
12259
  ];
12375
12260
  DEFAULT_BATTLE_UNITS = [
12376
- { id: "u1", position: { x: 1, y: 1 }, unitType: "worker", name: "Worker", team: "player", health: 10, maxHealth: 10, sprite: `${CDN}/sprite-sheets/amir-sprite-sheet-se.png` },
12377
- { id: "u2", position: { x: 3, y: 3 }, unitType: "guardian", name: "Guardian", team: "enemy", health: 8, maxHealth: 10, sprite: `${CDN}/sprite-sheets/destroyer-sprite-sheet-sw.png` }
12261
+ { id: "u1", position: { x: 1, y: 1 }, unitType: "worker", name: "Worker", team: "player", health: 10, maxHealth: 10, sprite: makeAsset(`${CDN}/sprite-sheets/amir-sprite-sheet-se.png`, "player") },
12262
+ { id: "u2", position: { x: 3, y: 3 }, unitType: "guardian", name: "Guardian", team: "enemy", health: 8, maxHealth: 10, sprite: makeAsset(`${CDN}/sprite-sheets/destroyer-sprite-sheet-sw.png`, "enemy") }
12378
12263
  ];
12379
12264
  DEFAULT_BATTLE_FEATURES = [
12380
- { id: "f1", x: 2, y: 2, type: "gold_mine", sprite: `${CDN}/world-map/gold_mine.png` },
12381
- { id: "f2", x: 3, y: 1, type: "portal", sprite: `${CDN}/world-map/portal_open.png` }
12265
+ { id: "f1", x: 2, y: 2, type: "gold_mine", sprite: makeAsset(`${CDN}/world-map/gold_mine.png`, "decoration") },
12266
+ { id: "f2", x: 3, y: 1, type: "portal", sprite: makeAsset(`${CDN}/world-map/portal_open.png`, "decoration") }
12382
12267
  ];
12383
12268
  DEFAULT_BATTLE_MANIFEST = {
12384
- baseUrl: CDN,
12385
- terrains: {
12386
- stone: "/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png",
12387
- dirt: "/isometric-blocks/PNG/Abstract tiles/abstractTile_01.png",
12388
- grass: "/isometric-blocks/PNG/Abstract tiles/abstractTile_13.png"
12389
- },
12390
- units: {
12391
- worker: "/sprite-sheets/amir-sprite-sheet-se.png",
12392
- guardian: "/sprite-sheets/destroyer-sprite-sheet-sw.png"
12393
- },
12394
- features: {
12395
- gold_mine: "/world-map/gold_mine.png",
12396
- portal: "/world-map/portal_open.png"
12397
- }
12269
+ terrains: makeAssetMap({
12270
+ stone: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_07.png`,
12271
+ dirt: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_01.png`,
12272
+ grass: `${CDN}/isometric-blocks/PNG/Abstract tiles/abstractTile_13.png`
12273
+ }, "tile"),
12274
+ units: makeAssetMap({
12275
+ worker: `${CDN}/sprite-sheets/amir-sprite-sheet-se.png`,
12276
+ guardian: `${CDN}/sprite-sheets/destroyer-sprite-sheet-sw.png`
12277
+ }, "npc"),
12278
+ features: makeAssetMap({
12279
+ gold_mine: `${CDN}/world-map/gold_mine.png`,
12280
+ portal: `${CDN}/world-map/portal_open.png`
12281
+ }, "decoration")
12398
12282
  };
12399
12283
  BattleTemplate.displayName = "BattleTemplate";
12400
12284
  }
@@ -13385,6 +13269,50 @@ var init_Tabs = __esm({
13385
13269
  Tabs.displayName = "Tabs";
13386
13270
  }
13387
13271
  });
13272
+ var LoadingState;
13273
+ var init_LoadingState = __esm({
13274
+ "components/core/molecules/LoadingState.tsx"() {
13275
+ "use client";
13276
+ init_cn();
13277
+ init_atoms2();
13278
+ init_Stack();
13279
+ init_Typography();
13280
+ LoadingState = ({
13281
+ title,
13282
+ message,
13283
+ className
13284
+ }) => {
13285
+ const { t } = useTranslate();
13286
+ const displayMessage = message ?? t("common.loading");
13287
+ return /* @__PURE__ */ jsxs(
13288
+ VStack,
13289
+ {
13290
+ align: "center",
13291
+ className: cn(
13292
+ "justify-center py-12",
13293
+ className
13294
+ ),
13295
+ children: [
13296
+ /* @__PURE__ */ jsx(Spinner, { size: "lg" }),
13297
+ title && /* @__PURE__ */ jsx(Typography, { variant: "h3", className: "mt-4 text-lg font-semibold text-foreground", children: title }),
13298
+ /* @__PURE__ */ jsx(
13299
+ Typography,
13300
+ {
13301
+ variant: "small",
13302
+ className: cn(
13303
+ "text-muted-foreground",
13304
+ title ? "mt-2" : "mt-4"
13305
+ ),
13306
+ children: displayMessage
13307
+ }
13308
+ )
13309
+ ]
13310
+ }
13311
+ );
13312
+ };
13313
+ LoadingState.displayName = "LoadingState";
13314
+ }
13315
+ });
13388
13316
  var ICON_NAME_ALIASES, lookStyles3, EmptyState;
13389
13317
  var init_EmptyState = __esm({
13390
13318
  "components/core/molecules/EmptyState.tsx"() {
@@ -13665,7 +13593,7 @@ var init_CodeBlock = __esm({
13665
13593
  };
13666
13594
  LINE_PROPS_FN = (n) => ({ "data-line": String(n - 1) });
13667
13595
  HIDDEN_LINE_NUMBERS = { display: "none" };
13668
- CodeBlock = React89__default.memo(
13596
+ CodeBlock = React87__default.memo(
13669
13597
  ({
13670
13598
  code: rawCode,
13671
13599
  language = "text",
@@ -14252,7 +14180,7 @@ var init_MarkdownContent = __esm({
14252
14180
  init_Box();
14253
14181
  init_CodeBlock();
14254
14182
  init_cn();
14255
- MarkdownContent = React89__default.memo(
14183
+ MarkdownContent = React87__default.memo(
14256
14184
  ({ content, direction = "ltr", className }) => {
14257
14185
  const { t: _t } = useTranslate();
14258
14186
  const safeContent = typeof content === "string" ? content : String(content ?? "");
@@ -14565,7 +14493,6 @@ function BoardgameBoard({
14565
14493
  units,
14566
14494
  features,
14567
14495
  assetManifest,
14568
- assetBaseUrl,
14569
14496
  scale,
14570
14497
  showMinimap,
14571
14498
  enableCamera,
@@ -15621,7 +15548,7 @@ var init_StateMachineView = __esm({
15621
15548
  style: { top: title ? 30 : 0 },
15622
15549
  children: [
15623
15550
  entity && /* @__PURE__ */ jsx(EntityBox, { entity, config }),
15624
- states.map((state) => renderStateNode ? /* @__PURE__ */ jsx(React89__default.Fragment, { children: renderStateNode(state, config) }, state.id) : /* @__PURE__ */ jsx(
15551
+ states.map((state) => renderStateNode ? /* @__PURE__ */ jsx(React87__default.Fragment, { children: renderStateNode(state, config) }, state.id) : /* @__PURE__ */ jsx(
15625
15552
  StateNode,
15626
15553
  {
15627
15554
  state,
@@ -19590,7 +19517,7 @@ function CardHand({
19590
19517
  className
19591
19518
  }) {
19592
19519
  const eventBus = useEventBus();
19593
- const handleClick = React89.useCallback(
19520
+ const handleClick = React87.useCallback(
19594
19521
  (card) => {
19595
19522
  if (card.disabled) return;
19596
19523
  onCardClick?.(card.id);
@@ -19635,7 +19562,7 @@ function CardHand({
19635
19562
  /* @__PURE__ */ jsx(Box, { className: "flex-1 flex items-center justify-center w-full", children: card.iconUrl ? /* @__PURE__ */ jsx(
19636
19563
  "img",
19637
19564
  {
19638
- src: card.iconUrl,
19565
+ src: card.iconUrl.url,
19639
19566
  alt: card.title ?? card.id,
19640
19567
  width: art,
19641
19568
  height: art,
@@ -19693,15 +19620,6 @@ var init_CardHand = __esm({
19693
19620
  CardHand.displayName = "CardHand";
19694
19621
  }
19695
19622
  });
19696
- function resolveManifestUrl(manifest, relative) {
19697
- if (relative == null) return void 0;
19698
- if (/^https?:\/\//.test(relative)) return relative;
19699
- const base = manifest?.baseUrl;
19700
- if (base == null) return relative;
19701
- const cleanBase = base.replace(/\/$/, "");
19702
- const cleanRel = relative.replace(/^\//, "");
19703
- return `${cleanBase}/${cleanRel}`;
19704
- }
19705
19623
  function rowToCard(r) {
19706
19624
  return {
19707
19625
  id: str(r.id),
@@ -19715,7 +19633,7 @@ function rowToCard(r) {
19715
19633
  function toHandCards(cards, manifest, mana) {
19716
19634
  return cards.map((c) => {
19717
19635
  const key = c.iconKey ?? c.id;
19718
- const iconUrl = resolveManifestUrl(manifest, manifest?.cards?.[key]);
19636
+ const iconUrl = manifest?.cards?.[key];
19719
19637
  return {
19720
19638
  id: c.id,
19721
19639
  iconUrl,
@@ -20829,7 +20747,6 @@ function CastleBoard({
20829
20747
  onTileHover: (x, y) => setHoveredTile({ x, y }),
20830
20748
  onTileLeave: () => setHoveredTile(null),
20831
20749
  scale,
20832
- assetBaseUrl: assetManifest?.baseUrl,
20833
20750
  assetManifest,
20834
20751
  backgroundImage
20835
20752
  }
@@ -20905,60 +20822,63 @@ function CastleTemplate({
20905
20822
  }
20906
20823
  );
20907
20824
  }
20908
- var CDN2, DEFAULT_CASTLE_TILES, DEFAULT_CASTLE_UNITS, DEFAULT_CASTLE_FEATURES, DEFAULT_CASTLE_MANIFEST;
20825
+ var CDN2, WALL, FLOOR, FLOOR_CENTER, DEFAULT_CASTLE_TILES, DEFAULT_CASTLE_UNITS, DEFAULT_CASTLE_FEATURES, DEFAULT_CASTLE_MANIFEST;
20909
20826
  var init_CastleTemplate = __esm({
20910
20827
  "components/game/templates/CastleTemplate.tsx"() {
20911
20828
  init_CastleBoard();
20829
+ init_makeAsset();
20912
20830
  CDN2 = "https://almadar-kflow-assets.web.app/shared";
20831
+ WALL = makeAsset(`${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png`, "tile");
20832
+ FLOOR = makeAsset(`${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png`, "tile");
20833
+ FLOOR_CENTER = makeAsset(`${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_09.png`, "tile");
20913
20834
  DEFAULT_CASTLE_TILES = [
20914
- { x: 0, y: 0, terrain: "wall", passable: false, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png` },
20915
- { x: 1, y: 0, terrain: "wall", passable: false, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png` },
20916
- { x: 2, y: 0, terrain: "wall", passable: false, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png` },
20917
- { x: 3, y: 0, terrain: "wall", passable: false, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png` },
20918
- { x: 4, y: 0, terrain: "wall", passable: false, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png` },
20919
- { x: 0, y: 1, terrain: "wall", passable: false, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png` },
20920
- { x: 1, y: 1, terrain: "floor", passable: true, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png` },
20921
- { x: 2, y: 1, terrain: "floor", passable: true, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png` },
20922
- { x: 3, y: 1, terrain: "floor", passable: true, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png` },
20923
- { x: 4, y: 1, terrain: "wall", passable: false, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png` },
20924
- { x: 0, y: 2, terrain: "wall", passable: false, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png` },
20925
- { x: 1, y: 2, terrain: "floor", passable: true, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png` },
20926
- { x: 2, y: 2, terrain: "floor", passable: true, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_09.png` },
20927
- { x: 3, y: 2, terrain: "floor", passable: true, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png` },
20928
- { x: 4, y: 2, terrain: "wall", passable: false, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png` },
20929
- { x: 0, y: 3, terrain: "wall", passable: false, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png` },
20930
- { x: 1, y: 3, terrain: "floor", passable: true, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png` },
20931
- { x: 2, y: 3, terrain: "floor", passable: true, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png` },
20932
- { x: 3, y: 3, terrain: "floor", passable: true, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png` },
20933
- { x: 4, y: 3, terrain: "wall", passable: false, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png` },
20934
- { x: 0, y: 4, terrain: "wall", passable: false, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png` },
20935
- { x: 1, y: 4, terrain: "wall", passable: false, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png` },
20936
- { x: 2, y: 4, terrain: "wall", passable: false, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png` },
20937
- { x: 3, y: 4, terrain: "wall", passable: false, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png` },
20938
- { x: 4, y: 4, terrain: "wall", passable: false, terrainSprite: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png` }
20835
+ { x: 0, y: 0, terrain: "wall", passable: false, terrainSprite: WALL },
20836
+ { x: 1, y: 0, terrain: "wall", passable: false, terrainSprite: WALL },
20837
+ { x: 2, y: 0, terrain: "wall", passable: false, terrainSprite: WALL },
20838
+ { x: 3, y: 0, terrain: "wall", passable: false, terrainSprite: WALL },
20839
+ { x: 4, y: 0, terrain: "wall", passable: false, terrainSprite: WALL },
20840
+ { x: 0, y: 1, terrain: "wall", passable: false, terrainSprite: WALL },
20841
+ { x: 1, y: 1, terrain: "floor", passable: true, terrainSprite: FLOOR },
20842
+ { x: 2, y: 1, terrain: "floor", passable: true, terrainSprite: FLOOR },
20843
+ { x: 3, y: 1, terrain: "floor", passable: true, terrainSprite: FLOOR },
20844
+ { x: 4, y: 1, terrain: "wall", passable: false, terrainSprite: WALL },
20845
+ { x: 0, y: 2, terrain: "wall", passable: false, terrainSprite: WALL },
20846
+ { x: 1, y: 2, terrain: "floor", passable: true, terrainSprite: FLOOR },
20847
+ { x: 2, y: 2, terrain: "floor", passable: true, terrainSprite: FLOOR_CENTER },
20848
+ { x: 3, y: 2, terrain: "floor", passable: true, terrainSprite: FLOOR },
20849
+ { x: 4, y: 2, terrain: "wall", passable: false, terrainSprite: WALL },
20850
+ { x: 0, y: 3, terrain: "wall", passable: false, terrainSprite: WALL },
20851
+ { x: 1, y: 3, terrain: "floor", passable: true, terrainSprite: FLOOR },
20852
+ { x: 2, y: 3, terrain: "floor", passable: true, terrainSprite: FLOOR },
20853
+ { x: 3, y: 3, terrain: "floor", passable: true, terrainSprite: FLOOR },
20854
+ { x: 4, y: 3, terrain: "wall", passable: false, terrainSprite: WALL },
20855
+ { x: 0, y: 4, terrain: "wall", passable: false, terrainSprite: WALL },
20856
+ { x: 1, y: 4, terrain: "wall", passable: false, terrainSprite: WALL },
20857
+ { x: 2, y: 4, terrain: "wall", passable: false, terrainSprite: WALL },
20858
+ { x: 3, y: 4, terrain: "wall", passable: false, terrainSprite: WALL },
20859
+ { x: 4, y: 4, terrain: "wall", passable: false, terrainSprite: WALL }
20939
20860
  ];
20940
20861
  DEFAULT_CASTLE_UNITS = [
20941
- { id: "u1", position: { x: 1, y: 1 }, unitType: "worker", name: "Worker", team: "player", health: 10, maxHealth: 10, sprite: `${CDN2}/sprite-sheets/coordinator-sprite-sheet-se.png` },
20942
- { id: "u2", position: { x: 3, y: 3 }, unitType: "guardian", name: "Guardian", team: "player", health: 10, maxHealth: 10, sprite: `${CDN2}/sprite-sheets/forger-sprite-sheet-se.png` }
20862
+ { id: "u1", position: { x: 1, y: 1 }, unitType: "worker", name: "Worker", team: "player", health: 10, maxHealth: 10, sprite: makeAsset(`${CDN2}/sprite-sheets/coordinator-sprite-sheet-se.png`, "player") },
20863
+ { id: "u2", position: { x: 3, y: 3 }, unitType: "guardian", name: "Guardian", team: "player", health: 10, maxHealth: 10, sprite: makeAsset(`${CDN2}/sprite-sheets/forger-sprite-sheet-se.png`, "player") }
20943
20864
  ];
20944
20865
  DEFAULT_CASTLE_FEATURES = [
20945
- { id: "f1", x: 2, y: 2, type: "chest", sprite: `${CDN2}/world-map/treasure_chest_closed.png` },
20946
- { id: "f2", x: 3, y: 1, type: "crystal", sprite: `${CDN2}/world-map/resonance_crystal.png` }
20866
+ { id: "f1", x: 2, y: 2, type: "chest", sprite: makeAsset(`${CDN2}/world-map/treasure_chest_closed.png`, "decoration") },
20867
+ { id: "f2", x: 3, y: 1, type: "crystal", sprite: makeAsset(`${CDN2}/world-map/resonance_crystal.png`, "decoration") }
20947
20868
  ];
20948
20869
  DEFAULT_CASTLE_MANIFEST = {
20949
- baseUrl: CDN2,
20950
- terrains: {
20951
- wall: "/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png",
20952
- floor: "/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png"
20953
- },
20954
- units: {
20955
- worker: "/sprite-sheets/coordinator-sprite-sheet-se.png",
20956
- guardian: "/sprite-sheets/forger-sprite-sheet-se.png"
20957
- },
20958
- features: {
20959
- chest: "/world-map/treasure_chest_closed.png",
20960
- crystal: "/world-map/resonance_crystal.png"
20961
- }
20870
+ terrains: makeAssetMap({
20871
+ wall: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_05.png`,
20872
+ floor: `${CDN2}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png`
20873
+ }, "tile"),
20874
+ units: makeAssetMap({
20875
+ worker: `${CDN2}/sprite-sheets/coordinator-sprite-sheet-se.png`,
20876
+ guardian: `${CDN2}/sprite-sheets/forger-sprite-sheet-se.png`
20877
+ }, "player"),
20878
+ features: makeAssetMap({
20879
+ chest: `${CDN2}/world-map/treasure_chest_closed.png`,
20880
+ crystal: `${CDN2}/world-map/resonance_crystal.png`
20881
+ }, "decoration")
20962
20882
  };
20963
20883
  CastleTemplate.displayName = "CastleTemplate";
20964
20884
  }
@@ -21946,15 +21866,6 @@ var init_ChatBar = __esm({
21946
21866
  ChatBar.displayName = "ChatBar";
21947
21867
  }
21948
21868
  });
21949
- function resolveManifestUrl2(manifest, relative) {
21950
- if (relative == null) return void 0;
21951
- if (/^https?:\/\//.test(relative)) return relative;
21952
- const base = manifest?.baseUrl;
21953
- if (base == null) return relative;
21954
- const cleanBase = base.replace(/\/$/, "");
21955
- const cleanRel = relative.replace(/^\//, "");
21956
- return `${cleanBase}/${cleanRel}`;
21957
- }
21958
21869
  function buildDefaultCBTiles() {
21959
21870
  const tiles = [];
21960
21871
  for (let y = 0; y < CB_GRID_H; y++) {
@@ -21969,12 +21880,12 @@ function buildDefaultCBTiles() {
21969
21880
  function tilesToIso(tiles, manifest) {
21970
21881
  return tiles.map((t) => {
21971
21882
  const key = t.terrain ?? "grass";
21972
- const sprite = t.terrainSprite ?? resolveManifestUrl2(manifest, manifest?.terrains?.[key]) ?? resolveManifestUrl2(manifest, manifest?.terrains?.grass);
21883
+ const terrainSprite = t.terrainSprite ?? manifest?.terrains?.[key] ?? manifest?.terrains?.grass;
21973
21884
  return {
21974
21885
  x: t.x,
21975
21886
  y: t.y,
21976
21887
  terrain: t.terrain,
21977
- terrainSprite: sprite,
21888
+ terrainSprite,
21978
21889
  passable: t.passable
21979
21890
  };
21980
21891
  });
@@ -21985,7 +21896,7 @@ function buildingsToFeatures(buildings, manifest) {
21985
21896
  x: b.x,
21986
21897
  y: b.y,
21987
21898
  type: b.type,
21988
- sprite: resolveManifestUrl2(manifest, manifest?.features?.[b.type])
21899
+ sprite: manifest?.features?.[b.type]
21989
21900
  }));
21990
21901
  }
21991
21902
  function CityBuilderBoard({
@@ -22017,7 +21928,7 @@ function CityBuilderBoard({
22017
21928
  x: num(r.x),
22018
21929
  y: num(r.y),
22019
21930
  terrain: r.terrain == null ? void 0 : str(r.terrain),
22020
- terrainSprite: r.terrainSprite == null ? void 0 : str(r.terrainSprite),
21931
+ terrainSprite: r.terrainSprite == null ? void 0 : makeAsset(str(r.terrainSprite), "tile"),
22021
21932
  passable: r.passable !== false
22022
21933
  })),
22023
21934
  [board.tiles]
@@ -22126,7 +22037,6 @@ function CityBuilderBoard({
22126
22037
  {
22127
22038
  tiles: isoTiles,
22128
22039
  features: buildingFeatures,
22129
- assetBaseUrl: assetManifest?.baseUrl,
22130
22040
  assetManifest,
22131
22041
  validMoves,
22132
22042
  hoveredTile,
@@ -22161,6 +22071,7 @@ var CB_GRID_W, CB_GRID_H, DEFAULT_BUILD_TYPES, DEFAULT_CB_TILES;
22161
22071
  var init_CityBuilderBoard = __esm({
22162
22072
  "components/game/organisms/CityBuilderBoard.tsx"() {
22163
22073
  "use client";
22074
+ init_makeAsset();
22164
22075
  init_cn();
22165
22076
  init_useEventBus();
22166
22077
  init_Box();
@@ -22579,10 +22490,10 @@ function CombatLog({
22579
22490
  }, [events2, autoScroll]);
22580
22491
  const safeEvents = events2 ?? [];
22581
22492
  const visibleEvents = safeEvents.slice(-maxVisible);
22582
- return /* @__PURE__ */ jsxs(Card, { variant: "default", className: cn("flex flex-col", className), children: [
22493
+ return /* @__PURE__ */ jsxs(Box, { className: cn("flex flex-col rounded-container border border-border bg-card shadow-elevation-card", className), children: [
22583
22494
  /* @__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: [
22584
22495
  /* @__PURE__ */ jsx(Typography, { variant: "body2", className: "font-bold", children: title }),
22585
- /* @__PURE__ */ jsxs(Badge, { variant: "neutral", size: "sm", children: [
22496
+ /* @__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: [
22586
22497
  safeEvents.length,
22587
22498
  " events"
22588
22499
  ] })
@@ -22602,7 +22513,7 @@ function CombatLog({
22602
22513
  /* @__PURE__ */ jsx(Box, { className: cn("flex-shrink-0 mt-0.5", colorClass), children: /* @__PURE__ */ jsx(EventIcon, { className: "h-4 w-4" }) }),
22603
22514
  /* @__PURE__ */ jsxs(Box, { className: "flex-1 min-w-0", children: [
22604
22515
  /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "block", children: event.message }),
22605
- event.value !== void 0 && /* @__PURE__ */ jsxs(Badge, { variant: eventBadgeVariants[eventType], size: "sm", className: "mt-1", children: [
22516
+ 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: [
22606
22517
  eventType === "heal" ? "+" : eventType === "attack" ? "-" : "",
22607
22518
  event.value
22608
22519
  ] })
@@ -22615,7 +22526,7 @@ function CombatLog({
22615
22526
  }) }) })
22616
22527
  ] });
22617
22528
  }
22618
- var eventIcons, eventColors, eventBadgeVariants, DEFAULT_COMBAT_EVENTS;
22529
+ var eventIcons, eventColors, eventValueColors, DEFAULT_COMBAT_EVENTS;
22619
22530
  var init_CombatLog = __esm({
22620
22531
  "components/game/molecules/CombatLog.tsx"() {
22621
22532
  init_atoms2();
@@ -22638,14 +22549,14 @@ var init_CombatLog = __esm({
22638
22549
  death: "text-muted-foreground",
22639
22550
  spawn: "text-accent"
22640
22551
  };
22641
- eventBadgeVariants = {
22642
- attack: "danger",
22643
- defend: "primary",
22644
- heal: "success",
22645
- move: "warning",
22646
- special: "secondary",
22647
- death: "secondary",
22648
- spawn: "secondary"
22552
+ eventValueColors = {
22553
+ attack: "text-error bg-error/10 border-error/30",
22554
+ defend: "text-info bg-info/10 border-info/30",
22555
+ heal: "text-success bg-success/10 border-success/30",
22556
+ move: "text-warning bg-warning/10 border-warning/30",
22557
+ special: "text-accent bg-accent/10 border-accent/30",
22558
+ death: "text-muted-foreground bg-muted/30 border-border",
22559
+ spawn: "text-accent bg-accent/10 border-accent/30"
22649
22560
  };
22650
22561
  DEFAULT_COMBAT_EVENTS = [
22651
22562
  { id: "e1", type: "spawn", message: "Shadow Guard entered the field.", timestamp: 0, turn: 1 },
@@ -23069,7 +22980,7 @@ function CraftingRecipe({
23069
22980
  className
23070
22981
  }) {
23071
22982
  const eventBus = useEventBus();
23072
- const handleCraft = React89.useCallback(() => {
22983
+ const handleCraft = React87.useCallback(() => {
23073
22984
  onCraft?.();
23074
22985
  if (craftEvent) {
23075
22986
  eventBus.emit(craftEvent, { output: output.label });
@@ -23086,7 +22997,7 @@ function CraftingRecipe({
23086
22997
  children: [
23087
22998
  /* @__PURE__ */ jsx(HStack, { gap: "xs", className: "flex-wrap items-center", children: inputs.map((ingredient, index) => {
23088
22999
  const hasSufficient = ingredient.available >= ingredient.required;
23089
- return /* @__PURE__ */ jsxs(React89.Fragment, { children: [
23000
+ return /* @__PURE__ */ jsxs(React87.Fragment, { children: [
23090
23001
  /* @__PURE__ */ jsx(Box, { className: "relative", children: /* @__PURE__ */ jsx(
23091
23002
  ItemSlot,
23092
23003
  {
@@ -23111,13 +23022,13 @@ function CraftingRecipe({
23111
23022
  }
23112
23023
  ),
23113
23024
  /* @__PURE__ */ jsx(
23114
- Button,
23025
+ ActionButton,
23115
23026
  {
23027
+ label: "Craft",
23116
23028
  onClick: handleCraft,
23117
23029
  disabled: !canCraft,
23118
23030
  variant: canCraft ? "primary" : "secondary",
23119
- size: "sm",
23120
- children: "Craft"
23031
+ size: "sm"
23121
23032
  }
23122
23033
  )
23123
23034
  ]
@@ -23131,7 +23042,7 @@ var init_CraftingRecipe = __esm({
23131
23042
  init_cn();
23132
23043
  init_useEventBus();
23133
23044
  init_ItemSlot();
23134
- init_Button();
23045
+ init_ActionButton();
23135
23046
  init_Box();
23136
23047
  init_Stack();
23137
23048
  init_Icon();
@@ -23158,8 +23069,8 @@ function DPad({
23158
23069
  }) {
23159
23070
  const eventBus = useEventBus();
23160
23071
  const sizes = sizeMap15[size];
23161
- const [activeDirections, setActiveDirections] = React89.useState(/* @__PURE__ */ new Set());
23162
- const handlePress = React89.useCallback(
23072
+ const [activeDirections, setActiveDirections] = React87.useState(/* @__PURE__ */ new Set());
23073
+ const handlePress = React87.useCallback(
23163
23074
  (direction) => {
23164
23075
  setActiveDirections((prev) => new Set(prev).add(direction));
23165
23076
  if (directionEvent) eventBus.emit(`UI:${directionEvent}`, { direction, pressed: true });
@@ -23167,7 +23078,7 @@ function DPad({
23167
23078
  },
23168
23079
  [directionEvent, eventBus, onDirection]
23169
23080
  );
23170
- const handleRelease = React89.useCallback(
23081
+ const handleRelease = React87.useCallback(
23171
23082
  (direction) => {
23172
23083
  setActiveDirections((prev) => {
23173
23084
  const next = new Set(prev);
@@ -24052,8 +23963,8 @@ var init_Menu = __esm({
24052
23963
  "bottom-end": "bottom-start"
24053
23964
  };
24054
23965
  const effectivePosition = direction === "rtl" ? rtlMirror[position] ?? position : position;
24055
- const triggerChild = React89__default.isValidElement(trigger) ? trigger : /* @__PURE__ */ jsx(Typography, { variant: "small", as: "span", children: trigger });
24056
- const triggerElement = React89__default.cloneElement(
23966
+ const triggerChild = React87__default.isValidElement(trigger) ? trigger : /* @__PURE__ */ jsx(Typography, { variant: "small", as: "span", children: trigger });
23967
+ const triggerElement = React87__default.cloneElement(
24057
23968
  triggerChild,
24058
23969
  {
24059
23970
  ref: triggerRef,
@@ -24148,14 +24059,14 @@ function useDataDnd(args) {
24148
24059
  const isZone = Boolean(dragGroup || accepts || sortable);
24149
24060
  const enabled = isZone || Boolean(dndRoot);
24150
24061
  const eventBus = useEventBus();
24151
- const parentRoot = React89__default.useContext(RootCtx);
24062
+ const parentRoot = React87__default.useContext(RootCtx);
24152
24063
  const isRoot = enabled && parentRoot === null;
24153
- const zoneId = React89__default.useId();
24064
+ const zoneId = React87__default.useId();
24154
24065
  const ownGroup = dragGroup ?? accepts ?? zoneId;
24155
- const [optimisticOrders, setOptimisticOrders] = React89__default.useState(() => /* @__PURE__ */ new Map());
24156
- const optimisticOrdersRef = React89__default.useRef(optimisticOrders);
24066
+ const [optimisticOrders, setOptimisticOrders] = React87__default.useState(() => /* @__PURE__ */ new Map());
24067
+ const optimisticOrdersRef = React87__default.useRef(optimisticOrders);
24157
24068
  optimisticOrdersRef.current = optimisticOrders;
24158
- const clearOptimisticOrder = React89__default.useCallback((group) => {
24069
+ const clearOptimisticOrder = React87__default.useCallback((group) => {
24159
24070
  setOptimisticOrders((prev) => {
24160
24071
  if (!prev.has(group)) return prev;
24161
24072
  const next = new Map(prev);
@@ -24180,7 +24091,7 @@ function useDataDnd(args) {
24180
24091
  const raw = it[dndItemIdField];
24181
24092
  return raw != null ? String(raw) : `__idx_${idx}`;
24182
24093
  }).join("|");
24183
- const itemIds = React89__default.useMemo(
24094
+ const itemIds = React87__default.useMemo(
24184
24095
  () => orderedItems.map((it, idx) => {
24185
24096
  const raw = it[dndItemIdField];
24186
24097
  return raw != null ? String(raw) : `__idx_${idx}`;
@@ -24191,7 +24102,7 @@ function useDataDnd(args) {
24191
24102
  const raw = it[dndItemIdField];
24192
24103
  return raw != null ? String(raw) : `__${idx}`;
24193
24104
  }).join("|");
24194
- React89__default.useEffect(() => {
24105
+ React87__default.useEffect(() => {
24195
24106
  const root = isRoot ? null : parentRoot;
24196
24107
  if (root) {
24197
24108
  root.clearOptimisticOrder(ownGroup);
@@ -24199,20 +24110,20 @@ function useDataDnd(args) {
24199
24110
  clearOptimisticOrder(ownGroup);
24200
24111
  }
24201
24112
  }, [itemsContentSig, ownGroup]);
24202
- const zonesRef = React89__default.useRef(/* @__PURE__ */ new Map());
24203
- const registerZone = React89__default.useCallback((zoneId2, meta2) => {
24113
+ const zonesRef = React87__default.useRef(/* @__PURE__ */ new Map());
24114
+ const registerZone = React87__default.useCallback((zoneId2, meta2) => {
24204
24115
  zonesRef.current.set(zoneId2, meta2);
24205
24116
  }, []);
24206
- const unregisterZone = React89__default.useCallback((zoneId2) => {
24117
+ const unregisterZone = React87__default.useCallback((zoneId2) => {
24207
24118
  zonesRef.current.delete(zoneId2);
24208
24119
  }, []);
24209
- const [activeDrag, setActiveDrag] = React89__default.useState(null);
24210
- const [overZoneGroup, setOverZoneGroup] = React89__default.useState(null);
24211
- const meta = React89__default.useMemo(
24120
+ const [activeDrag, setActiveDrag] = React87__default.useState(null);
24121
+ const [overZoneGroup, setOverZoneGroup] = React87__default.useState(null);
24122
+ const meta = React87__default.useMemo(
24212
24123
  () => ({ group: ownGroup, dropEvent, reorderEvent, positionEvent, itemIds, rawItems: items, idField: dndItemIdField }),
24213
24124
  [ownGroup, dropEvent, reorderEvent, positionEvent, itemIds, items, dndItemIdField]
24214
24125
  );
24215
- React89__default.useEffect(() => {
24126
+ React87__default.useEffect(() => {
24216
24127
  const target = isRoot ? null : parentRoot;
24217
24128
  if (!target) {
24218
24129
  zonesRef.current.set(zoneId, meta);
@@ -24231,7 +24142,7 @@ function useDataDnd(args) {
24231
24142
  }, [parentRoot, isRoot, zoneId, meta]);
24232
24143
  const sensors = useAlmadarDndSensors(true);
24233
24144
  const collisionDetection = almadarDndCollisionDetection;
24234
- const findZoneByItem = React89__default.useCallback(
24145
+ const findZoneByItem = React87__default.useCallback(
24235
24146
  (id) => {
24236
24147
  for (const z of zonesRef.current.values()) {
24237
24148
  if (z.itemIds.includes(id)) return z;
@@ -24240,7 +24151,7 @@ function useDataDnd(args) {
24240
24151
  },
24241
24152
  []
24242
24153
  );
24243
- React89__default.useCallback(
24154
+ React87__default.useCallback(
24244
24155
  (group) => {
24245
24156
  for (const z of zonesRef.current.values()) {
24246
24157
  if (z.group === group) return z;
@@ -24249,7 +24160,7 @@ function useDataDnd(args) {
24249
24160
  },
24250
24161
  []
24251
24162
  );
24252
- const handleDragEnd = React89__default.useCallback(
24163
+ const handleDragEnd = React87__default.useCallback(
24253
24164
  (event) => {
24254
24165
  const { active, over } = event;
24255
24166
  const activeIdStr = String(active.id);
@@ -24340,8 +24251,8 @@ function useDataDnd(args) {
24340
24251
  },
24341
24252
  [eventBus]
24342
24253
  );
24343
- const sortableData = React89__default.useMemo(() => ({ dndGroup: ownGroup }), [ownGroup]);
24344
- const SortableItem = React89__default.useCallback(
24254
+ const sortableData = React87__default.useMemo(() => ({ dndGroup: ownGroup }), [ownGroup]);
24255
+ const SortableItem = React87__default.useCallback(
24345
24256
  ({ id, children }) => {
24346
24257
  const {
24347
24258
  attributes,
@@ -24381,7 +24292,7 @@ function useDataDnd(args) {
24381
24292
  id: droppableId,
24382
24293
  data: sortableData
24383
24294
  });
24384
- const ctx = React89__default.useContext(RootCtx);
24295
+ const ctx = React87__default.useContext(RootCtx);
24385
24296
  const activeDrag2 = ctx?.activeDrag ?? null;
24386
24297
  const overZoneGroup2 = ctx?.overZoneGroup ?? null;
24387
24298
  const isThisZoneOver = overZoneGroup2 === ownGroup;
@@ -24396,7 +24307,7 @@ function useDataDnd(args) {
24396
24307
  showForeignPlaceholder,
24397
24308
  ctxAvailable: ctx != null
24398
24309
  });
24399
- React89__default.useEffect(() => {
24310
+ React87__default.useEffect(() => {
24400
24311
  dndLog.info("dropzone:isOver:change", { droppableId, group: ownGroup, isOver, isThisZoneOver, showForeignPlaceholder, activeDragSourceGroup: activeDrag2?.sourceGroup ?? null });
24401
24312
  }, [droppableId, isOver, isThisZoneOver, showForeignPlaceholder]);
24402
24313
  return /* @__PURE__ */ jsx(
@@ -24410,11 +24321,11 @@ function useDataDnd(args) {
24410
24321
  }
24411
24322
  );
24412
24323
  };
24413
- const rootContextValue = React89__default.useMemo(
24324
+ const rootContextValue = React87__default.useMemo(
24414
24325
  () => ({ registerZone, unregisterZone, activeDrag, overZoneGroup, optimisticOrders, clearOptimisticOrder }),
24415
24326
  [registerZone, unregisterZone, activeDrag, overZoneGroup, optimisticOrders, clearOptimisticOrder]
24416
24327
  );
24417
- const handleDragStart = React89__default.useCallback((event) => {
24328
+ const handleDragStart = React87__default.useCallback((event) => {
24418
24329
  const sourceZone = findZoneByItem(event.active.id);
24419
24330
  const rect = event.active.rect.current.initial;
24420
24331
  const height = rect?.height && rect.height > 0 ? rect.height : 64;
@@ -24433,7 +24344,7 @@ function useDataDnd(args) {
24433
24344
  isRoot
24434
24345
  });
24435
24346
  }, [findZoneByItem, isRoot, zoneId]);
24436
- const handleDragOver = React89__default.useCallback((event) => {
24347
+ const handleDragOver = React87__default.useCallback((event) => {
24437
24348
  const { active, over } = event;
24438
24349
  const overData = over?.data?.current;
24439
24350
  const overGroup = overData?.dndGroup ?? null;
@@ -24503,7 +24414,7 @@ function useDataDnd(args) {
24503
24414
  return next;
24504
24415
  });
24505
24416
  }, []);
24506
- const handleDragCancel = React89__default.useCallback((event) => {
24417
+ const handleDragCancel = React87__default.useCallback((event) => {
24507
24418
  setActiveDrag(null);
24508
24419
  setOverZoneGroup(null);
24509
24420
  dndLog.warn("dragCancel", {
@@ -24511,12 +24422,12 @@ function useDataDnd(args) {
24511
24422
  reason: "dnd-kit cancelled the drag (escape key, pointer interrupted, or external)"
24512
24423
  });
24513
24424
  }, []);
24514
- const handleDragEndWithCleanup = React89__default.useCallback((event) => {
24425
+ const handleDragEndWithCleanup = React87__default.useCallback((event) => {
24515
24426
  handleDragEnd(event);
24516
24427
  setActiveDrag(null);
24517
24428
  setOverZoneGroup(null);
24518
24429
  }, [handleDragEnd]);
24519
- const wrapContainer = React89__default.useCallback(
24430
+ const wrapContainer = React87__default.useCallback(
24520
24431
  (children) => {
24521
24432
  if (!enabled) return children;
24522
24433
  const strategy = layout === "grid" ? rectSortingStrategy : verticalListSortingStrategy;
@@ -24570,7 +24481,7 @@ var init_useDataDnd = __esm({
24570
24481
  init_useAlmadarDndCollision();
24571
24482
  init_Box();
24572
24483
  dndLog = createLogger("almadar:ui:dnd");
24573
- RootCtx = React89__default.createContext(null);
24484
+ RootCtx = React87__default.createContext(null);
24574
24485
  }
24575
24486
  });
24576
24487
  function renderIconInput(icon, props) {
@@ -25096,7 +25007,7 @@ function DataList({
25096
25007
  }) {
25097
25008
  const eventBus = useEventBus();
25098
25009
  const { t } = useTranslate();
25099
- const [visibleCount, setVisibleCount] = React89__default.useState(pageSize || Infinity);
25010
+ const [visibleCount, setVisibleCount] = React87__default.useState(pageSize || Infinity);
25100
25011
  const fieldDefs = fields ?? columns ?? [];
25101
25012
  const allDataRaw = Array.isArray(entity) ? entity : entity ? [entity] : [];
25102
25013
  const dnd = useDataDnd({
@@ -25115,7 +25026,7 @@ function DataList({
25115
25026
  const data = pageSize > 0 ? allData.slice(0, visibleCount) : allData;
25116
25027
  const hasMoreLocal = pageSize > 0 && visibleCount < allData.length;
25117
25028
  const hasRenderProp = typeof children === "function";
25118
- React89__default.useEffect(() => {
25029
+ React87__default.useEffect(() => {
25119
25030
  const renderItemTypeOf = typeof schemaRenderItem;
25120
25031
  const childrenTypeOf = typeof children;
25121
25032
  if (data.length > 0 && !hasRenderProp) {
@@ -25219,7 +25130,7 @@ function DataList({
25219
25130
  const items2 = [...data];
25220
25131
  const groups2 = groupBy ? groupData(items2, groupBy) : [{ label: "", items: items2 }];
25221
25132
  const contentField = titleField?.name ?? fieldDefs[0]?.name ?? "";
25222
- return /* @__PURE__ */ jsx(VStack, { gap: "sm", className: cn("py-2", className), children: groups2.map((group, gi) => /* @__PURE__ */ jsxs(React89__default.Fragment, { children: [
25133
+ return /* @__PURE__ */ jsx(VStack, { gap: "sm", className: cn("py-2", className), children: groups2.map((group, gi) => /* @__PURE__ */ jsxs(React87__default.Fragment, { children: [
25223
25134
  group.label && /* @__PURE__ */ jsx(Divider, { label: group.label, className: "my-2" }),
25224
25135
  group.items.map((itemData, index) => {
25225
25136
  const id = itemData.id || `${gi}-${index}`;
@@ -25360,7 +25271,7 @@ function DataList({
25360
25271
  className
25361
25272
  ),
25362
25273
  children: [
25363
- groups.map((group, gi) => /* @__PURE__ */ jsxs(React89__default.Fragment, { children: [
25274
+ groups.map((group, gi) => /* @__PURE__ */ jsxs(React87__default.Fragment, { children: [
25364
25275
  group.label && /* @__PURE__ */ jsx(Divider, { label: group.label, className: gi > 0 ? "mt-4" : "mt-0" }),
25365
25276
  group.items.map(
25366
25277
  (itemData, index) => renderItem(itemData, index, gi === groups.length - 1 && index === group.items.length - 1)
@@ -26153,7 +26064,7 @@ var init_Flex = __esm({
26153
26064
  flexStyle.flexBasis = typeof basis === "number" ? `${basis}px` : basis;
26154
26065
  }
26155
26066
  }
26156
- return React89__default.createElement(Component2, {
26067
+ return React87__default.createElement(Component2, {
26157
26068
  className: cn(
26158
26069
  inline ? "inline-flex" : "flex",
26159
26070
  directionStyles[direction],
@@ -26272,7 +26183,7 @@ var init_Grid = __esm({
26272
26183
  as: Component2 = "div"
26273
26184
  }) => {
26274
26185
  const mergedStyle = rows2 ? { gridTemplateRows: `repeat(${rows2}, minmax(0, 1fr))`, ...style } : style;
26275
- return React89__default.createElement(
26186
+ return React87__default.createElement(
26276
26187
  Component2,
26277
26188
  {
26278
26189
  className: cn(
@@ -26468,9 +26379,9 @@ var init_Popover = __esm({
26468
26379
  onMouseLeave: handleClose,
26469
26380
  onPointerDown: tapTriggerProps.onPointerDown
26470
26381
  };
26471
- const childElement = React89__default.isValidElement(children) ? children : /* @__PURE__ */ jsx("span", { children });
26382
+ const childElement = React87__default.isValidElement(children) ? children : /* @__PURE__ */ jsx("span", { children });
26472
26383
  const childPointerDown = childElement.props.onPointerDown;
26473
- const triggerElement = React89__default.cloneElement(
26384
+ const triggerElement = React87__default.cloneElement(
26474
26385
  childElement,
26475
26386
  {
26476
26387
  ref: triggerRef,
@@ -27072,9 +26983,9 @@ var init_Tooltip = __esm({
27072
26983
  if (hideTimeoutRef.current) clearTimeout(hideTimeoutRef.current);
27073
26984
  };
27074
26985
  }, []);
27075
- const triggerElement = React89__default.isValidElement(children) ? children : /* @__PURE__ */ jsx("span", { children });
26986
+ const triggerElement = React87__default.isValidElement(children) ? children : /* @__PURE__ */ jsx("span", { children });
27076
26987
  const childPointerDown = triggerElement.props.onPointerDown;
27077
- const trigger = React89__default.cloneElement(triggerElement, {
26988
+ const trigger = React87__default.cloneElement(triggerElement, {
27078
26989
  ref: triggerRef,
27079
26990
  onMouseEnter: handleMouseEnter,
27080
26991
  onMouseLeave: handleMouseLeave,
@@ -27164,7 +27075,7 @@ var init_WizardProgress = __esm({
27164
27075
  children: /* @__PURE__ */ jsx("div", { className: "flex items-center gap-2", children: normalizedSteps.map((step, index) => {
27165
27076
  const isActive = index === currentStep;
27166
27077
  const isCompleted = index < currentStep;
27167
- return /* @__PURE__ */ jsxs(React89__default.Fragment, { children: [
27078
+ return /* @__PURE__ */ jsxs(React87__default.Fragment, { children: [
27168
27079
  /* @__PURE__ */ jsx(
27169
27080
  "button",
27170
27081
  {
@@ -28127,6 +28038,7 @@ var init_ProgressDots = __esm({
28127
28038
  });
28128
28039
  function StatBadge({
28129
28040
  assetUrl,
28041
+ iconUrl,
28130
28042
  label,
28131
28043
  value = 0,
28132
28044
  max,
@@ -28140,6 +28052,7 @@ function StatBadge({
28140
28052
  field: _field
28141
28053
  }) {
28142
28054
  const numValue = typeof value === "number" ? value : parseInt(String(value), 10) || 0;
28055
+ const resolvedAsset = iconUrl ?? assetUrl;
28143
28056
  return /* @__PURE__ */ jsxs(
28144
28057
  "div",
28145
28058
  {
@@ -28150,10 +28063,10 @@ function StatBadge({
28150
28063
  className
28151
28064
  ),
28152
28065
  children: [
28153
- assetUrl ? /* @__PURE__ */ jsx(
28066
+ resolvedAsset ? /* @__PURE__ */ jsx(
28154
28067
  "img",
28155
28068
  {
28156
- src: assetUrl,
28069
+ src: resolvedAsset.url,
28157
28070
  alt: "",
28158
28071
  width: 16,
28159
28072
  height: 16,
@@ -28184,8 +28097,7 @@ function StatBadge({
28184
28097
  ScoreDisplay,
28185
28098
  {
28186
28099
  value: numValue,
28187
- size: size === "lg" ? "md" : "sm",
28188
- animated: true
28100
+ size: size === "lg" ? "md" : "sm"
28189
28101
  }
28190
28102
  ),
28191
28103
  format === "text" && /* @__PURE__ */ jsx("span", { className: "font-bold text-foreground", children: value })
@@ -28228,7 +28140,7 @@ function InventoryGrid({
28228
28140
  const eventBus = useEventBus();
28229
28141
  const slotCount = totalSlots ?? items.length;
28230
28142
  const emptySlotCount = Math.max(0, slotCount - items.length);
28231
- const handleSelect = React89.useCallback(
28143
+ const handleSelect = React87.useCallback(
28232
28144
  (id) => {
28233
28145
  onSelect?.(id);
28234
28146
  if (selectEvent) {
@@ -28335,12 +28247,14 @@ function QuestTracker({
28335
28247
  }
28336
28248
  ),
28337
28249
  /* @__PURE__ */ jsx(Box, { className: "mt-1.5", children: /* @__PURE__ */ jsx(
28338
- ProgressBar,
28250
+ HealthBar,
28339
28251
  {
28340
- value: quest.progress,
28252
+ current: quest.progress,
28341
28253
  max: quest.maxProgress,
28342
- variant: isCompleted ? "success" : isActive ? "primary" : "default",
28343
- size: "sm"
28254
+ format: "bar",
28255
+ size: "sm",
28256
+ animated: true,
28257
+ className: isCompleted ? "[--health-color:var(--color-success)]" : isActive ? "" : "opacity-60"
28344
28258
  }
28345
28259
  ) }),
28346
28260
  /* @__PURE__ */ jsxs(
@@ -28368,7 +28282,7 @@ var init_QuestTracker = __esm({
28368
28282
  "use client";
28369
28283
  init_cn();
28370
28284
  init_WaypointMarker();
28371
- init_ProgressBar();
28285
+ init_HealthBar();
28372
28286
  init_Typography();
28373
28287
  init_Box();
28374
28288
  init_Stack();
@@ -28459,35 +28373,35 @@ function GameCanvas2D({
28459
28373
  tickEvent,
28460
28374
  drawEvent,
28461
28375
  fps = 60,
28462
- backgroundImage = "",
28376
+ backgroundImage,
28463
28377
  assetBaseUrl,
28464
28378
  className
28465
28379
  }) {
28466
- const canvasRef = React89.useRef(null);
28467
- const rafRef = React89.useRef(0);
28468
- const frameRef = React89.useRef(0);
28469
- const lastTimeRef = React89.useRef(0);
28470
- const imageCache = React89.useRef(/* @__PURE__ */ new Map());
28380
+ const canvasRef = React87.useRef(null);
28381
+ const rafRef = React87.useRef(0);
28382
+ const frameRef = React87.useRef(0);
28383
+ const lastTimeRef = React87.useRef(0);
28384
+ const imageCache = React87.useRef(/* @__PURE__ */ new Map());
28471
28385
  const emit = useEmitEvent();
28472
- const onDrawRef = React89.useRef(onDraw);
28386
+ const onDrawRef = React87.useRef(onDraw);
28473
28387
  onDrawRef.current = onDraw;
28474
- const onTickRef = React89.useRef(onTick);
28388
+ const onTickRef = React87.useRef(onTick);
28475
28389
  onTickRef.current = onTick;
28476
- const tickEventRef = React89.useRef(tickEvent);
28390
+ const tickEventRef = React87.useRef(tickEvent);
28477
28391
  tickEventRef.current = tickEvent;
28478
- const drawEventRef = React89.useRef(drawEvent);
28392
+ const drawEventRef = React87.useRef(drawEvent);
28479
28393
  drawEventRef.current = drawEvent;
28480
- const emitRef = React89.useRef(emit);
28394
+ const emitRef = React87.useRef(emit);
28481
28395
  emitRef.current = emit;
28482
- const assetBaseUrlRef = React89.useRef(assetBaseUrl);
28396
+ const assetBaseUrlRef = React87.useRef(assetBaseUrl);
28483
28397
  assetBaseUrlRef.current = assetBaseUrl;
28484
- const backgroundImageRef = React89.useRef(backgroundImage);
28398
+ const backgroundImageRef = React87.useRef(backgroundImage);
28485
28399
  backgroundImageRef.current = backgroundImage;
28486
- const widthRef = React89.useRef(width);
28400
+ const widthRef = React87.useRef(width);
28487
28401
  widthRef.current = width;
28488
- const heightRef = React89.useRef(height);
28402
+ const heightRef = React87.useRef(height);
28489
28403
  heightRef.current = height;
28490
- const loadImage = React89.useCallback((url) => {
28404
+ const loadImage = React87.useCallback((url) => {
28491
28405
  const base = assetBaseUrlRef.current;
28492
28406
  if (!url.startsWith("http") && !base) return null;
28493
28407
  const fullUrl = url.startsWith("http") ? url : `${base}${url}`;
@@ -28501,7 +28415,7 @@ function GameCanvas2D({
28501
28415
  }
28502
28416
  return null;
28503
28417
  }, []);
28504
- React89.useEffect(() => {
28418
+ React87.useEffect(() => {
28505
28419
  const canvas = canvasRef.current;
28506
28420
  if (!canvas) return;
28507
28421
  const ctx = canvas.getContext("2d");
@@ -28523,7 +28437,7 @@ function GameCanvas2D({
28523
28437
  emitRef.current(tickEventRef.current, { dt, frame });
28524
28438
  }
28525
28439
  if (backgroundImageRef.current) {
28526
- const bgImg = loadImage(backgroundImageRef.current);
28440
+ const bgImg = loadImage(backgroundImageRef.current.url);
28527
28441
  if (bgImg) {
28528
28442
  ctx.drawImage(bgImg, 0, 0, widthRef.current, heightRef.current);
28529
28443
  } else {
@@ -28649,26 +28563,14 @@ function HealthPanel({
28649
28563
  )
28650
28564
  }
28651
28565
  ),
28652
- effects && effects.length > 0 && /* @__PURE__ */ jsx(Box, { className: "flex items-center gap-1 flex-wrap", children: effects.map((effect, i) => /* @__PURE__ */ jsxs(
28653
- Badge,
28566
+ effects && effects.length > 0 && /* @__PURE__ */ jsx(Box, { className: "flex items-center gap-1 flex-wrap", children: effects.map((effect, i) => /* @__PURE__ */ jsx(
28567
+ StatusEffect,
28654
28568
  {
28569
+ assetUrl: effect.assetUrl,
28570
+ icon: effect.icon,
28571
+ label: effect.label,
28655
28572
  variant: effectVariantMap[effect.variant ?? "neutral"],
28656
- size: "sm",
28657
- icon: effect.assetUrl ? void 0 : effect.icon,
28658
- children: [
28659
- effect.assetUrl && /* @__PURE__ */ jsx(
28660
- "img",
28661
- {
28662
- src: effect.assetUrl,
28663
- alt: "",
28664
- width: 12,
28665
- height: 12,
28666
- style: { imageRendering: "pixelated", objectFit: "contain" },
28667
- className: "flex-shrink-0 inline-block"
28668
- }
28669
- ),
28670
- effect.label
28671
- ]
28573
+ size: "sm"
28672
28574
  },
28673
28575
  i
28674
28576
  )) })
@@ -28682,17 +28584,17 @@ var init_HealthPanel = __esm({
28682
28584
  "use client";
28683
28585
  init_cn();
28684
28586
  init_HealthBar();
28587
+ init_StatusEffect();
28685
28588
  init_Box();
28686
28589
  init_Typography();
28687
- init_Badge();
28688
28590
  sizeMap18 = {
28689
28591
  sm: { gap: "gap-1", padding: "px-2 py-1.5", text: "text-xs", barSize: "sm" },
28690
28592
  md: { gap: "gap-1.5", padding: "px-3 py-2", text: "text-sm", barSize: "md" },
28691
28593
  lg: { gap: "gap-2", padding: "px-4 py-3", text: "text-base", barSize: "lg" }
28692
28594
  };
28693
28595
  effectVariantMap = {
28694
- buff: "success",
28695
- debuff: "danger",
28596
+ buff: "buff",
28597
+ debuff: "debuff",
28696
28598
  neutral: "neutral"
28697
28599
  };
28698
28600
  HealthPanel.displayName = "HealthPanel";
@@ -28712,13 +28614,13 @@ function ScoreBoard({
28712
28614
  const multiplier = rawMultiplier ?? 1;
28713
28615
  const level = rawLevel ?? 1;
28714
28616
  return /* @__PURE__ */ jsx(
28715
- Card,
28617
+ Box,
28716
28618
  {
28717
28619
  className: cn(
28718
- "bg-[var(--color-card)]/90 border-border backdrop-blur-sm",
28620
+ "rounded-container border border-border bg-[var(--color-card)]/90 backdrop-blur-sm p-3",
28719
28621
  className
28720
28622
  ),
28721
- children: /* @__PURE__ */ jsx(CardContent, { className: "p-3", children: /* @__PURE__ */ jsxs(Box, { className: "flex items-center gap-3 flex-wrap", children: [
28623
+ children: /* @__PURE__ */ jsxs(Box, { className: "flex items-center gap-3 flex-wrap", children: [
28722
28624
  /* @__PURE__ */ jsx(
28723
28625
  StatBadge,
28724
28626
  {
@@ -28760,7 +28662,7 @@ function ScoreBoard({
28760
28662
  }
28761
28663
  ),
28762
28664
  combo != null && combo > 0 && /* @__PURE__ */ jsx(ComboCounter, { combo, multiplier, size: "sm" })
28763
- ] }) })
28665
+ ] })
28764
28666
  }
28765
28667
  );
28766
28668
  }
@@ -28770,7 +28672,6 @@ var init_ScoreBoard = __esm({
28770
28672
  init_cn();
28771
28673
  init_ComboCounter();
28772
28674
  init_StatBadge();
28773
- init_Card();
28774
28675
  init_Box();
28775
28676
  ScoreBoard.displayName = "ScoreBoard";
28776
28677
  }
@@ -28826,7 +28727,7 @@ function TurnPanel({
28826
28727
  className
28827
28728
  }) {
28828
28729
  const eventBus = useEventBus();
28829
- const handleAction = React89.useCallback(
28730
+ const handleAction = React87.useCallback(
28830
28731
  (event) => {
28831
28732
  if (event) {
28832
28733
  eventBus.emit(event, { turn: currentTurn, phase, activeTeam });
@@ -28851,28 +28752,16 @@ function TurnPanel({
28851
28752
  activeTeam
28852
28753
  }
28853
28754
  ),
28854
- actions && actions.length > 0 && /* @__PURE__ */ jsx(Box, { className: "flex items-center gap-1.5 ml-auto", children: actions.map((action, i) => /* @__PURE__ */ jsxs(
28855
- Button,
28755
+ actions && actions.length > 0 && /* @__PURE__ */ jsx(Box, { className: "flex items-center gap-1.5 ml-auto", children: actions.map((action, i) => /* @__PURE__ */ jsx(
28756
+ ActionButton,
28856
28757
  {
28857
- variant: "ghost",
28858
- size: "sm",
28758
+ label: action.label,
28759
+ icon: action.assetUrl ? void 0 : action.icon,
28760
+ assetUrl: action.assetUrl,
28859
28761
  disabled: action.disabled,
28860
- leftIcon: action.assetUrl ? void 0 : action.icon,
28861
- onClick: () => handleAction(action.event),
28862
- children: [
28863
- action.assetUrl && /* @__PURE__ */ jsx(
28864
- "img",
28865
- {
28866
- src: action.assetUrl,
28867
- alt: "",
28868
- width: 14,
28869
- height: 14,
28870
- style: { imageRendering: "pixelated", objectFit: "contain" },
28871
- className: "flex-shrink-0"
28872
- }
28873
- ),
28874
- action.label
28875
- ]
28762
+ variant: "secondary",
28763
+ size: "sm",
28764
+ onClick: () => handleAction(action.event)
28876
28765
  },
28877
28766
  i
28878
28767
  )) })
@@ -28886,7 +28775,7 @@ var init_TurnPanel = __esm({
28886
28775
  "use client";
28887
28776
  init_cn();
28888
28777
  init_TurnIndicator();
28889
- init_Button();
28778
+ init_ActionButton();
28890
28779
  init_Box();
28891
28780
  init_useEventBus();
28892
28781
  DEFAULT_TURN_ACTIONS = [
@@ -28919,7 +28808,7 @@ function EnemyPlate({
28919
28808
  assetUrl && /* @__PURE__ */ jsx(
28920
28809
  "img",
28921
28810
  {
28922
- src: assetUrl,
28811
+ src: assetUrl.url,
28923
28812
  alt: name,
28924
28813
  width: 24,
28925
28814
  height: 24,
@@ -28937,7 +28826,7 @@ function EnemyPlate({
28937
28826
  }
28938
28827
  )
28939
28828
  ] }),
28940
- level != null && /* @__PURE__ */ jsxs(Badge, { variant: "neutral", size: "sm", children: [
28829
+ 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: [
28941
28830
  "Lv.",
28942
28831
  level
28943
28832
  ] })
@@ -28968,12 +28857,12 @@ function EnemyPlate({
28968
28857
  )
28969
28858
  ] }),
28970
28859
  effects && effects.length > 0 && /* @__PURE__ */ jsx(Box, { className: "flex items-center gap-1 flex-wrap", children: effects.map((effect, i) => /* @__PURE__ */ jsx(
28971
- Badge,
28860
+ StatusEffect,
28972
28861
  {
28973
- variant: effectVariantMap2[effect.variant ?? "neutral"],
28974
- size: "sm",
28975
28862
  icon: effect.icon,
28976
- children: effect.label
28863
+ label: effect.label,
28864
+ variant: effectVariantMap2[effect.variant ?? "neutral"],
28865
+ size: "sm"
28977
28866
  },
28978
28867
  i
28979
28868
  )) })
@@ -28987,12 +28876,12 @@ var init_EnemyPlate = __esm({
28987
28876
  "use client";
28988
28877
  init_cn();
28989
28878
  init_HealthBar();
28879
+ init_StatusEffect();
28990
28880
  init_Box();
28991
28881
  init_Typography();
28992
- init_Badge();
28993
28882
  effectVariantMap2 = {
28994
- buff: "success",
28995
- debuff: "danger",
28883
+ buff: "buff",
28884
+ debuff: "debuff",
28996
28885
  neutral: "neutral"
28997
28886
  };
28998
28887
  DEFAULT_ENEMY_EFFECTS = [
@@ -29007,7 +28896,7 @@ function UnitCommandBar({
29007
28896
  className
29008
28897
  }) {
29009
28898
  const eventBus = useEventBus();
29010
- const handleCommand = React89.useCallback(
28899
+ const handleCommand = React87.useCallback(
29011
28900
  (event) => {
29012
28901
  if (event) {
29013
28902
  eventBus.emit(event, { unitId: selectedUnitId });
@@ -29022,27 +28911,18 @@ function UnitCommandBar({
29022
28911
  "flex items-center gap-1.5 rounded-container bg-[var(--color-card)]/90 border border-border backdrop-blur-sm px-2 py-1.5",
29023
28912
  className
29024
28913
  ),
29025
- children: commands.map((command, i) => /* @__PURE__ */ jsxs(Box, { className: "flex flex-col items-center gap-0.5", children: [
29026
- /* @__PURE__ */ jsx(
29027
- Button,
29028
- {
29029
- variant: "ghost",
29030
- size: "sm",
29031
- disabled: command.disabled,
29032
- leftIcon: command.icon,
29033
- onClick: () => handleCommand(command.event),
29034
- children: command.label
29035
- }
29036
- ),
29037
- command.hotkey && /* @__PURE__ */ jsx(
29038
- Typography,
29039
- {
29040
- variant: "caption",
29041
- className: "text-muted-foreground text-xs font-mono",
29042
- children: command.hotkey
29043
- }
29044
- )
29045
- ] }, i))
28914
+ children: commands.map((command, i) => /* @__PURE__ */ jsx(Box, { className: "flex flex-col items-center gap-0.5", children: /* @__PURE__ */ jsx(
28915
+ ActionButton,
28916
+ {
28917
+ label: command.label,
28918
+ icon: command.icon,
28919
+ disabled: command.disabled,
28920
+ hotkey: command.hotkey,
28921
+ variant: "secondary",
28922
+ size: "sm",
28923
+ onClick: () => handleCommand(command.event)
28924
+ }
28925
+ ) }, i))
29046
28926
  }
29047
28927
  );
29048
28928
  }
@@ -29051,9 +28931,8 @@ var init_UnitCommandBar = __esm({
29051
28931
  "components/game/molecules/UnitCommandBar.tsx"() {
29052
28932
  "use client";
29053
28933
  init_cn();
29054
- init_Button();
28934
+ init_ActionButton();
29055
28935
  init_Box();
29056
- init_Typography();
29057
28936
  init_useEventBus();
29058
28937
  DEFAULT_COMMANDS = [
29059
28938
  { label: "Move", icon: "move", event: "MOVE", hotkey: "M" },
@@ -29271,7 +29150,7 @@ function DialogueBox({
29271
29150
  "div",
29272
29151
  {
29273
29152
  className: "fixed inset-0 z-20 bg-center bg-cover bg-no-repeat",
29274
- style: { backgroundImage: `url(${backgroundImage})` },
29153
+ style: { backgroundImage: `url(${backgroundImage?.url})` },
29275
29154
  "aria-hidden": "true"
29276
29155
  }
29277
29156
  ),
@@ -29286,7 +29165,7 @@ function DialogueBox({
29286
29165
  children: /* @__PURE__ */ jsx(
29287
29166
  "img",
29288
29167
  {
29289
- src: portraitUrl,
29168
+ src: portraitUrl?.url,
29290
29169
  alt: dialogue.speaker,
29291
29170
  className: "h-full w-auto object-contain drop-shadow-2xl"
29292
29171
  }
@@ -29558,7 +29437,7 @@ function GameMenu({
29558
29437
  } catch {
29559
29438
  }
29560
29439
  const eventBus = eventBusProp || eventBusFromHook;
29561
- const handleOptionClick = React89.useCallback(
29440
+ const handleOptionClick = React87.useCallback(
29562
29441
  (option) => {
29563
29442
  if (option.event && eventBus) {
29564
29443
  eventBus.emit(`UI:${option.event}`, { option });
@@ -29677,7 +29556,7 @@ function GameOverScreen({
29677
29556
  } catch {
29678
29557
  }
29679
29558
  const eventBus = eventBusProp || eventBusFromHook;
29680
- const handleActionClick = React89.useCallback(
29559
+ const handleActionClick = React87.useCallback(
29681
29560
  (action) => {
29682
29561
  if (action.event && eventBus) {
29683
29562
  eventBus.emit(`UI:${action.event}`, { action });
@@ -29892,6 +29771,7 @@ function PlatformerCanvas({
29892
29771
  rightEvent = "MOVE_RIGHT",
29893
29772
  jumpEvent = "JUMP",
29894
29773
  stopEvent = "STOP",
29774
+ effects = [],
29895
29775
  className
29896
29776
  }) {
29897
29777
  const canvasRef = useRef(null);
@@ -29962,7 +29842,8 @@ function PlatformerCanvas({
29962
29842
  playerSprite,
29963
29843
  tileSprites,
29964
29844
  backgroundImage,
29965
- assetBaseUrl
29845
+ assetBaseUrl,
29846
+ effects
29966
29847
  });
29967
29848
  propsRef.current = {
29968
29849
  platforms,
@@ -29975,7 +29856,8 @@ function PlatformerCanvas({
29975
29856
  playerSprite,
29976
29857
  tileSprites,
29977
29858
  backgroundImage,
29978
- assetBaseUrl
29859
+ assetBaseUrl,
29860
+ effects
29979
29861
  };
29980
29862
  const handleKeyDown = useCallback((e) => {
29981
29863
  if (keysRef.current.has(e.code)) return;
@@ -30042,7 +29924,8 @@ function PlatformerCanvas({
30042
29924
  bgColor: bg,
30043
29925
  playerSprite: pSprite,
30044
29926
  tileSprites: tSprites,
30045
- backgroundImage: bgImg
29927
+ backgroundImage: bgImg,
29928
+ effects: fxList
30046
29929
  } = propsRef.current;
30047
29930
  const auth = playerRef.current;
30048
29931
  const interped = positions.get("player");
@@ -30196,6 +30079,18 @@ function PlatformerCanvas({
30196
30079
  ctx.arc(ppx + eyeOffsetX + 7, eyeY, eyeSize, 0, Math.PI * 2);
30197
30080
  ctx.fill();
30198
30081
  }
30082
+ for (const fx of fxList) {
30083
+ const fxScreenX = fx.x - camX;
30084
+ const fxScreenY = fx.y - camY;
30085
+ const alpha = Math.min(1, fx.ttl / 4);
30086
+ const prev = ctx.globalAlpha;
30087
+ ctx.globalAlpha = alpha;
30088
+ ctx.fillStyle = "#ffe066";
30089
+ ctx.beginPath();
30090
+ ctx.arc(fxScreenX, fxScreenY, 12, 0, Math.PI * 2);
30091
+ ctx.fill();
30092
+ ctx.globalAlpha = prev;
30093
+ }
30199
30094
  };
30200
30095
  return interp.startLoop(drawFrame);
30201
30096
  }, [interp.startLoop, loadImage]);
@@ -30609,13 +30504,13 @@ var init_MapView = __esm({
30609
30504
  shadowSize: [41, 41]
30610
30505
  });
30611
30506
  L.Marker.prototype.options.icon = defaultIcon;
30612
- const { useEffect: useEffect85, useRef: useRef80, useCallback: useCallback127, useState: useState117 } = React89__default;
30507
+ const { useEffect: useEffect83, useRef: useRef80, useCallback: useCallback127, useState: useState115 } = React87__default;
30613
30508
  const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
30614
30509
  const { useEventBus: useEventBus4 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
30615
30510
  function MapUpdater({ centerLat, centerLng, zoom }) {
30616
30511
  const map = useMap();
30617
30512
  const prevRef = useRef80({ centerLat, centerLng, zoom });
30618
- useEffect85(() => {
30513
+ useEffect83(() => {
30619
30514
  const prev = prevRef.current;
30620
30515
  if (prev.centerLat !== centerLat || prev.centerLng !== centerLng || prev.zoom !== zoom) {
30621
30516
  map.setView([centerLat, centerLng], zoom);
@@ -30626,7 +30521,7 @@ var init_MapView = __esm({
30626
30521
  }
30627
30522
  function MapClickHandler({ onMapClick }) {
30628
30523
  const map = useMap();
30629
- useEffect85(() => {
30524
+ useEffect83(() => {
30630
30525
  if (!onMapClick) return;
30631
30526
  const handler = (e) => {
30632
30527
  onMapClick(e.latlng.lat, e.latlng.lng);
@@ -30654,7 +30549,7 @@ var init_MapView = __esm({
30654
30549
  showAttribution = true
30655
30550
  }) {
30656
30551
  const eventBus = useEventBus4();
30657
- const [clickedPosition, setClickedPosition] = useState117(null);
30552
+ const [clickedPosition, setClickedPosition] = useState115(null);
30658
30553
  const handleMapClick = useCallback127((lat, lng) => {
30659
30554
  if (showClickedPin) {
30660
30555
  setClickedPosition({ lat, lng });
@@ -31524,8 +31419,8 @@ function TableView({
31524
31419
  }) {
31525
31420
  const eventBus = useEventBus();
31526
31421
  const { t } = useTranslate();
31527
- const [visibleCount, setVisibleCount] = React89__default.useState(pageSize > 0 ? pageSize : Infinity);
31528
- const [localSelected, setLocalSelected] = React89__default.useState(/* @__PURE__ */ new Set());
31422
+ const [visibleCount, setVisibleCount] = React87__default.useState(pageSize > 0 ? pageSize : Infinity);
31423
+ const [localSelected, setLocalSelected] = React87__default.useState(/* @__PURE__ */ new Set());
31529
31424
  const colDefs = columns ?? fields ?? [];
31530
31425
  const allDataRaw = Array.isArray(entity) ? entity : entity ? [entity] : [];
31531
31426
  const dnd = useDataDnd({
@@ -31720,12 +31615,12 @@ function TableView({
31720
31615
  ]
31721
31616
  }
31722
31617
  );
31723
- return dnd.isZone ? /* @__PURE__ */ jsx(dnd.SortableItem, { id: row[idField] ?? id, children: rowInner }, id) : /* @__PURE__ */ jsx(React89__default.Fragment, { children: rowInner }, id);
31618
+ return dnd.isZone ? /* @__PURE__ */ jsx(dnd.SortableItem, { id: row[idField] ?? id, children: rowInner }, id) : /* @__PURE__ */ jsx(React87__default.Fragment, { children: rowInner }, id);
31724
31619
  };
31725
31620
  const items = Array.from(data);
31726
31621
  const groups = groupBy ? groupData2(items, groupBy) : [{ label: "", items }];
31727
31622
  let runningIndex = 0;
31728
- const body = /* @__PURE__ */ jsx(Box, { role: "rowgroup", children: groups.map((group, gi) => /* @__PURE__ */ jsxs(React89__default.Fragment, { children: [
31623
+ const body = /* @__PURE__ */ jsx(Box, { role: "rowgroup", children: groups.map((group, gi) => /* @__PURE__ */ jsxs(React87__default.Fragment, { children: [
31729
31624
  group.label && /* @__PURE__ */ jsx(Divider, { label: group.label, className: gi > 0 ? "mt-3" : "mt-0" }),
31730
31625
  group.items.map((row) => renderRow(row, runningIndex++))
31731
31626
  ] }, gi)) });
@@ -33082,7 +32977,7 @@ var init_StepFlow = __esm({
33082
32977
  className
33083
32978
  }) => {
33084
32979
  if (orientation === "vertical") {
33085
- return /* @__PURE__ */ jsx(VStack, { gap: "none", className: cn("w-full", className), children: steps.map((step, index) => /* @__PURE__ */ jsx(React89__default.Fragment, { children: /* @__PURE__ */ jsxs(HStack, { gap: "md", align: "start", className: "w-full", children: [
32980
+ return /* @__PURE__ */ jsx(VStack, { gap: "none", className: cn("w-full", className), children: steps.map((step, index) => /* @__PURE__ */ jsx(React87__default.Fragment, { children: /* @__PURE__ */ jsxs(HStack, { gap: "md", align: "start", className: "w-full", children: [
33086
32981
  /* @__PURE__ */ jsxs(VStack, { gap: "none", align: "center", children: [
33087
32982
  /* @__PURE__ */ jsx(StepCircle, { step, index }),
33088
32983
  showConnectors && index < steps.length - 1 && /* @__PURE__ */ jsx(Box, { className: "w-px h-8 bg-border" })
@@ -33093,7 +32988,7 @@ var init_StepFlow = __esm({
33093
32988
  ] })
33094
32989
  ] }) }, index)) });
33095
32990
  }
33096
- 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(React89__default.Fragment, { children: [
32991
+ 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(React87__default.Fragment, { children: [
33097
32992
  /* @__PURE__ */ jsxs(VStack, { gap: "sm", align: "center", className: "flex-1 w-full md:w-auto", children: [
33098
32993
  /* @__PURE__ */ jsx(StepCircle, { step, index }),
33099
32994
  /* @__PURE__ */ jsx(Typography, { variant: "h4", className: "text-center", children: step.title }),
@@ -34078,7 +33973,7 @@ var init_LikertScale = __esm({
34078
33973
  md: "text-base",
34079
33974
  lg: "text-lg"
34080
33975
  };
34081
- LikertScale = React89__default.forwardRef(
33976
+ LikertScale = React87__default.forwardRef(
34082
33977
  ({
34083
33978
  question,
34084
33979
  options = DEFAULT_LIKERT_OPTIONS,
@@ -34090,7 +33985,7 @@ var init_LikertScale = __esm({
34090
33985
  variant = "radios",
34091
33986
  className
34092
33987
  }, ref) => {
34093
- const groupId = React89__default.useId();
33988
+ const groupId = React87__default.useId();
34094
33989
  const eventBus = useEventBus();
34095
33990
  const handleSelect = useCallback(
34096
33991
  (next) => {
@@ -36372,7 +36267,7 @@ var init_DocBreadcrumb = __esm({
36372
36267
  "aria-label": t("aria.breadcrumb"),
36373
36268
  children: /* @__PURE__ */ jsx(HStack, { gap: "xs", align: "center", wrap: true, children: items.map((item, idx) => {
36374
36269
  const isLast = idx === items.length - 1;
36375
- return /* @__PURE__ */ jsxs(React89__default.Fragment, { children: [
36270
+ return /* @__PURE__ */ jsxs(React87__default.Fragment, { children: [
36376
36271
  idx > 0 && /* @__PURE__ */ jsx(
36377
36272
  Icon,
36378
36273
  {
@@ -37241,7 +37136,7 @@ var init_MiniStateMachine = __esm({
37241
37136
  const x = 2 + i * (NODE_W + GAP + ARROW_W + GAP);
37242
37137
  const tc = transitionCounts[s.name] ?? 0;
37243
37138
  const role = getStateRole(s.name, s.isInitial ?? void 0, s.isTerminal ?? void 0, tc, maxTC);
37244
- return /* @__PURE__ */ jsxs(React89__default.Fragment, { children: [
37139
+ return /* @__PURE__ */ jsxs(React87__default.Fragment, { children: [
37245
37140
  /* @__PURE__ */ jsx(
37246
37141
  AvlState,
37247
37142
  {
@@ -37445,7 +37340,7 @@ var init_PageHeader = __esm({
37445
37340
  info: "bg-info/10 text-info"
37446
37341
  };
37447
37342
  return /* @__PURE__ */ jsxs(Box, { className: cn("mb-6", className), children: [
37448
- 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(React89__default.Fragment, { children: [
37343
+ 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(React87__default.Fragment, { children: [
37449
37344
  idx > 0 && /* @__PURE__ */ jsx(Typography, { variant: "small", color: "muted", children: "/" }),
37450
37345
  crumb.href ? /* @__PURE__ */ jsx(
37451
37346
  "a",
@@ -37803,7 +37698,7 @@ var init_Section = __esm({
37803
37698
  as: Component2 = "section"
37804
37699
  }) => {
37805
37700
  const hasHeader = title || description || action;
37806
- return React89__default.createElement(
37701
+ return React87__default.createElement(
37807
37702
  Component2,
37808
37703
  {
37809
37704
  className: cn(
@@ -38171,7 +38066,7 @@ var init_WizardContainer = __esm({
38171
38066
  const isCompleted = index < currentStep;
38172
38067
  const stepKey = step.id ?? step.tabId ?? `step-${index}`;
38173
38068
  const stepTitle = step.title ?? step.name ?? `Step ${index + 1}`;
38174
- return /* @__PURE__ */ jsxs(React89__default.Fragment, { children: [
38069
+ return /* @__PURE__ */ jsxs(React87__default.Fragment, { children: [
38175
38070
  /* @__PURE__ */ jsx(
38176
38071
  Button,
38177
38072
  {
@@ -40750,7 +40645,7 @@ var init_DetailPanel = __esm({
40750
40645
  }
40751
40646
  });
40752
40647
  function extractTitle(children) {
40753
- if (!React89__default.isValidElement(children)) return void 0;
40648
+ if (!React87__default.isValidElement(children)) return void 0;
40754
40649
  const props = children.props;
40755
40650
  if (typeof props.title === "string") {
40756
40651
  return props.title;
@@ -40805,7 +40700,7 @@ function LinearView({
40805
40700
  /* @__PURE__ */ jsx(HStack, { className: "flex-wrap items-center", gap: "xs", children: trait.states.map((state, i) => {
40806
40701
  const isDone = i < currentIdx;
40807
40702
  const isCurrent = i === currentIdx;
40808
- return /* @__PURE__ */ jsxs(React89__default.Fragment, { children: [
40703
+ return /* @__PURE__ */ jsxs(React87__default.Fragment, { children: [
40809
40704
  i > 0 && /* @__PURE__ */ jsx(
40810
40705
  Typography,
40811
40706
  {
@@ -41576,7 +41471,6 @@ var init_FeatureGridOrganism = __esm({
41576
41471
  });
41577
41472
  function FishingBoard({
41578
41473
  backgroundImage,
41579
- assetBaseUrl,
41580
41474
  scale = 1,
41581
41475
  showMinimap = false,
41582
41476
  enableCamera = true,
@@ -41594,8 +41488,7 @@ function FishingBoard({
41594
41488
  {
41595
41489
  width,
41596
41490
  height,
41597
- backgroundImage: backgroundImage ?? "",
41598
- assetBaseUrl,
41491
+ backgroundImage,
41599
41492
  fps: 60,
41600
41493
  className: "w-full h-full"
41601
41494
  }
@@ -41791,12 +41684,12 @@ var init_Form = __esm({
41791
41684
  const isSchemaEntity = isOrbitalEntitySchema(entity);
41792
41685
  const resolvedEntity = isSchemaEntity ? entity : void 0;
41793
41686
  const entityName = typeof entity === "string" ? entity : resolvedEntity?.name;
41794
- const normalizedInitialData = React89__default.useMemo(() => {
41687
+ const normalizedInitialData = React87__default.useMemo(() => {
41795
41688
  const entityRowAsInitial = isPlainEntityRow(entity) ? entity : void 0;
41796
41689
  const callerInitial = initialData !== null && typeof initialData === "object" && !Array.isArray(initialData) ? initialData : {};
41797
41690
  return entityRowAsInitial !== void 0 ? { ...entityRowAsInitial, ...callerInitial } : callerInitial;
41798
41691
  }, [entity, initialData]);
41799
- const entityDerivedFields = React89__default.useMemo(() => {
41692
+ const entityDerivedFields = React87__default.useMemo(() => {
41800
41693
  if (fields && fields.length > 0) return void 0;
41801
41694
  if (!resolvedEntity) return void 0;
41802
41695
  return resolvedEntity.fields.map(
@@ -41817,16 +41710,16 @@ var init_Form = __esm({
41817
41710
  const conditionalFields = typeof conditionalFieldsRaw === "boolean" ? {} : conditionalFieldsRaw;
41818
41711
  const hiddenCalculations = typeof hiddenCalculationsRaw === "boolean" ? [] : hiddenCalculationsRaw;
41819
41712
  const violationTriggers = typeof violationTriggersRaw === "boolean" ? [] : violationTriggersRaw;
41820
- const [formData, setFormData] = React89__default.useState(
41713
+ const [formData, setFormData] = React87__default.useState(
41821
41714
  normalizedInitialData
41822
41715
  );
41823
- const [collapsedSections, setCollapsedSections] = React89__default.useState(
41716
+ const [collapsedSections, setCollapsedSections] = React87__default.useState(
41824
41717
  /* @__PURE__ */ new Set()
41825
41718
  );
41826
- const [submitError, setSubmitError] = React89__default.useState(null);
41827
- const formRef = React89__default.useRef(null);
41719
+ const [submitError, setSubmitError] = React87__default.useState(null);
41720
+ const formRef = React87__default.useRef(null);
41828
41721
  const formMode = props.mode;
41829
- const mountedRef = React89__default.useRef(false);
41722
+ const mountedRef = React87__default.useRef(false);
41830
41723
  if (!mountedRef.current) {
41831
41724
  mountedRef.current = true;
41832
41725
  debug("forms", "mount", {
@@ -41839,7 +41732,7 @@ var init_Form = __esm({
41839
41732
  });
41840
41733
  }
41841
41734
  const shouldShowCancel = showCancel ?? (fields && fields.length > 0);
41842
- const evalContext = React89__default.useMemo(
41735
+ const evalContext = React87__default.useMemo(
41843
41736
  () => ({
41844
41737
  formValues: formData,
41845
41738
  globalVariables: externalContext?.globalVariables ?? {},
@@ -41848,7 +41741,7 @@ var init_Form = __esm({
41848
41741
  }),
41849
41742
  [formData, externalContext]
41850
41743
  );
41851
- React89__default.useEffect(() => {
41744
+ React87__default.useEffect(() => {
41852
41745
  debug("forms", "initialData-sync", {
41853
41746
  mode: formMode,
41854
41747
  normalizedInitialData,
@@ -41859,7 +41752,7 @@ var init_Form = __esm({
41859
41752
  setFormData(normalizedInitialData);
41860
41753
  }
41861
41754
  }, [normalizedInitialData]);
41862
- const processCalculations = React89__default.useCallback(
41755
+ const processCalculations = React87__default.useCallback(
41863
41756
  (changedFieldId, newFormData) => {
41864
41757
  if (!hiddenCalculations.length) return;
41865
41758
  const context = {
@@ -41884,7 +41777,7 @@ var init_Form = __esm({
41884
41777
  },
41885
41778
  [hiddenCalculations, externalContext, eventBus]
41886
41779
  );
41887
- const checkViolations = React89__default.useCallback(
41780
+ const checkViolations = React87__default.useCallback(
41888
41781
  (changedFieldId, newFormData) => {
41889
41782
  if (!violationTriggers.length) return;
41890
41783
  const context = {
@@ -41922,7 +41815,7 @@ var init_Form = __esm({
41922
41815
  processCalculations(name, newFormData);
41923
41816
  checkViolations(name, newFormData);
41924
41817
  };
41925
- const isFieldVisible = React89__default.useCallback(
41818
+ const isFieldVisible = React87__default.useCallback(
41926
41819
  (fieldName) => {
41927
41820
  const condition = conditionalFields[fieldName];
41928
41821
  if (!condition) return true;
@@ -41930,7 +41823,7 @@ var init_Form = __esm({
41930
41823
  },
41931
41824
  [conditionalFields, evalContext]
41932
41825
  );
41933
- const isSectionVisible = React89__default.useCallback(
41826
+ const isSectionVisible = React87__default.useCallback(
41934
41827
  (section) => {
41935
41828
  if (!section.condition) return true;
41936
41829
  return Boolean(evaluateFormExpression(section.condition, evalContext));
@@ -42006,7 +41899,7 @@ var init_Form = __esm({
42006
41899
  eventBus.emit(`UI:${onCancel}`);
42007
41900
  }
42008
41901
  };
42009
- const renderField = React89__default.useCallback(
41902
+ const renderField = React87__default.useCallback(
42010
41903
  (field) => {
42011
41904
  const fieldName = field.name || field.field;
42012
41905
  if (!fieldName) return null;
@@ -42027,7 +41920,7 @@ var init_Form = __esm({
42027
41920
  [formData, isFieldVisible, relationsData, relationsLoading, isLoading]
42028
41921
  );
42029
41922
  const effectiveFields = entityDerivedFields ?? fields;
42030
- const normalizedFields = React89__default.useMemo(() => {
41923
+ const normalizedFields = React87__default.useMemo(() => {
42031
41924
  if (!effectiveFields || effectiveFields.length === 0) return [];
42032
41925
  return effectiveFields.map((field) => {
42033
41926
  if (typeof field === "string") {
@@ -42051,7 +41944,7 @@ var init_Form = __esm({
42051
41944
  return field;
42052
41945
  });
42053
41946
  }, [effectiveFields, resolvedEntity]);
42054
- const schemaFields = React89__default.useMemo(() => {
41947
+ const schemaFields = React87__default.useMemo(() => {
42055
41948
  if (normalizedFields.length === 0) return null;
42056
41949
  if (isDebugEnabled()) {
42057
41950
  debugGroup(`Form: ${entityName || "unknown"}`);
@@ -42061,7 +41954,7 @@ var init_Form = __esm({
42061
41954
  }
42062
41955
  return normalizedFields.map(renderField).filter(Boolean);
42063
41956
  }, [normalizedFields, renderField, entityName, conditionalFields]);
42064
- const sectionElements = React89__default.useMemo(() => {
41957
+ const sectionElements = React87__default.useMemo(() => {
42065
41958
  if (!sections || sections.length === 0) return null;
42066
41959
  return sections.map((section) => {
42067
41960
  if (!isSectionVisible(section)) {
@@ -43582,7 +43475,6 @@ var init_GameCanvas3D2 = __esm({
43582
43475
  className,
43583
43476
  isLoading: externalLoading,
43584
43477
  error: externalError,
43585
- entity,
43586
43478
  preloadAssets = [],
43587
43479
  tileClickEvent,
43588
43480
  unitClickEvent,
@@ -43815,7 +43707,7 @@ var init_GameCanvas3D2 = __esm({
43815
43707
  children: /* @__PURE__ */ jsx(
43816
43708
  ModelLoader,
43817
43709
  {
43818
- url: tile.modelUrl,
43710
+ url: tile.modelUrl.url,
43819
43711
  scale: 0.95,
43820
43712
  fallbackGeometry: "box",
43821
43713
  castShadow: true,
@@ -43880,7 +43772,7 @@ var init_GameCanvas3D2 = __esm({
43880
43772
  /* @__PURE__ */ jsx(
43881
43773
  ModelLoader,
43882
43774
  {
43883
- url: unit.modelUrl,
43775
+ url: unit.modelUrl.url,
43884
43776
  scale: modelScale,
43885
43777
  fallbackGeometry: "box",
43886
43778
  castShadow: true
@@ -43940,7 +43832,7 @@ var init_GameCanvas3D2 = __esm({
43940
43832
  return /* @__PURE__ */ jsx(
43941
43833
  ModelLoader,
43942
43834
  {
43943
- url: feature.assetUrl,
43835
+ url: feature.assetUrl.url,
43944
43836
  position,
43945
43837
  scale: 0.5,
43946
43838
  rotation: [0, feature.rotation ?? 0, 0],
@@ -44161,7 +44053,18 @@ function GameBoard3D({
44161
44053
  const row = boardEntity(entity);
44162
44054
  const eventBus = useEventBus();
44163
44055
  const entityUnits = row ? rows(row.units) : [];
44164
- const units = entityUnits;
44056
+ const units = entityUnits.map((r) => ({
44057
+ id: str(r.id),
44058
+ x: num(r.x),
44059
+ y: num(r.y),
44060
+ z: num(r.z),
44061
+ faction: str(r.faction) || "neutral",
44062
+ team: str(r.team) || str(r.faction) || "neutral",
44063
+ unitType: r.unitType == null ? void 0 : str(r.unitType),
44064
+ name: r.name == null ? void 0 : str(r.name),
44065
+ health: r.health == null ? void 0 : num(r.health),
44066
+ maxHealth: r.maxHealth == null ? void 0 : num(r.maxHealth)
44067
+ }));
44165
44068
  const selectedUnitId = row ? str(row.selectedUnitId) || null : null;
44166
44069
  const phase = row ? str(row.phase) : "observation";
44167
44070
  const result = row ? str(row.result) : "none";
@@ -44318,7 +44221,7 @@ var init_GameBoard3D = __esm({
44318
44221
  }
44319
44222
  });
44320
44223
  function asDescriptor(v) {
44321
- if (Array.isArray(v) || React89__default.isValidElement(v)) return null;
44224
+ if (Array.isArray(v) || React87__default.isValidElement(v)) return null;
44322
44225
  const o = v;
44323
44226
  if (typeof o.type !== "string") return null;
44324
44227
  const props = o.props !== void 0 && typeof o.props === "object" && !Array.isArray(o.props) && o.props !== null ? o.props : void 0;
@@ -44333,10 +44236,10 @@ function getSlotContentRenderer2() {
44333
44236
  }
44334
44237
  function resolveDescriptor(value, idPrefix) {
44335
44238
  if (value === null || value === void 0) return value;
44336
- if (React89__default.isValidElement(value)) return value;
44239
+ if (React87__default.isValidElement(value)) return value;
44337
44240
  if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") return value;
44338
44241
  if (Array.isArray(value)) {
44339
- return value.map((item, i) => /* @__PURE__ */ jsx(React89__default.Fragment, { children: resolveDescriptor(item, `${idPrefix}-${i}`) }, i));
44242
+ return value.map((item, i) => /* @__PURE__ */ jsx(React87__default.Fragment, { children: resolveDescriptor(item, `${idPrefix}-${i}`) }, i));
44340
44243
  }
44341
44244
  if (typeof value === "object" && value !== null) {
44342
44245
  const desc = asDescriptor(value);
@@ -44436,10 +44339,10 @@ function getSlotContentRenderer3() {
44436
44339
  }
44437
44340
  function resolveDescriptor2(value, idPrefix) {
44438
44341
  if (value === null || value === void 0) return value;
44439
- if (React89__default.isValidElement(value)) return value;
44342
+ if (React87__default.isValidElement(value)) return value;
44440
44343
  if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") return value;
44441
44344
  if (Array.isArray(value)) {
44442
- return value.map((item, i) => /* @__PURE__ */ jsx(React89__default.Fragment, { children: resolveDescriptor2(item, `${idPrefix}-${i}`) }, i));
44345
+ return value.map((item, i) => /* @__PURE__ */ jsx(React87__default.Fragment, { children: resolveDescriptor2(item, `${idPrefix}-${i}`) }, i));
44443
44346
  }
44444
44347
  if (typeof value === "object") {
44445
44348
  const rec = value;
@@ -44756,7 +44659,6 @@ function HexStrategyBoard({
44756
44659
  units,
44757
44660
  features,
44758
44661
  assetManifest,
44759
- assetBaseUrl,
44760
44662
  scale,
44761
44663
  showMinimap,
44762
44664
  enableCamera,
@@ -44798,7 +44700,6 @@ function HolidayRunnerBoard({
44798
44700
  units,
44799
44701
  features,
44800
44702
  assetManifest,
44801
- assetBaseUrl,
44802
44703
  scale,
44803
44704
  showMinimap,
44804
44705
  enableCamera,
@@ -45152,7 +45053,7 @@ var init_List = __esm({
45152
45053
  if (entity && typeof entity === "object" && "id" in entity) return [entity];
45153
45054
  return [];
45154
45055
  }, [entity]);
45155
- const getItemActions = React89__default.useCallback(
45056
+ const getItemActions = React87__default.useCallback(
45156
45057
  (item) => {
45157
45058
  if (!itemActions) return [];
45158
45059
  if (typeof itemActions === "function") {
@@ -45593,7 +45494,6 @@ function MatchPuzzleBoard({
45593
45494
  units,
45594
45495
  features,
45595
45496
  assetManifest,
45596
- assetBaseUrl,
45597
45497
  scale,
45598
45498
  showMinimap,
45599
45499
  enableCamera,
@@ -45669,7 +45569,7 @@ var init_MediaGallery = __esm({
45669
45569
  [selectable, selectedItems, selectionEvent, eventBus]
45670
45570
  );
45671
45571
  const entityData = Array.isArray(entity) ? entity : [];
45672
- const items = React89__default.useMemo(() => {
45572
+ const items = React87__default.useMemo(() => {
45673
45573
  if (propItems) return propItems;
45674
45574
  if (entityData.length === 0) return [];
45675
45575
  return entityData.map((record, idx) => {
@@ -45854,7 +45754,6 @@ function MinigolfBoard({
45854
45754
  units,
45855
45755
  features,
45856
45756
  assetManifest,
45857
- assetBaseUrl,
45858
45757
  scale,
45859
45758
  showMinimap,
45860
45759
  enableCamera,
@@ -45874,7 +45773,7 @@ var init_MinigolfBoard = __esm({
45874
45773
  }
45875
45774
  });
45876
45775
  function extractTitle2(children) {
45877
- if (!React89__default.isValidElement(children)) return void 0;
45776
+ if (!React87__default.isValidElement(children)) return void 0;
45878
45777
  const props = children.props;
45879
45778
  if (typeof props.title === "string") {
45880
45779
  return props.title;
@@ -46160,7 +46059,6 @@ function PirateBoard({
46160
46059
  units,
46161
46060
  features,
46162
46061
  assetManifest,
46163
- assetBaseUrl,
46164
46062
  scale,
46165
46063
  showMinimap,
46166
46064
  enableCamera,
@@ -46281,8 +46179,8 @@ function PlatformerBoard({
46281
46179
  canvasHeight,
46282
46180
  followCamera: true,
46283
46181
  bgColor,
46284
- playerSprite,
46285
- tileSprites,
46182
+ playerSprite: playerSprite?.url,
46183
+ tileSprites: tileSprites ? Object.fromEntries(Object.entries(tileSprites).map(([k, a]) => [k, a.url])) : void 0,
46286
46184
  leftEvent,
46287
46185
  rightEvent,
46288
46186
  jumpEvent,
@@ -46347,7 +46245,7 @@ function PlatformerTemplate({
46347
46245
  worldHeight = 400,
46348
46246
  canvasWidth = 800,
46349
46247
  canvasHeight = 400,
46350
- playerSprite = `${CDN3}/characters/platformChar_idle.png`,
46248
+ playerSprite = makeAsset(`${CDN3}/characters/platformChar_idle.png`, "player"),
46351
46249
  tileSprites = DEFAULT_TILE_SPRITES,
46352
46250
  bgColor = "#5c94fc",
46353
46251
  gameEndEvent = "GAME_END",
@@ -46400,13 +46298,14 @@ var init_PlatformerTemplate = __esm({
46400
46298
  init_PlatformerBoard();
46401
46299
  init_GameHud();
46402
46300
  init_ScoreBoard();
46301
+ init_makeAsset();
46403
46302
  CDN3 = "https://almadar-kflow-assets.web.app/shared/platformer";
46404
- DEFAULT_TILE_SPRITES = {
46303
+ DEFAULT_TILE_SPRITES = makeAssetMap({
46405
46304
  ground: `${CDN3}/tiles/platformPack_tile001.png`,
46406
46305
  platform: `${CDN3}/tiles/platformPack_tile004.png`,
46407
46306
  hazard: `${CDN3}/tiles/platformPack_tile017.png`,
46408
46307
  goal: `${CDN3}/tiles/platformPack_tile007.png`
46409
- };
46308
+ }, "tile");
46410
46309
  DEFAULT_PLATFORMS = [
46411
46310
  { x: 0, y: 368, width: 800, height: 32, type: "ground" },
46412
46311
  { x: 150, y: 280, width: 160, height: 16, type: "platform" },
@@ -46562,7 +46461,6 @@ function RacingBoard({
46562
46461
  units,
46563
46462
  features,
46564
46463
  assetManifest,
46565
- assetBaseUrl,
46566
46464
  scale,
46567
46465
  showMinimap,
46568
46466
  enableCamera,
@@ -46581,27 +46479,18 @@ var init_RacingBoard = __esm({
46581
46479
  RacingBoard.displayName = "RacingBoard";
46582
46480
  }
46583
46481
  });
46584
- function resolveManifestUrl3(manifest, relative) {
46585
- if (relative == null) return void 0;
46586
- if (/^https?:\/\//.test(relative)) return relative;
46587
- const base = manifest?.baseUrl;
46588
- if (base == null) return relative;
46589
- const cleanBase = base.replace(/\/$/, "");
46590
- const cleanRel = relative.replace(/^\//, "");
46591
- return `${cleanBase}/${cleanRel}`;
46592
- }
46593
46482
  function dungeonTerrain(x, y, stairsX, stairsY, manifest) {
46594
46483
  const isBorder = x === 0 || y === 0 || x === DUNGEON_GRID_W - 1 || y === DUNGEON_GRID_H - 1;
46595
46484
  const isPillar = x % 4 === 0 && y % 4 === 0 && !isBorder;
46596
46485
  const isWall = isBorder || isPillar;
46597
46486
  const terrains = manifest?.terrains;
46598
46487
  if (x === stairsX && y === stairsY) {
46599
- return { terrain: "stairs", passable: true, terrainSprite: resolveManifestUrl3(manifest, terrains?.stairs) };
46488
+ return { terrain: "stairs", passable: true, terrainSprite: terrains?.stairs };
46600
46489
  }
46601
46490
  if (isWall) {
46602
- return { terrain: "wall", passable: false, terrainSprite: resolveManifestUrl3(manifest, terrains?.wall) };
46491
+ return { terrain: "wall", passable: false, terrainSprite: terrains?.wall };
46603
46492
  }
46604
- return { terrain: "floor", passable: true, terrainSprite: resolveManifestUrl3(manifest, terrains?.floor) };
46493
+ return { terrain: "floor", passable: true, terrainSprite: terrains?.floor };
46605
46494
  }
46606
46495
  function buildDefaultDungeonTiles(stairsX, stairsY, manifest) {
46607
46496
  const tiles = [];
@@ -46645,7 +46534,7 @@ function RoguelikeBoard({
46645
46534
  x: num(r.x),
46646
46535
  y: num(r.y),
46647
46536
  terrain: r.terrain == null ? void 0 : str(r.terrain),
46648
- terrainSprite: r.terrainSprite == null ? void 0 : str(r.terrainSprite),
46537
+ terrainSprite: r.terrainSprite == null ? void 0 : makeAsset(str(r.terrainSprite), "tile"),
46649
46538
  passable: r.passable !== false
46650
46539
  })),
46651
46540
  [board.tiles]
@@ -46725,7 +46614,7 @@ function RoguelikeBoard({
46725
46614
  health: playerHp,
46726
46615
  maxHealth: playerMaxHp,
46727
46616
  unitType: "player",
46728
- sprite: resolveManifestUrl3(assetManifest, assetManifest?.units?.player)
46617
+ sprite: assetManifest?.units?.player
46729
46618
  },
46730
46619
  ...liveEnemies.map((e) => ({
46731
46620
  id: e.id,
@@ -46735,7 +46624,7 @@ function RoguelikeBoard({
46735
46624
  health: e.hp,
46736
46625
  maxHealth: 6,
46737
46626
  unitType: "enemy",
46738
- sprite: resolveManifestUrl3(assetManifest, assetManifest?.units?.enemy)
46627
+ sprite: assetManifest?.units?.enemy
46739
46628
  }))
46740
46629
  ];
46741
46630
  }, [player, enemies, playerHp, playerMaxHp, assetManifest, t]);
@@ -46745,7 +46634,7 @@ function RoguelikeBoard({
46745
46634
  x: it.x,
46746
46635
  y: it.y,
46747
46636
  type: it.kind,
46748
- sprite: resolveManifestUrl3(assetManifest, assetManifest?.features?.[it.kind])
46637
+ sprite: assetManifest?.features?.[it.kind]
46749
46638
  })),
46750
46639
  [items, assetManifest]
46751
46640
  );
@@ -46806,7 +46695,6 @@ function RoguelikeBoard({
46806
46695
  onTileHover: (x, y) => setHoveredTile({ x, y }),
46807
46696
  onTileLeave: () => setHoveredTile(null),
46808
46697
  scale,
46809
- assetBaseUrl: assetManifest?.baseUrl,
46810
46698
  assetManifest,
46811
46699
  unitScale,
46812
46700
  spriteHeightRatio,
@@ -46866,6 +46754,7 @@ var init_RoguelikeBoard = __esm({
46866
46754
  init_Stack();
46867
46755
  init_IsometricCanvas();
46868
46756
  init_boardEntity();
46757
+ init_makeAsset();
46869
46758
  DUNGEON_GRID_W = 16;
46870
46759
  DUNGEON_GRID_H = 16;
46871
46760
  DEFAULT_ENEMIES = [
@@ -46916,55 +46805,59 @@ function RoguelikeTemplate({
46916
46805
  }
46917
46806
  );
46918
46807
  }
46919
- var CDN4, DEFAULT_ROGUELIKE_TILES, DEFAULT_ROGUELIKE_MANIFEST;
46808
+ var CDN4, wall, floor, tiles2, stairs, DEFAULT_ROGUELIKE_TILES, DEFAULT_ROGUELIKE_MANIFEST;
46920
46809
  var init_RoguelikeTemplate = __esm({
46921
46810
  "components/game/templates/RoguelikeTemplate.tsx"() {
46922
46811
  init_RoguelikeBoard();
46812
+ init_makeAsset();
46923
46813
  CDN4 = "https://almadar-kflow-assets.web.app/shared";
46814
+ wall = makeAsset(`${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png`, "tile");
46815
+ floor = makeAsset(`${CDN4}/isometric-dungeon/Isometric/dirt_E.png`, "tile");
46816
+ tiles2 = makeAsset(`${CDN4}/isometric-dungeon/Isometric/dirtTiles_E.png`, "tile");
46817
+ stairs = makeAsset(`${CDN4}/isometric-dungeon/Isometric/stairs_E.png`, "tile");
46924
46818
  DEFAULT_ROGUELIKE_TILES = [
46925
- { x: 0, y: 0, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
46926
- { x: 1, y: 0, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
46927
- { x: 2, y: 0, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
46928
- { x: 3, y: 0, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
46929
- { x: 4, y: 0, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
46930
- { x: 0, y: 1, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
46931
- { x: 1, y: 1, terrain: "floor", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/dirt_E.png` },
46932
- { x: 2, y: 1, terrain: "floor", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/dirt_E.png` },
46933
- { x: 3, y: 1, terrain: "floor", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/dirt_E.png` },
46934
- { x: 4, y: 1, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
46935
- { x: 0, y: 2, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
46936
- { x: 1, y: 2, terrain: "floor", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/dirtTiles_E.png` },
46937
- { x: 2, y: 2, terrain: "floor", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/dirtTiles_E.png` },
46938
- { x: 3, y: 2, terrain: "floor", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/dirt_E.png` },
46939
- { x: 4, y: 2, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
46940
- { x: 0, y: 3, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
46941
- { x: 1, y: 3, terrain: "floor", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/dirt_E.png` },
46942
- { x: 2, y: 3, terrain: "floor", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/dirtTiles_E.png` },
46943
- { x: 3, y: 3, terrain: "stairs", passable: true, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stairs_E.png` },
46944
- { x: 4, y: 3, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
46945
- { x: 0, y: 4, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
46946
- { x: 1, y: 4, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
46947
- { x: 2, y: 4, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
46948
- { x: 3, y: 4, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` },
46949
- { x: 4, y: 4, terrain: "wall", passable: false, terrainSprite: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png` }
46819
+ { x: 0, y: 0, terrain: "wall", passable: false, terrainSprite: wall },
46820
+ { x: 1, y: 0, terrain: "wall", passable: false, terrainSprite: wall },
46821
+ { x: 2, y: 0, terrain: "wall", passable: false, terrainSprite: wall },
46822
+ { x: 3, y: 0, terrain: "wall", passable: false, terrainSprite: wall },
46823
+ { x: 4, y: 0, terrain: "wall", passable: false, terrainSprite: wall },
46824
+ { x: 0, y: 1, terrain: "wall", passable: false, terrainSprite: wall },
46825
+ { x: 1, y: 1, terrain: "floor", passable: true, terrainSprite: floor },
46826
+ { x: 2, y: 1, terrain: "floor", passable: true, terrainSprite: floor },
46827
+ { x: 3, y: 1, terrain: "floor", passable: true, terrainSprite: floor },
46828
+ { x: 4, y: 1, terrain: "wall", passable: false, terrainSprite: wall },
46829
+ { x: 0, y: 2, terrain: "wall", passable: false, terrainSprite: wall },
46830
+ { x: 1, y: 2, terrain: "floor", passable: true, terrainSprite: tiles2 },
46831
+ { x: 2, y: 2, terrain: "floor", passable: true, terrainSprite: tiles2 },
46832
+ { x: 3, y: 2, terrain: "floor", passable: true, terrainSprite: floor },
46833
+ { x: 4, y: 2, terrain: "wall", passable: false, terrainSprite: wall },
46834
+ { x: 0, y: 3, terrain: "wall", passable: false, terrainSprite: wall },
46835
+ { x: 1, y: 3, terrain: "floor", passable: true, terrainSprite: floor },
46836
+ { x: 2, y: 3, terrain: "floor", passable: true, terrainSprite: tiles2 },
46837
+ { x: 3, y: 3, terrain: "stairs", passable: true, terrainSprite: stairs },
46838
+ { x: 4, y: 3, terrain: "wall", passable: false, terrainSprite: wall },
46839
+ { x: 0, y: 4, terrain: "wall", passable: false, terrainSprite: wall },
46840
+ { x: 1, y: 4, terrain: "wall", passable: false, terrainSprite: wall },
46841
+ { x: 2, y: 4, terrain: "wall", passable: false, terrainSprite: wall },
46842
+ { x: 3, y: 4, terrain: "wall", passable: false, terrainSprite: wall },
46843
+ { x: 4, y: 4, terrain: "wall", passable: false, terrainSprite: wall }
46950
46844
  ];
46951
46845
  DEFAULT_ROGUELIKE_MANIFEST = {
46952
- baseUrl: CDN4,
46953
- terrains: {
46954
- floor: "/isometric-dungeon/Isometric/dirt_E.png",
46955
- wall: "/isometric-dungeon/Isometric/stoneInset_E.png",
46956
- stairs: "/isometric-dungeon/Isometric/stairs_E.png",
46957
- planks: "/isometric-dungeon/Isometric/planks_E.png"
46958
- },
46846
+ terrains: makeAssetMap({
46847
+ floor: `${CDN4}/isometric-dungeon/Isometric/dirt_E.png`,
46848
+ wall: `${CDN4}/isometric-dungeon/Isometric/stoneInset_E.png`,
46849
+ stairs: `${CDN4}/isometric-dungeon/Isometric/stairs_E.png`,
46850
+ planks: `${CDN4}/isometric-dungeon/Isometric/planks_E.png`
46851
+ }, "tile"),
46959
46852
  units: {
46960
- player: "/isometric-dungeon/Characters/Male/Male_0_Idle0.png",
46961
- enemy: "/sprite-sheets/shadow-legion-sprite-sheet-sw.png"
46853
+ player: makeAsset(`${CDN4}/isometric-dungeon/Characters/Male/Male_0_Idle0.png`, "player"),
46854
+ enemy: makeAsset(`${CDN4}/sprite-sheets/shadow-legion-sprite-sheet-sw.png`, "enemy")
46962
46855
  },
46963
- features: {
46964
- health_potion: "/isometric-dungeon/Isometric/chestClosed_E.png",
46965
- sword: "/isometric-dungeon/Isometric/barrel_E.png",
46966
- shield: "/isometric-dungeon/Isometric/barrel_E.png"
46967
- }
46856
+ features: makeAssetMap({
46857
+ health_potion: `${CDN4}/isometric-dungeon/Isometric/chestClosed_E.png`,
46858
+ sword: `${CDN4}/isometric-dungeon/Isometric/barrel_E.png`,
46859
+ shield: `${CDN4}/isometric-dungeon/Isometric/barrel_E.png`
46860
+ }, "item")
46968
46861
  };
46969
46862
  RoguelikeTemplate.displayName = "RoguelikeTemplate";
46970
46863
  }
@@ -47075,7 +46968,7 @@ var init_debugRegistry = __esm({
47075
46968
  }
47076
46969
  });
47077
46970
  function useDebugData() {
47078
- const [data, setData] = React89.useState(() => ({
46971
+ const [data, setData] = React87.useState(() => ({
47079
46972
  traits: [],
47080
46973
  ticks: [],
47081
46974
  guards: [],
@@ -47089,7 +46982,7 @@ function useDebugData() {
47089
46982
  },
47090
46983
  lastUpdate: Date.now()
47091
46984
  }));
47092
- React89.useEffect(() => {
46985
+ React87.useEffect(() => {
47093
46986
  const updateData = () => {
47094
46987
  setData({
47095
46988
  traits: getAllTraits(),
@@ -47198,12 +47091,12 @@ function layoutGraph(states, transitions, initialState, width, height) {
47198
47091
  return positions;
47199
47092
  }
47200
47093
  function WalkMinimap() {
47201
- const [walkStep, setWalkStep] = React89.useState(null);
47202
- const [traits2, setTraits] = React89.useState([]);
47203
- const [coveredEdges, setCoveredEdges] = React89.useState([]);
47204
- const [completedTraits, setCompletedTraits] = React89.useState(/* @__PURE__ */ new Set());
47205
- const prevTraitRef = React89.useRef(null);
47206
- React89.useEffect(() => {
47094
+ const [walkStep, setWalkStep] = React87.useState(null);
47095
+ const [traits2, setTraits] = React87.useState([]);
47096
+ const [coveredEdges, setCoveredEdges] = React87.useState([]);
47097
+ const [completedTraits, setCompletedTraits] = React87.useState(/* @__PURE__ */ new Set());
47098
+ const prevTraitRef = React87.useRef(null);
47099
+ React87.useEffect(() => {
47207
47100
  const interval = setInterval(() => {
47208
47101
  const w = window;
47209
47102
  const step = w.__orbitalWalkStep;
@@ -47639,15 +47532,15 @@ var init_EntitiesTab = __esm({
47639
47532
  });
47640
47533
  function EventFlowTab({ events: events2 }) {
47641
47534
  const { t } = useTranslate();
47642
- const [filter, setFilter] = React89.useState("all");
47643
- const containerRef = React89.useRef(null);
47644
- const [autoScroll, setAutoScroll] = React89.useState(true);
47645
- React89.useEffect(() => {
47535
+ const [filter, setFilter] = React87.useState("all");
47536
+ const containerRef = React87.useRef(null);
47537
+ const [autoScroll, setAutoScroll] = React87.useState(true);
47538
+ React87.useEffect(() => {
47646
47539
  if (autoScroll && containerRef.current) {
47647
47540
  containerRef.current.scrollTop = containerRef.current.scrollHeight;
47648
47541
  }
47649
47542
  }, [events2.length, autoScroll]);
47650
- const filteredEvents = React89.useMemo(() => {
47543
+ const filteredEvents = React87.useMemo(() => {
47651
47544
  if (filter === "all") return events2;
47652
47545
  return events2.filter((e) => e.type === filter);
47653
47546
  }, [events2, filter]);
@@ -47763,7 +47656,7 @@ var init_EventFlowTab = __esm({
47763
47656
  });
47764
47657
  function GuardsPanel({ guards }) {
47765
47658
  const { t } = useTranslate();
47766
- const [filter, setFilter] = React89.useState("all");
47659
+ const [filter, setFilter] = React87.useState("all");
47767
47660
  if (guards.length === 0) {
47768
47661
  return /* @__PURE__ */ jsx(
47769
47662
  EmptyState,
@@ -47776,7 +47669,7 @@ function GuardsPanel({ guards }) {
47776
47669
  }
47777
47670
  const passedCount = guards.filter((g) => g.result).length;
47778
47671
  const failedCount = guards.length - passedCount;
47779
- const filteredGuards = React89.useMemo(() => {
47672
+ const filteredGuards = React87.useMemo(() => {
47780
47673
  if (filter === "all") return guards;
47781
47674
  if (filter === "passed") return guards.filter((g) => g.result);
47782
47675
  return guards.filter((g) => !g.result);
@@ -47939,10 +47832,10 @@ function EffectBadge({ effect }) {
47939
47832
  }
47940
47833
  function TransitionTimeline({ transitions }) {
47941
47834
  const { t } = useTranslate();
47942
- const containerRef = React89.useRef(null);
47943
- const [autoScroll, setAutoScroll] = React89.useState(true);
47944
- const [expandedId, setExpandedId] = React89.useState(null);
47945
- React89.useEffect(() => {
47835
+ const containerRef = React87.useRef(null);
47836
+ const [autoScroll, setAutoScroll] = React87.useState(true);
47837
+ const [expandedId, setExpandedId] = React87.useState(null);
47838
+ React87.useEffect(() => {
47946
47839
  if (autoScroll && containerRef.current) {
47947
47840
  containerRef.current.scrollTop = containerRef.current.scrollHeight;
47948
47841
  }
@@ -48222,9 +48115,9 @@ function getAllEvents(traits2) {
48222
48115
  function EventDispatcherTab({ traits: traits2, schema }) {
48223
48116
  const eventBus = useEventBus();
48224
48117
  const { t } = useTranslate();
48225
- const [log14, setLog] = React89.useState([]);
48226
- const prevStatesRef = React89.useRef(/* @__PURE__ */ new Map());
48227
- React89.useEffect(() => {
48118
+ const [log14, setLog] = React87.useState([]);
48119
+ const prevStatesRef = React87.useRef(/* @__PURE__ */ new Map());
48120
+ React87.useEffect(() => {
48228
48121
  for (const trait of traits2) {
48229
48122
  const prev = prevStatesRef.current.get(trait.id);
48230
48123
  if (prev && prev !== trait.currentState) {
@@ -48393,10 +48286,10 @@ function VerifyModePanel({
48393
48286
  localCount
48394
48287
  }) {
48395
48288
  const { t } = useTranslate();
48396
- const [expanded, setExpanded] = React89.useState(true);
48397
- const scrollRef = React89.useRef(null);
48398
- const prevCountRef = React89.useRef(0);
48399
- React89.useEffect(() => {
48289
+ const [expanded, setExpanded] = React87.useState(true);
48290
+ const scrollRef = React87.useRef(null);
48291
+ const prevCountRef = React87.useRef(0);
48292
+ React87.useEffect(() => {
48400
48293
  if (expanded && transitions.length > prevCountRef.current && scrollRef.current) {
48401
48294
  scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
48402
48295
  }
@@ -48453,10 +48346,10 @@ function RuntimeDebugger({
48453
48346
  schema
48454
48347
  }) {
48455
48348
  const { t } = useTranslate();
48456
- const [isCollapsed, setIsCollapsed] = React89.useState(mode === "verify" ? true : defaultCollapsed);
48457
- const [isVisible, setIsVisible] = React89.useState(mode === "inline" || mode === "verify" || isDebugEnabled2());
48349
+ const [isCollapsed, setIsCollapsed] = React87.useState(mode === "verify" ? true : defaultCollapsed);
48350
+ const [isVisible, setIsVisible] = React87.useState(mode === "inline" || mode === "verify" || isDebugEnabled2());
48458
48351
  const debugData = useDebugData();
48459
- React89.useEffect(() => {
48352
+ React87.useEffect(() => {
48460
48353
  if (mode === "inline") return;
48461
48354
  return onDebugToggle((enabled) => {
48462
48355
  setIsVisible(enabled);
@@ -48465,7 +48358,7 @@ function RuntimeDebugger({
48465
48358
  }
48466
48359
  });
48467
48360
  }, [mode]);
48468
- React89.useEffect(() => {
48361
+ React87.useEffect(() => {
48469
48362
  if (mode === "inline") return;
48470
48363
  const handleKeyDown = (e) => {
48471
48364
  if (e.key === "`" && isVisible) {
@@ -49025,7 +48918,7 @@ function SequenceBar({
49025
48918
  onSlotRemove(index);
49026
48919
  }, [onSlotRemove, playing]);
49027
48920
  const paddedSlots = Array.from({ length: maxSlots }, (_, i) => slots[i]);
49028
- return /* @__PURE__ */ jsx(HStack, { className: cn("items-center", className), gap: "sm", children: paddedSlots.map((slot, i) => /* @__PURE__ */ jsxs(React89__default.Fragment, { children: [
48921
+ return /* @__PURE__ */ jsx(HStack, { className: cn("items-center", className), gap: "sm", children: paddedSlots.map((slot, i) => /* @__PURE__ */ jsxs(React87__default.Fragment, { children: [
49029
48922
  i > 0 && /* @__PURE__ */ jsx(
49030
48923
  Typography,
49031
48924
  {
@@ -49838,7 +49731,6 @@ function SokobanBoard({
49838
49731
  units,
49839
49732
  features,
49840
49733
  assetManifest,
49841
- assetBaseUrl,
49842
49734
  scale,
49843
49735
  showMinimap,
49844
49736
  enableCamera,
@@ -49880,7 +49772,6 @@ function SpaceShmupBoard({
49880
49772
  units,
49881
49773
  features,
49882
49774
  assetManifest,
49883
- assetBaseUrl,
49884
49775
  scale,
49885
49776
  showMinimap,
49886
49777
  enableCamera,
@@ -49922,7 +49813,6 @@ function SpaceStationBoard({
49922
49813
  units,
49923
49814
  features,
49924
49815
  assetManifest,
49925
- assetBaseUrl,
49926
49816
  scale,
49927
49817
  showMinimap,
49928
49818
  enableCamera,
@@ -50057,7 +49947,6 @@ function SportsBoard({
50057
49947
  units,
50058
49948
  features,
50059
49949
  assetManifest,
50060
- assetBaseUrl,
50061
49950
  scale,
50062
49951
  showMinimap,
50063
49952
  enableCamera,
@@ -50114,7 +50003,7 @@ var init_StatCard = __esm({
50114
50003
  const labelToUse = propLabel ?? propTitle;
50115
50004
  const eventBus = useEventBus();
50116
50005
  const { t } = useTranslate();
50117
- const handleActionClick = React89__default.useCallback(() => {
50006
+ const handleActionClick = React87__default.useCallback(() => {
50118
50007
  if (action?.event) {
50119
50008
  eventBus.emit(`UI:${action.event}`, {});
50120
50009
  }
@@ -50125,7 +50014,7 @@ var init_StatCard = __esm({
50125
50014
  const data = Array.isArray(entity) ? entity : entity ? [entity] : [];
50126
50015
  const isLoading = externalLoading ?? false;
50127
50016
  const error = externalError;
50128
- const computeMetricValue = React89__default.useCallback(
50017
+ const computeMetricValue = React87__default.useCallback(
50129
50018
  (metric, items) => {
50130
50019
  if (metric.value !== void 0) {
50131
50020
  return metric.value;
@@ -50164,7 +50053,7 @@ var init_StatCard = __esm({
50164
50053
  },
50165
50054
  []
50166
50055
  );
50167
- const schemaStats = React89__default.useMemo(() => {
50056
+ const schemaStats = React87__default.useMemo(() => {
50168
50057
  if (!metrics || metrics.length === 0) return null;
50169
50058
  return metrics.map((metric) => ({
50170
50059
  label: metric.label,
@@ -50172,7 +50061,7 @@ var init_StatCard = __esm({
50172
50061
  format: metric.format
50173
50062
  }));
50174
50063
  }, [metrics, data, computeMetricValue]);
50175
- const calculatedTrend = React89__default.useMemo(() => {
50064
+ const calculatedTrend = React87__default.useMemo(() => {
50176
50065
  if (manualTrend !== void 0) return manualTrend;
50177
50066
  if (previousValue === void 0 || currentValue === void 0)
50178
50067
  return void 0;
@@ -51378,8 +51267,8 @@ var init_SubagentTracePanel = __esm({
51378
51267
  ] });
51379
51268
  };
51380
51269
  InlineActivityStream = ({ activities, autoScroll = true, className }) => {
51381
- const endRef = React89__default.useRef(null);
51382
- React89__default.useEffect(() => {
51270
+ const endRef = React87__default.useRef(null);
51271
+ React87__default.useEffect(() => {
51383
51272
  if (!autoScroll) return;
51384
51273
  endRef.current?.scrollIntoView({ behavior: "smooth", block: "end" });
51385
51274
  }, [activities.length, autoScroll]);
@@ -51473,7 +51362,7 @@ var init_SubagentTracePanel = __esm({
51473
51362
  };
51474
51363
  SubagentRichCard = ({ subagent }) => {
51475
51364
  const { t } = useTranslate();
51476
- const activities = React89__default.useMemo(
51365
+ const activities = React87__default.useMemo(
51477
51366
  () => subagentMessagesToActivities(subagent.messages),
51478
51367
  [subagent.messages]
51479
51368
  );
@@ -51550,8 +51439,8 @@ var init_SubagentTracePanel = __esm({
51550
51439
  ] });
51551
51440
  };
51552
51441
  CoordinatorConversation = ({ messages, autoScroll = true, className }) => {
51553
- const endRef = React89__default.useRef(null);
51554
- React89__default.useEffect(() => {
51442
+ const endRef = React87__default.useRef(null);
51443
+ React87__default.useEffect(() => {
51555
51444
  if (!autoScroll) return;
51556
51445
  endRef.current?.scrollIntoView({ behavior: "smooth", block: "end" });
51557
51446
  }, [messages.length, autoScroll]);
@@ -51901,7 +51790,6 @@ function TanksBoard({
51901
51790
  units,
51902
51791
  features,
51903
51792
  assetManifest,
51904
- assetBaseUrl,
51905
51793
  scale,
51906
51794
  showMinimap,
51907
51795
  enableCamera,
@@ -52023,7 +51911,7 @@ var init_Timeline = __esm({
52023
51911
  }) => {
52024
51912
  const { t } = useTranslate();
52025
51913
  const entityData = entity ?? [];
52026
- const items = React89__default.useMemo(() => {
51914
+ const items = React87__default.useMemo(() => {
52027
51915
  if (propItems) return propItems;
52028
51916
  if (entityData.length === 0) return [];
52029
51917
  return entityData.map((record, idx) => {
@@ -52125,7 +52013,7 @@ var init_Timeline = __esm({
52125
52013
  }
52126
52014
  });
52127
52015
  function extractToastProps(children) {
52128
- if (!React89__default.isValidElement(children)) {
52016
+ if (!React87__default.isValidElement(children)) {
52129
52017
  if (typeof children === "string") {
52130
52018
  return { message: children };
52131
52019
  }
@@ -52163,7 +52051,7 @@ var init_ToastSlot = __esm({
52163
52051
  eventBus.emit("UI:CLOSE");
52164
52052
  };
52165
52053
  if (!isVisible) return null;
52166
- const isCustomContent = React89__default.isValidElement(children) && !message;
52054
+ const isCustomContent = React87__default.isValidElement(children) && !message;
52167
52055
  return /* @__PURE__ */ jsx(Box, { className: "fixed bottom-4 right-4 z-50", children: isCustomContent ? children : /* @__PURE__ */ jsx(
52168
52056
  Toast,
52169
52057
  {
@@ -52179,15 +52067,6 @@ var init_ToastSlot = __esm({
52179
52067
  ToastSlot.displayName = "ToastSlot";
52180
52068
  }
52181
52069
  });
52182
- function resolveManifestUrl4(manifest, relative) {
52183
- if (relative == null || relative === "") return void 0;
52184
- if (/^https?:\/\//.test(relative)) return relative;
52185
- const base = manifest?.baseUrl;
52186
- if (base == null) return relative;
52187
- const cleanBase = base.replace(/\/$/, "");
52188
- const cleanRel = relative.replace(/^\//, "");
52189
- return `${cleanBase}/${cleanRel}`;
52190
- }
52191
52070
  function readPlayer(v) {
52192
52071
  if (v == null || typeof v !== "object") return void 0;
52193
52072
  const o = v;
@@ -52240,10 +52119,10 @@ function TopDownShooterBoard({
52240
52119
  const wave = propWave ?? num(board.wave, 1);
52241
52120
  const lives = propLives ?? num(board.lives, 3);
52242
52121
  const result = propResult ?? (str(board.result) || "none");
52243
- const playerSprite = resolveManifestUrl4(assetManifest, assetManifest?.units?.player);
52244
- const enemySprite = resolveManifestUrl4(assetManifest, assetManifest?.units?.enemy);
52245
- const projectileSprite = resolveManifestUrl4(assetManifest, assetManifest?.features?.projectile);
52246
- const backgroundSprite = resolveManifestUrl4(assetManifest, assetManifest?.background);
52122
+ const playerSprite = assetManifest?.units?.player?.url;
52123
+ const enemySprite = assetManifest?.units?.enemy?.url;
52124
+ const projectileSprite = assetManifest?.features?.projectile?.url;
52125
+ const backgroundSprite = assetManifest?.background;
52247
52126
  const spriteUrls = useMemo(
52248
52127
  () => [playerSprite, enemySprite, projectileSprite].filter((u) => u != null),
52249
52128
  [playerSprite, enemySprite, projectileSprite]
@@ -52410,7 +52289,6 @@ function TopDownShooterBoard({
52410
52289
  width,
52411
52290
  height,
52412
52291
  backgroundImage: backgroundSprite,
52413
- assetBaseUrl: assetManifest?.baseUrl,
52414
52292
  onDraw
52415
52293
  }
52416
52294
  ),
@@ -52535,15 +52413,6 @@ var init_TopDownShooterTemplate = __esm({
52535
52413
  TopDownShooterTemplate.displayName = "TopDownShooterTemplate";
52536
52414
  }
52537
52415
  });
52538
- function resolveManifestUrl5(manifest, relative) {
52539
- if (relative == null) return void 0;
52540
- if (/^https?:\/\//.test(relative)) return relative;
52541
- const base = manifest?.baseUrl;
52542
- if (base == null) return relative;
52543
- const cleanBase = base.replace(/\/$/, "");
52544
- const cleanRel = relative.replace(/^\//, "");
52545
- return `${cleanBase}/${cleanRel}`;
52546
- }
52547
52416
  function buildDefaultTDTiles() {
52548
52417
  const pathSet = new Set(DEFAULT_TD_PATH.map((p2) => `${p2.x},${p2.y}`));
52549
52418
  const tiles = [];
@@ -52563,18 +52432,18 @@ function buildDefaultTDTiles() {
52563
52432
  function tilesToIso2(tiles, manifest) {
52564
52433
  return tiles.map((t) => {
52565
52434
  const key = t.terrain ?? "ground";
52566
- const sprite = t.terrainSprite ?? resolveManifestUrl5(manifest, manifest?.terrains?.[key]) ?? resolveManifestUrl5(manifest, manifest?.terrains?.ground);
52435
+ const terrainSprite = t.terrainSprite != null ? makeAsset(t.terrainSprite, "tile") : manifest?.terrains?.[key] ?? manifest?.terrains?.ground;
52567
52436
  return {
52568
52437
  x: t.x,
52569
52438
  y: t.y,
52570
52439
  terrain: t.terrain,
52571
- terrainSprite: sprite,
52440
+ terrainSprite,
52572
52441
  passable: t.passable
52573
52442
  };
52574
52443
  });
52575
52444
  }
52576
52445
  function creepsToUnits(creeps, manifest) {
52577
- const sprite = resolveManifestUrl5(manifest, manifest?.units?.creep);
52446
+ const sprite = manifest?.units?.creep;
52578
52447
  return creeps.map((c) => ({
52579
52448
  id: c.id,
52580
52449
  position: { x: c.x, y: c.y },
@@ -52592,14 +52461,14 @@ function heroToUnit(hero, manifest) {
52592
52461
  position: { x: hero.x, y: hero.y },
52593
52462
  name: "Hero",
52594
52463
  team: "player",
52595
- sprite: resolveManifestUrl5(manifest, manifest?.units?.hero),
52464
+ sprite: manifest?.units?.hero,
52596
52465
  unitType: "hero",
52597
52466
  health: 1,
52598
52467
  maxHealth: 1
52599
52468
  };
52600
52469
  }
52601
52470
  function towersToFeatures(towers, manifest) {
52602
- const sprite = resolveManifestUrl5(manifest, manifest?.features?.tower);
52471
+ const sprite = manifest?.features?.tower;
52603
52472
  return towers.map((t) => ({
52604
52473
  id: t.id,
52605
52474
  x: t.x,
@@ -52797,7 +52666,6 @@ function TowerDefenseBoard({
52797
52666
  tiles: isoTiles,
52798
52667
  units: isoUnits,
52799
52668
  features: towerFeatures,
52800
- assetBaseUrl: assetManifest?.baseUrl,
52801
52669
  assetManifest,
52802
52670
  validMoves,
52803
52671
  hoveredTile,
@@ -52841,6 +52709,7 @@ var TD_GRID_W, TD_GRID_H, DEFAULT_TD_PATH, DEFAULT_TD_TILES;
52841
52709
  var init_TowerDefenseBoard = __esm({
52842
52710
  "components/game/organisms/TowerDefenseBoard.tsx"() {
52843
52711
  "use client";
52712
+ init_makeAsset();
52844
52713
  init_cn();
52845
52714
  init_useEventBus();
52846
52715
  init_Box();
@@ -53170,15 +53039,6 @@ var init_UncontrolledBattleBoard = __esm({
53170
53039
  UncontrolledBattleBoard.displayName = "UncontrolledBattleBoard";
53171
53040
  }
53172
53041
  });
53173
- function resolveManifestUrl6(manifest, relative) {
53174
- if (relative == null) return void 0;
53175
- if (/^https?:\/\//.test(relative)) return relative;
53176
- const base = manifest?.baseUrl;
53177
- if (base == null) return relative;
53178
- const cleanBase = base.replace(/\/$/, "");
53179
- const cleanRel = relative.replace(/^\//, "");
53180
- return `${cleanBase}/${cleanRel}`;
53181
- }
53182
53042
  function VisualNovelBoard({
53183
53043
  entity,
53184
53044
  nodes: propNodes,
@@ -53213,11 +53073,11 @@ function VisualNovelBoard({
53213
53073
  const currentNodeId = propCurrentNodeId ?? (str(board.currentNodeId) || nodes[0]?.id);
53214
53074
  const currentNode = nodes.find((n) => n.id === currentNodeId) ?? nodes[0];
53215
53075
  const backgroundImage = useMemo(
53216
- () => resolveManifestUrl6(assetManifest, assetManifest?.backgrounds?.[currentNode?.backgroundKey ?? ""]),
53076
+ () => assetManifest?.backgrounds?.[currentNode?.backgroundKey ?? ""],
53217
53077
  [assetManifest, currentNode?.backgroundKey]
53218
53078
  );
53219
53079
  const portraitUrl = useMemo(
53220
- () => resolveManifestUrl6(assetManifest, assetManifest?.portraits?.[currentNode?.portraitKey ?? ""]),
53080
+ () => assetManifest?.portraits?.[currentNode?.portraitKey ?? ""],
53221
53081
  [assetManifest, currentNode?.portraitKey]
53222
53082
  );
53223
53083
  const dialogueChoices = useMemo(
@@ -53391,7 +53251,7 @@ function buildDefaultWorldTiles() {
53391
53251
  for (let x = 0; x < WORLD_GRID_W; x++) {
53392
53252
  const isBorder = x === 0 || y === 0 || x === WORLD_GRID_W - 1 || y === WORLD_GRID_H - 1;
53393
53253
  const def = isBorder ? WORLD_TERRAIN_DEFS[3] : WORLD_TERRAIN_DEFS[(x * 5 + y * 3 + (x ^ y)) % (WORLD_TERRAIN_DEFS.length - 1)];
53394
- tiles.push({ x, y, terrain: def.terrain, terrainSprite: def.sprite, passable: def.passable });
53254
+ tiles.push({ x, y, terrain: def.terrain, terrainSprite: makeAsset(def.sprite, "tile"), passable: def.passable });
53395
53255
  }
53396
53256
  }
53397
53257
  return tiles;
@@ -53435,7 +53295,12 @@ function WorldMapBoard({
53435
53295
  const resolved = boardEntity(entity);
53436
53296
  const entityUnits = rows(resolved?.units);
53437
53297
  const entityTiles = rows(resolved?.tiles);
53438
- const features = propFeatures ?? rows(resolved?.features);
53298
+ const features = propFeatures ?? rows(resolved?.features).map((r) => ({
53299
+ id: r.id == null ? void 0 : str(r.id),
53300
+ x: num(r.x),
53301
+ y: num(r.y),
53302
+ type: str(r.type)
53303
+ }));
53439
53304
  const selectedHeroId = resolved?.selectedHeroId ?? null;
53440
53305
  const assetManifest = propAssetManifest ?? resolved?.assetManifest;
53441
53306
  const backgroundImage = resolved?.backgroundImage;
@@ -53445,7 +53310,7 @@ function WorldMapBoard({
53445
53310
  x: num(t.x),
53446
53311
  y: num(t.y),
53447
53312
  terrain: str(t.terrain),
53448
- terrainSprite: t.terrainSprite == null ? void 0 : str(t.terrainSprite),
53313
+ terrainSprite: t.terrainSprite == null ? void 0 : makeAsset(str(t.terrainSprite), "tile"),
53449
53314
  passable: t.passable !== false
53450
53315
  })),
53451
53316
  [entityTiles]
@@ -53461,7 +53326,7 @@ function WorldMapBoard({
53461
53326
  team: str(u.team) === "enemy" ? "enemy" : "player",
53462
53327
  health: num(u.health) || 100,
53463
53328
  maxHealth: num(u.maxHealth) || 100,
53464
- sprite: u.sprite == null ? void 0 : str(u.sprite)
53329
+ sprite: u.sprite == null ? void 0 : makeAsset(str(u.sprite), "player")
53465
53330
  })),
53466
53331
  [entityUnits, propUnits]
53467
53332
  );
@@ -53643,7 +53508,6 @@ function WorldMapBoard({
53643
53508
  onTileHover: (x, y) => setHoveredTile({ x, y }),
53644
53509
  onTileLeave: () => setHoveredTile(null),
53645
53510
  scale,
53646
- assetBaseUrl: assetManifest?.baseUrl,
53647
53511
  assetManifest,
53648
53512
  backgroundImage,
53649
53513
  effectSpriteUrls,
@@ -53666,6 +53530,7 @@ var WORLD_CDN, WORLD_GRID_W, WORLD_GRID_H, WORLD_TERRAIN_DEFS, DEFAULT_WORLD_TIL
53666
53530
  var init_WorldMapBoard = __esm({
53667
53531
  "components/game/organisms/WorldMapBoard.tsx"() {
53668
53532
  "use client";
53533
+ init_makeAsset();
53669
53534
  init_cn();
53670
53535
  init_useEventBus();
53671
53536
  init_Stack();
@@ -53719,68 +53584,72 @@ function WorldMapTemplate({
53719
53584
  }
53720
53585
  );
53721
53586
  }
53722
- var CDN5, DEFAULT_WORLDMAP_TILES, DEFAULT_WORLDMAP_UNITS, DEFAULT_WORLDMAP_FEATURES, DEFAULT_WORLDMAP_MANIFEST;
53587
+ var CDN5, mountain, water, grass, road, DEFAULT_WORLDMAP_TILES, DEFAULT_WORLDMAP_UNITS, DEFAULT_WORLDMAP_FEATURES, DEFAULT_WORLDMAP_MANIFEST;
53723
53588
  var init_WorldMapTemplate = __esm({
53724
53589
  "components/game/templates/WorldMapTemplate.tsx"() {
53725
53590
  init_WorldMapBoard();
53591
+ init_makeAsset();
53726
53592
  CDN5 = "https://almadar-kflow-assets.web.app/shared";
53593
+ mountain = makeAsset(`${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_13.png`, "tile");
53594
+ water = makeAsset(`${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_11.png`, "tile");
53595
+ grass = makeAsset(`${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png`, "tile");
53596
+ road = makeAsset(`${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_03.png`, "tile");
53727
53597
  DEFAULT_WORLDMAP_TILES = [
53728
- { x: 0, y: 0, terrain: "mountain", passable: false, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_13.png` },
53729
- { x: 1, y: 0, terrain: "mountain", passable: false, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_13.png` },
53730
- { x: 2, y: 0, terrain: "water", passable: false, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_11.png` },
53731
- { x: 3, y: 0, terrain: "mountain", passable: false, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_13.png` },
53732
- { x: 4, y: 0, terrain: "mountain", passable: false, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_13.png` },
53733
- { x: 0, y: 1, terrain: "mountain", passable: false, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_13.png` },
53734
- { x: 1, y: 1, terrain: "grass", passable: true, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png` },
53735
- { x: 2, y: 1, terrain: "grass", passable: true, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png` },
53736
- { x: 3, y: 1, terrain: "grass", passable: true, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png` },
53737
- { x: 4, y: 1, terrain: "water", passable: false, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_11.png` },
53738
- { x: 0, y: 2, terrain: "water", passable: false, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_11.png` },
53739
- { x: 1, y: 2, terrain: "grass", passable: true, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png` },
53740
- { x: 2, y: 2, terrain: "grass", passable: true, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_03.png` },
53741
- { x: 3, y: 2, terrain: "grass", passable: true, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png` },
53742
- { x: 4, y: 2, terrain: "mountain", passable: false, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_13.png` },
53743
- { x: 0, y: 3, terrain: "mountain", passable: false, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_13.png` },
53744
- { x: 1, y: 3, terrain: "grass", passable: true, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png` },
53745
- { x: 2, y: 3, terrain: "grass", passable: true, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png` },
53746
- { x: 3, y: 3, terrain: "grass", passable: true, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_03.png` },
53747
- { x: 4, y: 3, terrain: "mountain", passable: false, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_13.png` },
53748
- { x: 0, y: 4, terrain: "mountain", passable: false, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_13.png` },
53749
- { x: 1, y: 4, terrain: "water", passable: false, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_11.png` },
53750
- { x: 2, y: 4, terrain: "grass", passable: true, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png` },
53751
- { x: 3, y: 4, terrain: "mountain", passable: false, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_13.png` },
53752
- { x: 4, y: 4, terrain: "mountain", passable: false, terrainSprite: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_13.png` }
53598
+ { x: 0, y: 0, terrain: "mountain", passable: false, terrainSprite: mountain },
53599
+ { x: 1, y: 0, terrain: "mountain", passable: false, terrainSprite: mountain },
53600
+ { x: 2, y: 0, terrain: "water", passable: false, terrainSprite: water },
53601
+ { x: 3, y: 0, terrain: "mountain", passable: false, terrainSprite: mountain },
53602
+ { x: 4, y: 0, terrain: "mountain", passable: false, terrainSprite: mountain },
53603
+ { x: 0, y: 1, terrain: "mountain", passable: false, terrainSprite: mountain },
53604
+ { x: 1, y: 1, terrain: "grass", passable: true, terrainSprite: grass },
53605
+ { x: 2, y: 1, terrain: "grass", passable: true, terrainSprite: grass },
53606
+ { x: 3, y: 1, terrain: "grass", passable: true, terrainSprite: grass },
53607
+ { x: 4, y: 1, terrain: "water", passable: false, terrainSprite: water },
53608
+ { x: 0, y: 2, terrain: "water", passable: false, terrainSprite: water },
53609
+ { x: 1, y: 2, terrain: "grass", passable: true, terrainSprite: grass },
53610
+ { x: 2, y: 2, terrain: "grass", passable: true, terrainSprite: road },
53611
+ { x: 3, y: 2, terrain: "grass", passable: true, terrainSprite: grass },
53612
+ { x: 4, y: 2, terrain: "mountain", passable: false, terrainSprite: mountain },
53613
+ { x: 0, y: 3, terrain: "mountain", passable: false, terrainSprite: mountain },
53614
+ { x: 1, y: 3, terrain: "grass", passable: true, terrainSprite: grass },
53615
+ { x: 2, y: 3, terrain: "grass", passable: true, terrainSprite: grass },
53616
+ { x: 3, y: 3, terrain: "grass", passable: true, terrainSprite: road },
53617
+ { x: 4, y: 3, terrain: "mountain", passable: false, terrainSprite: mountain },
53618
+ { x: 0, y: 4, terrain: "mountain", passable: false, terrainSprite: mountain },
53619
+ { x: 1, y: 4, terrain: "water", passable: false, terrainSprite: water },
53620
+ { x: 2, y: 4, terrain: "grass", passable: true, terrainSprite: grass },
53621
+ { x: 3, y: 4, terrain: "mountain", passable: false, terrainSprite: mountain },
53622
+ { x: 4, y: 4, terrain: "mountain", passable: false, terrainSprite: mountain }
53753
53623
  ];
53754
53624
  DEFAULT_WORLDMAP_UNITS = [
53755
- { id: "h1", position: { x: 1, y: 1 }, unitType: "hero", name: "Amir", team: "player", health: 10, maxHealth: 10, sprite: `${CDN5}/sprite-sheets/amir-sprite-sheet-se.png` },
53756
- { id: "h2", position: { x: 3, y: 3 }, unitType: "scout", name: "Archivist", team: "player", health: 10, maxHealth: 10, sprite: `${CDN5}/sprite-sheets/archivist-sprite-sheet-se.png` }
53625
+ { id: "h1", position: { x: 1, y: 1 }, unitType: "hero", name: "Amir", team: "player", health: 10, maxHealth: 10, sprite: makeAsset(`${CDN5}/sprite-sheets/amir-sprite-sheet-se.png`, "player") },
53626
+ { id: "h2", position: { x: 3, y: 3 }, unitType: "scout", name: "Archivist", team: "player", health: 10, maxHealth: 10, sprite: makeAsset(`${CDN5}/sprite-sheets/archivist-sprite-sheet-se.png`, "npc") }
53757
53627
  ];
53758
53628
  DEFAULT_WORLDMAP_FEATURES = [
53759
- { id: "f1", x: 2, y: 2, type: "capital", sprite: `${CDN5}/scenes/world/capital.png` },
53760
- { id: "f2", x: 4, y: 2, type: "power_node", sprite: `${CDN5}/world-map/power_node.png` }
53629
+ { id: "f1", x: 2, y: 2, type: "capital", sprite: makeAsset(`${CDN5}/scenes/world/capital.png`, "decoration") },
53630
+ { id: "f2", x: 4, y: 2, type: "power_node", sprite: makeAsset(`${CDN5}/world-map/power_node.png`, "decoration") }
53761
53631
  ];
53762
53632
  DEFAULT_WORLDMAP_MANIFEST = {
53763
- baseUrl: CDN5,
53764
- terrains: {
53765
- grass: "/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png",
53766
- water: "/isometric-blocks/PNG/Platformer tiles/platformerTile_11.png",
53767
- mountain: "/isometric-blocks/PNG/Platformer tiles/platformerTile_13.png",
53768
- road: "/isometric-blocks/PNG/Platformer tiles/platformerTile_03.png"
53769
- },
53633
+ terrains: makeAssetMap({
53634
+ grass: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_01.png`,
53635
+ water: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_11.png`,
53636
+ mountain: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_13.png`,
53637
+ road: `${CDN5}/isometric-blocks/PNG/Platformer tiles/platformerTile_03.png`
53638
+ }, "tile"),
53770
53639
  units: {
53771
- hero: "/sprite-sheets/amir-sprite-sheet-se.png",
53772
- scout: "/sprite-sheets/archivist-sprite-sheet-se.png"
53640
+ hero: makeAsset(`${CDN5}/sprite-sheets/amir-sprite-sheet-se.png`, "player"),
53641
+ scout: makeAsset(`${CDN5}/sprite-sheets/archivist-sprite-sheet-se.png`, "npc")
53773
53642
  },
53774
- features: {
53775
- capital: "/scenes/world/capital.png",
53776
- power_node: "/world-map/power_node.png"
53777
- }
53643
+ features: makeAssetMap({
53644
+ capital: `${CDN5}/scenes/world/capital.png`,
53645
+ power_node: `${CDN5}/world-map/power_node.png`
53646
+ }, "decoration")
53778
53647
  };
53779
53648
  WorldMapTemplate.displayName = "WorldMapTemplate";
53780
53649
  }
53781
53650
  });
53782
53651
  function lazyThree(name, loader) {
53783
- const Lazy = React89__default.lazy(
53652
+ const Lazy = React87__default.lazy(
53784
53653
  () => loader().then((m) => {
53785
53654
  const Resolved = m[name];
53786
53655
  if (!Resolved) {
@@ -53792,13 +53661,13 @@ function lazyThree(name, loader) {
53792
53661
  })
53793
53662
  );
53794
53663
  function ThreeWrapper(props) {
53795
- return React89__default.createElement(
53664
+ return React87__default.createElement(
53796
53665
  ThreeBoundary,
53797
53666
  { name },
53798
- React89__default.createElement(
53799
- React89__default.Suspense,
53667
+ React87__default.createElement(
53668
+ React87__default.Suspense,
53800
53669
  { fallback: null },
53801
- React89__default.createElement(Lazy, props)
53670
+ React87__default.createElement(Lazy, props)
53802
53671
  )
53803
53672
  );
53804
53673
  }
@@ -54121,7 +53990,7 @@ var init_component_registry_generated = __esm({
54121
53990
  init_WorldMapBoard();
54122
53991
  init_WorldMapTemplate();
54123
53992
  init_XPBar();
54124
- ThreeBoundary = class extends React89__default.Component {
53993
+ ThreeBoundary = class extends React87__default.Component {
54125
53994
  constructor() {
54126
53995
  super(...arguments);
54127
53996
  __publicField(this, "state", { failed: false });
@@ -54131,7 +54000,7 @@ var init_component_registry_generated = __esm({
54131
54000
  }
54132
54001
  render() {
54133
54002
  if (this.state.failed) {
54134
- return React89__default.createElement(
54003
+ return React87__default.createElement(
54135
54004
  "div",
54136
54005
  {
54137
54006
  "data-testid": "three-unavailable",
@@ -54497,7 +54366,7 @@ function SuspenseConfigProvider({
54497
54366
  config,
54498
54367
  children
54499
54368
  }) {
54500
- return React89__default.createElement(
54369
+ return React87__default.createElement(
54501
54370
  SuspenseConfigContext.Provider,
54502
54371
  { value: config },
54503
54372
  children
@@ -54539,7 +54408,7 @@ function enrichFormFields(fields, entityDef) {
54539
54408
  }
54540
54409
  return { name: field, label: field.replace(/([a-z])([A-Z])/g, "$1 $2").replace(/\b\w/g, (c) => c.toUpperCase()) };
54541
54410
  }
54542
- if (field && typeof field === "object" && !Array.isArray(field) && !React89__default.isValidElement(field) && !(field instanceof Date)) {
54411
+ if (field && typeof field === "object" && !Array.isArray(field) && !React87__default.isValidElement(field) && !(field instanceof Date)) {
54543
54412
  const obj = field;
54544
54413
  const fieldName = typeof obj.name === "string" ? obj.name : typeof obj.field === "string" ? obj.field : void 0;
54545
54414
  if (!fieldName) return field;
@@ -54985,7 +54854,7 @@ function renderPatternChildren(children, onDismiss, parentId = "root", parentPat
54985
54854
  const key = `${parentId}-${index}-trait:${traitName}`;
54986
54855
  return /* @__PURE__ */ jsx(TraitFrame, { traitName }, key);
54987
54856
  }
54988
- return /* @__PURE__ */ jsx(React89__default.Fragment, { children: child }, `${parentId}-${index}`);
54857
+ return /* @__PURE__ */ jsx(React87__default.Fragment, { children: child }, `${parentId}-${index}`);
54989
54858
  }
54990
54859
  if (!child || typeof child !== "object") return null;
54991
54860
  const childId = `${parentId}-${index}`;
@@ -55025,14 +54894,14 @@ function isPatternConfig(value) {
55025
54894
  if (value === null || value === void 0) return false;
55026
54895
  if (typeof value !== "object") return false;
55027
54896
  if (Array.isArray(value)) return false;
55028
- if (React89__default.isValidElement(value)) return false;
54897
+ if (React87__default.isValidElement(value)) return false;
55029
54898
  if (value instanceof Date) return false;
55030
54899
  if (typeof value === "function") return false;
55031
54900
  const record = value;
55032
54901
  return "type" in record && typeof record.type === "string" && getComponentForPattern(record.type) !== null;
55033
54902
  }
55034
54903
  function isPlainConfigObject(value) {
55035
- if (React89__default.isValidElement(value)) return false;
54904
+ if (React87__default.isValidElement(value)) return false;
55036
54905
  if (value instanceof Date) return false;
55037
54906
  const proto = Object.getPrototypeOf(value);
55038
54907
  return proto === Object.prototype || proto === null;
@@ -55158,7 +55027,7 @@ function SlotContentRenderer({
55158
55027
  for (const slotKey of CONTENT_NODE_SLOTS) {
55159
55028
  const slotVal = restProps[slotKey];
55160
55029
  if (slotVal === void 0 || slotVal === null) continue;
55161
- if (React89__default.isValidElement(slotVal) || typeof slotVal === "string" || typeof slotVal === "number" || typeof slotVal === "boolean") continue;
55030
+ if (React87__default.isValidElement(slotVal) || typeof slotVal === "string" || typeof slotVal === "number" || typeof slotVal === "boolean") continue;
55162
55031
  if (Array.isArray(slotVal) || typeof slotVal === "object" && "type" in slotVal) {
55163
55032
  nodeSlotOverrides[slotKey] = renderPatternChildren(
55164
55033
  slotVal,
@@ -55207,7 +55076,7 @@ function SlotContentRenderer({
55207
55076
  const resolvedItems = Array.isArray(entityVal) && entityVal[0] !== "fn" ? entityVal : null;
55208
55077
  if (resolvedItems && resolvedItems.length > 0 && !finalProps.fields && !finalProps.columns) {
55209
55078
  const sample = resolvedItems[0];
55210
- if (sample && typeof sample === "object" && !Array.isArray(sample) && !React89__default.isValidElement(sample) && !(sample instanceof Date)) {
55079
+ if (sample && typeof sample === "object" && !Array.isArray(sample) && !React87__default.isValidElement(sample) && !(sample instanceof Date)) {
55211
55080
  const keys = Object.keys(sample).filter((k) => k !== "id" && k !== "_id");
55212
55081
  finalProps.fields = keys.map((k, i) => ({ name: k, variant: i === 0 ? "h4" : "body" }));
55213
55082
  }
@@ -55495,7 +55364,7 @@ function resolveLambdaBindings(body, params, item, index) {
55495
55364
  if (Array.isArray(body)) {
55496
55365
  return body.map((b) => recur(b));
55497
55366
  }
55498
- if (body !== null && typeof body === "object" && !React89__default.isValidElement(body) && !(body instanceof Date) && typeof body !== "function") {
55367
+ if (body !== null && typeof body === "object" && !React87__default.isValidElement(body) && !(body instanceof Date) && typeof body !== "function") {
55499
55368
  const out = {};
55500
55369
  for (const [k, v] of Object.entries(body)) {
55501
55370
  out[k] = recur(v);
@@ -55514,7 +55383,7 @@ function getSlotContentRenderer4() {
55514
55383
  function makeLambdaFn(params, lambdaBody, callerKey) {
55515
55384
  return (item, index) => {
55516
55385
  const resolvedBody = resolveLambdaBindings(lambdaBody, params, item, index);
55517
- if (resolvedBody === null || typeof resolvedBody !== "object" || Array.isArray(resolvedBody) || typeof resolvedBody === "function" || React89__default.isValidElement(resolvedBody) || resolvedBody instanceof Date) {
55386
+ if (resolvedBody === null || typeof resolvedBody !== "object" || Array.isArray(resolvedBody) || typeof resolvedBody === "function" || React87__default.isValidElement(resolvedBody) || resolvedBody instanceof Date) {
55518
55387
  return null;
55519
55388
  }
55520
55389
  const record = resolvedBody;
@@ -55533,7 +55402,7 @@ function makeLambdaFn(params, lambdaBody, callerKey) {
55533
55402
  props: childProps,
55534
55403
  priority: 0
55535
55404
  };
55536
- return React89__default.createElement(SlotContentRenderer2, { content: childContent });
55405
+ return React87__default.createElement(SlotContentRenderer2, { content: childContent });
55537
55406
  };
55538
55407
  }
55539
55408
  function convertNode(node, callerKey) {
@@ -55552,7 +55421,7 @@ function convertNode(node, callerKey) {
55552
55421
  });
55553
55422
  return anyChanged ? mapped : node;
55554
55423
  }
55555
- if (typeof node === "object" && !React89__default.isValidElement(node) && !(node instanceof Date)) {
55424
+ if (typeof node === "object" && !React87__default.isValidElement(node) && !(node instanceof Date)) {
55556
55425
  return convertObjectProps(node);
55557
55426
  }
55558
55427
  return node;