83 lines
2.2 KiB
TypeScript
83 lines
2.2 KiB
TypeScript
import _ from "lodash";
|
|
import React, { DetailedHTMLProps, ImgHTMLAttributes } from "react";
|
|
import { twMerge } from "tailwind-merge";
|
|
|
|
export type TWUIImageProps = DetailedHTMLProps<
|
|
ImgHTMLAttributes<HTMLImageElement>,
|
|
HTMLImageElement
|
|
> & {
|
|
size?: number;
|
|
circle?: boolean;
|
|
bgImg?: boolean;
|
|
backgroundImage?: boolean;
|
|
fallbackImageSrc?: string;
|
|
srcLight?: string;
|
|
srcDark?: string;
|
|
};
|
|
|
|
/**
|
|
* # Image Component
|
|
* @className twui-img
|
|
*/
|
|
export default function Img({ ...props }: TWUIImageProps) {
|
|
const width = props.size || props.width;
|
|
const height = props.size || props.height;
|
|
const sizeRatio = width && height ? Number(width) / Number(height) : 1;
|
|
|
|
const finalProps = _.omit(props, [
|
|
"size",
|
|
"circle",
|
|
"bgImg",
|
|
"backgroundImage",
|
|
"fallbackImageSrc",
|
|
"srcLight",
|
|
"srcDark",
|
|
]);
|
|
|
|
const interpolatedProps: typeof props = {
|
|
...finalProps,
|
|
width: width,
|
|
height: height,
|
|
className: twMerge(
|
|
"object-cover",
|
|
props.circle && "rounded-full",
|
|
props.bgImg || props.backgroundImage
|
|
? "absolute top-0 left-0 w-full h-full object-cover z-0"
|
|
: "",
|
|
"twui-img",
|
|
props.className
|
|
),
|
|
onError: (e) => {
|
|
if (props.fallbackImageSrc) {
|
|
e.currentTarget.src = props.fallbackImageSrc;
|
|
}
|
|
props.onError?.(e);
|
|
},
|
|
};
|
|
|
|
if (props.srcDark && props.srcLight) {
|
|
return (
|
|
<React.Fragment>
|
|
<img
|
|
{...interpolatedProps}
|
|
className={twMerge(
|
|
"hidden dark:block",
|
|
interpolatedProps.className
|
|
)}
|
|
src={props.srcDark}
|
|
/>
|
|
<img
|
|
{...interpolatedProps}
|
|
className={twMerge(
|
|
"block dark:hidden",
|
|
interpolatedProps.className
|
|
)}
|
|
src={props.srcLight}
|
|
/>
|
|
</React.Fragment>
|
|
);
|
|
}
|
|
|
|
return <img {...interpolatedProps} />;
|
|
}
|