{"version":3,"sources":["../src/image/index.tsx"],"names":["forwardRef","Image","useTheme","useState","radiusTokens","jsx","jsxs"],"mappings":";;;;;;;;AAmCO,IAAM,KAAA,GAAQA,gBAAA,CAAyC,SAASC,MAAAA,CACrE;AAAA,EACE,GAAA;AAAA,EACA,GAAA;AAAA,EACA,KAAA;AAAA,EACA,MAAA;AAAA,EACA,WAAA;AAAA,EACA,GAAA,GAAM,OAAA;AAAA,EACN,MAAA;AAAA,EACA,WAAA;AAAA,EACA,QAAA;AAAA,EACA,KAAA;AAAA,EACA,GAAG;AACL,CAAA,EACA,GAAA,EACA;AACA,EAAA,MAAM,EAAE,MAAA,EAAO,GAAIC,eAAA,EAAS;AAC5B,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAIC,eAAyC,SAAS,CAAA;AAE5E,EAAA,MAAM,WAAA,GACJ,OAAO,MAAA,KAAW,QAAA,GAAW,SAAS,MAAA,GAASC,WAAA,CAAa,MAAM,CAAA,GAAI,MAAA;AAExE,EAAA,MAAM,cAAA,GAAgC;AAAA,IACpC,QAAA,EAAU,UAAA;AAAA,IACV,OAAA,EAAS,cAAA;AAAA,IACT,KAAA;AAAA,IACA,MAAA;AAAA,IACA,WAAA;AAAA,IACA,YAAA,EAAc,WAAA;AAAA,IACd,QAAA,EAAU,cAAc,QAAA,GAAW,MAAA;AAAA,IACnC,UAAA,EAAY,KAAA,KAAU,SAAA,GAAY,MAAA,CAAO,aAAA,GAAgB,MAAA;AAAA,IACzD,UAAA,EAAY;AAAA,GACd;AAEA,EAAA,IAAI,KAAA,KAAU,WAAW,QAAA,EAAU;AACjC,IAAA,uBACEC,cAAA,CAAC,UAAK,KAAA,EAAO,cAAA,EAAgB,cAAY,GAAA,EAAK,IAAA,EAAK,OAChD,QAAA,EAAA,QAAA,EACH,CAAA;AAAA,EAEJ;AAEA,EAAA,uBACEC,eAAA,CAAC,MAAA,EAAA,EAAK,KAAA,EAAO,cAAA,EACX,QAAA,EAAA;AAAA,oBAAAD,cAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,GAAA;AAAA,QACA,GAAA;AAAA,QACA,GAAA;AAAA,QACA,MAAA,EAAQ,MAAM,QAAA,CAAS,QAAQ,CAAA;AAAA,QAC/B,OAAA,EAAS,MAAM,QAAA,CAAS,OAAO,CAAA;AAAA,QAC/B,KAAA,EAAO;AAAA,UACL,KAAA,EAAO,MAAA;AAAA,UACP,MAAA,EAAQ,MAAA;AAAA,UACR,SAAA,EAAW,GAAA;AAAA,UACX,OAAA,EAAS,OAAA;AAAA,UACT,YAAA,EAAc,WAAA;AAAA,UACd,OAAA,EAAS,KAAA,KAAU,QAAA,GAAW,CAAA,GAAI,CAAA;AAAA,UAClC,UAAA,EAAY,oBAAA;AAAA,UACZ,GAAG;AAAA,SACL;AAAA,QACC,GAAG;AAAA;AAAA,KACN;AAAA,IACC,KAAA,KAAU,SAAA,IAAa,CAAC,WAAA,GAAc,IAAA,GAAO,IAAA;AAAA,IAC7C,UAAU,SAAA,IAAa,WAAA,mBACtBA,cAAA,CAAC,MAAA,EAAA,EAAK,OAAO,EAAE,QAAA,EAAU,UAAA,EAAY,KAAA,EAAO,GAAG,OAAA,EAAS,MAAA,EAAQ,YAAY,QAAA,EAAS,EAClF,uBACH,CAAA,GACE;AAAA,GAAA,EACN,CAAA;AAEJ,CAAC","file":"image.cjs","sourcesContent":["/**\n * Image (web). Thin wrapper around <img> with theme-aware skeleton, fit,\n * and an optional fallback when the URL fails.\n *\n *   <Image src={user.avatar} alt={user.name} width={32} height={32} radius=\"pill\" />\n *\n * Aspect ratio takes precedence over width/height when both are set;\n * useful for responsive cards where you want a 16/9 slot regardless of\n * the actual image size.\n */\nimport { forwardRef, useState, type CSSProperties, type ImgHTMLAttributes, type ReactNode } from \"react\";\nimport { useTheme } from \"@plyxui/styles\";\nimport { radius as radiusTokens, type RadiusKey } from \"@plyxui/core\";\n\nexport type ImageFit = \"cover\" | \"contain\" | \"fill\" | \"none\" | \"scale-down\";\n\nexport interface ImageProps\n  extends Omit<ImgHTMLAttributes<HTMLImageElement>, \"width\" | \"height\"> {\n  src: string;\n  alt: string;\n  width?: number | string;\n  height?: number | string;\n  /** Aspect ratio in CSS form, e.g. \"16 / 9\" or 1.5. Wins over width+height when both are set. */\n  aspectRatio?: string | number;\n  /** object-fit. Default \"cover\". */\n  fit?: ImageFit;\n  /** Radius token from @plyxui/core, or a raw pixel value. */\n  radius?: RadiusKey | number;\n  /** Rendered while the image is loading. Defaults to a theme-colored skeleton. */\n  placeholder?: ReactNode;\n  /** Rendered when the image fails to load. */\n  fallback?: ReactNode;\n  style?: CSSProperties;\n}\n\nexport const Image = forwardRef<HTMLImageElement, ImageProps>(function Image(\n  {\n    src,\n    alt,\n    width,\n    height,\n    aspectRatio,\n    fit = \"cover\",\n    radius,\n    placeholder,\n    fallback,\n    style,\n    ...rest\n  },\n  ref,\n) {\n  const { colors } = useTheme();\n  const [state, setState] = useState<\"loading\" | \"loaded\" | \"error\">(\"loading\");\n\n  const radiusValue =\n    typeof radius === \"number\" ? radius : radius ? radiusTokens[radius] : undefined;\n\n  const containerStyle: CSSProperties = {\n    position: \"relative\",\n    display: \"inline-block\",\n    width,\n    height,\n    aspectRatio: aspectRatio as CSSProperties[\"aspectRatio\"],\n    borderRadius: radiusValue,\n    overflow: radiusValue ? \"hidden\" : undefined,\n    background: state === \"loading\" ? colors.containerFill : undefined,\n    lineHeight: 0,\n  };\n\n  if (state === \"error\" && fallback) {\n    return (\n      <span style={containerStyle} aria-label={alt} role=\"img\">\n        {fallback}\n      </span>\n    );\n  }\n\n  return (\n    <span style={containerStyle}>\n      <img\n        ref={ref}\n        src={src}\n        alt={alt}\n        onLoad={() => setState(\"loaded\")}\n        onError={() => setState(\"error\")}\n        style={{\n          width: \"100%\",\n          height: \"100%\",\n          objectFit: fit,\n          display: \"block\",\n          borderRadius: radiusValue,\n          opacity: state === \"loaded\" ? 1 : 0,\n          transition: \"opacity 0.18s ease\",\n          ...style,\n        }}\n        {...rest}\n      />\n      {state === \"loading\" && !placeholder ? null : null}\n      {state === \"loading\" && placeholder ? (\n        <span style={{ position: \"absolute\", inset: 0, display: \"grid\", placeItems: \"center\" }}>\n          {placeholder}\n        </span>\n      ) : null}\n    </span>\n  );\n});\n"]}