'use client';
import type { CSSProperties, ReactNode } from 'react';
import type { PPTImageElement } from '@openmaic/dsl';
import { useElementShadow } from '../shared/useElementShadow';
import { useElementFlip } from '../shared/useElementFlip';
import { useClipImage } from './useClipImage';
import { useFilter } from './useFilter';
import { ImageOutline } from './ImageOutline';
export interface BaseImageElementProps {
elementInfo: PPTImageElement;
/**
* Optional render slot: replace the default with custom content.
* The slot receives `(element, resolvedSrc, defaultContent)` and is responsible
* for selecting placeholders, retry UI, or the renderer's prepared image.
* Its return value is authoritative, including `null`.
*/
renderImage?: (
element: PPTImageElement,
resolvedSrc: string,
defaultContent: ReactNode,
) => ReactNode;
}
export function BaseImageElement({ elementInfo, renderImage }: BaseImageElementProps) {
const { shadowStyle } = useElementShadow(elementInfo.shadow);
const { flipStyle } = useElementFlip(elementInfo.flipH, elementInfo.flipV);
const { clipShape, imgPosition } = useClipImage(elementInfo);
const { filter } = useFilter(elementInfo.filters);
const src = elementInfo.src;
// Soft-edge feather (a:softEdge): fade the image alpha to transparent over
// `softEdge` px at every edge. Two intersecting linear-gradient masks feather
// all four sides (corners get both). html2canvas-pro ignores CSS masks, so
// slideToPng bakes the same feather into pixels via the data-soft-edge hook.
const softEdge =
elementInfo.softEdge && elementInfo.softEdge > 0 ? elementInfo.softEdge : undefined;
const softEdgeMaskStyle: CSSProperties = softEdge
? (() => {
const grad = (dir: string) =>
`linear-gradient(${dir}, transparent 0, #000 ${softEdge}px, #000 calc(100% - ${softEdge}px), transparent 100%)`;
const mask = `${grad('to right')}, ${grad('to bottom')}`;
return {
maskImage: mask,
WebkitMaskImage: mask,
maskComposite: 'intersect',
WebkitMaskComposite: 'source-in',
maskRepeat: 'no-repeat',
WebkitMaskRepeat: 'no-repeat',
} as CSSProperties;
})()
: {};
const defaultContent = src ? (
<>
e.preventDefault()}
/>
{elementInfo.colorMask && (