@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
JavaScript
;
"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