@almadar/ui 5.81.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
  {
@@ -12193,6 +12196,7 @@ function GameCard({
12193
12196
  id,
12194
12197
  cost,
12195
12198
  art,
12199
+ frameAsset,
12196
12200
  attack,
12197
12201
  defense,
12198
12202
  name,
@@ -12210,6 +12214,7 @@ function GameCard({
12210
12214
  if (clickEvent) eventBus.emit(`UI:${clickEvent}`, { cardId: id });
12211
12215
  }, [disabled, id, onClick, clickEvent, eventBus]);
12212
12216
  const artPx = artPxMap[size];
12217
+ const frameStyle = frameAsset?.url ? { backgroundImage: `url(${frameAsset.url})`, backgroundSize: "100% 100%", backgroundRepeat: "no-repeat" } : {};
12213
12218
  return /* @__PURE__ */ jsxRuntime.jsxs(
12214
12219
  Button,
12215
12220
  {
@@ -12217,9 +12222,11 @@ function GameCard({
12217
12222
  onClick: handleClick,
12218
12223
  disabled,
12219
12224
  title: name,
12225
+ style: frameStyle,
12220
12226
  className: cn(
12221
- "relative flex flex-col items-center rounded-interactive border-2",
12227
+ "relative flex flex-col items-center rounded-interactive",
12222
12228
  "bg-card/90 px-1.5 pt-1.5 pb-1 transition-all duration-150",
12229
+ frameAsset?.url ? "border-0" : "border-2",
12223
12230
  cardSizeMap[size],
12224
12231
  disabled ? "border-border opacity-50 cursor-not-allowed" : "border-accent hover:brightness-125 hover:-translate-y-1 cursor-pointer",
12225
12232
  selected && "ring-2 ring-foreground ring-offset-1 ring-offset-background -translate-y-1",
@@ -25814,7 +25821,7 @@ var init_Tabs = __esm({
25814
25821
  isActive ? variant === "pills" ? "text-primary-foreground font-bold" : "text-foreground font-bold" : "text-muted-foreground hover:text-foreground"
25815
25822
  ),
25816
25823
  children: [
25817
- 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" })),
25818
25825
  /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "small", weight: isActive ? "semibold" : "normal", className: "!text-inherit", children: item.label }),
25819
25826
  item.badge !== void 0 && /* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: "default", size: "sm", children: item.badge })
25820
25827
  ]
package/dist/avl/index.js CHANGED
@@ -5384,6 +5384,7 @@ var init_Button = __esm({
5384
5384
  rightIcon,
5385
5385
  icon: iconProp,
5386
5386
  iconRight: iconRightProp,
5387
+ iconAsset,
5387
5388
  action,
5388
5389
  actionPayload,
5389
5390
  label,
@@ -5395,7 +5396,8 @@ var init_Button = __esm({
5395
5396
  const eventBus = useEventBus();
5396
5397
  const leftIconValue = leftIcon || iconProp;
5397
5398
  const rightIconValue = rightIcon || iconRightProp;
5398
- const resolvedLeftIcon = resolveIconProp(leftIconValue, iconSizeStyles[size]);
5399
+ const px = size === "sm" ? 16 : size === "lg" ? 20 : 16;
5400
+ const resolvedLeftIcon = iconAsset?.url ? /* @__PURE__ */ 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]);
5399
5401
  const resolvedRightIcon = resolveIconProp(rightIconValue, iconSizeStyles[size]);
5400
5402
  const handleClick = (e) => {
5401
5403
  if (action) {
@@ -5935,13 +5937,14 @@ var init_Badge = __esm({
5935
5937
  lg: "px-3 py-1.5 text-base"
5936
5938
  };
5937
5939
  Badge = React112__default.forwardRef(
5938
- ({ className, variant = "default", size = "sm", amount, label, icon, children, onRemove, removeLabel, ...props }, ref) => {
5940
+ ({ className, variant = "default", size = "sm", amount, label, icon, iconAsset, children, onRemove, removeLabel, ...props }, ref) => {
5939
5941
  const iconSizes3 = {
5940
5942
  sm: "h-icon-default w-icon-default",
5941
5943
  md: "h-icon-default w-icon-default",
5942
5944
  lg: "h-icon-default w-icon-default"
5943
5945
  };
5944
- const resolvedIcon = typeof icon === "string" ? /* @__PURE__ */ jsx(Icon, { name: icon, className: iconSizes3[size] }) : icon ? /* @__PURE__ */ jsx(Icon, { icon, className: iconSizes3[size] }) : null;
5946
+ const iconPx = size === "lg" ? 20 : 16;
5947
+ const resolvedIcon = iconAsset?.url ? /* @__PURE__ */ 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__ */ jsx(Icon, { name: icon, className: iconSizes3[size] }) : icon ? /* @__PURE__ */ jsx(Icon, { icon, className: iconSizes3[size] }) : null;
5945
5948
  return /* @__PURE__ */ jsxs(
5946
5949
  "span",
5947
5950
  {
@@ -12147,6 +12150,7 @@ function GameCard({
12147
12150
  id,
12148
12151
  cost,
12149
12152
  art,
12153
+ frameAsset,
12150
12154
  attack,
12151
12155
  defense,
12152
12156
  name,
@@ -12164,6 +12168,7 @@ function GameCard({
12164
12168
  if (clickEvent) eventBus.emit(`UI:${clickEvent}`, { cardId: id });
12165
12169
  }, [disabled, id, onClick, clickEvent, eventBus]);
12166
12170
  const artPx = artPxMap[size];
12171
+ const frameStyle = frameAsset?.url ? { backgroundImage: `url(${frameAsset.url})`, backgroundSize: "100% 100%", backgroundRepeat: "no-repeat" } : {};
12167
12172
  return /* @__PURE__ */ jsxs(
12168
12173
  Button,
12169
12174
  {
@@ -12171,9 +12176,11 @@ function GameCard({
12171
12176
  onClick: handleClick,
12172
12177
  disabled,
12173
12178
  title: name,
12179
+ style: frameStyle,
12174
12180
  className: cn(
12175
- "relative flex flex-col items-center rounded-interactive border-2",
12181
+ "relative flex flex-col items-center rounded-interactive",
12176
12182
  "bg-card/90 px-1.5 pt-1.5 pb-1 transition-all duration-150",
12183
+ frameAsset?.url ? "border-0" : "border-2",
12177
12184
  cardSizeMap[size],
12178
12185
  disabled ? "border-border opacity-50 cursor-not-allowed" : "border-accent hover:brightness-125 hover:-translate-y-1 cursor-pointer",
12179
12186
  selected && "ring-2 ring-foreground ring-offset-1 ring-offset-background -translate-y-1",
@@ -25768,7 +25775,7 @@ var init_Tabs = __esm({
25768
25775
  isActive ? variant === "pills" ? "text-primary-foreground font-bold" : "text-foreground font-bold" : "text-muted-foreground hover:text-foreground"
25769
25776
  ),
25770
25777
  children: [
25771
- item.icon && (typeof item.icon === "string" ? /* @__PURE__ */ jsx(Icon, { name: item.icon, size: "sm" }) : /* @__PURE__ */ jsx(Icon, { icon: item.icon, size: "sm" })),
25778
+ item.iconAsset?.url ? /* @__PURE__ */ 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__ */ jsx(Icon, { name: item.icon, size: "sm" }) : /* @__PURE__ */ jsx(Icon, { icon: item.icon, size: "sm" })),
25772
25779
  /* @__PURE__ */ jsx(Typography, { variant: "small", weight: isActive ? "semibold" : "normal", className: "!text-inherit", children: item.label }),
25773
25780
  item.badge !== void 0 && /* @__PURE__ */ jsx(Badge, { variant: "default", size: "sm", children: item.badge })
25774
25781
  ]
@@ -1,5 +1,6 @@
1
1
  import React from "react";
2
2
  import { type IconInput } from "./Icon";
3
+ import type { Asset } from "@almadar/core";
3
4
  export type BadgeVariant = "default" | "primary" | "secondary" | "success" | "warning" | "danger" | "error" | "info" | "neutral";
4
5
  export type BadgeSize = "sm" | "md" | "lg";
5
6
  export interface BadgeProps extends React.HTMLAttributes<HTMLSpanElement> {
@@ -15,6 +16,8 @@ export interface BadgeProps extends React.HTMLAttributes<HTMLSpanElement> {
15
16
  label?: string | number;
16
17
  /** Lucide icon component or canonical kebab-case icon name string */
17
18
  icon?: IconInput;
19
+ /** Asset image rendered as the badge icon; takes precedence over icon when provided. */
20
+ iconAsset?: Asset;
18
21
  /** When set, renders a small X button on the right of the badge that
19
22
  * invokes this handler — turns the badge into a removable chip.
20
23
  * Used by the TagInput molecule and other "list of removable values"
@@ -1,5 +1,5 @@
1
1
  import React from "react";
2
- import type { EventKey, EventPayload } from "@almadar/core";
2
+ import type { Asset, EventKey, EventPayload } from "@almadar/core";
3
3
  import { type IconInput } from "./Icon";
4
4
  export type ButtonVariant = "primary" | "secondary" | "ghost" | "danger" | "success" | "warning" | "default";
5
5
  export type ButtonSize = "sm" | "md" | "lg";
@@ -17,6 +17,8 @@ export interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElemen
17
17
  icon?: IconInput;
18
18
  /** Alias for rightIcon */
19
19
  iconRight?: IconInput;
20
+ /** Asset image rendered as the leading icon; takes precedence over icon/leftIcon when provided. */
21
+ iconAsset?: Asset;
20
22
  /** Declarative event name — emits UI:{action} via eventBus on click */
21
23
  action?: EventKey;
22
24
  /** Payload to include with the action event */
@@ -5,7 +5,7 @@
5
5
  * Uses theme-aware CSS variables for styling.
6
6
  */
7
7
  import React from 'react';
8
- import type { EventEmit } from '@almadar/core';
8
+ import type { Asset, EventEmit } from '@almadar/core';
9
9
  import type { IconInput } from '../atoms/index';
10
10
  export interface TabItem {
11
11
  /**
@@ -24,6 +24,8 @@ export interface TabItem {
24
24
  content?: React.ReactNode;
25
25
  /** Tab icon — pass either a Lucide component or its registry name (e.g. "file-text") */
26
26
  icon?: IconInput;
27
+ /** Asset image rendered as the tab icon; takes precedence over icon when provided. */
28
+ iconAsset?: Asset;
27
29
  /** Tab badge */
28
30
  badge?: string | number;
29
31
  /** Disable tab */
@@ -5,6 +5,8 @@ export interface GameCardProps {
5
5
  cost?: number;
6
6
  /** Card art asset */
7
7
  art?: Asset;
8
+ /** Asset rendered as the card border/frame via backgroundImage; falls back to CSS border styling when absent. */
9
+ frameAsset?: Asset;
8
10
  attack?: number;
9
11
  defense?: number;
10
12
  name?: string;
@@ -20,7 +22,7 @@ export interface GameCardProps {
20
22
  }>;
21
23
  className?: string;
22
24
  }
23
- export declare function GameCard({ id, cost, art, attack, defense, name, selected, disabled, size, onClick, clickEvent, className, }: GameCardProps): React.JSX.Element;
25
+ export declare function GameCard({ id, cost, art, frameAsset, attack, defense, name, selected, disabled, size, onClick, clickEvent, className, }: GameCardProps): React.JSX.Element;
24
26
  export declare namespace GameCard {
25
27
  var displayName: string;
26
28
  }
@@ -3196,6 +3196,7 @@ var Button = React6__default.default.forwardRef(
3196
3196
  rightIcon,
3197
3197
  icon: iconProp,
3198
3198
  iconRight: iconRightProp,
3199
+ iconAsset,
3199
3200
  action,
3200
3201
  actionPayload,
3201
3202
  label,
@@ -3207,7 +3208,8 @@ var Button = React6__default.default.forwardRef(
3207
3208
  const eventBus = useEventBus();
3208
3209
  const leftIconValue = leftIcon || iconProp;
3209
3210
  const rightIconValue = rightIcon || iconRightProp;
3210
- const resolvedLeftIcon = resolveIconProp(leftIconValue, iconSizeStyles[size]);
3211
+ const px = size === "sm" ? 16 : size === "lg" ? 20 : 16;
3212
+ 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]);
3211
3213
  const resolvedRightIcon = resolveIconProp(rightIconValue, iconSizeStyles[size]);
3212
3214
  const handleClick = (e) => {
3213
3215
  if (action) {
@@ -3172,6 +3172,7 @@ var Button = React6.forwardRef(
3172
3172
  rightIcon,
3173
3173
  icon: iconProp,
3174
3174
  iconRight: iconRightProp,
3175
+ iconAsset,
3175
3176
  action,
3176
3177
  actionPayload,
3177
3178
  label,
@@ -3183,7 +3184,8 @@ var Button = React6.forwardRef(
3183
3184
  const eventBus = useEventBus();
3184
3185
  const leftIconValue = leftIcon || iconProp;
3185
3186
  const rightIconValue = rightIcon || iconRightProp;
3186
- const resolvedLeftIcon = resolveIconProp(leftIconValue, iconSizeStyles[size]);
3187
+ const px = size === "sm" ? 16 : size === "lg" ? 20 : 16;
3188
+ const resolvedLeftIcon = iconAsset?.url ? /* @__PURE__ */ 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]);
3187
3189
  const resolvedRightIcon = resolveIconProp(rightIconValue, iconSizeStyles[size]);
3188
3190
  const handleClick = (e) => {
3189
3191
  if (action) {
@@ -2168,6 +2168,7 @@ var init_Button = __esm({
2168
2168
  rightIcon,
2169
2169
  icon: iconProp,
2170
2170
  iconRight: iconRightProp,
2171
+ iconAsset,
2171
2172
  action,
2172
2173
  actionPayload,
2173
2174
  label,
@@ -2179,7 +2180,8 @@ var init_Button = __esm({
2179
2180
  const eventBus = useEventBus();
2180
2181
  const leftIconValue = leftIcon || iconProp;
2181
2182
  const rightIconValue = rightIcon || iconRightProp;
2182
- const resolvedLeftIcon = resolveIconProp(leftIconValue, iconSizeStyles[size]);
2183
+ const px = size === "sm" ? 16 : size === "lg" ? 20 : 16;
2184
+ 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]);
2183
2185
  const resolvedRightIcon = resolveIconProp(rightIconValue, iconSizeStyles[size]);
2184
2186
  const handleClick = (e) => {
2185
2187
  if (action) {
@@ -2933,13 +2935,14 @@ var init_Badge = __esm({
2933
2935
  lg: "px-3 py-1.5 text-base"
2934
2936
  };
2935
2937
  exports.Badge = React79__namespace.default.forwardRef(
2936
- ({ className, variant = "default", size = "sm", amount, label, icon, children, onRemove, removeLabel, ...props }, ref) => {
2938
+ ({ className, variant = "default", size = "sm", amount, label, icon, iconAsset, children, onRemove, removeLabel, ...props }, ref) => {
2937
2939
  const iconSizes3 = {
2938
2940
  sm: "h-icon-default w-icon-default",
2939
2941
  md: "h-icon-default w-icon-default",
2940
2942
  lg: "h-icon-default w-icon-default"
2941
2943
  };
2942
- const resolvedIcon = typeof icon === "string" ? /* @__PURE__ */ jsxRuntime.jsx(exports.Icon, { name: icon, className: iconSizes3[size] }) : icon ? /* @__PURE__ */ jsxRuntime.jsx(exports.Icon, { icon, className: iconSizes3[size] }) : null;
2944
+ const iconPx = size === "lg" ? 20 : 16;
2945
+ 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(exports.Icon, { name: icon, className: iconSizes3[size] }) : icon ? /* @__PURE__ */ jsxRuntime.jsx(exports.Icon, { icon, className: iconSizes3[size] }) : null;
2943
2946
  return /* @__PURE__ */ jsxRuntime.jsxs(
2944
2947
  "span",
2945
2948
  {
@@ -12899,7 +12902,7 @@ var init_Tabs = __esm({
12899
12902
  isActive ? variant === "pills" ? "text-primary-foreground font-bold" : "text-foreground font-bold" : "text-muted-foreground hover:text-foreground"
12900
12903
  ),
12901
12904
  children: [
12902
- item.icon && (typeof item.icon === "string" ? /* @__PURE__ */ jsxRuntime.jsx(exports.Icon, { name: item.icon, size: "sm" }) : /* @__PURE__ */ jsxRuntime.jsx(exports.Icon, { icon: item.icon, size: "sm" })),
12905
+ 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(exports.Icon, { name: item.icon, size: "sm" }) : /* @__PURE__ */ jsxRuntime.jsx(exports.Icon, { icon: item.icon, size: "sm" })),
12903
12906
  /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "small", weight: isActive ? "semibold" : "normal", className: "!text-inherit", children: item.label }),
12904
12907
  item.badge !== void 0 && /* @__PURE__ */ jsxRuntime.jsx(exports.Badge, { variant: "default", size: "sm", children: item.badge })
12905
12908
  ]
@@ -19059,6 +19062,7 @@ function GameCard({
19059
19062
  id,
19060
19063
  cost,
19061
19064
  art,
19065
+ frameAsset,
19062
19066
  attack,
19063
19067
  defense,
19064
19068
  name,
@@ -19076,6 +19080,7 @@ function GameCard({
19076
19080
  if (clickEvent) eventBus.emit(`UI:${clickEvent}`, { cardId: id });
19077
19081
  }, [disabled, id, onClick, clickEvent, eventBus]);
19078
19082
  const artPx = artPxMap[size];
19083
+ const frameStyle = frameAsset?.url ? { backgroundImage: `url(${frameAsset.url})`, backgroundSize: "100% 100%", backgroundRepeat: "no-repeat" } : {};
19079
19084
  return /* @__PURE__ */ jsxRuntime.jsxs(
19080
19085
  exports.Button,
19081
19086
  {
@@ -19083,9 +19088,11 @@ function GameCard({
19083
19088
  onClick: handleClick,
19084
19089
  disabled,
19085
19090
  title: name,
19091
+ style: frameStyle,
19086
19092
  className: cn(
19087
- "relative flex flex-col items-center rounded-interactive border-2",
19093
+ "relative flex flex-col items-center rounded-interactive",
19088
19094
  "bg-card/90 px-1.5 pt-1.5 pb-1 transition-all duration-150",
19095
+ frameAsset?.url ? "border-0" : "border-2",
19089
19096
  cardSizeMap[size],
19090
19097
  disabled ? "border-border opacity-50 cursor-not-allowed" : "border-accent hover:brightness-125 hover:-translate-y-1 cursor-pointer",
19091
19098
  selected && "ring-2 ring-foreground ring-offset-1 ring-offset-background -translate-y-1",
@@ -2122,6 +2122,7 @@ var init_Button = __esm({
2122
2122
  rightIcon,
2123
2123
  icon: iconProp,
2124
2124
  iconRight: iconRightProp,
2125
+ iconAsset,
2125
2126
  action,
2126
2127
  actionPayload,
2127
2128
  label,
@@ -2133,7 +2134,8 @@ var init_Button = __esm({
2133
2134
  const eventBus = useEventBus();
2134
2135
  const leftIconValue = leftIcon || iconProp;
2135
2136
  const rightIconValue = rightIcon || iconRightProp;
2136
- const resolvedLeftIcon = resolveIconProp(leftIconValue, iconSizeStyles[size]);
2137
+ const px = size === "sm" ? 16 : size === "lg" ? 20 : 16;
2138
+ const resolvedLeftIcon = iconAsset?.url ? /* @__PURE__ */ 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]);
2137
2139
  const resolvedRightIcon = resolveIconProp(rightIconValue, iconSizeStyles[size]);
2138
2140
  const handleClick = (e) => {
2139
2141
  if (action) {
@@ -2887,13 +2889,14 @@ var init_Badge = __esm({
2887
2889
  lg: "px-3 py-1.5 text-base"
2888
2890
  };
2889
2891
  Badge = React79__default.forwardRef(
2890
- ({ className, variant = "default", size = "sm", amount, label, icon, children, onRemove, removeLabel, ...props }, ref) => {
2892
+ ({ className, variant = "default", size = "sm", amount, label, icon, iconAsset, children, onRemove, removeLabel, ...props }, ref) => {
2891
2893
  const iconSizes3 = {
2892
2894
  sm: "h-icon-default w-icon-default",
2893
2895
  md: "h-icon-default w-icon-default",
2894
2896
  lg: "h-icon-default w-icon-default"
2895
2897
  };
2896
- const resolvedIcon = typeof icon === "string" ? /* @__PURE__ */ jsx(Icon, { name: icon, className: iconSizes3[size] }) : icon ? /* @__PURE__ */ jsx(Icon, { icon, className: iconSizes3[size] }) : null;
2898
+ const iconPx = size === "lg" ? 20 : 16;
2899
+ const resolvedIcon = iconAsset?.url ? /* @__PURE__ */ 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__ */ jsx(Icon, { name: icon, className: iconSizes3[size] }) : icon ? /* @__PURE__ */ jsx(Icon, { icon, className: iconSizes3[size] }) : null;
2897
2900
  return /* @__PURE__ */ jsxs(
2898
2901
  "span",
2899
2902
  {
@@ -12853,7 +12856,7 @@ var init_Tabs = __esm({
12853
12856
  isActive ? variant === "pills" ? "text-primary-foreground font-bold" : "text-foreground font-bold" : "text-muted-foreground hover:text-foreground"
12854
12857
  ),
12855
12858
  children: [
12856
- item.icon && (typeof item.icon === "string" ? /* @__PURE__ */ jsx(Icon, { name: item.icon, size: "sm" }) : /* @__PURE__ */ jsx(Icon, { icon: item.icon, size: "sm" })),
12859
+ item.iconAsset?.url ? /* @__PURE__ */ 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__ */ jsx(Icon, { name: item.icon, size: "sm" }) : /* @__PURE__ */ jsx(Icon, { icon: item.icon, size: "sm" })),
12857
12860
  /* @__PURE__ */ jsx(Typography, { variant: "small", weight: isActive ? "semibold" : "normal", className: "!text-inherit", children: item.label }),
12858
12861
  item.badge !== void 0 && /* @__PURE__ */ jsx(Badge, { variant: "default", size: "sm", children: item.badge })
12859
12862
  ]
@@ -19013,6 +19016,7 @@ function GameCard({
19013
19016
  id,
19014
19017
  cost,
19015
19018
  art,
19019
+ frameAsset,
19016
19020
  attack,
19017
19021
  defense,
19018
19022
  name,
@@ -19030,6 +19034,7 @@ function GameCard({
19030
19034
  if (clickEvent) eventBus.emit(`UI:${clickEvent}`, { cardId: id });
19031
19035
  }, [disabled, id, onClick, clickEvent, eventBus]);
19032
19036
  const artPx = artPxMap[size];
19037
+ const frameStyle = frameAsset?.url ? { backgroundImage: `url(${frameAsset.url})`, backgroundSize: "100% 100%", backgroundRepeat: "no-repeat" } : {};
19033
19038
  return /* @__PURE__ */ jsxs(
19034
19039
  Button,
19035
19040
  {
@@ -19037,9 +19042,11 @@ function GameCard({
19037
19042
  onClick: handleClick,
19038
19043
  disabled,
19039
19044
  title: name,
19045
+ style: frameStyle,
19040
19046
  className: cn(
19041
- "relative flex flex-col items-center rounded-interactive border-2",
19047
+ "relative flex flex-col items-center rounded-interactive",
19042
19048
  "bg-card/90 px-1.5 pt-1.5 pb-1 transition-all duration-150",
19049
+ frameAsset?.url ? "border-0" : "border-2",
19043
19050
  cardSizeMap[size],
19044
19051
  disabled ? "border-border opacity-50 cursor-not-allowed" : "border-accent hover:brightness-125 hover:-translate-y-1 cursor-pointer",
19045
19052
  selected && "ring-2 ring-foreground ring-offset-1 ring-offset-background -translate-y-1",
@@ -3983,6 +3983,7 @@ var Button = React11__default.default.forwardRef(
3983
3983
  rightIcon,
3984
3984
  icon: iconProp,
3985
3985
  iconRight: iconRightProp,
3986
+ iconAsset,
3986
3987
  action,
3987
3988
  actionPayload,
3988
3989
  label,
@@ -3994,7 +3995,8 @@ var Button = React11__default.default.forwardRef(
3994
3995
  const eventBus = useEventBus();
3995
3996
  const leftIconValue = leftIcon || iconProp;
3996
3997
  const rightIconValue = rightIcon || iconRightProp;
3997
- const resolvedLeftIcon = resolveIconProp(leftIconValue, iconSizeStyles[size]);
3998
+ const px = size === "sm" ? 16 : size === "lg" ? 20 : 16;
3999
+ 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]);
3998
4000
  const resolvedRightIcon = resolveIconProp(rightIconValue, iconSizeStyles[size]);
3999
4001
  const handleClick = (e) => {
4000
4002
  if (action) {
@@ -4070,13 +4072,14 @@ var sizeStyles2 = {
4070
4072
  lg: "px-3 py-1.5 text-base"
4071
4073
  };
4072
4074
  var Badge = React11__default.default.forwardRef(
4073
- ({ className, variant = "default", size = "sm", amount, label, icon, children, onRemove, removeLabel, ...props }, ref) => {
4075
+ ({ className, variant = "default", size = "sm", amount, label, icon, iconAsset, children, onRemove, removeLabel, ...props }, ref) => {
4074
4076
  const iconSizes = {
4075
4077
  sm: "h-icon-default w-icon-default",
4076
4078
  md: "h-icon-default w-icon-default",
4077
4079
  lg: "h-icon-default w-icon-default"
4078
4080
  };
4079
- const resolvedIcon = typeof icon === "string" ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: icon, className: iconSizes[size] }) : icon ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { icon, className: iconSizes[size] }) : null;
4081
+ const iconPx = size === "lg" ? 20 : 16;
4082
+ 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: iconSizes[size] }) : icon ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { icon, className: iconSizes[size] }) : null;
4080
4083
  return /* @__PURE__ */ jsxRuntime.jsxs(
4081
4084
  "span",
4082
4085
  {
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import { EventKey, EventPayload, AssetUrl } from '@almadar/core';
2
+ import { EventKey, EventPayload, AssetUrl, Asset } from '@almadar/core';
3
3
  import { LucideIcon } from 'lucide-react';
4
4
 
5
5
  /**
@@ -259,6 +259,8 @@ interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
259
259
  icon?: IconInput;
260
260
  /** Alias for rightIcon */
261
261
  iconRight?: IconInput;
262
+ /** Asset image rendered as the leading icon; takes precedence over icon/leftIcon when provided. */
263
+ iconAsset?: Asset;
262
264
  /** Declarative event name — emits UI:{action} via eventBus on click */
263
265
  action?: EventKey;
264
266
  /** Payload to include with the action event */
@@ -287,6 +289,8 @@ interface BadgeProps extends React.HTMLAttributes<HTMLSpanElement> {
287
289
  label?: string | number;
288
290
  /** Lucide icon component or canonical kebab-case icon name string */
289
291
  icon?: IconInput;
292
+ /** Asset image rendered as the badge icon; takes precedence over icon when provided. */
293
+ iconAsset?: Asset;
290
294
  /** When set, renders a small X button on the right of the badge that
291
295
  * invokes this handler — turns the badge into a removable chip.
292
296
  * Used by the TagInput molecule and other "list of removable values"
@@ -1,6 +1,6 @@
1
1
  import React11, { createContext, useCallback, useState, useRef, useEffect, useContext, useMemo, useSyncExternalStore, useId } from 'react';
2
2
  import { createLogger } from '@almadar/logger';
3
- import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
3
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
4
4
  import * as LucideIcons2 from 'lucide-react';
5
5
  import { Loader2, X } from 'lucide-react';
6
6
 
@@ -3959,6 +3959,7 @@ var Button = React11.forwardRef(
3959
3959
  rightIcon,
3960
3960
  icon: iconProp,
3961
3961
  iconRight: iconRightProp,
3962
+ iconAsset,
3962
3963
  action,
3963
3964
  actionPayload,
3964
3965
  label,
@@ -3970,7 +3971,8 @@ var Button = React11.forwardRef(
3970
3971
  const eventBus = useEventBus();
3971
3972
  const leftIconValue = leftIcon || iconProp;
3972
3973
  const rightIconValue = rightIcon || iconRightProp;
3973
- const resolvedLeftIcon = resolveIconProp(leftIconValue, iconSizeStyles[size]);
3974
+ const px = size === "sm" ? 16 : size === "lg" ? 20 : 16;
3975
+ const resolvedLeftIcon = iconAsset?.url ? /* @__PURE__ */ 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]);
3974
3976
  const resolvedRightIcon = resolveIconProp(rightIconValue, iconSizeStyles[size]);
3975
3977
  const handleClick = (e) => {
3976
3978
  if (action) {
@@ -4046,13 +4048,14 @@ var sizeStyles2 = {
4046
4048
  lg: "px-3 py-1.5 text-base"
4047
4049
  };
4048
4050
  var Badge = React11.forwardRef(
4049
- ({ className, variant = "default", size = "sm", amount, label, icon, children, onRemove, removeLabel, ...props }, ref) => {
4051
+ ({ className, variant = "default", size = "sm", amount, label, icon, iconAsset, children, onRemove, removeLabel, ...props }, ref) => {
4050
4052
  const iconSizes = {
4051
4053
  sm: "h-icon-default w-icon-default",
4052
4054
  md: "h-icon-default w-icon-default",
4053
4055
  lg: "h-icon-default w-icon-default"
4054
4056
  };
4055
- const resolvedIcon = typeof icon === "string" ? /* @__PURE__ */ jsx(Icon, { name: icon, className: iconSizes[size] }) : icon ? /* @__PURE__ */ jsx(Icon, { icon, className: iconSizes[size] }) : null;
4057
+ const iconPx = size === "lg" ? 20 : 16;
4058
+ const resolvedIcon = iconAsset?.url ? /* @__PURE__ */ 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__ */ jsx(Icon, { name: icon, className: iconSizes[size] }) : icon ? /* @__PURE__ */ jsx(Icon, { icon, className: iconSizes[size] }) : null;
4056
4059
  return /* @__PURE__ */ jsxs(
4057
4060
  "span",
4058
4061
  {
@@ -1484,6 +1484,7 @@ var init_Button = __esm({
1484
1484
  rightIcon,
1485
1485
  icon: iconProp,
1486
1486
  iconRight: iconRightProp,
1487
+ iconAsset,
1487
1488
  action,
1488
1489
  actionPayload,
1489
1490
  label,
@@ -1495,7 +1496,8 @@ var init_Button = __esm({
1495
1496
  const eventBus = useEventBus();
1496
1497
  const leftIconValue = leftIcon || iconProp;
1497
1498
  const rightIconValue = rightIcon || iconRightProp;
1498
- const resolvedLeftIcon = resolveIconProp(leftIconValue, iconSizeStyles[size]);
1499
+ const px = size === "sm" ? 16 : size === "lg" ? 20 : 16;
1500
+ 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]);
1499
1501
  const resolvedRightIcon = resolveIconProp(rightIconValue, iconSizeStyles[size]);
1500
1502
  const handleClick = (e) => {
1501
1503
  if (action) {
@@ -2153,13 +2155,14 @@ var init_Badge = __esm({
2153
2155
  lg: "px-3 py-1.5 text-base"
2154
2156
  };
2155
2157
  Badge = React105__namespace.default.forwardRef(
2156
- ({ className, variant = "default", size = "sm", amount, label, icon, children, onRemove, removeLabel, ...props }, ref) => {
2158
+ ({ className, variant = "default", size = "sm", amount, label, icon, iconAsset, children, onRemove, removeLabel, ...props }, ref) => {
2157
2159
  const iconSizes3 = {
2158
2160
  sm: "h-icon-default w-icon-default",
2159
2161
  md: "h-icon-default w-icon-default",
2160
2162
  lg: "h-icon-default w-icon-default"
2161
2163
  };
2162
- const resolvedIcon = typeof icon === "string" ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: icon, className: iconSizes3[size] }) : icon ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { icon, className: iconSizes3[size] }) : null;
2164
+ const iconPx = size === "lg" ? 20 : 16;
2165
+ 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;
2163
2166
  return /* @__PURE__ */ jsxRuntime.jsxs(
2164
2167
  "span",
2165
2168
  {
@@ -8438,6 +8441,7 @@ function GameCard({
8438
8441
  id,
8439
8442
  cost,
8440
8443
  art,
8444
+ frameAsset,
8441
8445
  attack,
8442
8446
  defense,
8443
8447
  name,
@@ -8455,6 +8459,7 @@ function GameCard({
8455
8459
  if (clickEvent) eventBus.emit(`UI:${clickEvent}`, { cardId: id });
8456
8460
  }, [disabled, id, onClick, clickEvent, eventBus]);
8457
8461
  const artPx = artPxMap[size];
8462
+ const frameStyle = frameAsset?.url ? { backgroundImage: `url(${frameAsset.url})`, backgroundSize: "100% 100%", backgroundRepeat: "no-repeat" } : {};
8458
8463
  return /* @__PURE__ */ jsxRuntime.jsxs(
8459
8464
  Button,
8460
8465
  {
@@ -8462,9 +8467,11 @@ function GameCard({
8462
8467
  onClick: handleClick,
8463
8468
  disabled,
8464
8469
  title: name,
8470
+ style: frameStyle,
8465
8471
  className: cn(
8466
- "relative flex flex-col items-center rounded-interactive border-2",
8472
+ "relative flex flex-col items-center rounded-interactive",
8467
8473
  "bg-card/90 px-1.5 pt-1.5 pb-1 transition-all duration-150",
8474
+ frameAsset?.url ? "border-0" : "border-2",
8468
8475
  cardSizeMap[size],
8469
8476
  disabled ? "border-border opacity-50 cursor-not-allowed" : "border-accent hover:brightness-125 hover:-translate-y-1 cursor-pointer",
8470
8477
  selected && "ring-2 ring-foreground ring-offset-1 ring-offset-background -translate-y-1",
@@ -23269,7 +23276,7 @@ var init_Tabs = __esm({
23269
23276
  isActive ? variant === "pills" ? "text-primary-foreground font-bold" : "text-foreground font-bold" : "text-muted-foreground hover:text-foreground"
23270
23277
  ),
23271
23278
  children: [
23272
- item.icon && (typeof item.icon === "string" ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: item.icon, size: "sm" }) : /* @__PURE__ */ jsxRuntime.jsx(Icon, { icon: item.icon, size: "sm" })),
23279
+ 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" })),
23273
23280
  /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "small", weight: isActive ? "semibold" : "normal", className: "!text-inherit", children: item.label }),
23274
23281
  item.badge !== void 0 && /* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: "default", size: "sm", children: item.badge })
23275
23282
  ]
@@ -1439,6 +1439,7 @@ var init_Button = __esm({
1439
1439
  rightIcon,
1440
1440
  icon: iconProp,
1441
1441
  iconRight: iconRightProp,
1442
+ iconAsset,
1442
1443
  action,
1443
1444
  actionPayload,
1444
1445
  label,
@@ -1450,7 +1451,8 @@ var init_Button = __esm({
1450
1451
  const eventBus = useEventBus();
1451
1452
  const leftIconValue = leftIcon || iconProp;
1452
1453
  const rightIconValue = rightIcon || iconRightProp;
1453
- const resolvedLeftIcon = resolveIconProp(leftIconValue, iconSizeStyles[size]);
1454
+ const px = size === "sm" ? 16 : size === "lg" ? 20 : 16;
1455
+ const resolvedLeftIcon = iconAsset?.url ? /* @__PURE__ */ 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]);
1454
1456
  const resolvedRightIcon = resolveIconProp(rightIconValue, iconSizeStyles[size]);
1455
1457
  const handleClick = (e) => {
1456
1458
  if (action) {
@@ -2108,13 +2110,14 @@ var init_Badge = __esm({
2108
2110
  lg: "px-3 py-1.5 text-base"
2109
2111
  };
2110
2112
  Badge = React105__default.forwardRef(
2111
- ({ className, variant = "default", size = "sm", amount, label, icon, children, onRemove, removeLabel, ...props }, ref) => {
2113
+ ({ className, variant = "default", size = "sm", amount, label, icon, iconAsset, children, onRemove, removeLabel, ...props }, ref) => {
2112
2114
  const iconSizes3 = {
2113
2115
  sm: "h-icon-default w-icon-default",
2114
2116
  md: "h-icon-default w-icon-default",
2115
2117
  lg: "h-icon-default w-icon-default"
2116
2118
  };
2117
- const resolvedIcon = typeof icon === "string" ? /* @__PURE__ */ jsx(Icon, { name: icon, className: iconSizes3[size] }) : icon ? /* @__PURE__ */ jsx(Icon, { icon, className: iconSizes3[size] }) : null;
2119
+ const iconPx = size === "lg" ? 20 : 16;
2120
+ const resolvedIcon = iconAsset?.url ? /* @__PURE__ */ 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__ */ jsx(Icon, { name: icon, className: iconSizes3[size] }) : icon ? /* @__PURE__ */ jsx(Icon, { icon, className: iconSizes3[size] }) : null;
2118
2121
  return /* @__PURE__ */ jsxs(
2119
2122
  "span",
2120
2123
  {
@@ -8393,6 +8396,7 @@ function GameCard({
8393
8396
  id,
8394
8397
  cost,
8395
8398
  art,
8399
+ frameAsset,
8396
8400
  attack,
8397
8401
  defense,
8398
8402
  name,
@@ -8410,6 +8414,7 @@ function GameCard({
8410
8414
  if (clickEvent) eventBus.emit(`UI:${clickEvent}`, { cardId: id });
8411
8415
  }, [disabled, id, onClick, clickEvent, eventBus]);
8412
8416
  const artPx = artPxMap[size];
8417
+ const frameStyle = frameAsset?.url ? { backgroundImage: `url(${frameAsset.url})`, backgroundSize: "100% 100%", backgroundRepeat: "no-repeat" } : {};
8413
8418
  return /* @__PURE__ */ jsxs(
8414
8419
  Button,
8415
8420
  {
@@ -8417,9 +8422,11 @@ function GameCard({
8417
8422
  onClick: handleClick,
8418
8423
  disabled,
8419
8424
  title: name,
8425
+ style: frameStyle,
8420
8426
  className: cn(
8421
- "relative flex flex-col items-center rounded-interactive border-2",
8427
+ "relative flex flex-col items-center rounded-interactive",
8422
8428
  "bg-card/90 px-1.5 pt-1.5 pb-1 transition-all duration-150",
8429
+ frameAsset?.url ? "border-0" : "border-2",
8423
8430
  cardSizeMap[size],
8424
8431
  disabled ? "border-border opacity-50 cursor-not-allowed" : "border-accent hover:brightness-125 hover:-translate-y-1 cursor-pointer",
8425
8432
  selected && "ring-2 ring-foreground ring-offset-1 ring-offset-background -translate-y-1",
@@ -23224,7 +23231,7 @@ var init_Tabs = __esm({
23224
23231
  isActive ? variant === "pills" ? "text-primary-foreground font-bold" : "text-foreground font-bold" : "text-muted-foreground hover:text-foreground"
23225
23232
  ),
23226
23233
  children: [
23227
- item.icon && (typeof item.icon === "string" ? /* @__PURE__ */ jsx(Icon, { name: item.icon, size: "sm" }) : /* @__PURE__ */ jsx(Icon, { icon: item.icon, size: "sm" })),
23234
+ item.iconAsset?.url ? /* @__PURE__ */ 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__ */ jsx(Icon, { name: item.icon, size: "sm" }) : /* @__PURE__ */ jsx(Icon, { icon: item.icon, size: "sm" })),
23228
23235
  /* @__PURE__ */ jsx(Typography, { variant: "small", weight: isActive ? "semibold" : "normal", className: "!text-inherit", children: item.label }),
23229
23236
  item.badge !== void 0 && /* @__PURE__ */ jsx(Badge, { variant: "default", size: "sm", children: item.badge })
23230
23237
  ]
@@ -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
  {
@@ -8964,6 +8967,7 @@ function GameCard({
8964
8967
  id,
8965
8968
  cost,
8966
8969
  art,
8970
+ frameAsset,
8967
8971
  attack,
8968
8972
  defense,
8969
8973
  name,
@@ -8981,6 +8985,7 @@ function GameCard({
8981
8985
  if (clickEvent) eventBus.emit(`UI:${clickEvent}`, { cardId: id });
8982
8986
  }, [disabled, id, onClick, clickEvent, eventBus]);
8983
8987
  const artPx = artPxMap[size];
8988
+ const frameStyle = frameAsset?.url ? { backgroundImage: `url(${frameAsset.url})`, backgroundSize: "100% 100%", backgroundRepeat: "no-repeat" } : {};
8984
8989
  return /* @__PURE__ */ jsxRuntime.jsxs(
8985
8990
  Button,
8986
8991
  {
@@ -8988,9 +8993,11 @@ function GameCard({
8988
8993
  onClick: handleClick,
8989
8994
  disabled,
8990
8995
  title: name,
8996
+ style: frameStyle,
8991
8997
  className: cn(
8992
- "relative flex flex-col items-center rounded-interactive border-2",
8998
+ "relative flex flex-col items-center rounded-interactive",
8993
8999
  "bg-card/90 px-1.5 pt-1.5 pb-1 transition-all duration-150",
9000
+ frameAsset?.url ? "border-0" : "border-2",
8994
9001
  cardSizeMap[size],
8995
9002
  disabled ? "border-border opacity-50 cursor-not-allowed" : "border-accent hover:brightness-125 hover:-translate-y-1 cursor-pointer",
8996
9003
  selected && "ring-2 ring-foreground ring-offset-1 ring-offset-background -translate-y-1",
@@ -23233,7 +23240,7 @@ var init_Tabs = __esm({
23233
23240
  isActive ? variant === "pills" ? "text-primary-foreground font-bold" : "text-foreground font-bold" : "text-muted-foreground hover:text-foreground"
23234
23241
  ),
23235
23242
  children: [
23236
- 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" })),
23237
23244
  /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "small", weight: isActive ? "semibold" : "normal", className: "!text-inherit", children: item.label }),
23238
23245
  item.badge !== void 0 && /* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: "default", size: "sm", children: item.badge })
23239
23246
  ]
@@ -1988,6 +1988,7 @@ var init_Button = __esm({
1988
1988
  rightIcon,
1989
1989
  icon: iconProp,
1990
1990
  iconRight: iconRightProp,
1991
+ iconAsset,
1991
1992
  action,
1992
1993
  actionPayload,
1993
1994
  label,
@@ -1999,7 +2000,8 @@ var init_Button = __esm({
1999
2000
  const eventBus = useEventBus();
2000
2001
  const leftIconValue = leftIcon || iconProp;
2001
2002
  const rightIconValue = rightIcon || iconRightProp;
2002
- const resolvedLeftIcon = resolveIconProp(leftIconValue, iconSizeStyles[size]);
2003
+ const px = size === "sm" ? 16 : size === "lg" ? 20 : 16;
2004
+ const resolvedLeftIcon = iconAsset?.url ? /* @__PURE__ */ 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]);
2003
2005
  const resolvedRightIcon = resolveIconProp(rightIconValue, iconSizeStyles[size]);
2004
2006
  const handleClick = (e) => {
2005
2007
  if (action) {
@@ -2657,13 +2659,14 @@ var init_Badge = __esm({
2657
2659
  lg: "px-3 py-1.5 text-base"
2658
2660
  };
2659
2661
  Badge = React103__default.forwardRef(
2660
- ({ className, variant = "default", size = "sm", amount, label, icon, children, onRemove, removeLabel, ...props }, ref) => {
2662
+ ({ className, variant = "default", size = "sm", amount, label, icon, iconAsset, children, onRemove, removeLabel, ...props }, ref) => {
2661
2663
  const iconSizes3 = {
2662
2664
  sm: "h-icon-default w-icon-default",
2663
2665
  md: "h-icon-default w-icon-default",
2664
2666
  lg: "h-icon-default w-icon-default"
2665
2667
  };
2666
- const resolvedIcon = typeof icon === "string" ? /* @__PURE__ */ jsx(Icon, { name: icon, className: iconSizes3[size] }) : icon ? /* @__PURE__ */ jsx(Icon, { icon, className: iconSizes3[size] }) : null;
2668
+ const iconPx = size === "lg" ? 20 : 16;
2669
+ const resolvedIcon = iconAsset?.url ? /* @__PURE__ */ 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__ */ jsx(Icon, { name: icon, className: iconSizes3[size] }) : icon ? /* @__PURE__ */ jsx(Icon, { icon, className: iconSizes3[size] }) : null;
2667
2670
  return /* @__PURE__ */ jsxs(
2668
2671
  "span",
2669
2672
  {
@@ -8919,6 +8922,7 @@ function GameCard({
8919
8922
  id,
8920
8923
  cost,
8921
8924
  art,
8925
+ frameAsset,
8922
8926
  attack,
8923
8927
  defense,
8924
8928
  name,
@@ -8936,6 +8940,7 @@ function GameCard({
8936
8940
  if (clickEvent) eventBus.emit(`UI:${clickEvent}`, { cardId: id });
8937
8941
  }, [disabled, id, onClick, clickEvent, eventBus]);
8938
8942
  const artPx = artPxMap[size];
8943
+ const frameStyle = frameAsset?.url ? { backgroundImage: `url(${frameAsset.url})`, backgroundSize: "100% 100%", backgroundRepeat: "no-repeat" } : {};
8939
8944
  return /* @__PURE__ */ jsxs(
8940
8945
  Button,
8941
8946
  {
@@ -8943,9 +8948,11 @@ function GameCard({
8943
8948
  onClick: handleClick,
8944
8949
  disabled,
8945
8950
  title: name,
8951
+ style: frameStyle,
8946
8952
  className: cn(
8947
- "relative flex flex-col items-center rounded-interactive border-2",
8953
+ "relative flex flex-col items-center rounded-interactive",
8948
8954
  "bg-card/90 px-1.5 pt-1.5 pb-1 transition-all duration-150",
8955
+ frameAsset?.url ? "border-0" : "border-2",
8949
8956
  cardSizeMap[size],
8950
8957
  disabled ? "border-border opacity-50 cursor-not-allowed" : "border-accent hover:brightness-125 hover:-translate-y-1 cursor-pointer",
8951
8958
  selected && "ring-2 ring-foreground ring-offset-1 ring-offset-background -translate-y-1",
@@ -23188,7 +23195,7 @@ var init_Tabs = __esm({
23188
23195
  isActive ? variant === "pills" ? "text-primary-foreground font-bold" : "text-foreground font-bold" : "text-muted-foreground hover:text-foreground"
23189
23196
  ),
23190
23197
  children: [
23191
- item.icon && (typeof item.icon === "string" ? /* @__PURE__ */ jsx(Icon, { name: item.icon, size: "sm" }) : /* @__PURE__ */ jsx(Icon, { icon: item.icon, size: "sm" })),
23198
+ item.iconAsset?.url ? /* @__PURE__ */ 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__ */ jsx(Icon, { name: item.icon, size: "sm" }) : /* @__PURE__ */ jsx(Icon, { icon: item.icon, size: "sm" })),
23192
23199
  /* @__PURE__ */ jsx(Typography, { variant: "small", weight: isActive ? "semibold" : "normal", className: "!text-inherit", children: item.label }),
23193
23200
  item.badge !== void 0 && /* @__PURE__ */ jsx(Badge, { variant: "default", size: "sm", children: item.badge })
23194
23201
  ]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@almadar/ui",
3
- "version": "5.81.0",
3
+ "version": "5.82.0",
4
4
  "description": "React UI components, hooks, and providers for Almadar",
5
5
  "type": "module",
6
6
  "sideEffects": [