import { useState, useRef } from "react"; import { ImageIcon } from "lucide-react"; import { useTranslation } from "react-i18next"; import { registerWidget } from "./WidgetRegistry"; import type { ImageWidgetConfig, WidgetComponentProps, } from "@/types/homepage-types"; import { GRID_SIZE } from "@/types/homepage-types"; import { WidgetTitle } from "./WidgetTitle"; const FIT_MAP = { contain: "object-contain", cover: "object-cover", fill: "object-fill", }; function ImageWidget({ widget, config, isReadOnly, }: WidgetComponentProps) { const { t } = useTranslation(); const { imageUrl, fit, alt, linkUrl } = config; const [failed, setFailed] = useState(false); const mouseDownRef = useRef<{ x: number; y: number } | null>(null); const titleBar = widget.title ? ( } /> ) : null; const content = (
{titleBar}
{imageUrl && !failed ? ( {alt setFailed(true)} /> ) : (
{t("homepage.noImage")}
)}
); if (isReadOnly || !linkUrl) return content; return ( { mouseDownRef.current = { x: e.clientX, y: e.clientY }; }} onClick={(e) => { const s = mouseDownRef.current; if ( s && (Math.abs(e.clientX - s.x) > 4 || Math.abs(e.clientY - s.y) > 4) ) e.preventDefault(); mouseDownRef.current = null; }} > {content} ); } registerWidget({ id: "image_widget", name: "Image", description: "Display any image from a URL", category: "info", icon: , defaultConfig: { imageUrl: "", fit: "contain" }, defaultSize: { w: GRID_SIZE * 10, h: GRID_SIZE * 8 }, minSize: { w: GRID_SIZE * 2, h: GRID_SIZE * 2 }, component: ImageWidget, }); export { ImageWidget };