diff --git a/.changeset/rich-hands-pull.md b/.changeset/rich-hands-pull.md new file mode 100644 index 0000000..f1f3488 --- /dev/null +++ b/.changeset/rich-hands-pull.md @@ -0,0 +1,5 @@ +--- +'@clutch-creator/toolkit': patch +--- + +Image support client side rendering diff --git a/src/components/ClientImage/index.tsx b/src/components/ClientImage/index.tsx deleted file mode 100644 index 106a212..0000000 --- a/src/components/ClientImage/index.tsx +++ /dev/null @@ -1,42 +0,0 @@ -'use client'; - -import NextImage from 'next/image'; -import React, { cloneElement, use } from 'react'; - -type TClientImageProps = { - // @deprecated This component is used to wrap a lazy-loaded image component. - children?: React.LazyExoticComponent>; -} & React.ComponentProps; - -export const ClientImage = ({ children, ...props }: TClientImageProps) => { - // @deprecated: This component is used to wrap a lazy-loaded image component. - if (children) { - const child = - children?.$$typeof === Symbol.for('react.lazy') - ? // @ts-expect-error next react lazy payload - use(children._payload) - : children; - - return React.isValidElement(child) - ? cloneElement(child, { ...props }) - : child; - } - - if (!props.src) return null; - - let placeholderVal = props.placeholder; - - if (typeof placeholderVal === 'boolean') { - placeholderVal = placeholderVal ? 'blur' : 'empty'; - } - - return ( - - ); -}; diff --git a/src/components/Image/index.tsx b/src/components/Image/index.tsx index 1fb138c..4f73e6a 100644 --- a/src/components/Image/index.tsx +++ b/src/components/Image/index.tsx @@ -1,8 +1,8 @@ -import NextImage from 'next/image'; +import NextImage, { StaticImageData } from 'next/image'; import { getImageInfo } from './utils'; type TClutchImageProps = { - src: string; + src: string | StaticImageData; alt: string; fill?: boolean; sizes?: string; @@ -16,22 +16,37 @@ type TClutchImageProps = { type PlaceholderValue = 'blur' | 'empty' | `data:image/${string}`; -export async function Image({ +export function Image(props: TClutchImageProps) { + const { src } = props; + + if (!src) return null; + + // If not in browser (server-side), use ServerImage + if (typeof window === 'undefined') { + return ; + } + + return ; +} + +async function ServerImage({ src, className, placeholder, sizes = 'auto', ...props }: TClutchImageProps) { - if (!src) return null; - - const { width, height, format, blurDataURL } = - typeof src === 'string' ? await getImageInfo(src) : src; + const imageInfo = typeof src === 'string' ? await getImageInfo(src) : src; + const { width, height, blurDataURL } = imageInfo; let placeholderVal: PlaceholderValue = placeholder ? 'blur' : 'empty'; + const isSvg = + 'format' in imageInfo + ? imageInfo.format === 'svg' + : imageInfo.src.endsWith('.svg'); const size = width + height; - if (placeholder === undefined && format !== 'svg' && size > 80) { + if (placeholder === undefined && !isSvg && size > 80) { placeholderVal = 'blur'; } @@ -48,3 +63,17 @@ export async function Image({ /> ); } + +function ClientImage({ + src, + className, + sizes = 'auto', + placeholder, + ...props +}: TClutchImageProps) { + if (typeof src === 'string') { + return ; + } + + return ; +}