@almadar/ui 5.80.0 → 5.82.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.
@@ -2033,6 +2033,7 @@ var init_Button = __esm({
2033
2033
  rightIcon,
2034
2034
  icon: iconProp,
2035
2035
  iconRight: iconRightProp,
2036
+ iconAsset,
2036
2037
  action,
2037
2038
  actionPayload,
2038
2039
  label,
@@ -2044,7 +2045,8 @@ var init_Button = __esm({
2044
2045
  const eventBus = useEventBus();
2045
2046
  const leftIconValue = leftIcon || iconProp;
2046
2047
  const rightIconValue = rightIcon || iconRightProp;
2047
- const resolvedLeftIcon = resolveIconProp(leftIconValue, iconSizeStyles[size]);
2048
+ const px = size === "sm" ? 16 : size === "lg" ? 20 : 16;
2049
+ const resolvedLeftIcon = iconAsset?.url ? /* @__PURE__ */ jsxRuntime.jsx("img", { src: iconAsset.url, alt: iconAsset.name ?? iconAsset.category ?? "", width: px, height: px, style: { imageRendering: "pixelated", objectFit: "contain", width: px, height: px }, className: "flex-shrink-0" }) : resolveIconProp(leftIconValue, iconSizeStyles[size]);
2048
2050
  const resolvedRightIcon = resolveIconProp(rightIconValue, iconSizeStyles[size]);
2049
2051
  const handleClick = (e) => {
2050
2052
  if (action) {
@@ -2702,13 +2704,14 @@ var init_Badge = __esm({
2702
2704
  lg: "px-3 py-1.5 text-base"
2703
2705
  };
2704
2706
  Badge = React103__namespace.default.forwardRef(
2705
- ({ className, variant = "default", size = "sm", amount, label, icon, children, onRemove, removeLabel, ...props }, ref) => {
2707
+ ({ className, variant = "default", size = "sm", amount, label, icon, iconAsset, children, onRemove, removeLabel, ...props }, ref) => {
2706
2708
  const iconSizes3 = {
2707
2709
  sm: "h-icon-default w-icon-default",
2708
2710
  md: "h-icon-default w-icon-default",
2709
2711
  lg: "h-icon-default w-icon-default"
2710
2712
  };
2711
- const resolvedIcon = typeof icon === "string" ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: icon, className: iconSizes3[size] }) : icon ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { icon, className: iconSizes3[size] }) : null;
2713
+ const iconPx = size === "lg" ? 20 : 16;
2714
+ const resolvedIcon = iconAsset?.url ? /* @__PURE__ */ jsxRuntime.jsx("img", { src: iconAsset.url, alt: iconAsset.name ?? iconAsset.category ?? "", width: iconPx, height: iconPx, style: { imageRendering: "pixelated", objectFit: "contain", width: iconPx, height: iconPx }, className: "flex-shrink-0" }) : typeof icon === "string" ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: icon, className: iconSizes3[size] }) : icon ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { icon, className: iconSizes3[size] }) : null;
2712
2715
  return /* @__PURE__ */ jsxRuntime.jsxs(
2713
2716
  "span",
2714
2717
  {
@@ -8928,10 +8931,43 @@ var init_shared = __esm({
8928
8931
  init_canvasEffects();
8929
8932
  }
8930
8933
  });
8934
+ function GameIcon({ assetUrl, icon, size = "md", alt, className }) {
8935
+ const px = typeof size === "number" ? size : sizeMap[size];
8936
+ if (assetUrl?.url) {
8937
+ return /* @__PURE__ */ jsxRuntime.jsx(
8938
+ "img",
8939
+ {
8940
+ src: assetUrl.url,
8941
+ alt: alt ?? assetUrl.category ?? "",
8942
+ width: px,
8943
+ height: px,
8944
+ style: { imageRendering: "pixelated", objectFit: "contain", width: px, height: px },
8945
+ className: cn("flex-shrink-0", className)
8946
+ }
8947
+ );
8948
+ }
8949
+ const I = typeof icon === "string" ? resolveIcon(icon) : icon;
8950
+ return /* @__PURE__ */ jsxRuntime.jsx(I, { width: px, height: px, className: cn("flex-shrink-0", className) });
8951
+ }
8952
+ var sizeMap;
8953
+ var init_GameIcon = __esm({
8954
+ "components/game/2d/atoms/GameIcon.tsx"() {
8955
+ "use client";
8956
+ init_cn();
8957
+ init_Icon();
8958
+ sizeMap = {
8959
+ sm: 16,
8960
+ md: 24,
8961
+ lg: 32
8962
+ };
8963
+ GameIcon.displayName = "GameIcon";
8964
+ }
8965
+ });
8931
8966
  function GameCard({
8932
8967
  id,
8933
8968
  cost,
8934
8969
  art,
8970
+ frameAsset,
8935
8971
  attack,
8936
8972
  defense,
8937
8973
  name,
@@ -8949,16 +8985,19 @@ function GameCard({
8949
8985
  if (clickEvent) eventBus.emit(`UI:${clickEvent}`, { cardId: id });
8950
8986
  }, [disabled, id, onClick, clickEvent, eventBus]);
8951
8987
  const artPx = artPxMap[size];
8988
+ const frameStyle = frameAsset?.url ? { backgroundImage: `url(${frameAsset.url})`, backgroundSize: "100% 100%", backgroundRepeat: "no-repeat" } : {};
8952
8989
  return /* @__PURE__ */ jsxRuntime.jsxs(
8953
- "button",
8990
+ Button,
8954
8991
  {
8955
- type: "button",
8992
+ variant: "ghost",
8956
8993
  onClick: handleClick,
8957
8994
  disabled,
8958
8995
  title: name,
8996
+ style: frameStyle,
8959
8997
  className: cn(
8960
- "relative flex flex-col items-center rounded-interactive border-2",
8998
+ "relative flex flex-col items-center rounded-interactive",
8961
8999
  "bg-card/90 px-1.5 pt-1.5 pb-1 transition-all duration-150",
9000
+ frameAsset?.url ? "border-0" : "border-2",
8962
9001
  cardSizeMap[size],
8963
9002
  disabled ? "border-border opacity-50 cursor-not-allowed" : "border-accent hover:brightness-125 hover:-translate-y-1 cursor-pointer",
8964
9003
  selected && "ring-2 ring-foreground ring-offset-1 ring-offset-background -translate-y-1",
@@ -8966,8 +9005,9 @@ function GameCard({
8966
9005
  ),
8967
9006
  children: [
8968
9007
  cost != null && /* @__PURE__ */ jsxRuntime.jsx(
8969
- "span",
9008
+ Typography,
8970
9009
  {
9010
+ as: "span",
8971
9011
  className: cn(
8972
9012
  "absolute -top-2 -left-2 flex items-center justify-center",
8973
9013
  "min-w-[22px] h-[22px] rounded-full px-1",
@@ -8976,17 +9016,7 @@ function GameCard({
8976
9016
  children: cost
8977
9017
  }
8978
9018
  ),
8979
- /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "flex-1 flex items-center justify-center w-full", children: art ? /* @__PURE__ */ jsxRuntime.jsx(
8980
- "img",
8981
- {
8982
- src: art.url,
8983
- alt: name ?? id,
8984
- width: artPx,
8985
- height: artPx,
8986
- style: { imageRendering: "pixelated", objectFit: "contain" },
8987
- className: "flex-shrink-0"
8988
- }
8989
- ) : /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "rounded bg-muted/40", style: { width: artPx, height: artPx } }) }),
9019
+ /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "flex-1 flex items-center justify-center w-full", children: art ? /* @__PURE__ */ jsxRuntime.jsx(GameIcon, { assetUrl: art, icon: "image", size: artPx, alt: name ?? id, className: "flex-shrink-0" }) : /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "rounded bg-muted/40", style: { width: artPx, height: artPx } }) }),
8990
9020
  name != null && /* @__PURE__ */ jsxRuntime.jsx(
8991
9021
  Typography,
8992
9022
  {
@@ -8996,8 +9026,8 @@ function GameCard({
8996
9026
  }
8997
9027
  ),
8998
9028
  (attack != null || defense != null) && /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "flex w-full items-center justify-between px-0.5 text-[10px] font-bold leading-none", children: [
8999
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-error", children: attack != null ? `\u2694${attack}` : "" }),
9000
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-info", children: defense != null ? `\u{1F6E1}${defense}` : "" })
9029
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "text-error", children: attack != null ? `\u2694${attack}` : "" }),
9030
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "text-info", children: defense != null ? `\u{1F6E1}${defense}` : "" })
9001
9031
  ] })
9002
9032
  ]
9003
9033
  }
@@ -9010,7 +9040,9 @@ var init_GameCard = __esm({
9010
9040
  init_cn();
9011
9041
  init_useEventBus();
9012
9042
  init_Box();
9043
+ init_Button();
9013
9044
  init_Typography();
9045
+ init_GameIcon();
9014
9046
  cardSizeMap = {
9015
9047
  sm: "w-16 h-24",
9016
9048
  md: "w-20 h-28",
@@ -9033,12 +9065,13 @@ function HealthBar({
9033
9065
  frameAsset,
9034
9066
  fillAsset
9035
9067
  }) {
9036
- const sizes = sizeMap[size];
9068
+ const sizes = sizeMap2[size];
9037
9069
  const percentage = max > 0 ? Math.max(0, Math.min(100, current / max * 100)) : 0;
9038
9070
  if (format === "hearts") {
9039
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("flex items-center gap-1", className), children: Array.from({ length: max }).map((_, i) => /* @__PURE__ */ jsxRuntime.jsx(
9040
- "span",
9071
+ return /* @__PURE__ */ jsxRuntime.jsx(Box, { className: cn("flex items-center gap-1", className), children: Array.from({ length: max }).map((_, i) => /* @__PURE__ */ jsxRuntime.jsx(
9072
+ Box,
9041
9073
  {
9074
+ as: "span",
9042
9075
  className: cn(animated && "transition-transform hover:scale-110"),
9043
9076
  children: heartIcon(i < current, sizes.heart)
9044
9077
  },
@@ -9047,10 +9080,12 @@ function HealthBar({
9047
9080
  }
9048
9081
  if (format === "bar") {
9049
9082
  return /* @__PURE__ */ jsxRuntime.jsx(
9050
- "div",
9083
+ Box,
9051
9084
  {
9085
+ position: "relative",
9086
+ overflow: "hidden",
9052
9087
  className: cn(
9053
- "relative overflow-hidden rounded-full",
9088
+ "rounded-full",
9054
9089
  !frameAsset && "bg-muted",
9055
9090
  sizes.bar,
9056
9091
  "w-24",
@@ -9058,10 +9093,11 @@ function HealthBar({
9058
9093
  ),
9059
9094
  style: frameAsset ? { backgroundImage: `url(${frameAsset.url})`, backgroundSize: "100% 100%" } : void 0,
9060
9095
  children: /* @__PURE__ */ jsxRuntime.jsx(
9061
- "div",
9096
+ Box,
9062
9097
  {
9098
+ position: "absolute",
9063
9099
  className: cn(
9064
- "absolute inset-y-0 left-0 rounded-full",
9100
+ "inset-y-0 left-0 rounded-full",
9065
9101
  !fillAsset && (percentage > 66 ? "bg-success" : percentage > 33 ? "bg-warning" : "bg-error"),
9066
9102
  animated && "transition-all duration-300"
9067
9103
  ),
@@ -9075,10 +9111,11 @@ function HealthBar({
9075
9111
  );
9076
9112
  }
9077
9113
  if (format === "progress") {
9078
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex items-center gap-2", className), children: [
9114
+ return /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: cn("flex items-center gap-2", className), children: [
9079
9115
  level != null && /* @__PURE__ */ jsxRuntime.jsxs(
9080
- "span",
9116
+ Typography,
9081
9117
  {
9118
+ as: "span",
9082
9119
  className: cn(
9083
9120
  "flex-shrink-0 rounded-interactive font-bold",
9084
9121
  "bg-accent text-accent-foreground border border-accent",
@@ -9090,21 +9127,23 @@ function HealthBar({
9090
9127
  ]
9091
9128
  }
9092
9129
  ),
9093
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 flex flex-col gap-0.5", children: [
9130
+ /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "flex-1 flex flex-col gap-0.5", children: [
9094
9131
  /* @__PURE__ */ jsxRuntime.jsx(
9095
- "div",
9132
+ Box,
9096
9133
  {
9134
+ position: "relative",
9097
9135
  className: cn(
9098
- "relative w-full overflow-hidden rounded-full",
9136
+ "w-full overflow-hidden rounded-full",
9099
9137
  !frameAsset && "bg-muted border border-muted",
9100
9138
  sizes.bar
9101
9139
  ),
9102
9140
  style: frameAsset ? { backgroundImage: `url(${frameAsset.url})`, backgroundSize: "100% 100%" } : void 0,
9103
9141
  children: /* @__PURE__ */ jsxRuntime.jsx(
9104
- "div",
9142
+ Box,
9105
9143
  {
9144
+ position: "absolute",
9106
9145
  className: cn(
9107
- "absolute inset-y-0 left-0 rounded-full",
9146
+ "inset-y-0 left-0 rounded-full",
9108
9147
  !fillAsset && "bg-gradient-to-r from-accent to-info",
9109
9148
  animated && "transition-all duration-500 ease-out"
9110
9149
  ),
@@ -9116,7 +9155,7 @@ function HealthBar({
9116
9155
  )
9117
9156
  }
9118
9157
  ),
9119
- showLabel && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: cn("text-foreground/70 tabular-nums", sizes.label), children: [
9158
+ showLabel && /* @__PURE__ */ jsxRuntime.jsxs(Typography, { as: "span", className: cn("text-foreground/70 tabular-nums", sizes.label), children: [
9120
9159
  current,
9121
9160
  " / ",
9122
9161
  max,
@@ -9125,16 +9164,18 @@ function HealthBar({
9125
9164
  ] })
9126
9165
  ] });
9127
9166
  }
9128
- return /* @__PURE__ */ jsxRuntime.jsxs("span", { className: cn("font-mono font-bold", sizes.text, className), children: [
9167
+ return /* @__PURE__ */ jsxRuntime.jsxs(Typography, { as: "span", className: cn("font-mono font-bold", sizes.text, className), children: [
9129
9168
  current,
9130
9169
  "/",
9131
9170
  max
9132
9171
  ] });
9133
9172
  }
9134
- var heartIcon, sizeMap;
9173
+ var heartIcon, sizeMap2;
9135
9174
  var init_HealthBar = __esm({
9136
9175
  "components/game/2d/atoms/HealthBar.tsx"() {
9137
9176
  init_cn();
9177
+ init_Box();
9178
+ init_Typography();
9138
9179
  heartIcon = (filled, size) => /* @__PURE__ */ jsxRuntime.jsx(
9139
9180
  "svg",
9140
9181
  {
@@ -9146,7 +9187,7 @@ var init_HealthBar = __esm({
9146
9187
  children: /* @__PURE__ */ jsxRuntime.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" })
9147
9188
  }
9148
9189
  );
9149
- sizeMap = {
9190
+ sizeMap2 = {
9150
9191
  sm: { heart: "w-4 h-4", bar: "h-2", text: "text-sm", label: "text-xs", badge: "text-xs px-1.5 py-0.5" },
9151
9192
  md: { heart: "w-6 h-6", bar: "h-3", text: "text-base", label: "text-xs", badge: "text-xs px-2 py-0.5" },
9152
9193
  lg: { heart: "w-8 h-8", bar: "h-4", text: "text-lg", label: "text-sm", badge: "text-sm px-2.5 py-1" }
@@ -9167,37 +9208,30 @@ function ScoreDisplay({
9167
9208
  const resolvedValue = typeof value === "number" && !Number.isNaN(value) ? value : typeof score === "number" && !Number.isNaN(score) ? score : 0;
9168
9209
  const formattedValue = new Intl.NumberFormat(locale).format(resolvedValue);
9169
9210
  return /* @__PURE__ */ jsxRuntime.jsxs(
9170
- "div",
9211
+ Box,
9171
9212
  {
9172
9213
  className: cn(
9173
9214
  "flex items-center gap-2 font-bold",
9174
- sizeMap2[size],
9215
+ sizeMap3[size],
9175
9216
  className
9176
9217
  ),
9177
9218
  children: [
9178
- assetUrl ? /* @__PURE__ */ jsxRuntime.jsx(
9179
- "img",
9180
- {
9181
- src: assetUrl.url,
9182
- alt: "",
9183
- width: 20,
9184
- height: 20,
9185
- style: { imageRendering: "pixelated", objectFit: "contain" },
9186
- className: "flex-shrink-0"
9187
- }
9188
- ) : icon ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-shrink-0", children: typeof icon === "string" ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: icon }) : /* @__PURE__ */ jsxRuntime.jsx(Icon, { icon }) }) : null,
9189
- label && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: label }),
9190
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "tabular-nums", children: formattedValue })
9219
+ assetUrl ? /* @__PURE__ */ jsxRuntime.jsx(GameIcon, { assetUrl, icon: "image", size: 20, className: "flex-shrink-0" }) : icon ? /* @__PURE__ */ jsxRuntime.jsx(Box, { as: "span", className: "flex-shrink-0", children: typeof icon === "string" ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: icon }) : /* @__PURE__ */ jsxRuntime.jsx(Icon, { icon }) }) : null,
9220
+ label && /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "text-muted-foreground", children: label }),
9221
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "tabular-nums", children: formattedValue })
9191
9222
  ]
9192
9223
  }
9193
9224
  );
9194
9225
  }
9195
- var sizeMap2, DEFAULT_ASSET_URL;
9226
+ var sizeMap3, DEFAULT_ASSET_URL;
9196
9227
  var init_ScoreDisplay = __esm({
9197
9228
  "components/game/2d/atoms/ScoreDisplay.tsx"() {
9198
9229
  init_cn();
9199
9230
  init_Icon();
9200
- sizeMap2 = {
9231
+ init_Box();
9232
+ init_Typography();
9233
+ init_GameIcon();
9234
+ sizeMap3 = {
9201
9235
  sm: "text-sm",
9202
9236
  md: "text-lg",
9203
9237
  lg: "text-2xl",
@@ -9260,9 +9294,9 @@ function ControlButton({
9260
9294
  [isPressed, releaseEvent, eventBus, onRelease]
9261
9295
  );
9262
9296
  return /* @__PURE__ */ jsxRuntime.jsx(
9263
- "button",
9297
+ Button,
9264
9298
  {
9265
- type: "button",
9299
+ variant,
9266
9300
  disabled,
9267
9301
  onPointerDown: handlePointerDown,
9268
9302
  onPointerUp: handlePointerUp,
@@ -9273,41 +9307,35 @@ function ControlButton({
9273
9307
  "select-none touch-none",
9274
9308
  "transition-all duration-100",
9275
9309
  "active:scale-95",
9276
- sizeMap3[size] ?? sizeMap3.md,
9310
+ sizeMap4[size] ?? sizeMap4.md,
9277
9311
  shapeMap[shape] ?? shapeMap.circle,
9278
9312
  variantMap[variant] ?? variantMap.secondary,
9279
9313
  actualPressed && "scale-95 brightness-110 border-foreground",
9280
9314
  disabled && "opacity-50 cursor-not-allowed",
9281
9315
  className
9282
9316
  ),
9283
- children: assetUrl ? /* @__PURE__ */ jsxRuntime.jsx(
9284
- "img",
9285
- {
9286
- src: assetUrl.url,
9287
- alt: "",
9288
- width: 24,
9289
- height: 24,
9290
- style: { imageRendering: "pixelated", objectFit: "contain" },
9291
- className: "flex-shrink-0"
9292
- }
9293
- ) : icon ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-2xl", children: typeof icon === "string" ? /^[a-zA-Z0-9-]+$/.test(icon) ? (() => {
9317
+ children: assetUrl ? /* @__PURE__ */ jsxRuntime.jsx(GameIcon, { assetUrl, icon: "image", size: 24, className: "flex-shrink-0" }) : icon ? /* @__PURE__ */ jsxRuntime.jsx(Box, { as: "span", className: "text-2xl", children: typeof icon === "string" ? /^[a-zA-Z0-9-]+$/.test(icon) ? (() => {
9294
9318
  const I = resolveIcon(icon);
9295
9319
  return I ? /* @__PURE__ */ jsxRuntime.jsx(I, { className: "w-6 h-6" }) : null;
9296
9320
  })() : icon : /* @__PURE__ */ (() => {
9297
9321
  const I = icon;
9298
9322
  return /* @__PURE__ */ jsxRuntime.jsx(I, { className: "w-6 h-6" });
9299
- })() }) : label ? /* @__PURE__ */ jsxRuntime.jsx("span", { children: label }) : null
9323
+ })() }) : label ? /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", children: label }) : null
9300
9324
  }
9301
9325
  );
9302
9326
  }
9303
- var sizeMap3, shapeMap, variantMap, DEFAULT_ASSET_URL2;
9327
+ var sizeMap4, shapeMap, variantMap, DEFAULT_ASSET_URL2;
9304
9328
  var init_ControlButton = __esm({
9305
9329
  "components/game/2d/atoms/ControlButton.tsx"() {
9306
9330
  "use client";
9307
9331
  init_cn();
9308
9332
  init_useEventBus();
9309
9333
  init_Icon();
9310
- sizeMap3 = {
9334
+ init_Button();
9335
+ init_Box();
9336
+ init_Typography();
9337
+ init_GameIcon();
9338
+ sizeMap4 = {
9311
9339
  sm: "w-10 h-10 text-sm",
9312
9340
  md: "w-14 h-14 text-base",
9313
9341
  lg: "w-18 h-18 text-lg",
@@ -9377,12 +9405,12 @@ function Sprite({
9377
9405
  onClick?.();
9378
9406
  };
9379
9407
  return /* @__PURE__ */ jsxRuntime.jsx(
9380
- "div",
9408
+ Box,
9381
9409
  {
9410
+ position: "absolute",
9382
9411
  className,
9383
9412
  onClick: action || onClick ? handleClick : void 0,
9384
9413
  style: {
9385
- position: "absolute",
9386
9414
  width: frameWidth,
9387
9415
  height: frameHeight,
9388
9416
  backgroundImage: `url(${spritesheet.url})`,
@@ -9403,6 +9431,7 @@ var init_Sprite = __esm({
9403
9431
  "components/game/2d/atoms/Sprite.tsx"() {
9404
9432
  "use client";
9405
9433
  init_useEventBus();
9434
+ init_Box();
9406
9435
  init_spriteAnimation();
9407
9436
  DEFAULT_SPRITESHEET = {
9408
9437
  url: "https://almadar-kflow-assets.web.app/shared/isometric-blocks/Spritesheet/allTiles_sheet.png",
@@ -9439,17 +9468,7 @@ function StateIndicator({
9439
9468
  className
9440
9469
  ),
9441
9470
  children: [
9442
- /* @__PURE__ */ jsxRuntime.jsx(Box, { as: "span", children: assetUrl ? /* @__PURE__ */ jsxRuntime.jsx(
9443
- "img",
9444
- {
9445
- src: assetUrl.url,
9446
- alt: displayLabel,
9447
- width: 16,
9448
- height: 16,
9449
- style: { imageRendering: "pixelated", objectFit: "contain" },
9450
- className: "flex-shrink-0"
9451
- }
9452
- ) : typeof config.icon === "string" ? /^[a-zA-Z0-9-]+$/.test(config.icon) ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: config.icon }) : config.icon : /* @__PURE__ */ jsxRuntime.jsx(Icon, { icon: config.icon }) }),
9471
+ /* @__PURE__ */ jsxRuntime.jsx(Box, { as: "span", children: assetUrl ? /* @__PURE__ */ jsxRuntime.jsx(GameIcon, { assetUrl, icon: "image", size: 16, alt: displayLabel, className: "flex-shrink-0" }) : typeof config.icon === "string" ? /^[a-zA-Z0-9-]+$/.test(config.icon) ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: config.icon }) : config.icon : /* @__PURE__ */ jsxRuntime.jsx(Icon, { icon: config.icon }) }),
9453
9472
  /* @__PURE__ */ jsxRuntime.jsx(Box, { as: "span", children: displayLabel })
9454
9473
  ]
9455
9474
  }
@@ -9461,6 +9480,7 @@ var init_StateIndicator = __esm({
9461
9480
  init_Box();
9462
9481
  init_Icon();
9463
9482
  init_cn();
9483
+ init_GameIcon();
9464
9484
  DEFAULT_ASSET_URL3 = {
9465
9485
  url: "https://almadar-kflow-assets.web.app/shared/isometric-dungeon/Isometric/chestClosed_E.png",
9466
9486
  role: "ui",
@@ -9514,29 +9534,31 @@ function TimerDisplay({
9514
9534
  }) {
9515
9535
  const isLow = lowThreshold != null && seconds <= lowThreshold && seconds > 0;
9516
9536
  return /* @__PURE__ */ jsxRuntime.jsxs(
9517
- "div",
9537
+ Box,
9518
9538
  {
9519
9539
  className: cn(
9520
9540
  "inline-flex items-center gap-1 justify-center rounded-container",
9521
9541
  "bg-card/80 border border-muted font-mono font-bold tabular-nums",
9522
- sizeMap4[size],
9542
+ sizeMap5[size],
9523
9543
  running && "border-success/50",
9524
9544
  isLow && "text-error border-error/50 animate-pulse",
9525
9545
  !isLow && "text-foreground",
9526
9546
  className
9527
9547
  ),
9528
9548
  children: [
9529
- iconAsset && /* @__PURE__ */ jsxRuntime.jsx("img", { src: iconAsset.url, alt: "", className: "w-4 h-4 object-contain flex-shrink-0" }),
9549
+ iconAsset && /* @__PURE__ */ jsxRuntime.jsx(GameIcon, { assetUrl: iconAsset, icon: "image", size: 16, className: "w-4 h-4 object-contain flex-shrink-0" }),
9530
9550
  formatTime(seconds, format)
9531
9551
  ]
9532
9552
  }
9533
9553
  );
9534
9554
  }
9535
- var sizeMap4;
9555
+ var sizeMap5;
9536
9556
  var init_TimerDisplay = __esm({
9537
9557
  "components/game/2d/atoms/TimerDisplay.tsx"() {
9538
9558
  init_cn();
9539
- sizeMap4 = {
9559
+ init_Box();
9560
+ init_GameIcon();
9561
+ sizeMap5 = {
9540
9562
  sm: "text-sm px-2 py-0.5",
9541
9563
  md: "text-lg px-3 py-1",
9542
9564
  lg: "text-2xl px-4 py-1.5"
@@ -9554,9 +9576,9 @@ function ResourceCounter({
9554
9576
  size = "md",
9555
9577
  className
9556
9578
  }) {
9557
- const sizes = sizeMap5[size];
9579
+ const sizes = sizeMap6[size];
9558
9580
  return /* @__PURE__ */ jsxRuntime.jsxs(
9559
- "div",
9581
+ Box,
9560
9582
  {
9561
9583
  className: cn(
9562
9584
  "inline-flex items-center rounded-container",
@@ -9565,21 +9587,11 @@ function ResourceCounter({
9565
9587
  className
9566
9588
  ),
9567
9589
  children: [
9568
- assetUrl ? /* @__PURE__ */ jsxRuntime.jsx(
9569
- "img",
9570
- {
9571
- src: assetUrl.url,
9572
- alt: label,
9573
- width: sizes.img,
9574
- height: sizes.img,
9575
- style: { imageRendering: "pixelated", objectFit: "contain" },
9576
- className: "flex-shrink-0"
9577
- }
9578
- ) : icon ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("flex-shrink-0", sizes.icon), children: typeof icon === "string" ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: icon }) : /* @__PURE__ */ jsxRuntime.jsx(Icon, { icon }) }) : null,
9579
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: label }),
9580
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: cn("font-bold tabular-nums", color && (color in colorTokenClasses2 ? colorTokenClasses2[color] : color)), children: [
9590
+ assetUrl ? /* @__PURE__ */ jsxRuntime.jsx(GameIcon, { assetUrl, icon: "image", size: sizes.img, alt: label, className: "flex-shrink-0" }) : icon ? /* @__PURE__ */ jsxRuntime.jsx(Box, { as: "span", className: cn("flex-shrink-0", sizes.icon), children: typeof icon === "string" ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: icon }) : /* @__PURE__ */ jsxRuntime.jsx(Icon, { icon }) }) : null,
9591
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "text-muted-foreground", children: label }),
9592
+ /* @__PURE__ */ jsxRuntime.jsxs(Typography, { as: "span", className: cn("font-bold tabular-nums", color && (color in colorTokenClasses2 ? colorTokenClasses2[color] : color)), children: [
9581
9593
  value,
9582
- max != null && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-muted-foreground", children: [
9594
+ max != null && /* @__PURE__ */ jsxRuntime.jsxs(Typography, { as: "span", className: "text-muted-foreground", children: [
9583
9595
  "/",
9584
9596
  max
9585
9597
  ] })
@@ -9588,11 +9600,14 @@ function ResourceCounter({
9588
9600
  }
9589
9601
  );
9590
9602
  }
9591
- var colorTokenClasses2, DEFAULT_ASSET_URL4, sizeMap5;
9603
+ var colorTokenClasses2, DEFAULT_ASSET_URL4, sizeMap6;
9592
9604
  var init_ResourceCounter = __esm({
9593
9605
  "components/game/2d/atoms/ResourceCounter.tsx"() {
9594
9606
  init_cn();
9595
9607
  init_Icon();
9608
+ init_Box();
9609
+ init_Typography();
9610
+ init_GameIcon();
9596
9611
  colorTokenClasses2 = {
9597
9612
  primary: "text-primary",
9598
9613
  secondary: "text-secondary",
@@ -9606,7 +9621,7 @@ var init_ResourceCounter = __esm({
9606
9621
  role: "ui",
9607
9622
  category: "coin"
9608
9623
  };
9609
- sizeMap5 = {
9624
+ sizeMap6 = {
9610
9625
  sm: { wrapper: "text-xs gap-1 px-1.5 py-0.5", icon: "text-sm", img: 16 },
9611
9626
  md: { wrapper: "text-sm gap-1.5 px-2 py-1", icon: "text-base", img: 20 },
9612
9627
  lg: { wrapper: "text-base gap-2 px-3 py-1.5", icon: "text-lg", img: 28 }
@@ -9631,9 +9646,9 @@ function ItemSlot({
9631
9646
  const isClickable = onClick != null || action != null;
9632
9647
  const px = assetSizeMap[size];
9633
9648
  return /* @__PURE__ */ jsxRuntime.jsx(
9634
- "button",
9649
+ Button,
9635
9650
  {
9636
- type: "button",
9651
+ variant: "ghost",
9637
9652
  onClick: () => {
9638
9653
  if (action) eventBus.emit(`UI:${action}`, {});
9639
9654
  onClick?.();
@@ -9643,7 +9658,7 @@ function ItemSlot({
9643
9658
  className: cn(
9644
9659
  "relative flex items-center justify-center rounded-interactive border-2",
9645
9660
  "bg-card/80 transition-all duration-150",
9646
- sizeMap6[size],
9661
+ sizeMap7[size],
9647
9662
  empty ? "border-border bg-card/50" : rarityBorderMap[rarity],
9648
9663
  !empty && rarityGlowMap[rarity],
9649
9664
  selected && "ring-2 ring-foreground ring-offset-1 ring-offset-background",
@@ -9652,21 +9667,12 @@ function ItemSlot({
9652
9667
  !isClickable && "cursor-default",
9653
9668
  className
9654
9669
  ),
9655
- children: empty ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground text-base", children: "+" }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
9656
- assetUrl ? /* @__PURE__ */ jsxRuntime.jsx(
9657
- "img",
9658
- {
9659
- src: assetUrl?.url,
9660
- alt: label,
9661
- width: px,
9662
- height: px,
9663
- style: { imageRendering: "pixelated", objectFit: "contain" },
9664
- className: "flex-shrink-0"
9665
- }
9666
- ) : icon ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-shrink-0", children: typeof icon === "string" ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: icon }) : /* @__PURE__ */ jsxRuntime.jsx(Icon, { icon }) }) : null,
9670
+ children: empty ? /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "text-muted-foreground text-base", children: "+" }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
9671
+ assetUrl ? /* @__PURE__ */ jsxRuntime.jsx(GameIcon, { assetUrl, icon: "image", size: px, alt: label, className: "flex-shrink-0" }) : icon ? /* @__PURE__ */ jsxRuntime.jsx(Box, { as: "span", className: "flex-shrink-0", children: typeof icon === "string" ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: icon }) : /* @__PURE__ */ jsxRuntime.jsx(Icon, { icon }) }) : null,
9667
9672
  quantity != null && quantity > 1 && /* @__PURE__ */ jsxRuntime.jsx(
9668
- "span",
9673
+ Typography,
9669
9674
  {
9675
+ as: "span",
9670
9676
  className: cn(
9671
9677
  "absolute -bottom-1 -right-1 flex items-center justify-center",
9672
9678
  "min-w-[18px] h-[18px] rounded-full px-1",
@@ -9679,14 +9685,18 @@ function ItemSlot({
9679
9685
  }
9680
9686
  );
9681
9687
  }
9682
- var sizeMap6, rarityBorderMap, rarityGlowMap, DEFAULT_ASSET_URL5, assetSizeMap;
9688
+ var sizeMap7, rarityBorderMap, rarityGlowMap, DEFAULT_ASSET_URL5, assetSizeMap;
9683
9689
  var init_ItemSlot = __esm({
9684
9690
  "components/game/2d/atoms/ItemSlot.tsx"() {
9685
9691
  "use client";
9686
9692
  init_cn();
9687
9693
  init_Icon();
9688
9694
  init_useEventBus();
9689
- sizeMap6 = {
9695
+ init_Button();
9696
+ init_Box();
9697
+ init_Typography();
9698
+ init_GameIcon();
9699
+ sizeMap7 = {
9690
9700
  sm: "w-10 h-10 text-lg",
9691
9701
  md: "w-14 h-14 text-2xl",
9692
9702
  lg: "w-18 h-18 text-3xl"
@@ -9727,9 +9737,9 @@ function TurnIndicator({
9727
9737
  size = "md",
9728
9738
  className
9729
9739
  }) {
9730
- const sizes = sizeMap7[size];
9740
+ const sizes = sizeMap8[size];
9731
9741
  return /* @__PURE__ */ jsxRuntime.jsxs(
9732
- "div",
9742
+ Box,
9733
9743
  {
9734
9744
  className: cn(
9735
9745
  "inline-flex items-center rounded-container",
@@ -9738,42 +9748,35 @@ function TurnIndicator({
9738
9748
  className
9739
9749
  ),
9740
9750
  children: [
9741
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "font-bold tabular-nums", children: [
9751
+ /* @__PURE__ */ jsxRuntime.jsxs(Typography, { as: "span", className: "font-bold tabular-nums", children: [
9742
9752
  "Turn ",
9743
9753
  currentTurn,
9744
- maxTurns != null && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-muted-foreground", children: [
9754
+ maxTurns != null && /* @__PURE__ */ jsxRuntime.jsxs(Typography, { as: "span", className: "text-muted-foreground", children: [
9745
9755
  "/",
9746
9756
  maxTurns
9747
9757
  ] })
9748
9758
  ] }),
9749
9759
  phase && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
9750
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: "|" }),
9751
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: phase })
9760
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "text-muted-foreground", children: "|" }),
9761
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "text-muted-foreground", children: phase })
9752
9762
  ] }),
9753
9763
  activeTeam && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
9754
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: "|" }),
9755
- assetUrl ? /* @__PURE__ */ jsxRuntime.jsx(
9756
- "img",
9757
- {
9758
- src: assetUrl.url,
9759
- alt: "",
9760
- width: 12,
9761
- height: 12,
9762
- style: { imageRendering: "pixelated", objectFit: "contain" },
9763
- className: "flex-shrink-0"
9764
- }
9765
- ) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("rounded-full bg-success/20", sizes.dot) }),
9766
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-success", children: activeTeam })
9764
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "text-muted-foreground", children: "|" }),
9765
+ assetUrl ? /* @__PURE__ */ jsxRuntime.jsx(GameIcon, { assetUrl, icon: "image", size: 12, className: "flex-shrink-0" }) : /* @__PURE__ */ jsxRuntime.jsx(Box, { as: "span", className: cn("rounded-full bg-success/20", sizes.dot) }),
9766
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "text-success", children: activeTeam })
9767
9767
  ] })
9768
9768
  ]
9769
9769
  }
9770
9770
  );
9771
9771
  }
9772
- var sizeMap7, DEFAULT_ASSET_URL6;
9772
+ var sizeMap8, DEFAULT_ASSET_URL6;
9773
9773
  var init_TurnIndicator = __esm({
9774
9774
  "components/game/2d/atoms/TurnIndicator.tsx"() {
9775
9775
  init_cn();
9776
- sizeMap7 = {
9776
+ init_Box();
9777
+ init_Typography();
9778
+ init_GameIcon();
9779
+ sizeMap8 = {
9777
9780
  sm: { wrapper: "text-xs gap-1.5 px-2 py-0.5", dot: "w-1.5 h-1.5" },
9778
9781
  md: { wrapper: "text-sm gap-2 px-3 py-1", dot: "w-2 h-2" },
9779
9782
  lg: { wrapper: "text-base gap-2.5 px-4 py-1.5", dot: "w-2.5 h-2.5" }
@@ -9805,10 +9808,10 @@ function ComboCounter({
9805
9808
  size = "md",
9806
9809
  className
9807
9810
  }) {
9808
- const sizes = sizeMap8[size];
9811
+ const sizes = sizeMap9[size];
9809
9812
  if (combo <= 0) return null;
9810
9813
  return /* @__PURE__ */ jsxRuntime.jsxs(
9811
- "div",
9814
+ Box,
9812
9815
  {
9813
9816
  className: cn(
9814
9817
  "inline-flex flex-col items-center justify-center",
@@ -9818,24 +9821,14 @@ function ComboCounter({
9818
9821
  className
9819
9822
  ),
9820
9823
  children: [
9821
- assetUrl && /* @__PURE__ */ jsxRuntime.jsx(
9822
- "img",
9823
- {
9824
- src: assetUrl.url,
9825
- alt: "combo",
9826
- width: 24,
9827
- height: 24,
9828
- style: { imageRendering: "pixelated", objectFit: "contain" },
9829
- className: "flex-shrink-0 mb-0.5"
9830
- }
9831
- ),
9832
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("font-black tabular-nums leading-none", sizes.combo, getComboIntensity(combo)), children: combo }),
9833
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("font-bold uppercase tracking-wider text-muted-foreground", sizes.label), children: "combo" }),
9834
- multiplier != null && multiplier > 1 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: cn("font-bold text-warning tabular-nums", sizes.multiplier), children: [
9824
+ assetUrl && /* @__PURE__ */ jsxRuntime.jsx(GameIcon, { assetUrl, icon: "image", size: 24, className: "flex-shrink-0 mb-0.5" }),
9825
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: cn("font-black tabular-nums leading-none", sizes.combo, getComboIntensity(combo)), children: combo }),
9826
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: cn("font-bold uppercase tracking-wider text-muted-foreground", sizes.label), children: "combo" }),
9827
+ multiplier != null && multiplier > 1 && /* @__PURE__ */ jsxRuntime.jsxs(Typography, { as: "span", className: cn("font-bold text-warning tabular-nums", sizes.multiplier), children: [
9835
9828
  "x",
9836
9829
  multiplier.toFixed(1)
9837
9830
  ] }),
9838
- streak != null && streak > 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: cn("text-muted-foreground tabular-nums", sizes.label), children: [
9831
+ streak != null && streak > 0 && /* @__PURE__ */ jsxRuntime.jsxs(Typography, { as: "span", className: cn("text-muted-foreground tabular-nums", sizes.label), children: [
9839
9832
  streak,
9840
9833
  " streak"
9841
9834
  ] })
@@ -9843,16 +9836,19 @@ function ComboCounter({
9843
9836
  }
9844
9837
  );
9845
9838
  }
9846
- var DEFAULT_ASSET_URL7, sizeMap8;
9839
+ var DEFAULT_ASSET_URL7, sizeMap9;
9847
9840
  var init_ComboCounter = __esm({
9848
9841
  "components/game/2d/atoms/ComboCounter.tsx"() {
9849
9842
  init_cn();
9843
+ init_Box();
9844
+ init_Typography();
9845
+ init_GameIcon();
9850
9846
  DEFAULT_ASSET_URL7 = {
9851
9847
  url: "https://almadar-kflow-assets.web.app/shared/effects/flash/flash00.png",
9852
9848
  role: "effect",
9853
9849
  category: "effect"
9854
9850
  };
9855
- sizeMap8 = {
9851
+ sizeMap9 = {
9856
9852
  sm: { combo: "text-lg", label: "text-xs", multiplier: "text-xs" },
9857
9853
  md: { combo: "text-2xl", label: "text-xs", multiplier: "text-sm" },
9858
9854
  lg: { combo: "text-4xl", label: "text-sm", multiplier: "text-base" }
@@ -9869,54 +9865,48 @@ function WaypointMarker({
9869
9865
  size = "md",
9870
9866
  className
9871
9867
  }) {
9872
- const sizes = sizeMap9[size];
9873
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex flex-col items-center", className), children: [
9874
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex items-center justify-center", children: [
9868
+ const sizes = sizeMap10[size];
9869
+ return /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: cn("flex flex-col items-center", className), children: [
9870
+ /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "relative flex items-center justify-center", children: [
9875
9871
  active && /* @__PURE__ */ jsxRuntime.jsx(
9876
- "div",
9872
+ Box,
9877
9873
  {
9874
+ position: "absolute",
9878
9875
  className: cn(
9879
- "absolute rounded-full border-2 border-info animate-ping opacity-50",
9876
+ "rounded-full border-2 border-info animate-ping opacity-50",
9880
9877
  sizes.ring
9881
9878
  )
9882
9879
  }
9883
9880
  ),
9884
9881
  active && /* @__PURE__ */ jsxRuntime.jsx(
9885
- "div",
9882
+ Box,
9886
9883
  {
9884
+ position: "absolute",
9887
9885
  className: cn(
9888
- "absolute rounded-full border-2 border-info",
9886
+ "rounded-full border-2 border-info",
9889
9887
  sizes.ring
9890
9888
  )
9891
9889
  }
9892
9890
  ),
9893
9891
  /* @__PURE__ */ jsxRuntime.jsx(
9894
- "div",
9892
+ Box,
9895
9893
  {
9894
+ position: "relative",
9896
9895
  className: cn(
9897
- "relative flex items-center justify-center rounded-full transition-all duration-200",
9896
+ "flex items-center justify-center rounded-full transition-all duration-200",
9898
9897
  sizes.dot,
9899
9898
  completed && "bg-success text-foreground",
9900
9899
  active && !completed && "bg-info text-foreground",
9901
9900
  !active && !completed && "bg-muted"
9902
9901
  ),
9903
- children: completed ? checkIcon : assetUrl ? /* @__PURE__ */ jsxRuntime.jsx(
9904
- "img",
9905
- {
9906
- src: assetUrl.url,
9907
- alt: label,
9908
- width: sizes.img,
9909
- height: sizes.img,
9910
- style: { imageRendering: "pixelated", objectFit: "contain" },
9911
- className: "flex-shrink-0"
9912
- }
9913
- ) : icon ? typeof icon === "string" ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: icon }) : /* @__PURE__ */ jsxRuntime.jsx(Icon, { icon }) : null
9902
+ children: completed ? checkIcon : assetUrl ? /* @__PURE__ */ jsxRuntime.jsx(GameIcon, { assetUrl, icon: "image", size: sizes.img, alt: label, className: "flex-shrink-0" }) : icon ? typeof icon === "string" ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: icon }) : /* @__PURE__ */ jsxRuntime.jsx(Icon, { icon }) : null
9914
9903
  }
9915
9904
  )
9916
9905
  ] }),
9917
9906
  label && /* @__PURE__ */ jsxRuntime.jsx(
9918
- "span",
9907
+ Typography,
9919
9908
  {
9909
+ as: "span",
9920
9910
  className: cn(
9921
9911
  "text-center whitespace-nowrap",
9922
9912
  sizes.label,
@@ -9927,17 +9917,20 @@ function WaypointMarker({
9927
9917
  )
9928
9918
  ] });
9929
9919
  }
9930
- var DEFAULT_ASSET_URL8, sizeMap9, checkIcon;
9920
+ var DEFAULT_ASSET_URL8, sizeMap10, checkIcon;
9931
9921
  var init_WaypointMarker = __esm({
9932
9922
  "components/game/2d/atoms/WaypointMarker.tsx"() {
9933
9923
  init_cn();
9934
9924
  init_Icon();
9925
+ init_Box();
9926
+ init_Typography();
9927
+ init_GameIcon();
9935
9928
  DEFAULT_ASSET_URL8 = {
9936
9929
  url: "https://almadar-kflow-assets.web.app/shared/world-map/battle_marker.png",
9937
9930
  role: "ui",
9938
9931
  category: "waypoint"
9939
9932
  };
9940
- sizeMap9 = {
9933
+ sizeMap10 = {
9941
9934
  sm: { dot: "w-4 h-4", ring: "w-6 h-6", label: "text-xs mt-1", img: 12 },
9942
9935
  md: { dot: "w-6 h-6", ring: "w-8 h-8", label: "text-sm mt-1.5", img: 18 },
9943
9936
  lg: { dot: "w-8 h-8", ring: "w-10 h-10", label: "text-base mt-2", img: 24 }
@@ -9962,32 +9955,24 @@ function StatusEffect({
9962
9955
  size = "md",
9963
9956
  className
9964
9957
  }) {
9965
- const sizes = sizeMap10[size];
9966
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("relative inline-flex flex-col items-center", className), children: [
9958
+ const sizes = sizeMap11[size];
9959
+ return /* @__PURE__ */ jsxRuntime.jsxs(Box, { position: "relative", className: cn("inline-flex flex-col items-center", className), children: [
9967
9960
  /* @__PURE__ */ jsxRuntime.jsxs(
9968
- "div",
9961
+ Box,
9969
9962
  {
9963
+ position: "relative",
9970
9964
  className: cn(
9971
- "relative flex items-center justify-center rounded-interactive border-2",
9965
+ "flex items-center justify-center rounded-interactive border-2",
9972
9966
  sizes.container,
9973
9967
  variantStyles7[variant]
9974
9968
  ),
9975
9969
  title: label,
9976
9970
  children: [
9977
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("flex items-center justify-center", sizes.icon), children: assetUrl ? /* @__PURE__ */ jsxRuntime.jsx(
9978
- "img",
9979
- {
9980
- src: assetUrl.url,
9981
- alt: label,
9982
- width: sizes.img,
9983
- height: sizes.img,
9984
- style: { imageRendering: "pixelated", objectFit: "contain" },
9985
- className: "flex-shrink-0"
9986
- }
9987
- ) : icon != null && typeof icon === "string" ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: icon, size: "sm" }) : icon != null ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { icon, size: "sm" }) : null }),
9971
+ /* @__PURE__ */ jsxRuntime.jsx(Box, { as: "span", className: cn("flex items-center justify-center", sizes.icon), children: assetUrl ? /* @__PURE__ */ jsxRuntime.jsx(GameIcon, { assetUrl, icon: "image", size: sizes.img, alt: label, className: "flex-shrink-0" }) : icon != null && typeof icon === "string" ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: icon, size: "sm" }) : icon != null ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { icon, size: "sm" }) : null }),
9988
9972
  duration !== void 0 && /* @__PURE__ */ jsxRuntime.jsx(
9989
- "span",
9973
+ Typography,
9990
9974
  {
9975
+ as: "span",
9991
9976
  className: cn(
9992
9977
  "absolute bottom-0 left-0 right-0 text-center font-mono font-bold text-foreground bg-background/60 leading-tight",
9993
9978
  sizes.timer
@@ -9999,8 +9984,9 @@ function StatusEffect({
9999
9984
  }
10000
9985
  ),
10001
9986
  stacks !== void 0 && stacks > 1 && /* @__PURE__ */ jsxRuntime.jsx(
10002
- "span",
9987
+ Typography,
10003
9988
  {
9989
+ as: "span",
10004
9990
  className: cn(
10005
9991
  "absolute flex items-center justify-center rounded-full bg-card text-foreground font-bold leading-none",
10006
9992
  sizes.badge
@@ -10008,20 +9994,23 @@ function StatusEffect({
10008
9994
  children: stacks
10009
9995
  }
10010
9996
  ),
10011
- label && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-muted-foreground mt-0.5 text-center whitespace-nowrap", children: label })
9997
+ label && /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "text-xs text-muted-foreground mt-0.5 text-center whitespace-nowrap", children: label })
10012
9998
  ] });
10013
9999
  }
10014
- var DEFAULT_ASSET_URL9, sizeMap10, variantStyles7;
10000
+ var DEFAULT_ASSET_URL9, sizeMap11, variantStyles7;
10015
10001
  var init_StatusEffect = __esm({
10016
10002
  "components/game/2d/atoms/StatusEffect.tsx"() {
10017
10003
  init_cn();
10018
10004
  init_Icon();
10005
+ init_Box();
10006
+ init_Typography();
10007
+ init_GameIcon();
10019
10008
  DEFAULT_ASSET_URL9 = {
10020
10009
  url: "https://almadar-kflow-assets.web.app/shared/effects/particles/flame_01.png",
10021
10010
  role: "ui",
10022
10011
  category: "effect"
10023
10012
  };
10024
- sizeMap10 = {
10013
+ sizeMap11 = {
10025
10014
  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 },
10026
10015
  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 },
10027
10016
  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 }
@@ -10045,38 +10034,31 @@ function DamageNumber({
10045
10034
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
10046
10035
  /* @__PURE__ */ jsxRuntime.jsx("style", { children: floatKeyframes }),
10047
10036
  /* @__PURE__ */ jsxRuntime.jsxs(
10048
- "span",
10037
+ Typography,
10049
10038
  {
10039
+ as: "span",
10050
10040
  className: cn(
10051
10041
  "inline-flex items-center gap-0.5 font-mono select-none pointer-events-none",
10052
- sizeMap11[size],
10042
+ sizeMap12[size],
10053
10043
  typeStyles[type],
10054
10044
  className
10055
10045
  ),
10056
10046
  style: { animation: "damageFloat 1s ease-out forwards" },
10057
10047
  children: [
10058
- assetUrl && /* @__PURE__ */ jsxRuntime.jsx(
10059
- "img",
10060
- {
10061
- src: assetUrl.url,
10062
- alt: "",
10063
- width: 14,
10064
- height: 14,
10065
- style: { imageRendering: "pixelated", objectFit: "contain" },
10066
- className: "flex-shrink-0"
10067
- }
10068
- ),
10048
+ assetUrl && /* @__PURE__ */ jsxRuntime.jsx(GameIcon, { assetUrl, icon: "image", size: 14, className: "flex-shrink-0" }),
10069
10049
  displayText
10070
10050
  ]
10071
10051
  }
10072
10052
  )
10073
10053
  ] });
10074
10054
  }
10075
- var sizeMap11, typeStyles, floatKeyframes, DEFAULT_ASSET_URL10;
10055
+ var sizeMap12, typeStyles, floatKeyframes, DEFAULT_ASSET_URL10;
10076
10056
  var init_DamageNumber = __esm({
10077
10057
  "components/game/2d/atoms/DamageNumber.tsx"() {
10078
10058
  init_cn();
10079
- sizeMap11 = {
10059
+ init_Typography();
10060
+ init_GameIcon();
10061
+ sizeMap12 = {
10080
10062
  sm: "text-sm",
10081
10063
  md: "text-lg",
10082
10064
  lg: "text-2xl"
@@ -10110,7 +10092,7 @@ function DialogueBubble({
10110
10092
  className
10111
10093
  }) {
10112
10094
  return /* @__PURE__ */ jsxRuntime.jsxs(
10113
- "div",
10095
+ Box,
10114
10096
  {
10115
10097
  className: cn(
10116
10098
  "flex items-start gap-3 rounded-container bg-background/80 backdrop-blur-sm px-4 py-3 border border-border/10",
@@ -10118,17 +10100,10 @@ function DialogueBubble({
10118
10100
  className
10119
10101
  ),
10120
10102
  children: [
10121
- portrait && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-shrink-0 w-12 h-12 rounded-full overflow-hidden border-2 border-warning/60", children: /* @__PURE__ */ jsxRuntime.jsx(
10122
- "img",
10123
- {
10124
- src: portrait?.url,
10125
- alt: speaker ?? "speaker",
10126
- className: "w-full h-full object-cover"
10127
- }
10128
- ) }),
10129
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1 min-w-0", children: [
10130
- speaker && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-bold text-warning", children: speaker }),
10131
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-foreground leading-relaxed", children: text })
10103
+ portrait && /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "flex-shrink-0 w-12 h-12 rounded-full overflow-hidden border-2 border-warning/60", children: /* @__PURE__ */ jsxRuntime.jsx(GameIcon, { assetUrl: portrait, icon: "image", size: 48, alt: speaker ?? "speaker", className: "w-full h-full object-cover" }) }),
10104
+ /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "flex flex-col gap-1 min-w-0", children: [
10105
+ speaker && /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "text-sm font-bold text-warning", children: speaker }),
10106
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "text-sm text-foreground leading-relaxed", children: text })
10132
10107
  ] })
10133
10108
  ]
10134
10109
  }
@@ -10138,6 +10113,9 @@ var DEFAULT_PORTRAIT;
10138
10113
  var init_DialogueBubble = __esm({
10139
10114
  "components/game/2d/atoms/DialogueBubble.tsx"() {
10140
10115
  init_cn();
10116
+ init_Box();
10117
+ init_Typography();
10118
+ init_GameIcon();
10141
10119
  DEFAULT_PORTRAIT = {
10142
10120
  url: "https://almadar-kflow-assets.web.app/shared/characters/archetypes/04_hero.png",
10143
10121
  role: "effect",
@@ -10159,11 +10137,11 @@ function ChoiceButton({
10159
10137
  }) {
10160
10138
  const eventBus = useEventBus();
10161
10139
  return /* @__PURE__ */ jsxRuntime.jsxs(
10162
- "button",
10140
+ Button,
10163
10141
  {
10164
- type: "button",
10142
+ variant: "ghost",
10165
10143
  disabled,
10166
- onClick: (e) => {
10144
+ onClick: () => {
10167
10145
  if (action) eventBus.emit(`UI:${action}`, {});
10168
10146
  onClick?.();
10169
10147
  },
@@ -10176,8 +10154,9 @@ function ChoiceButton({
10176
10154
  ),
10177
10155
  children: [
10178
10156
  index !== void 0 && /* @__PURE__ */ jsxRuntime.jsxs(
10179
- "span",
10157
+ Typography,
10180
10158
  {
10159
+ as: "span",
10181
10160
  className: cn(
10182
10161
  "flex-shrink-0 font-mono font-bold text-sm",
10183
10162
  selected ? "text-accent" : "text-muted-foreground"
@@ -10188,24 +10167,14 @@ function ChoiceButton({
10188
10167
  ]
10189
10168
  }
10190
10169
  ),
10191
- assetUrl ? /* @__PURE__ */ jsxRuntime.jsx(
10192
- "img",
10193
- {
10194
- src: assetUrl.url,
10195
- alt: "",
10196
- width: 16,
10197
- height: 16,
10198
- style: { imageRendering: "pixelated", objectFit: "contain" },
10199
- className: "flex-shrink-0"
10200
- }
10201
- ) : icon ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-shrink-0 text-sm", children: typeof icon === "string" ? (() => {
10170
+ assetUrl ? /* @__PURE__ */ jsxRuntime.jsx(GameIcon, { assetUrl, icon: "image", size: 16, className: "flex-shrink-0" }) : icon ? /* @__PURE__ */ jsxRuntime.jsx(Box, { as: "span", className: "flex-shrink-0 text-sm", children: typeof icon === "string" ? (() => {
10202
10171
  const I = resolveIcon(icon);
10203
10172
  return I ? /* @__PURE__ */ jsxRuntime.jsx(I, { className: "w-4 h-4" }) : null;
10204
10173
  })() : /* @__PURE__ */ (() => {
10205
10174
  const I = icon;
10206
10175
  return /* @__PURE__ */ jsxRuntime.jsx(I, { className: "w-4 h-4" });
10207
10176
  })() }) : null,
10208
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm leading-snug", children: text })
10177
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "text-sm leading-snug", children: text })
10209
10178
  ]
10210
10179
  }
10211
10180
  );
@@ -10215,6 +10184,10 @@ var init_ChoiceButton = __esm({
10215
10184
  init_cn();
10216
10185
  init_Icon();
10217
10186
  init_useEventBus();
10187
+ init_Button();
10188
+ init_Box();
10189
+ init_Typography();
10190
+ init_GameIcon();
10218
10191
  ChoiceButton.displayName = "ChoiceButton";
10219
10192
  }
10220
10193
  });
@@ -10232,16 +10205,16 @@ function ActionButton({
10232
10205
  className
10233
10206
  }) {
10234
10207
  const eventBus = useEventBus();
10235
- const sizes = sizeMap12[size];
10208
+ const sizes = sizeMap13[size];
10236
10209
  const onCooldown = cooldown > 0;
10237
10210
  const isDisabled = disabled || onCooldown;
10238
10211
  const cooldownDeg = Math.round(cooldown * 360);
10239
10212
  return /* @__PURE__ */ jsxRuntime.jsxs(
10240
- "button",
10213
+ Button,
10241
10214
  {
10242
- type: "button",
10215
+ variant: variant === "danger" ? "danger" : variant === "secondary" ? "secondary" : "primary",
10243
10216
  disabled: isDisabled,
10244
- onClick: (e) => {
10217
+ onClick: () => {
10245
10218
  if (action) eventBus.emit(`UI:${action}`, {});
10246
10219
  onClick?.();
10247
10220
  },
@@ -10254,9 +10227,10 @@ function ActionButton({
10254
10227
  ),
10255
10228
  children: [
10256
10229
  onCooldown && /* @__PURE__ */ jsxRuntime.jsx(
10257
- "div",
10230
+ Box,
10258
10231
  {
10259
- className: "absolute inset-0 bg-foreground/40 pointer-events-none",
10232
+ position: "absolute",
10233
+ className: "inset-0 bg-foreground/40 pointer-events-none",
10260
10234
  style: {
10261
10235
  clipPath: `conic-gradient(from 0deg, transparent ${360 - cooldownDeg}deg, black ${360 - cooldownDeg}deg)`,
10262
10236
  WebkitClipPath: `conic-gradient(from 0deg, transparent ${360 - cooldownDeg}deg, black ${360 - cooldownDeg}deg)`,
@@ -10264,27 +10238,18 @@ function ActionButton({
10264
10238
  }
10265
10239
  }
10266
10240
  ),
10267
- assetUrl ? /* @__PURE__ */ jsxRuntime.jsx(
10268
- "img",
10269
- {
10270
- src: assetUrl.url,
10271
- alt: "",
10272
- width: 16,
10273
- height: 16,
10274
- style: { imageRendering: "pixelated", objectFit: "contain" },
10275
- className: cn("flex-shrink-0", sizes.icon)
10276
- }
10277
- ) : icon ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("flex-shrink-0", sizes.icon), children: typeof icon === "string" ? (() => {
10241
+ assetUrl ? /* @__PURE__ */ jsxRuntime.jsx(GameIcon, { assetUrl, icon: "image", size: 16, className: cn("flex-shrink-0", sizes.icon) }) : icon ? /* @__PURE__ */ jsxRuntime.jsx(Box, { as: "span", className: cn("flex-shrink-0", sizes.icon), children: typeof icon === "string" ? (() => {
10278
10242
  const I = resolveIcon(icon);
10279
10243
  return I ? /* @__PURE__ */ jsxRuntime.jsx(I, { className: "w-4 h-4" }) : null;
10280
10244
  })() : /* @__PURE__ */ (() => {
10281
10245
  const I = icon;
10282
10246
  return /* @__PURE__ */ jsxRuntime.jsx(I, { className: "w-4 h-4" });
10283
10247
  })() }) : null,
10284
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "relative z-10", children: label }),
10248
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "relative z-10", children: label }),
10285
10249
  hotkey && /* @__PURE__ */ jsxRuntime.jsx(
10286
- "span",
10250
+ Typography,
10287
10251
  {
10252
+ as: "span",
10288
10253
  className: cn(
10289
10254
  "absolute top-0.5 right-0.5 bg-foreground/30 text-primary-foreground rounded font-mono leading-tight",
10290
10255
  sizes.hotkey
@@ -10296,13 +10261,17 @@ function ActionButton({
10296
10261
  }
10297
10262
  );
10298
10263
  }
10299
- var sizeMap12, variantStyles8, DEFAULT_ASSET_URL11;
10264
+ var sizeMap13, variantStyles8, DEFAULT_ASSET_URL11;
10300
10265
  var init_ActionButton = __esm({
10301
10266
  "components/game/2d/atoms/ActionButton.tsx"() {
10302
10267
  init_cn();
10303
10268
  init_Icon();
10304
10269
  init_useEventBus();
10305
- sizeMap12 = {
10270
+ init_Button();
10271
+ init_Box();
10272
+ init_Typography();
10273
+ init_GameIcon();
10274
+ sizeMap13 = {
10306
10275
  sm: { button: "h-button-sm px-3 text-xs", hotkey: "text-[9px] px-1", icon: "text-xs" },
10307
10276
  md: { button: "h-button-md px-4 text-sm", hotkey: "text-xs px-1.5", icon: "text-sm" },
10308
10277
  lg: { button: "h-button-lg px-5 text-base", hotkey: "text-xs px-2", icon: "text-base" }
@@ -10404,10 +10373,12 @@ function MiniMap({
10404
10373
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
10405
10374
  /* @__PURE__ */ jsxRuntime.jsx("style", { children: `@keyframes minimap-blink{0%,49%{opacity:1}50%,100%{opacity:0}}` }),
10406
10375
  /* @__PURE__ */ jsxRuntime.jsxs(
10407
- "div",
10376
+ Box,
10408
10377
  {
10378
+ position: "relative",
10379
+ display: "inline-block",
10409
10380
  className: cn(
10410
- "relative inline-block border border-border/20 rounded-container",
10381
+ "border border-border/20 rounded-container",
10411
10382
  className
10412
10383
  ),
10413
10384
  children: [
@@ -10422,10 +10393,10 @@ function MiniMap({
10422
10393
  }
10423
10394
  ),
10424
10395
  playerLeft !== null && playerTop !== null && /* @__PURE__ */ jsxRuntime.jsx(
10425
- "div",
10396
+ Box,
10426
10397
  {
10398
+ position: "absolute",
10427
10399
  style: {
10428
- position: "absolute",
10429
10400
  left: playerLeft,
10430
10401
  top: playerTop,
10431
10402
  width: 3,
@@ -10446,6 +10417,7 @@ var init_MiniMap = __esm({
10446
10417
  "components/game/2d/atoms/MiniMap.tsx"() {
10447
10418
  "use client";
10448
10419
  init_cn();
10420
+ init_Box();
10449
10421
  DEFAULT_TILES = [
10450
10422
  { x: 10, y: 10, color: "#4ade80" },
10451
10423
  { x: 20, y: 15, color: "#4ade80" },
@@ -10463,38 +10435,6 @@ var init_MiniMap = __esm({
10463
10435
  MiniMap.displayName = "MiniMap";
10464
10436
  }
10465
10437
  });
10466
- function GameIcon({ assetUrl, icon, size = "md", alt, className }) {
10467
- const px = typeof size === "number" ? size : sizeMap13[size];
10468
- if (assetUrl?.url) {
10469
- return /* @__PURE__ */ jsxRuntime.jsx(
10470
- "img",
10471
- {
10472
- src: assetUrl.url,
10473
- alt: alt ?? assetUrl.category ?? "",
10474
- width: px,
10475
- height: px,
10476
- style: { imageRendering: "pixelated", objectFit: "contain", width: px, height: px },
10477
- className: cn("flex-shrink-0", className)
10478
- }
10479
- );
10480
- }
10481
- const I = typeof icon === "string" ? resolveIcon(icon) : icon;
10482
- return /* @__PURE__ */ jsxRuntime.jsx(I, { width: px, height: px, className: cn("flex-shrink-0", className) });
10483
- }
10484
- var sizeMap13;
10485
- var init_GameIcon = __esm({
10486
- "components/game/2d/atoms/GameIcon.tsx"() {
10487
- "use client";
10488
- init_cn();
10489
- init_Icon();
10490
- sizeMap13 = {
10491
- sm: 16,
10492
- md: 24,
10493
- lg: 32
10494
- };
10495
- GameIcon.displayName = "GameIcon";
10496
- }
10497
- });
10498
10438
  function ControlGrid({
10499
10439
  kind,
10500
10440
  buttons = DEFAULT_BUTTONS,
@@ -10555,22 +10495,22 @@ function ControlGrid({
10555
10495
  },
10556
10496
  d
10557
10497
  );
10558
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("inline-grid grid-cols-3", ds.gap, ds.container, className), children: [
10559
- /* @__PURE__ */ jsxRuntime.jsx("div", {}),
10498
+ return /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: cn("inline-grid grid-cols-3", ds.gap, ds.container, className), children: [
10499
+ /* @__PURE__ */ jsxRuntime.jsx(Box, {}),
10560
10500
  dir("up"),
10561
- /* @__PURE__ */ jsxRuntime.jsx("div", {}),
10501
+ /* @__PURE__ */ jsxRuntime.jsx(Box, {}),
10562
10502
  dir("left"),
10563
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-6 h-6 rounded-interactive bg-muted border-2 border-muted-foreground" }) }),
10503
+ /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "w-6 h-6 rounded-interactive bg-muted border-2 border-muted-foreground" }) }),
10564
10504
  dir("right"),
10565
- /* @__PURE__ */ jsxRuntime.jsx("div", {}),
10505
+ /* @__PURE__ */ jsxRuntime.jsx(Box, {}),
10566
10506
  dir("down"),
10567
- /* @__PURE__ */ jsxRuntime.jsx("div", {})
10507
+ /* @__PURE__ */ jsxRuntime.jsx(Box, {})
10568
10508
  ] });
10569
10509
  }
10570
10510
  if (layout === "diamond" && buttons.length === 4) {
10571
10511
  const [top, right, bottom, left] = buttons;
10572
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn(layoutClass.diamond, className), children: [
10573
- /* @__PURE__ */ jsxRuntime.jsx("div", {}),
10512
+ return /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: cn(layoutClass.diamond, className), children: [
10513
+ /* @__PURE__ */ jsxRuntime.jsx(Box, {}),
10574
10514
  /* @__PURE__ */ jsxRuntime.jsx(
10575
10515
  ControlButton,
10576
10516
  {
@@ -10585,7 +10525,7 @@ function ControlGrid({
10585
10525
  disabled
10586
10526
  }
10587
10527
  ),
10588
- /* @__PURE__ */ jsxRuntime.jsx("div", {}),
10528
+ /* @__PURE__ */ jsxRuntime.jsx(Box, {}),
10589
10529
  /* @__PURE__ */ jsxRuntime.jsx(
10590
10530
  ControlButton,
10591
10531
  {
@@ -10600,7 +10540,7 @@ function ControlGrid({
10600
10540
  disabled
10601
10541
  }
10602
10542
  ),
10603
- /* @__PURE__ */ jsxRuntime.jsx("div", {}),
10543
+ /* @__PURE__ */ jsxRuntime.jsx(Box, {}),
10604
10544
  /* @__PURE__ */ jsxRuntime.jsx(
10605
10545
  ControlButton,
10606
10546
  {
@@ -10615,7 +10555,7 @@ function ControlGrid({
10615
10555
  disabled
10616
10556
  }
10617
10557
  ),
10618
- /* @__PURE__ */ jsxRuntime.jsx("div", {}),
10558
+ /* @__PURE__ */ jsxRuntime.jsx(Box, {}),
10619
10559
  /* @__PURE__ */ jsxRuntime.jsx(
10620
10560
  ControlButton,
10621
10561
  {
@@ -10630,10 +10570,10 @@ function ControlGrid({
10630
10570
  disabled
10631
10571
  }
10632
10572
  ),
10633
- /* @__PURE__ */ jsxRuntime.jsx("div", {})
10573
+ /* @__PURE__ */ jsxRuntime.jsx(Box, {})
10634
10574
  ] });
10635
10575
  }
10636
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn(layoutClass[layout], className), children: buttons.map((button) => /* @__PURE__ */ jsxRuntime.jsx(
10576
+ return /* @__PURE__ */ jsxRuntime.jsx(Box, { className: cn(layoutClass[layout], className), children: buttons.map((button) => /* @__PURE__ */ jsxRuntime.jsx(
10637
10577
  ControlButton,
10638
10578
  {
10639
10579
  icon: button.icon,
@@ -10655,6 +10595,7 @@ var init_ControlGrid = __esm({
10655
10595
  "use client";
10656
10596
  init_cn();
10657
10597
  init_useEventBus();
10598
+ init_Box();
10658
10599
  init_ControlButton();
10659
10600
  sizeKey = { sm: "sm", md: "md", lg: "lg" };
10660
10601
  layoutClass = {
@@ -10699,7 +10640,7 @@ function StatBadge({
10699
10640
  const numValue = typeof value === "number" ? value : parseInt(String(value), 10) || 0;
10700
10641
  const resolvedAsset = iconUrl ?? assetUrl;
10701
10642
  return /* @__PURE__ */ jsxRuntime.jsxs(
10702
- "div",
10643
+ Box,
10703
10644
  {
10704
10645
  className: cn(
10705
10646
  "inline-flex items-center gap-2 rounded-container border backdrop-blur-sm",
@@ -10708,18 +10649,8 @@ function StatBadge({
10708
10649
  className
10709
10650
  ),
10710
10651
  children: [
10711
- resolvedAsset ? /* @__PURE__ */ jsxRuntime.jsx(
10712
- "img",
10713
- {
10714
- src: resolvedAsset.url,
10715
- alt: "",
10716
- width: 16,
10717
- height: 16,
10718
- style: { imageRendering: "pixelated", objectFit: "contain" },
10719
- className: "flex-shrink-0"
10720
- }
10721
- ) : icon ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-shrink-0 text-lg", children: typeof icon === "string" ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: icon, className: "w-4 h-4" }) : /* @__PURE__ */ jsxRuntime.jsx(Icon, { icon, className: "w-4 h-4" }) }) : null,
10722
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground font-medium", children: label }),
10652
+ resolvedAsset ? /* @__PURE__ */ jsxRuntime.jsx(GameIcon, { assetUrl: resolvedAsset, icon: "image", size: 16, className: "flex-shrink-0" }) : icon ? /* @__PURE__ */ jsxRuntime.jsx(Box, { as: "span", className: "flex-shrink-0 text-lg", children: typeof icon === "string" ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: icon, className: "w-4 h-4" }) : /* @__PURE__ */ jsxRuntime.jsx(Icon, { icon, className: "w-4 h-4" }) }) : null,
10653
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "text-muted-foreground font-medium", children: label }),
10723
10654
  format === "hearts" && max && /* @__PURE__ */ jsxRuntime.jsx(
10724
10655
  HealthBar,
10725
10656
  {
@@ -10745,7 +10676,7 @@ function StatBadge({
10745
10676
  size: size === "lg" ? "md" : "sm"
10746
10677
  }
10747
10678
  ),
10748
- format === "text" && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-bold text-foreground", children: value })
10679
+ format === "text" && /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "font-bold text-foreground", children: value })
10749
10680
  ]
10750
10681
  }
10751
10682
  );
@@ -10755,6 +10686,9 @@ var init_StatBadge = __esm({
10755
10686
  "components/game/2d/molecules/StatBadge.tsx"() {
10756
10687
  init_cn();
10757
10688
  init_Icon();
10689
+ init_Box();
10690
+ init_Typography();
10691
+ init_GameIcon();
10758
10692
  init_HealthBar();
10759
10693
  init_ScoreDisplay();
10760
10694
  sizeMap14 = {
@@ -10932,9 +10866,9 @@ function GameHud({
10932
10866
  if (position === "corners") {
10933
10867
  const leftStats = stats.slice(0, Math.ceil(stats.length / 2));
10934
10868
  const rightStats = stats.slice(Math.ceil(stats.length / 2));
10935
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("relative", positionMap[position], className), children: [
10936
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute top-4 left-4 flex flex-col gap-2 pointer-events-auto", children: leftStats.map((stat, i) => /* @__PURE__ */ jsxRuntime.jsx(StatBadge, { ...stat, size }, i)) }),
10937
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute top-4 right-4 flex flex-col gap-2 items-end pointer-events-auto", children: rightStats.map((stat, i) => /* @__PURE__ */ jsxRuntime.jsx(StatBadge, { ...stat, size }, i)) })
10869
+ return /* @__PURE__ */ jsxRuntime.jsxs(Box, { position: "relative", className: cn(positionMap[position], className), children: [
10870
+ /* @__PURE__ */ jsxRuntime.jsx(Box, { position: "absolute", className: "top-4 left-4 flex flex-col gap-2 pointer-events-auto", children: leftStats.map((stat, i) => /* @__PURE__ */ jsxRuntime.jsx(StatBadge, { ...stat, size }, i)) }),
10871
+ /* @__PURE__ */ jsxRuntime.jsx(Box, { position: "absolute", className: "top-4 right-4 flex flex-col gap-2 items-end pointer-events-auto", children: rightStats.map((stat, i) => /* @__PURE__ */ jsxRuntime.jsx(StatBadge, { ...stat, size }, i)) })
10938
10872
  ] });
10939
10873
  }
10940
10874
  if (position === "top" || position === "bottom") {
@@ -10943,7 +10877,7 @@ function GameHud({
10943
10877
  const rightStats = stats.slice(mid);
10944
10878
  const isTop = position === "top";
10945
10879
  return /* @__PURE__ */ jsxRuntime.jsxs(
10946
- "div",
10880
+ Box,
10947
10881
  {
10948
10882
  className: cn(
10949
10883
  "flex items-center justify-between w-full",
@@ -10953,17 +10887,18 @@ function GameHud({
10953
10887
  className
10954
10888
  ),
10955
10889
  children: [
10956
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-3 flex-shrink-0", children: leftStats.map((stat, i) => /* @__PURE__ */ jsxRuntime.jsx(StatBadge, { ...stat, size }, i)) }),
10957
- rightStats.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-3 flex-shrink-0", children: rightStats.map((stat, i) => /* @__PURE__ */ jsxRuntime.jsx(StatBadge, { ...stat, size }, i)) })
10890
+ /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "flex items-center gap-3 flex-shrink-0", children: leftStats.map((stat, i) => /* @__PURE__ */ jsxRuntime.jsx(StatBadge, { ...stat, size }, i)) }),
10891
+ rightStats.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "flex items-center gap-3 flex-shrink-0", children: rightStats.map((stat, i) => /* @__PURE__ */ jsxRuntime.jsx(StatBadge, { ...stat, size }, i)) })
10958
10892
  ]
10959
10893
  }
10960
10894
  );
10961
10895
  }
10962
10896
  return /* @__PURE__ */ jsxRuntime.jsx(
10963
- "div",
10897
+ Box,
10964
10898
  {
10899
+ position: "relative",
10965
10900
  className: cn(
10966
- "relative z-10 flex items-center gap-4 px-4 py-2",
10901
+ "z-10 flex items-center gap-4 px-4 py-2",
10967
10902
  transparent ? "bg-black/30 backdrop-blur-sm" : "bg-surface/90 backdrop-blur-sm",
10968
10903
  className
10969
10904
  ),
@@ -10975,6 +10910,7 @@ var positionMap, DEFAULT_HUD_STATS;
10975
10910
  var init_GameHud = __esm({
10976
10911
  "components/game/2d/molecules/GameHud.tsx"() {
10977
10912
  init_cn();
10913
+ init_Box();
10978
10914
  init_StatBadge();
10979
10915
  positionMap = {
10980
10916
  corners: "inset-0 pointer-events-none"
@@ -11015,7 +10951,7 @@ function GameMenu({
11015
10951
  [eventBus, onSelect]
11016
10952
  );
11017
10953
  return /* @__PURE__ */ jsxRuntime.jsxs(
11018
- "div",
10954
+ Box,
11019
10955
  {
11020
10956
  className: cn(
11021
10957
  "min-h-screen w-full flex flex-col items-center justify-center p-8",
@@ -11025,18 +10961,12 @@ function GameMenu({
11025
10961
  background: background ?? "linear-gradient(135deg, #1a1a2e 0%, #16213e 50%, #0f0e17 100%)"
11026
10962
  },
11027
10963
  children: [
11028
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center mb-12 animate-fade-in", children: [
11029
- logo && /* @__PURE__ */ jsxRuntime.jsx(
11030
- "img",
11031
- {
11032
- src: logo.url,
11033
- alt: title,
11034
- className: "h-24 w-auto mx-auto mb-6 drop-shadow-2xl"
11035
- }
11036
- ),
10964
+ /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "text-center mb-12 animate-fade-in", children: [
10965
+ logo && /* @__PURE__ */ jsxRuntime.jsx(GameIcon, { assetUrl: logo, icon: "image", size: 96, alt: title, className: "h-24 w-auto mx-auto mb-6 drop-shadow-2xl" }),
11037
10966
  /* @__PURE__ */ jsxRuntime.jsx(
11038
- "h1",
10967
+ Typography,
11039
10968
  {
10969
+ variant: "h1",
11040
10970
  className: "text-5xl md:text-7xl font-bold text-[var(--color-foreground)] tracking-tight",
11041
10971
  style: {
11042
10972
  textShadow: "0 4px 12px rgba(0,0,0,0.5)"
@@ -11044,9 +10974,9 @@ function GameMenu({
11044
10974
  children: title
11045
10975
  }
11046
10976
  ),
11047
- subtitle && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-2 text-lg text-muted-foreground tracking-widest uppercase", children: subtitle })
10977
+ subtitle && /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", className: "mt-2 text-lg text-muted-foreground tracking-widest uppercase", children: subtitle })
11048
10978
  ] }),
11049
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-4 w-full max-w-md", children: resolvedOptions.map((option, index) => /* @__PURE__ */ jsxRuntime.jsx(
10979
+ /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "flex flex-col gap-4 w-full max-w-md", children: resolvedOptions.map((option, index) => /* @__PURE__ */ jsxRuntime.jsx(
11050
10980
  ChoiceButton,
11051
10981
  {
11052
10982
  text: option.label,
@@ -11057,9 +10987,9 @@ function GameMenu({
11057
10987
  },
11058
10988
  index
11059
10989
  )) }),
11060
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "absolute inset-0 pointer-events-none overflow-hidden", children: [
11061
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute top-1/4 left-1/4 w-64 h-64 bg-info/10 rounded-container blur-3xl" }),
11062
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute bottom-1/4 right-1/4 w-96 h-96 bg-accent/10 rounded-container blur-3xl" })
10990
+ /* @__PURE__ */ jsxRuntime.jsxs(Box, { position: "absolute", className: "inset-0 pointer-events-none overflow-hidden", children: [
10991
+ /* @__PURE__ */ jsxRuntime.jsx(Box, { position: "absolute", className: "top-1/4 left-1/4 w-64 h-64 bg-info/10 rounded-container blur-3xl" }),
10992
+ /* @__PURE__ */ jsxRuntime.jsx(Box, { position: "absolute", className: "bottom-1/4 right-1/4 w-96 h-96 bg-accent/10 rounded-container blur-3xl" })
11063
10993
  ] })
11064
10994
  ]
11065
10995
  }
@@ -11071,6 +11001,9 @@ var init_GameMenu = __esm({
11071
11001
  "use client";
11072
11002
  init_cn();
11073
11003
  init_useEventBus();
11004
+ init_Box();
11005
+ init_Typography();
11006
+ init_GameIcon();
11074
11007
  init_ChoiceButton();
11075
11008
  DEFAULT_MENU_OPTIONS = [
11076
11009
  { label: "New Game", event: "NEW_GAME", variant: "primary" },
@@ -12311,10 +12244,11 @@ function Canvas2D({
12311
12244
  }
12312
12245
  }
12313
12246
  ),
12314
- process.env.NODE_ENV !== "production" && /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-game-actions": "", className: "sr-only", "aria-hidden": "true", children: [
12247
+ process.env.NODE_ENV !== "production" && /* @__PURE__ */ jsxRuntime.jsxs(Box, { "data-game-actions": "", className: "sr-only", "aria-hidden": "true", children: [
12315
12248
  tileClickEvent && /* @__PURE__ */ jsxRuntime.jsx(
12316
- "button",
12249
+ Button,
12317
12250
  {
12251
+ variant: "ghost",
12318
12252
  "data-event": tileClickEvent,
12319
12253
  "data-x": "0",
12320
12254
  "data-y": "0",
@@ -12323,8 +12257,9 @@ function Canvas2D({
12323
12257
  }
12324
12258
  ),
12325
12259
  unitClickEvent && units && units.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
12326
- "button",
12260
+ Button,
12327
12261
  {
12262
+ variant: "ghost",
12328
12263
  "data-event": unitClickEvent,
12329
12264
  "data-unit-id": units[0].id,
12330
12265
  onClick: () => eventBus.emit(`UI:${unitClickEvent}`, { unitId: units[0].id }),
@@ -12333,15 +12268,17 @@ function Canvas2D({
12333
12268
  )
12334
12269
  ] }),
12335
12270
  unitOverlays.map(({ unit, screenX, screenY }) => /* @__PURE__ */ jsxRuntime.jsxs(
12336
- "div",
12271
+ Box,
12337
12272
  {
12338
- className: "absolute pointer-events-none",
12273
+ position: "absolute",
12274
+ className: "pointer-events-none",
12339
12275
  style: { left: Math.round(screenX), top: Math.round(screenY), transform: "translate(-50%, 0)", zIndex: 5 },
12340
12276
  children: [
12341
12277
  unit.name && /* @__PURE__ */ jsxRuntime.jsx(
12342
- "div",
12278
+ Typography,
12343
12279
  {
12344
- className: "text-white text-xs font-bold px-1.5 py-0.5 rounded mb-0.5 whitespace-nowrap",
12280
+ as: "span",
12281
+ className: "text-white text-xs font-bold px-1.5 py-0.5 rounded mb-0.5 whitespace-nowrap block",
12345
12282
  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)" },
12346
12283
  children: unit.name
12347
12284
  }
@@ -12351,7 +12288,7 @@ function Canvas2D({
12351
12288
  },
12352
12289
  unit.id
12353
12290
  )),
12354
- showMinimap && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute bottom-2 right-2 pointer-events-none", style: { zIndex: 10 }, children: /* @__PURE__ */ jsxRuntime.jsx(
12291
+ showMinimap && /* @__PURE__ */ jsxRuntime.jsx(Box, { position: "absolute", className: "bottom-2 right-2 pointer-events-none", style: { zIndex: 10 }, children: /* @__PURE__ */ jsxRuntime.jsx(
12355
12292
  MiniMap,
12356
12293
  {
12357
12294
  tiles: miniMapTiles,
@@ -12373,6 +12310,7 @@ var init_Canvas2D = __esm({
12373
12310
  init_cn();
12374
12311
  init_useEventBus();
12375
12312
  init_Box();
12313
+ init_Button();
12376
12314
  init_Stack();
12377
12315
  init_Icon();
12378
12316
  init_Typography();
@@ -12704,7 +12642,7 @@ function GameAudioToggle({
12704
12642
  onClick: handleToggle,
12705
12643
  className: cn("text-lg leading-none px-2", className),
12706
12644
  "aria-pressed": muted,
12707
- children: activeAsset ? /* @__PURE__ */ jsxRuntime.jsx("img", { src: activeAsset.url, alt: muted ? "Muted" : "Sound on", className: "w-5 h-5 object-contain" }) : muted ? "\u{1F507}" : "\u{1F50A}"
12645
+ children: activeAsset ? /* @__PURE__ */ jsxRuntime.jsx(GameIcon, { assetUrl: activeAsset, icon: "image", size: 20, alt: muted ? "Muted" : "Sound on", className: "w-5 h-5 object-contain" }) : muted ? "\u{1F507}" : "\u{1F50A}"
12708
12646
  }
12709
12647
  );
12710
12648
  }
@@ -12714,6 +12652,7 @@ var init_GameAudioToggle = __esm({
12714
12652
  init_atoms();
12715
12653
  init_cn();
12716
12654
  init_GameAudioProvider();
12655
+ init_GameIcon();
12717
12656
  GameAudioToggle.displayName = "GameAudioToggle";
12718
12657
  }
12719
12658
  });
@@ -23301,7 +23240,7 @@ var init_Tabs = __esm({
23301
23240
  isActive ? variant === "pills" ? "text-primary-foreground font-bold" : "text-foreground font-bold" : "text-muted-foreground hover:text-foreground"
23302
23241
  ),
23303
23242
  children: [
23304
- item.icon && (typeof item.icon === "string" ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: item.icon, size: "sm" }) : /* @__PURE__ */ jsxRuntime.jsx(Icon, { icon: item.icon, size: "sm" })),
23243
+ item.iconAsset?.url ? /* @__PURE__ */ jsxRuntime.jsx("img", { src: item.iconAsset.url, alt: item.iconAsset.name ?? item.iconAsset.category ?? "", width: 16, height: 16, style: { imageRendering: "pixelated", objectFit: "contain", width: 16, height: 16 }, className: "flex-shrink-0" }) : item.icon && (typeof item.icon === "string" ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: item.icon, size: "sm" }) : /* @__PURE__ */ jsxRuntime.jsx(Icon, { icon: item.icon, size: "sm" })),
23305
23244
  /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "small", weight: isActive ? "semibold" : "normal", className: "!text-inherit", children: item.label }),
23306
23245
  item.badge !== void 0 && /* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: "default", size: "sm", children: item.badge })
23307
23246
  ]