import { usePalettes } from '@agent/hooks/usePalettes'; import { useVariationOverride } from '@agent/hooks/useVariationOverride'; import { useChatStore } from '@agent/state/chat'; import { remapPaletteDuotone } from '@shared/lib/palette-preview'; import { useEffect, useMemo, useRef, useState } from '@wordpress/element'; import { __ } from '@wordpress/i18n'; const colorsArrayToMap = (colors) => { const map = {}; colors.forEach(({ slug, color }) => { map[slug] = color; }); return map; }; const getBackgroundColor = (colors) => { const bgSlugs = ['base', 'background', 'bg']; for (const slug of bgSlugs) { if (colors[slug]) return colors[slug]; } return '#ffffff'; }; const buildPreviewCss = (colorsMap) => { const styleEl = document.getElementById('global-styles-inline-css'); if (!styleEl) return ''; let css = styleEl.innerHTML; Object.entries(colorsMap).forEach(([slug, hex]) => { const regex = new RegExp( `(--wp--preset--color--${slug}\\s*:\\s*)([^;]+)(;)`, 'g', ); css = css.replace(regex, `$1${hex}$3`); }); return css; }; const themeReference = () => { const presets = window.extAgentData?.context?.themePresets; return { colors: presets?.colors, settings: { color: { duotone: presets?.duotone } }, }; }; export const SelectGeneratedPalette = ({ inputs, onConfirm, onCancel, onRetry, }) => { const [selected, setSelected] = useState(null); const [previewCss, setPreviewCss] = useState(''); const { addMessage, messages } = useChatStore(); const { applied } = usePalettes(); const aiPalettes = inputs?.palettes; const palettes = useMemo( () => aiPalettes?.map(({ name, colors }) => { return { name, colors: colorsArrayToMap(colors), colorsArray: colors, }; }) || [], [aiPalettes], ); const noPalettes = !aiPalettes?.length || palettes.length === 0; const selectedPalette = palettes.find(({ name }) => name === selected); // foreground-and-background is served-only; the theme never registers it. const duotoneTheme = useMemo(() => { if (!selectedPalette) return null; const reference = applied ?? themeReference(); return remapPaletteDuotone(reference, selectedPalette.colors) ?? null; }, [applied, selectedPalette]); const { undoChange } = useVariationOverride({ css: previewCss, duotoneTheme, }); const confirmed = useRef(false); useEffect(() => { return () => { if (!confirmed.current) undoChange(); }; }, []); useEffect(() => { if (!noPalettes) return; const timer = setTimeout(() => onCancel(), 100); const content = __( 'We were unable to generate color palettes. Please try again.', 'extendify-local', ); const last = messages.at(-1)?.details?.content; if (content === last) return () => clearTimeout(timer); addMessage('message', { role: 'assistant', content, error: true }); return () => clearTimeout(timer); }, [addMessage, onCancel, noPalettes, messages]); const handleRetry = () => { undoChange(); onRetry(); }; const handleConfirm = () => { if (!selectedPalette) return; confirmed.current = true; onConfirm({ data: { palette: { name: selectedPalette.name, colors: selectedPalette.colorsArray.map(({ slug, color }) => ({ slug, color, name: slug, })), }, duotone: duotoneTheme, }, shouldRefreshPage: true, }); }; if (noPalettes) return null; return (