@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.
@@ -5430,6 +5430,7 @@ var init_Button = __esm({
5430
5430
  rightIcon,
5431
5431
  icon: iconProp,
5432
5432
  iconRight: iconRightProp,
5433
+ iconAsset,
5433
5434
  action,
5434
5435
  actionPayload,
5435
5436
  label,
@@ -5441,7 +5442,8 @@ var init_Button = __esm({
5441
5442
  const eventBus = useEventBus();
5442
5443
  const leftIconValue = leftIcon || iconProp;
5443
5444
  const rightIconValue = rightIcon || iconRightProp;
5444
- const resolvedLeftIcon = resolveIconProp(leftIconValue, iconSizeStyles[size]);
5445
+ const px = size === "sm" ? 16 : size === "lg" ? 20 : 16;
5446
+ 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]);
5445
5447
  const resolvedRightIcon = resolveIconProp(rightIconValue, iconSizeStyles[size]);
5446
5448
  const handleClick = (e) => {
5447
5449
  if (action) {
@@ -5981,13 +5983,14 @@ var init_Badge = __esm({
5981
5983
  lg: "px-3 py-1.5 text-base"
5982
5984
  };
5983
5985
  Badge = React112__namespace.default.forwardRef(
5984
- ({ className, variant = "default", size = "sm", amount, label, icon, children, onRemove, removeLabel, ...props }, ref) => {
5986
+ ({ className, variant = "default", size = "sm", amount, label, icon, iconAsset, children, onRemove, removeLabel, ...props }, ref) => {
5985
5987
  const iconSizes3 = {
5986
5988
  sm: "h-icon-default w-icon-default",
5987
5989
  md: "h-icon-default w-icon-default",
5988
5990
  lg: "h-icon-default w-icon-default"
5989
5991
  };
5990
- const resolvedIcon = typeof icon === "string" ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: icon, className: iconSizes3[size] }) : icon ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { icon, className: iconSizes3[size] }) : null;
5992
+ const iconPx = size === "lg" ? 20 : 16;
5993
+ 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;
5991
5994
  return /* @__PURE__ */ jsxRuntime.jsxs(
5992
5995
  "span",
5993
5996
  {
@@ -12157,10 +12160,43 @@ var init_shared = __esm({
12157
12160
  init_canvasEffects();
12158
12161
  }
12159
12162
  });
12163
+ function GameIcon({ assetUrl, icon, size = "md", alt, className }) {
12164
+ const px = typeof size === "number" ? size : sizeMap[size];
12165
+ if (assetUrl?.url) {
12166
+ return /* @__PURE__ */ jsxRuntime.jsx(
12167
+ "img",
12168
+ {
12169
+ src: assetUrl.url,
12170
+ alt: alt ?? assetUrl.category ?? "",
12171
+ width: px,
12172
+ height: px,
12173
+ style: { imageRendering: "pixelated", objectFit: "contain", width: px, height: px },
12174
+ className: cn("flex-shrink-0", className)
12175
+ }
12176
+ );
12177
+ }
12178
+ const I = typeof icon === "string" ? resolveIcon(icon) : icon;
12179
+ return /* @__PURE__ */ jsxRuntime.jsx(I, { width: px, height: px, className: cn("flex-shrink-0", className) });
12180
+ }
12181
+ var sizeMap;
12182
+ var init_GameIcon = __esm({
12183
+ "components/game/2d/atoms/GameIcon.tsx"() {
12184
+ "use client";
12185
+ init_cn();
12186
+ init_Icon();
12187
+ sizeMap = {
12188
+ sm: 16,
12189
+ md: 24,
12190
+ lg: 32
12191
+ };
12192
+ GameIcon.displayName = "GameIcon";
12193
+ }
12194
+ });
12160
12195
  function GameCard({
12161
12196
  id,
12162
12197
  cost,
12163
12198
  art,
12199
+ frameAsset,
12164
12200
  attack,
12165
12201
  defense,
12166
12202
  name,
@@ -12178,16 +12214,19 @@ function GameCard({
12178
12214
  if (clickEvent) eventBus.emit(`UI:${clickEvent}`, { cardId: id });
12179
12215
  }, [disabled, id, onClick, clickEvent, eventBus]);
12180
12216
  const artPx = artPxMap[size];
12217
+ const frameStyle = frameAsset?.url ? { backgroundImage: `url(${frameAsset.url})`, backgroundSize: "100% 100%", backgroundRepeat: "no-repeat" } : {};
12181
12218
  return /* @__PURE__ */ jsxRuntime.jsxs(
12182
- "button",
12219
+ Button,
12183
12220
  {
12184
- type: "button",
12221
+ variant: "ghost",
12185
12222
  onClick: handleClick,
12186
12223
  disabled,
12187
12224
  title: name,
12225
+ style: frameStyle,
12188
12226
  className: cn(
12189
- "relative flex flex-col items-center rounded-interactive border-2",
12227
+ "relative flex flex-col items-center rounded-interactive",
12190
12228
  "bg-card/90 px-1.5 pt-1.5 pb-1 transition-all duration-150",
12229
+ frameAsset?.url ? "border-0" : "border-2",
12191
12230
  cardSizeMap[size],
12192
12231
  disabled ? "border-border opacity-50 cursor-not-allowed" : "border-accent hover:brightness-125 hover:-translate-y-1 cursor-pointer",
12193
12232
  selected && "ring-2 ring-foreground ring-offset-1 ring-offset-background -translate-y-1",
@@ -12195,8 +12234,9 @@ function GameCard({
12195
12234
  ),
12196
12235
  children: [
12197
12236
  cost != null && /* @__PURE__ */ jsxRuntime.jsx(
12198
- "span",
12237
+ Typography,
12199
12238
  {
12239
+ as: "span",
12200
12240
  className: cn(
12201
12241
  "absolute -top-2 -left-2 flex items-center justify-center",
12202
12242
  "min-w-[22px] h-[22px] rounded-full px-1",
@@ -12205,17 +12245,7 @@ function GameCard({
12205
12245
  children: cost
12206
12246
  }
12207
12247
  ),
12208
- /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "flex-1 flex items-center justify-center w-full", children: art ? /* @__PURE__ */ jsxRuntime.jsx(
12209
- "img",
12210
- {
12211
- src: art.url,
12212
- alt: name ?? id,
12213
- width: artPx,
12214
- height: artPx,
12215
- style: { imageRendering: "pixelated", objectFit: "contain" },
12216
- className: "flex-shrink-0"
12217
- }
12218
- ) : /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "rounded bg-muted/40", style: { width: artPx, height: artPx } }) }),
12248
+ /* @__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 } }) }),
12219
12249
  name != null && /* @__PURE__ */ jsxRuntime.jsx(
12220
12250
  Typography,
12221
12251
  {
@@ -12225,8 +12255,8 @@ function GameCard({
12225
12255
  }
12226
12256
  ),
12227
12257
  (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: [
12228
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-error", children: attack != null ? `\u2694${attack}` : "" }),
12229
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-info", children: defense != null ? `\u{1F6E1}${defense}` : "" })
12258
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "text-error", children: attack != null ? `\u2694${attack}` : "" }),
12259
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "text-info", children: defense != null ? `\u{1F6E1}${defense}` : "" })
12230
12260
  ] })
12231
12261
  ]
12232
12262
  }
@@ -12239,7 +12269,9 @@ var init_GameCard = __esm({
12239
12269
  init_cn();
12240
12270
  init_useEventBus();
12241
12271
  init_Box();
12272
+ init_Button();
12242
12273
  init_Typography();
12274
+ init_GameIcon();
12243
12275
  cardSizeMap = {
12244
12276
  sm: "w-16 h-24",
12245
12277
  md: "w-20 h-28",
@@ -12262,12 +12294,13 @@ function HealthBar({
12262
12294
  frameAsset,
12263
12295
  fillAsset
12264
12296
  }) {
12265
- const sizes = sizeMap[size];
12297
+ const sizes = sizeMap2[size];
12266
12298
  const percentage = max > 0 ? Math.max(0, Math.min(100, current / max * 100)) : 0;
12267
12299
  if (format === "hearts") {
12268
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("flex items-center gap-1", className), children: Array.from({ length: max }).map((_, i) => /* @__PURE__ */ jsxRuntime.jsx(
12269
- "span",
12300
+ return /* @__PURE__ */ jsxRuntime.jsx(Box, { className: cn("flex items-center gap-1", className), children: Array.from({ length: max }).map((_, i) => /* @__PURE__ */ jsxRuntime.jsx(
12301
+ Box,
12270
12302
  {
12303
+ as: "span",
12271
12304
  className: cn(animated && "transition-transform hover:scale-110"),
12272
12305
  children: heartIcon(i < current, sizes.heart)
12273
12306
  },
@@ -12276,10 +12309,12 @@ function HealthBar({
12276
12309
  }
12277
12310
  if (format === "bar") {
12278
12311
  return /* @__PURE__ */ jsxRuntime.jsx(
12279
- "div",
12312
+ Box,
12280
12313
  {
12314
+ position: "relative",
12315
+ overflow: "hidden",
12281
12316
  className: cn(
12282
- "relative overflow-hidden rounded-full",
12317
+ "rounded-full",
12283
12318
  !frameAsset && "bg-muted",
12284
12319
  sizes.bar,
12285
12320
  "w-24",
@@ -12287,10 +12322,11 @@ function HealthBar({
12287
12322
  ),
12288
12323
  style: frameAsset ? { backgroundImage: `url(${frameAsset.url})`, backgroundSize: "100% 100%" } : void 0,
12289
12324
  children: /* @__PURE__ */ jsxRuntime.jsx(
12290
- "div",
12325
+ Box,
12291
12326
  {
12327
+ position: "absolute",
12292
12328
  className: cn(
12293
- "absolute inset-y-0 left-0 rounded-full",
12329
+ "inset-y-0 left-0 rounded-full",
12294
12330
  !fillAsset && (percentage > 66 ? "bg-success" : percentage > 33 ? "bg-warning" : "bg-error"),
12295
12331
  animated && "transition-all duration-300"
12296
12332
  ),
@@ -12304,10 +12340,11 @@ function HealthBar({
12304
12340
  );
12305
12341
  }
12306
12342
  if (format === "progress") {
12307
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex items-center gap-2", className), children: [
12343
+ return /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: cn("flex items-center gap-2", className), children: [
12308
12344
  level != null && /* @__PURE__ */ jsxRuntime.jsxs(
12309
- "span",
12345
+ Typography,
12310
12346
  {
12347
+ as: "span",
12311
12348
  className: cn(
12312
12349
  "flex-shrink-0 rounded-interactive font-bold",
12313
12350
  "bg-accent text-accent-foreground border border-accent",
@@ -12319,21 +12356,23 @@ function HealthBar({
12319
12356
  ]
12320
12357
  }
12321
12358
  ),
12322
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 flex flex-col gap-0.5", children: [
12359
+ /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "flex-1 flex flex-col gap-0.5", children: [
12323
12360
  /* @__PURE__ */ jsxRuntime.jsx(
12324
- "div",
12361
+ Box,
12325
12362
  {
12363
+ position: "relative",
12326
12364
  className: cn(
12327
- "relative w-full overflow-hidden rounded-full",
12365
+ "w-full overflow-hidden rounded-full",
12328
12366
  !frameAsset && "bg-muted border border-muted",
12329
12367
  sizes.bar
12330
12368
  ),
12331
12369
  style: frameAsset ? { backgroundImage: `url(${frameAsset.url})`, backgroundSize: "100% 100%" } : void 0,
12332
12370
  children: /* @__PURE__ */ jsxRuntime.jsx(
12333
- "div",
12371
+ Box,
12334
12372
  {
12373
+ position: "absolute",
12335
12374
  className: cn(
12336
- "absolute inset-y-0 left-0 rounded-full",
12375
+ "inset-y-0 left-0 rounded-full",
12337
12376
  !fillAsset && "bg-gradient-to-r from-accent to-info",
12338
12377
  animated && "transition-all duration-500 ease-out"
12339
12378
  ),
@@ -12345,7 +12384,7 @@ function HealthBar({
12345
12384
  )
12346
12385
  }
12347
12386
  ),
12348
- showLabel && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: cn("text-foreground/70 tabular-nums", sizes.label), children: [
12387
+ showLabel && /* @__PURE__ */ jsxRuntime.jsxs(Typography, { as: "span", className: cn("text-foreground/70 tabular-nums", sizes.label), children: [
12349
12388
  current,
12350
12389
  " / ",
12351
12390
  max,
@@ -12354,16 +12393,18 @@ function HealthBar({
12354
12393
  ] })
12355
12394
  ] });
12356
12395
  }
12357
- return /* @__PURE__ */ jsxRuntime.jsxs("span", { className: cn("font-mono font-bold", sizes.text, className), children: [
12396
+ return /* @__PURE__ */ jsxRuntime.jsxs(Typography, { as: "span", className: cn("font-mono font-bold", sizes.text, className), children: [
12358
12397
  current,
12359
12398
  "/",
12360
12399
  max
12361
12400
  ] });
12362
12401
  }
12363
- var heartIcon, sizeMap;
12402
+ var heartIcon, sizeMap2;
12364
12403
  var init_HealthBar = __esm({
12365
12404
  "components/game/2d/atoms/HealthBar.tsx"() {
12366
12405
  init_cn();
12406
+ init_Box();
12407
+ init_Typography();
12367
12408
  heartIcon = (filled, size) => /* @__PURE__ */ jsxRuntime.jsx(
12368
12409
  "svg",
12369
12410
  {
@@ -12375,7 +12416,7 @@ var init_HealthBar = __esm({
12375
12416
  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" })
12376
12417
  }
12377
12418
  );
12378
- sizeMap = {
12419
+ sizeMap2 = {
12379
12420
  sm: { heart: "w-4 h-4", bar: "h-2", text: "text-sm", label: "text-xs", badge: "text-xs px-1.5 py-0.5" },
12380
12421
  md: { heart: "w-6 h-6", bar: "h-3", text: "text-base", label: "text-xs", badge: "text-xs px-2 py-0.5" },
12381
12422
  lg: { heart: "w-8 h-8", bar: "h-4", text: "text-lg", label: "text-sm", badge: "text-sm px-2.5 py-1" }
@@ -12396,37 +12437,30 @@ function ScoreDisplay({
12396
12437
  const resolvedValue = typeof value === "number" && !Number.isNaN(value) ? value : typeof score === "number" && !Number.isNaN(score) ? score : 0;
12397
12438
  const formattedValue = new Intl.NumberFormat(locale).format(resolvedValue);
12398
12439
  return /* @__PURE__ */ jsxRuntime.jsxs(
12399
- "div",
12440
+ Box,
12400
12441
  {
12401
12442
  className: cn(
12402
12443
  "flex items-center gap-2 font-bold",
12403
- sizeMap2[size],
12444
+ sizeMap3[size],
12404
12445
  className
12405
12446
  ),
12406
12447
  children: [
12407
- assetUrl ? /* @__PURE__ */ jsxRuntime.jsx(
12408
- "img",
12409
- {
12410
- src: assetUrl.url,
12411
- alt: "",
12412
- width: 20,
12413
- height: 20,
12414
- style: { imageRendering: "pixelated", objectFit: "contain" },
12415
- className: "flex-shrink-0"
12416
- }
12417
- ) : 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,
12418
- label && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: label }),
12419
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "tabular-nums", children: formattedValue })
12448
+ 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,
12449
+ label && /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "text-muted-foreground", children: label }),
12450
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "tabular-nums", children: formattedValue })
12420
12451
  ]
12421
12452
  }
12422
12453
  );
12423
12454
  }
12424
- var sizeMap2, DEFAULT_ASSET_URL;
12455
+ var sizeMap3, DEFAULT_ASSET_URL;
12425
12456
  var init_ScoreDisplay = __esm({
12426
12457
  "components/game/2d/atoms/ScoreDisplay.tsx"() {
12427
12458
  init_cn();
12428
12459
  init_Icon();
12429
- sizeMap2 = {
12460
+ init_Box();
12461
+ init_Typography();
12462
+ init_GameIcon();
12463
+ sizeMap3 = {
12430
12464
  sm: "text-sm",
12431
12465
  md: "text-lg",
12432
12466
  lg: "text-2xl",
@@ -12489,9 +12523,9 @@ function ControlButton({
12489
12523
  [isPressed, releaseEvent, eventBus, onRelease]
12490
12524
  );
12491
12525
  return /* @__PURE__ */ jsxRuntime.jsx(
12492
- "button",
12526
+ Button,
12493
12527
  {
12494
- type: "button",
12528
+ variant,
12495
12529
  disabled,
12496
12530
  onPointerDown: handlePointerDown,
12497
12531
  onPointerUp: handlePointerUp,
@@ -12502,41 +12536,35 @@ function ControlButton({
12502
12536
  "select-none touch-none",
12503
12537
  "transition-all duration-100",
12504
12538
  "active:scale-95",
12505
- sizeMap3[size] ?? sizeMap3.md,
12539
+ sizeMap4[size] ?? sizeMap4.md,
12506
12540
  shapeMap[shape] ?? shapeMap.circle,
12507
12541
  variantMap[variant] ?? variantMap.secondary,
12508
12542
  actualPressed && "scale-95 brightness-110 border-foreground",
12509
12543
  disabled && "opacity-50 cursor-not-allowed",
12510
12544
  className
12511
12545
  ),
12512
- children: assetUrl ? /* @__PURE__ */ jsxRuntime.jsx(
12513
- "img",
12514
- {
12515
- src: assetUrl.url,
12516
- alt: "",
12517
- width: 24,
12518
- height: 24,
12519
- style: { imageRendering: "pixelated", objectFit: "contain" },
12520
- className: "flex-shrink-0"
12521
- }
12522
- ) : icon ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-2xl", children: typeof icon === "string" ? /^[a-zA-Z0-9-]+$/.test(icon) ? (() => {
12546
+ 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) ? (() => {
12523
12547
  const I = resolveIcon(icon);
12524
12548
  return I ? /* @__PURE__ */ jsxRuntime.jsx(I, { className: "w-6 h-6" }) : null;
12525
12549
  })() : icon : /* @__PURE__ */ (() => {
12526
12550
  const I = icon;
12527
12551
  return /* @__PURE__ */ jsxRuntime.jsx(I, { className: "w-6 h-6" });
12528
- })() }) : label ? /* @__PURE__ */ jsxRuntime.jsx("span", { children: label }) : null
12552
+ })() }) : label ? /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", children: label }) : null
12529
12553
  }
12530
12554
  );
12531
12555
  }
12532
- var sizeMap3, shapeMap, variantMap, DEFAULT_ASSET_URL2;
12556
+ var sizeMap4, shapeMap, variantMap, DEFAULT_ASSET_URL2;
12533
12557
  var init_ControlButton = __esm({
12534
12558
  "components/game/2d/atoms/ControlButton.tsx"() {
12535
12559
  "use client";
12536
12560
  init_cn();
12537
12561
  init_useEventBus();
12538
12562
  init_Icon();
12539
- sizeMap3 = {
12563
+ init_Button();
12564
+ init_Box();
12565
+ init_Typography();
12566
+ init_GameIcon();
12567
+ sizeMap4 = {
12540
12568
  sm: "w-10 h-10 text-sm",
12541
12569
  md: "w-14 h-14 text-base",
12542
12570
  lg: "w-18 h-18 text-lg",
@@ -12606,12 +12634,12 @@ function Sprite({
12606
12634
  onClick?.();
12607
12635
  };
12608
12636
  return /* @__PURE__ */ jsxRuntime.jsx(
12609
- "div",
12637
+ Box,
12610
12638
  {
12639
+ position: "absolute",
12611
12640
  className,
12612
12641
  onClick: action || onClick ? handleClick : void 0,
12613
12642
  style: {
12614
- position: "absolute",
12615
12643
  width: frameWidth,
12616
12644
  height: frameHeight,
12617
12645
  backgroundImage: `url(${spritesheet.url})`,
@@ -12632,6 +12660,7 @@ var init_Sprite = __esm({
12632
12660
  "components/game/2d/atoms/Sprite.tsx"() {
12633
12661
  "use client";
12634
12662
  init_useEventBus();
12663
+ init_Box();
12635
12664
  init_spriteAnimation();
12636
12665
  DEFAULT_SPRITESHEET = {
12637
12666
  url: "https://almadar-kflow-assets.web.app/shared/isometric-blocks/Spritesheet/allTiles_sheet.png",
@@ -12668,17 +12697,7 @@ function StateIndicator({
12668
12697
  className
12669
12698
  ),
12670
12699
  children: [
12671
- /* @__PURE__ */ jsxRuntime.jsx(Box, { as: "span", children: assetUrl ? /* @__PURE__ */ jsxRuntime.jsx(
12672
- "img",
12673
- {
12674
- src: assetUrl.url,
12675
- alt: displayLabel,
12676
- width: 16,
12677
- height: 16,
12678
- style: { imageRendering: "pixelated", objectFit: "contain" },
12679
- className: "flex-shrink-0"
12680
- }
12681
- ) : 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 }) }),
12700
+ /* @__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 }) }),
12682
12701
  /* @__PURE__ */ jsxRuntime.jsx(Box, { as: "span", children: displayLabel })
12683
12702
  ]
12684
12703
  }
@@ -12690,6 +12709,7 @@ var init_StateIndicator = __esm({
12690
12709
  init_Box();
12691
12710
  init_Icon();
12692
12711
  init_cn();
12712
+ init_GameIcon();
12693
12713
  DEFAULT_ASSET_URL3 = {
12694
12714
  url: "https://almadar-kflow-assets.web.app/shared/isometric-dungeon/Isometric/chestClosed_E.png",
12695
12715
  role: "ui",
@@ -12743,29 +12763,31 @@ function TimerDisplay({
12743
12763
  }) {
12744
12764
  const isLow = lowThreshold != null && seconds <= lowThreshold && seconds > 0;
12745
12765
  return /* @__PURE__ */ jsxRuntime.jsxs(
12746
- "div",
12766
+ Box,
12747
12767
  {
12748
12768
  className: cn(
12749
12769
  "inline-flex items-center gap-1 justify-center rounded-container",
12750
12770
  "bg-card/80 border border-muted font-mono font-bold tabular-nums",
12751
- sizeMap4[size],
12771
+ sizeMap5[size],
12752
12772
  running && "border-success/50",
12753
12773
  isLow && "text-error border-error/50 animate-pulse",
12754
12774
  !isLow && "text-foreground",
12755
12775
  className
12756
12776
  ),
12757
12777
  children: [
12758
- iconAsset && /* @__PURE__ */ jsxRuntime.jsx("img", { src: iconAsset.url, alt: "", className: "w-4 h-4 object-contain flex-shrink-0" }),
12778
+ iconAsset && /* @__PURE__ */ jsxRuntime.jsx(GameIcon, { assetUrl: iconAsset, icon: "image", size: 16, className: "w-4 h-4 object-contain flex-shrink-0" }),
12759
12779
  formatTime(seconds, format)
12760
12780
  ]
12761
12781
  }
12762
12782
  );
12763
12783
  }
12764
- var sizeMap4;
12784
+ var sizeMap5;
12765
12785
  var init_TimerDisplay = __esm({
12766
12786
  "components/game/2d/atoms/TimerDisplay.tsx"() {
12767
12787
  init_cn();
12768
- sizeMap4 = {
12788
+ init_Box();
12789
+ init_GameIcon();
12790
+ sizeMap5 = {
12769
12791
  sm: "text-sm px-2 py-0.5",
12770
12792
  md: "text-lg px-3 py-1",
12771
12793
  lg: "text-2xl px-4 py-1.5"
@@ -12783,9 +12805,9 @@ function ResourceCounter({
12783
12805
  size = "md",
12784
12806
  className
12785
12807
  }) {
12786
- const sizes = sizeMap5[size];
12808
+ const sizes = sizeMap6[size];
12787
12809
  return /* @__PURE__ */ jsxRuntime.jsxs(
12788
- "div",
12810
+ Box,
12789
12811
  {
12790
12812
  className: cn(
12791
12813
  "inline-flex items-center rounded-container",
@@ -12794,21 +12816,11 @@ function ResourceCounter({
12794
12816
  className
12795
12817
  ),
12796
12818
  children: [
12797
- assetUrl ? /* @__PURE__ */ jsxRuntime.jsx(
12798
- "img",
12799
- {
12800
- src: assetUrl.url,
12801
- alt: label,
12802
- width: sizes.img,
12803
- height: sizes.img,
12804
- style: { imageRendering: "pixelated", objectFit: "contain" },
12805
- className: "flex-shrink-0"
12806
- }
12807
- ) : 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,
12808
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: label }),
12809
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: cn("font-bold tabular-nums", color && (color in colorTokenClasses2 ? colorTokenClasses2[color] : color)), children: [
12819
+ 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,
12820
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "text-muted-foreground", children: label }),
12821
+ /* @__PURE__ */ jsxRuntime.jsxs(Typography, { as: "span", className: cn("font-bold tabular-nums", color && (color in colorTokenClasses2 ? colorTokenClasses2[color] : color)), children: [
12810
12822
  value,
12811
- max != null && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-muted-foreground", children: [
12823
+ max != null && /* @__PURE__ */ jsxRuntime.jsxs(Typography, { as: "span", className: "text-muted-foreground", children: [
12812
12824
  "/",
12813
12825
  max
12814
12826
  ] })
@@ -12817,11 +12829,14 @@ function ResourceCounter({
12817
12829
  }
12818
12830
  );
12819
12831
  }
12820
- var colorTokenClasses2, DEFAULT_ASSET_URL4, sizeMap5;
12832
+ var colorTokenClasses2, DEFAULT_ASSET_URL4, sizeMap6;
12821
12833
  var init_ResourceCounter = __esm({
12822
12834
  "components/game/2d/atoms/ResourceCounter.tsx"() {
12823
12835
  init_cn();
12824
12836
  init_Icon();
12837
+ init_Box();
12838
+ init_Typography();
12839
+ init_GameIcon();
12825
12840
  colorTokenClasses2 = {
12826
12841
  primary: "text-primary",
12827
12842
  secondary: "text-secondary",
@@ -12835,7 +12850,7 @@ var init_ResourceCounter = __esm({
12835
12850
  role: "ui",
12836
12851
  category: "coin"
12837
12852
  };
12838
- sizeMap5 = {
12853
+ sizeMap6 = {
12839
12854
  sm: { wrapper: "text-xs gap-1 px-1.5 py-0.5", icon: "text-sm", img: 16 },
12840
12855
  md: { wrapper: "text-sm gap-1.5 px-2 py-1", icon: "text-base", img: 20 },
12841
12856
  lg: { wrapper: "text-base gap-2 px-3 py-1.5", icon: "text-lg", img: 28 }
@@ -12860,9 +12875,9 @@ function ItemSlot({
12860
12875
  const isClickable = onClick != null || action != null;
12861
12876
  const px = assetSizeMap[size];
12862
12877
  return /* @__PURE__ */ jsxRuntime.jsx(
12863
- "button",
12878
+ Button,
12864
12879
  {
12865
- type: "button",
12880
+ variant: "ghost",
12866
12881
  onClick: () => {
12867
12882
  if (action) eventBus.emit(`UI:${action}`, {});
12868
12883
  onClick?.();
@@ -12872,7 +12887,7 @@ function ItemSlot({
12872
12887
  className: cn(
12873
12888
  "relative flex items-center justify-center rounded-interactive border-2",
12874
12889
  "bg-card/80 transition-all duration-150",
12875
- sizeMap6[size],
12890
+ sizeMap7[size],
12876
12891
  empty ? "border-border bg-card/50" : rarityBorderMap[rarity],
12877
12892
  !empty && rarityGlowMap[rarity],
12878
12893
  selected && "ring-2 ring-foreground ring-offset-1 ring-offset-background",
@@ -12881,21 +12896,12 @@ function ItemSlot({
12881
12896
  !isClickable && "cursor-default",
12882
12897
  className
12883
12898
  ),
12884
- children: empty ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground text-base", children: "+" }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
12885
- assetUrl ? /* @__PURE__ */ jsxRuntime.jsx(
12886
- "img",
12887
- {
12888
- src: assetUrl?.url,
12889
- alt: label,
12890
- width: px,
12891
- height: px,
12892
- style: { imageRendering: "pixelated", objectFit: "contain" },
12893
- className: "flex-shrink-0"
12894
- }
12895
- ) : 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,
12899
+ children: empty ? /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "text-muted-foreground text-base", children: "+" }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
12900
+ 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,
12896
12901
  quantity != null && quantity > 1 && /* @__PURE__ */ jsxRuntime.jsx(
12897
- "span",
12902
+ Typography,
12898
12903
  {
12904
+ as: "span",
12899
12905
  className: cn(
12900
12906
  "absolute -bottom-1 -right-1 flex items-center justify-center",
12901
12907
  "min-w-[18px] h-[18px] rounded-full px-1",
@@ -12908,14 +12914,18 @@ function ItemSlot({
12908
12914
  }
12909
12915
  );
12910
12916
  }
12911
- var sizeMap6, rarityBorderMap, rarityGlowMap, DEFAULT_ASSET_URL5, assetSizeMap;
12917
+ var sizeMap7, rarityBorderMap, rarityGlowMap, DEFAULT_ASSET_URL5, assetSizeMap;
12912
12918
  var init_ItemSlot = __esm({
12913
12919
  "components/game/2d/atoms/ItemSlot.tsx"() {
12914
12920
  "use client";
12915
12921
  init_cn();
12916
12922
  init_Icon();
12917
12923
  init_useEventBus();
12918
- sizeMap6 = {
12924
+ init_Button();
12925
+ init_Box();
12926
+ init_Typography();
12927
+ init_GameIcon();
12928
+ sizeMap7 = {
12919
12929
  sm: "w-10 h-10 text-lg",
12920
12930
  md: "w-14 h-14 text-2xl",
12921
12931
  lg: "w-18 h-18 text-3xl"
@@ -12956,9 +12966,9 @@ function TurnIndicator({
12956
12966
  size = "md",
12957
12967
  className
12958
12968
  }) {
12959
- const sizes = sizeMap7[size];
12969
+ const sizes = sizeMap8[size];
12960
12970
  return /* @__PURE__ */ jsxRuntime.jsxs(
12961
- "div",
12971
+ Box,
12962
12972
  {
12963
12973
  className: cn(
12964
12974
  "inline-flex items-center rounded-container",
@@ -12967,42 +12977,35 @@ function TurnIndicator({
12967
12977
  className
12968
12978
  ),
12969
12979
  children: [
12970
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "font-bold tabular-nums", children: [
12980
+ /* @__PURE__ */ jsxRuntime.jsxs(Typography, { as: "span", className: "font-bold tabular-nums", children: [
12971
12981
  "Turn ",
12972
12982
  currentTurn,
12973
- maxTurns != null && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-muted-foreground", children: [
12983
+ maxTurns != null && /* @__PURE__ */ jsxRuntime.jsxs(Typography, { as: "span", className: "text-muted-foreground", children: [
12974
12984
  "/",
12975
12985
  maxTurns
12976
12986
  ] })
12977
12987
  ] }),
12978
12988
  phase && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
12979
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: "|" }),
12980
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: phase })
12989
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "text-muted-foreground", children: "|" }),
12990
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "text-muted-foreground", children: phase })
12981
12991
  ] }),
12982
12992
  activeTeam && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
12983
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: "|" }),
12984
- assetUrl ? /* @__PURE__ */ jsxRuntime.jsx(
12985
- "img",
12986
- {
12987
- src: assetUrl.url,
12988
- alt: "",
12989
- width: 12,
12990
- height: 12,
12991
- style: { imageRendering: "pixelated", objectFit: "contain" },
12992
- className: "flex-shrink-0"
12993
- }
12994
- ) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("rounded-full bg-success/20", sizes.dot) }),
12995
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-success", children: activeTeam })
12993
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "text-muted-foreground", children: "|" }),
12994
+ 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) }),
12995
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "text-success", children: activeTeam })
12996
12996
  ] })
12997
12997
  ]
12998
12998
  }
12999
12999
  );
13000
13000
  }
13001
- var sizeMap7, DEFAULT_ASSET_URL6;
13001
+ var sizeMap8, DEFAULT_ASSET_URL6;
13002
13002
  var init_TurnIndicator = __esm({
13003
13003
  "components/game/2d/atoms/TurnIndicator.tsx"() {
13004
13004
  init_cn();
13005
- sizeMap7 = {
13005
+ init_Box();
13006
+ init_Typography();
13007
+ init_GameIcon();
13008
+ sizeMap8 = {
13006
13009
  sm: { wrapper: "text-xs gap-1.5 px-2 py-0.5", dot: "w-1.5 h-1.5" },
13007
13010
  md: { wrapper: "text-sm gap-2 px-3 py-1", dot: "w-2 h-2" },
13008
13011
  lg: { wrapper: "text-base gap-2.5 px-4 py-1.5", dot: "w-2.5 h-2.5" }
@@ -13034,10 +13037,10 @@ function ComboCounter({
13034
13037
  size = "md",
13035
13038
  className
13036
13039
  }) {
13037
- const sizes = sizeMap8[size];
13040
+ const sizes = sizeMap9[size];
13038
13041
  if (combo <= 0) return null;
13039
13042
  return /* @__PURE__ */ jsxRuntime.jsxs(
13040
- "div",
13043
+ Box,
13041
13044
  {
13042
13045
  className: cn(
13043
13046
  "inline-flex flex-col items-center justify-center",
@@ -13047,24 +13050,14 @@ function ComboCounter({
13047
13050
  className
13048
13051
  ),
13049
13052
  children: [
13050
- assetUrl && /* @__PURE__ */ jsxRuntime.jsx(
13051
- "img",
13052
- {
13053
- src: assetUrl.url,
13054
- alt: "combo",
13055
- width: 24,
13056
- height: 24,
13057
- style: { imageRendering: "pixelated", objectFit: "contain" },
13058
- className: "flex-shrink-0 mb-0.5"
13059
- }
13060
- ),
13061
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("font-black tabular-nums leading-none", sizes.combo, getComboIntensity(combo)), children: combo }),
13062
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("font-bold uppercase tracking-wider text-muted-foreground", sizes.label), children: "combo" }),
13063
- multiplier != null && multiplier > 1 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: cn("font-bold text-warning tabular-nums", sizes.multiplier), children: [
13053
+ assetUrl && /* @__PURE__ */ jsxRuntime.jsx(GameIcon, { assetUrl, icon: "image", size: 24, className: "flex-shrink-0 mb-0.5" }),
13054
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: cn("font-black tabular-nums leading-none", sizes.combo, getComboIntensity(combo)), children: combo }),
13055
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: cn("font-bold uppercase tracking-wider text-muted-foreground", sizes.label), children: "combo" }),
13056
+ multiplier != null && multiplier > 1 && /* @__PURE__ */ jsxRuntime.jsxs(Typography, { as: "span", className: cn("font-bold text-warning tabular-nums", sizes.multiplier), children: [
13064
13057
  "x",
13065
13058
  multiplier.toFixed(1)
13066
13059
  ] }),
13067
- streak != null && streak > 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: cn("text-muted-foreground tabular-nums", sizes.label), children: [
13060
+ streak != null && streak > 0 && /* @__PURE__ */ jsxRuntime.jsxs(Typography, { as: "span", className: cn("text-muted-foreground tabular-nums", sizes.label), children: [
13068
13061
  streak,
13069
13062
  " streak"
13070
13063
  ] })
@@ -13072,16 +13065,19 @@ function ComboCounter({
13072
13065
  }
13073
13066
  );
13074
13067
  }
13075
- var DEFAULT_ASSET_URL7, sizeMap8;
13068
+ var DEFAULT_ASSET_URL7, sizeMap9;
13076
13069
  var init_ComboCounter = __esm({
13077
13070
  "components/game/2d/atoms/ComboCounter.tsx"() {
13078
13071
  init_cn();
13072
+ init_Box();
13073
+ init_Typography();
13074
+ init_GameIcon();
13079
13075
  DEFAULT_ASSET_URL7 = {
13080
13076
  url: "https://almadar-kflow-assets.web.app/shared/effects/flash/flash00.png",
13081
13077
  role: "effect",
13082
13078
  category: "effect"
13083
13079
  };
13084
- sizeMap8 = {
13080
+ sizeMap9 = {
13085
13081
  sm: { combo: "text-lg", label: "text-xs", multiplier: "text-xs" },
13086
13082
  md: { combo: "text-2xl", label: "text-xs", multiplier: "text-sm" },
13087
13083
  lg: { combo: "text-4xl", label: "text-sm", multiplier: "text-base" }
@@ -13098,54 +13094,48 @@ function WaypointMarker({
13098
13094
  size = "md",
13099
13095
  className
13100
13096
  }) {
13101
- const sizes = sizeMap9[size];
13102
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex flex-col items-center", className), children: [
13103
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex items-center justify-center", children: [
13097
+ const sizes = sizeMap10[size];
13098
+ return /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: cn("flex flex-col items-center", className), children: [
13099
+ /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "relative flex items-center justify-center", children: [
13104
13100
  active && /* @__PURE__ */ jsxRuntime.jsx(
13105
- "div",
13101
+ Box,
13106
13102
  {
13103
+ position: "absolute",
13107
13104
  className: cn(
13108
- "absolute rounded-full border-2 border-info animate-ping opacity-50",
13105
+ "rounded-full border-2 border-info animate-ping opacity-50",
13109
13106
  sizes.ring
13110
13107
  )
13111
13108
  }
13112
13109
  ),
13113
13110
  active && /* @__PURE__ */ jsxRuntime.jsx(
13114
- "div",
13111
+ Box,
13115
13112
  {
13113
+ position: "absolute",
13116
13114
  className: cn(
13117
- "absolute rounded-full border-2 border-info",
13115
+ "rounded-full border-2 border-info",
13118
13116
  sizes.ring
13119
13117
  )
13120
13118
  }
13121
13119
  ),
13122
13120
  /* @__PURE__ */ jsxRuntime.jsx(
13123
- "div",
13121
+ Box,
13124
13122
  {
13123
+ position: "relative",
13125
13124
  className: cn(
13126
- "relative flex items-center justify-center rounded-full transition-all duration-200",
13125
+ "flex items-center justify-center rounded-full transition-all duration-200",
13127
13126
  sizes.dot,
13128
13127
  completed && "bg-success text-foreground",
13129
13128
  active && !completed && "bg-info text-foreground",
13130
13129
  !active && !completed && "bg-muted"
13131
13130
  ),
13132
- children: completed ? checkIcon : assetUrl ? /* @__PURE__ */ jsxRuntime.jsx(
13133
- "img",
13134
- {
13135
- src: assetUrl.url,
13136
- alt: label,
13137
- width: sizes.img,
13138
- height: sizes.img,
13139
- style: { imageRendering: "pixelated", objectFit: "contain" },
13140
- className: "flex-shrink-0"
13141
- }
13142
- ) : icon ? typeof icon === "string" ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: icon }) : /* @__PURE__ */ jsxRuntime.jsx(Icon, { icon }) : null
13131
+ 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
13143
13132
  }
13144
13133
  )
13145
13134
  ] }),
13146
13135
  label && /* @__PURE__ */ jsxRuntime.jsx(
13147
- "span",
13136
+ Typography,
13148
13137
  {
13138
+ as: "span",
13149
13139
  className: cn(
13150
13140
  "text-center whitespace-nowrap",
13151
13141
  sizes.label,
@@ -13156,17 +13146,20 @@ function WaypointMarker({
13156
13146
  )
13157
13147
  ] });
13158
13148
  }
13159
- var DEFAULT_ASSET_URL8, sizeMap9, checkIcon;
13149
+ var DEFAULT_ASSET_URL8, sizeMap10, checkIcon;
13160
13150
  var init_WaypointMarker = __esm({
13161
13151
  "components/game/2d/atoms/WaypointMarker.tsx"() {
13162
13152
  init_cn();
13163
13153
  init_Icon();
13154
+ init_Box();
13155
+ init_Typography();
13156
+ init_GameIcon();
13164
13157
  DEFAULT_ASSET_URL8 = {
13165
13158
  url: "https://almadar-kflow-assets.web.app/shared/world-map/battle_marker.png",
13166
13159
  role: "ui",
13167
13160
  category: "waypoint"
13168
13161
  };
13169
- sizeMap9 = {
13162
+ sizeMap10 = {
13170
13163
  sm: { dot: "w-4 h-4", ring: "w-6 h-6", label: "text-xs mt-1", img: 12 },
13171
13164
  md: { dot: "w-6 h-6", ring: "w-8 h-8", label: "text-sm mt-1.5", img: 18 },
13172
13165
  lg: { dot: "w-8 h-8", ring: "w-10 h-10", label: "text-base mt-2", img: 24 }
@@ -13191,32 +13184,24 @@ function StatusEffect({
13191
13184
  size = "md",
13192
13185
  className
13193
13186
  }) {
13194
- const sizes = sizeMap10[size];
13195
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("relative inline-flex flex-col items-center", className), children: [
13187
+ const sizes = sizeMap11[size];
13188
+ return /* @__PURE__ */ jsxRuntime.jsxs(Box, { position: "relative", className: cn("inline-flex flex-col items-center", className), children: [
13196
13189
  /* @__PURE__ */ jsxRuntime.jsxs(
13197
- "div",
13190
+ Box,
13198
13191
  {
13192
+ position: "relative",
13199
13193
  className: cn(
13200
- "relative flex items-center justify-center rounded-interactive border-2",
13194
+ "flex items-center justify-center rounded-interactive border-2",
13201
13195
  sizes.container,
13202
13196
  variantStyles7[variant]
13203
13197
  ),
13204
13198
  title: label,
13205
13199
  children: [
13206
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("flex items-center justify-center", sizes.icon), children: assetUrl ? /* @__PURE__ */ jsxRuntime.jsx(
13207
- "img",
13208
- {
13209
- src: assetUrl.url,
13210
- alt: label,
13211
- width: sizes.img,
13212
- height: sizes.img,
13213
- style: { imageRendering: "pixelated", objectFit: "contain" },
13214
- className: "flex-shrink-0"
13215
- }
13216
- ) : icon != null && typeof icon === "string" ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: icon, size: "sm" }) : icon != null ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { icon, size: "sm" }) : null }),
13200
+ /* @__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 }),
13217
13201
  duration !== void 0 && /* @__PURE__ */ jsxRuntime.jsx(
13218
- "span",
13202
+ Typography,
13219
13203
  {
13204
+ as: "span",
13220
13205
  className: cn(
13221
13206
  "absolute bottom-0 left-0 right-0 text-center font-mono font-bold text-foreground bg-background/60 leading-tight",
13222
13207
  sizes.timer
@@ -13228,8 +13213,9 @@ function StatusEffect({
13228
13213
  }
13229
13214
  ),
13230
13215
  stacks !== void 0 && stacks > 1 && /* @__PURE__ */ jsxRuntime.jsx(
13231
- "span",
13216
+ Typography,
13232
13217
  {
13218
+ as: "span",
13233
13219
  className: cn(
13234
13220
  "absolute flex items-center justify-center rounded-full bg-card text-foreground font-bold leading-none",
13235
13221
  sizes.badge
@@ -13237,20 +13223,23 @@ function StatusEffect({
13237
13223
  children: stacks
13238
13224
  }
13239
13225
  ),
13240
- label && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-muted-foreground mt-0.5 text-center whitespace-nowrap", children: label })
13226
+ label && /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "text-xs text-muted-foreground mt-0.5 text-center whitespace-nowrap", children: label })
13241
13227
  ] });
13242
13228
  }
13243
- var DEFAULT_ASSET_URL9, sizeMap10, variantStyles7;
13229
+ var DEFAULT_ASSET_URL9, sizeMap11, variantStyles7;
13244
13230
  var init_StatusEffect = __esm({
13245
13231
  "components/game/2d/atoms/StatusEffect.tsx"() {
13246
13232
  init_cn();
13247
13233
  init_Icon();
13234
+ init_Box();
13235
+ init_Typography();
13236
+ init_GameIcon();
13248
13237
  DEFAULT_ASSET_URL9 = {
13249
13238
  url: "https://almadar-kflow-assets.web.app/shared/effects/particles/flame_01.png",
13250
13239
  role: "ui",
13251
13240
  category: "effect"
13252
13241
  };
13253
- sizeMap10 = {
13242
+ sizeMap11 = {
13254
13243
  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 },
13255
13244
  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 },
13256
13245
  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 }
@@ -13274,38 +13263,31 @@ function DamageNumber({
13274
13263
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
13275
13264
  /* @__PURE__ */ jsxRuntime.jsx("style", { children: floatKeyframes }),
13276
13265
  /* @__PURE__ */ jsxRuntime.jsxs(
13277
- "span",
13266
+ Typography,
13278
13267
  {
13268
+ as: "span",
13279
13269
  className: cn(
13280
13270
  "inline-flex items-center gap-0.5 font-mono select-none pointer-events-none",
13281
- sizeMap11[size],
13271
+ sizeMap12[size],
13282
13272
  typeStyles[type],
13283
13273
  className
13284
13274
  ),
13285
13275
  style: { animation: "damageFloat 1s ease-out forwards" },
13286
13276
  children: [
13287
- assetUrl && /* @__PURE__ */ jsxRuntime.jsx(
13288
- "img",
13289
- {
13290
- src: assetUrl.url,
13291
- alt: "",
13292
- width: 14,
13293
- height: 14,
13294
- style: { imageRendering: "pixelated", objectFit: "contain" },
13295
- className: "flex-shrink-0"
13296
- }
13297
- ),
13277
+ assetUrl && /* @__PURE__ */ jsxRuntime.jsx(GameIcon, { assetUrl, icon: "image", size: 14, className: "flex-shrink-0" }),
13298
13278
  displayText
13299
13279
  ]
13300
13280
  }
13301
13281
  )
13302
13282
  ] });
13303
13283
  }
13304
- var sizeMap11, typeStyles, floatKeyframes, DEFAULT_ASSET_URL10;
13284
+ var sizeMap12, typeStyles, floatKeyframes, DEFAULT_ASSET_URL10;
13305
13285
  var init_DamageNumber = __esm({
13306
13286
  "components/game/2d/atoms/DamageNumber.tsx"() {
13307
13287
  init_cn();
13308
- sizeMap11 = {
13288
+ init_Typography();
13289
+ init_GameIcon();
13290
+ sizeMap12 = {
13309
13291
  sm: "text-sm",
13310
13292
  md: "text-lg",
13311
13293
  lg: "text-2xl"
@@ -13339,7 +13321,7 @@ function DialogueBubble({
13339
13321
  className
13340
13322
  }) {
13341
13323
  return /* @__PURE__ */ jsxRuntime.jsxs(
13342
- "div",
13324
+ Box,
13343
13325
  {
13344
13326
  className: cn(
13345
13327
  "flex items-start gap-3 rounded-container bg-background/80 backdrop-blur-sm px-4 py-3 border border-border/10",
@@ -13347,17 +13329,10 @@ function DialogueBubble({
13347
13329
  className
13348
13330
  ),
13349
13331
  children: [
13350
- 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(
13351
- "img",
13352
- {
13353
- src: portrait?.url,
13354
- alt: speaker ?? "speaker",
13355
- className: "w-full h-full object-cover"
13356
- }
13357
- ) }),
13358
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1 min-w-0", children: [
13359
- speaker && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-bold text-warning", children: speaker }),
13360
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-foreground leading-relaxed", children: text })
13332
+ 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" }) }),
13333
+ /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "flex flex-col gap-1 min-w-0", children: [
13334
+ speaker && /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "text-sm font-bold text-warning", children: speaker }),
13335
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "text-sm text-foreground leading-relaxed", children: text })
13361
13336
  ] })
13362
13337
  ]
13363
13338
  }
@@ -13367,6 +13342,9 @@ var DEFAULT_PORTRAIT;
13367
13342
  var init_DialogueBubble = __esm({
13368
13343
  "components/game/2d/atoms/DialogueBubble.tsx"() {
13369
13344
  init_cn();
13345
+ init_Box();
13346
+ init_Typography();
13347
+ init_GameIcon();
13370
13348
  DEFAULT_PORTRAIT = {
13371
13349
  url: "https://almadar-kflow-assets.web.app/shared/characters/archetypes/04_hero.png",
13372
13350
  role: "effect",
@@ -13388,11 +13366,11 @@ function ChoiceButton({
13388
13366
  }) {
13389
13367
  const eventBus = useEventBus();
13390
13368
  return /* @__PURE__ */ jsxRuntime.jsxs(
13391
- "button",
13369
+ Button,
13392
13370
  {
13393
- type: "button",
13371
+ variant: "ghost",
13394
13372
  disabled,
13395
- onClick: (e) => {
13373
+ onClick: () => {
13396
13374
  if (action) eventBus.emit(`UI:${action}`, {});
13397
13375
  onClick?.();
13398
13376
  },
@@ -13405,8 +13383,9 @@ function ChoiceButton({
13405
13383
  ),
13406
13384
  children: [
13407
13385
  index !== void 0 && /* @__PURE__ */ jsxRuntime.jsxs(
13408
- "span",
13386
+ Typography,
13409
13387
  {
13388
+ as: "span",
13410
13389
  className: cn(
13411
13390
  "flex-shrink-0 font-mono font-bold text-sm",
13412
13391
  selected ? "text-accent" : "text-muted-foreground"
@@ -13417,24 +13396,14 @@ function ChoiceButton({
13417
13396
  ]
13418
13397
  }
13419
13398
  ),
13420
- assetUrl ? /* @__PURE__ */ jsxRuntime.jsx(
13421
- "img",
13422
- {
13423
- src: assetUrl.url,
13424
- alt: "",
13425
- width: 16,
13426
- height: 16,
13427
- style: { imageRendering: "pixelated", objectFit: "contain" },
13428
- className: "flex-shrink-0"
13429
- }
13430
- ) : icon ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-shrink-0 text-sm", children: typeof icon === "string" ? (() => {
13399
+ 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" ? (() => {
13431
13400
  const I = resolveIcon(icon);
13432
13401
  return I ? /* @__PURE__ */ jsxRuntime.jsx(I, { className: "w-4 h-4" }) : null;
13433
13402
  })() : /* @__PURE__ */ (() => {
13434
13403
  const I = icon;
13435
13404
  return /* @__PURE__ */ jsxRuntime.jsx(I, { className: "w-4 h-4" });
13436
13405
  })() }) : null,
13437
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm leading-snug", children: text })
13406
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "text-sm leading-snug", children: text })
13438
13407
  ]
13439
13408
  }
13440
13409
  );
@@ -13444,6 +13413,10 @@ var init_ChoiceButton = __esm({
13444
13413
  init_cn();
13445
13414
  init_Icon();
13446
13415
  init_useEventBus();
13416
+ init_Button();
13417
+ init_Box();
13418
+ init_Typography();
13419
+ init_GameIcon();
13447
13420
  ChoiceButton.displayName = "ChoiceButton";
13448
13421
  }
13449
13422
  });
@@ -13461,16 +13434,16 @@ function ActionButton({
13461
13434
  className
13462
13435
  }) {
13463
13436
  const eventBus = useEventBus();
13464
- const sizes = sizeMap12[size];
13437
+ const sizes = sizeMap13[size];
13465
13438
  const onCooldown = cooldown > 0;
13466
13439
  const isDisabled = disabled || onCooldown;
13467
13440
  const cooldownDeg = Math.round(cooldown * 360);
13468
13441
  return /* @__PURE__ */ jsxRuntime.jsxs(
13469
- "button",
13442
+ Button,
13470
13443
  {
13471
- type: "button",
13444
+ variant: variant === "danger" ? "danger" : variant === "secondary" ? "secondary" : "primary",
13472
13445
  disabled: isDisabled,
13473
- onClick: (e) => {
13446
+ onClick: () => {
13474
13447
  if (action) eventBus.emit(`UI:${action}`, {});
13475
13448
  onClick?.();
13476
13449
  },
@@ -13483,9 +13456,10 @@ function ActionButton({
13483
13456
  ),
13484
13457
  children: [
13485
13458
  onCooldown && /* @__PURE__ */ jsxRuntime.jsx(
13486
- "div",
13459
+ Box,
13487
13460
  {
13488
- className: "absolute inset-0 bg-foreground/40 pointer-events-none",
13461
+ position: "absolute",
13462
+ className: "inset-0 bg-foreground/40 pointer-events-none",
13489
13463
  style: {
13490
13464
  clipPath: `conic-gradient(from 0deg, transparent ${360 - cooldownDeg}deg, black ${360 - cooldownDeg}deg)`,
13491
13465
  WebkitClipPath: `conic-gradient(from 0deg, transparent ${360 - cooldownDeg}deg, black ${360 - cooldownDeg}deg)`,
@@ -13493,27 +13467,18 @@ function ActionButton({
13493
13467
  }
13494
13468
  }
13495
13469
  ),
13496
- assetUrl ? /* @__PURE__ */ jsxRuntime.jsx(
13497
- "img",
13498
- {
13499
- src: assetUrl.url,
13500
- alt: "",
13501
- width: 16,
13502
- height: 16,
13503
- style: { imageRendering: "pixelated", objectFit: "contain" },
13504
- className: cn("flex-shrink-0", sizes.icon)
13505
- }
13506
- ) : icon ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("flex-shrink-0", sizes.icon), children: typeof icon === "string" ? (() => {
13470
+ 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" ? (() => {
13507
13471
  const I = resolveIcon(icon);
13508
13472
  return I ? /* @__PURE__ */ jsxRuntime.jsx(I, { className: "w-4 h-4" }) : null;
13509
13473
  })() : /* @__PURE__ */ (() => {
13510
13474
  const I = icon;
13511
13475
  return /* @__PURE__ */ jsxRuntime.jsx(I, { className: "w-4 h-4" });
13512
13476
  })() }) : null,
13513
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "relative z-10", children: label }),
13477
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "relative z-10", children: label }),
13514
13478
  hotkey && /* @__PURE__ */ jsxRuntime.jsx(
13515
- "span",
13479
+ Typography,
13516
13480
  {
13481
+ as: "span",
13517
13482
  className: cn(
13518
13483
  "absolute top-0.5 right-0.5 bg-foreground/30 text-primary-foreground rounded font-mono leading-tight",
13519
13484
  sizes.hotkey
@@ -13525,13 +13490,17 @@ function ActionButton({
13525
13490
  }
13526
13491
  );
13527
13492
  }
13528
- var sizeMap12, variantStyles8, DEFAULT_ASSET_URL11;
13493
+ var sizeMap13, variantStyles8, DEFAULT_ASSET_URL11;
13529
13494
  var init_ActionButton = __esm({
13530
13495
  "components/game/2d/atoms/ActionButton.tsx"() {
13531
13496
  init_cn();
13532
13497
  init_Icon();
13533
13498
  init_useEventBus();
13534
- sizeMap12 = {
13499
+ init_Button();
13500
+ init_Box();
13501
+ init_Typography();
13502
+ init_GameIcon();
13503
+ sizeMap13 = {
13535
13504
  sm: { button: "h-button-sm px-3 text-xs", hotkey: "text-[9px] px-1", icon: "text-xs" },
13536
13505
  md: { button: "h-button-md px-4 text-sm", hotkey: "text-xs px-1.5", icon: "text-sm" },
13537
13506
  lg: { button: "h-button-lg px-5 text-base", hotkey: "text-xs px-2", icon: "text-base" }
@@ -13633,10 +13602,12 @@ function MiniMap({
13633
13602
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
13634
13603
  /* @__PURE__ */ jsxRuntime.jsx("style", { children: `@keyframes minimap-blink{0%,49%{opacity:1}50%,100%{opacity:0}}` }),
13635
13604
  /* @__PURE__ */ jsxRuntime.jsxs(
13636
- "div",
13605
+ Box,
13637
13606
  {
13607
+ position: "relative",
13608
+ display: "inline-block",
13638
13609
  className: cn(
13639
- "relative inline-block border border-border/20 rounded-container",
13610
+ "border border-border/20 rounded-container",
13640
13611
  className
13641
13612
  ),
13642
13613
  children: [
@@ -13651,10 +13622,10 @@ function MiniMap({
13651
13622
  }
13652
13623
  ),
13653
13624
  playerLeft !== null && playerTop !== null && /* @__PURE__ */ jsxRuntime.jsx(
13654
- "div",
13625
+ Box,
13655
13626
  {
13627
+ position: "absolute",
13656
13628
  style: {
13657
- position: "absolute",
13658
13629
  left: playerLeft,
13659
13630
  top: playerTop,
13660
13631
  width: 3,
@@ -13675,6 +13646,7 @@ var init_MiniMap = __esm({
13675
13646
  "components/game/2d/atoms/MiniMap.tsx"() {
13676
13647
  "use client";
13677
13648
  init_cn();
13649
+ init_Box();
13678
13650
  DEFAULT_TILES = [
13679
13651
  { x: 10, y: 10, color: "#4ade80" },
13680
13652
  { x: 20, y: 15, color: "#4ade80" },
@@ -13692,38 +13664,6 @@ var init_MiniMap = __esm({
13692
13664
  MiniMap.displayName = "MiniMap";
13693
13665
  }
13694
13666
  });
13695
- function GameIcon({ assetUrl, icon, size = "md", alt, className }) {
13696
- const px = typeof size === "number" ? size : sizeMap13[size];
13697
- if (assetUrl?.url) {
13698
- return /* @__PURE__ */ jsxRuntime.jsx(
13699
- "img",
13700
- {
13701
- src: assetUrl.url,
13702
- alt: alt ?? assetUrl.category ?? "",
13703
- width: px,
13704
- height: px,
13705
- style: { imageRendering: "pixelated", objectFit: "contain", width: px, height: px },
13706
- className: cn("flex-shrink-0", className)
13707
- }
13708
- );
13709
- }
13710
- const I = typeof icon === "string" ? resolveIcon(icon) : icon;
13711
- return /* @__PURE__ */ jsxRuntime.jsx(I, { width: px, height: px, className: cn("flex-shrink-0", className) });
13712
- }
13713
- var sizeMap13;
13714
- var init_GameIcon = __esm({
13715
- "components/game/2d/atoms/GameIcon.tsx"() {
13716
- "use client";
13717
- init_cn();
13718
- init_Icon();
13719
- sizeMap13 = {
13720
- sm: 16,
13721
- md: 24,
13722
- lg: 32
13723
- };
13724
- GameIcon.displayName = "GameIcon";
13725
- }
13726
- });
13727
13667
  function ControlGrid({
13728
13668
  kind,
13729
13669
  buttons = DEFAULT_BUTTONS,
@@ -13784,22 +13724,22 @@ function ControlGrid({
13784
13724
  },
13785
13725
  d
13786
13726
  );
13787
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("inline-grid grid-cols-3", ds.gap, ds.container, className), children: [
13788
- /* @__PURE__ */ jsxRuntime.jsx("div", {}),
13727
+ return /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: cn("inline-grid grid-cols-3", ds.gap, ds.container, className), children: [
13728
+ /* @__PURE__ */ jsxRuntime.jsx(Box, {}),
13789
13729
  dir("up"),
13790
- /* @__PURE__ */ jsxRuntime.jsx("div", {}),
13730
+ /* @__PURE__ */ jsxRuntime.jsx(Box, {}),
13791
13731
  dir("left"),
13792
- /* @__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" }) }),
13732
+ /* @__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" }) }),
13793
13733
  dir("right"),
13794
- /* @__PURE__ */ jsxRuntime.jsx("div", {}),
13734
+ /* @__PURE__ */ jsxRuntime.jsx(Box, {}),
13795
13735
  dir("down"),
13796
- /* @__PURE__ */ jsxRuntime.jsx("div", {})
13736
+ /* @__PURE__ */ jsxRuntime.jsx(Box, {})
13797
13737
  ] });
13798
13738
  }
13799
13739
  if (layout === "diamond" && buttons.length === 4) {
13800
13740
  const [top, right, bottom, left] = buttons;
13801
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn(layoutClass.diamond, className), children: [
13802
- /* @__PURE__ */ jsxRuntime.jsx("div", {}),
13741
+ return /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: cn(layoutClass.diamond, className), children: [
13742
+ /* @__PURE__ */ jsxRuntime.jsx(Box, {}),
13803
13743
  /* @__PURE__ */ jsxRuntime.jsx(
13804
13744
  ControlButton,
13805
13745
  {
@@ -13814,7 +13754,7 @@ function ControlGrid({
13814
13754
  disabled
13815
13755
  }
13816
13756
  ),
13817
- /* @__PURE__ */ jsxRuntime.jsx("div", {}),
13757
+ /* @__PURE__ */ jsxRuntime.jsx(Box, {}),
13818
13758
  /* @__PURE__ */ jsxRuntime.jsx(
13819
13759
  ControlButton,
13820
13760
  {
@@ -13829,7 +13769,7 @@ function ControlGrid({
13829
13769
  disabled
13830
13770
  }
13831
13771
  ),
13832
- /* @__PURE__ */ jsxRuntime.jsx("div", {}),
13772
+ /* @__PURE__ */ jsxRuntime.jsx(Box, {}),
13833
13773
  /* @__PURE__ */ jsxRuntime.jsx(
13834
13774
  ControlButton,
13835
13775
  {
@@ -13844,7 +13784,7 @@ function ControlGrid({
13844
13784
  disabled
13845
13785
  }
13846
13786
  ),
13847
- /* @__PURE__ */ jsxRuntime.jsx("div", {}),
13787
+ /* @__PURE__ */ jsxRuntime.jsx(Box, {}),
13848
13788
  /* @__PURE__ */ jsxRuntime.jsx(
13849
13789
  ControlButton,
13850
13790
  {
@@ -13859,10 +13799,10 @@ function ControlGrid({
13859
13799
  disabled
13860
13800
  }
13861
13801
  ),
13862
- /* @__PURE__ */ jsxRuntime.jsx("div", {})
13802
+ /* @__PURE__ */ jsxRuntime.jsx(Box, {})
13863
13803
  ] });
13864
13804
  }
13865
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn(layoutClass[layout], className), children: buttons.map((button) => /* @__PURE__ */ jsxRuntime.jsx(
13805
+ return /* @__PURE__ */ jsxRuntime.jsx(Box, { className: cn(layoutClass[layout], className), children: buttons.map((button) => /* @__PURE__ */ jsxRuntime.jsx(
13866
13806
  ControlButton,
13867
13807
  {
13868
13808
  icon: button.icon,
@@ -13884,6 +13824,7 @@ var init_ControlGrid = __esm({
13884
13824
  "use client";
13885
13825
  init_cn();
13886
13826
  init_useEventBus();
13827
+ init_Box();
13887
13828
  init_ControlButton();
13888
13829
  sizeKey = { sm: "sm", md: "md", lg: "lg" };
13889
13830
  layoutClass = {
@@ -13928,7 +13869,7 @@ function StatBadge({
13928
13869
  const numValue = typeof value === "number" ? value : parseInt(String(value), 10) || 0;
13929
13870
  const resolvedAsset = iconUrl ?? assetUrl;
13930
13871
  return /* @__PURE__ */ jsxRuntime.jsxs(
13931
- "div",
13872
+ Box,
13932
13873
  {
13933
13874
  className: cn(
13934
13875
  "inline-flex items-center gap-2 rounded-container border backdrop-blur-sm",
@@ -13937,18 +13878,8 @@ function StatBadge({
13937
13878
  className
13938
13879
  ),
13939
13880
  children: [
13940
- resolvedAsset ? /* @__PURE__ */ jsxRuntime.jsx(
13941
- "img",
13942
- {
13943
- src: resolvedAsset.url,
13944
- alt: "",
13945
- width: 16,
13946
- height: 16,
13947
- style: { imageRendering: "pixelated", objectFit: "contain" },
13948
- className: "flex-shrink-0"
13949
- }
13950
- ) : 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,
13951
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground font-medium", children: label }),
13881
+ 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,
13882
+ /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "text-muted-foreground font-medium", children: label }),
13952
13883
  format === "hearts" && max && /* @__PURE__ */ jsxRuntime.jsx(
13953
13884
  HealthBar,
13954
13885
  {
@@ -13974,7 +13905,7 @@ function StatBadge({
13974
13905
  size: size === "lg" ? "md" : "sm"
13975
13906
  }
13976
13907
  ),
13977
- format === "text" && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-bold text-foreground", children: value })
13908
+ format === "text" && /* @__PURE__ */ jsxRuntime.jsx(Typography, { as: "span", className: "font-bold text-foreground", children: value })
13978
13909
  ]
13979
13910
  }
13980
13911
  );
@@ -13984,6 +13915,9 @@ var init_StatBadge = __esm({
13984
13915
  "components/game/2d/molecules/StatBadge.tsx"() {
13985
13916
  init_cn();
13986
13917
  init_Icon();
13918
+ init_Box();
13919
+ init_Typography();
13920
+ init_GameIcon();
13987
13921
  init_HealthBar();
13988
13922
  init_ScoreDisplay();
13989
13923
  sizeMap14 = {
@@ -14161,9 +14095,9 @@ function GameHud({
14161
14095
  if (position === "corners") {
14162
14096
  const leftStats = stats.slice(0, Math.ceil(stats.length / 2));
14163
14097
  const rightStats = stats.slice(Math.ceil(stats.length / 2));
14164
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("relative", positionMap[position], className), children: [
14165
- /* @__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)) }),
14166
- /* @__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)) })
14098
+ return /* @__PURE__ */ jsxRuntime.jsxs(Box, { position: "relative", className: cn(positionMap[position], className), children: [
14099
+ /* @__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)) }),
14100
+ /* @__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)) })
14167
14101
  ] });
14168
14102
  }
14169
14103
  if (position === "top" || position === "bottom") {
@@ -14172,7 +14106,7 @@ function GameHud({
14172
14106
  const rightStats = stats.slice(mid);
14173
14107
  const isTop = position === "top";
14174
14108
  return /* @__PURE__ */ jsxRuntime.jsxs(
14175
- "div",
14109
+ Box,
14176
14110
  {
14177
14111
  className: cn(
14178
14112
  "flex items-center justify-between w-full",
@@ -14182,17 +14116,18 @@ function GameHud({
14182
14116
  className
14183
14117
  ),
14184
14118
  children: [
14185
- /* @__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)) }),
14186
- 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)) })
14119
+ /* @__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)) }),
14120
+ 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)) })
14187
14121
  ]
14188
14122
  }
14189
14123
  );
14190
14124
  }
14191
14125
  return /* @__PURE__ */ jsxRuntime.jsx(
14192
- "div",
14126
+ Box,
14193
14127
  {
14128
+ position: "relative",
14194
14129
  className: cn(
14195
- "relative z-10 flex items-center gap-4 px-4 py-2",
14130
+ "z-10 flex items-center gap-4 px-4 py-2",
14196
14131
  transparent ? "bg-black/30 backdrop-blur-sm" : "bg-surface/90 backdrop-blur-sm",
14197
14132
  className
14198
14133
  ),
@@ -14204,6 +14139,7 @@ var positionMap, DEFAULT_HUD_STATS;
14204
14139
  var init_GameHud = __esm({
14205
14140
  "components/game/2d/molecules/GameHud.tsx"() {
14206
14141
  init_cn();
14142
+ init_Box();
14207
14143
  init_StatBadge();
14208
14144
  positionMap = {
14209
14145
  corners: "inset-0 pointer-events-none"
@@ -14244,7 +14180,7 @@ function GameMenu({
14244
14180
  [eventBus, onSelect]
14245
14181
  );
14246
14182
  return /* @__PURE__ */ jsxRuntime.jsxs(
14247
- "div",
14183
+ Box,
14248
14184
  {
14249
14185
  className: cn(
14250
14186
  "min-h-screen w-full flex flex-col items-center justify-center p-8",
@@ -14254,18 +14190,12 @@ function GameMenu({
14254
14190
  background: background ?? "linear-gradient(135deg, #1a1a2e 0%, #16213e 50%, #0f0e17 100%)"
14255
14191
  },
14256
14192
  children: [
14257
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center mb-12 animate-fade-in", children: [
14258
- logo && /* @__PURE__ */ jsxRuntime.jsx(
14259
- "img",
14260
- {
14261
- src: logo.url,
14262
- alt: title,
14263
- className: "h-24 w-auto mx-auto mb-6 drop-shadow-2xl"
14264
- }
14265
- ),
14193
+ /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "text-center mb-12 animate-fade-in", children: [
14194
+ 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" }),
14266
14195
  /* @__PURE__ */ jsxRuntime.jsx(
14267
- "h1",
14196
+ Typography,
14268
14197
  {
14198
+ variant: "h1",
14269
14199
  className: "text-5xl md:text-7xl font-bold text-[var(--color-foreground)] tracking-tight",
14270
14200
  style: {
14271
14201
  textShadow: "0 4px 12px rgba(0,0,0,0.5)"
@@ -14273,9 +14203,9 @@ function GameMenu({
14273
14203
  children: title
14274
14204
  }
14275
14205
  ),
14276
- subtitle && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-2 text-lg text-muted-foreground tracking-widest uppercase", children: subtitle })
14206
+ subtitle && /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "body", className: "mt-2 text-lg text-muted-foreground tracking-widest uppercase", children: subtitle })
14277
14207
  ] }),
14278
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-4 w-full max-w-md", children: resolvedOptions.map((option, index) => /* @__PURE__ */ jsxRuntime.jsx(
14208
+ /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "flex flex-col gap-4 w-full max-w-md", children: resolvedOptions.map((option, index) => /* @__PURE__ */ jsxRuntime.jsx(
14279
14209
  ChoiceButton,
14280
14210
  {
14281
14211
  text: option.label,
@@ -14286,9 +14216,9 @@ function GameMenu({
14286
14216
  },
14287
14217
  index
14288
14218
  )) }),
14289
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "absolute inset-0 pointer-events-none overflow-hidden", children: [
14290
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute top-1/4 left-1/4 w-64 h-64 bg-info/10 rounded-container blur-3xl" }),
14291
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute bottom-1/4 right-1/4 w-96 h-96 bg-accent/10 rounded-container blur-3xl" })
14219
+ /* @__PURE__ */ jsxRuntime.jsxs(Box, { position: "absolute", className: "inset-0 pointer-events-none overflow-hidden", children: [
14220
+ /* @__PURE__ */ jsxRuntime.jsx(Box, { position: "absolute", className: "top-1/4 left-1/4 w-64 h-64 bg-info/10 rounded-container blur-3xl" }),
14221
+ /* @__PURE__ */ jsxRuntime.jsx(Box, { position: "absolute", className: "bottom-1/4 right-1/4 w-96 h-96 bg-accent/10 rounded-container blur-3xl" })
14292
14222
  ] })
14293
14223
  ]
14294
14224
  }
@@ -14300,6 +14230,9 @@ var init_GameMenu = __esm({
14300
14230
  "use client";
14301
14231
  init_cn();
14302
14232
  init_useEventBus();
14233
+ init_Box();
14234
+ init_Typography();
14235
+ init_GameIcon();
14303
14236
  init_ChoiceButton();
14304
14237
  DEFAULT_MENU_OPTIONS = [
14305
14238
  { label: "New Game", event: "NEW_GAME", variant: "primary" },
@@ -15719,10 +15652,11 @@ function Canvas2D({
15719
15652
  }
15720
15653
  }
15721
15654
  ),
15722
- process.env.NODE_ENV !== "production" && /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-game-actions": "", className: "sr-only", "aria-hidden": "true", children: [
15655
+ process.env.NODE_ENV !== "production" && /* @__PURE__ */ jsxRuntime.jsxs(Box, { "data-game-actions": "", className: "sr-only", "aria-hidden": "true", children: [
15723
15656
  tileClickEvent && /* @__PURE__ */ jsxRuntime.jsx(
15724
- "button",
15657
+ Button,
15725
15658
  {
15659
+ variant: "ghost",
15726
15660
  "data-event": tileClickEvent,
15727
15661
  "data-x": "0",
15728
15662
  "data-y": "0",
@@ -15731,8 +15665,9 @@ function Canvas2D({
15731
15665
  }
15732
15666
  ),
15733
15667
  unitClickEvent && units && units.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
15734
- "button",
15668
+ Button,
15735
15669
  {
15670
+ variant: "ghost",
15736
15671
  "data-event": unitClickEvent,
15737
15672
  "data-unit-id": units[0].id,
15738
15673
  onClick: () => eventBus.emit(`UI:${unitClickEvent}`, { unitId: units[0].id }),
@@ -15741,15 +15676,17 @@ function Canvas2D({
15741
15676
  )
15742
15677
  ] }),
15743
15678
  unitOverlays.map(({ unit, screenX, screenY }) => /* @__PURE__ */ jsxRuntime.jsxs(
15744
- "div",
15679
+ Box,
15745
15680
  {
15746
- className: "absolute pointer-events-none",
15681
+ position: "absolute",
15682
+ className: "pointer-events-none",
15747
15683
  style: { left: Math.round(screenX), top: Math.round(screenY), transform: "translate(-50%, 0)", zIndex: 5 },
15748
15684
  children: [
15749
15685
  unit.name && /* @__PURE__ */ jsxRuntime.jsx(
15750
- "div",
15686
+ Typography,
15751
15687
  {
15752
- className: "text-white text-xs font-bold px-1.5 py-0.5 rounded mb-0.5 whitespace-nowrap",
15688
+ as: "span",
15689
+ className: "text-white text-xs font-bold px-1.5 py-0.5 rounded mb-0.5 whitespace-nowrap block",
15753
15690
  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)" },
15754
15691
  children: unit.name
15755
15692
  }
@@ -15759,7 +15696,7 @@ function Canvas2D({
15759
15696
  },
15760
15697
  unit.id
15761
15698
  )),
15762
- showMinimap && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute bottom-2 right-2 pointer-events-none", style: { zIndex: 10 }, children: /* @__PURE__ */ jsxRuntime.jsx(
15699
+ showMinimap && /* @__PURE__ */ jsxRuntime.jsx(Box, { position: "absolute", className: "bottom-2 right-2 pointer-events-none", style: { zIndex: 10 }, children: /* @__PURE__ */ jsxRuntime.jsx(
15763
15700
  MiniMap,
15764
15701
  {
15765
15702
  tiles: miniMapTiles,
@@ -15781,6 +15718,7 @@ var init_Canvas2D = __esm({
15781
15718
  init_cn();
15782
15719
  init_useEventBus();
15783
15720
  init_Box();
15721
+ init_Button();
15784
15722
  init_Stack();
15785
15723
  init_Icon();
15786
15724
  init_Typography();
@@ -16112,7 +16050,7 @@ function GameAudioToggle({
16112
16050
  onClick: handleToggle,
16113
16051
  className: cn("text-lg leading-none px-2", className),
16114
16052
  "aria-pressed": muted,
16115
- 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}"
16053
+ 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}"
16116
16054
  }
16117
16055
  );
16118
16056
  }
@@ -16122,6 +16060,7 @@ var init_GameAudioToggle = __esm({
16122
16060
  init_atoms();
16123
16061
  init_cn();
16124
16062
  init_GameAudioProvider();
16063
+ init_GameIcon();
16125
16064
  GameAudioToggle.displayName = "GameAudioToggle";
16126
16065
  }
16127
16066
  });
@@ -25882,7 +25821,7 @@ var init_Tabs = __esm({
25882
25821
  isActive ? variant === "pills" ? "text-primary-foreground font-bold" : "text-foreground font-bold" : "text-muted-foreground hover:text-foreground"
25883
25822
  ),
25884
25823
  children: [
25885
- item.icon && (typeof item.icon === "string" ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: item.icon, size: "sm" }) : /* @__PURE__ */ jsxRuntime.jsx(Icon, { icon: item.icon, size: "sm" })),
25824
+ 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" })),
25886
25825
  /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "small", weight: isActive ? "semibold" : "normal", className: "!text-inherit", children: item.label }),
25887
25826
  item.badge !== void 0 && /* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: "default", size: "sm", children: item.badge })
25888
25827
  ]