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 = '
';
+ // 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 = '';
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));