| @@ -1,14 +1,16 @@ | ||
| 1 | -import blockStyleVariations from '@launch/_data/block-style-variations.json'; | |
| 1 | +import { isObject } from '@shared/lib/utils'; | |
| 2 | +import { | |
| 3 | + buildVibeResetCss, | |
| 4 | + withAppliedVariation, | |
| 5 | +} from '@shared/lib/vibe-preview'; | |
| 6 | +import { getVibes, vibeCssBySlug, vibesBySlug } from '@shared/lib/vibes'; | |
| 2 | 7 | import apiFetch from '@wordpress/api-fetch'; |
| 3 | 8 | import useSWRImmutable from 'swr/immutable'; |
| 4 | 9 | |
| 5 | 10 | export const useSiteVibesVariations = () => { |
| 6 | 11 | const { data, error, isLoading } = useSWRImmutable( |
| 7 | - { | |
| 8 | - key: 'site-vibes-variations', | |
| 9 | - themeSlug: window.extAgentData.context.themeSlug, | |
| 10 | - }, | |
| 12 | + { key: 'site-vibes-variations' }, | |
| 11 | 13 | fetcher, |
| 12 | 14 | ); |
| 13 | 15 | return { data, error, isLoading }; |
| 14 | 16 | }; |
| @@ -13,58 +15,72 @@ | ||
| 13 | 15 | return { data, error, isLoading }; |
| 14 | 16 | }; |
| 15 | 17 | |
| 16 | 18 | const fetcher = async () => { |
| 17 | - const stylesResponse = await apiFetch({ | |
| 18 | - path: '/wp/v2/global-styles/themes/extendable?context=edit', | |
| 19 | + const optionsResponse = await apiFetch({ | |
| 20 | + path: '/extendify/v1/launch/options?option=extendify_siteStyle', | |
| 19 | 21 | }); |
| 20 | 22 | |
| 21 | - const styles = stylesResponse?.styles; | |
| 22 | - if (!styles?.blocks) return null; | |
| 23 | + const siteStyle = optionsResponse?.data; | |
| 24 | + const currentVibe = siteStyle?.vibe || 'natural-1'; | |
| 23 | 25 | |
| 24 | - const optionsResponse = await apiFetch({ | |
| 25 | - path: '/extendify/v1/launch/options?option=extendify_siteStyle', | |
| 26 | - }); | |
| 26 | + // The site's current vibe is not necessarily offered on this surface. | |
| 27 | + const payloads = await getVibes(`agent,${currentVibe}`); | |
| 28 | + if (!payloads.length) return null; | |
| 27 | 29 | |
| 28 | - const currentVibe = optionsResponse?.data?.vibe; | |
| 30 | + const bySlug = vibesBySlug(payloads); | |
| 31 | + const [theme, variation] = await Promise.all([ | |
| 32 | + getThemeGlobalStyles(), | |
| 33 | + getAppliedVariation(siteStyle), | |
| 34 | + ]); | |
| 35 | + const themeStyles = withAppliedVariation(theme?.styles, variation?.styles); | |
| 36 | + const themeSettings = withAppliedVariation( | |
| 37 | + theme?.settings, | |
| 38 | + variation?.settings, | |
| 39 | + ); | |
| 29 | 40 | |
| 30 | 41 | return { |
| 31 | - vibes: extractVibesFromTheme(styles), | |
| 32 | - css: { ...blockStyleVariations }, | |
| 33 | - currentVibe: currentVibe || 'natural-1', | |
| 42 | + vibes: payloads.map(({ slug, title }) => ({ name: title || slug, slug })), | |
| 43 | + css: vibeCssBySlug(payloads), | |
| 44 | + payloads: bySlug, | |
| 45 | + resets: Object.fromEntries( | |
| 46 | + Object.keys(bySlug).map((slug) => [ | |
| 47 | + slug, | |
| 48 | + buildVibeResetCss({ | |
| 49 | + payloads: bySlug, | |
| 50 | + slug, | |
| 51 | + themeStyles, | |
| 52 | + themeSettings, | |
| 53 | + }), | |
| 54 | + ]), | |
| 55 | + ), | |
| 56 | + currentVibe, | |
| 34 | 57 | }; |
| 35 | 58 | }; |
| 36 | 59 | |
| 37 | -const extractVibesFromTheme = (themeStyles) => { | |
| 38 | - if (!themeStyles?.blocks) return []; | |
| 60 | +const getThemeGlobalStyles = async () => { | |
| 61 | + const themeSlug = window.extAgentData?.context?.themeSlug; | |
| 62 | + if (!themeSlug) return null; | |
| 39 | 63 | |
| 40 | - const vibeSet = new Set(); | |
| 41 | - const { blocks } = themeStyles; | |
| 64 | + try { | |
| 65 | + return await apiFetch({ | |
| 66 | + path: `/wp/v2/global-styles/themes/${themeSlug}?context=edit`, | |
| 67 | + }); | |
| 68 | + } catch { | |
| 69 | + return null; | |
| 70 | + } | |
| 71 | +}; | |
| 42 | 72 | |
| 43 | - // Scan all blocks for vibe variations | |
| 44 | - for (const blockObj of Object.values(blocks)) { | |
| 45 | - if (!blockObj?.variations) continue; | |
| 73 | +// Sites launched before extendify_siteStyle carried the variation hold it on | |
| 74 | +// the legacy AutoLaunch row only. | |
| 75 | +const getAppliedVariation = async (siteStyle) => { | |
| 76 | + if (isObject(siteStyle?.variation)) return siteStyle.variation; | |
| 46 | 77 | |
| 47 | - for (const styleName of Object.keys(blockObj.variations)) { | |
| 48 | - if (!styleName.startsWith('ext-preset--')) continue; | |
| 49 | - | |
| 50 | - // Split the slug: ext-preset--group--gradient-1--item-card-1--align-center | |
| 51 | - const parts = styleName.split('--'); | |
| 52 | - | |
| 53 | - if (parts.length >= 4) { | |
| 54 | - const vibe = parts[2]; // 'gradient-1' ← This is what we want! | |
| 55 | - if (vibe) vibeSet.add(vibe); | |
| 56 | - } | |
| 57 | - } | |
| 78 | + try { | |
| 79 | + const { data } = await apiFetch({ | |
| 80 | + path: '/extendify/v1/launch/options?option=extendify_site_style', | |
| 81 | + }); | |
| 82 | + return isObject(data?.variation) ? data.variation : null; | |
| 83 | + } catch { | |
| 84 | + return null; | |
| 58 | 85 | } |
| 59 | - | |
| 60 | - return Array.from(vibeSet).map((slug) => ({ | |
| 61 | - name: slugToDisplayName(slug), // "gradient-1" → "Gradient 1" | |
| 62 | - slug, | |
| 63 | - })); | |
| 64 | 86 | }; |
| 65 | - | |
| 66 | -const slugToDisplayName = (slug) => | |
| 67 | - slug | |
| 68 | - .split('-') | |
| 69 | - .map((word) => word.charAt(0).toUpperCase() + word.slice(1)) | |
| 70 | - .join(' '); | |