104 lines
3.5 KiB
JavaScript
104 lines
3.5 KiB
JavaScript
"use client";
|
|
|
|
// packages/react/avatar/src/Avatar.tsx
|
|
import * as React from "react";
|
|
import { createContextScope } from "@radix-ui/react-context";
|
|
import { useCallbackRef } from "@radix-ui/react-use-callback-ref";
|
|
import { useLayoutEffect } from "@radix-ui/react-use-layout-effect";
|
|
import { Primitive } from "@radix-ui/react-primitive";
|
|
import { jsx } from "react/jsx-runtime";
|
|
var AVATAR_NAME = "Avatar";
|
|
var [createAvatarContext, createAvatarScope] = createContextScope(AVATAR_NAME);
|
|
var [AvatarProvider, useAvatarContext] = createAvatarContext(AVATAR_NAME);
|
|
var Avatar = React.forwardRef(
|
|
(props, forwardedRef) => {
|
|
const { __scopeAvatar, ...avatarProps } = props;
|
|
const [imageLoadingStatus, setImageLoadingStatus] = React.useState("idle");
|
|
return /* @__PURE__ */ jsx(
|
|
AvatarProvider,
|
|
{
|
|
scope: __scopeAvatar,
|
|
imageLoadingStatus,
|
|
onImageLoadingStatusChange: setImageLoadingStatus,
|
|
children: /* @__PURE__ */ jsx(Primitive.span, { ...avatarProps, ref: forwardedRef })
|
|
}
|
|
);
|
|
}
|
|
);
|
|
Avatar.displayName = AVATAR_NAME;
|
|
var IMAGE_NAME = "AvatarImage";
|
|
var AvatarImage = React.forwardRef(
|
|
(props, forwardedRef) => {
|
|
const { __scopeAvatar, src, onLoadingStatusChange = () => {
|
|
}, ...imageProps } = props;
|
|
const context = useAvatarContext(IMAGE_NAME, __scopeAvatar);
|
|
const imageLoadingStatus = useImageLoadingStatus(src, imageProps.referrerPolicy);
|
|
const handleLoadingStatusChange = useCallbackRef((status) => {
|
|
onLoadingStatusChange(status);
|
|
context.onImageLoadingStatusChange(status);
|
|
});
|
|
useLayoutEffect(() => {
|
|
if (imageLoadingStatus !== "idle") {
|
|
handleLoadingStatusChange(imageLoadingStatus);
|
|
}
|
|
}, [imageLoadingStatus, handleLoadingStatusChange]);
|
|
return imageLoadingStatus === "loaded" ? /* @__PURE__ */ jsx(Primitive.img, { ...imageProps, ref: forwardedRef, src }) : null;
|
|
}
|
|
);
|
|
AvatarImage.displayName = IMAGE_NAME;
|
|
var FALLBACK_NAME = "AvatarFallback";
|
|
var AvatarFallback = React.forwardRef(
|
|
(props, forwardedRef) => {
|
|
const { __scopeAvatar, delayMs, ...fallbackProps } = props;
|
|
const context = useAvatarContext(FALLBACK_NAME, __scopeAvatar);
|
|
const [canRender, setCanRender] = React.useState(delayMs === void 0);
|
|
React.useEffect(() => {
|
|
if (delayMs !== void 0) {
|
|
const timerId = window.setTimeout(() => setCanRender(true), delayMs);
|
|
return () => window.clearTimeout(timerId);
|
|
}
|
|
}, [delayMs]);
|
|
return canRender && context.imageLoadingStatus !== "loaded" ? /* @__PURE__ */ jsx(Primitive.span, { ...fallbackProps, ref: forwardedRef }) : null;
|
|
}
|
|
);
|
|
AvatarFallback.displayName = FALLBACK_NAME;
|
|
function useImageLoadingStatus(src, referrerPolicy) {
|
|
const [loadingStatus, setLoadingStatus] = React.useState("idle");
|
|
useLayoutEffect(() => {
|
|
if (!src) {
|
|
setLoadingStatus("error");
|
|
return;
|
|
}
|
|
let isMounted = true;
|
|
const image = new window.Image();
|
|
const updateStatus = (status) => () => {
|
|
if (!isMounted) return;
|
|
setLoadingStatus(status);
|
|
};
|
|
setLoadingStatus("loading");
|
|
image.onload = updateStatus("loaded");
|
|
image.onerror = updateStatus("error");
|
|
image.src = src;
|
|
if (referrerPolicy) {
|
|
image.referrerPolicy = referrerPolicy;
|
|
}
|
|
return () => {
|
|
isMounted = false;
|
|
};
|
|
}, [src, referrerPolicy]);
|
|
return loadingStatus;
|
|
}
|
|
var Root = Avatar;
|
|
var Image = AvatarImage;
|
|
var Fallback = AvatarFallback;
|
|
export {
|
|
Avatar,
|
|
AvatarFallback,
|
|
AvatarImage,
|
|
Fallback,
|
|
Image,
|
|
Root,
|
|
createAvatarScope
|
|
};
|
|
//# sourceMappingURL=index.mjs.map
|