@prass/betterimage
Version:
BetterImage is a Next.js-focused library for building optimized image components with advanced features, including fallback animations. It enhances Next.js's built-in Image component, offering seamless optimization and an improved user experience for your
1 lines • 8.4 kB
Source Map (JSON)
{"version":3,"sources":["../src/better.ts","../src/context/index.ts","../src/index.ts"],"sourcesContent":["\"use client\";\nimport React from \"react\";\nimport { createRoot } from \"react-dom/client\";\nimport Image from \"next/image\";\nimport { jsx } from \"react/jsx-runtime\";\nimport { useBetter, ImageLoadingStatus, BetterContext } from \"./context\";\n\n/**\n * This is a type for the props of the `div` element.\n * It is used as a type for the `Root` component.\n */\ntype RProps = React.ComponentPropsWithoutRef<\"div\">;\n\n/**\n * This is the main component of the library.\n * It renders a `div` element with the `children` prop.\n * It also renders a `BetterContext.Provider` element with the `value` prop.\n * The `value` prop is an object with two properties: `imageStatus` and `setImageStatus`.\n * `imageStatus` is a state variable that can be one of the following values: \"idle\", \"loading\", \"loaded\", or \"error\".\n * `setImageStatus` is a function that sets the `imageStatus` state variable.\n * The `children` prop is a React component that is rendered inside the `div` element.\n */\nconst R = React.forwardRef<HTMLDivElement, RProps>(({ ...props }, ref) => {\n const [imageStatus, setImageStatus] =\n React.useState<ImageLoadingStatus>(\"idle\");\n\n return jsx(BetterContext.Provider, {\n value: { imageStatus, setImageStatus },\n children: jsx(\"div\", { ...props, ref }),\n });\n});\nR.displayName = \"BetterVersion\";\n\n/**\n * This is a type for the props of the `Image` component.\n * It is used as a type for the `BetterImage` component.\n */\ntype IProps = React.ComponentPropsWithoutRef<typeof Image>;\n\n/**\n * This component renders an `Image` element with the `src` prop.\n * It uses the `useImageStatus` hook to determine the status of the image.\n * If the status is \"loaded\", it renders the `Image` element.\n * Otherwise, it renders nothing.\n */\nconst I = React.forwardRef<HTMLImageElement, IProps>(({ ...props }, ref) => {\n const imageStatus = useImageStatus(props);\n\n return (\n imageStatus === \"loaded\" &&\n jsx(Image, {\n ...props,\n ref,\n })\n );\n});\n\nI.displayName = \"Image\";\n\n/**\n * This is a type for the props of the `Fallback` component.\n * It is used as a type for the `Fallback` component.\n */\ntype FProps = React.ComponentPropsWithoutRef<\"div\"> & {\n /**\n * An optional number prop that specifies how long to wait before rendering\n * the fallback element.\n */\n delay?: number;\n\n /**\n * An optional string prop that specifies the content of the fallback element.\n */\n onFailString?: string;\n};\n\n/**\n * This component renders a `div` element with the `children` prop.\n * It uses the `useBetter` hook to determine the status of the image.\n * If the status is \"error\" and the `delay` prop is not set, it renders the `children` prop.\n * If the status is \"error\" and the `delay` prop is set, it renders a temporary `div` element\n * with the `onFailString` prop as its content.\n * If the status is not \"error\", it renders nothing.\n */\nconst F = React.forwardRef<HTMLDivElement, FProps>(\n ({ delay, onFailString, ...props }, ref) => {\n const [canRender, setCanRender] = React.useState(delay === undefined);\n const { imageStatus } = useBetter();\n\n React.useEffect(() => {\n if (delay !== undefined) {\n const timeout = setTimeout(() => {\n setCanRender(true);\n }, delay);\n return () => clearTimeout(timeout);\n }\n }, [delay]);\n\n return canRender && imageStatus === \"error\"\n ? jsx(\"div\", { ...props, ref, children: onFailString || \"\" })\n : canRender && imageStatus !== \"loaded\"\n ? jsx(\"div\", { ...props, ref })\n : null;\n }\n);\nF.displayName = \"Fallback\";\n\n/**\n * This hook uses the `useBetter` hook to determine the status of the image.\n * It returns the current status of the image.\n */\nconst useImageStatus = (ImageProps?: IProps) => {\n const { imageStatus, setImageStatus } = useBetter();\n\n React.useEffect(() => {\n if (!ImageProps?.src) {\n setImageStatus(\"error\");\n return;\n }\n\n setImageStatus(\"loading\");\n\n const tempImageDiv = document.createElement(\"div\");\n tempImageDiv.style.cssText =\n \"position: absolute; visibility: hidden; top: -9999px; left: -9999px;\";\n document.body.appendChild(tempImageDiv);\n\n const tempImageRoot = createRoot(tempImageDiv);\n\n const handleComplete = () => {\n setImageStatus(\"loaded\");\n cleanup();\n };\n\n const handleError = () => {\n setImageStatus(\"error\");\n cleanup();\n };\n\n const cleanup = () => {\n tempImageRoot.unmount();\n if (tempImageDiv.parentNode) {\n document.body.removeChild(tempImageDiv);\n }\n };\n\n tempImageRoot.render(\n jsx(Image, {\n ...ImageProps,\n alt: Math.random().toString(),\n onLoad: handleComplete,\n onError: handleError,\n priority: true,\n })\n );\n\n return () => {\n cleanup();\n };\n }, [ImageProps?.src, setImageStatus]);\n\n return imageStatus;\n};\n\nexport { R, I, F, type RProps, type IProps, type FProps };\n","\"use client\";\nimport React from \"react\";\n\nexport type ImageLoadingStatus = \"idle\" | \"loading\" | \"loaded\" | \"error\";\n\ninterface BetterContextType {\n imageStatus: \"idle\" | \"loading\" | \"loaded\" | \"error\";\n setImageStatus: React.Dispatch<\n React.SetStateAction<\"idle\" | \"loading\" | \"loaded\" | \"error\">\n >;\n}\n\nexport const BetterContext = React.createContext<BetterContextType | undefined>(\n undefined\n);\n\nexport const useBetter = () => {\n const context = React.useContext(BetterContext);\n if (context === undefined) {\n throw new Error(\"useBetter must be used within a BetterProvider\");\n }\n return context;\n};\n","\"use client\";\nimport * as BetterThings from \"./better\";\n\nconst Root = BetterThings.R;\nconst Image = BetterThings.I;\nconst Fallback = BetterThings.F;\ntype RootProps = BetterThings.RProps;\ntype ImageProps = BetterThings.IProps;\ntype FallbackProps = BetterThings.FProps;\n\nexport {\n Root,\n Image,\n Fallback,\n type RootProps,\n type ImageProps,\n type FallbackProps,\n};"],"mappings":"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","names":["React","React","Image"]}