UNPKG

@lobehub/ui

Version:

Lobe UI is an open-source UI component library for building AIGC web apps

164 lines (163 loc) 5.35 kB
"use client"; import FlexBasic_default from "../Flex/FlexBasic.mjs"; import SkeletonAvatar from "../Skeleton/SkeletonAvatar.mjs"; import { usePreviewGroupContext } from "./PreviewGroup.mjs"; import { FALLBACK_DARK, FALLBACK_LIGHT, styles, variants } from "./style.mjs"; import { openPreview } from "./viewer/registry.mjs"; import PreviewOutlet from "./viewer/PreviewOutlet.mjs"; import { memo, useCallback, useEffect, useId, useMemo, useRef, useState } from "react"; import { jsx, jsxs } from "react/jsx-runtime"; import { cx, useThemeMode } from "antd-style"; //#region src/Image/Image.tsx const resolvePreview = (groupPreview, imagePreview) => { if (imagePreview === false) return false; if (imagePreview === void 0 && groupPreview === false) return false; const groupOptions = typeof groupPreview === "object" ? groupPreview : void 0; const imageOptions = typeof imagePreview === "object" ? imagePreview : void 0; return { ...groupOptions, ...imageOptions }; }; const Image = memo(({ ref, style, preview, isLoading, maxHeight = "100%", maxWidth = "100%", minHeight, minWidth, actions, className, alwaysShowActions, variant = "filled", objectFit = "cover", classNames, styles: customStyles, onClick, onError, onPointerDown, width, height, size, src, alt, loading = "lazy", ...rest }) => { const { isDarkMode } = useThemeMode(); const [hasError, setHasError] = useState(false); const lastSrcRef = useRef(src); const imgRef = useRef(null); const preOpenFocusRef = useRef(null); const id = useId(); const group = usePreviewGroupContext(); if (lastSrcRef.current !== src) { lastSrcRef.current = src; if (hasError) setHasError(false); } const resolvedWidth = width ?? size; const resolvedHeight = height ?? size; const resolvedPreview = resolvePreview(group?.preview, preview); const previewEnabled = resolvedPreview !== false; const resolvedOptions = useMemo(() => previewEnabled ? { autoZoomThreshold: 2, defaultZoom: "auto", maxScale: 8, ...resolvedPreview } : void 0, [previewEnabled, resolvedPreview]); const previewSrc = resolvedOptions?.src; useEffect(() => { if (!group) return; return group.register({ getElement: () => imgRef.current, id, options: resolvedOptions, previewSrc, src: src ?? "" }); }, [ group, id, src, previewSrc, resolvedOptions ]); const handleError = useCallback((event) => { setHasError(true); onError?.(event); }, [onError]); const handlePointerDown = useCallback((event) => { onPointerDown?.(event); const active = document.activeElement; preOpenFocusRef.current = active instanceof HTMLElement && active !== document.body && active !== document.documentElement ? active : null; }, [onPointerDown]); const handleClick = useCallback((event) => { onClick?.(event); if (!previewEnabled || !imgRef.current || !resolvedOptions) return; const clickedEntry = { element: imgRef.current, options: resolvedOptions, previewSrc, src: imgRef.current.currentSrc || imgRef.current.src }; const openerFocusElement = preOpenFocusRef.current; if (!group) { openPreview(clickedEntry, void 0, 0, openerFocusElement); return; } const galleryEntries = []; let clickedIndex = -1; for (const groupEntry of group.getEntries()) { const element = groupEntry.getElement(); if (!element || !groupEntry.options) continue; if (element === imgRef.current) clickedIndex = galleryEntries.length; galleryEntries.push({ element, options: groupEntry.options, previewSrc: groupEntry.previewSrc, src: element.currentSrc || element.src }); } openPreview(clickedEntry, galleryEntries, clickedIndex >= 0 ? clickedIndex : 0, openerFocusElement); }, [ onClick, previewEnabled, resolvedOptions, previewSrc, group ]); const actionsClassName = alwaysShowActions ? styles.actionsVisible : styles.actionsHidden; if (isLoading) return /* @__PURE__ */ jsx("div", { onClick, children: /* @__PURE__ */ jsx(SkeletonAvatar, { active: true, height: resolvedHeight, style: { maxHeight, maxWidth, minHeight, minWidth }, width: resolvedWidth }) }); return /* @__PURE__ */ jsxs(FlexBasic_default, { className: cx(variants({ variant }), className), ref, style, children: [ actions && /* @__PURE__ */ jsx("div", { className: cx(actionsClassName, alwaysShowActions ? "" : "actions-hidden"), children: actions }), /* @__PURE__ */ jsx("div", { className: cx(styles.wrapper, classNames?.wrapper), style: customStyles?.wrapper, children: /* @__PURE__ */ jsx("img", { alt, className: cx(styles.image, previewEnabled && styles.previewable, classNames?.image), height: resolvedHeight, loading, ref: imgRef, src: hasError ? isDarkMode ? FALLBACK_DARK : FALLBACK_LIGHT : src, width: resolvedWidth, style: { height: resolvedHeight, maxHeight, maxWidth, minHeight, minWidth, objectFit, width: resolvedWidth, ...customStyles?.image }, onClick: handleClick, onError: handleError, onPointerDown: handlePointerDown, ...rest }) }), previewEnabled && /* @__PURE__ */ jsx(PreviewOutlet, { elementRef: imgRef }) ] }); }); Image.displayName = "Image"; //#endregion export { Image as default }; //# sourceMappingURL=Image.mjs.map