UNPKG

@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

230 lines (220 loc) 8.31 kB
"use strict"; "use client"; var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/components/index.ts var components_exports = {}; __export(components_exports, { BetterImage: () => BetterImage, BetterVersion: () => BetterVersion, Fallback: () => Fallback2, Img: () => Img }); module.exports = __toCommonJS(components_exports); // src/components/ui/BetterImage.ts var React4 = __toESM(require("react")); // src/better.ts var import_react2 = __toESM(require("react")); var import_client = require("react-dom/client"); var import_image = __toESM(require("next/image")); var import_jsx_runtime = require("react/jsx-runtime"); // src/context/index.ts var import_react = __toESM(require("react")); var BetterContext = import_react.default.createContext( void 0 ); var useBetter = /* @__PURE__ */ __name(() => { const context = import_react.default.useContext(BetterContext); if (context === void 0) { throw new Error("useBetter must be used within a BetterProvider"); } return context; }, "useBetter"); // src/better.ts var R = import_react2.default.forwardRef(({ ...props }, ref) => { const [imageStatus, setImageStatus] = import_react2.default.useState("idle"); return (0, import_jsx_runtime.jsx)(BetterContext.Provider, { value: { imageStatus, setImageStatus }, children: (0, import_jsx_runtime.jsx)("div", { ...props, ref }) }); }); R.displayName = "BetterVersion"; var I = import_react2.default.forwardRef(({ ...props }, ref) => { const imageStatus = useImageStatus(props); return imageStatus === "loaded" && (0, import_jsx_runtime.jsx)(import_image.default, { ...props, ref }); }); I.displayName = "Image"; var F = import_react2.default.forwardRef( ({ delay, onFailString, ...props }, ref) => { const [canRender, setCanRender] = import_react2.default.useState(delay === void 0); const { imageStatus } = useBetter(); import_react2.default.useEffect(() => { if (delay !== void 0) { const timeout = setTimeout(() => { setCanRender(true); }, delay); return () => clearTimeout(timeout); } }, [delay]); return canRender && imageStatus === "error" ? (0, import_jsx_runtime.jsx)("div", { ...props, ref, children: onFailString || "" }) : canRender && imageStatus !== "loaded" ? (0, import_jsx_runtime.jsx)("div", { ...props, ref }) : null; } ); F.displayName = "Fallback"; var useImageStatus = /* @__PURE__ */ __name((ImageProps) => { const { imageStatus, setImageStatus } = useBetter(); import_react2.default.useEffect(() => { if (!ImageProps?.src) { setImageStatus("error"); return; } setImageStatus("loading"); const tempImageDiv = document.createElement("div"); tempImageDiv.style.cssText = "position: absolute; visibility: hidden; top: -9999px; left: -9999px;"; document.body.appendChild(tempImageDiv); const tempImageRoot = (0, import_client.createRoot)(tempImageDiv); const handleComplete = /* @__PURE__ */ __name(() => { setImageStatus("loaded"); cleanup(); }, "handleComplete"); const handleError = /* @__PURE__ */ __name(() => { setImageStatus("error"); cleanup(); }, "handleError"); const cleanup = /* @__PURE__ */ __name(() => { tempImageRoot.unmount(); if (tempImageDiv.parentNode) { document.body.removeChild(tempImageDiv); } }, "cleanup"); tempImageRoot.render( (0, import_jsx_runtime.jsx)(import_image.default, { ...ImageProps, alt: Math.random().toString(), onLoad: handleComplete, onError: handleError, priority: true }) ); return () => { cleanup(); }; }, [ImageProps?.src, setImageStatus]); return imageStatus; }, "useImageStatus"); // src/index.ts var Root = R; var Image2 = I; var Fallback = F; // src/components/ui/BetterImage.ts var import_jsx_runtime3 = require("react/jsx-runtime"); // src/lib/utils.ts var pras = /* @__PURE__ */ __name((...args) => { return args.filter(Boolean).join(" "); }, "pras"); // src/components/ui/svg/Loader.tsx var import_react3 = __toESM(require("react")); var import_jsx_runtime2 = require("react/jsx-runtime"); var Loader = import_react3.default.forwardRef(({ size, ...props }, ref) => { return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)( "svg", { ...props, xmlns: "http://www.w3.org/2000/svg", width: size || 24, height: size || 24, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M12 2v4" }), /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "m16.2 7.8 2.9-2.9" }), /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M18 12h4" }), /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "m16.2 16.2 2.9 2.9" }), /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M12 18v4" }), /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "m4.9 19.1 2.9-2.9" }), /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M2 12h4" }), /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "m4.9 4.9 2.9 2.9" }) ] } ); }); var Loader_default = Loader; // src/components/ui/BetterImage.ts var BetterVersion = React4.forwardRef(({ className, ...props }, ref) => { return (0, import_jsx_runtime3.jsx)(Root, { ...props, ref, className: pras("relative flex h-full w-full", className) }); }); BetterVersion.displayName = Root.displayName; var Img = React4.forwardRef(({ className, ...props }, ref) => { return (0, import_jsx_runtime3.jsx)(Image2, { ...props, ref, className: pras("h-full w-full", className) }); }); Img.displayName = Image2.displayName; var Fallback2 = React4.forwardRef(({ className, ...props }, ref) => { return (0, import_jsx_runtime3.jsx)(Fallback, { ...props, ref, className: pras( "flex h-full w-full items-center justify-center", className ), children: (0, import_jsx_runtime3.jsx)(Loader_default, { className: "h-4 w-4 animate-spin", size: 24 }) }); }); Fallback2.displayName = Fallback.displayName; var BetterImage = React4.forwardRef(({ src, alt, className, onFailString, delay, ...props }, ref) => { return (0, import_jsx_runtime3.jsx)(BetterVersion, { ref, children: [ (0, import_jsx_runtime3.jsx)(Img, { src, alt, className, ...props }, "image"), (0, import_jsx_runtime3.jsx)(Fallback2, { onFailString, delay }, "fallback") ] }); }); BetterImage.displayName = "BetterImage"; // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { BetterImage, BetterVersion, Fallback, Img }); //# sourceMappingURL=components.js.map