{"version":3,"file":"image.cjs","sources":["../../../components/image/image.tsx"],"sourcesContent":["'use client';\n\nimport { cva, cx, type VariantProps } from 'class-variance-authority';\nimport { ComponentProps, SyntheticEvent, useRef, useState } from 'react';\nimport { useIsomorphicLayoutEffect } from '~/hooks';\n\nimport styles from './image.module.css';\n\nconst image = cva(styles.image, {\n  variants: {\n    fit: {\n      contain: styles['image-contain'],\n      cover: styles['image-cover'],\n      fill: styles['image-fill']\n    },\n    radius: {\n      none: styles['image-radius-none'],\n      small: styles['image-radius-small'],\n      medium: styles['image-radius-medium'],\n      full: styles['image-radius-full']\n    }\n  },\n  defaultVariants: {\n    fit: 'cover',\n    radius: 'none'\n  }\n});\n\ninterface ImageProps extends ComponentProps<'img'>, VariantProps<typeof image> {\n  fallback?: string;\n}\n\nexport function Image({\n  alt = '',\n  className,\n  fit,\n  radius,\n  fallback,\n  onError,\n  onLoad,\n  src,\n  width,\n  height,\n  style,\n  loading = 'lazy',\n  decoding = 'async',\n  ...props\n}: ImageProps) {\n  const imgRef = useRef<HTMLImageElement>(null);\n  const hasFallenBackRef = useRef(false);\n  const [loadState, setLoadState] = useState<'static' | 'loading' | 'loaded'>(\n    'static'\n  );\n\n  useIsomorphicLayoutEffect(() => {\n    hasFallenBackRef.current = false;\n    const node = imgRef.current;\n    // Already-decoded (cached/SSR-painted) images stay visible — no fade.\n    setLoadState(node && !node.complete ? 'loading' : 'static');\n  }, [src]);\n\n  const handleLoad = (event: SyntheticEvent<HTMLImageElement, Event>) => {\n    setLoadState(prev => (prev === 'loading' ? 'loaded' : prev));\n    onLoad?.(event);\n  };\n\n  const handleError = (event: SyntheticEvent<HTMLImageElement, Event>) => {\n    if (fallback && !hasFallenBackRef.current) {\n      // One-shot: if the fallback itself errors, never re-assign it.\n      hasFallenBackRef.current = true;\n      event.currentTarget.src = fallback;\n    } else {\n      // No fallback (or the fallback failed): show the alt/broken rendering\n      // instead of holding the img invisible.\n      setLoadState('static');\n    }\n    onError?.(event);\n  };\n\n  const imageStyle = {\n    width: width,\n    height: height,\n    ...style\n  };\n\n  return (\n    <img\n      data-slot='image'\n      ref={imgRef}\n      alt={alt}\n      src={src}\n      className={image({\n        fit,\n        radius,\n        className: cx(\n          loadState === 'loading' && styles['image-loading'],\n          loadState === 'loaded' && styles['image-loaded'],\n          className\n        )\n      })}\n      onError={handleError}\n      onLoad={handleLoad}\n      style={imageStyle}\n      loading={loading}\n      decoding={decoding}\n      {...props}\n    />\n  );\n}\n\nImage.displayName = 'Image';\n"],"names":[],"mappings":";;;;;;;;;AAQA;AACE;AACE;AACE;AACA;AACA;AACD;AACD;AACE;AACA;AACA;AACA;AACD;AACF;AACD;AACE;AACA;AACD;AACF;;AAsBC;AACA;;;AAME;AACA;;AAEA;AACF;AAEA;AACE;AACA;AACF;AAEA;AACE;;AAEE;AACA;;;;;;;AAMF;AACF;AAEA;AACE;AACA;AACA;;AAGF;;;;;AAuBF;AAEA;;"}