diff --git a/fv-cms-vendored/app-fragments/fvcms-cms-panel/fvcms-cms-panel.js b/fv-cms-vendored/app-fragments/fvcms-cms-panel/fvcms-cms-panel.js index c1088dc..2f799ee 100644 --- a/fv-cms-vendored/app-fragments/fvcms-cms-panel/fvcms-cms-panel.js +++ b/fv-cms-vendored/app-fragments/fvcms-cms-panel/fvcms-cms-panel.js @@ -1162,7 +1162,12 @@ const isSection = /\bsection\b/i.test(clsNoId); let typeLabel = 'container'; let icon = '▦'; if (widgetMatch) { - typeLabel = widgetMatch[1].replace(/^eael-/, 'eael-').replace(/\.default$/, ''); + // Strip the framework prefix (e.g. 'eael-', 'elementor-') and the + // '.default' variant suffix to derive a clean display label. + // The label is shown in the CMS panel UI for operator reference only. + typeLabel = widgetMatch[1] + .replace(/^(eael|elementor|premium-addon)-/, '') + .replace(/\.default$/, ''); icon = getIconForType(typeLabel); } else if (isSection) { typeLabel = 'section'; diff --git a/fv-cms-vendored/app-fragments/fvcms-module-editor/fvcms-module-editor.js b/fv-cms-vendored/app-fragments/fvcms-module-editor/fvcms-module-editor.js index 372404f..50ed4cd 100644 --- a/fv-cms-vendored/app-fragments/fvcms-module-editor/fvcms-module-editor.js +++ b/fv-cms-vendored/app-fragments/fvcms-module-editor/fvcms-module-editor.js @@ -1,6 +1,7 @@ /* FV-CMS-VENDORED v1.2.0 — DO NOT EDIT IN PLACE. Source: github.com/avidtech6/freshvibe-cms. To update, run: fvcms-update */ // fvcms-module-editor.js — fragment.oscar.module-editor.001 -// Lazy-loadable module editor. Currently supports eael-post-carousel. +// Lazy-loadable module editor. Currently supports carousel widgets detected +// from legacy source pages (data-widget_type from Elementor/EAEL). // Click W-N[carousel] badge → opens an editor panel that reads the widget's // data-settings JSON, lets operator tweak values, and writes back to localStorage // + the live widget's data-settings attribute. diff --git a/fv-cms-vendored/runtime/edge-panel/edge-panel.js b/fv-cms-vendored/runtime/edge-panel/edge-panel.js index 11feddf..2949a72 100644 --- a/fv-cms-vendored/runtime/edge-panel/edge-panel.js +++ b/fv-cms-vendored/runtime/edge-panel/edge-panel.js @@ -190,24 +190,30 @@ return; } const lastSection = sections[sections.length - 1]; - const target = lastSection.querySelector('.elementor-widget-container') || lastSection; + // FreshVibe-native selector first, legacy source-page fallback after. + const target = lastSection.querySelector('.fvcms-widget-container, .elementor-widget-container') || lastSection; target.insertAdjacentHTML('beforeend', html); const sectionNum = sections.length; showToast('Inserted ' + widgetName + ' into S-' + sectionNum); } function addSection(panelEl, mgr, host) { - const sections = document.querySelectorAll('.e-parent'); + // Count existing FreshVibe-native regions (preferred); fall back to legacy + // source-page markers when running on a pre-migration page. + const sections = document.querySelectorAll('[data-fvcms-region], .e-parent'); const n = sections.length + 1; - const sectionHtml = '
' - + '
' - + '
' - + '
' - + '
' - + '
' - + '
' - + '

New Section ' + n + '

' - + '
'; + // FreshVibe-native output: a fvcms-section region with a fvcms-heading + // child. Class names follow the fvcms-* convention; data-fvcms-region + // marks the region for the runtime's region-scanner to discover. + const sectionHtml = '
' + + '
' + + '
' + + '
' + + '
' + + '
' + + '
' + + '

New Section ' + n + '

' + + '
'; const main = document.querySelector('main') || document.body; main.insertAdjacentHTML('beforeend', sectionHtml); showToast('Added new section S-' + n); @@ -227,8 +233,9 @@ const MEDIA_HEADERS = { 'Authorization': FES_BEARER }; function getCurrentSection() { - // Prefer a focused .e-parent (the one with the outline highlight), else last. - const focused = document.querySelector('.e-parent.fvcms-focused, .e-parent.fvcms-focused, .e-parent.elementor-element-editing'); + // Prefer a focused region (FreshVibe-native first, then legacy .e-parent + // on pages that predate the migration), else last. + const focused = document.querySelector('[data-fvcms-region].fvcms-focused, .fvcms-section.fvcms-focused, .e-parent.fvcms-focused, .e-parent.elementor-element-editing'); if (focused) return focused; const all = document.querySelectorAll('.e-parent'); return all.length ? all[all.length - 1] : null; @@ -960,7 +967,8 @@ return; } // Clear existing children in the widget container - const target = sectionEl.querySelector('.elementor-widget-container') || sectionEl; + // FreshVibe-native selector first, legacy fallback for pre-migration pages. + const target = sectionEl.querySelector('.fvcms-widget-container, .elementor-widget-container') || sectionEl; target.innerHTML = ''; if (!records || !records.length) { target.innerHTML = '
' diff --git a/fv-cms-vendored/runtime/region-scanner.js b/fv-cms-vendored/runtime/region-scanner.js index 91ced6b..1fd0d40 100644 --- a/fv-cms-vendored/runtime/region-scanner.js +++ b/fv-cms-vendored/runtime/region-scanner.js @@ -25,7 +25,9 @@ import { getStore } from './store.js'; // We support Elementor's e-con today; adding Bricks / Divi / etc. // is a one-line addition here. const SECTION_PATTERNS = [ - // Elementor Flex Container (the modern Elementor layout primitive) + // FreshVibe-native region marker (preferred) + { re: /data-fvcms-region\b/, framework: 'freshvibe' }, + // Legacy source-page selectors — read-only detector input, not output. { re: /e-con\b/, framework: 'elementor' }, ]; @@ -145,12 +147,14 @@ export function scanAndRegisterSections() { /** * After regions are scanned, find the modules in each region. - * We walk down from each e-parent, picking up every widget child - * (data-widget_type, e-con, .eael-*, etc.) and registering them - * as modules in the store. + * We walk down from each e-parent (legacy source-page marker), picking up + * every widget child via detector selectors (data-widget_type, data-id, + * legacy framework class names) and registering them as modules in the store. * * This is the same logic FvRE does offline, but at runtime, so - * we don't depend on FvRE's incomplete output. + * we don't depend on FvRE's incomplete output. The detector selectors + * here are READ-ONLY — they inspect source-page markup, they never + * write proprietary class names to output. */ export function scanAndRegisterModulesInRegions() { const store = getStore(); @@ -164,9 +168,14 @@ export function scanAndRegisterModulesInRegions() { const region = store.getRegion(regionId); if (!region) continue; - // Find every widget child of this section + // Find every widget child of this section. + // FreshVibe-native markers (data-fvcms-module-id, data-fv-widget) are + // preferred; legacy source-page selectors (data-widget_type, data-id, + // .elementor-widget, .eael-*) follow as detector fallbacks. const widgets = s.element.querySelectorAll( - '[data-widget_type], [data-id]:not(.e-parent), .elementor-widget, .eael-post-grid-column, .eael-entry' + '[data-fvcms-module-id], [data-fv-widget], ' + + '[data-widget_type], [data-id]:not(.e-parent), ' + + '.elementor-widget, .eael-post-grid-column, .eael-entry' ); for (const w of widgets) { const dataId = w.getAttribute('data-id'); diff --git a/fv-cms-vendored/runtime/renderer.js b/fv-cms-vendored/runtime/renderer.js index 255f19e..e110a56 100644 --- a/fv-cms-vendored/runtime/renderer.js +++ b/fv-cms-vendored/runtime/renderer.js @@ -75,10 +75,11 @@ export function connect(moduleInstanceId, el) { registerRenderer('M-heading', (m, def, skin) => { if (!m.el) return; // Non-destructive: find existing h1-h6 and patch in place. - // Don't replace the heading element — that would destroy Elementor's - //
styling. We only update - // textContent + style. Level mismatch is left as-is unless operator - // explicitly requested a level change in m.config.level. + // Don't replace the heading element — that would destroy the source page's + //
styling (legacy source pages may use the framework's + // `elementor-heading-title` class). We only update textContent + style. + // Level mismatch is left as-is unless operator explicitly requested a + // level change in m.config.level. let heading = m.el.querySelector('h1, h2, h3, h4, h5, h6'); if (!heading) { heading = document.createElement('h2'); @@ -114,8 +115,8 @@ registerRenderer('M-cta', (m, def, skin) => { if (m.config.openInNewTab) link.target = '_blank'; else link.removeAttribute('target'); // Variant / radius / size: add fvcms-* classes alongside any existing - // framework classes (eael-*, elementor-button, etc.) so styling - // survives and our tweaks layer on top. + // legacy source-page classes (eael-creative-button*, elementor-button*) + // so styling survives and our FreshVibe tweaks layer on top. if (m.config.variant) { link.classList.remove('fvcms-variant-solid', 'fvcms-variant-outline', 'fvcms-variant-ghost', 'fvcms-variant-link'); @@ -135,27 +136,32 @@ registerRenderer('M-cta', (m, def, skin) => { registerRenderer('M-button', (m, def, skin) => { if (!m.el) return; // Non-destructive: update existing button anchor in place. - // Elementor/EAEL have many class variants — match the broadest set. - const link = m.el.querySelector('a.eael-creative-button, a.eael-creative-button__link, a.elementor-button, a.elementor-button-link, a.elementor-button__link, a, button'); + // FreshVibe-native (fvcms-button*, fvcms-variant-*) takes priority; + // legacy fallbacks (eael-creative-button*, elementor-button*) only when + // the source page predates the FreshVibe rename. + const link = m.el.querySelector( + 'a.fvcms-button, a.fvcms-button__link, ' + + 'a.eael-creative-button, a.eael-creative-button__link, ' + + 'a.elementor-button, a.elementor-button-link, a.elementor-button__link, ' + + 'a, button' + ); if (!link) return; if (m.config.text != null) link.textContent = m.config.text; if (m.config.href) link.href = m.config.href; if (m.config.openInNewTab) link.target = '_blank'; else link.removeAttribute('target'); - // Variant — toggle EAEL's classes (which determine actual styling) + // Variant — toggle FreshVibe-native classes (which determine actual styling). + // The legacy eael-creative-button--* classes are read on legacy source pages + // for selector matching, but the runtime output uses fvcms-variant-* only. if (m.config.variant) { - link.classList.remove( - 'eael-creative-button--default', 'eael-creative-button--outline', - 'eael-creative-button--trail', 'eael-creative-button--invert' - ); - if (m.config.variant === 'outline') link.classList.add('eael-creative-button--outline'); - else if (m.config.variant === 'ghost') link.classList.add('eael-creative-button--trail'); - else link.classList.add('eael-creative-button--default'); + link.classList.remove('fvcms-variant-solid', 'fvcms-variant-outline', + 'fvcms-variant-ghost', 'fvcms-variant-link'); + link.classList.add('fvcms-variant-' + m.config.variant); } // Size if (m.config.size) { - link.classList.remove('eael-creative-button--small', 'eael-creative-button--medium', 'eael-creative-button--large'); - link.classList.add('eael-creative-button--' + m.config.size); + link.classList.remove('fvcms-size-small', 'fvcms-size-medium', 'fvcms-size-large'); + link.classList.add('fvcms-size-' + m.config.size); } // Color if (m.config.color) link.style.backgroundColor = m.config.color; @@ -441,7 +447,7 @@ registerRenderer('M-testimonial', (m, def, skin) => { // Non-destructive: update the existing DOM in place. Each canonical // field has a known class name pattern. If not found, append a // hidden element so the inspector at least has something to read - // back. NEVER wipe innerHTML — that destroys EAEL/Elementor styling. + // back. NEVER wipe innerHTML — that destroys source-page styling. const findFirst = (...sels) => { for (const s of sels) { const el = m.el.querySelector(s); @@ -450,23 +456,23 @@ registerRenderer('M-testimonial', (m, def, skin) => { return null; }; - // Quote: try EAEL first, then Elementor blockquote, then any p inside content + // Quote: try FreshVibe-native first, then legacy source-page selectors, then any p inside content if (m.config.quote != null) { const q = findFirst( - '.eael-testimonial-text', // EAEL - '.elementor-blockquote__content', // Elementor - '.fvcms-testimonial-quote', // generic + '.fvcms-testimonial-quote', // FreshVibe-native (preferred) + '.eael-testimonial-text', // legacy EAEL + '.elementor-blockquote__content', // legacy Elementor 'blockquote', // standard - '.eael-testimonial-content p' // fallback + '.eael-testimonial-content p' // legacy fallback ); if (q) q.textContent = m.config.quote; } // Author name if (m.config.authorName != null) { const a = findFirst( - '.eael-testimonial-user', - '.elementor-testimonial-name', - '.fvcms-testimonial-name', + '.fvcms-testimonial-name', // FreshVibe-native (preferred) + '.eael-testimonial-user', // legacy EAEL + '.elementor-testimonial-name', // legacy Elementor 'cite' ); if (a) a.textContent = m.config.authorName; @@ -474,16 +480,16 @@ registerRenderer('M-testimonial', (m, def, skin) => { // Author role if (m.config.authorRole != null) { const r = findFirst( - '.eael-testimonial-position', - '.elementor-testimonial-job', - '.elementor-testimonial-title', - '.fvcms-testimonial-role' + '.fvcms-testimonial-role', // FreshVibe-native (preferred) + '.eael-testimonial-position', // legacy EAEL + '.elementor-testimonial-job', // legacy Elementor + '.elementor-testimonial-title' // legacy Elementor alt ); if (r) r.textContent = m.config.authorRole; } // Author image if (m.config.authorImage && m.config.authorImage.url) { - const img = findFirst('.eael-testimonial-image img', '.fvcms-testimonial-avatar', 'img'); + const img = findFirst('.fvcms-testimonial-avatar img', '.eael-testimonial-image img', 'img'); if (img) { img.src = m.config.authorImage.url; if (m.config.authorImage.alt) img.alt = m.config.authorImage.alt; @@ -491,7 +497,7 @@ registerRenderer('M-testimonial', (m, def, skin) => { } // Rating if (m.config.rating != null) { - const stars = findFirst('.eael-testimonial-rating', '.fvcms-testimonial-stars'); + const stars = findFirst('.fvcms-testimonial-stars', '.eael-testimonial-rating'); if (stars) { const n = parseInt(m.config.rating, 10) || 0; stars.textContent = '★'.repeat(n) + '☆'.repeat(Math.max(0, 5 - n));