import { useEffect, useRef } from 'react' import type { HTMLAttributes, ReactNode } from 'react' import { motion } from 'framer-motion' import { SparklingLine } from '../basic/icons-inline' export interface ImageGeneratingProps extends HTMLAttributes { width?: string height?: string speed?: number caption?: string captionClassName?: string showOverlay?: boolean overlayText?: string sparklingIcon?: ReactNode } function cn(...inputs: (string | undefined | false)[]): string { return inputs.filter(Boolean).join(' ') } const defaultSparkling = export function ImageGenerating({ width = 'var(--spacing-80)', height = 'var(--spacing-60)', speed = 1.0, caption = 'Spark is drawing...', captionClassName, className, style: styleProp, showOverlay = false, overlayText, sparklingIcon = defaultSparkling, ...props }: ImageGeneratingProps) { const containerRef = useRef(null) useEffect(() => { if (typeof CSS !== 'undefined' && CSS.registerProperty) { try { CSS.registerProperty({ name: '--a', syntax: '', inherits: true, initialValue: '0deg' }) CSS.registerProperty({ name: '--l', syntax: '', inherits: true, initialValue: '0' }) CSS.registerProperty({ name: '--x', syntax: '', inherits: false, initialValue: '0' }) CSS.registerProperty({ name: '--y', syntax: '', inherits: false, initialValue: '0' }) CSS.registerProperty({ name: '--o', syntax: '', inherits: false, initialValue: '0' }) CSS.registerProperty({ name: '--value', syntax: '', inherits: true, initialValue: '0deg' }) CSS.registerProperty({ name: '--width-ratio', syntax: '', inherits: true, initialValue: '0' }) CSS.registerProperty({ name: '--scale', syntax: '', inherits: true, initialValue: '0' }) } catch { // ignore } } }, []) useEffect(() => { const container = containerRef.current if (!container) return const updateSize = () => { const rect = container.getBoundingClientRect() if (rect.width > 0 && rect.height > 0) { const size = Math.max(rect.width, rect.height) container.style.setProperty('--actual-size', `${size}px`) } } const isPercent = (typeof width === 'string' && width.includes('%')) || (typeof height === 'string' && height.includes('%')) let resizeObserver: ResizeObserver | null = null const setup = () => { updateSize() resizeObserver = new ResizeObserver(updateSize) resizeObserver.observe(container) } if (isPercent) { const id = requestAnimationFrame(() => setup()) return () => { cancelAnimationFrame(id) resizeObserver?.disconnect() } } setup() return () => resizeObserver?.disconnect() }, [width, height]) return ( <>
{showOverlay ? (
{overlayText}
) : (
{sparklingIcon} {caption}
)}
) } ImageGenerating.displayName = 'ImageGenerating' export const ImageGenerationPlaceholder = ImageGenerating export type ImageGenerationPlaceholderProps = ImageGeneratingProps