@elementor/editor-canvas 4.0.0-564 → 4.0.0-573
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +0 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.js +123 -128
- package/dist/index.mjs +123 -128
- package/package.json +18 -18
- package/src/legacy/create-nested-templated-element-type.ts +77 -24
- package/src/legacy/create-templated-element-type.ts +70 -23
- package/src/legacy/twig-rendering-utils.ts +16 -135
- package/src/legacy/types.ts +0 -2
- package/src/mcp/tools/build-composition/schema.ts +0 -14
- package/src/mcp/tools/build-composition/tool.ts +11 -10
- package/src/renderers/__tests__/create-dom-renderer.test.ts +1 -0
- package/src/renderers/__tests__/create-styles-renderer.test.ts +1 -0
- package/src/legacy/__tests__/twig-rendering-utils.test.ts +0 -115
package/dist/index.mjs
CHANGED
|
@@ -1728,9 +1728,9 @@ function createElementViewClassDeclaration() {
|
|
|
1728
1728
|
import { ELEMENT_STYLE_CHANGE_EVENT } from "@elementor/editor-elements";
|
|
1729
1729
|
|
|
1730
1730
|
// src/legacy/twig-rendering-utils.ts
|
|
1731
|
-
function
|
|
1731
|
+
function setupTwigRenderer({ renderer, element }) {
|
|
1732
1732
|
const templateKey = element.twig_main_template;
|
|
1733
|
-
const
|
|
1733
|
+
const baseStylesDictionary = element.base_styles_dictionary;
|
|
1734
1734
|
Object.entries(element.twig_templates).forEach(([key, template]) => {
|
|
1735
1735
|
renderer.register(key, template);
|
|
1736
1736
|
});
|
|
@@ -1738,7 +1738,7 @@ function createTwigRenderState({ renderer, element }) {
|
|
|
1738
1738
|
transformers: settingsTransformersRegistry,
|
|
1739
1739
|
schema: element.atomic_props_schema
|
|
1740
1740
|
});
|
|
1741
|
-
return { templateKey,
|
|
1741
|
+
return { templateKey, baseStylesDictionary, resolveProps };
|
|
1742
1742
|
}
|
|
1743
1743
|
function createBeforeRender(view) {
|
|
1744
1744
|
view._ensureViewIsIntact();
|
|
@@ -1751,87 +1751,18 @@ function createAfterRender(view) {
|
|
|
1751
1751
|
view.isRendered = true;
|
|
1752
1752
|
view.triggerMethod("render", view);
|
|
1753
1753
|
}
|
|
1754
|
-
function
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
domUpdateWasSkipped: false,
|
|
1758
|
-
invalidate() {
|
|
1759
|
-
this.lastResolvedSettingsHash = null;
|
|
1760
|
-
this.domUpdateWasSkipped = false;
|
|
1761
|
-
}
|
|
1762
|
-
};
|
|
1763
|
-
}
|
|
1764
|
-
async function renderTwigTemplate({
|
|
1765
|
-
view,
|
|
1766
|
-
signal,
|
|
1767
|
-
renderState,
|
|
1768
|
-
buildContext,
|
|
1769
|
-
attachContent,
|
|
1770
|
-
afterSettingsResolve
|
|
1771
|
-
}) {
|
|
1772
|
-
view.triggerMethod("before:render:template");
|
|
1773
|
-
const { resolveProps, cacheState, renderer, templateKey } = renderState;
|
|
1774
|
-
if (signal?.aborted) {
|
|
1775
|
-
return;
|
|
1776
|
-
}
|
|
1777
|
-
const settings = view.model.get("settings").toJSON();
|
|
1778
|
-
let resolvedSettings = await resolveProps({
|
|
1779
|
-
props: settings,
|
|
1780
|
-
signal,
|
|
1781
|
-
renderContext: view.getResolverRenderContext?.()
|
|
1754
|
+
function rerenderExistingChildren(view) {
|
|
1755
|
+
view.children?.each((childView) => {
|
|
1756
|
+
childView.render();
|
|
1782
1757
|
});
|
|
1783
|
-
if (signal?.aborted) {
|
|
1784
|
-
return;
|
|
1785
|
-
}
|
|
1786
|
-
if (afterSettingsResolve) {
|
|
1787
|
-
resolvedSettings = afterSettingsResolve(resolvedSettings);
|
|
1788
|
-
}
|
|
1789
|
-
const settingsHash = JSON.stringify(resolvedSettings);
|
|
1790
|
-
const settingsChanged = settingsHash !== cacheState.lastResolvedSettingsHash;
|
|
1791
|
-
if (!settingsChanged && view.isRendered) {
|
|
1792
|
-
cacheState.domUpdateWasSkipped = true;
|
|
1793
|
-
view.bindUIElements();
|
|
1794
|
-
view.triggerMethod("render:template");
|
|
1795
|
-
return;
|
|
1796
|
-
}
|
|
1797
|
-
cacheState.domUpdateWasSkipped = false;
|
|
1798
|
-
cacheState.lastResolvedSettingsHash = settingsHash;
|
|
1799
|
-
const context = buildContext(resolvedSettings);
|
|
1800
|
-
const html = await renderer.render(templateKey, context);
|
|
1801
|
-
if (signal?.aborted) {
|
|
1802
|
-
return;
|
|
1803
|
-
}
|
|
1804
|
-
attachContent(html);
|
|
1805
|
-
view.bindUIElements();
|
|
1806
|
-
view.triggerMethod("render:template");
|
|
1807
1758
|
}
|
|
1808
|
-
function
|
|
1759
|
+
async function waitForChildrenToComplete(view) {
|
|
1809
1760
|
const promises = [];
|
|
1810
|
-
children?.each((childView) => {
|
|
1761
|
+
view.children?.each((childView) => {
|
|
1811
1762
|
if (childView._currentRenderPromise) {
|
|
1812
1763
|
promises.push(childView._currentRenderPromise);
|
|
1813
1764
|
}
|
|
1814
1765
|
});
|
|
1815
|
-
return promises;
|
|
1816
|
-
}
|
|
1817
|
-
async function renderChildrenWithOptimization({
|
|
1818
|
-
children,
|
|
1819
|
-
domUpdateWasSkipped,
|
|
1820
|
-
renderChildren
|
|
1821
|
-
}) {
|
|
1822
|
-
const shouldReuseChildren = domUpdateWasSkipped && !!children?.length;
|
|
1823
|
-
if (shouldReuseChildren) {
|
|
1824
|
-
rerenderExistingChildViews(children);
|
|
1825
|
-
} else {
|
|
1826
|
-
renderChildren();
|
|
1827
|
-
}
|
|
1828
|
-
const promises = collectChildrenRenderPromises(children);
|
|
1829
|
-
await waitForChildrenToComplete(promises);
|
|
1830
|
-
}
|
|
1831
|
-
function rerenderExistingChildViews(children) {
|
|
1832
|
-
children?.each((childView) => childView.render());
|
|
1833
|
-
}
|
|
1834
|
-
async function waitForChildrenToComplete(promises) {
|
|
1835
1766
|
if (promises.length > 0) {
|
|
1836
1767
|
await Promise.all(promises);
|
|
1837
1768
|
}
|
|
@@ -1847,9 +1778,15 @@ function createTemplatedElementView({
|
|
|
1847
1778
|
element
|
|
1848
1779
|
}) {
|
|
1849
1780
|
const BaseView = createElementViewClassDeclaration();
|
|
1850
|
-
const
|
|
1781
|
+
const { templateKey, baseStylesDictionary, resolveProps } = setupTwigRenderer({
|
|
1782
|
+
type,
|
|
1783
|
+
renderer,
|
|
1784
|
+
element
|
|
1785
|
+
});
|
|
1851
1786
|
return class extends BaseView {
|
|
1852
1787
|
_abortController = null;
|
|
1788
|
+
_lastResolvedSettingsHash = null;
|
|
1789
|
+
_domUpdateWasSkipped = false;
|
|
1853
1790
|
getTemplateType() {
|
|
1854
1791
|
return "twig";
|
|
1855
1792
|
}
|
|
@@ -1866,7 +1803,7 @@ function createTemplatedElementView({
|
|
|
1866
1803
|
return this._parent?.getResolverRenderContext?.();
|
|
1867
1804
|
}
|
|
1868
1805
|
invalidateRenderCache() {
|
|
1869
|
-
|
|
1806
|
+
this._lastResolvedSettingsHash = null;
|
|
1870
1807
|
}
|
|
1871
1808
|
render() {
|
|
1872
1809
|
this._abortController?.abort();
|
|
@@ -1876,26 +1813,52 @@ function createTemplatedElementView({
|
|
|
1876
1813
|
return this._currentRenderPromise;
|
|
1877
1814
|
}
|
|
1878
1815
|
async _renderChildren() {
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
}
|
|
1816
|
+
if (this._shouldReuseChildren()) {
|
|
1817
|
+
rerenderExistingChildren(this);
|
|
1818
|
+
} else {
|
|
1819
|
+
super._renderChildren();
|
|
1820
|
+
}
|
|
1821
|
+
await waitForChildrenToComplete(this);
|
|
1822
|
+
}
|
|
1823
|
+
_shouldReuseChildren() {
|
|
1824
|
+
return this._domUpdateWasSkipped && this.children?.length > 0;
|
|
1884
1825
|
}
|
|
1885
1826
|
async _renderTemplate() {
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1827
|
+
this.triggerMethod("before:render:template");
|
|
1828
|
+
const process = signalizedProcess(this._abortController?.signal).then((_, signal) => {
|
|
1829
|
+
const settings = this.model.get("settings").toJSON();
|
|
1830
|
+
return resolveProps({
|
|
1831
|
+
props: settings,
|
|
1832
|
+
signal,
|
|
1833
|
+
renderContext: this.getResolverRenderContext()
|
|
1834
|
+
});
|
|
1835
|
+
}).then((settings) => {
|
|
1836
|
+
return this.afterSettingsResolve(settings);
|
|
1837
|
+
}).then(async (settings) => {
|
|
1838
|
+
const settingsHash = JSON.stringify(settings);
|
|
1839
|
+
const settingsChanged = settingsHash !== this._lastResolvedSettingsHash;
|
|
1840
|
+
if (!settingsChanged && this.isRendered) {
|
|
1841
|
+
this._domUpdateWasSkipped = true;
|
|
1842
|
+
return null;
|
|
1843
|
+
}
|
|
1844
|
+
this._domUpdateWasSkipped = false;
|
|
1845
|
+
this._lastResolvedSettingsHash = settingsHash;
|
|
1846
|
+
const context = {
|
|
1891
1847
|
id: this.model.get("id"),
|
|
1892
1848
|
type,
|
|
1893
|
-
settings
|
|
1894
|
-
base_styles:
|
|
1895
|
-
}
|
|
1896
|
-
|
|
1897
|
-
|
|
1849
|
+
settings,
|
|
1850
|
+
base_styles: baseStylesDictionary
|
|
1851
|
+
};
|
|
1852
|
+
return renderer.render(templateKey, context);
|
|
1853
|
+
}).then((html) => {
|
|
1854
|
+
if (html === null) {
|
|
1855
|
+
return;
|
|
1856
|
+
}
|
|
1857
|
+
this.$el.html(html);
|
|
1898
1858
|
});
|
|
1859
|
+
await process.execute();
|
|
1860
|
+
this.bindUIElements();
|
|
1861
|
+
this.triggerMethod("render:template");
|
|
1899
1862
|
}
|
|
1900
1863
|
afterSettingsResolve(settings) {
|
|
1901
1864
|
return settings;
|
|
@@ -1966,18 +1929,24 @@ function createNestedTemplatedElementView({
|
|
|
1966
1929
|
element
|
|
1967
1930
|
}) {
|
|
1968
1931
|
const legacyWindow = window;
|
|
1969
|
-
const
|
|
1932
|
+
const { templateKey, baseStylesDictionary, resolveProps } = setupTwigRenderer({
|
|
1933
|
+
type,
|
|
1934
|
+
renderer,
|
|
1935
|
+
element
|
|
1936
|
+
});
|
|
1970
1937
|
const AtomicElementBaseView = legacyWindow.elementor.modules.elements.views.createAtomicElementBase(type);
|
|
1971
1938
|
const parentRenderChildren = AtomicElementBaseView.prototype._renderChildren;
|
|
1972
1939
|
const parentOpenEditingPanel = AtomicElementBaseView.prototype._openEditingPanel;
|
|
1973
1940
|
return AtomicElementBaseView.extend({
|
|
1974
1941
|
_abortController: null,
|
|
1942
|
+
_lastResolvedSettingsHash: null,
|
|
1943
|
+
_domUpdateWasSkipped: false,
|
|
1975
1944
|
template: false,
|
|
1976
1945
|
getTemplateType() {
|
|
1977
1946
|
return "twig";
|
|
1978
1947
|
},
|
|
1979
1948
|
invalidateRenderCache() {
|
|
1980
|
-
|
|
1949
|
+
this._lastResolvedSettingsHash = null;
|
|
1981
1950
|
},
|
|
1982
1951
|
render() {
|
|
1983
1952
|
this._abortController?.abort();
|
|
@@ -2003,20 +1972,47 @@ function createNestedTemplatedElementView({
|
|
|
2003
1972
|
},
|
|
2004
1973
|
async _renderTemplate() {
|
|
2005
1974
|
const model = this.model;
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
1975
|
+
this.triggerMethod("before:render:template");
|
|
1976
|
+
const process = signalizedProcess(this._abortController?.signal).then((_, signal) => {
|
|
1977
|
+
const settings = model.get("settings").toJSON();
|
|
1978
|
+
return resolveProps({
|
|
1979
|
+
props: settings,
|
|
1980
|
+
signal,
|
|
1981
|
+
renderContext: this.getResolverRenderContext?.()
|
|
1982
|
+
});
|
|
1983
|
+
}).then(async (settings) => {
|
|
1984
|
+
const settingsHash = JSON.stringify(settings);
|
|
1985
|
+
const settingsChanged = settingsHash !== this._lastResolvedSettingsHash;
|
|
1986
|
+
if (!settingsChanged && this.isRendered) {
|
|
1987
|
+
this._domUpdateWasSkipped = true;
|
|
1988
|
+
return null;
|
|
1989
|
+
}
|
|
1990
|
+
this._domUpdateWasSkipped = false;
|
|
1991
|
+
this._lastResolvedSettingsHash = settingsHash;
|
|
1992
|
+
const context = {
|
|
2011
1993
|
id: model.get("id"),
|
|
2012
1994
|
type,
|
|
2013
|
-
settings
|
|
2014
|
-
base_styles:
|
|
1995
|
+
settings,
|
|
1996
|
+
base_styles: baseStylesDictionary,
|
|
2015
1997
|
editor_attributes: buildEditorAttributes(model),
|
|
2016
1998
|
editor_classes: buildEditorClasses(model)
|
|
2017
|
-
}
|
|
2018
|
-
|
|
1999
|
+
};
|
|
2000
|
+
return renderer.render(templateKey, context);
|
|
2001
|
+
}).then((html) => {
|
|
2002
|
+
if (html === null) {
|
|
2003
|
+
return;
|
|
2004
|
+
}
|
|
2005
|
+
this._attachTwigContent(html);
|
|
2019
2006
|
});
|
|
2007
|
+
await process.execute();
|
|
2008
|
+
this.bindUIElements();
|
|
2009
|
+
this.triggerMethod("render:template");
|
|
2010
|
+
},
|
|
2011
|
+
getRenderContext() {
|
|
2012
|
+
return this._parent?.getRenderContext?.();
|
|
2013
|
+
},
|
|
2014
|
+
getResolverRenderContext() {
|
|
2015
|
+
return this._parent?.getResolverRenderContext?.();
|
|
2020
2016
|
},
|
|
2021
2017
|
getChildType() {
|
|
2022
2018
|
const allowedTypes = element.allowed_child_types ?? [];
|
|
@@ -2041,13 +2037,17 @@ function createNestedTemplatedElementView({
|
|
|
2041
2037
|
oldEl.innerHTML = overlayHTML + newEl.innerHTML;
|
|
2042
2038
|
},
|
|
2043
2039
|
async _renderChildren() {
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
}
|
|
2040
|
+
if (this._shouldReuseChildren()) {
|
|
2041
|
+
rerenderExistingChildren(this);
|
|
2042
|
+
} else {
|
|
2043
|
+
parentRenderChildren.call(this);
|
|
2044
|
+
}
|
|
2045
|
+
await waitForChildrenToComplete(this);
|
|
2049
2046
|
this._removeChildrenPlaceholder();
|
|
2050
2047
|
},
|
|
2048
|
+
_shouldReuseChildren() {
|
|
2049
|
+
return this._domUpdateWasSkipped && this.children?.length > 0;
|
|
2050
|
+
},
|
|
2051
2051
|
_removeChildrenPlaceholder() {
|
|
2052
2052
|
const el = this.$el.get(0);
|
|
2053
2053
|
if (!el) {
|
|
@@ -3435,13 +3435,6 @@ var inputSchema = {
|
|
|
3435
3435
|
`A record mapping element IDs to their styles configuration objects. Use the actual styles schema from [${STYLE_SCHEMA_URI}].`
|
|
3436
3436
|
).default({})
|
|
3437
3437
|
};
|
|
3438
|
-
var outputSchema = {
|
|
3439
|
-
errors: z.string().describe("Error message if the composition building failed").optional(),
|
|
3440
|
-
xmlStructure: z.string().describe(
|
|
3441
|
-
"The built XML structure as a string. Must use this XML after completion of building the composition, it contains real IDs."
|
|
3442
|
-
).optional(),
|
|
3443
|
-
llm_instructions: z.string().describe("Instructions what to do next, Important to follow these instructions!").optional()
|
|
3444
|
-
};
|
|
3445
3438
|
|
|
3446
3439
|
// src/mcp/tools/build-composition/tool.ts
|
|
3447
3440
|
var initBuildCompositionsTool = (reg) => {
|
|
@@ -3457,7 +3450,7 @@ var initBuildCompositionsTool = (reg) => {
|
|
|
3457
3450
|
{ description: "Global Variables", uri: "elementor://global-variables" },
|
|
3458
3451
|
{ description: "Styles best practices", uri: BEST_PRACTICES_URI }
|
|
3459
3452
|
],
|
|
3460
|
-
outputSchema,
|
|
3453
|
+
// outputSchema: '',
|
|
3461
3454
|
modelPreferences: {
|
|
3462
3455
|
hints: [{ name: "claude-sonnet-4-5" }]
|
|
3463
3456
|
},
|
|
@@ -3539,10 +3532,10 @@ ${errorMessages.join(
|
|
|
3539
3532
|
Now that you have these errors, fix them and try again. Errors regarding configuration objects, please check against the PropType schemas`;
|
|
3540
3533
|
throw new Error(errorText);
|
|
3541
3534
|
}
|
|
3542
|
-
|
|
3543
|
-
|
|
3544
|
-
|
|
3545
|
-
|
|
3535
|
+
if (errors.length) {
|
|
3536
|
+
throw new Error(errors.map((e) => typeof e === "string" ? e : e.message).join("\n"));
|
|
3537
|
+
}
|
|
3538
|
+
return `The composition was built successfully with element IDs embedded in the XML.
|
|
3546
3539
|
|
|
3547
3540
|
**CRITICAL NEXT STEPS** (Follow in order):
|
|
3548
3541
|
1. **Apply Global Classes**: Use "apply-global-class" tool to apply the global classes you created BEFORE building this composition
|
|
@@ -3552,8 +3545,10 @@ Now that you have these errors, fix them and try again. Errors regarding configu
|
|
|
3552
3545
|
2. **Fine-tune if needed**: Use "configure-element" tool only for element-specific adjustments that don't warrant global classes
|
|
3553
3546
|
|
|
3554
3547
|
Remember: Global classes ensure design consistency and reusability. Don't skip applying them!
|
|
3555
|
-
|
|
3556
|
-
|
|
3548
|
+
|
|
3549
|
+
Updated XML structure:
|
|
3550
|
+
${generatedXML}
|
|
3551
|
+
`;
|
|
3557
3552
|
}
|
|
3558
3553
|
});
|
|
3559
3554
|
};
|
|
@@ -3672,7 +3667,7 @@ var inputSchema2 = {
|
|
|
3672
3667
|
elementType: z2.string().describe("The type of the element to retreive the schema"),
|
|
3673
3668
|
elementId: z2.string().describe("The unique id of the element to configure")
|
|
3674
3669
|
};
|
|
3675
|
-
var
|
|
3670
|
+
var outputSchema = {
|
|
3676
3671
|
success: z2.boolean().describe(
|
|
3677
3672
|
"Whether the configuration change was successful, only if propertyName and propertyValue are provided"
|
|
3678
3673
|
)
|
|
@@ -3685,7 +3680,7 @@ var initConfigureElementTool = (reg) => {
|
|
|
3685
3680
|
name: "configure-element",
|
|
3686
3681
|
description: configureElementToolPrompt,
|
|
3687
3682
|
schema: inputSchema2,
|
|
3688
|
-
outputSchema
|
|
3683
|
+
outputSchema,
|
|
3689
3684
|
requiredResources: [
|
|
3690
3685
|
{ description: "Widgets schema", uri: WIDGET_SCHEMA_URI },
|
|
3691
3686
|
{ description: "Styles schema", uri: STYLE_SCHEMA_URI }
|
|
@@ -3783,7 +3778,7 @@ import { z as z3 } from "@elementor/schema";
|
|
|
3783
3778
|
var schema = {
|
|
3784
3779
|
elementId: z3.string()
|
|
3785
3780
|
};
|
|
3786
|
-
var
|
|
3781
|
+
var outputSchema2 = {
|
|
3787
3782
|
properties: z3.record(z3.string(), z3.any()).describe("A record mapping PropTypes to their corresponding PropValues"),
|
|
3788
3783
|
style: z3.record(z3.string(), z3.any()).describe("A record mapping StyleSchema properties to their corresponding PropValues"),
|
|
3789
3784
|
childElements: z3.array(
|
|
@@ -3810,7 +3805,7 @@ var initGetElementConfigTool = (reg) => {
|
|
|
3810
3805
|
name: "get-element-configuration-values",
|
|
3811
3806
|
description: "Retrieve the element's configuration PropValues for a specific element by unique ID.",
|
|
3812
3807
|
schema,
|
|
3813
|
-
outputSchema:
|
|
3808
|
+
outputSchema: outputSchema2,
|
|
3814
3809
|
modelPreferences: {
|
|
3815
3810
|
intelligencePriority: 0.6,
|
|
3816
3811
|
speedPriority: 0.9
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@elementor/editor-canvas",
|
|
3
3
|
"description": "Elementor Editor Canvas",
|
|
4
|
-
"version": "4.0.0-
|
|
4
|
+
"version": "4.0.0-573",
|
|
5
5
|
"private": false,
|
|
6
6
|
"author": "Elementor Team",
|
|
7
7
|
"homepage": "https://elementor.com/",
|
|
@@ -37,24 +37,24 @@
|
|
|
37
37
|
"react-dom": "^18.3.1"
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@elementor/editor": "4.0.0-
|
|
41
|
-
"@elementor/editor-controls": "4.0.0-
|
|
42
|
-
"@elementor/editor-documents": "4.0.0-
|
|
43
|
-
"@elementor/editor-elements": "4.0.0-
|
|
44
|
-
"@elementor/editor-interactions": "4.0.0-
|
|
45
|
-
"@elementor/editor-mcp": "4.0.0-
|
|
46
|
-
"@elementor/editor-notifications": "4.0.0-
|
|
47
|
-
"@elementor/editor-props": "4.0.0-
|
|
48
|
-
"@elementor/editor-responsive": "4.0.0-
|
|
49
|
-
"@elementor/editor-styles": "4.0.0-
|
|
50
|
-
"@elementor/editor-styles-repository": "4.0.0-
|
|
51
|
-
"@elementor/editor-ui": "4.0.0-
|
|
52
|
-
"@elementor/editor-v1-adapters": "4.0.0-
|
|
53
|
-
"@elementor/schema": "4.0.0-
|
|
54
|
-
"@elementor/twing": "4.0.0-
|
|
40
|
+
"@elementor/editor": "4.0.0-573",
|
|
41
|
+
"@elementor/editor-controls": "4.0.0-573",
|
|
42
|
+
"@elementor/editor-documents": "4.0.0-573",
|
|
43
|
+
"@elementor/editor-elements": "4.0.0-573",
|
|
44
|
+
"@elementor/editor-interactions": "4.0.0-573",
|
|
45
|
+
"@elementor/editor-mcp": "4.0.0-573",
|
|
46
|
+
"@elementor/editor-notifications": "4.0.0-573",
|
|
47
|
+
"@elementor/editor-props": "4.0.0-573",
|
|
48
|
+
"@elementor/editor-responsive": "4.0.0-573",
|
|
49
|
+
"@elementor/editor-styles": "4.0.0-573",
|
|
50
|
+
"@elementor/editor-styles-repository": "4.0.0-573",
|
|
51
|
+
"@elementor/editor-ui": "4.0.0-573",
|
|
52
|
+
"@elementor/editor-v1-adapters": "4.0.0-573",
|
|
53
|
+
"@elementor/schema": "4.0.0-573",
|
|
54
|
+
"@elementor/twing": "4.0.0-573",
|
|
55
55
|
"@elementor/ui": "1.36.17",
|
|
56
|
-
"@elementor/utils": "4.0.0-
|
|
57
|
-
"@elementor/wp-media": "4.0.0-
|
|
56
|
+
"@elementor/utils": "4.0.0-573",
|
|
57
|
+
"@elementor/wp-media": "4.0.0-573",
|
|
58
58
|
"@floating-ui/react": "^0.27.5",
|
|
59
59
|
"@wordpress/i18n": "^5.13.0"
|
|
60
60
|
},
|
|
@@ -6,9 +6,9 @@ import { canBeTemplated, type TemplatedElementConfig } from './create-templated-
|
|
|
6
6
|
import {
|
|
7
7
|
createAfterRender,
|
|
8
8
|
createBeforeRender,
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
rerenderExistingChildren,
|
|
10
|
+
setupTwigRenderer,
|
|
11
|
+
waitForChildrenToComplete,
|
|
12
12
|
} from './twig-rendering-utils';
|
|
13
13
|
import { type ElementType, type ElementView, type LegacyWindow } from './types';
|
|
14
14
|
|
|
@@ -91,7 +91,11 @@ export function createNestedTemplatedElementView( {
|
|
|
91
91
|
}: CreateNestedTemplatedElementViewOptions ): typeof ElementView {
|
|
92
92
|
const legacyWindow = window as unknown as LegacyWindow;
|
|
93
93
|
|
|
94
|
-
const
|
|
94
|
+
const { templateKey, baseStylesDictionary, resolveProps } = setupTwigRenderer( {
|
|
95
|
+
type,
|
|
96
|
+
renderer,
|
|
97
|
+
element,
|
|
98
|
+
} );
|
|
95
99
|
|
|
96
100
|
const AtomicElementBaseView = legacyWindow.elementor.modules.elements.views.createAtomicElementBase( type );
|
|
97
101
|
const parentRenderChildren = AtomicElementBaseView.prototype._renderChildren;
|
|
@@ -99,6 +103,8 @@ export function createNestedTemplatedElementView( {
|
|
|
99
103
|
|
|
100
104
|
return AtomicElementBaseView.extend( {
|
|
101
105
|
_abortController: null as AbortController | null,
|
|
106
|
+
_lastResolvedSettingsHash: null as string | null,
|
|
107
|
+
_domUpdateWasSkipped: false,
|
|
102
108
|
|
|
103
109
|
template: false,
|
|
104
110
|
|
|
@@ -107,7 +113,7 @@ export function createNestedTemplatedElementView( {
|
|
|
107
113
|
},
|
|
108
114
|
|
|
109
115
|
invalidateRenderCache() {
|
|
110
|
-
|
|
116
|
+
this._lastResolvedSettingsHash = null;
|
|
111
117
|
},
|
|
112
118
|
|
|
113
119
|
render() {
|
|
@@ -117,6 +123,7 @@ export function createNestedTemplatedElementView( {
|
|
|
117
123
|
const process = signalizedProcess( this._abortController.signal )
|
|
118
124
|
.then( () => this._beforeRender() )
|
|
119
125
|
.then( () => this._renderTemplate() )
|
|
126
|
+
// Dispatch the render event after the template is ready
|
|
120
127
|
.then( () => this._onTemplateReady() )
|
|
121
128
|
.then( () => this._renderChildren() )
|
|
122
129
|
.then( () => this._afterRender() );
|
|
@@ -149,20 +156,61 @@ export function createNestedTemplatedElementView( {
|
|
|
149
156
|
async _renderTemplate() {
|
|
150
157
|
const model = this.model;
|
|
151
158
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
159
|
+
this.triggerMethod( 'before:render:template' );
|
|
160
|
+
|
|
161
|
+
const process = signalizedProcess( this._abortController?.signal as AbortSignal )
|
|
162
|
+
.then( ( _, signal ) => {
|
|
163
|
+
const settings = model.get( 'settings' ).toJSON();
|
|
164
|
+
return resolveProps( {
|
|
165
|
+
props: settings,
|
|
166
|
+
signal,
|
|
167
|
+
renderContext: this.getResolverRenderContext?.(),
|
|
168
|
+
} );
|
|
169
|
+
} )
|
|
170
|
+
.then( async ( settings ) => {
|
|
171
|
+
const settingsHash = JSON.stringify( settings );
|
|
172
|
+
const settingsChanged = settingsHash !== this._lastResolvedSettingsHash;
|
|
173
|
+
|
|
174
|
+
if ( ! settingsChanged && this.isRendered ) {
|
|
175
|
+
this._domUpdateWasSkipped = true;
|
|
176
|
+
return null;
|
|
177
|
+
}
|
|
178
|
+
this._domUpdateWasSkipped = false;
|
|
179
|
+
|
|
180
|
+
this._lastResolvedSettingsHash = settingsHash;
|
|
181
|
+
|
|
182
|
+
const context = {
|
|
183
|
+
id: model.get( 'id' ),
|
|
184
|
+
type,
|
|
185
|
+
settings,
|
|
186
|
+
base_styles: baseStylesDictionary,
|
|
187
|
+
editor_attributes: buildEditorAttributes( model ),
|
|
188
|
+
editor_classes: buildEditorClasses( model ),
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
return renderer.render( templateKey, context );
|
|
192
|
+
} )
|
|
193
|
+
.then( ( html ) => {
|
|
194
|
+
if ( html === null ) {
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
this._attachTwigContent( html );
|
|
199
|
+
} );
|
|
200
|
+
|
|
201
|
+
await process.execute();
|
|
202
|
+
|
|
203
|
+
this.bindUIElements();
|
|
204
|
+
|
|
205
|
+
this.triggerMethod( 'render:template' );
|
|
206
|
+
},
|
|
207
|
+
|
|
208
|
+
getRenderContext() {
|
|
209
|
+
return this._parent?.getRenderContext?.();
|
|
210
|
+
},
|
|
211
|
+
|
|
212
|
+
getResolverRenderContext() {
|
|
213
|
+
return this._parent?.getResolverRenderContext?.();
|
|
166
214
|
},
|
|
167
215
|
|
|
168
216
|
getChildType(): string[] {
|
|
@@ -197,15 +245,20 @@ export function createNestedTemplatedElementView( {
|
|
|
197
245
|
},
|
|
198
246
|
|
|
199
247
|
async _renderChildren() {
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
}
|
|
248
|
+
if ( this._shouldReuseChildren() ) {
|
|
249
|
+
rerenderExistingChildren( this );
|
|
250
|
+
} else {
|
|
251
|
+
parentRenderChildren.call( this );
|
|
252
|
+
}
|
|
205
253
|
|
|
254
|
+
await waitForChildrenToComplete( this );
|
|
206
255
|
this._removeChildrenPlaceholder();
|
|
207
256
|
},
|
|
208
257
|
|
|
258
|
+
_shouldReuseChildren() {
|
|
259
|
+
return this._domUpdateWasSkipped && this.children?.length > 0;
|
|
260
|
+
},
|
|
261
|
+
|
|
209
262
|
_removeChildrenPlaceholder() {
|
|
210
263
|
const el = this.$el.get( 0 );
|
|
211
264
|
if ( ! el ) {
|