{"version":3,"file":"index.cjs","names":[],"sources":["../../../src/hooks/useResponsiveContainer.ts","../../../src/components/ImageBlock/ImageBlock.tsx"],"sourcesContent":["import { RefObject, useLayoutEffect, useState } from \"react\";\n\nexport type Breakpoint = \"mobile\" | \"tablet\" | \"desktop\";\n\nexport function getBreakpoint(width: number): Breakpoint {\n  if (width < 480) return \"mobile\";\n  if (width < 800) return \"tablet\";\n  return \"desktop\";\n}\n\nexport interface ContainerSize {\n  width: number;\n  height: number;\n  breakpoint: Breakpoint;\n}\n\n/**\n * Continuously tracks a container's size via ResizeObserver and returns\n * width, height, and a breakpoint derived from the container width.\n *\n * Breakpoints: mobile (<480px) | tablet (480–800px) | desktop (>800px)\n */\nexport function useResponsiveContainer(containerRef: RefObject<HTMLElement | null>): ContainerSize {\n  const [size, setSize] = useState<ContainerSize>({\n    width: 0,\n    height: 0,\n    breakpoint: \"mobile\",\n  });\n\n  const [element, setElement] = useState<HTMLElement | null>(null);\n\n  // Sync ref.current → state on every render so we pick up refs\n  // populated after initial mount (portals, conditional renders, etc.)\n  // eslint-disable-next-line react-hooks/exhaustive-deps\n  useLayoutEffect(() => {\n    const current = containerRef.current;\n    if (current !== element) {\n      setElement(current);\n    }\n  });\n\n  useLayoutEffect(() => {\n    if (!element) return;\n\n    const updateSize = () => {\n      const width = element.clientWidth;\n      const height = element.clientHeight;\n      setSize((prev) => {\n        if (prev.width === width && prev.height === height) return prev;\n        return { width, height, breakpoint: getBreakpoint(width) };\n      });\n    };\n\n    const rafUpdateSize = () => requestAnimationFrame(updateSize);\n\n    const resizeObserver = new ResizeObserver(rafUpdateSize);\n    resizeObserver.observe(element);\n    updateSize();\n\n    return () => {\n      resizeObserver.disconnect();\n    };\n  }, [element]);\n\n  return size;\n}\n","import clsx from \"clsx\";\nimport React, { forwardRef, useRef, useState } from \"react\";\nimport { useResponsiveContainer } from \"../../hooks/useResponsiveContainer\";\n\nexport interface ImageBlockProps extends React.HTMLAttributes<HTMLDivElement> {\n  src: string;\n  alt?: string;\n  imageLoading?: boolean;\n}\n\nexport const ImageBlock = forwardRef<HTMLDivElement, ImageBlockProps>(\n  ({ src, alt, className, imageLoading, ...rest }, ref) => {\n    const [isImageLoading, setIsImageLoading] = useState<boolean>(imageLoading ?? true);\n    const [hasError, setHasError] = useState<boolean>(false);\n    const containerRef = useRef<HTMLDivElement>(null);\n    const { breakpoint } = useResponsiveContainer(containerRef);\n    const isMobile = breakpoint === \"mobile\";\n\n    if (!src) return null;\n\n    return (\n      <div\n        ref={(node) => {\n          (containerRef as React.MutableRefObject<HTMLDivElement | null>).current = node;\n          if (typeof ref === \"function\") ref(node);\n          else if (ref) (ref as React.MutableRefObject<HTMLDivElement | null>).current = node;\n        }}\n        className={clsx(\n          \"openui-image-block-wrapper\",\n          {\n            \"openui-image-block-wrapper--mobile\": isMobile,\n            \"openui-image-block-wrapper--error\": hasError,\n          },\n          className,\n        )}\n        style={\n          src && !hasError ? ({ \"--bg-image\": `url(${src})` } as React.CSSProperties) : undefined\n        }\n        {...rest}\n      >\n        <img\n          src={src}\n          alt={alt}\n          className={clsx(\"openui-image-block-image\", {\n            \"openui-image-block-image--mobile\": isMobile,\n            \"openui-image-block-image--error\": hasError,\n          })}\n          onLoad={() => {\n            setIsImageLoading(false);\n            setHasError(false);\n          }}\n          onError={() => {\n            setIsImageLoading(false);\n            setHasError(true);\n          }}\n        />\n        {isImageLoading && <div className=\"openui-image-block-loader\" />}\n      </div>\n    );\n  },\n);\n\nImageBlock.displayName = \"ImageBlock\";\n"],"mappings":";;;;;;;;AAIA,SAAgB,cAAc,OAA2B;AACvD,KAAI,QAAQ,IAAK,QAAO;AACxB,KAAI,QAAQ,IAAK,QAAO;AACxB,QAAO;;;;;;;;AAeT,SAAgB,uBAAuB,cAA4D;CACjG,MAAM,CAAC,MAAM,YAAA,GAAA,MAAA,UAAmC;EAC9C,OAAO;EACP,QAAQ;EACR,YAAY;EACb,CAAC;CAEF,MAAM,CAAC,SAAS,eAAA,GAAA,MAAA,UAA2C,KAAK;AAKhE,EAAA,GAAA,MAAA,uBAAsB;EACpB,MAAM,UAAU,aAAa;AAC7B,MAAI,YAAY,QACd,YAAW,QAAQ;GAErB;AAEF,EAAA,GAAA,MAAA,uBAAsB;AACpB,MAAI,CAAC,QAAS;EAEd,MAAM,mBAAmB;GACvB,MAAM,QAAQ,QAAQ;GACtB,MAAM,SAAS,QAAQ;AACvB,YAAS,SAAS;AAChB,QAAI,KAAK,UAAU,SAAS,KAAK,WAAW,OAAQ,QAAO;AAC3D,WAAO;KAAE;KAAO;KAAQ,YAAY,cAAc,MAAM;KAAE;KAC1D;;EAGJ,MAAM,sBAAsB,sBAAsB,WAAW;EAE7D,MAAM,iBAAiB,IAAI,eAAe,cAAc;AACxD,iBAAe,QAAQ,QAAQ;AAC/B,cAAY;AAEZ,eAAa;AACX,kBAAe,YAAY;;IAE5B,CAAC,QAAQ,CAAC;AAEb,QAAO;;;;ACtDT,MAAa,cAAA,GAAA,MAAA,aACV,EAAE,KAAK,KAAK,WAAW,cAAc,GAAG,QAAQ,QAAQ;CACvD,MAAM,CAAC,gBAAgB,sBAAA,GAAA,MAAA,UAAuC,gBAAgB,KAAK;CACnF,MAAM,CAAC,UAAU,gBAAA,GAAA,MAAA,UAAiC,MAAM;CACxD,MAAM,gBAAA,GAAA,MAAA,QAAsC,KAAK;CACjD,MAAM,EAAE,eAAe,uBAAuB,aAAa;CAC3D,MAAM,WAAW,eAAe;AAEhC,KAAI,CAAC,IAAK,QAAO;AAEjB,QACE,iBAAA,GAAA,kBAAA,MAAC,OAAD;EACE,MAAM,SAAS;AACZ,gBAA+D,UAAU;AAC1E,OAAI,OAAO,QAAQ,WAAY,KAAI,KAAK;YAC/B,IAAM,KAAsD,UAAU;;EAEjF,YAAA,GAAA,KAAA,SACE,8BACA;GACE,sCAAsC;GACtC,qCAAqC;GACtC,EACD,UACD;EACD,OACE,OAAO,CAAC,WAAY,EAAE,cAAc,OAAO,IAAI,IAAI,GAA2B,KAAA;EAEhF,GAAI;YAjBN,CAmBE,iBAAA,GAAA,kBAAA,KAAC,OAAD;GACO;GACA;GACL,YAAA,GAAA,KAAA,SAAgB,4BAA4B;IAC1C,oCAAoC;IACpC,mCAAmC;IACpC,CAAC;GACF,cAAc;AACZ,sBAAkB,MAAM;AACxB,gBAAY,MAAM;;GAEpB,eAAe;AACb,sBAAkB,MAAM;AACxB,gBAAY,KAAK;;GAEnB,CAAA,EACD,kBAAkB,iBAAA,GAAA,kBAAA,KAAC,OAAD,EAAK,WAAU,6BAA8B,CAAA,CAC5D;;EAGX;AAED,WAAW,cAAc"}