@almadar/ui 5.71.0 → 5.72.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
2
- import * as React84 from 'react';
3
- import React84__default, { useContext, useMemo, useRef, useEffect, useCallback, useState, Suspense, lazy, createContext, useLayoutEffect, useId, forwardRef, useImperativeHandle, useSyncExternalStore, Component } from 'react';
2
+ import * as React85 from 'react';
3
+ import React85__default, { useContext, useMemo, useRef, useEffect, useCallback, useState, Suspense, lazy, createContext, useLayoutEffect, useId, forwardRef, useImperativeHandle, useSyncExternalStore, Component } from 'react';
4
4
  import { clsx } from 'clsx';
5
5
  import { twMerge } from 'tailwind-merge';
6
6
  import { EventBusContext, useTraitScope, TraitScopeProvider } from '@almadar/ui/providers';
@@ -234,7 +234,7 @@ var init_SvgFlow = __esm({
234
234
  width = 100,
235
235
  height = 100
236
236
  }) => {
237
- const markerId = React84__default.useMemo(() => {
237
+ const markerId = React85__default.useMemo(() => {
238
238
  flowIdCounter += 1;
239
239
  return `almadar-flow-arrow-${flowIdCounter}`;
240
240
  }, []);
@@ -827,7 +827,7 @@ var init_SvgRing = __esm({
827
827
  width = 100,
828
828
  height = 100
829
829
  }) => {
830
- const gradientId = React84__default.useMemo(() => {
830
+ const gradientId = React85__default.useMemo(() => {
831
831
  ringIdCounter += 1;
832
832
  return `almadar-ring-glow-${ringIdCounter}`;
833
833
  }, []);
@@ -1239,7 +1239,7 @@ function loadLib(key, importer) {
1239
1239
  return p2;
1240
1240
  }
1241
1241
  function lazyFamilyIcon(libKey, importer, pick, fallbackName, family) {
1242
- const Lazy = React84__default.lazy(async () => {
1242
+ const Lazy = React85__default.lazy(async () => {
1243
1243
  const lib = await loadLib(libKey, importer);
1244
1244
  const Comp = pick(lib);
1245
1245
  if (!Comp) {
@@ -1249,7 +1249,7 @@ function lazyFamilyIcon(libKey, importer, pick, fallbackName, family) {
1249
1249
  return { default: Comp };
1250
1250
  });
1251
1251
  const Wrapped = (props) => /* @__PURE__ */ jsx(
1252
- React84__default.Suspense,
1252
+ React85__default.Suspense,
1253
1253
  {
1254
1254
  fallback: /* @__PURE__ */ jsx(
1255
1255
  "span",
@@ -1976,7 +1976,7 @@ var init_Icon = __esm({
1976
1976
  const directIcon = typeof icon === "string" ? void 0 : icon;
1977
1977
  const effectiveName = typeof icon === "string" ? icon : name;
1978
1978
  const family = useIconFamily();
1979
- const RenderedComponent = React84__default.useMemo(() => {
1979
+ const RenderedComponent = React85__default.useMemo(() => {
1980
1980
  if (directIcon) return null;
1981
1981
  return effectiveName ? resolveIconForFamily(effectiveName, family) : null;
1982
1982
  }, [directIcon, effectiveName, family]);
@@ -2038,7 +2038,7 @@ function resolveIconProp(value, sizeClass) {
2038
2038
  const IconComp = value;
2039
2039
  return /* @__PURE__ */ jsx(IconComp, { className: sizeClass });
2040
2040
  }
2041
- if (React84__default.isValidElement(value)) {
2041
+ if (React85__default.isValidElement(value)) {
2042
2042
  return value;
2043
2043
  }
2044
2044
  if (typeof value === "object" && value !== null && isIconLike(value)) {
@@ -2114,7 +2114,7 @@ var init_Button = __esm({
2114
2114
  md: "h-icon-default w-icon-default",
2115
2115
  lg: "h-icon-default w-icon-default"
2116
2116
  };
2117
- Button = React84__default.forwardRef(
2117
+ Button = React85__default.forwardRef(
2118
2118
  ({
2119
2119
  className,
2120
2120
  variant = "primary",
@@ -2182,7 +2182,7 @@ var init_Input = __esm({
2182
2182
  init_cn();
2183
2183
  init_Icon();
2184
2184
  init_useEventBus();
2185
- Input = React84__default.forwardRef(
2185
+ Input = React85__default.forwardRef(
2186
2186
  ({
2187
2187
  className,
2188
2188
  inputType,
@@ -2342,7 +2342,7 @@ var Label;
2342
2342
  var init_Label = __esm({
2343
2343
  "components/core/atoms/Label.tsx"() {
2344
2344
  init_cn();
2345
- Label = React84__default.forwardRef(
2345
+ Label = React85__default.forwardRef(
2346
2346
  ({ className, required, children, ...props }, ref) => {
2347
2347
  return /* @__PURE__ */ jsxs(
2348
2348
  "label",
@@ -2369,7 +2369,7 @@ var init_Textarea = __esm({
2369
2369
  "components/core/atoms/Textarea.tsx"() {
2370
2370
  init_cn();
2371
2371
  init_useEventBus();
2372
- Textarea = React84__default.forwardRef(
2372
+ Textarea = React85__default.forwardRef(
2373
2373
  ({ className, error, onChange, ...props }, ref) => {
2374
2374
  const eventBus = useEventBus();
2375
2375
  const handleChange = (e) => {
@@ -2608,7 +2608,7 @@ var init_Select = __esm({
2608
2608
  init_cn();
2609
2609
  init_Icon();
2610
2610
  init_useEventBus();
2611
- Select = React84__default.forwardRef(
2611
+ Select = React85__default.forwardRef(
2612
2612
  (props, _ref) => {
2613
2613
  const { multiple, searchable, clearable } = props;
2614
2614
  if (multiple || searchable || clearable) {
@@ -2625,7 +2625,7 @@ var init_Checkbox = __esm({
2625
2625
  "components/core/atoms/Checkbox.tsx"() {
2626
2626
  init_cn();
2627
2627
  init_useEventBus();
2628
- Checkbox = React84__default.forwardRef(
2628
+ Checkbox = React85__default.forwardRef(
2629
2629
  ({ className, label, id, onChange, ...props }, ref) => {
2630
2630
  const inputId = id || `checkbox-${Math.random().toString(36).substr(2, 9)}`;
2631
2631
  const eventBus = useEventBus();
@@ -2679,7 +2679,7 @@ var init_Spinner = __esm({
2679
2679
  md: "h-6 w-6",
2680
2680
  lg: "h-8 w-8"
2681
2681
  };
2682
- Spinner = React84__default.forwardRef(
2682
+ Spinner = React85__default.forwardRef(
2683
2683
  ({ className, size = "md", overlay, ...props }, ref) => {
2684
2684
  if (overlay) {
2685
2685
  return /* @__PURE__ */ jsx(
@@ -2769,7 +2769,7 @@ var init_Card = __esm({
2769
2769
  chip: "shadow-none rounded-pill border-[length:var(--border-width)] border-border",
2770
2770
  "tile-image-first": "p-0 overflow-hidden"
2771
2771
  };
2772
- Card = React84__default.forwardRef(
2772
+ Card = React85__default.forwardRef(
2773
2773
  ({
2774
2774
  className,
2775
2775
  variant = "bordered",
@@ -2817,9 +2817,9 @@ var init_Card = __esm({
2817
2817
  }
2818
2818
  );
2819
2819
  Card.displayName = "Card";
2820
- CardHeader = React84__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("mb-4", className), ...props }));
2820
+ CardHeader = React85__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("mb-4", className), ...props }));
2821
2821
  CardHeader.displayName = "CardHeader";
2822
- CardTitle = React84__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
2822
+ CardTitle = React85__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
2823
2823
  "h3",
2824
2824
  {
2825
2825
  ref,
@@ -2832,11 +2832,11 @@ var init_Card = __esm({
2832
2832
  }
2833
2833
  ));
2834
2834
  CardTitle.displayName = "CardTitle";
2835
- CardContent = React84__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("", className), ...props }));
2835
+ CardContent = React85__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("", className), ...props }));
2836
2836
  CardContent.displayName = "CardContent";
2837
2837
  CardBody = CardContent;
2838
2838
  CardBody.displayName = "CardBody";
2839
- CardFooter = React84__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
2839
+ CardFooter = React85__default.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
2840
2840
  "div",
2841
2841
  {
2842
2842
  ref,
@@ -2889,7 +2889,7 @@ var init_Badge = __esm({
2889
2889
  md: "px-2.5 py-1 text-sm",
2890
2890
  lg: "px-3 py-1.5 text-base"
2891
2891
  };
2892
- Badge = React84__default.forwardRef(
2892
+ Badge = React85__default.forwardRef(
2893
2893
  ({ className, variant = "default", size = "sm", amount, label, icon, children, onRemove, removeLabel, ...props }, ref) => {
2894
2894
  const iconSizes3 = {
2895
2895
  sm: "h-icon-default w-icon-default",
@@ -2982,7 +2982,7 @@ var init_FilterPill = __esm({
2982
2982
  md: "w-3.5 h-3.5",
2983
2983
  lg: "w-4 h-4"
2984
2984
  };
2985
- FilterPill = React84__default.forwardRef(
2985
+ FilterPill = React85__default.forwardRef(
2986
2986
  ({
2987
2987
  className,
2988
2988
  variant = "default",
@@ -3111,8 +3111,8 @@ var init_Avatar = __esm({
3111
3111
  actionPayload
3112
3112
  }) => {
3113
3113
  const eventBus = useEventBus();
3114
- const [imgFailed, setImgFailed] = React84__default.useState(false);
3115
- React84__default.useEffect(() => {
3114
+ const [imgFailed, setImgFailed] = React85__default.useState(false);
3115
+ React85__default.useEffect(() => {
3116
3116
  setImgFailed(false);
3117
3117
  }, [src]);
3118
3118
  const initials = providedInitials ?? (name ? generateInitials(name) : void 0);
@@ -3364,7 +3364,7 @@ var init_Box = __esm({
3364
3364
  fixed: "fixed",
3365
3365
  sticky: "sticky"
3366
3366
  };
3367
- Box = React84__default.forwardRef(
3367
+ Box = React85__default.forwardRef(
3368
3368
  ({
3369
3369
  padding,
3370
3370
  paddingX,
@@ -3429,7 +3429,7 @@ var init_Box = __esm({
3429
3429
  onPointerDown?.(e);
3430
3430
  }, [hoverEvent, tapReveal, triggerProps, onPointerDown]);
3431
3431
  const isClickable = action || onClick;
3432
- return React84__default.createElement(
3432
+ return React85__default.createElement(
3433
3433
  Component2,
3434
3434
  {
3435
3435
  ref,
@@ -3483,7 +3483,7 @@ var init_Center = __esm({
3483
3483
  as: Component2 = "div"
3484
3484
  }) => {
3485
3485
  const mergedStyle = minHeight ? { minHeight, ...style } : style;
3486
- return React84__default.createElement(Component2, {
3486
+ return React85__default.createElement(Component2, {
3487
3487
  className: cn(
3488
3488
  inline ? "inline-flex" : "flex",
3489
3489
  horizontal && "justify-center",
@@ -3751,7 +3751,7 @@ var init_Radio = __esm({
3751
3751
  md: "w-2.5 h-2.5",
3752
3752
  lg: "w-3 h-3"
3753
3753
  };
3754
- Radio = React84__default.forwardRef(
3754
+ Radio = React85__default.forwardRef(
3755
3755
  ({
3756
3756
  label,
3757
3757
  helperText,
@@ -3768,12 +3768,12 @@ var init_Radio = __esm({
3768
3768
  onChange,
3769
3769
  ...props
3770
3770
  }, ref) => {
3771
- const reactId = React84__default.useId();
3771
+ const reactId = React85__default.useId();
3772
3772
  const baseId = id || `radio-${reactId}`;
3773
3773
  const hasError = !!error;
3774
3774
  const eventBus = useEventBus();
3775
- const [selected, setSelected] = React84__default.useState(value);
3776
- React84__default.useEffect(() => {
3775
+ const [selected, setSelected] = React85__default.useState(value);
3776
+ React85__default.useEffect(() => {
3777
3777
  if (value !== void 0) setSelected(value);
3778
3778
  }, [value]);
3779
3779
  const pick = (next, e) => {
@@ -3955,7 +3955,7 @@ var init_Switch = __esm({
3955
3955
  "components/core/atoms/Switch.tsx"() {
3956
3956
  "use client";
3957
3957
  init_cn();
3958
- Switch = React84.forwardRef(
3958
+ Switch = React85.forwardRef(
3959
3959
  ({
3960
3960
  checked,
3961
3961
  defaultChecked = false,
@@ -3966,10 +3966,10 @@ var init_Switch = __esm({
3966
3966
  name,
3967
3967
  className
3968
3968
  }, ref) => {
3969
- const [isChecked, setIsChecked] = React84.useState(
3969
+ const [isChecked, setIsChecked] = React85.useState(
3970
3970
  checked !== void 0 ? checked : defaultChecked
3971
3971
  );
3972
- React84.useEffect(() => {
3972
+ React85.useEffect(() => {
3973
3973
  if (checked !== void 0) {
3974
3974
  setIsChecked(checked);
3975
3975
  }
@@ -4128,7 +4128,7 @@ var init_Stack = __esm({
4128
4128
  };
4129
4129
  const isHorizontal = direction === "horizontal";
4130
4130
  const directionClass = responsive && isHorizontal ? reverse ? "flex-col-reverse md:flex-row-reverse" : "flex-col md:flex-row" : isHorizontal ? reverse ? "flex-row-reverse" : "flex-row" : reverse ? "flex-col-reverse" : "flex-col";
4131
- return React84__default.createElement(
4131
+ return React85__default.createElement(
4132
4132
  Component2,
4133
4133
  {
4134
4134
  className: cn(
@@ -4324,7 +4324,7 @@ var init_Typography = __esm({
4324
4324
  }) => {
4325
4325
  const variant = variantProp ?? (level ? `h${level}` : "body1");
4326
4326
  const Component2 = as || defaultElements[variant];
4327
- return React84__default.createElement(
4327
+ return React85__default.createElement(
4328
4328
  Component2,
4329
4329
  {
4330
4330
  id,
@@ -4624,7 +4624,7 @@ var Dialog;
4624
4624
  var init_Dialog = __esm({
4625
4625
  "components/core/atoms/Dialog.tsx"() {
4626
4626
  init_cn();
4627
- Dialog = React84__default.forwardRef(
4627
+ Dialog = React85__default.forwardRef(
4628
4628
  ({
4629
4629
  role = "dialog",
4630
4630
  "aria-modal": ariaModal = true,
@@ -4650,7 +4650,7 @@ var Aside;
4650
4650
  var init_Aside = __esm({
4651
4651
  "components/core/atoms/Aside.tsx"() {
4652
4652
  init_cn();
4653
- Aside = React84__default.forwardRef(
4653
+ Aside = React85__default.forwardRef(
4654
4654
  ({ className, children, ...rest }, ref) => /* @__PURE__ */ jsx("aside", { ref, className: cn(className), ...rest, children })
4655
4655
  );
4656
4656
  Aside.displayName = "Aside";
@@ -4729,9 +4729,9 @@ var init_LawReferenceTooltip = __esm({
4729
4729
  className
4730
4730
  }) => {
4731
4731
  const { t } = useTranslate();
4732
- const [isVisible, setIsVisible] = React84__default.useState(false);
4733
- const timeoutRef = React84__default.useRef(null);
4734
- const triggerRef = React84__default.useRef(null);
4732
+ const [isVisible, setIsVisible] = React85__default.useState(false);
4733
+ const timeoutRef = React85__default.useRef(null);
4734
+ const triggerRef = React85__default.useRef(null);
4735
4735
  const handleMouseEnter = () => {
4736
4736
  if (timeoutRef.current) clearTimeout(timeoutRef.current);
4737
4737
  timeoutRef.current = setTimeout(() => setIsVisible(true), 200);
@@ -4742,7 +4742,7 @@ var init_LawReferenceTooltip = __esm({
4742
4742
  };
4743
4743
  const { revealed, triggerProps } = useTapReveal({ refs: [triggerRef] });
4744
4744
  const open = isVisible || revealed;
4745
- React84__default.useEffect(() => {
4745
+ React85__default.useEffect(() => {
4746
4746
  return () => {
4747
4747
  if (timeoutRef.current) clearTimeout(timeoutRef.current);
4748
4748
  };
@@ -4954,7 +4954,7 @@ var init_StatusDot = __esm({
4954
4954
  md: "w-2.5 h-2.5",
4955
4955
  lg: "w-3 h-3"
4956
4956
  };
4957
- StatusDot = React84__default.forwardRef(
4957
+ StatusDot = React85__default.forwardRef(
4958
4958
  ({ className, status = "offline", pulse = false, size = "md", label, ...props }, ref) => {
4959
4959
  return /* @__PURE__ */ jsx(
4960
4960
  "span",
@@ -5008,7 +5008,7 @@ var init_TrendIndicator = __esm({
5008
5008
  down: "trending-down",
5009
5009
  flat: "arrow-right"
5010
5010
  };
5011
- TrendIndicator = React84__default.forwardRef(
5011
+ TrendIndicator = React85__default.forwardRef(
5012
5012
  ({
5013
5013
  className,
5014
5014
  value,
@@ -5075,7 +5075,7 @@ var init_RangeSlider = __esm({
5075
5075
  md: "w-4 h-4",
5076
5076
  lg: "w-5 h-5"
5077
5077
  };
5078
- RangeSlider = React84__default.forwardRef(
5078
+ RangeSlider = React85__default.forwardRef(
5079
5079
  ({
5080
5080
  className,
5081
5081
  min = 0,
@@ -5671,7 +5671,7 @@ var init_ContentSection = __esm({
5671
5671
  md: "py-16",
5672
5672
  lg: "py-24"
5673
5673
  };
5674
- ContentSection = React84__default.forwardRef(
5674
+ ContentSection = React85__default.forwardRef(
5675
5675
  ({ children, background = "default", padding = "lg", id, className }, ref) => {
5676
5676
  return /* @__PURE__ */ jsx(
5677
5677
  Box,
@@ -6205,7 +6205,7 @@ var init_AnimatedReveal = __esm({
6205
6205
  "scale-up": { opacity: 1, transform: "scale(1) translateY(0)" },
6206
6206
  "none": {}
6207
6207
  };
6208
- AnimatedReveal = React84__default.forwardRef(
6208
+ AnimatedReveal = React85__default.forwardRef(
6209
6209
  ({
6210
6210
  trigger = "scroll",
6211
6211
  animation = "fade-up",
@@ -6365,7 +6365,7 @@ var init_AnimatedGraphic = __esm({
6365
6365
  "components/marketing/atoms/AnimatedGraphic.tsx"() {
6366
6366
  "use client";
6367
6367
  init_cn();
6368
- AnimatedGraphic = React84__default.forwardRef(
6368
+ AnimatedGraphic = React85__default.forwardRef(
6369
6369
  ({
6370
6370
  src,
6371
6371
  svgContent,
@@ -6388,7 +6388,7 @@ var init_AnimatedGraphic = __esm({
6388
6388
  const fetchedSvg = useFetchedSvg(svgContent ? void 0 : src);
6389
6389
  const resolvedSvg = svgContent ?? fetchedSvg;
6390
6390
  const prevAnimateRef = useRef(animate);
6391
- const setRef = React84__default.useCallback(
6391
+ const setRef = React85__default.useCallback(
6392
6392
  (node) => {
6393
6393
  containerRef.current = node;
6394
6394
  if (typeof ref === "function") ref(node);
@@ -7070,7 +7070,7 @@ var init_ErrorBoundary = __esm({
7070
7070
  }
7071
7071
  );
7072
7072
  };
7073
- ErrorBoundary = class extends React84__default.Component {
7073
+ ErrorBoundary = class extends React85__default.Component {
7074
7074
  constructor(props) {
7075
7075
  super(props);
7076
7076
  __publicField(this, "reset", () => {
@@ -7368,7 +7368,7 @@ var init_Container = __esm({
7368
7368
  as: Component2 = "div"
7369
7369
  }) => {
7370
7370
  const resolvedSize = maxWidth ?? size ?? "lg";
7371
- return React84__default.createElement(
7371
+ return React85__default.createElement(
7372
7372
  Component2,
7373
7373
  {
7374
7374
  className: cn(
@@ -8189,9 +8189,9 @@ function ControlButton({
8189
8189
  className
8190
8190
  }) {
8191
8191
  const eventBus = useEventBus();
8192
- const [isPressed, setIsPressed] = React84.useState(false);
8192
+ const [isPressed, setIsPressed] = React85.useState(false);
8193
8193
  const actualPressed = pressed ?? isPressed;
8194
- const handlePointerDown = React84.useCallback(
8194
+ const handlePointerDown = React85.useCallback(
8195
8195
  (e) => {
8196
8196
  e.preventDefault();
8197
8197
  if (disabled) return;
@@ -8201,7 +8201,7 @@ function ControlButton({
8201
8201
  },
8202
8202
  [disabled, pressEvent, eventBus, onPress]
8203
8203
  );
8204
- const handlePointerUp = React84.useCallback(
8204
+ const handlePointerUp = React85.useCallback(
8205
8205
  (e) => {
8206
8206
  e.preventDefault();
8207
8207
  if (disabled) return;
@@ -8211,7 +8211,7 @@ function ControlButton({
8211
8211
  },
8212
8212
  [disabled, releaseEvent, eventBus, onRelease]
8213
8213
  );
8214
- const handlePointerLeave = React84.useCallback(
8214
+ const handlePointerLeave = React85.useCallback(
8215
8215
  (e) => {
8216
8216
  if (isPressed) {
8217
8217
  setIsPressed(false);
@@ -8299,8 +8299,8 @@ function ActionButtons({
8299
8299
  disabled
8300
8300
  }) {
8301
8301
  const eventBus = useEventBus();
8302
- const [activeButtons, setActiveButtons] = React84.useState(/* @__PURE__ */ new Set());
8303
- const handlePress = React84.useCallback(
8302
+ const [activeButtons, setActiveButtons] = React85.useState(/* @__PURE__ */ new Set());
8303
+ const handlePress = React85.useCallback(
8304
8304
  (id) => {
8305
8305
  setActiveButtons((prev) => new Set(prev).add(id));
8306
8306
  if (actionEvent) eventBus.emit(`UI:${actionEvent}`, { id, pressed: true });
@@ -8308,7 +8308,7 @@ function ActionButtons({
8308
8308
  },
8309
8309
  [actionEvent, eventBus, onAction]
8310
8310
  );
8311
- const handleRelease = React84.useCallback(
8311
+ const handleRelease = React85.useCallback(
8312
8312
  (id) => {
8313
8313
  setActiveButtons((prev) => {
8314
8314
  const next = new Set(prev);
@@ -9138,48 +9138,185 @@ var init_AuthLayout = __esm({
9138
9138
  AuthLayout.displayName = "AuthLayout";
9139
9139
  }
9140
9140
  });
9141
- var LoadingState;
9142
- var init_LoadingState = __esm({
9143
- "components/core/molecules/LoadingState.tsx"() {
9144
- "use client";
9145
- init_cn();
9146
- init_atoms2();
9147
- init_Stack();
9148
- init_Typography();
9149
- LoadingState = ({
9150
- title,
9151
- message,
9152
- className
9153
- }) => {
9154
- const { t } = useTranslate();
9155
- const displayMessage = message ?? t("common.loading");
9156
- return /* @__PURE__ */ jsxs(
9157
- VStack,
9141
+ function MiniMap({
9142
+ tiles = DEFAULT_TILES,
9143
+ units = DEFAULT_UNITS,
9144
+ width = 150,
9145
+ height = 150,
9146
+ mapWidth = 100,
9147
+ mapHeight = 100,
9148
+ viewportRect = DEFAULT_VIEWPORT,
9149
+ className
9150
+ }) {
9151
+ const canvasRef = React85.useRef(null);
9152
+ const frameRef = React85.useRef(0);
9153
+ React85.useEffect(() => {
9154
+ const canvas = canvasRef.current;
9155
+ if (!canvas) return;
9156
+ const ctx = canvas.getContext("2d");
9157
+ if (!ctx) return;
9158
+ const scaleX = width / mapWidth;
9159
+ const scaleY = height / mapHeight;
9160
+ let blinkOn = true;
9161
+ let animFrame;
9162
+ function draw() {
9163
+ if (!ctx) return;
9164
+ ctx.clearRect(0, 0, width, height);
9165
+ ctx.fillStyle = "#111";
9166
+ ctx.fillRect(0, 0, width, height);
9167
+ for (const tile of tiles) {
9168
+ ctx.fillStyle = tile.color;
9169
+ ctx.fillRect(
9170
+ Math.floor(tile.x * scaleX),
9171
+ Math.floor(tile.y * scaleY),
9172
+ Math.max(1, Math.ceil(scaleX)),
9173
+ Math.max(1, Math.ceil(scaleY))
9174
+ );
9175
+ }
9176
+ for (const unit of units) {
9177
+ if (unit.isPlayer && !blinkOn) continue;
9178
+ ctx.fillStyle = unit.isPlayer ? "#ffffff" : unit.color;
9179
+ const ux = Math.floor(unit.x * scaleX) - 1;
9180
+ const uy = Math.floor(unit.y * scaleY) - 1;
9181
+ ctx.fillRect(ux, uy, 3, 3);
9182
+ }
9183
+ if (viewportRect) {
9184
+ ctx.strokeStyle = "#ffffff";
9185
+ ctx.lineWidth = 1;
9186
+ ctx.strokeRect(
9187
+ Math.floor(viewportRect.x * scaleX),
9188
+ Math.floor(viewportRect.y * scaleY),
9189
+ Math.floor(viewportRect.w * scaleX),
9190
+ Math.floor(viewportRect.h * scaleY)
9191
+ );
9192
+ }
9193
+ }
9194
+ function tick() {
9195
+ frameRef.current++;
9196
+ if (frameRef.current % 30 === 0) {
9197
+ blinkOn = !blinkOn;
9198
+ }
9199
+ draw();
9200
+ animFrame = requestAnimationFrame(tick);
9201
+ }
9202
+ tick();
9203
+ return () => {
9204
+ cancelAnimationFrame(animFrame);
9205
+ };
9206
+ }, [tiles, units, width, height, mapWidth, mapHeight, viewportRect]);
9207
+ return /* @__PURE__ */ jsx(
9208
+ "div",
9209
+ {
9210
+ className: cn(
9211
+ "relative inline-block border border-border/20 rounded-container",
9212
+ className
9213
+ ),
9214
+ children: /* @__PURE__ */ jsx(
9215
+ "canvas",
9158
9216
  {
9159
- align: "center",
9160
- className: cn(
9161
- "justify-center py-12",
9162
- className
9163
- ),
9164
- children: [
9165
- /* @__PURE__ */ jsx(Spinner, { size: "lg" }),
9166
- title && /* @__PURE__ */ jsx(Typography, { variant: "h3", className: "mt-4 text-lg font-semibold text-foreground", children: title }),
9167
- /* @__PURE__ */ jsx(
9168
- Typography,
9169
- {
9170
- variant: "small",
9171
- className: cn(
9172
- "text-muted-foreground",
9173
- title ? "mt-2" : "mt-4"
9174
- ),
9175
- children: displayMessage
9176
- }
9177
- )
9178
- ]
9217
+ ref: canvasRef,
9218
+ width,
9219
+ height,
9220
+ className: "block",
9221
+ style: { width, height }
9179
9222
  }
9180
- );
9223
+ )
9224
+ }
9225
+ );
9226
+ }
9227
+ var DEFAULT_TILES, DEFAULT_UNITS, DEFAULT_VIEWPORT;
9228
+ var init_MiniMap = __esm({
9229
+ "components/game/atoms/MiniMap.tsx"() {
9230
+ "use client";
9231
+ init_cn();
9232
+ DEFAULT_TILES = [
9233
+ { x: 10, y: 10, color: "#4ade80" },
9234
+ { x: 20, y: 15, color: "#4ade80" },
9235
+ { x: 30, y: 25, color: "#22c55e" },
9236
+ { x: 50, y: 40, color: "#4ade80" },
9237
+ { x: 60, y: 55, color: "#16a34a" },
9238
+ { x: 40, y: 60, color: "#4ade80" },
9239
+ { x: 70, y: 30, color: "#22c55e" },
9240
+ { x: 80, y: 70, color: "#4ade80" }
9241
+ ];
9242
+ DEFAULT_UNITS = [
9243
+ { x: 30, y: 30, color: "#60a5fa", isPlayer: true }
9244
+ ];
9245
+ DEFAULT_VIEWPORT = { x: 20, y: 20, w: 40, h: 40 };
9246
+ MiniMap.displayName = "MiniMap";
9247
+ }
9248
+ });
9249
+ function HealthBar({
9250
+ current = 3,
9251
+ max = 5,
9252
+ format = "hearts",
9253
+ size = "md",
9254
+ className,
9255
+ animated = true
9256
+ }) {
9257
+ const sizes = sizeMap4[size];
9258
+ const percentage = Math.max(0, Math.min(100, current / max * 100));
9259
+ if (format === "hearts") {
9260
+ return /* @__PURE__ */ jsx("div", { className: cn("flex items-center gap-1", className), children: Array.from({ length: max }).map((_, i) => /* @__PURE__ */ jsx(
9261
+ "span",
9262
+ {
9263
+ className: cn(animated && "transition-transform hover:scale-110"),
9264
+ children: heartIcon(i < current, sizes.heart)
9265
+ },
9266
+ i
9267
+ )) });
9268
+ }
9269
+ if (format === "bar") {
9270
+ return /* @__PURE__ */ jsx(
9271
+ "div",
9272
+ {
9273
+ className: cn(
9274
+ "relative overflow-hidden rounded-full bg-muted",
9275
+ sizes.bar,
9276
+ "w-24",
9277
+ className
9278
+ ),
9279
+ children: /* @__PURE__ */ jsx(
9280
+ "div",
9281
+ {
9282
+ className: cn(
9283
+ "absolute inset-y-0 left-0 rounded-full",
9284
+ percentage > 66 ? "bg-success" : percentage > 33 ? "bg-warning" : "bg-error",
9285
+ animated && "transition-all duration-300"
9286
+ ),
9287
+ style: { width: `${percentage}%` }
9288
+ }
9289
+ )
9290
+ }
9291
+ );
9292
+ }
9293
+ return /* @__PURE__ */ jsxs("span", { className: cn("font-mono font-bold", sizes.text, className), children: [
9294
+ current,
9295
+ "/",
9296
+ max
9297
+ ] });
9298
+ }
9299
+ var heartIcon, sizeMap4;
9300
+ var init_HealthBar = __esm({
9301
+ "components/game/atoms/HealthBar.tsx"() {
9302
+ init_cn();
9303
+ heartIcon = (filled, size) => /* @__PURE__ */ jsx(
9304
+ "svg",
9305
+ {
9306
+ className: cn("transition-all duration-200", size, filled ? "text-error" : "text-muted-foreground"),
9307
+ viewBox: "0 0 24 24",
9308
+ fill: filled ? "currentColor" : "none",
9309
+ stroke: "currentColor",
9310
+ strokeWidth: filled ? 0 : 2,
9311
+ children: /* @__PURE__ */ jsx("path", { d: "M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z" })
9312
+ }
9313
+ );
9314
+ sizeMap4 = {
9315
+ sm: { heart: "w-4 h-4", bar: "h-2", text: "text-sm" },
9316
+ md: { heart: "w-6 h-6", bar: "h-3", text: "text-base" },
9317
+ lg: { heart: "w-8 h-8", bar: "h-4", text: "text-lg" }
9181
9318
  };
9182
- LoadingState.displayName = "LoadingState";
9319
+ HealthBar.displayName = "HealthBar";
9183
9320
  }
9184
9321
  });
9185
9322
  function getState() {
@@ -9737,9 +9874,6 @@ function useUnitSpriteAtlas(units) {
9737
9874
  const loadingRef = useRef(/* @__PURE__ */ new Set());
9738
9875
  const [pendingCount, setPendingCount] = useState(0);
9739
9876
  const [, forceTick] = useState(0);
9740
- const animStatesRef = useRef(/* @__PURE__ */ new Map());
9741
- const lastTickRef = useRef(0);
9742
- const rafRef = useRef(0);
9743
9877
  const atlasUrls = useMemo(() => {
9744
9878
  const set = /* @__PURE__ */ new Set();
9745
9879
  for (const unit of units) {
@@ -9785,54 +9919,6 @@ function useUnitSpriteAtlas(units) {
9785
9919
  }
9786
9920
  return [...urls];
9787
9921
  }, [units, pendingCount]);
9788
- useEffect(() => {
9789
- const hasAtlasUnits = units.some((u) => unitAtlasUrl(u) !== null);
9790
- if (!hasAtlasUnits) return;
9791
- let running = true;
9792
- const tick = (ts) => {
9793
- if (!running) return;
9794
- const last = lastTickRef.current || ts;
9795
- const delta = ts - last;
9796
- lastTickRef.current = ts;
9797
- const states = animStatesRef.current;
9798
- const currentIds = /* @__PURE__ */ new Set();
9799
- for (const unit of units) {
9800
- if (unitAtlasUrl(unit) === null) continue;
9801
- currentIds.add(unit.id);
9802
- let state = states.get(unit.id);
9803
- if (!state) {
9804
- state = { animation: "idle", direction: "se", elapsed: 0, walkHold: 0, prev: null };
9805
- states.set(unit.id, state);
9806
- }
9807
- const posX = unit.position?.x ?? unit.x ?? 0;
9808
- const posY = unit.position?.y ?? unit.y ?? 0;
9809
- if (state.prev) {
9810
- const dx = posX - state.prev.x;
9811
- const dy = posY - state.prev.y;
9812
- if (dx !== 0 || dy !== 0) {
9813
- state.animation = "walk";
9814
- state.direction = inferDirection(dx, dy);
9815
- state.walkHold = WALK_HOLD_MS;
9816
- } else if (state.animation === "walk") {
9817
- state.walkHold -= delta;
9818
- if (state.walkHold <= 0) state.animation = "idle";
9819
- }
9820
- }
9821
- state.prev = { x: posX, y: posY };
9822
- state.elapsed += delta;
9823
- }
9824
- for (const id of states.keys()) {
9825
- if (!currentIds.has(id)) states.delete(id);
9826
- }
9827
- rafRef.current = requestAnimationFrame(tick);
9828
- };
9829
- rafRef.current = requestAnimationFrame(tick);
9830
- return () => {
9831
- running = false;
9832
- cancelAnimationFrame(rafRef.current);
9833
- lastTickRef.current = 0;
9834
- };
9835
- }, [units]);
9836
9922
  const resolveUnitFrame = useCallback((unitId) => {
9837
9923
  const unit = units.find((u) => u.id === unitId);
9838
9924
  if (!unit) return null;
@@ -9840,18 +9926,14 @@ function useUnitSpriteAtlas(units) {
9840
9926
  if (!atlasUrl) return null;
9841
9927
  const atlas = atlasCacheRef.current.get(atlasUrl);
9842
9928
  if (!atlas) return null;
9843
- const state = animStatesRef.current.get(unitId);
9844
- const animation = state?.animation ?? "idle";
9845
- const direction = state?.direction ?? "se";
9846
- const elapsed = state?.elapsed ?? 0;
9929
+ const animation = unit.animation ?? "idle";
9930
+ const frame = unit.frame ?? 0;
9847
9931
  const def = atlas.animations[animation] ?? atlas.animations.idle;
9848
9932
  if (!def) return null;
9849
- const { sheetDir, flipX } = resolveSheetDirection(direction);
9933
+ const { sheetDir, flipX } = resolveSheetDirection("se");
9850
9934
  const rel = atlas.sheets[sheetDir] ?? atlas.sheets.se ?? atlas.sheets.sw;
9851
9935
  if (!rel) return null;
9852
9936
  const sheetUrl = resolveSheetUrl(atlasUrl, rel);
9853
- const isIdle = animation === "idle";
9854
- const frame = isIdle ? 0 : getCurrentFrameFromDef(def, elapsed).frame;
9855
9937
  const rect = frameRect(frame, def.row, atlas.columns, atlas.frameWidth, atlas.frameHeight);
9856
9938
  return {
9857
9939
  sheetUrl,
@@ -9860,17 +9942,15 @@ function useUnitSpriteAtlas(units) {
9860
9942
  sw: rect.sw,
9861
9943
  sh: rect.sh,
9862
9944
  flipX,
9863
- applyBreathing: isIdle
9945
+ applyBreathing: animation === "idle"
9864
9946
  };
9865
9947
  }, [units]);
9866
9948
  return { sheetUrls, resolveUnitFrame, pendingCount };
9867
9949
  }
9868
- var WALK_HOLD_MS;
9869
9950
  var init_useUnitSpriteAtlas = __esm({
9870
9951
  "components/game/molecules/useUnitSpriteAtlas.ts"() {
9871
9952
  "use client";
9872
9953
  init_spriteAnimation();
9873
- WALK_HOLD_MS = 600;
9874
9954
  }
9875
9955
  });
9876
9956
 
@@ -9938,6 +10018,7 @@ function IsometricCanvas({
9938
10018
  tiles: _tilesPropRaw = [],
9939
10019
  units: _unitsPropRaw = [],
9940
10020
  features: _featuresPropRaw = [],
10021
+ effects: _effectsPropRaw = [],
9941
10022
  // Interaction state
9942
10023
  selectedUnitId = null,
9943
10024
  validMoves = [],
@@ -9970,7 +10051,7 @@ function IsometricCanvas({
9970
10051
  resolveUnitFrame,
9971
10052
  effectSpriteUrls = [],
9972
10053
  onDrawEffects,
9973
- hasActiveEffects: hasActiveEffects2 = false,
10054
+ hasActiveEffects: _hasActiveEffects = false,
9974
10055
  // Tuning
9975
10056
  diamondTopY: diamondTopYProp,
9976
10057
  // Remote asset loading
@@ -9980,13 +10061,12 @@ function IsometricCanvas({
9980
10061
  const tilesProp = Array.isArray(_tilesPropRaw) ? _tilesPropRaw : [];
9981
10062
  const unitsProp = Array.isArray(_unitsPropRaw) ? _unitsPropRaw : [];
9982
10063
  const featuresProp = Array.isArray(_featuresPropRaw) ? _featuresPropRaw : [];
10064
+ const effects = Array.isArray(_effectsPropRaw) ? _effectsPropRaw : [];
9983
10065
  const eventBus = useEventBus();
9984
10066
  const { t } = useTranslate();
9985
10067
  const canvasRef = useRef(null);
9986
10068
  const containerRef = useRef(null);
9987
- const minimapRef = useRef(null);
9988
- const animTimeRef = useRef(0);
9989
- const rafIdRef = useRef(0);
10069
+ const lerpRafRef = useRef(0);
9990
10070
  const [viewportSize, setViewportSize] = useState({ width: 800, height: 600 });
9991
10071
  useEffect(() => {
9992
10072
  const el = containerRef.current;
@@ -10010,7 +10090,7 @@ function IsometricCanvas({
10010
10090
  () => unitsProp.map((u) => u.position ? u : { ...u, position: { x: u.x ?? 0, y: u.y ?? 0 } }),
10011
10091
  [unitsProp]
10012
10092
  );
10013
- const { sheetUrls: atlasSheetUrls, resolveUnitFrame: resolveUnitFrameInternal, pendingCount: atlasPending } = useUnitSpriteAtlas(units);
10093
+ const { sheetUrls: atlasSheetUrls, resolveUnitFrame: resolveUnitFrameInternal } = useUnitSpriteAtlas(units);
10014
10094
  const resolveFrameForUnit = useCallback((unitId) => {
10015
10095
  return resolveUnitFrame?.(unitId) ?? resolveUnitFrameInternal(unitId);
10016
10096
  }, [resolveUnitFrame, resolveUnitFrameInternal]);
@@ -10105,7 +10185,7 @@ function IsometricCanvas({
10105
10185
  if (backgroundImage) urls.push(backgroundImage);
10106
10186
  return [...new Set(urls.filter(Boolean))];
10107
10187
  }, [sortedTiles, features, units, getTerrainSprite, getFeatureSprite, getUnitSprite, effectSpriteUrls, atlasSheetUrls, backgroundImage, assetManifest, resolveManifestUrl7]);
10108
- const { getImage, pendingCount } = useImageCache(spriteUrls);
10188
+ const { getImage, pendingCount: _imagePendingCount } = useImageCache(spriteUrls);
10109
10189
  useEffect(() => {
10110
10190
  if (typeof window === "undefined") return;
10111
10191
  const canvas = canvasRef.current;
@@ -10137,63 +10217,26 @@ function IsometricCanvas({
10137
10217
  const resolveUnitSpriteUrl = useCallback((unit) => {
10138
10218
  return unit.sprite || getUnitSprite?.(unit) || (unit.unitType ? resolveManifestUrl7(assetManifest?.units?.[unit.unitType]) : void 0);
10139
10219
  }, [getUnitSprite, assetManifest, resolveManifestUrl7]);
10140
- const drawMinimap = useCallback(() => {
10141
- if (!showMinimap) return;
10142
- const miniCanvas = minimapRef.current;
10143
- if (!miniCanvas || sortedTiles.length === 0) return;
10144
- const mCtx = miniCanvas.getContext("2d");
10145
- if (!mCtx) return;
10146
- const mW = 150;
10147
- const mH = 100;
10148
- miniCanvas.width = mW;
10149
- miniCanvas.height = mH;
10150
- mCtx.clearRect(0, 0, mW, mH);
10151
- const allScreenPos = sortedTiles.map((t2) => isoToScreen(t2.x, t2.y, scale, baseOffsetX, tileLayout));
10152
- const minX = Math.min(...allScreenPos.map((p2) => p2.x));
10153
- const maxX = Math.max(...allScreenPos.map((p2) => p2.x + scaledTileWidth));
10154
- const minY = Math.min(...allScreenPos.map((p2) => p2.y));
10155
- const tileBottomExtent = tileLayout === "hex" || tileLayout === "flat" ? scaledTileWidth : scaledTileHeight;
10156
- const maxY = Math.max(...allScreenPos.map((p2) => p2.y + tileBottomExtent));
10157
- const worldW = maxX - minX;
10158
- const worldH = maxY - minY;
10159
- const scaleM = Math.min(mW / worldW, mH / worldH) * 0.9;
10160
- const offsetMx = (mW - worldW * scaleM) / 2;
10161
- const offsetMy = (mH - worldH * scaleM) / 2;
10162
- for (const tile of sortedTiles) {
10163
- const pos = isoToScreen(tile.x, tile.y, scale, baseOffsetX, tileLayout);
10164
- const mx = (pos.x - minX) * scaleM + offsetMx;
10165
- const my = (pos.y - minY) * scaleM + offsetMy;
10166
- const mTileW = scaledTileWidth * scaleM;
10167
- const mFloorH = scaledFloorHeight * scaleM;
10168
- mCtx.fillStyle = tile.terrain === "water" ? "#3b82f6" : tile.terrain === "mountain" ? "#78716c" : "#4ade80";
10169
- mCtx.beginPath();
10170
- mCtx.moveTo(mx + mTileW / 2, my);
10171
- mCtx.lineTo(mx + mTileW, my + mFloorH / 2);
10172
- mCtx.lineTo(mx + mTileW / 2, my + mFloorH);
10173
- mCtx.lineTo(mx, my + mFloorH / 2);
10174
- mCtx.closePath();
10175
- mCtx.fill();
10176
- }
10177
- for (const unit of units) {
10178
- if (!unit.position) continue;
10179
- const pos = isoToScreen(unit.position.x, unit.position.y, scale, baseOffsetX, tileLayout);
10180
- const mx = (pos.x + scaledTileWidth / 2 - minX) * scaleM + offsetMx;
10181
- const my = (pos.y + scaledTileHeight / 2 - minY) * scaleM + offsetMy;
10182
- mCtx.fillStyle = unit.team === "player" ? "#60a5fa" : unit.team === "enemy" ? "#f87171" : "#9ca3af";
10183
- mCtx.beginPath();
10184
- mCtx.arc(mx, my, 3, 0, Math.PI * 2);
10185
- mCtx.fill();
10186
- }
10187
- const cam = cameraRef.current;
10188
- const vLeft = (cam.x - minX) * scaleM + offsetMx;
10189
- const vTop = (cam.y - minY) * scaleM + offsetMy;
10190
- const vW = viewportSize.width / cam.zoom * scaleM;
10191
- const vH = viewportSize.height / cam.zoom * scaleM;
10192
- mCtx.strokeStyle = "rgba(255, 255, 255, 0.8)";
10193
- mCtx.lineWidth = 1;
10194
- mCtx.strokeRect(vLeft, vTop, vW, vH);
10195
- }, [showMinimap, sortedTiles, units, tileLayout, scale, baseOffsetX, scaledTileWidth, scaledTileHeight, scaledFloorHeight, viewportSize, cameraRef]);
10196
- const draw = useCallback((animTime) => {
10220
+ const miniMapTiles = useMemo(() => {
10221
+ if (!showMinimap) return [];
10222
+ return sortedTiles.map((t2) => ({
10223
+ x: t2.x,
10224
+ y: t2.y,
10225
+ color: t2.terrain === "water" ? "#3b82f6" : t2.terrain === "mountain" ? "#78716c" : "#4ade80"
10226
+ }));
10227
+ }, [showMinimap, sortedTiles]);
10228
+ const miniMapUnits = useMemo(() => {
10229
+ if (!showMinimap) return [];
10230
+ return units.filter((u) => u.position).map((u) => ({
10231
+ x: u.position.x,
10232
+ y: u.position.y,
10233
+ color: u.team === "player" ? "#60a5fa" : u.team === "enemy" ? "#f87171" : "#9ca3af",
10234
+ isPlayer: u.team === "player"
10235
+ }));
10236
+ }, [showMinimap, units]);
10237
+ const miniMapWidth = gridWidth || 10;
10238
+ const miniMapHeight = gridHeight || 10;
10239
+ const draw = useCallback(() => {
10197
10240
  const canvas = canvasRef.current;
10198
10241
  if (!canvas) return;
10199
10242
  const ctx = canvas.getContext("2d");
@@ -10279,8 +10322,7 @@ function IsometricCanvas({
10279
10322
  if (validMoveSet.has(tileKey)) {
10280
10323
  const centerX = pos.x + scaledTileWidth / 2;
10281
10324
  const topY = pos.y + scaledDiamondTopY;
10282
- const pulse = 0.15 + 0.1 * Math.sin(animTime * 4e-3);
10283
- ctx.fillStyle = `rgba(74, 222, 128, ${pulse})`;
10325
+ ctx.fillStyle = "rgba(74, 222, 128, 0.25)";
10284
10326
  ctx.beginPath();
10285
10327
  ctx.moveTo(centerX, topY);
10286
10328
  ctx.lineTo(pos.x + scaledTileWidth, topY + scaledFloorHeight / 2);
@@ -10292,8 +10334,7 @@ function IsometricCanvas({
10292
10334
  if (attackTargetSet.has(tileKey)) {
10293
10335
  const centerX = pos.x + scaledTileWidth / 2;
10294
10336
  const topY = pos.y + scaledDiamondTopY;
10295
- const pulse = 0.2 + 0.15 * Math.sin(animTime * 5e-3);
10296
- ctx.fillStyle = `rgba(239, 68, 68, ${pulse})`;
10337
+ ctx.fillStyle = "rgba(239, 68, 68, 0.35)";
10297
10338
  ctx.beginPath();
10298
10339
  ctx.moveTo(centerX, topY);
10299
10340
  ctx.lineTo(pos.x + scaledTileWidth, topY + scaledFloorHeight / 2);
@@ -10366,7 +10407,7 @@ function IsometricCanvas({
10366
10407
  const isSelected = unit.id === selectedUnitId;
10367
10408
  const centerX = pos.x + scaledTileWidth / 2;
10368
10409
  const groundY = pos.y + scaledDiamondTopY + scaledFloorHeight * 0.5;
10369
- const breatheOffset = 0.8 * scale * (1 + Math.sin(animTime * 2e-3 + (unit.position.x * 3.7 + unit.position.y * 5.3)));
10410
+ const breatheOffset = 0;
10370
10411
  const unitSpriteUrl = resolveUnitSpriteUrl(unit);
10371
10412
  const img = unitSpriteUrl ? getImage(unitSpriteUrl) : null;
10372
10413
  const unitDrawH = scaledFloorHeight * spriteHeightRatio * unitScale;
@@ -10406,10 +10447,9 @@ function IsometricCanvas({
10406
10447
  ctx.restore();
10407
10448
  }
10408
10449
  if (isSelected) {
10409
- const ringAlpha = 0.6 + 0.3 * Math.sin(animTime * 4e-3);
10410
10450
  ctx.beginPath();
10411
10451
  ctx.ellipse(centerX, groundY, drawW / 2 + 4 * scale, 12 * scale, 0, 0, Math.PI * 2);
10412
- ctx.strokeStyle = `rgba(0, 200, 255, ${ringAlpha})`;
10452
+ ctx.strokeStyle = "rgba(0, 200, 255, 0.8)";
10413
10453
  ctx.lineWidth = 3;
10414
10454
  ctx.stroke();
10415
10455
  }
@@ -10465,66 +10505,29 @@ function IsometricCanvas({
10465
10505
  ctx.lineWidth = 2;
10466
10506
  ctx.stroke();
10467
10507
  }
10468
- if (unit.name) {
10469
- 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)";
10470
- ctx.font = `bold ${10 * scale * 2.5}px system-ui`;
10471
- ctx.textAlign = "center";
10472
- const textWidth = ctx.measureText(unit.name).width;
10473
- const labelY = groundY + 14 * scale - breatheOffset;
10474
- ctx.fillStyle = labelBg;
10475
- ctx.beginPath();
10476
- ctx.roundRect(centerX - textWidth / 2 - 6 * scale, labelY - 8 * scale, textWidth + 12 * scale, 16 * scale, 4 * scale);
10477
- ctx.fill();
10478
- ctx.fillStyle = "white";
10479
- ctx.fillText(unit.name, centerX, labelY + 4 * scale);
10480
- }
10481
- if (unit.health !== void 0 && unit.maxHealth !== void 0) {
10482
- const barWidth = 40 * scale;
10483
- const barHeight = 6 * scale;
10484
- const barX = centerX - barWidth / 2;
10485
- const barY = groundY - drawH - 2 * scale - breatheOffset;
10486
- const healthRatio = unit.health / unit.maxHealth;
10487
- const barRadius = barHeight / 2;
10488
- ctx.fillStyle = "rgba(0, 0, 0, 0.7)";
10489
- ctx.beginPath();
10490
- ctx.roundRect(barX, barY, barWidth, barHeight, barRadius);
10491
- ctx.fill();
10492
- if (healthRatio > 0) {
10493
- const fillWidth = barWidth * healthRatio;
10494
- const gradient = ctx.createLinearGradient(barX, barY, barX, barY + barHeight);
10495
- if (healthRatio > 0.6) {
10496
- gradient.addColorStop(0, "#4ade80");
10497
- gradient.addColorStop(1, "#22c55e");
10498
- } else if (healthRatio > 0.3) {
10499
- gradient.addColorStop(0, "#fde047");
10500
- gradient.addColorStop(1, "#eab308");
10501
- } else {
10502
- gradient.addColorStop(0, "#f87171");
10503
- gradient.addColorStop(1, "#ef4444");
10504
- }
10505
- ctx.fillStyle = gradient;
10506
- ctx.save();
10507
- ctx.beginPath();
10508
- ctx.roundRect(barX, barY, fillWidth, barHeight, barRadius);
10509
- ctx.clip();
10510
- ctx.fillRect(barX, barY, fillWidth, barHeight);
10511
- ctx.restore();
10512
- }
10513
- ctx.strokeStyle = "rgba(255, 255, 255, 0.3)";
10514
- ctx.lineWidth = 1;
10515
- ctx.beginPath();
10516
- ctx.roundRect(barX, barY, barWidth, barHeight, barRadius);
10517
- ctx.stroke();
10518
- }
10519
10508
  }
10520
- onDrawEffects?.(ctx, animTime, getImage);
10509
+ for (const fx of effects) {
10510
+ const spriteUrl = resolveManifestUrl7(assetManifest?.effects?.[fx.key]);
10511
+ if (!spriteUrl) continue;
10512
+ const img = getImage(spriteUrl);
10513
+ if (!img) continue;
10514
+ const pos = isoToScreen(fx.x, fx.y, scale, baseOffsetX, tileLayout);
10515
+ const cx = pos.x + scaledTileWidth / 2;
10516
+ const cy = pos.y + scaledDiamondTopY + scaledFloorHeight * 0.5;
10517
+ const alpha = Math.min(1, fx.ttl / 4);
10518
+ const prev = ctx.globalAlpha;
10519
+ ctx.globalAlpha = alpha;
10520
+ ctx.drawImage(img, cx - img.naturalWidth / 2, cy - img.naturalHeight / 2);
10521
+ ctx.globalAlpha = prev;
10522
+ }
10523
+ onDrawEffects?.(ctx, 0, getImage);
10521
10524
  ctx.restore();
10522
- drawMinimap();
10523
10525
  }, [
10524
10526
  sortedTiles,
10525
10527
  units,
10526
10528
  features,
10527
10529
  selectedUnitId,
10530
+ effects,
10528
10531
  tileLayout,
10529
10532
  scale,
10530
10533
  debug2,
@@ -10544,11 +10547,12 @@ function IsometricCanvas({
10544
10547
  attackTargetSet,
10545
10548
  hoveredTile,
10546
10549
  viewportSize,
10547
- drawMinimap,
10548
10550
  onDrawEffects,
10549
10551
  backgroundImage,
10550
10552
  cameraRef,
10551
- unitScale
10553
+ unitScale,
10554
+ resolveManifestUrl7,
10555
+ assetManifest
10552
10556
  ]);
10553
10557
  useEffect(() => {
10554
10558
  if (!selectedUnitId) return;
@@ -10563,30 +10567,33 @@ function IsometricCanvas({
10563
10567
  };
10564
10568
  }, [selectedUnitId, units, tileLayout, scale, baseOffsetX, scaledTileWidth, scaledDiamondTopY, scaledFloorHeight, viewportSize, targetCameraRef]);
10565
10569
  useEffect(() => {
10566
- const hasAnimations = units.length > 0 || validMoves.length > 0 || attackTargets.length > 0 || selectedUnitId != null || targetCameraRef.current != null || hasActiveEffects2 || pendingCount > 0 || atlasPending > 0;
10567
- draw(animTimeRef.current);
10568
- if (!hasAnimations) return;
10570
+ draw();
10571
+ }, [draw]);
10572
+ useEffect(() => {
10573
+ draw();
10574
+ }, [_imagePendingCount]);
10575
+ useEffect(() => {
10576
+ if (selectedUnitId == null) return;
10569
10577
  let running = true;
10570
- const animate = (timestamp) => {
10578
+ const tick = () => {
10571
10579
  if (!running) return;
10572
- animTimeRef.current = timestamp;
10573
- lerpToTarget();
10574
- draw(timestamp);
10575
- rafIdRef.current = requestAnimationFrame(animate);
10580
+ const stillLerping = lerpToTarget();
10581
+ draw();
10582
+ if (stillLerping) lerpRafRef.current = requestAnimationFrame(tick);
10576
10583
  };
10577
- rafIdRef.current = requestAnimationFrame(animate);
10584
+ lerpRafRef.current = requestAnimationFrame(tick);
10578
10585
  return () => {
10579
10586
  running = false;
10580
- cancelAnimationFrame(rafIdRef.current);
10587
+ cancelAnimationFrame(lerpRafRef.current);
10581
10588
  };
10582
- }, [draw, units.length, validMoves.length, attackTargets.length, selectedUnitId, hasActiveEffects2, pendingCount, atlasPending, lerpToTarget, targetCameraRef]);
10589
+ }, [selectedUnitId, lerpToTarget, draw]);
10583
10590
  const singlePointerActiveRef = useRef(false);
10584
10591
  const handleCanvasPointerDown = useCallback((e) => {
10585
10592
  singlePointerActiveRef.current = true;
10586
10593
  if (enableCamera) handlePointerDown(e);
10587
10594
  }, [enableCamera, handlePointerDown]);
10588
10595
  const handleCanvasPointerMove = useCallback((e) => {
10589
- if (enableCamera) handlePointerMove(e, () => draw(animTimeRef.current));
10596
+ if (enableCamera) handlePointerMove(e, () => draw());
10590
10597
  }, [enableCamera, handlePointerMove, draw]);
10591
10598
  const handleCanvasHover = useCallback((e) => {
10592
10599
  if (singlePointerActiveRef.current) return;
@@ -10628,10 +10635,10 @@ function IsometricCanvas({
10628
10635
  onTileLeave?.();
10629
10636
  }, [handleMouseLeave, onTileLeave, tileLeaveEvent, eventBus]);
10630
10637
  const applyZoom = useCallback((factor, centerX, centerY) => {
10631
- if (enableCamera) zoomAtPoint(factor, centerX, centerY, viewportSize, () => draw(animTimeRef.current));
10638
+ if (enableCamera) zoomAtPoint(factor, centerX, centerY, viewportSize, () => draw());
10632
10639
  }, [enableCamera, zoomAtPoint, viewportSize, draw]);
10633
10640
  const applyPanDelta = useCallback((dx, dy) => {
10634
- if (enableCamera) panBy(dx, dy, () => draw(animTimeRef.current));
10641
+ if (enableCamera) panBy(dx, dy, () => draw());
10635
10642
  }, [enableCamera, panBy, draw]);
10636
10643
  const cancelSinglePointer = useCallback(() => {
10637
10644
  singlePointerActiveRef.current = false;
@@ -10647,11 +10654,27 @@ function IsometricCanvas({
10647
10654
  onPanDelta: applyPanDelta,
10648
10655
  onMultiTouchStart: cancelSinglePointer
10649
10656
  });
10657
+ const unitOverlays = useMemo(() => {
10658
+ if (sortedTiles.length === 0) return [];
10659
+ return units.filter((u) => !!u.position).map((u) => {
10660
+ const pos = isoToScreen(u.position.x, u.position.y, scale, baseOffsetX, tileLayout);
10661
+ const cam = cameraRef.current;
10662
+ const screenX = (pos.x + scaledTileWidth / 2 - (cam.x + viewportSize.width / 2)) * cam.zoom + viewportSize.width / 2;
10663
+ const screenY = (pos.y + scaledDiamondTopY + scaledFloorHeight * 0.5 - (cam.y + viewportSize.height / 2)) * cam.zoom + viewportSize.height / 2;
10664
+ return { unit: u, screenX, screenY };
10665
+ });
10666
+ }, [units, sortedTiles.length, scale, baseOffsetX, tileLayout, scaledTileWidth, scaledDiamondTopY, scaledFloorHeight, viewportSize, cameraRef]);
10650
10667
  if (error) {
10651
- return /* @__PURE__ */ jsx(ErrorState, { title: t("canvas.errorTitle"), message: error.message, className });
10668
+ return /* @__PURE__ */ jsx(Box, { className: cn("flex items-center justify-center w-full h-full bg-[var(--color-card)] rounded-container", className), children: /* @__PURE__ */ jsxs(Stack, { direction: "vertical", gap: "md", align: "center", children: [
10669
+ /* @__PURE__ */ jsx(Icon, { name: "alert-circle", size: "xl" }),
10670
+ /* @__PURE__ */ jsx(Typography, { variant: "body", className: "text-error", children: error.message })
10671
+ ] }) });
10652
10672
  }
10653
10673
  if (isLoading) {
10654
- return /* @__PURE__ */ jsx(LoadingState, { className });
10674
+ return /* @__PURE__ */ jsx(Box, { className: cn("flex items-center justify-center w-full h-full bg-[var(--color-card)] rounded-container", className), children: /* @__PURE__ */ jsxs(Stack, { direction: "vertical", gap: "md", align: "center", children: [
10675
+ /* @__PURE__ */ jsx(Icon, { name: "loader", size: "xl", className: "animate-spin" }),
10676
+ /* @__PURE__ */ jsx(Typography, { variant: "body", className: "text-muted-foreground", children: t("canvas.loadingMessage") || "Loading\u2026" })
10677
+ ] }) });
10655
10678
  }
10656
10679
  if (sortedTiles.length === 0) {
10657
10680
  return /* @__PURE__ */ jsx(
@@ -10716,14 +10739,36 @@ function IsometricCanvas({
10716
10739
  }
10717
10740
  )
10718
10741
  ] }),
10719
- showMinimap && /* @__PURE__ */ jsx(
10720
- "canvas",
10742
+ unitOverlays.map(({ unit, screenX, screenY }) => /* @__PURE__ */ jsxs(
10743
+ "div",
10721
10744
  {
10722
- ref: minimapRef,
10723
- className: "absolute bottom-2 right-2 border border-border rounded bg-background/80 pointer-events-none",
10724
- style: { width: 150, height: 100, zIndex: 10 }
10745
+ className: "absolute pointer-events-none",
10746
+ style: { left: Math.round(screenX), top: Math.round(screenY), transform: "translate(-50%, 0)", zIndex: 5 },
10747
+ children: [
10748
+ unit.name && /* @__PURE__ */ jsx(
10749
+ "div",
10750
+ {
10751
+ className: "text-white text-xs font-bold px-1.5 py-0.5 rounded mb-0.5 whitespace-nowrap",
10752
+ style: { background: unit.team === "player" ? "rgba(59,130,246,0.9)" : unit.team === "enemy" ? "rgba(239,68,68,0.9)" : "rgba(107,114,128,0.9)" },
10753
+ children: unit.name
10754
+ }
10755
+ ),
10756
+ unit.health !== void 0 && unit.maxHealth !== void 0 && unit.maxHealth > 0 && /* @__PURE__ */ jsx(HealthBar, { current: unit.health, max: unit.maxHealth, format: "bar", size: "sm" })
10757
+ ]
10758
+ },
10759
+ unit.id
10760
+ )),
10761
+ showMinimap && /* @__PURE__ */ jsx("div", { className: "absolute bottom-2 right-2 pointer-events-none", style: { zIndex: 10 }, children: /* @__PURE__ */ jsx(
10762
+ MiniMap,
10763
+ {
10764
+ tiles: miniMapTiles,
10765
+ units: miniMapUnits,
10766
+ width: 150,
10767
+ height: 100,
10768
+ mapWidth: miniMapWidth,
10769
+ mapHeight: miniMapHeight
10725
10770
  }
10726
- )
10771
+ ) })
10727
10772
  ]
10728
10773
  }
10729
10774
  );
@@ -10738,8 +10783,8 @@ var init_IsometricCanvas = __esm({
10738
10783
  init_Stack();
10739
10784
  init_Icon();
10740
10785
  init_Typography();
10741
- init_LoadingState();
10742
- init_ErrorState();
10786
+ init_MiniMap();
10787
+ init_HealthBar();
10743
10788
  init_useImageCache();
10744
10789
  init_useCamera();
10745
10790
  init_useCanvasGestures();
@@ -12297,6 +12342,50 @@ var init_Tabs = __esm({
12297
12342
  Tabs.displayName = "Tabs";
12298
12343
  }
12299
12344
  });
12345
+ var LoadingState;
12346
+ var init_LoadingState = __esm({
12347
+ "components/core/molecules/LoadingState.tsx"() {
12348
+ "use client";
12349
+ init_cn();
12350
+ init_atoms2();
12351
+ init_Stack();
12352
+ init_Typography();
12353
+ LoadingState = ({
12354
+ title,
12355
+ message,
12356
+ className
12357
+ }) => {
12358
+ const { t } = useTranslate();
12359
+ const displayMessage = message ?? t("common.loading");
12360
+ return /* @__PURE__ */ jsxs(
12361
+ VStack,
12362
+ {
12363
+ align: "center",
12364
+ className: cn(
12365
+ "justify-center py-12",
12366
+ className
12367
+ ),
12368
+ children: [
12369
+ /* @__PURE__ */ jsx(Spinner, { size: "lg" }),
12370
+ title && /* @__PURE__ */ jsx(Typography, { variant: "h3", className: "mt-4 text-lg font-semibold text-foreground", children: title }),
12371
+ /* @__PURE__ */ jsx(
12372
+ Typography,
12373
+ {
12374
+ variant: "small",
12375
+ className: cn(
12376
+ "text-muted-foreground",
12377
+ title ? "mt-2" : "mt-4"
12378
+ ),
12379
+ children: displayMessage
12380
+ }
12381
+ )
12382
+ ]
12383
+ }
12384
+ );
12385
+ };
12386
+ LoadingState.displayName = "LoadingState";
12387
+ }
12388
+ });
12300
12389
  var ICON_NAME_ALIASES, lookStyles3, EmptyState;
12301
12390
  var init_EmptyState = __esm({
12302
12391
  "components/core/molecules/EmptyState.tsx"() {
@@ -12577,7 +12666,7 @@ var init_CodeBlock = __esm({
12577
12666
  };
12578
12667
  LINE_PROPS_FN = (n) => ({ "data-line": String(n - 1) });
12579
12668
  HIDDEN_LINE_NUMBERS = { display: "none" };
12580
- CodeBlock = React84__default.memo(
12669
+ CodeBlock = React85__default.memo(
12581
12670
  ({
12582
12671
  code: rawCode,
12583
12672
  language = "text",
@@ -13164,7 +13253,7 @@ var init_MarkdownContent = __esm({
13164
13253
  init_Box();
13165
13254
  init_CodeBlock();
13166
13255
  init_cn();
13167
- MarkdownContent = React84__default.memo(
13256
+ MarkdownContent = React85__default.memo(
13168
13257
  ({ content, direction = "ltr", className }) => {
13169
13258
  const { t: _t } = useTranslate();
13170
13259
  const safeContent = typeof content === "string" ? content : String(content ?? "");
@@ -14533,7 +14622,7 @@ var init_StateMachineView = __esm({
14533
14622
  style: { top: title ? 30 : 0 },
14534
14623
  children: [
14535
14624
  entity && /* @__PURE__ */ jsx(EntityBox, { entity, config }),
14536
- states.map((state) => renderStateNode ? /* @__PURE__ */ jsx(React84__default.Fragment, { children: renderStateNode(state, config) }, state.id) : /* @__PURE__ */ jsx(
14625
+ states.map((state) => renderStateNode ? /* @__PURE__ */ jsx(React85__default.Fragment, { children: renderStateNode(state, config) }, state.id) : /* @__PURE__ */ jsx(
14537
14626
  StateNode,
14538
14627
  {
14539
14628
  state,
@@ -18502,7 +18591,7 @@ function CardHand({
18502
18591
  className
18503
18592
  }) {
18504
18593
  const eventBus = useEventBus();
18505
- const handleClick = React84.useCallback(
18594
+ const handleClick = React85.useCallback(
18506
18595
  (card) => {
18507
18596
  if (card.disabled) return;
18508
18597
  onCardClick?.(card.id);
@@ -21557,10 +21646,10 @@ function CombatLog({
21557
21646
  }, [events2, autoScroll]);
21558
21647
  const safeEvents = events2 ?? [];
21559
21648
  const visibleEvents = safeEvents.slice(-maxVisible);
21560
- return /* @__PURE__ */ jsxs(Card, { variant: "default", className: cn("flex flex-col", className), children: [
21649
+ return /* @__PURE__ */ jsxs(Box, { className: cn("flex flex-col rounded-container border border-border bg-card shadow-elevation-card", className), children: [
21561
21650
  /* @__PURE__ */ jsx(Box, { padding: "sm", border: true, className: "border-b-2 border-x-0 border-t-0 border-border", children: /* @__PURE__ */ jsxs(Box, { display: "flex", className: "items-center justify-between", children: [
21562
21651
  /* @__PURE__ */ jsx(Typography, { variant: "body2", className: "font-bold", children: title }),
21563
- /* @__PURE__ */ jsxs(Badge, { variant: "neutral", size: "sm", children: [
21652
+ /* @__PURE__ */ jsxs("span", { className: "text-xs text-muted-foreground bg-muted/60 rounded px-1.5 py-0.5 border border-border/50 font-mono", children: [
21564
21653
  safeEvents.length,
21565
21654
  " events"
21566
21655
  ] })
@@ -21580,7 +21669,7 @@ function CombatLog({
21580
21669
  /* @__PURE__ */ jsx(Box, { className: cn("flex-shrink-0 mt-0.5", colorClass), children: /* @__PURE__ */ jsx(EventIcon, { className: "h-4 w-4" }) }),
21581
21670
  /* @__PURE__ */ jsxs(Box, { className: "flex-1 min-w-0", children: [
21582
21671
  /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "block", children: event.message }),
21583
- event.value !== void 0 && /* @__PURE__ */ jsxs(Badge, { variant: eventBadgeVariants[eventType], size: "sm", className: "mt-1", children: [
21672
+ event.value !== void 0 && /* @__PURE__ */ jsxs("span", { className: cn("inline-block mt-1 text-xs font-bold rounded px-1.5 py-0.5 border", eventValueColors[eventType]), children: [
21584
21673
  eventType === "heal" ? "+" : eventType === "attack" ? "-" : "",
21585
21674
  event.value
21586
21675
  ] })
@@ -21593,7 +21682,7 @@ function CombatLog({
21593
21682
  }) }) })
21594
21683
  ] });
21595
21684
  }
21596
- var eventIcons, eventColors, eventBadgeVariants, DEFAULT_COMBAT_EVENTS;
21685
+ var eventIcons, eventColors, eventValueColors, DEFAULT_COMBAT_EVENTS;
21597
21686
  var init_CombatLog = __esm({
21598
21687
  "components/game/molecules/CombatLog.tsx"() {
21599
21688
  init_atoms2();
@@ -21616,14 +21705,14 @@ var init_CombatLog = __esm({
21616
21705
  death: "text-muted-foreground",
21617
21706
  spawn: "text-accent"
21618
21707
  };
21619
- eventBadgeVariants = {
21620
- attack: "danger",
21621
- defend: "primary",
21622
- heal: "success",
21623
- move: "warning",
21624
- special: "secondary",
21625
- death: "secondary",
21626
- spawn: "secondary"
21708
+ eventValueColors = {
21709
+ attack: "text-error bg-error/10 border-error/30",
21710
+ defend: "text-info bg-info/10 border-info/30",
21711
+ heal: "text-success bg-success/10 border-success/30",
21712
+ move: "text-warning bg-warning/10 border-warning/30",
21713
+ special: "text-accent bg-accent/10 border-accent/30",
21714
+ death: "text-muted-foreground bg-muted/30 border-border",
21715
+ spawn: "text-accent bg-accent/10 border-accent/30"
21627
21716
  };
21628
21717
  DEFAULT_COMBAT_EVENTS = [
21629
21718
  { id: "e1", type: "spawn", message: "Shadow Guard entered the field.", timestamp: 0, turn: 1 },
@@ -21654,7 +21743,7 @@ function ComboCounter({
21654
21743
  size = "md",
21655
21744
  className
21656
21745
  }) {
21657
- const sizes = sizeMap4[size];
21746
+ const sizes = sizeMap5[size];
21658
21747
  if (combo <= 0) return null;
21659
21748
  return /* @__PURE__ */ jsxs(
21660
21749
  "div",
@@ -21692,12 +21781,12 @@ function ComboCounter({
21692
21781
  }
21693
21782
  );
21694
21783
  }
21695
- var DEFAULT_ASSET_URL3, sizeMap4;
21784
+ var DEFAULT_ASSET_URL3, sizeMap5;
21696
21785
  var init_ComboCounter = __esm({
21697
21786
  "components/game/atoms/ComboCounter.tsx"() {
21698
21787
  init_cn();
21699
21788
  DEFAULT_ASSET_URL3 = "https://almadar-kflow-assets.web.app/shared/effects/flash/flash00.png";
21700
- sizeMap4 = {
21789
+ sizeMap5 = {
21701
21790
  sm: { combo: "text-lg", label: "text-xs", multiplier: "text-xs" },
21702
21791
  md: { combo: "text-2xl", label: "text-xs", multiplier: "text-sm" },
21703
21792
  lg: { combo: "text-4xl", label: "text-sm", multiplier: "text-base" }
@@ -22128,7 +22217,7 @@ function ItemSlot({
22128
22217
  className: cn(
22129
22218
  "relative flex items-center justify-center rounded-interactive border-2",
22130
22219
  "bg-card/80 transition-all duration-150",
22131
- sizeMap5[size],
22220
+ sizeMap6[size],
22132
22221
  empty ? "border-border bg-card/50" : rarityBorderMap[rarity],
22133
22222
  !empty && rarityGlowMap[rarity],
22134
22223
  selected && "ring-2 ring-foreground ring-offset-1 ring-offset-background",
@@ -22164,13 +22253,13 @@ function ItemSlot({
22164
22253
  }
22165
22254
  );
22166
22255
  }
22167
- var sizeMap5, rarityBorderMap, rarityGlowMap, DEFAULT_ASSET_URL4, assetSizeMap;
22256
+ var sizeMap6, rarityBorderMap, rarityGlowMap, DEFAULT_ASSET_URL4, assetSizeMap;
22168
22257
  var init_ItemSlot = __esm({
22169
22258
  "components/game/atoms/ItemSlot.tsx"() {
22170
22259
  "use client";
22171
22260
  init_cn();
22172
22261
  init_Icon();
22173
- sizeMap5 = {
22262
+ sizeMap6 = {
22174
22263
  sm: "w-10 h-10 text-lg",
22175
22264
  md: "w-14 h-14 text-2xl",
22176
22265
  lg: "w-18 h-18 text-3xl"
@@ -22211,7 +22300,7 @@ function CraftingRecipe({
22211
22300
  className
22212
22301
  }) {
22213
22302
  const eventBus = useEventBus();
22214
- const handleCraft = React84.useCallback(() => {
22303
+ const handleCraft = React85.useCallback(() => {
22215
22304
  onCraft?.();
22216
22305
  if (craftEvent) {
22217
22306
  eventBus.emit(craftEvent, { output: output.label });
@@ -22228,7 +22317,7 @@ function CraftingRecipe({
22228
22317
  children: [
22229
22318
  /* @__PURE__ */ jsx(HStack, { gap: "xs", className: "flex-wrap items-center", children: inputs.map((ingredient, index) => {
22230
22319
  const hasSufficient = ingredient.available >= ingredient.required;
22231
- return /* @__PURE__ */ jsxs(React84.Fragment, { children: [
22320
+ return /* @__PURE__ */ jsxs(React85.Fragment, { children: [
22232
22321
  /* @__PURE__ */ jsx(Box, { className: "relative", children: /* @__PURE__ */ jsx(
22233
22322
  ItemSlot,
22234
22323
  {
@@ -22253,13 +22342,13 @@ function CraftingRecipe({
22253
22342
  }
22254
22343
  ),
22255
22344
  /* @__PURE__ */ jsx(
22256
- Button,
22345
+ ActionButton,
22257
22346
  {
22347
+ label: "Craft",
22258
22348
  onClick: handleCraft,
22259
22349
  disabled: !canCraft,
22260
22350
  variant: canCraft ? "primary" : "secondary",
22261
- size: "sm",
22262
- children: "Craft"
22351
+ size: "sm"
22263
22352
  }
22264
22353
  )
22265
22354
  ]
@@ -22273,7 +22362,7 @@ var init_CraftingRecipe = __esm({
22273
22362
  init_cn();
22274
22363
  init_useEventBus();
22275
22364
  init_ItemSlot();
22276
- init_Button();
22365
+ init_ActionButton();
22277
22366
  init_Box();
22278
22367
  init_Stack();
22279
22368
  init_Icon();
@@ -22299,9 +22388,9 @@ function DPad({
22299
22388
  disabled
22300
22389
  }) {
22301
22390
  const eventBus = useEventBus();
22302
- const sizes = sizeMap6[size];
22303
- const [activeDirections, setActiveDirections] = React84.useState(/* @__PURE__ */ new Set());
22304
- const handlePress = React84.useCallback(
22391
+ const sizes = sizeMap7[size];
22392
+ const [activeDirections, setActiveDirections] = React85.useState(/* @__PURE__ */ new Set());
22393
+ const handlePress = React85.useCallback(
22305
22394
  (direction) => {
22306
22395
  setActiveDirections((prev) => new Set(prev).add(direction));
22307
22396
  if (directionEvent) eventBus.emit(`UI:${directionEvent}`, { direction, pressed: true });
@@ -22309,7 +22398,7 @@ function DPad({
22309
22398
  },
22310
22399
  [directionEvent, eventBus, onDirection]
22311
22400
  );
22312
- const handleRelease = React84.useCallback(
22401
+ const handleRelease = React85.useCallback(
22313
22402
  (direction) => {
22314
22403
  setActiveDirections((prev) => {
22315
22404
  const next = new Set(prev);
@@ -22346,14 +22435,14 @@ function DPad({
22346
22435
  /* @__PURE__ */ jsx("div", {})
22347
22436
  ] });
22348
22437
  }
22349
- var sizeMap6, arrowIcons;
22438
+ var sizeMap7, arrowIcons;
22350
22439
  var init_DPad = __esm({
22351
22440
  "components/game/molecules/DPad.tsx"() {
22352
22441
  "use client";
22353
22442
  init_cn();
22354
22443
  init_useEventBus();
22355
22444
  init_ControlButton();
22356
- sizeMap6 = {
22445
+ sizeMap7 = {
22357
22446
  sm: { button: "sm", gap: "gap-0.5", container: "w-28" },
22358
22447
  md: { button: "md", gap: "gap-1", container: "w-40" },
22359
22448
  lg: { button: "lg", gap: "gap-1.5", container: "w-52" }
@@ -22382,7 +22471,7 @@ function DamageNumber({
22382
22471
  {
22383
22472
  className: cn(
22384
22473
  "inline-flex items-center gap-0.5 font-mono select-none pointer-events-none",
22385
- sizeMap7[size],
22474
+ sizeMap8[size],
22386
22475
  typeStyles[type],
22387
22476
  className
22388
22477
  ),
@@ -22405,11 +22494,11 @@ function DamageNumber({
22405
22494
  )
22406
22495
  ] });
22407
22496
  }
22408
- var sizeMap7, typeStyles, floatKeyframes, DEFAULT_ASSET_URL5;
22497
+ var sizeMap8, typeStyles, floatKeyframes, DEFAULT_ASSET_URL5;
22409
22498
  var init_DamageNumber = __esm({
22410
22499
  "components/game/atoms/DamageNumber.tsx"() {
22411
22500
  init_cn();
22412
- sizeMap7 = {
22501
+ sizeMap8 = {
22413
22502
  sm: "text-sm",
22414
22503
  md: "text-lg",
22415
22504
  lg: "text-2xl"
@@ -23258,8 +23347,8 @@ var init_Menu = __esm({
23258
23347
  "bottom-end": "bottom-start"
23259
23348
  };
23260
23349
  const effectivePosition = direction === "rtl" ? rtlMirror[position] ?? position : position;
23261
- const triggerChild = React84__default.isValidElement(trigger) ? trigger : /* @__PURE__ */ jsx(Typography, { variant: "small", as: "span", children: trigger });
23262
- const triggerElement = React84__default.cloneElement(
23350
+ const triggerChild = React85__default.isValidElement(trigger) ? trigger : /* @__PURE__ */ jsx(Typography, { variant: "small", as: "span", children: trigger });
23351
+ const triggerElement = React85__default.cloneElement(
23263
23352
  triggerChild,
23264
23353
  {
23265
23354
  ref: triggerRef,
@@ -23354,14 +23443,14 @@ function useDataDnd(args) {
23354
23443
  const isZone = Boolean(dragGroup || accepts || sortable);
23355
23444
  const enabled = isZone || Boolean(dndRoot);
23356
23445
  const eventBus = useEventBus();
23357
- const parentRoot = React84__default.useContext(RootCtx);
23446
+ const parentRoot = React85__default.useContext(RootCtx);
23358
23447
  const isRoot = enabled && parentRoot === null;
23359
- const zoneId = React84__default.useId();
23448
+ const zoneId = React85__default.useId();
23360
23449
  const ownGroup = dragGroup ?? accepts ?? zoneId;
23361
- const [optimisticOrders, setOptimisticOrders] = React84__default.useState(() => /* @__PURE__ */ new Map());
23362
- const optimisticOrdersRef = React84__default.useRef(optimisticOrders);
23450
+ const [optimisticOrders, setOptimisticOrders] = React85__default.useState(() => /* @__PURE__ */ new Map());
23451
+ const optimisticOrdersRef = React85__default.useRef(optimisticOrders);
23363
23452
  optimisticOrdersRef.current = optimisticOrders;
23364
- const clearOptimisticOrder = React84__default.useCallback((group) => {
23453
+ const clearOptimisticOrder = React85__default.useCallback((group) => {
23365
23454
  setOptimisticOrders((prev) => {
23366
23455
  if (!prev.has(group)) return prev;
23367
23456
  const next = new Map(prev);
@@ -23386,7 +23475,7 @@ function useDataDnd(args) {
23386
23475
  const raw = it[dndItemIdField];
23387
23476
  return raw != null ? String(raw) : `__idx_${idx}`;
23388
23477
  }).join("|");
23389
- const itemIds = React84__default.useMemo(
23478
+ const itemIds = React85__default.useMemo(
23390
23479
  () => orderedItems.map((it, idx) => {
23391
23480
  const raw = it[dndItemIdField];
23392
23481
  return raw != null ? String(raw) : `__idx_${idx}`;
@@ -23397,7 +23486,7 @@ function useDataDnd(args) {
23397
23486
  const raw = it[dndItemIdField];
23398
23487
  return raw != null ? String(raw) : `__${idx}`;
23399
23488
  }).join("|");
23400
- React84__default.useEffect(() => {
23489
+ React85__default.useEffect(() => {
23401
23490
  const root = isRoot ? null : parentRoot;
23402
23491
  if (root) {
23403
23492
  root.clearOptimisticOrder(ownGroup);
@@ -23405,20 +23494,20 @@ function useDataDnd(args) {
23405
23494
  clearOptimisticOrder(ownGroup);
23406
23495
  }
23407
23496
  }, [itemsContentSig, ownGroup]);
23408
- const zonesRef = React84__default.useRef(/* @__PURE__ */ new Map());
23409
- const registerZone = React84__default.useCallback((zoneId2, meta2) => {
23497
+ const zonesRef = React85__default.useRef(/* @__PURE__ */ new Map());
23498
+ const registerZone = React85__default.useCallback((zoneId2, meta2) => {
23410
23499
  zonesRef.current.set(zoneId2, meta2);
23411
23500
  }, []);
23412
- const unregisterZone = React84__default.useCallback((zoneId2) => {
23501
+ const unregisterZone = React85__default.useCallback((zoneId2) => {
23413
23502
  zonesRef.current.delete(zoneId2);
23414
23503
  }, []);
23415
- const [activeDrag, setActiveDrag] = React84__default.useState(null);
23416
- const [overZoneGroup, setOverZoneGroup] = React84__default.useState(null);
23417
- const meta = React84__default.useMemo(
23504
+ const [activeDrag, setActiveDrag] = React85__default.useState(null);
23505
+ const [overZoneGroup, setOverZoneGroup] = React85__default.useState(null);
23506
+ const meta = React85__default.useMemo(
23418
23507
  () => ({ group: ownGroup, dropEvent, reorderEvent, positionEvent, itemIds, rawItems: items, idField: dndItemIdField }),
23419
23508
  [ownGroup, dropEvent, reorderEvent, positionEvent, itemIds, items, dndItemIdField]
23420
23509
  );
23421
- React84__default.useEffect(() => {
23510
+ React85__default.useEffect(() => {
23422
23511
  const target = isRoot ? null : parentRoot;
23423
23512
  if (!target) {
23424
23513
  zonesRef.current.set(zoneId, meta);
@@ -23437,7 +23526,7 @@ function useDataDnd(args) {
23437
23526
  }, [parentRoot, isRoot, zoneId, meta]);
23438
23527
  const sensors = useAlmadarDndSensors(true);
23439
23528
  const collisionDetection = almadarDndCollisionDetection;
23440
- const findZoneByItem = React84__default.useCallback(
23529
+ const findZoneByItem = React85__default.useCallback(
23441
23530
  (id) => {
23442
23531
  for (const z of zonesRef.current.values()) {
23443
23532
  if (z.itemIds.includes(id)) return z;
@@ -23446,7 +23535,7 @@ function useDataDnd(args) {
23446
23535
  },
23447
23536
  []
23448
23537
  );
23449
- React84__default.useCallback(
23538
+ React85__default.useCallback(
23450
23539
  (group) => {
23451
23540
  for (const z of zonesRef.current.values()) {
23452
23541
  if (z.group === group) return z;
@@ -23455,7 +23544,7 @@ function useDataDnd(args) {
23455
23544
  },
23456
23545
  []
23457
23546
  );
23458
- const handleDragEnd = React84__default.useCallback(
23547
+ const handleDragEnd = React85__default.useCallback(
23459
23548
  (event) => {
23460
23549
  const { active, over } = event;
23461
23550
  const activeIdStr = String(active.id);
@@ -23546,8 +23635,8 @@ function useDataDnd(args) {
23546
23635
  },
23547
23636
  [eventBus]
23548
23637
  );
23549
- const sortableData = React84__default.useMemo(() => ({ dndGroup: ownGroup }), [ownGroup]);
23550
- const SortableItem = React84__default.useCallback(
23638
+ const sortableData = React85__default.useMemo(() => ({ dndGroup: ownGroup }), [ownGroup]);
23639
+ const SortableItem = React85__default.useCallback(
23551
23640
  ({ id, children }) => {
23552
23641
  const {
23553
23642
  attributes,
@@ -23587,7 +23676,7 @@ function useDataDnd(args) {
23587
23676
  id: droppableId,
23588
23677
  data: sortableData
23589
23678
  });
23590
- const ctx = React84__default.useContext(RootCtx);
23679
+ const ctx = React85__default.useContext(RootCtx);
23591
23680
  const activeDrag2 = ctx?.activeDrag ?? null;
23592
23681
  const overZoneGroup2 = ctx?.overZoneGroup ?? null;
23593
23682
  const isThisZoneOver = overZoneGroup2 === ownGroup;
@@ -23602,7 +23691,7 @@ function useDataDnd(args) {
23602
23691
  showForeignPlaceholder,
23603
23692
  ctxAvailable: ctx != null
23604
23693
  });
23605
- React84__default.useEffect(() => {
23694
+ React85__default.useEffect(() => {
23606
23695
  dndLog.info("dropzone:isOver:change", { droppableId, group: ownGroup, isOver, isThisZoneOver, showForeignPlaceholder, activeDragSourceGroup: activeDrag2?.sourceGroup ?? null });
23607
23696
  }, [droppableId, isOver, isThisZoneOver, showForeignPlaceholder]);
23608
23697
  return /* @__PURE__ */ jsx(
@@ -23616,11 +23705,11 @@ function useDataDnd(args) {
23616
23705
  }
23617
23706
  );
23618
23707
  };
23619
- const rootContextValue = React84__default.useMemo(
23708
+ const rootContextValue = React85__default.useMemo(
23620
23709
  () => ({ registerZone, unregisterZone, activeDrag, overZoneGroup, optimisticOrders, clearOptimisticOrder }),
23621
23710
  [registerZone, unregisterZone, activeDrag, overZoneGroup, optimisticOrders, clearOptimisticOrder]
23622
23711
  );
23623
- const handleDragStart = React84__default.useCallback((event) => {
23712
+ const handleDragStart = React85__default.useCallback((event) => {
23624
23713
  const sourceZone = findZoneByItem(event.active.id);
23625
23714
  const rect = event.active.rect.current.initial;
23626
23715
  const height = rect?.height && rect.height > 0 ? rect.height : 64;
@@ -23639,7 +23728,7 @@ function useDataDnd(args) {
23639
23728
  isRoot
23640
23729
  });
23641
23730
  }, [findZoneByItem, isRoot, zoneId]);
23642
- const handleDragOver = React84__default.useCallback((event) => {
23731
+ const handleDragOver = React85__default.useCallback((event) => {
23643
23732
  const { active, over } = event;
23644
23733
  const overData = over?.data?.current;
23645
23734
  const overGroup = overData?.dndGroup ?? null;
@@ -23709,7 +23798,7 @@ function useDataDnd(args) {
23709
23798
  return next;
23710
23799
  });
23711
23800
  }, []);
23712
- const handleDragCancel = React84__default.useCallback((event) => {
23801
+ const handleDragCancel = React85__default.useCallback((event) => {
23713
23802
  setActiveDrag(null);
23714
23803
  setOverZoneGroup(null);
23715
23804
  dndLog.warn("dragCancel", {
@@ -23717,12 +23806,12 @@ function useDataDnd(args) {
23717
23806
  reason: "dnd-kit cancelled the drag (escape key, pointer interrupted, or external)"
23718
23807
  });
23719
23808
  }, []);
23720
- const handleDragEndWithCleanup = React84__default.useCallback((event) => {
23809
+ const handleDragEndWithCleanup = React85__default.useCallback((event) => {
23721
23810
  handleDragEnd(event);
23722
23811
  setActiveDrag(null);
23723
23812
  setOverZoneGroup(null);
23724
23813
  }, [handleDragEnd]);
23725
- const wrapContainer = React84__default.useCallback(
23814
+ const wrapContainer = React85__default.useCallback(
23726
23815
  (children) => {
23727
23816
  if (!enabled) return children;
23728
23817
  const strategy = layout === "grid" ? rectSortingStrategy : verticalListSortingStrategy;
@@ -23776,7 +23865,7 @@ var init_useDataDnd = __esm({
23776
23865
  init_useAlmadarDndCollision();
23777
23866
  init_Box();
23778
23867
  dndLog = createLogger("almadar:ui:dnd");
23779
- RootCtx = React84__default.createContext(null);
23868
+ RootCtx = React85__default.createContext(null);
23780
23869
  }
23781
23870
  });
23782
23871
  function renderIconInput(icon, props) {
@@ -24302,7 +24391,7 @@ function DataList({
24302
24391
  }) {
24303
24392
  const eventBus = useEventBus();
24304
24393
  const { t } = useTranslate();
24305
- const [visibleCount, setVisibleCount] = React84__default.useState(pageSize || Infinity);
24394
+ const [visibleCount, setVisibleCount] = React85__default.useState(pageSize || Infinity);
24306
24395
  const fieldDefs = fields ?? columns ?? [];
24307
24396
  const allDataRaw = Array.isArray(entity) ? entity : entity ? [entity] : [];
24308
24397
  const dnd = useDataDnd({
@@ -24321,7 +24410,7 @@ function DataList({
24321
24410
  const data = pageSize > 0 ? allData.slice(0, visibleCount) : allData;
24322
24411
  const hasMoreLocal = pageSize > 0 && visibleCount < allData.length;
24323
24412
  const hasRenderProp = typeof children === "function";
24324
- React84__default.useEffect(() => {
24413
+ React85__default.useEffect(() => {
24325
24414
  const renderItemTypeOf = typeof schemaRenderItem;
24326
24415
  const childrenTypeOf = typeof children;
24327
24416
  if (data.length > 0 && !hasRenderProp) {
@@ -24425,7 +24514,7 @@ function DataList({
24425
24514
  const items2 = [...data];
24426
24515
  const groups2 = groupBy ? groupData(items2, groupBy) : [{ label: "", items: items2 }];
24427
24516
  const contentField = titleField?.name ?? fieldDefs[0]?.name ?? "";
24428
- return /* @__PURE__ */ jsx(VStack, { gap: "sm", className: cn("py-2", className), children: groups2.map((group, gi) => /* @__PURE__ */ jsxs(React84__default.Fragment, { children: [
24517
+ return /* @__PURE__ */ jsx(VStack, { gap: "sm", className: cn("py-2", className), children: groups2.map((group, gi) => /* @__PURE__ */ jsxs(React85__default.Fragment, { children: [
24429
24518
  group.label && /* @__PURE__ */ jsx(Divider, { label: group.label, className: "my-2" }),
24430
24519
  group.items.map((itemData, index) => {
24431
24520
  const id = itemData.id || `${gi}-${index}`;
@@ -24566,7 +24655,7 @@ function DataList({
24566
24655
  className
24567
24656
  ),
24568
24657
  children: [
24569
- groups.map((group, gi) => /* @__PURE__ */ jsxs(React84__default.Fragment, { children: [
24658
+ groups.map((group, gi) => /* @__PURE__ */ jsxs(React85__default.Fragment, { children: [
24570
24659
  group.label && /* @__PURE__ */ jsx(Divider, { label: group.label, className: gi > 0 ? "mt-4" : "mt-0" }),
24571
24660
  group.items.map(
24572
24661
  (itemData, index) => renderItem(itemData, index, gi === groups.length - 1 && index === group.items.length - 1)
@@ -24673,8 +24762,8 @@ function ScalarControl({
24673
24762
  }
24674
24763
  const numeric = typeof value === "number";
24675
24764
  const initial = value === null ? "" : String(value);
24676
- const [draft, setDraft] = React84__default.useState(initial);
24677
- React84__default.useEffect(() => setDraft(initial), [initial]);
24765
+ const [draft, setDraft] = React85__default.useState(initial);
24766
+ React85__default.useEffect(() => setDraft(initial), [initial]);
24678
24767
  const commit = () => {
24679
24768
  if (numeric) {
24680
24769
  const n = draft.trim() === "" ? 0 : Number(draft);
@@ -24742,8 +24831,8 @@ function Row({
24742
24831
  onRemove,
24743
24832
  readonly
24744
24833
  }) {
24745
- const [keyDraft, setKeyDraft] = React84__default.useState(rowKey);
24746
- React84__default.useEffect(() => setKeyDraft(rowKey), [rowKey]);
24834
+ const [keyDraft, setKeyDraft] = React85__default.useState(rowKey);
24835
+ React85__default.useEffect(() => setKeyDraft(rowKey), [rowKey]);
24747
24836
  const container = isObj(value) || isArr(value);
24748
24837
  return /* @__PURE__ */ jsxs(VStack, { gap: "none", className: "group w-max min-w-full", children: [
24749
24838
  /* @__PURE__ */ jsxs(HStack, { gap: "xs", align: "center", className: "py-0.5 w-max", children: [
@@ -24786,7 +24875,7 @@ function ContainerNode({
24786
24875
  depth,
24787
24876
  readonly
24788
24877
  }) {
24789
- const [open, setOpen] = React84__default.useState(depth < 2);
24878
+ const [open, setOpen] = React85__default.useState(depth < 2);
24790
24879
  const array = isArr(value);
24791
24880
  const entries = array ? value.map((v, i) => [String(i), v]) : Object.entries(value);
24792
24881
  const setObjValue = (key, next) => {
@@ -24928,7 +25017,7 @@ var init_FormSection = __esm({
24928
25017
  columns = 1,
24929
25018
  className
24930
25019
  }) => {
24931
- const [collapsed, setCollapsed] = React84__default.useState(defaultCollapsed);
25020
+ const [collapsed, setCollapsed] = React85__default.useState(defaultCollapsed);
24932
25021
  const { t } = useTranslate();
24933
25022
  const eventBus = useEventBus();
24934
25023
  const gridClass = {
@@ -24936,7 +25025,7 @@ var init_FormSection = __esm({
24936
25025
  2: "grid-cols-1 md:grid-cols-2",
24937
25026
  3: "grid-cols-1 md:grid-cols-2 lg:grid-cols-3"
24938
25027
  }[columns];
24939
- React84__default.useCallback(() => {
25028
+ React85__default.useCallback(() => {
24940
25029
  if (collapsible) {
24941
25030
  setCollapsed((prev) => !prev);
24942
25031
  eventBus.emit("UI:TOGGLE_COLLAPSE", { collapsed: !collapsed });
@@ -25344,8 +25433,8 @@ function TextLikeControl({
25344
25433
  onCommit
25345
25434
  }) {
25346
25435
  const initial = value === void 0 || value === null ? "" : String(value);
25347
- const [draft, setDraft] = React84__default.useState(initial);
25348
- React84__default.useEffect(() => setDraft(initial), [initial]);
25436
+ const [draft, setDraft] = React85__default.useState(initial);
25437
+ React85__default.useEffect(() => setDraft(initial), [initial]);
25349
25438
  const commit = () => {
25350
25439
  if (numeric) {
25351
25440
  const n = draft.trim() === "" ? 0 : Number(draft);
@@ -25511,14 +25600,14 @@ var init_NodeSlotEditor = __esm({
25511
25600
  isObj2 = (v) => v !== null && v !== void 0 && typeof v === "object" && !Array.isArray(v);
25512
25601
  NodeSlotEditor = ({ value, onChange, className }) => {
25513
25602
  const { type, props, wasArray } = normalize(value);
25514
- const patterns = React84__default.useMemo(() => {
25603
+ const patterns = React85__default.useMemo(() => {
25515
25604
  try {
25516
25605
  return [...getKnownPatterns()].sort();
25517
25606
  } catch {
25518
25607
  return [];
25519
25608
  }
25520
25609
  }, []);
25521
- const options = React84__default.useMemo(
25610
+ const options = React85__default.useMemo(
25522
25611
  () => [{ value: "", label: "\u2014 none \u2014" }, ...patterns.map((p2) => ({ value: p2, label: p2 }))],
25523
25612
  [patterns]
25524
25613
  );
@@ -25530,7 +25619,7 @@ var init_NodeSlotEditor = __esm({
25530
25619
  const pattern = { type: nextType, ...nextProps };
25531
25620
  onChange(wasArray || value === void 0 ? [pattern] : pattern);
25532
25621
  };
25533
- const schemaEntries = React84__default.useMemo(() => {
25622
+ const schemaEntries = React85__default.useMemo(() => {
25534
25623
  if (!type) return [];
25535
25624
  const def = getPatternDefinition(type);
25536
25625
  if (!def?.propsSchema) return [];
@@ -26301,7 +26390,7 @@ var init_Flex = __esm({
26301
26390
  flexStyle.flexBasis = typeof basis === "number" ? `${basis}px` : basis;
26302
26391
  }
26303
26392
  }
26304
- return React84__default.createElement(Component2, {
26393
+ return React85__default.createElement(Component2, {
26305
26394
  className: cn(
26306
26395
  inline ? "inline-flex" : "flex",
26307
26396
  directionStyles[direction],
@@ -26420,7 +26509,7 @@ var init_Grid = __esm({
26420
26509
  as: Component2 = "div"
26421
26510
  }) => {
26422
26511
  const mergedStyle = rows2 ? { gridTemplateRows: `repeat(${rows2}, minmax(0, 1fr))`, ...style } : style;
26423
- return React84__default.createElement(
26512
+ return React85__default.createElement(
26424
26513
  Component2,
26425
26514
  {
26426
26515
  className: cn(
@@ -26616,9 +26705,9 @@ var init_Popover = __esm({
26616
26705
  onMouseLeave: handleClose,
26617
26706
  onPointerDown: tapTriggerProps.onPointerDown
26618
26707
  };
26619
- const childElement = React84__default.isValidElement(children) ? children : /* @__PURE__ */ jsx("span", { children });
26708
+ const childElement = React85__default.isValidElement(children) ? children : /* @__PURE__ */ jsx("span", { children });
26620
26709
  const childPointerDown = childElement.props.onPointerDown;
26621
- const triggerElement = React84__default.cloneElement(
26710
+ const triggerElement = React85__default.cloneElement(
26622
26711
  childElement,
26623
26712
  {
26624
26713
  ref: triggerRef,
@@ -27470,9 +27559,9 @@ var init_Tooltip = __esm({
27470
27559
  if (hideTimeoutRef.current) clearTimeout(hideTimeoutRef.current);
27471
27560
  };
27472
27561
  }, []);
27473
- const triggerElement = React84__default.isValidElement(children) ? children : /* @__PURE__ */ jsx("span", { children });
27562
+ const triggerElement = React85__default.isValidElement(children) ? children : /* @__PURE__ */ jsx("span", { children });
27474
27563
  const childPointerDown = triggerElement.props.onPointerDown;
27475
- const trigger = React84__default.cloneElement(triggerElement, {
27564
+ const trigger = React85__default.cloneElement(triggerElement, {
27476
27565
  ref: triggerRef,
27477
27566
  onMouseEnter: handleMouseEnter,
27478
27567
  onMouseLeave: handleMouseLeave,
@@ -27562,7 +27651,7 @@ var init_WizardProgress = __esm({
27562
27651
  children: /* @__PURE__ */ jsx("div", { className: "flex items-center gap-2", children: normalizedSteps.map((step, index) => {
27563
27652
  const isActive = index === currentStep;
27564
27653
  const isCompleted = index < currentStep;
27565
- return /* @__PURE__ */ jsxs(React84__default.Fragment, { children: [
27654
+ return /* @__PURE__ */ jsxs(React85__default.Fragment, { children: [
27566
27655
  /* @__PURE__ */ jsx(
27567
27656
  "button",
27568
27657
  {
@@ -28464,13 +28553,13 @@ var init_LineChart = __esm({
28464
28553
  LineChart2.displayName = "LineChart";
28465
28554
  }
28466
28555
  });
28467
- var sizeMap8, stateColors, ProgressDots;
28556
+ var sizeMap9, stateColors, ProgressDots;
28468
28557
  var init_ProgressDots = __esm({
28469
28558
  "components/core/molecules/ProgressDots.tsx"() {
28470
28559
  "use client";
28471
28560
  init_cn();
28472
28561
  init_atoms2();
28473
- sizeMap8 = {
28562
+ sizeMap9 = {
28474
28563
  sm: { dot: 6, active: 8 },
28475
28564
  md: { dot: 8, active: 10 },
28476
28565
  lg: { dot: 10, active: 14 }
@@ -28496,7 +28585,7 @@ var init_ProgressDots = __esm({
28496
28585
  [currentIndex]
28497
28586
  );
28498
28587
  const resolveState = getState2 ?? defaultGetState;
28499
- const dims = sizeMap8[size];
28588
+ const dims = sizeMap9[size];
28500
28589
  return /* @__PURE__ */ jsx(HStack, { gap: "xs", align: "center", className: cn(className), children: Array.from({ length: count }, (_, index) => {
28501
28590
  const state = resolveState(index);
28502
28591
  const isActive = state === "active";
@@ -28523,79 +28612,6 @@ var init_ProgressDots = __esm({
28523
28612
  ProgressDots.displayName = "ProgressDots";
28524
28613
  }
28525
28614
  });
28526
- function HealthBar({
28527
- current = 3,
28528
- max = 5,
28529
- format = "hearts",
28530
- size = "md",
28531
- className,
28532
- animated = true
28533
- }) {
28534
- const sizes = sizeMap9[size];
28535
- const percentage = Math.max(0, Math.min(100, current / max * 100));
28536
- if (format === "hearts") {
28537
- return /* @__PURE__ */ jsx("div", { className: cn("flex items-center gap-1", className), children: Array.from({ length: max }).map((_, i) => /* @__PURE__ */ jsx(
28538
- "span",
28539
- {
28540
- className: cn(animated && "transition-transform hover:scale-110"),
28541
- children: heartIcon(i < current, sizes.heart)
28542
- },
28543
- i
28544
- )) });
28545
- }
28546
- if (format === "bar") {
28547
- return /* @__PURE__ */ jsx(
28548
- "div",
28549
- {
28550
- className: cn(
28551
- "relative overflow-hidden rounded-full bg-muted",
28552
- sizes.bar,
28553
- "w-24",
28554
- className
28555
- ),
28556
- children: /* @__PURE__ */ jsx(
28557
- "div",
28558
- {
28559
- className: cn(
28560
- "absolute inset-y-0 left-0 rounded-full",
28561
- percentage > 66 ? "bg-success" : percentage > 33 ? "bg-warning" : "bg-error",
28562
- animated && "transition-all duration-300"
28563
- ),
28564
- style: { width: `${percentage}%` }
28565
- }
28566
- )
28567
- }
28568
- );
28569
- }
28570
- return /* @__PURE__ */ jsxs("span", { className: cn("font-mono font-bold", sizes.text, className), children: [
28571
- current,
28572
- "/",
28573
- max
28574
- ] });
28575
- }
28576
- var heartIcon, sizeMap9;
28577
- var init_HealthBar = __esm({
28578
- "components/game/atoms/HealthBar.tsx"() {
28579
- init_cn();
28580
- heartIcon = (filled, size) => /* @__PURE__ */ jsx(
28581
- "svg",
28582
- {
28583
- className: cn("transition-all duration-200", size, filled ? "text-error" : "text-muted-foreground"),
28584
- viewBox: "0 0 24 24",
28585
- fill: filled ? "currentColor" : "none",
28586
- stroke: "currentColor",
28587
- strokeWidth: filled ? 0 : 2,
28588
- children: /* @__PURE__ */ jsx("path", { d: "M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z" })
28589
- }
28590
- );
28591
- sizeMap9 = {
28592
- sm: { heart: "w-4 h-4", bar: "h-2", text: "text-sm" },
28593
- md: { heart: "w-6 h-6", bar: "h-3", text: "text-base" },
28594
- lg: { heart: "w-8 h-8", bar: "h-4", text: "text-lg" }
28595
- };
28596
- HealthBar.displayName = "HealthBar";
28597
- }
28598
- });
28599
28615
  function ScoreDisplay({
28600
28616
  assetUrl = DEFAULT_ASSET_URL6,
28601
28617
  value,
@@ -28604,43 +28620,16 @@ function ScoreDisplay({
28604
28620
  icon,
28605
28621
  size = "md",
28606
28622
  className,
28607
- animated = true,
28608
28623
  locale = "en-US"
28609
28624
  }) {
28610
28625
  const resolvedValue = typeof value === "number" && !Number.isNaN(value) ? value : typeof score === "number" && !Number.isNaN(score) ? score : 0;
28611
- const [displayValue, setDisplayValue] = React84.useState(resolvedValue);
28612
- const [isAnimating, setIsAnimating] = React84.useState(false);
28613
- React84.useEffect(() => {
28614
- if (!animated || displayValue === resolvedValue) {
28615
- setDisplayValue(resolvedValue);
28616
- return;
28617
- }
28618
- setIsAnimating(true);
28619
- const diff = resolvedValue - displayValue;
28620
- const steps = Math.min(Math.abs(diff), 20);
28621
- const increment = diff / steps;
28622
- let current = displayValue;
28623
- let step = 0;
28624
- const timer = setInterval(() => {
28625
- step++;
28626
- current += increment;
28627
- setDisplayValue(Math.round(current));
28628
- if (step >= steps) {
28629
- clearInterval(timer);
28630
- setDisplayValue(resolvedValue);
28631
- setIsAnimating(false);
28632
- }
28633
- }, 50);
28634
- return () => clearInterval(timer);
28635
- }, [resolvedValue, animated]);
28636
- const formattedValue = new Intl.NumberFormat(locale).format(displayValue);
28626
+ const formattedValue = new Intl.NumberFormat(locale).format(resolvedValue);
28637
28627
  return /* @__PURE__ */ jsxs(
28638
28628
  "div",
28639
28629
  {
28640
28630
  className: cn(
28641
28631
  "flex items-center gap-2 font-bold",
28642
28632
  sizeMap10[size],
28643
- isAnimating && "animate-pulse",
28644
28633
  className
28645
28634
  ),
28646
28635
  children: [
@@ -28664,7 +28653,6 @@ function ScoreDisplay({
28664
28653
  var sizeMap10, DEFAULT_ASSET_URL6;
28665
28654
  var init_ScoreDisplay = __esm({
28666
28655
  "components/game/atoms/ScoreDisplay.tsx"() {
28667
- "use client";
28668
28656
  init_cn();
28669
28657
  init_Icon();
28670
28658
  sizeMap10 = {
@@ -28679,6 +28667,7 @@ var init_ScoreDisplay = __esm({
28679
28667
  });
28680
28668
  function StatBadge({
28681
28669
  assetUrl,
28670
+ iconUrl,
28682
28671
  label,
28683
28672
  value = 0,
28684
28673
  max,
@@ -28692,6 +28681,7 @@ function StatBadge({
28692
28681
  field: _field
28693
28682
  }) {
28694
28683
  const numValue = typeof value === "number" ? value : parseInt(String(value), 10) || 0;
28684
+ const resolvedAsset = iconUrl ?? assetUrl;
28695
28685
  return /* @__PURE__ */ jsxs(
28696
28686
  "div",
28697
28687
  {
@@ -28702,10 +28692,10 @@ function StatBadge({
28702
28692
  className
28703
28693
  ),
28704
28694
  children: [
28705
- assetUrl ? /* @__PURE__ */ jsx(
28695
+ resolvedAsset ? /* @__PURE__ */ jsx(
28706
28696
  "img",
28707
28697
  {
28708
- src: assetUrl,
28698
+ src: resolvedAsset,
28709
28699
  alt: "",
28710
28700
  width: 16,
28711
28701
  height: 16,
@@ -28736,8 +28726,7 @@ function StatBadge({
28736
28726
  ScoreDisplay,
28737
28727
  {
28738
28728
  value: numValue,
28739
- size: size === "lg" ? "md" : "sm",
28740
- animated: true
28729
+ size: size === "lg" ? "md" : "sm"
28741
28730
  }
28742
28731
  ),
28743
28732
  format === "text" && /* @__PURE__ */ jsx("span", { className: "font-bold text-foreground", children: value })
@@ -28780,7 +28769,7 @@ function InventoryGrid({
28780
28769
  const eventBus = useEventBus();
28781
28770
  const slotCount = totalSlots ?? items.length;
28782
28771
  const emptySlotCount = Math.max(0, slotCount - items.length);
28783
- const handleSelect = React84.useCallback(
28772
+ const handleSelect = React85.useCallback(
28784
28773
  (id) => {
28785
28774
  onSelect?.(id);
28786
28775
  if (selectEvent) {
@@ -28969,12 +28958,14 @@ function QuestTracker({
28969
28958
  }
28970
28959
  ),
28971
28960
  /* @__PURE__ */ jsx(Box, { className: "mt-1.5", children: /* @__PURE__ */ jsx(
28972
- ProgressBar,
28961
+ HealthBar,
28973
28962
  {
28974
- value: quest.progress,
28963
+ current: quest.progress,
28975
28964
  max: quest.maxProgress,
28976
- variant: isCompleted ? "success" : isActive ? "primary" : "default",
28977
- size: "sm"
28965
+ format: "bar",
28966
+ size: "sm",
28967
+ animated: true,
28968
+ className: isCompleted ? "[--health-color:var(--color-success)]" : isActive ? "" : "opacity-60"
28978
28969
  }
28979
28970
  ) }),
28980
28971
  /* @__PURE__ */ jsxs(
@@ -29002,7 +28993,7 @@ var init_QuestTracker = __esm({
29002
28993
  "use client";
29003
28994
  init_cn();
29004
28995
  init_WaypointMarker();
29005
- init_ProgressBar();
28996
+ init_HealthBar();
29006
28997
  init_Typography();
29007
28998
  init_Box();
29008
28999
  init_Stack();
@@ -29097,31 +29088,31 @@ function GameCanvas2D({
29097
29088
  assetBaseUrl,
29098
29089
  className
29099
29090
  }) {
29100
- const canvasRef = React84.useRef(null);
29101
- const rafRef = React84.useRef(0);
29102
- const frameRef = React84.useRef(0);
29103
- const lastTimeRef = React84.useRef(0);
29104
- const imageCache = React84.useRef(/* @__PURE__ */ new Map());
29091
+ const canvasRef = React85.useRef(null);
29092
+ const rafRef = React85.useRef(0);
29093
+ const frameRef = React85.useRef(0);
29094
+ const lastTimeRef = React85.useRef(0);
29095
+ const imageCache = React85.useRef(/* @__PURE__ */ new Map());
29105
29096
  const emit = useEmitEvent();
29106
- const onDrawRef = React84.useRef(onDraw);
29097
+ const onDrawRef = React85.useRef(onDraw);
29107
29098
  onDrawRef.current = onDraw;
29108
- const onTickRef = React84.useRef(onTick);
29099
+ const onTickRef = React85.useRef(onTick);
29109
29100
  onTickRef.current = onTick;
29110
- const tickEventRef = React84.useRef(tickEvent);
29101
+ const tickEventRef = React85.useRef(tickEvent);
29111
29102
  tickEventRef.current = tickEvent;
29112
- const drawEventRef = React84.useRef(drawEvent);
29103
+ const drawEventRef = React85.useRef(drawEvent);
29113
29104
  drawEventRef.current = drawEvent;
29114
- const emitRef = React84.useRef(emit);
29105
+ const emitRef = React85.useRef(emit);
29115
29106
  emitRef.current = emit;
29116
- const assetBaseUrlRef = React84.useRef(assetBaseUrl);
29107
+ const assetBaseUrlRef = React85.useRef(assetBaseUrl);
29117
29108
  assetBaseUrlRef.current = assetBaseUrl;
29118
- const backgroundImageRef = React84.useRef(backgroundImage);
29109
+ const backgroundImageRef = React85.useRef(backgroundImage);
29119
29110
  backgroundImageRef.current = backgroundImage;
29120
- const widthRef = React84.useRef(width);
29111
+ const widthRef = React85.useRef(width);
29121
29112
  widthRef.current = width;
29122
- const heightRef = React84.useRef(height);
29113
+ const heightRef = React85.useRef(height);
29123
29114
  heightRef.current = height;
29124
- const loadImage = React84.useCallback((url) => {
29115
+ const loadImage = React85.useCallback((url) => {
29125
29116
  const base = assetBaseUrlRef.current;
29126
29117
  if (!url.startsWith("http") && !base) return null;
29127
29118
  const fullUrl = url.startsWith("http") ? url : `${base}${url}`;
@@ -29135,7 +29126,7 @@ function GameCanvas2D({
29135
29126
  }
29136
29127
  return null;
29137
29128
  }, []);
29138
- React84.useEffect(() => {
29129
+ React85.useEffect(() => {
29139
29130
  const canvas = canvasRef.current;
29140
29131
  if (!canvas) return;
29141
29132
  const ctx = canvas.getContext("2d");
@@ -29198,6 +29189,90 @@ var init_GameCanvas2D = __esm({
29198
29189
  GameCanvas2D.displayName = "GameCanvas2D";
29199
29190
  }
29200
29191
  });
29192
+ function formatDuration(seconds) {
29193
+ if (seconds >= 60) {
29194
+ return `${Math.floor(seconds / 60)}m`;
29195
+ }
29196
+ return `${Math.round(seconds)}s`;
29197
+ }
29198
+ function StatusEffect({
29199
+ assetUrl = DEFAULT_ASSET_URL8,
29200
+ icon = "shield",
29201
+ label = "Shield",
29202
+ duration = 30,
29203
+ stacks,
29204
+ variant = "buff",
29205
+ size = "md",
29206
+ className
29207
+ }) {
29208
+ const sizes = sizeMap13[size];
29209
+ return /* @__PURE__ */ jsxs("div", { className: cn("relative inline-flex flex-col items-center", className), children: [
29210
+ /* @__PURE__ */ jsxs(
29211
+ "div",
29212
+ {
29213
+ className: cn(
29214
+ "relative flex items-center justify-center rounded-interactive border-2",
29215
+ sizes.container,
29216
+ variantStyles8[variant]
29217
+ ),
29218
+ title: label,
29219
+ children: [
29220
+ /* @__PURE__ */ jsx("span", { className: cn("flex items-center justify-center", sizes.icon), children: assetUrl ? /* @__PURE__ */ jsx(
29221
+ "img",
29222
+ {
29223
+ src: assetUrl,
29224
+ alt: label,
29225
+ width: sizes.img,
29226
+ height: sizes.img,
29227
+ style: { imageRendering: "pixelated", objectFit: "contain" },
29228
+ className: "flex-shrink-0"
29229
+ }
29230
+ ) : typeof icon === "string" ? /* @__PURE__ */ jsx(Icon, { name: icon, size: "sm" }) : /* @__PURE__ */ jsx(Icon, { icon, size: "sm" }) }),
29231
+ duration !== void 0 && /* @__PURE__ */ jsx(
29232
+ "span",
29233
+ {
29234
+ className: cn(
29235
+ "absolute bottom-0 left-0 right-0 text-center font-mono font-bold text-foreground bg-background/60 leading-tight",
29236
+ sizes.timer
29237
+ ),
29238
+ children: formatDuration(duration)
29239
+ }
29240
+ )
29241
+ ]
29242
+ }
29243
+ ),
29244
+ stacks !== void 0 && stacks > 1 && /* @__PURE__ */ jsx(
29245
+ "span",
29246
+ {
29247
+ className: cn(
29248
+ "absolute flex items-center justify-center rounded-full bg-card text-foreground font-bold leading-none",
29249
+ sizes.badge
29250
+ ),
29251
+ children: stacks
29252
+ }
29253
+ ),
29254
+ label && /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground mt-0.5 text-center whitespace-nowrap", children: label })
29255
+ ] });
29256
+ }
29257
+ var DEFAULT_ASSET_URL8, sizeMap13, variantStyles8;
29258
+ var init_StatusEffect = __esm({
29259
+ "components/game/atoms/StatusEffect.tsx"() {
29260
+ init_cn();
29261
+ init_Icon();
29262
+ DEFAULT_ASSET_URL8 = "https://almadar-kflow-assets.web.app/shared/effects/particles/flame_01.png";
29263
+ sizeMap13 = {
29264
+ sm: { container: "w-8 h-8", icon: "text-sm", badge: "text-xs -top-1 -right-1 w-4 h-4", timer: "text-[9px]", img: 20 },
29265
+ md: { container: "w-10 h-10", icon: "text-base", badge: "text-xs -top-1 -right-1 w-5 h-5", timer: "text-xs", img: 28 },
29266
+ lg: { container: "w-12 h-12", icon: "text-lg", badge: "text-sm -top-1.5 -right-1.5 w-6 h-6", timer: "text-xs", img: 36 }
29267
+ };
29268
+ variantStyles8 = {
29269
+ buff: "border-success bg-success/20",
29270
+ debuff: "border-error bg-error/20",
29271
+ neutral: "border-muted bg-muted/20"
29272
+ };
29273
+ StatusEffect.displayName = "StatusEffect";
29274
+ }
29275
+ });
29201
29276
  function HealthPanel({
29202
29277
  current = 75,
29203
29278
  max = 100,
@@ -29208,7 +29283,7 @@ function HealthPanel({
29208
29283
  size = "md",
29209
29284
  className
29210
29285
  }) {
29211
- const sizes = sizeMap13[size];
29286
+ const sizes = sizeMap14[size];
29212
29287
  return /* @__PURE__ */ jsx(
29213
29288
  Box,
29214
29289
  {
@@ -29283,26 +29358,14 @@ function HealthPanel({
29283
29358
  )
29284
29359
  }
29285
29360
  ),
29286
- effects && effects.length > 0 && /* @__PURE__ */ jsx(Box, { className: "flex items-center gap-1 flex-wrap", children: effects.map((effect, i) => /* @__PURE__ */ jsxs(
29287
- Badge,
29361
+ effects && effects.length > 0 && /* @__PURE__ */ jsx(Box, { className: "flex items-center gap-1 flex-wrap", children: effects.map((effect, i) => /* @__PURE__ */ jsx(
29362
+ StatusEffect,
29288
29363
  {
29364
+ assetUrl: effect.assetUrl,
29365
+ icon: effect.icon,
29366
+ label: effect.label,
29289
29367
  variant: effectVariantMap[effect.variant ?? "neutral"],
29290
- size: "sm",
29291
- icon: effect.assetUrl ? void 0 : effect.icon,
29292
- children: [
29293
- effect.assetUrl && /* @__PURE__ */ jsx(
29294
- "img",
29295
- {
29296
- src: effect.assetUrl,
29297
- alt: "",
29298
- width: 12,
29299
- height: 12,
29300
- style: { imageRendering: "pixelated", objectFit: "contain" },
29301
- className: "flex-shrink-0 inline-block"
29302
- }
29303
- ),
29304
- effect.label
29305
- ]
29368
+ size: "sm"
29306
29369
  },
29307
29370
  i
29308
29371
  )) })
@@ -29310,23 +29373,23 @@ function HealthPanel({
29310
29373
  }
29311
29374
  );
29312
29375
  }
29313
- var sizeMap13, effectVariantMap;
29376
+ var sizeMap14, effectVariantMap;
29314
29377
  var init_HealthPanel = __esm({
29315
29378
  "components/game/molecules/HealthPanel.tsx"() {
29316
29379
  "use client";
29317
29380
  init_cn();
29318
29381
  init_HealthBar();
29382
+ init_StatusEffect();
29319
29383
  init_Box();
29320
29384
  init_Typography();
29321
- init_Badge();
29322
- sizeMap13 = {
29385
+ sizeMap14 = {
29323
29386
  sm: { gap: "gap-1", padding: "px-2 py-1.5", text: "text-xs", barSize: "sm" },
29324
29387
  md: { gap: "gap-1.5", padding: "px-3 py-2", text: "text-sm", barSize: "md" },
29325
29388
  lg: { gap: "gap-2", padding: "px-4 py-3", text: "text-base", barSize: "lg" }
29326
29389
  };
29327
29390
  effectVariantMap = {
29328
- buff: "success",
29329
- debuff: "danger",
29391
+ buff: "buff",
29392
+ debuff: "debuff",
29330
29393
  neutral: "neutral"
29331
29394
  };
29332
29395
  HealthPanel.displayName = "HealthPanel";
@@ -29346,13 +29409,13 @@ function ScoreBoard({
29346
29409
  const multiplier = rawMultiplier ?? 1;
29347
29410
  const level = rawLevel ?? 1;
29348
29411
  return /* @__PURE__ */ jsx(
29349
- Card,
29412
+ Box,
29350
29413
  {
29351
29414
  className: cn(
29352
- "bg-[var(--color-card)]/90 border-border backdrop-blur-sm",
29415
+ "rounded-container border border-border bg-[var(--color-card)]/90 backdrop-blur-sm p-3",
29353
29416
  className
29354
29417
  ),
29355
- children: /* @__PURE__ */ jsx(CardContent, { className: "p-3", children: /* @__PURE__ */ jsxs(Box, { className: "flex items-center gap-3 flex-wrap", children: [
29418
+ children: /* @__PURE__ */ jsxs(Box, { className: "flex items-center gap-3 flex-wrap", children: [
29356
29419
  /* @__PURE__ */ jsx(
29357
29420
  StatBadge,
29358
29421
  {
@@ -29394,7 +29457,7 @@ function ScoreBoard({
29394
29457
  }
29395
29458
  ),
29396
29459
  combo != null && combo > 0 && /* @__PURE__ */ jsx(ComboCounter, { combo, multiplier, size: "sm" })
29397
- ] }) })
29460
+ ] })
29398
29461
  }
29399
29462
  );
29400
29463
  }
@@ -29404,7 +29467,6 @@ var init_ScoreBoard = __esm({
29404
29467
  init_cn();
29405
29468
  init_ComboCounter();
29406
29469
  init_StatBadge();
29407
- init_Card();
29408
29470
  init_Box();
29409
29471
  ScoreBoard.displayName = "ScoreBoard";
29410
29472
  }
@@ -29452,7 +29514,7 @@ var init_ResourceBar = __esm({
29452
29514
  }
29453
29515
  });
29454
29516
  function TurnIndicator({
29455
- assetUrl = DEFAULT_ASSET_URL8,
29517
+ assetUrl = DEFAULT_ASSET_URL9,
29456
29518
  currentTurn = 1,
29457
29519
  maxTurns,
29458
29520
  activeTeam,
@@ -29460,7 +29522,7 @@ function TurnIndicator({
29460
29522
  size = "md",
29461
29523
  className
29462
29524
  }) {
29463
- const sizes = sizeMap14[size];
29525
+ const sizes = sizeMap15[size];
29464
29526
  return /* @__PURE__ */ jsxs(
29465
29527
  "div",
29466
29528
  {
@@ -29502,16 +29564,16 @@ function TurnIndicator({
29502
29564
  }
29503
29565
  );
29504
29566
  }
29505
- var sizeMap14, DEFAULT_ASSET_URL8;
29567
+ var sizeMap15, DEFAULT_ASSET_URL9;
29506
29568
  var init_TurnIndicator = __esm({
29507
29569
  "components/game/atoms/TurnIndicator.tsx"() {
29508
29570
  init_cn();
29509
- sizeMap14 = {
29571
+ sizeMap15 = {
29510
29572
  sm: { wrapper: "text-xs gap-1.5 px-2 py-0.5", dot: "w-1.5 h-1.5" },
29511
29573
  md: { wrapper: "text-sm gap-2 px-3 py-1", dot: "w-2 h-2" },
29512
29574
  lg: { wrapper: "text-base gap-2.5 px-4 py-1.5", dot: "w-2.5 h-2.5" }
29513
29575
  };
29514
- DEFAULT_ASSET_URL8 = "https://almadar-kflow-assets.web.app/shared/effects/particles/symbol_01.png";
29576
+ DEFAULT_ASSET_URL9 = "https://almadar-kflow-assets.web.app/shared/effects/particles/symbol_01.png";
29515
29577
  TurnIndicator.displayName = "TurnIndicator";
29516
29578
  }
29517
29579
  });
@@ -29524,7 +29586,7 @@ function TurnPanel({
29524
29586
  className
29525
29587
  }) {
29526
29588
  const eventBus = useEventBus();
29527
- const handleAction = React84.useCallback(
29589
+ const handleAction = React85.useCallback(
29528
29590
  (event) => {
29529
29591
  if (event) {
29530
29592
  eventBus.emit(event, { turn: currentTurn, phase, activeTeam });
@@ -29549,28 +29611,16 @@ function TurnPanel({
29549
29611
  activeTeam
29550
29612
  }
29551
29613
  ),
29552
- actions && actions.length > 0 && /* @__PURE__ */ jsx(Box, { className: "flex items-center gap-1.5 ml-auto", children: actions.map((action, i) => /* @__PURE__ */ jsxs(
29553
- Button,
29614
+ actions && actions.length > 0 && /* @__PURE__ */ jsx(Box, { className: "flex items-center gap-1.5 ml-auto", children: actions.map((action, i) => /* @__PURE__ */ jsx(
29615
+ ActionButton,
29554
29616
  {
29555
- variant: "ghost",
29556
- size: "sm",
29617
+ label: action.label,
29618
+ icon: action.assetUrl ? void 0 : action.icon,
29619
+ assetUrl: action.assetUrl,
29557
29620
  disabled: action.disabled,
29558
- leftIcon: action.assetUrl ? void 0 : action.icon,
29559
- onClick: () => handleAction(action.event),
29560
- children: [
29561
- action.assetUrl && /* @__PURE__ */ jsx(
29562
- "img",
29563
- {
29564
- src: action.assetUrl,
29565
- alt: "",
29566
- width: 14,
29567
- height: 14,
29568
- style: { imageRendering: "pixelated", objectFit: "contain" },
29569
- className: "flex-shrink-0"
29570
- }
29571
- ),
29572
- action.label
29573
- ]
29621
+ variant: "secondary",
29622
+ size: "sm",
29623
+ onClick: () => handleAction(action.event)
29574
29624
  },
29575
29625
  i
29576
29626
  )) })
@@ -29584,7 +29634,7 @@ var init_TurnPanel = __esm({
29584
29634
  "use client";
29585
29635
  init_cn();
29586
29636
  init_TurnIndicator();
29587
- init_Button();
29637
+ init_ActionButton();
29588
29638
  init_Box();
29589
29639
  init_useEventBus();
29590
29640
  DEFAULT_TURN_ACTIONS = [
@@ -29635,7 +29685,7 @@ function EnemyPlate({
29635
29685
  }
29636
29686
  )
29637
29687
  ] }),
29638
- level != null && /* @__PURE__ */ jsxs(Badge, { variant: "neutral", size: "sm", children: [
29688
+ level != null && /* @__PURE__ */ jsxs("span", { className: "text-xs font-bold text-muted-foreground bg-muted/60 rounded px-1.5 py-0.5 border border-border/50 shrink-0", children: [
29639
29689
  "Lv.",
29640
29690
  level
29641
29691
  ] })
@@ -29666,12 +29716,12 @@ function EnemyPlate({
29666
29716
  )
29667
29717
  ] }),
29668
29718
  effects && effects.length > 0 && /* @__PURE__ */ jsx(Box, { className: "flex items-center gap-1 flex-wrap", children: effects.map((effect, i) => /* @__PURE__ */ jsx(
29669
- Badge,
29719
+ StatusEffect,
29670
29720
  {
29671
- variant: effectVariantMap2[effect.variant ?? "neutral"],
29672
- size: "sm",
29673
29721
  icon: effect.icon,
29674
- children: effect.label
29722
+ label: effect.label,
29723
+ variant: effectVariantMap2[effect.variant ?? "neutral"],
29724
+ size: "sm"
29675
29725
  },
29676
29726
  i
29677
29727
  )) })
@@ -29685,12 +29735,12 @@ var init_EnemyPlate = __esm({
29685
29735
  "use client";
29686
29736
  init_cn();
29687
29737
  init_HealthBar();
29738
+ init_StatusEffect();
29688
29739
  init_Box();
29689
29740
  init_Typography();
29690
- init_Badge();
29691
29741
  effectVariantMap2 = {
29692
- buff: "success",
29693
- debuff: "danger",
29742
+ buff: "buff",
29743
+ debuff: "debuff",
29694
29744
  neutral: "neutral"
29695
29745
  };
29696
29746
  DEFAULT_ENEMY_EFFECTS = [
@@ -29705,7 +29755,7 @@ function UnitCommandBar({
29705
29755
  className
29706
29756
  }) {
29707
29757
  const eventBus = useEventBus();
29708
- const handleCommand = React84.useCallback(
29758
+ const handleCommand = React85.useCallback(
29709
29759
  (event) => {
29710
29760
  if (event) {
29711
29761
  eventBus.emit(event, { unitId: selectedUnitId });
@@ -29720,27 +29770,18 @@ function UnitCommandBar({
29720
29770
  "flex items-center gap-1.5 rounded-container bg-[var(--color-card)]/90 border border-border backdrop-blur-sm px-2 py-1.5",
29721
29771
  className
29722
29772
  ),
29723
- children: commands.map((command, i) => /* @__PURE__ */ jsxs(Box, { className: "flex flex-col items-center gap-0.5", children: [
29724
- /* @__PURE__ */ jsx(
29725
- Button,
29726
- {
29727
- variant: "ghost",
29728
- size: "sm",
29729
- disabled: command.disabled,
29730
- leftIcon: command.icon,
29731
- onClick: () => handleCommand(command.event),
29732
- children: command.label
29733
- }
29734
- ),
29735
- command.hotkey && /* @__PURE__ */ jsx(
29736
- Typography,
29737
- {
29738
- variant: "caption",
29739
- className: "text-muted-foreground text-xs font-mono",
29740
- children: command.hotkey
29741
- }
29742
- )
29743
- ] }, i))
29773
+ children: commands.map((command, i) => /* @__PURE__ */ jsx(Box, { className: "flex flex-col items-center gap-0.5", children: /* @__PURE__ */ jsx(
29774
+ ActionButton,
29775
+ {
29776
+ label: command.label,
29777
+ icon: command.icon,
29778
+ disabled: command.disabled,
29779
+ hotkey: command.hotkey,
29780
+ variant: "secondary",
29781
+ size: "sm",
29782
+ onClick: () => handleCommand(command.event)
29783
+ }
29784
+ ) }, i))
29744
29785
  }
29745
29786
  );
29746
29787
  }
@@ -29749,9 +29790,8 @@ var init_UnitCommandBar = __esm({
29749
29790
  "components/game/molecules/UnitCommandBar.tsx"() {
29750
29791
  "use client";
29751
29792
  init_cn();
29752
- init_Button();
29793
+ init_ActionButton();
29753
29794
  init_Box();
29754
- init_Typography();
29755
29795
  init_useEventBus();
29756
29796
  DEFAULT_COMMANDS = [
29757
29797
  { label: "Move", icon: "move", event: "MOVE", hotkey: "M" },
@@ -30256,7 +30296,7 @@ function GameMenu({
30256
30296
  } catch {
30257
30297
  }
30258
30298
  const eventBus = eventBusProp || eventBusFromHook;
30259
- const handleOptionClick = React84.useCallback(
30299
+ const handleOptionClick = React85.useCallback(
30260
30300
  (option) => {
30261
30301
  if (option.event && eventBus) {
30262
30302
  eventBus.emit(`UI:${option.event}`, { option });
@@ -30375,7 +30415,7 @@ function GameOverScreen({
30375
30415
  } catch {
30376
30416
  }
30377
30417
  const eventBus = eventBusProp || eventBusFromHook;
30378
- const handleActionClick = React84.useCallback(
30418
+ const handleActionClick = React85.useCallback(
30379
30419
  (action) => {
30380
30420
  if (action.event && eventBus) {
30381
30421
  eventBus.emit(`UI:${action.event}`, { action });
@@ -30590,6 +30630,7 @@ function PlatformerCanvas({
30590
30630
  rightEvent = "MOVE_RIGHT",
30591
30631
  jumpEvent = "JUMP",
30592
30632
  stopEvent = "STOP",
30633
+ effects = [],
30593
30634
  className
30594
30635
  }) {
30595
30636
  const canvasRef = useRef(null);
@@ -30660,7 +30701,8 @@ function PlatformerCanvas({
30660
30701
  playerSprite,
30661
30702
  tileSprites,
30662
30703
  backgroundImage,
30663
- assetBaseUrl
30704
+ assetBaseUrl,
30705
+ effects
30664
30706
  });
30665
30707
  propsRef.current = {
30666
30708
  platforms,
@@ -30673,7 +30715,8 @@ function PlatformerCanvas({
30673
30715
  playerSprite,
30674
30716
  tileSprites,
30675
30717
  backgroundImage,
30676
- assetBaseUrl
30718
+ assetBaseUrl,
30719
+ effects
30677
30720
  };
30678
30721
  const handleKeyDown = useCallback((e) => {
30679
30722
  if (keysRef.current.has(e.code)) return;
@@ -30740,7 +30783,8 @@ function PlatformerCanvas({
30740
30783
  bgColor: bg,
30741
30784
  playerSprite: pSprite,
30742
30785
  tileSprites: tSprites,
30743
- backgroundImage: bgImg
30786
+ backgroundImage: bgImg,
30787
+ effects: fxList
30744
30788
  } = propsRef.current;
30745
30789
  const auth = playerRef.current;
30746
30790
  const interped = positions.get("player");
@@ -30894,6 +30938,18 @@ function PlatformerCanvas({
30894
30938
  ctx.arc(ppx + eyeOffsetX + 7, eyeY, eyeSize, 0, Math.PI * 2);
30895
30939
  ctx.fill();
30896
30940
  }
30941
+ for (const fx of fxList) {
30942
+ const fxScreenX = fx.x - camX;
30943
+ const fxScreenY = fx.y - camY;
30944
+ const alpha = Math.min(1, fx.ttl / 4);
30945
+ const prev = ctx.globalAlpha;
30946
+ ctx.globalAlpha = alpha;
30947
+ ctx.fillStyle = "#ffe066";
30948
+ ctx.beginPath();
30949
+ ctx.arc(fxScreenX, fxScreenY, 12, 0, Math.PI * 2);
30950
+ ctx.fill();
30951
+ ctx.globalAlpha = prev;
30952
+ }
30897
30953
  };
30898
30954
  return interp.startLoop(drawFrame);
30899
30955
  }, [interp.startLoop, loadImage]);
@@ -31330,13 +31386,13 @@ var init_MapView = __esm({
31330
31386
  shadowSize: [41, 41]
31331
31387
  });
31332
31388
  L.Marker.prototype.options.icon = defaultIcon;
31333
- const { useEffect: useEffect84, useRef: useRef83, useCallback: useCallback128, useState: useState114 } = React84__default;
31389
+ const { useEffect: useEffect82, useRef: useRef83, useCallback: useCallback128, useState: useState112 } = React85__default;
31334
31390
  const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
31335
31391
  const { useEventBus: useEventBus3 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
31336
31392
  function MapUpdater({ centerLat, centerLng, zoom }) {
31337
31393
  const map = useMap();
31338
31394
  const prevRef = useRef83({ centerLat, centerLng, zoom });
31339
- useEffect84(() => {
31395
+ useEffect82(() => {
31340
31396
  const prev = prevRef.current;
31341
31397
  if (prev.centerLat !== centerLat || prev.centerLng !== centerLng || prev.zoom !== zoom) {
31342
31398
  map.setView([centerLat, centerLng], zoom);
@@ -31347,7 +31403,7 @@ var init_MapView = __esm({
31347
31403
  }
31348
31404
  function MapClickHandler({ onMapClick }) {
31349
31405
  const map = useMap();
31350
- useEffect84(() => {
31406
+ useEffect82(() => {
31351
31407
  if (!onMapClick) return;
31352
31408
  const handler = (e) => {
31353
31409
  onMapClick(e.latlng.lat, e.latlng.lng);
@@ -31375,7 +31431,7 @@ var init_MapView = __esm({
31375
31431
  showAttribution = true
31376
31432
  }) {
31377
31433
  const eventBus = useEventBus3();
31378
- const [clickedPosition, setClickedPosition] = useState114(null);
31434
+ const [clickedPosition, setClickedPosition] = useState112(null);
31379
31435
  const handleMapClick = useCallback128((lat, lng) => {
31380
31436
  if (showClickedPin) {
31381
31437
  setClickedPosition({ lat, lng });
@@ -32245,8 +32301,8 @@ function TableView({
32245
32301
  }) {
32246
32302
  const eventBus = useEventBus();
32247
32303
  const { t } = useTranslate();
32248
- const [visibleCount, setVisibleCount] = React84__default.useState(pageSize > 0 ? pageSize : Infinity);
32249
- const [localSelected, setLocalSelected] = React84__default.useState(/* @__PURE__ */ new Set());
32304
+ const [visibleCount, setVisibleCount] = React85__default.useState(pageSize > 0 ? pageSize : Infinity);
32305
+ const [localSelected, setLocalSelected] = React85__default.useState(/* @__PURE__ */ new Set());
32250
32306
  const colDefs = columns ?? fields ?? [];
32251
32307
  const allDataRaw = Array.isArray(entity) ? entity : entity ? [entity] : [];
32252
32308
  const dnd = useDataDnd({
@@ -32441,12 +32497,12 @@ function TableView({
32441
32497
  ]
32442
32498
  }
32443
32499
  );
32444
- return dnd.isZone ? /* @__PURE__ */ jsx(dnd.SortableItem, { id: row[idField] ?? id, children: rowInner }, id) : /* @__PURE__ */ jsx(React84__default.Fragment, { children: rowInner }, id);
32500
+ return dnd.isZone ? /* @__PURE__ */ jsx(dnd.SortableItem, { id: row[idField] ?? id, children: rowInner }, id) : /* @__PURE__ */ jsx(React85__default.Fragment, { children: rowInner }, id);
32445
32501
  };
32446
32502
  const items = Array.from(data);
32447
32503
  const groups = groupBy ? groupData2(items, groupBy) : [{ label: "", items }];
32448
32504
  let runningIndex = 0;
32449
- const body = /* @__PURE__ */ jsx(Box, { role: "rowgroup", children: groups.map((group, gi) => /* @__PURE__ */ jsxs(React84__default.Fragment, { children: [
32505
+ const body = /* @__PURE__ */ jsx(Box, { role: "rowgroup", children: groups.map((group, gi) => /* @__PURE__ */ jsxs(React85__default.Fragment, { children: [
32450
32506
  group.label && /* @__PURE__ */ jsx(Divider, { label: group.label, className: gi > 0 ? "mt-3" : "mt-0" }),
32451
32507
  group.items.map((row) => renderRow(row, runningIndex++))
32452
32508
  ] }, gi)) });
@@ -33803,7 +33859,7 @@ var init_StepFlow = __esm({
33803
33859
  className
33804
33860
  }) => {
33805
33861
  if (orientation === "vertical") {
33806
- return /* @__PURE__ */ jsx(VStack, { gap: "none", className: cn("w-full", className), children: steps.map((step, index) => /* @__PURE__ */ jsx(React84__default.Fragment, { children: /* @__PURE__ */ jsxs(HStack, { gap: "md", align: "start", className: "w-full", children: [
33862
+ return /* @__PURE__ */ jsx(VStack, { gap: "none", className: cn("w-full", className), children: steps.map((step, index) => /* @__PURE__ */ jsx(React85__default.Fragment, { children: /* @__PURE__ */ jsxs(HStack, { gap: "md", align: "start", className: "w-full", children: [
33807
33863
  /* @__PURE__ */ jsxs(VStack, { gap: "none", align: "center", children: [
33808
33864
  /* @__PURE__ */ jsx(StepCircle, { step, index }),
33809
33865
  showConnectors && index < steps.length - 1 && /* @__PURE__ */ jsx(Box, { className: "w-px h-8 bg-border" })
@@ -33814,7 +33870,7 @@ var init_StepFlow = __esm({
33814
33870
  ] })
33815
33871
  ] }) }, index)) });
33816
33872
  }
33817
- 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(React84__default.Fragment, { children: [
33873
+ return /* @__PURE__ */ jsx(Box, { className: cn("w-full flex flex-col md:flex-row items-start gap-0", className), children: steps.map((step, index) => /* @__PURE__ */ jsxs(React85__default.Fragment, { children: [
33818
33874
  /* @__PURE__ */ jsxs(VStack, { gap: "sm", align: "center", className: "flex-1 w-full md:w-auto", children: [
33819
33875
  /* @__PURE__ */ jsx(StepCircle, { step, index }),
33820
33876
  /* @__PURE__ */ jsx(Typography, { variant: "h4", className: "text-center", children: step.title }),
@@ -34799,7 +34855,7 @@ var init_LikertScale = __esm({
34799
34855
  md: "text-base",
34800
34856
  lg: "text-lg"
34801
34857
  };
34802
- LikertScale = React84__default.forwardRef(
34858
+ LikertScale = React85__default.forwardRef(
34803
34859
  ({
34804
34860
  question,
34805
34861
  options = DEFAULT_LIKERT_OPTIONS,
@@ -34811,7 +34867,7 @@ var init_LikertScale = __esm({
34811
34867
  variant = "radios",
34812
34868
  className
34813
34869
  }, ref) => {
34814
- const groupId = React84__default.useId();
34870
+ const groupId = React85__default.useId();
34815
34871
  const eventBus = useEventBus();
34816
34872
  const handleSelect = useCallback(
34817
34873
  (next) => {
@@ -37093,7 +37149,7 @@ var init_DocBreadcrumb = __esm({
37093
37149
  "aria-label": t("aria.breadcrumb"),
37094
37150
  children: /* @__PURE__ */ jsx(HStack, { gap: "xs", align: "center", wrap: true, children: items.map((item, idx) => {
37095
37151
  const isLast = idx === items.length - 1;
37096
- return /* @__PURE__ */ jsxs(React84__default.Fragment, { children: [
37152
+ return /* @__PURE__ */ jsxs(React85__default.Fragment, { children: [
37097
37153
  idx > 0 && /* @__PURE__ */ jsx(
37098
37154
  Icon,
37099
37155
  {
@@ -37962,7 +38018,7 @@ var init_MiniStateMachine = __esm({
37962
38018
  const x = 2 + i * (NODE_W + GAP2 + ARROW_W + GAP2);
37963
38019
  const tc = transitionCounts[s.name] ?? 0;
37964
38020
  const role = getStateRole(s.name, s.isInitial ?? void 0, s.isTerminal ?? void 0, tc, maxTC);
37965
- return /* @__PURE__ */ jsxs(React84__default.Fragment, { children: [
38021
+ return /* @__PURE__ */ jsxs(React85__default.Fragment, { children: [
37966
38022
  /* @__PURE__ */ jsx(
37967
38023
  AvlState,
37968
38024
  {
@@ -38166,7 +38222,7 @@ var init_PageHeader = __esm({
38166
38222
  info: "bg-info/10 text-info"
38167
38223
  };
38168
38224
  return /* @__PURE__ */ jsxs(Box, { className: cn("mb-6", className), children: [
38169
- 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(React84__default.Fragment, { children: [
38225
+ breadcrumbs && breadcrumbs.length > 0 && /* @__PURE__ */ jsx(Box, { as: "nav", className: "mb-4", children: /* @__PURE__ */ jsx(Box, { as: "ol", className: "flex items-center gap-2 text-sm", children: breadcrumbs.map((crumb, idx) => /* @__PURE__ */ jsxs(React85__default.Fragment, { children: [
38170
38226
  idx > 0 && /* @__PURE__ */ jsx(Typography, { variant: "small", color: "muted", children: "/" }),
38171
38227
  crumb.href ? /* @__PURE__ */ jsx(
38172
38228
  "a",
@@ -38483,7 +38539,7 @@ var init_Navigation = __esm({
38483
38539
  Navigation.displayName = "Navigation";
38484
38540
  }
38485
38541
  });
38486
- var paddingStyles4, variantStyles8, Section;
38542
+ var paddingStyles4, variantStyles9, Section;
38487
38543
  var init_Section = __esm({
38488
38544
  "components/core/molecules/Section.tsx"() {
38489
38545
  init_cn();
@@ -38496,7 +38552,7 @@ var init_Section = __esm({
38496
38552
  lg: "p-6",
38497
38553
  xl: "p-8"
38498
38554
  };
38499
- variantStyles8 = {
38555
+ variantStyles9 = {
38500
38556
  default: "",
38501
38557
  card: [
38502
38558
  "bg-card",
@@ -38524,12 +38580,12 @@ var init_Section = __esm({
38524
38580
  as: Component2 = "section"
38525
38581
  }) => {
38526
38582
  const hasHeader = title || description || action;
38527
- return React84__default.createElement(
38583
+ return React85__default.createElement(
38528
38584
  Component2,
38529
38585
  {
38530
38586
  className: cn(
38531
38587
  paddingStyles4[padding],
38532
- variantStyles8[variant],
38588
+ variantStyles9[variant],
38533
38589
  className
38534
38590
  )
38535
38591
  },
@@ -38892,7 +38948,7 @@ var init_WizardContainer = __esm({
38892
38948
  const isCompleted = index < currentStep;
38893
38949
  const stepKey = step.id ?? step.tabId ?? `step-${index}`;
38894
38950
  const stepTitle = step.title ?? step.name ?? `Step ${index + 1}`;
38895
- return /* @__PURE__ */ jsxs(React84__default.Fragment, { children: [
38951
+ return /* @__PURE__ */ jsxs(React85__default.Fragment, { children: [
38896
38952
  /* @__PURE__ */ jsx(
38897
38953
  Button,
38898
38954
  {
@@ -41721,7 +41777,7 @@ var init_DialogueBubble = __esm({
41721
41777
  }
41722
41778
  });
41723
41779
  function extractTitle(children) {
41724
- if (!React84__default.isValidElement(children)) return void 0;
41780
+ if (!React85__default.isValidElement(children)) return void 0;
41725
41781
  const props = children.props;
41726
41782
  if (typeof props.title === "string") {
41727
41783
  return props.title;
@@ -41766,7 +41822,7 @@ var init_DrawerSlot = __esm({
41766
41822
  }
41767
41823
  });
41768
41824
  function StateIndicator({
41769
- assetUrl = DEFAULT_ASSET_URL9,
41825
+ assetUrl = DEFAULT_ASSET_URL10,
41770
41826
  state = "idle",
41771
41827
  label,
41772
41828
  size = "md",
@@ -41805,13 +41861,13 @@ function StateIndicator({
41805
41861
  }
41806
41862
  );
41807
41863
  }
41808
- var DEFAULT_ASSET_URL9, DEFAULT_STATE_STYLES, DEFAULT_STYLE, SIZE_CLASSES;
41864
+ var DEFAULT_ASSET_URL10, DEFAULT_STATE_STYLES, DEFAULT_STYLE, SIZE_CLASSES;
41809
41865
  var init_StateIndicator = __esm({
41810
41866
  "components/game/atoms/StateIndicator.tsx"() {
41811
41867
  init_Box();
41812
41868
  init_Icon();
41813
41869
  init_cn();
41814
- DEFAULT_ASSET_URL9 = "https://almadar-kflow-assets.web.app/shared/isometric-dungeon/Isometric/chestClosed_E.png";
41870
+ DEFAULT_ASSET_URL10 = "https://almadar-kflow-assets.web.app/shared/isometric-dungeon/Isometric/chestClosed_E.png";
41815
41871
  DEFAULT_STATE_STYLES = {
41816
41872
  idle: { icon: "\u23F8", bgClass: "bg-muted" },
41817
41873
  active: { icon: "\u25B6", bgClass: "bg-success" },
@@ -41846,7 +41902,7 @@ function LinearView({
41846
41902
  /* @__PURE__ */ jsx(HStack, { className: "flex-wrap items-center", gap: "xs", children: trait.states.map((state, i) => {
41847
41903
  const isDone = i < currentIdx;
41848
41904
  const isCurrent = i === currentIdx;
41849
- return /* @__PURE__ */ jsxs(React84__default.Fragment, { children: [
41905
+ return /* @__PURE__ */ jsxs(React85__default.Fragment, { children: [
41850
41906
  i > 0 && /* @__PURE__ */ jsx(
41851
41907
  Typography,
41852
41908
  {
@@ -42832,12 +42888,12 @@ var init_Form = __esm({
42832
42888
  const isSchemaEntity = isOrbitalEntitySchema(entity);
42833
42889
  const resolvedEntity = isSchemaEntity ? entity : void 0;
42834
42890
  const entityName = typeof entity === "string" ? entity : resolvedEntity?.name;
42835
- const normalizedInitialData = React84__default.useMemo(() => {
42891
+ const normalizedInitialData = React85__default.useMemo(() => {
42836
42892
  const entityRowAsInitial = isPlainEntityRow(entity) ? entity : void 0;
42837
42893
  const callerInitial = initialData !== null && typeof initialData === "object" && !Array.isArray(initialData) ? initialData : {};
42838
42894
  return entityRowAsInitial !== void 0 ? { ...entityRowAsInitial, ...callerInitial } : callerInitial;
42839
42895
  }, [entity, initialData]);
42840
- const entityDerivedFields = React84__default.useMemo(() => {
42896
+ const entityDerivedFields = React85__default.useMemo(() => {
42841
42897
  if (fields && fields.length > 0) return void 0;
42842
42898
  if (!resolvedEntity) return void 0;
42843
42899
  return resolvedEntity.fields.map(
@@ -42858,16 +42914,16 @@ var init_Form = __esm({
42858
42914
  const conditionalFields = typeof conditionalFieldsRaw === "boolean" ? {} : conditionalFieldsRaw;
42859
42915
  const hiddenCalculations = typeof hiddenCalculationsRaw === "boolean" ? [] : hiddenCalculationsRaw;
42860
42916
  const violationTriggers = typeof violationTriggersRaw === "boolean" ? [] : violationTriggersRaw;
42861
- const [formData, setFormData] = React84__default.useState(
42917
+ const [formData, setFormData] = React85__default.useState(
42862
42918
  normalizedInitialData
42863
42919
  );
42864
- const [collapsedSections, setCollapsedSections] = React84__default.useState(
42920
+ const [collapsedSections, setCollapsedSections] = React85__default.useState(
42865
42921
  /* @__PURE__ */ new Set()
42866
42922
  );
42867
- const [submitError, setSubmitError] = React84__default.useState(null);
42868
- const formRef = React84__default.useRef(null);
42923
+ const [submitError, setSubmitError] = React85__default.useState(null);
42924
+ const formRef = React85__default.useRef(null);
42869
42925
  const formMode = props.mode;
42870
- const mountedRef = React84__default.useRef(false);
42926
+ const mountedRef = React85__default.useRef(false);
42871
42927
  if (!mountedRef.current) {
42872
42928
  mountedRef.current = true;
42873
42929
  debug("forms", "mount", {
@@ -42880,7 +42936,7 @@ var init_Form = __esm({
42880
42936
  });
42881
42937
  }
42882
42938
  const shouldShowCancel = showCancel ?? (fields && fields.length > 0);
42883
- const evalContext = React84__default.useMemo(
42939
+ const evalContext = React85__default.useMemo(
42884
42940
  () => ({
42885
42941
  formValues: formData,
42886
42942
  globalVariables: externalContext?.globalVariables ?? {},
@@ -42889,7 +42945,7 @@ var init_Form = __esm({
42889
42945
  }),
42890
42946
  [formData, externalContext]
42891
42947
  );
42892
- React84__default.useEffect(() => {
42948
+ React85__default.useEffect(() => {
42893
42949
  debug("forms", "initialData-sync", {
42894
42950
  mode: formMode,
42895
42951
  normalizedInitialData,
@@ -42900,7 +42956,7 @@ var init_Form = __esm({
42900
42956
  setFormData(normalizedInitialData);
42901
42957
  }
42902
42958
  }, [normalizedInitialData]);
42903
- const processCalculations = React84__default.useCallback(
42959
+ const processCalculations = React85__default.useCallback(
42904
42960
  (changedFieldId, newFormData) => {
42905
42961
  if (!hiddenCalculations.length) return;
42906
42962
  const context = {
@@ -42925,7 +42981,7 @@ var init_Form = __esm({
42925
42981
  },
42926
42982
  [hiddenCalculations, externalContext, eventBus]
42927
42983
  );
42928
- const checkViolations = React84__default.useCallback(
42984
+ const checkViolations = React85__default.useCallback(
42929
42985
  (changedFieldId, newFormData) => {
42930
42986
  if (!violationTriggers.length) return;
42931
42987
  const context = {
@@ -42963,7 +43019,7 @@ var init_Form = __esm({
42963
43019
  processCalculations(name, newFormData);
42964
43020
  checkViolations(name, newFormData);
42965
43021
  };
42966
- const isFieldVisible = React84__default.useCallback(
43022
+ const isFieldVisible = React85__default.useCallback(
42967
43023
  (fieldName) => {
42968
43024
  const condition = conditionalFields[fieldName];
42969
43025
  if (!condition) return true;
@@ -42971,7 +43027,7 @@ var init_Form = __esm({
42971
43027
  },
42972
43028
  [conditionalFields, evalContext]
42973
43029
  );
42974
- const isSectionVisible = React84__default.useCallback(
43030
+ const isSectionVisible = React85__default.useCallback(
42975
43031
  (section) => {
42976
43032
  if (!section.condition) return true;
42977
43033
  return Boolean(evaluateFormExpression(section.condition, evalContext));
@@ -43047,7 +43103,7 @@ var init_Form = __esm({
43047
43103
  eventBus.emit(`UI:${onCancel}`);
43048
43104
  }
43049
43105
  };
43050
- const renderField = React84__default.useCallback(
43106
+ const renderField = React85__default.useCallback(
43051
43107
  (field) => {
43052
43108
  const fieldName = field.name || field.field;
43053
43109
  if (!fieldName) return null;
@@ -43068,7 +43124,7 @@ var init_Form = __esm({
43068
43124
  [formData, isFieldVisible, relationsData, relationsLoading, isLoading]
43069
43125
  );
43070
43126
  const effectiveFields = entityDerivedFields ?? fields;
43071
- const normalizedFields = React84__default.useMemo(() => {
43127
+ const normalizedFields = React85__default.useMemo(() => {
43072
43128
  if (!effectiveFields || effectiveFields.length === 0) return [];
43073
43129
  return effectiveFields.map((field) => {
43074
43130
  if (typeof field === "string") {
@@ -43092,7 +43148,7 @@ var init_Form = __esm({
43092
43148
  return field;
43093
43149
  });
43094
43150
  }, [effectiveFields, resolvedEntity]);
43095
- const schemaFields = React84__default.useMemo(() => {
43151
+ const schemaFields = React85__default.useMemo(() => {
43096
43152
  if (normalizedFields.length === 0) return null;
43097
43153
  if (isDebugEnabled()) {
43098
43154
  debugGroup(`Form: ${entityName || "unknown"}`);
@@ -43102,7 +43158,7 @@ var init_Form = __esm({
43102
43158
  }
43103
43159
  return normalizedFields.map(renderField).filter(Boolean);
43104
43160
  }, [normalizedFields, renderField, entityName, conditionalFields]);
43105
- const sectionElements = React84__default.useMemo(() => {
43161
+ const sectionElements = React85__default.useMemo(() => {
43106
43162
  if (!sections || sections.length === 0) return null;
43107
43163
  return sections.map((section) => {
43108
43164
  if (!isSectionVisible(section)) {
@@ -44630,7 +44686,6 @@ var init_GameCanvas3D2 = __esm({
44630
44686
  className,
44631
44687
  isLoading: externalLoading,
44632
44688
  error: externalError,
44633
- entity,
44634
44689
  preloadAssets = [],
44635
44690
  tileClickEvent,
44636
44691
  unitClickEvent,
@@ -45366,7 +45421,7 @@ var init_GameBoard3D = __esm({
45366
45421
  }
45367
45422
  });
45368
45423
  function asDescriptor(v) {
45369
- if (Array.isArray(v) || React84__default.isValidElement(v)) return null;
45424
+ if (Array.isArray(v) || React85__default.isValidElement(v)) return null;
45370
45425
  const o = v;
45371
45426
  if (typeof o.type !== "string") return null;
45372
45427
  const props = o.props !== void 0 && typeof o.props === "object" && !Array.isArray(o.props) && o.props !== null ? o.props : void 0;
@@ -45381,10 +45436,10 @@ function getSlotContentRenderer() {
45381
45436
  }
45382
45437
  function resolveDescriptor(value, idPrefix) {
45383
45438
  if (value === null || value === void 0) return value;
45384
- if (React84__default.isValidElement(value)) return value;
45439
+ if (React85__default.isValidElement(value)) return value;
45385
45440
  if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") return value;
45386
45441
  if (Array.isArray(value)) {
45387
- return value.map((item, i) => /* @__PURE__ */ jsx(React84__default.Fragment, { children: resolveDescriptor(item, `${idPrefix}-${i}`) }, i));
45442
+ return value.map((item, i) => /* @__PURE__ */ jsx(React85__default.Fragment, { children: resolveDescriptor(item, `${idPrefix}-${i}`) }, i));
45388
45443
  }
45389
45444
  if (typeof value === "object" && value !== null) {
45390
45445
  const desc = asDescriptor(value);
@@ -45484,10 +45539,10 @@ function getSlotContentRenderer2() {
45484
45539
  }
45485
45540
  function resolveDescriptor2(value, idPrefix) {
45486
45541
  if (value === null || value === void 0) return value;
45487
- if (React84__default.isValidElement(value)) return value;
45542
+ if (React85__default.isValidElement(value)) return value;
45488
45543
  if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") return value;
45489
45544
  if (Array.isArray(value)) {
45490
- return value.map((item, i) => /* @__PURE__ */ jsx(React84__default.Fragment, { children: resolveDescriptor2(item, `${idPrefix}-${i}`) }, i));
45545
+ return value.map((item, i) => /* @__PURE__ */ jsx(React85__default.Fragment, { children: resolveDescriptor2(item, `${idPrefix}-${i}`) }, i));
45491
45546
  }
45492
45547
  if (typeof value === "object") {
45493
45548
  const rec = value;
@@ -46200,7 +46255,7 @@ var init_List = __esm({
46200
46255
  if (entity && typeof entity === "object" && "id" in entity) return [entity];
46201
46256
  return [];
46202
46257
  }, [entity]);
46203
- const getItemActions = React84__default.useCallback(
46258
+ const getItemActions = React85__default.useCallback(
46204
46259
  (item) => {
46205
46260
  if (!itemActions) return [];
46206
46261
  if (typeof itemActions === "function") {
@@ -46717,7 +46772,7 @@ var init_MediaGallery = __esm({
46717
46772
  [selectable, selectedItems, selectionEvent, eventBus]
46718
46773
  );
46719
46774
  const entityData = Array.isArray(entity) ? entity : [];
46720
- const items = React84__default.useMemo(() => {
46775
+ const items = React85__default.useMemo(() => {
46721
46776
  if (propItems) return propItems;
46722
46777
  if (entityData.length === 0) return [];
46723
46778
  return entityData.map((record, idx) => {
@@ -46879,114 +46934,6 @@ var init_MediaGallery = __esm({
46879
46934
  MediaGallery.displayName = "MediaGallery";
46880
46935
  }
46881
46936
  });
46882
- function MiniMap({
46883
- tiles = DEFAULT_TILES,
46884
- units = DEFAULT_UNITS,
46885
- width = 150,
46886
- height = 150,
46887
- mapWidth = 100,
46888
- mapHeight = 100,
46889
- viewportRect = DEFAULT_VIEWPORT,
46890
- className
46891
- }) {
46892
- const canvasRef = React84.useRef(null);
46893
- const frameRef = React84.useRef(0);
46894
- React84.useEffect(() => {
46895
- const canvas = canvasRef.current;
46896
- if (!canvas) return;
46897
- const ctx = canvas.getContext("2d");
46898
- if (!ctx) return;
46899
- const scaleX = width / mapWidth;
46900
- const scaleY = height / mapHeight;
46901
- let blinkOn = true;
46902
- let animFrame;
46903
- function draw() {
46904
- if (!ctx) return;
46905
- ctx.clearRect(0, 0, width, height);
46906
- ctx.fillStyle = "#111";
46907
- ctx.fillRect(0, 0, width, height);
46908
- for (const tile of tiles) {
46909
- ctx.fillStyle = tile.color;
46910
- ctx.fillRect(
46911
- Math.floor(tile.x * scaleX),
46912
- Math.floor(tile.y * scaleY),
46913
- Math.max(1, Math.ceil(scaleX)),
46914
- Math.max(1, Math.ceil(scaleY))
46915
- );
46916
- }
46917
- for (const unit of units) {
46918
- if (unit.isPlayer && !blinkOn) continue;
46919
- ctx.fillStyle = unit.isPlayer ? "#ffffff" : unit.color;
46920
- const ux = Math.floor(unit.x * scaleX) - 1;
46921
- const uy = Math.floor(unit.y * scaleY) - 1;
46922
- ctx.fillRect(ux, uy, 3, 3);
46923
- }
46924
- if (viewportRect) {
46925
- ctx.strokeStyle = "#ffffff";
46926
- ctx.lineWidth = 1;
46927
- ctx.strokeRect(
46928
- Math.floor(viewportRect.x * scaleX),
46929
- Math.floor(viewportRect.y * scaleY),
46930
- Math.floor(viewportRect.w * scaleX),
46931
- Math.floor(viewportRect.h * scaleY)
46932
- );
46933
- }
46934
- }
46935
- function tick() {
46936
- frameRef.current++;
46937
- if (frameRef.current % 30 === 0) {
46938
- blinkOn = !blinkOn;
46939
- }
46940
- draw();
46941
- animFrame = requestAnimationFrame(tick);
46942
- }
46943
- tick();
46944
- return () => {
46945
- cancelAnimationFrame(animFrame);
46946
- };
46947
- }, [tiles, units, width, height, mapWidth, mapHeight, viewportRect]);
46948
- return /* @__PURE__ */ jsx(
46949
- "div",
46950
- {
46951
- className: cn(
46952
- "relative inline-block border border-border/20 rounded-container",
46953
- className
46954
- ),
46955
- children: /* @__PURE__ */ jsx(
46956
- "canvas",
46957
- {
46958
- ref: canvasRef,
46959
- width,
46960
- height,
46961
- className: "block",
46962
- style: { width, height }
46963
- }
46964
- )
46965
- }
46966
- );
46967
- }
46968
- var DEFAULT_TILES, DEFAULT_UNITS, DEFAULT_VIEWPORT;
46969
- var init_MiniMap = __esm({
46970
- "components/game/atoms/MiniMap.tsx"() {
46971
- "use client";
46972
- init_cn();
46973
- DEFAULT_TILES = [
46974
- { x: 10, y: 10, color: "#4ade80" },
46975
- { x: 20, y: 15, color: "#4ade80" },
46976
- { x: 30, y: 25, color: "#22c55e" },
46977
- { x: 50, y: 40, color: "#4ade80" },
46978
- { x: 60, y: 55, color: "#16a34a" },
46979
- { x: 40, y: 60, color: "#4ade80" },
46980
- { x: 70, y: 30, color: "#22c55e" },
46981
- { x: 80, y: 70, color: "#4ade80" }
46982
- ];
46983
- DEFAULT_UNITS = [
46984
- { x: 30, y: 30, color: "#60a5fa", isPlayer: true }
46985
- ];
46986
- DEFAULT_VIEWPORT = { x: 20, y: 20, w: 40, h: 40 };
46987
- MiniMap.displayName = "MiniMap";
46988
- }
46989
- });
46990
46937
  function MinigolfBoard({
46991
46938
  tiles,
46992
46939
  units,
@@ -47030,7 +46977,7 @@ var init_MinigolfBoard = __esm({
47030
46977
  }
47031
46978
  });
47032
46979
  function extractTitle2(children) {
47033
- if (!React84__default.isValidElement(children)) return void 0;
46980
+ if (!React85__default.isValidElement(children)) return void 0;
47034
46981
  const props = children.props;
47035
46982
  if (typeof props.title === "string") {
47036
46983
  return props.title;
@@ -47738,7 +47685,7 @@ var init_RacingBoard = __esm({
47738
47685
  }
47739
47686
  });
47740
47687
  function ResourceCounter({
47741
- assetUrl = DEFAULT_ASSET_URL10,
47688
+ assetUrl = DEFAULT_ASSET_URL11,
47742
47689
  icon,
47743
47690
  label = "Gold",
47744
47691
  value = 250,
@@ -47747,7 +47694,7 @@ function ResourceCounter({
47747
47694
  size = "md",
47748
47695
  className
47749
47696
  }) {
47750
- const sizes = sizeMap15[size];
47697
+ const sizes = sizeMap16[size];
47751
47698
  return /* @__PURE__ */ jsxs(
47752
47699
  "div",
47753
47700
  {
@@ -47781,7 +47728,7 @@ function ResourceCounter({
47781
47728
  }
47782
47729
  );
47783
47730
  }
47784
- var colorTokenClasses2, DEFAULT_ASSET_URL10, sizeMap15;
47731
+ var colorTokenClasses2, DEFAULT_ASSET_URL11, sizeMap16;
47785
47732
  var init_ResourceCounter = __esm({
47786
47733
  "components/game/atoms/ResourceCounter.tsx"() {
47787
47734
  init_cn();
@@ -47794,8 +47741,8 @@ var init_ResourceCounter = __esm({
47794
47741
  error: "text-error",
47795
47742
  muted: "text-muted-foreground"
47796
47743
  };
47797
- DEFAULT_ASSET_URL10 = "https://almadar-kflow-assets.web.app/shared/world-map/gold_mine.png";
47798
- sizeMap15 = {
47744
+ DEFAULT_ASSET_URL11 = "https://almadar-kflow-assets.web.app/shared/world-map/gold_mine.png";
47745
+ sizeMap16 = {
47799
47746
  sm: { wrapper: "text-xs gap-1 px-1.5 py-0.5", icon: "text-sm", img: 16 },
47800
47747
  md: { wrapper: "text-sm gap-1.5 px-2 py-1", icon: "text-base", img: 20 },
47801
47748
  lg: { wrapper: "text-base gap-2 px-3 py-1.5", icon: "text-lg", img: 28 }
@@ -48278,7 +48225,7 @@ var init_debugRegistry = __esm({
48278
48225
  }
48279
48226
  });
48280
48227
  function useDebugData() {
48281
- const [data, setData] = React84.useState(() => ({
48228
+ const [data, setData] = React85.useState(() => ({
48282
48229
  traits: [],
48283
48230
  ticks: [],
48284
48231
  guards: [],
@@ -48292,7 +48239,7 @@ function useDebugData() {
48292
48239
  },
48293
48240
  lastUpdate: Date.now()
48294
48241
  }));
48295
- React84.useEffect(() => {
48242
+ React85.useEffect(() => {
48296
48243
  const updateData = () => {
48297
48244
  setData({
48298
48245
  traits: getAllTraits(),
@@ -48401,12 +48348,12 @@ function layoutGraph(states, transitions, initialState, width, height) {
48401
48348
  return positions;
48402
48349
  }
48403
48350
  function WalkMinimap() {
48404
- const [walkStep, setWalkStep] = React84.useState(null);
48405
- const [traits2, setTraits] = React84.useState([]);
48406
- const [coveredEdges, setCoveredEdges] = React84.useState([]);
48407
- const [completedTraits, setCompletedTraits] = React84.useState(/* @__PURE__ */ new Set());
48408
- const prevTraitRef = React84.useRef(null);
48409
- React84.useEffect(() => {
48351
+ const [walkStep, setWalkStep] = React85.useState(null);
48352
+ const [traits2, setTraits] = React85.useState([]);
48353
+ const [coveredEdges, setCoveredEdges] = React85.useState([]);
48354
+ const [completedTraits, setCompletedTraits] = React85.useState(/* @__PURE__ */ new Set());
48355
+ const prevTraitRef = React85.useRef(null);
48356
+ React85.useEffect(() => {
48410
48357
  const interval = setInterval(() => {
48411
48358
  const w = window;
48412
48359
  const step = w.__orbitalWalkStep;
@@ -48842,15 +48789,15 @@ var init_EntitiesTab = __esm({
48842
48789
  });
48843
48790
  function EventFlowTab({ events: events2 }) {
48844
48791
  const { t } = useTranslate();
48845
- const [filter, setFilter] = React84.useState("all");
48846
- const containerRef = React84.useRef(null);
48847
- const [autoScroll, setAutoScroll] = React84.useState(true);
48848
- React84.useEffect(() => {
48792
+ const [filter, setFilter] = React85.useState("all");
48793
+ const containerRef = React85.useRef(null);
48794
+ const [autoScroll, setAutoScroll] = React85.useState(true);
48795
+ React85.useEffect(() => {
48849
48796
  if (autoScroll && containerRef.current) {
48850
48797
  containerRef.current.scrollTop = containerRef.current.scrollHeight;
48851
48798
  }
48852
48799
  }, [events2.length, autoScroll]);
48853
- const filteredEvents = React84.useMemo(() => {
48800
+ const filteredEvents = React85.useMemo(() => {
48854
48801
  if (filter === "all") return events2;
48855
48802
  return events2.filter((e) => e.type === filter);
48856
48803
  }, [events2, filter]);
@@ -48966,7 +48913,7 @@ var init_EventFlowTab = __esm({
48966
48913
  });
48967
48914
  function GuardsPanel({ guards }) {
48968
48915
  const { t } = useTranslate();
48969
- const [filter, setFilter] = React84.useState("all");
48916
+ const [filter, setFilter] = React85.useState("all");
48970
48917
  if (guards.length === 0) {
48971
48918
  return /* @__PURE__ */ jsx(
48972
48919
  EmptyState,
@@ -48979,7 +48926,7 @@ function GuardsPanel({ guards }) {
48979
48926
  }
48980
48927
  const passedCount = guards.filter((g) => g.result).length;
48981
48928
  const failedCount = guards.length - passedCount;
48982
- const filteredGuards = React84.useMemo(() => {
48929
+ const filteredGuards = React85.useMemo(() => {
48983
48930
  if (filter === "all") return guards;
48984
48931
  if (filter === "passed") return guards.filter((g) => g.result);
48985
48932
  return guards.filter((g) => !g.result);
@@ -49142,10 +49089,10 @@ function EffectBadge({ effect }) {
49142
49089
  }
49143
49090
  function TransitionTimeline({ transitions }) {
49144
49091
  const { t } = useTranslate();
49145
- const containerRef = React84.useRef(null);
49146
- const [autoScroll, setAutoScroll] = React84.useState(true);
49147
- const [expandedId, setExpandedId] = React84.useState(null);
49148
- React84.useEffect(() => {
49092
+ const containerRef = React85.useRef(null);
49093
+ const [autoScroll, setAutoScroll] = React85.useState(true);
49094
+ const [expandedId, setExpandedId] = React85.useState(null);
49095
+ React85.useEffect(() => {
49149
49096
  if (autoScroll && containerRef.current) {
49150
49097
  containerRef.current.scrollTop = containerRef.current.scrollHeight;
49151
49098
  }
@@ -49425,9 +49372,9 @@ function getAllEvents(traits2) {
49425
49372
  function EventDispatcherTab({ traits: traits2, schema }) {
49426
49373
  const eventBus = useEventBus();
49427
49374
  const { t } = useTranslate();
49428
- const [log10, setLog] = React84.useState([]);
49429
- const prevStatesRef = React84.useRef(/* @__PURE__ */ new Map());
49430
- React84.useEffect(() => {
49375
+ const [log10, setLog] = React85.useState([]);
49376
+ const prevStatesRef = React85.useRef(/* @__PURE__ */ new Map());
49377
+ React85.useEffect(() => {
49431
49378
  for (const trait of traits2) {
49432
49379
  const prev = prevStatesRef.current.get(trait.id);
49433
49380
  if (prev && prev !== trait.currentState) {
@@ -49596,10 +49543,10 @@ function VerifyModePanel({
49596
49543
  localCount
49597
49544
  }) {
49598
49545
  const { t } = useTranslate();
49599
- const [expanded, setExpanded] = React84.useState(true);
49600
- const scrollRef = React84.useRef(null);
49601
- const prevCountRef = React84.useRef(0);
49602
- React84.useEffect(() => {
49546
+ const [expanded, setExpanded] = React85.useState(true);
49547
+ const scrollRef = React85.useRef(null);
49548
+ const prevCountRef = React85.useRef(0);
49549
+ React85.useEffect(() => {
49603
49550
  if (expanded && transitions.length > prevCountRef.current && scrollRef.current) {
49604
49551
  scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
49605
49552
  }
@@ -49656,10 +49603,10 @@ function RuntimeDebugger({
49656
49603
  schema
49657
49604
  }) {
49658
49605
  const { t } = useTranslate();
49659
- const [isCollapsed, setIsCollapsed] = React84.useState(mode === "verify" ? true : defaultCollapsed);
49660
- const [isVisible, setIsVisible] = React84.useState(mode === "inline" || mode === "verify" || isDebugEnabled2());
49606
+ const [isCollapsed, setIsCollapsed] = React85.useState(mode === "verify" ? true : defaultCollapsed);
49607
+ const [isVisible, setIsVisible] = React85.useState(mode === "inline" || mode === "verify" || isDebugEnabled2());
49661
49608
  const debugData = useDebugData();
49662
- React84.useEffect(() => {
49609
+ React85.useEffect(() => {
49663
49610
  if (mode === "inline") return;
49664
49611
  return onDebugToggle((enabled) => {
49665
49612
  setIsVisible(enabled);
@@ -49668,7 +49615,7 @@ function RuntimeDebugger({
49668
49615
  }
49669
49616
  });
49670
49617
  }, [mode]);
49671
- React84.useEffect(() => {
49618
+ React85.useEffect(() => {
49672
49619
  if (mode === "inline") return;
49673
49620
  const handleKeyDown = (e) => {
49674
49621
  if (e.key === "`" && isVisible) {
@@ -50228,7 +50175,7 @@ function SequenceBar({
50228
50175
  onSlotRemove(index);
50229
50176
  }, [onSlotRemove, playing]);
50230
50177
  const paddedSlots = Array.from({ length: maxSlots }, (_, i) => slots[i]);
50231
- return /* @__PURE__ */ jsx(HStack, { className: cn("items-center", className), gap: "sm", children: paddedSlots.map((slot, i) => /* @__PURE__ */ jsxs(React84__default.Fragment, { children: [
50178
+ return /* @__PURE__ */ jsx(HStack, { className: cn("items-center", className), gap: "sm", children: paddedSlots.map((slot, i) => /* @__PURE__ */ jsxs(React85__default.Fragment, { children: [
50232
50179
  i > 0 && /* @__PURE__ */ jsx(
50233
50180
  Typography,
50234
50181
  {
@@ -51293,6 +51240,8 @@ function Sprite({
51293
51240
  opacity = 1,
51294
51241
  zIndex = 0,
51295
51242
  columns = 16,
51243
+ animState: _animState,
51244
+ frameRate: _frameRate,
51296
51245
  className,
51297
51246
  onClick,
51298
51247
  action
@@ -51424,7 +51373,7 @@ var init_StatCard = __esm({
51424
51373
  const labelToUse = propLabel ?? propTitle;
51425
51374
  const eventBus = useEventBus();
51426
51375
  const { t } = useTranslate();
51427
- const handleActionClick = React84__default.useCallback(() => {
51376
+ const handleActionClick = React85__default.useCallback(() => {
51428
51377
  if (action?.event) {
51429
51378
  eventBus.emit(`UI:${action.event}`, {});
51430
51379
  }
@@ -51435,7 +51384,7 @@ var init_StatCard = __esm({
51435
51384
  const data = Array.isArray(entity) ? entity : entity ? [entity] : [];
51436
51385
  const isLoading = externalLoading ?? false;
51437
51386
  const error = externalError;
51438
- const computeMetricValue = React84__default.useCallback(
51387
+ const computeMetricValue = React85__default.useCallback(
51439
51388
  (metric, items) => {
51440
51389
  if (metric.value !== void 0) {
51441
51390
  return metric.value;
@@ -51474,7 +51423,7 @@ var init_StatCard = __esm({
51474
51423
  },
51475
51424
  []
51476
51425
  );
51477
- const schemaStats = React84__default.useMemo(() => {
51426
+ const schemaStats = React85__default.useMemo(() => {
51478
51427
  if (!metrics || metrics.length === 0) return null;
51479
51428
  return metrics.map((metric) => ({
51480
51429
  label: metric.label,
@@ -51482,7 +51431,7 @@ var init_StatCard = __esm({
51482
51431
  format: metric.format
51483
51432
  }));
51484
51433
  }, [metrics, data, computeMetricValue]);
51485
- const calculatedTrend = React84__default.useMemo(() => {
51434
+ const calculatedTrend = React85__default.useMemo(() => {
51486
51435
  if (manualTrend !== void 0) return manualTrend;
51487
51436
  if (previousValue === void 0 || currentValue2 === void 0)
51488
51437
  return void 0;
@@ -52193,90 +52142,6 @@ var init_StatsOrganism = __esm({
52193
52142
  StatsOrganism.displayName = "StatsOrganism";
52194
52143
  }
52195
52144
  });
52196
- function formatDuration(seconds) {
52197
- if (seconds >= 60) {
52198
- return `${Math.floor(seconds / 60)}m`;
52199
- }
52200
- return `${Math.round(seconds)}s`;
52201
- }
52202
- function StatusEffect({
52203
- assetUrl = DEFAULT_ASSET_URL11,
52204
- icon = "shield",
52205
- label = "Shield",
52206
- duration = 30,
52207
- stacks,
52208
- variant = "buff",
52209
- size = "md",
52210
- className
52211
- }) {
52212
- const sizes = sizeMap16[size];
52213
- return /* @__PURE__ */ jsxs("div", { className: cn("relative inline-flex flex-col items-center", className), children: [
52214
- /* @__PURE__ */ jsxs(
52215
- "div",
52216
- {
52217
- className: cn(
52218
- "relative flex items-center justify-center rounded-interactive border-2",
52219
- sizes.container,
52220
- variantStyles9[variant]
52221
- ),
52222
- title: label,
52223
- children: [
52224
- /* @__PURE__ */ jsx("span", { className: cn("flex items-center justify-center", sizes.icon), children: assetUrl ? /* @__PURE__ */ jsx(
52225
- "img",
52226
- {
52227
- src: assetUrl,
52228
- alt: label,
52229
- width: sizes.img,
52230
- height: sizes.img,
52231
- style: { imageRendering: "pixelated", objectFit: "contain" },
52232
- className: "flex-shrink-0"
52233
- }
52234
- ) : typeof icon === "string" ? /* @__PURE__ */ jsx(Icon, { name: icon, size: "sm" }) : /* @__PURE__ */ jsx(Icon, { icon, size: "sm" }) }),
52235
- duration !== void 0 && /* @__PURE__ */ jsx(
52236
- "span",
52237
- {
52238
- className: cn(
52239
- "absolute bottom-0 left-0 right-0 text-center font-mono font-bold text-foreground bg-background/60 leading-tight",
52240
- sizes.timer
52241
- ),
52242
- children: formatDuration(duration)
52243
- }
52244
- )
52245
- ]
52246
- }
52247
- ),
52248
- stacks !== void 0 && stacks > 1 && /* @__PURE__ */ jsx(
52249
- "span",
52250
- {
52251
- className: cn(
52252
- "absolute flex items-center justify-center rounded-full bg-card text-foreground font-bold leading-none",
52253
- sizes.badge
52254
- ),
52255
- children: stacks
52256
- }
52257
- ),
52258
- label && /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground mt-0.5 text-center whitespace-nowrap", children: label })
52259
- ] });
52260
- }
52261
- var DEFAULT_ASSET_URL11, sizeMap16, variantStyles9;
52262
- var init_StatusEffect = __esm({
52263
- "components/game/atoms/StatusEffect.tsx"() {
52264
- init_cn();
52265
- init_Icon();
52266
- DEFAULT_ASSET_URL11 = "https://almadar-kflow-assets.web.app/shared/effects/particles/flame_01.png";
52267
- sizeMap16 = {
52268
- 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 },
52269
- 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 },
52270
- lg: { container: "w-12 h-12", icon: "text-lg", badge: "text-sm -top-1.5 -right-1.5 w-6 h-6", timer: "text-xs", img: 36 }
52271
- };
52272
- variantStyles9 = {
52273
- buff: "border-success bg-success/20",
52274
- debuff: "border-error bg-error/20",
52275
- neutral: "border-muted bg-muted/20"
52276
- };
52277
- StatusEffect.displayName = "StatusEffect";
52278
- }
52279
- });
52280
52145
  var StepFlowOrganism;
52281
52146
  var init_StepFlowOrganism = __esm({
52282
52147
  "components/marketing/organisms/StepFlowOrganism.tsx"() {
@@ -52772,8 +52637,8 @@ var init_SubagentTracePanel = __esm({
52772
52637
  ] });
52773
52638
  };
52774
52639
  InlineActivityStream = ({ activities, autoScroll = true, className }) => {
52775
- const endRef = React84__default.useRef(null);
52776
- React84__default.useEffect(() => {
52640
+ const endRef = React85__default.useRef(null);
52641
+ React85__default.useEffect(() => {
52777
52642
  if (!autoScroll) return;
52778
52643
  endRef.current?.scrollIntoView({ behavior: "smooth", block: "end" });
52779
52644
  }, [activities.length, autoScroll]);
@@ -52867,7 +52732,7 @@ var init_SubagentTracePanel = __esm({
52867
52732
  };
52868
52733
  SubagentRichCard = ({ subagent }) => {
52869
52734
  const { t } = useTranslate();
52870
- const activities = React84__default.useMemo(
52735
+ const activities = React85__default.useMemo(
52871
52736
  () => subagentMessagesToActivities(subagent.messages),
52872
52737
  [subagent.messages]
52873
52738
  );
@@ -52944,8 +52809,8 @@ var init_SubagentTracePanel = __esm({
52944
52809
  ] });
52945
52810
  };
52946
52811
  CoordinatorConversation = ({ messages, autoScroll = true, className }) => {
52947
- const endRef = React84__default.useRef(null);
52948
- React84__default.useEffect(() => {
52812
+ const endRef = React85__default.useRef(null);
52813
+ React85__default.useEffect(() => {
52949
52814
  if (!autoScroll) return;
52950
52815
  endRef.current?.scrollIntoView({ behavior: "smooth", block: "end" });
52951
52816
  }, [messages.length, autoScroll]);
@@ -53417,7 +53282,7 @@ var init_Timeline = __esm({
53417
53282
  }) => {
53418
53283
  const { t } = useTranslate();
53419
53284
  const entityData = entity ?? [];
53420
- const items = React84__default.useMemo(() => {
53285
+ const items = React85__default.useMemo(() => {
53421
53286
  if (propItems) return propItems;
53422
53287
  if (entityData.length === 0) return [];
53423
53288
  return entityData.map((record, idx) => {
@@ -53569,7 +53434,7 @@ var init_TimerDisplay = __esm({
53569
53434
  }
53570
53435
  });
53571
53436
  function extractToastProps(children) {
53572
- if (!React84__default.isValidElement(children)) {
53437
+ if (!React85__default.isValidElement(children)) {
53573
53438
  if (typeof children === "string") {
53574
53439
  return { message: children };
53575
53440
  }
@@ -53607,7 +53472,7 @@ var init_ToastSlot = __esm({
53607
53472
  eventBus.emit("UI:CLOSE");
53608
53473
  };
53609
53474
  if (!isVisible) return null;
53610
- const isCustomContent = React84__default.isValidElement(children) && !message;
53475
+ const isCustomContent = React85__default.isValidElement(children) && !message;
53611
53476
  return /* @__PURE__ */ jsx(Box, { className: "fixed bottom-4 right-4 z-50", children: isCustomContent ? children : /* @__PURE__ */ jsx(
53612
53477
  Toast,
53613
53478
  {
@@ -55234,21 +55099,6 @@ function XPBar({
55234
55099
  }) {
55235
55100
  const sizes = sizeMap18[size];
55236
55101
  const percentage = max > 0 ? Math.max(0, Math.min(100, current / max * 100)) : 0;
55237
- const [fillWidth, setFillWidth] = React84.useState(animated ? 0 : percentage);
55238
- React84.useEffect(() => {
55239
- if (!animated) {
55240
- setFillWidth(percentage);
55241
- return;
55242
- }
55243
- let frame2;
55244
- const frame1 = requestAnimationFrame(() => {
55245
- frame2 = requestAnimationFrame(() => setFillWidth(percentage));
55246
- });
55247
- return () => {
55248
- cancelAnimationFrame(frame1);
55249
- cancelAnimationFrame(frame2);
55250
- };
55251
- }, [animated, percentage]);
55252
55102
  return /* @__PURE__ */ jsxs("div", { className: cn("flex items-center gap-2", className), children: [
55253
55103
  level != null && /* @__PURE__ */ jsxs(
55254
55104
  "span",
@@ -55280,7 +55130,7 @@ function XPBar({
55280
55130
  "bg-gradient-to-r from-accent to-info",
55281
55131
  animated && "transition-all duration-500 ease-out"
55282
55132
  ),
55283
- style: { width: `${fillWidth}%` }
55133
+ style: { width: `${percentage}%` }
55284
55134
  }
55285
55135
  )
55286
55136
  }
@@ -55297,7 +55147,6 @@ function XPBar({
55297
55147
  var sizeMap18;
55298
55148
  var init_XPBar = __esm({
55299
55149
  "components/game/atoms/XPBar.tsx"() {
55300
- "use client";
55301
55150
  init_cn();
55302
55151
  sizeMap18 = {
55303
55152
  sm: { bar: "h-2", text: "text-xs", badge: "text-xs px-1.5 py-0.5" },
@@ -55308,7 +55157,7 @@ var init_XPBar = __esm({
55308
55157
  }
55309
55158
  });
55310
55159
  function lazyThree(name, loader) {
55311
- const Lazy = React84__default.lazy(
55160
+ const Lazy = React85__default.lazy(
55312
55161
  () => loader().then((m) => {
55313
55162
  const Resolved = m[name];
55314
55163
  if (!Resolved) {
@@ -55320,13 +55169,13 @@ function lazyThree(name, loader) {
55320
55169
  })
55321
55170
  );
55322
55171
  function ThreeWrapper(props) {
55323
- return React84__default.createElement(
55172
+ return React85__default.createElement(
55324
55173
  ThreeBoundary,
55325
55174
  { name },
55326
- React84__default.createElement(
55327
- React84__default.Suspense,
55175
+ React85__default.createElement(
55176
+ React85__default.Suspense,
55328
55177
  { fallback: null },
55329
- React84__default.createElement(Lazy, props)
55178
+ React85__default.createElement(Lazy, props)
55330
55179
  )
55331
55180
  );
55332
55181
  }
@@ -55649,7 +55498,7 @@ var init_component_registry_generated = __esm({
55649
55498
  init_WorldMapBoard();
55650
55499
  init_WorldMapTemplate();
55651
55500
  init_XPBar();
55652
- ThreeBoundary = class extends React84__default.Component {
55501
+ ThreeBoundary = class extends React85__default.Component {
55653
55502
  constructor() {
55654
55503
  super(...arguments);
55655
55504
  __publicField(this, "state", { failed: false });
@@ -55659,7 +55508,7 @@ var init_component_registry_generated = __esm({
55659
55508
  }
55660
55509
  render() {
55661
55510
  if (this.state.failed) {
55662
- return React84__default.createElement(
55511
+ return React85__default.createElement(
55663
55512
  "div",
55664
55513
  {
55665
55514
  "data-testid": "three-unavailable",
@@ -56025,7 +55874,7 @@ function SuspenseConfigProvider({
56025
55874
  config,
56026
55875
  children
56027
55876
  }) {
56028
- return React84__default.createElement(
55877
+ return React85__default.createElement(
56029
55878
  SuspenseConfigContext.Provider,
56030
55879
  { value: config },
56031
55880
  children
@@ -56067,7 +55916,7 @@ function enrichFormFields(fields, entityDef) {
56067
55916
  }
56068
55917
  return { name: field, label: field.replace(/([a-z])([A-Z])/g, "$1 $2").replace(/\b\w/g, (c) => c.toUpperCase()) };
56069
55918
  }
56070
- if (field && typeof field === "object" && !Array.isArray(field) && !React84__default.isValidElement(field) && !(field instanceof Date)) {
55919
+ if (field && typeof field === "object" && !Array.isArray(field) && !React85__default.isValidElement(field) && !(field instanceof Date)) {
56071
55920
  const obj = field;
56072
55921
  const fieldName = typeof obj.name === "string" ? obj.name : typeof obj.field === "string" ? obj.field : void 0;
56073
55922
  if (!fieldName) return field;
@@ -56513,7 +56362,7 @@ function renderPatternChildren(children, onDismiss, parentId = "root", parentPat
56513
56362
  const key = `${parentId}-${index}-trait:${traitName}`;
56514
56363
  return /* @__PURE__ */ jsx(TraitFrame, { traitName }, key);
56515
56364
  }
56516
- return /* @__PURE__ */ jsx(React84__default.Fragment, { children: child }, `${parentId}-${index}`);
56365
+ return /* @__PURE__ */ jsx(React85__default.Fragment, { children: child }, `${parentId}-${index}`);
56517
56366
  }
56518
56367
  if (!child || typeof child !== "object") return null;
56519
56368
  const childId = `${parentId}-${index}`;
@@ -56553,14 +56402,14 @@ function isPatternConfig(value) {
56553
56402
  if (value === null || value === void 0) return false;
56554
56403
  if (typeof value !== "object") return false;
56555
56404
  if (Array.isArray(value)) return false;
56556
- if (React84__default.isValidElement(value)) return false;
56405
+ if (React85__default.isValidElement(value)) return false;
56557
56406
  if (value instanceof Date) return false;
56558
56407
  if (typeof value === "function") return false;
56559
56408
  const record = value;
56560
56409
  return "type" in record && typeof record.type === "string" && getComponentForPattern(record.type) !== null;
56561
56410
  }
56562
56411
  function isPlainConfigObject(value) {
56563
- if (React84__default.isValidElement(value)) return false;
56412
+ if (React85__default.isValidElement(value)) return false;
56564
56413
  if (value instanceof Date) return false;
56565
56414
  const proto = Object.getPrototypeOf(value);
56566
56415
  return proto === Object.prototype || proto === null;
@@ -56686,7 +56535,7 @@ function SlotContentRenderer({
56686
56535
  for (const slotKey of CONTENT_NODE_SLOTS) {
56687
56536
  const slotVal = restProps[slotKey];
56688
56537
  if (slotVal === void 0 || slotVal === null) continue;
56689
- if (React84__default.isValidElement(slotVal) || typeof slotVal === "string" || typeof slotVal === "number" || typeof slotVal === "boolean") continue;
56538
+ if (React85__default.isValidElement(slotVal) || typeof slotVal === "string" || typeof slotVal === "number" || typeof slotVal === "boolean") continue;
56690
56539
  if (Array.isArray(slotVal) || typeof slotVal === "object" && "type" in slotVal) {
56691
56540
  nodeSlotOverrides[slotKey] = renderPatternChildren(
56692
56541
  slotVal,
@@ -56735,7 +56584,7 @@ function SlotContentRenderer({
56735
56584
  const resolvedItems = Array.isArray(entityVal) && entityVal[0] !== "fn" ? entityVal : null;
56736
56585
  if (resolvedItems && resolvedItems.length > 0 && !finalProps.fields && !finalProps.columns) {
56737
56586
  const sample = resolvedItems[0];
56738
- if (sample && typeof sample === "object" && !Array.isArray(sample) && !React84__default.isValidElement(sample) && !(sample instanceof Date)) {
56587
+ if (sample && typeof sample === "object" && !Array.isArray(sample) && !React85__default.isValidElement(sample) && !(sample instanceof Date)) {
56739
56588
  const keys = Object.keys(sample).filter((k) => k !== "id" && k !== "_id");
56740
56589
  finalProps.fields = keys.map((k, i) => ({ name: k, variant: i === 0 ? "h4" : "body" }));
56741
56590
  }
@@ -57106,7 +56955,7 @@ function useSpriteAnimations(getSheetUrls, getFrameDims, options = {}) {
57106
56955
  const prevPositionsRef = useRef(/* @__PURE__ */ new Map());
57107
56956
  const unitDataRef = useRef(/* @__PURE__ */ new Map());
57108
56957
  const walkHoldRef = useRef(/* @__PURE__ */ new Map());
57109
- const WALK_HOLD_MS2 = 600;
56958
+ const WALK_HOLD_MS = 600;
57110
56959
  const syncUnits = useCallback((units, deltaMs) => {
57111
56960
  const scaledDelta = deltaMs * speed;
57112
56961
  const states = animStatesRef.current;
@@ -57132,7 +56981,7 @@ function useSpriteAnimations(getSheetUrls, getFrameDims, options = {}) {
57132
56981
  const dir = inferDirection(dx, dy);
57133
56982
  if (state.animation !== "attack" && state.animation !== "hit" && state.animation !== "death") {
57134
56983
  state = transitionAnimation(state, "walk", dir);
57135
- walkHold.set(unit.id, WALK_HOLD_MS2);
56984
+ walkHold.set(unit.id, WALK_HOLD_MS);
57136
56985
  }
57137
56986
  } else if (state.animation === "walk") {
57138
56987
  const remaining = (walkHold.get(unit.id) ?? 0) - scaledDelta;