@elementor/editor-canvas 4.1.0-809 → 4.1.0-811

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 CHANGED
@@ -1,4 +1,4 @@
1
- import { V1Element, V1ElementConfig, V1ElementModelProps } from '@elementor/editor-elements';
1
+ import { V1Element, V1ElementModelProps, V1ElementConfig } from '@elementor/editor-elements';
2
2
  import { TwingArrayLoader, TwingEnvironment } from '@elementor/twing';
3
3
  import { Root } from 'react-dom/client';
4
4
  import * as _elementor_editor_props from '@elementor/editor-props';
@@ -89,6 +89,7 @@ declare class ElementView {
89
89
  map: <T>(callback: (view: ElementView) => T) => T[];
90
90
  };
91
91
  constructor(...args: unknown[]);
92
+ addElement(data: Partial<V1ElementModelProps>, options?: object): unknown;
92
93
  onRender(...args: unknown[]): void;
93
94
  onDestroy(...args: unknown[]): void;
94
95
  attributes(): Record<string, unknown>;
@@ -131,6 +132,7 @@ declare class ElementView {
131
132
  scrollIntoView: boolean;
132
133
  }): void;
133
134
  once: (event: string, callback: () => void) => void;
135
+ getContainer(): V1Element;
134
136
  }
135
137
  declare class TemplatedElementView extends ElementView {
136
138
  _doAfterRender(callback: () => void): void;
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { V1Element, V1ElementConfig, V1ElementModelProps } from '@elementor/editor-elements';
1
+ import { V1Element, V1ElementModelProps, V1ElementConfig } from '@elementor/editor-elements';
2
2
  import { TwingArrayLoader, TwingEnvironment } from '@elementor/twing';
3
3
  import { Root } from 'react-dom/client';
4
4
  import * as _elementor_editor_props from '@elementor/editor-props';
@@ -89,6 +89,7 @@ declare class ElementView {
89
89
  map: <T>(callback: (view: ElementView) => T) => T[];
90
90
  };
91
91
  constructor(...args: unknown[]);
92
+ addElement(data: Partial<V1ElementModelProps>, options?: object): unknown;
92
93
  onRender(...args: unknown[]): void;
93
94
  onDestroy(...args: unknown[]): void;
94
95
  attributes(): Record<string, unknown>;
@@ -131,6 +132,7 @@ declare class ElementView {
131
132
  scrollIntoView: boolean;
132
133
  }): void;
133
134
  once: (event: string, callback: () => void) => void;
135
+ getContainer(): V1Element;
134
136
  }
135
137
  declare class TemplatedElementView extends ElementView {
136
138
  _doAfterRender(callback: () => void): void;
package/dist/index.js CHANGED
@@ -1173,8 +1173,9 @@ function createProviderSubscriber2({ provider, renderStyles, setStyleItems, getC
1173
1173
  ...style,
1174
1174
  cssName: provider.actions.resolveCssName(style.id)
1175
1175
  }));
1176
- return renderStyles({ styles: breakToBreakpoints(changedStyles), signal }).then((rendered) => {
1177
- updateCacheItems(cache, rendered);
1176
+ const breakpointSplit = breakToBreakpoints(changedStyles);
1177
+ return renderStyles({ styles: breakpointSplit, signal }).then((rendered) => {
1178
+ updateCacheItems(cache, changedIds, rendered);
1178
1179
  return getOrderedItems(cache);
1179
1180
  });
1180
1181
  }
@@ -1231,19 +1232,14 @@ function getChangedStyleIds(previous, current) {
1231
1232
  function getOrderedItems(cache) {
1232
1233
  return cache.orderedIds.map((id) => cache.itemsById.get(id)).filter((items) => items !== void 0).flat();
1233
1234
  }
1234
- function updateCacheItems(cache, changedItems) {
1235
+ function updateCacheItems(cache, changedIds, changedItems) {
1236
+ for (const id of changedIds) {
1237
+ cache.itemsById.delete(id);
1238
+ }
1235
1239
  for (const item of changedItems) {
1236
- const existing = cache.itemsById.get(item.id);
1237
- if (existing) {
1238
- const idx = existing.findIndex((e) => e.breakpoint === item.breakpoint && e.state === item.state);
1239
- if (idx >= 0) {
1240
- existing[idx] = item;
1241
- } else {
1242
- existing.push(item);
1243
- }
1244
- } else {
1245
- cache.itemsById.set(item.id, [item]);
1246
- }
1240
+ const existing = cache.itemsById.get(item.id) || [];
1241
+ existing.push(item);
1242
+ cache.itemsById.set(item.id, existing);
1247
1243
  }
1248
1244
  }
1249
1245
  function rebuildCache(cache, allStyles, items) {
@@ -2001,7 +1997,7 @@ function initStyleTransformers() {
2001
1997
  }
2002
1998
 
2003
1999
  // src/legacy/init-legacy-views.ts
2004
- var import_editor_elements7 = require("@elementor/editor-elements");
2000
+ var import_editor_elements8 = require("@elementor/editor-elements");
2005
2001
  var import_editor_v1_adapters13 = require("@elementor/editor-v1-adapters");
2006
2002
 
2007
2003
  // src/renderers/create-dom-renderer.ts
@@ -2130,7 +2126,53 @@ function createElementViewClassDeclaration() {
2130
2126
  }
2131
2127
 
2132
2128
  // src/legacy/create-nested-templated-element-type.ts
2129
+ var import_editor_elements6 = require("@elementor/editor-elements");
2130
+
2131
+ // src/legacy/create-pending-element.ts
2133
2132
  var import_editor_elements5 = require("@elementor/editor-elements");
2133
+ function createPendingElement(wrapperView, data, options = {}) {
2134
+ const parentContainer = wrapperView.getContainer();
2135
+ const model = { ...data };
2136
+ if (!model.id) {
2137
+ model.id = (0, import_editor_elements5.generateElementId)();
2138
+ }
2139
+ if (!model.elements) {
2140
+ model.elements = [];
2141
+ }
2142
+ const added = (0, import_editor_elements5.addModelToParent)(parentContainer.id, model, options);
2143
+ if (!added) {
2144
+ return void 0;
2145
+ }
2146
+ const childId = model.id;
2147
+ const childModel = (0, import_editor_elements5.findModelInDocument)(childId);
2148
+ if (!childModel) {
2149
+ return void 0;
2150
+ }
2151
+ const pendingContainer = {
2152
+ id: childId,
2153
+ settings: { get: () => ({}), set: () => ({}), toJSON: () => ({}) },
2154
+ parent: parentContainer,
2155
+ model: childModel,
2156
+ view: void 0,
2157
+ lookup() {
2158
+ return (0, import_editor_elements5.getContainer)(childId) ?? pendingContainer;
2159
+ }
2160
+ };
2161
+ if (options.edit !== false) {
2162
+ selectChildWhenWrapperRenders(wrapperView, childId);
2163
+ }
2164
+ return { getContainer: () => pendingContainer };
2165
+ }
2166
+ function selectChildWhenWrapperRenders(wrapperView, childId) {
2167
+ wrapperView.once("render", () => {
2168
+ const childContainer = (0, import_editor_elements5.getContainer)(childId);
2169
+ if (childContainer?.model?.trigger) {
2170
+ childContainer.model.trigger("request:edit");
2171
+ return;
2172
+ }
2173
+ wrapperView.model?.trigger?.("request:edit");
2174
+ });
2175
+ }
2134
2176
 
2135
2177
  // src/legacy/twig-rendering-utils.ts
2136
2178
  function setupTwigRenderer({ renderer, element }) {
@@ -2349,6 +2391,7 @@ function createNestedTemplatedElementView({
2349
2391
  const AtomicElementBaseView = legacyWindow.elementor.modules.elements.views.createAtomicElementBase(type);
2350
2392
  const parentRenderChildren = AtomicElementBaseView.prototype._renderChildren;
2351
2393
  const parentOpenEditingPanel = AtomicElementBaseView.prototype._openEditingPanel;
2394
+ const parentAddElement = AtomicElementBaseView.prototype.addElement;
2352
2395
  return AtomicElementBaseView.extend({
2353
2396
  _abortController: null,
2354
2397
  _lastResolvedSettingsHash: null,
@@ -2388,7 +2431,7 @@ function createNestedTemplatedElementView({
2388
2431
  this._initAlpine();
2389
2432
  });
2390
2433
  this.model.trigger("render:complete");
2391
- window.dispatchEvent(new CustomEvent(import_editor_elements5.ELEMENT_STYLE_CHANGE_EVENT));
2434
+ window.dispatchEvent(new CustomEvent(import_editor_elements6.ELEMENT_STYLE_CHANGE_EVENT));
2392
2435
  },
2393
2436
  async _renderTemplate() {
2394
2437
  const model = this.model;
@@ -2548,6 +2591,12 @@ function createNestedTemplatedElementView({
2548
2591
  _openEditingPanel(options) {
2549
2592
  this._doAfterRender(() => parentOpenEditingPanel.call(this, options));
2550
2593
  },
2594
+ addElement(data, options) {
2595
+ if (this.isRendered) {
2596
+ return parentAddElement.call(this, data, options);
2597
+ }
2598
+ return createPendingElement(this, data, options);
2599
+ },
2551
2600
  getInteractionId() {
2552
2601
  const originId = this.model.get("originId");
2553
2602
  const id = this.model.get("id");
@@ -2624,7 +2673,7 @@ var import_client = require("react-dom/client");
2624
2673
 
2625
2674
  // src/legacy/replacements/inline-editing/inline-editing-elements.tsx
2626
2675
  var React6 = __toESM(require("react"));
2627
- var import_editor_elements6 = require("@elementor/editor-elements");
2676
+ var import_editor_elements7 = require("@elementor/editor-elements");
2628
2677
  var import_editor_props4 = require("@elementor/editor-props");
2629
2678
  var import_editor_v1_adapters12 = require("@elementor/editor-v1-adapters");
2630
2679
  var import_i18n3 = require("@wordpress/i18n");
@@ -3000,7 +3049,7 @@ var InlineEditingReplacement = class extends ReplacementBase {
3000
3049
  return INLINE_EDITING_PROPERTY_PER_TYPE[this.type] ?? "";
3001
3050
  }
3002
3051
  getInlineEditablePropType() {
3003
- const propSchema = (0, import_editor_elements6.getElementType)(this.type)?.propsSchema;
3052
+ const propSchema = (0, import_editor_elements7.getElementType)(this.type)?.propsSchema;
3004
3053
  const propertyName = this.getInlineEditablePropertyName();
3005
3054
  return propSchema?.[propertyName] ?? null;
3006
3055
  }
@@ -3034,7 +3083,7 @@ var InlineEditingReplacement = class extends ReplacementBase {
3034
3083
  }
3035
3084
  },
3036
3085
  {
3037
- title: (0, import_editor_elements6.getElementLabel)(this.id),
3086
+ title: (0, import_editor_elements7.getElementLabel)(this.id),
3038
3087
  // translators: %s is the name of the property that was edited.
3039
3088
  subtitle: (0, import_i18n3.__)("%s edited", "elementor").replace(
3040
3089
  "%s",
@@ -3067,7 +3116,7 @@ var InlineEditingReplacement = class extends ReplacementBase {
3067
3116
  (0, import_editor_v1_adapters12.__privateRunCommandSync)(
3068
3117
  "document/elements/set-settings",
3069
3118
  {
3070
- container: (0, import_editor_elements6.getContainer)(this.id),
3119
+ container: (0, import_editor_elements7.getContainer)(this.id),
3071
3120
  settings: {
3072
3121
  [key]: value
3073
3122
  }
@@ -3082,7 +3131,7 @@ var InlineEditingReplacement = class extends ReplacementBase {
3082
3131
  return import_editor_props4.stringPropTypeUtil.extract(this.getSetting(tagSettingKey) ?? null) ?? import_editor_props4.stringPropTypeUtil.extract(tagPropType?.default ?? null) ?? null;
3083
3132
  }
3084
3133
  getTagPropType() {
3085
- const propsSchema = (0, import_editor_elements6.getElementType)(this.type)?.propsSchema;
3134
+ const propsSchema = (0, import_editor_elements7.getElementType)(this.type)?.propsSchema;
3086
3135
  if (!propsSchema?.tag) {
3087
3136
  return null;
3088
3137
  }
@@ -3242,7 +3291,7 @@ function registerElementType(type, elementTypeGenerator) {
3242
3291
  }
3243
3292
  function initLegacyViews() {
3244
3293
  (0, import_editor_v1_adapters13.__privateListenTo)((0, import_editor_v1_adapters13.v1ReadyEvent)(), () => {
3245
- const widgetsCache = (0, import_editor_elements7.getWidgetsCache)() ?? {};
3294
+ const widgetsCache = (0, import_editor_elements8.getWidgetsCache)() ?? {};
3246
3295
  const legacyWindow = window;
3247
3296
  const renderer = createDomRenderer();
3248
3297
  registerProPromotionTypes(widgetsCache);
@@ -3386,7 +3435,7 @@ var initAvailableWidgetsResource = (reg) => {
3386
3435
  };
3387
3436
 
3388
3437
  // src/mcp/resources/document-structure-resource.ts
3389
- var import_editor_elements8 = require("@elementor/editor-elements");
3438
+ var import_editor_elements9 = require("@elementor/editor-elements");
3390
3439
  var import_editor_v1_adapters15 = require("@elementor/editor-v1-adapters");
3391
3440
  var DOCUMENT_STRUCTURE_URI = "elementor://document/structure";
3392
3441
  var initDocumentStructureResource = (reg) => {
@@ -3451,7 +3500,7 @@ function resolveElementVersion(element) {
3451
3500
  return "v4";
3452
3501
  }
3453
3502
  const widgetType = element.model?.attributes?.widgetType;
3454
- if (widgetType && (0, import_editor_elements8.getWidgetsCache)()?.[widgetType]?.atomic_props_schema) {
3503
+ if (widgetType && (0, import_editor_elements9.getWidgetsCache)()?.[widgetType]?.atomic_props_schema) {
3455
3504
  return "v4";
3456
3505
  }
3457
3506
  return "v3";
@@ -3647,7 +3696,7 @@ var initGeneralContextResource = (reg) => {
3647
3696
  };
3648
3697
 
3649
3698
  // src/mcp/resources/selected-element-resource.ts
3650
- var import_editor_elements9 = require("@elementor/editor-elements");
3699
+ var import_editor_elements10 = require("@elementor/editor-elements");
3651
3700
  var import_editor_v1_adapters18 = require("@elementor/editor-v1-adapters");
3652
3701
  var SELECTED_ELEMENT_URI = "elementor://context/selected-element";
3653
3702
  var initSelectedElementResource = (reg) => {
@@ -3718,11 +3767,11 @@ function createEmptySelectedElementPayload() {
3718
3767
  };
3719
3768
  }
3720
3769
  function readSelectionFromEditor() {
3721
- const elements = (0, import_editor_elements9.getSelectedElements)();
3770
+ const elements = (0, import_editor_elements10.getSelectedElements)();
3722
3771
  if (elements.length !== 1) {
3723
3772
  return createEmptySelectedElementPayload();
3724
3773
  }
3725
- const container = (0, import_editor_elements9.getContainer)(elements[0].id);
3774
+ const container = (0, import_editor_elements10.getContainer)(elements[0].id);
3726
3775
  return buildPayloadFromContainer(container);
3727
3776
  }
3728
3777
  function buildPayloadFromContainer(container) {
@@ -3745,7 +3794,7 @@ function resolveElementVersion2(container, widgetType) {
3745
3794
  if (container.model?.config?.atomic) {
3746
3795
  return "v4";
3747
3796
  }
3748
- if (widgetType && (0, import_editor_elements9.getWidgetsCache)()?.[widgetType]?.atomic_props_schema) {
3797
+ if (widgetType && (0, import_editor_elements10.getWidgetsCache)()?.[widgetType]?.atomic_props_schema) {
3749
3798
  return "v4";
3750
3799
  }
3751
3800
  return "v3";
@@ -3755,7 +3804,7 @@ function getElementProperties(container, widgetType) {
3755
3804
  if (!settings || typeof settings !== "object") {
3756
3805
  return null;
3757
3806
  }
3758
- const widgetConfig = widgetType ? (0, import_editor_elements9.getWidgetsCache)()?.[widgetType] : null;
3807
+ const widgetConfig = widgetType ? (0, import_editor_elements10.getWidgetsCache)()?.[widgetType] : null;
3759
3808
  const controls = widgetConfig?.controls;
3760
3809
  const filtered = {};
3761
3810
  for (const [key, value] of Object.entries(settings)) {
@@ -3794,13 +3843,13 @@ function getElementDisplayName(container) {
3794
3843
 
3795
3844
  // src/mcp/tools/build-composition/tool.ts
3796
3845
  var import_editor_documents3 = require("@elementor/editor-documents");
3797
- var import_editor_elements13 = require("@elementor/editor-elements");
3846
+ var import_editor_elements14 = require("@elementor/editor-elements");
3798
3847
 
3799
3848
  // src/composition-builder/composition-builder.ts
3800
- var import_editor_elements12 = require("@elementor/editor-elements");
3849
+ var import_editor_elements13 = require("@elementor/editor-elements");
3801
3850
 
3802
3851
  // src/mcp/utils/do-update-element-property.ts
3803
- var import_editor_elements10 = require("@elementor/editor-elements");
3852
+ var import_editor_elements11 = require("@elementor/editor-elements");
3804
3853
  var import_editor_props6 = require("@elementor/editor-props");
3805
3854
  var import_editor_styles5 = require("@elementor/editor-styles");
3806
3855
  function resolvePropValue(value, forceKey) {
@@ -3813,7 +3862,7 @@ function resolvePropValue(value, forceKey) {
3813
3862
  var doUpdateElementProperty = (params) => {
3814
3863
  const { elementId, propertyName, propertyValue, elementType } = params;
3815
3864
  if (propertyName === "_styles") {
3816
- const elementStyles = (0, import_editor_elements10.getElementStyles)(elementId) || {};
3865
+ const elementStyles = (0, import_editor_elements11.getElementStyles)(elementId) || {};
3817
3866
  const propertyMapValue = propertyValue;
3818
3867
  const styleSchema = (0, import_editor_styles5.getStylesSchema)();
3819
3868
  const transformedStyleValues = Object.fromEntries(
@@ -3861,7 +3910,7 @@ var doUpdateElementProperty = (params) => {
3861
3910
  delete transformedStyleValues.custom_css;
3862
3911
  const localStyle = Object.values(elementStyles).find((style) => style.label === "local");
3863
3912
  if (!localStyle) {
3864
- (0, import_editor_elements10.createElementStyle)({
3913
+ (0, import_editor_elements11.createElementStyle)({
3865
3914
  elementId,
3866
3915
  ...typeof customCss !== "undefined" ? { custom_css: customCss } : {},
3867
3916
  classesProp: "classes",
@@ -3875,7 +3924,7 @@ var doUpdateElementProperty = (params) => {
3875
3924
  }
3876
3925
  });
3877
3926
  } else {
3878
- (0, import_editor_elements10.updateElementStyle)({
3927
+ (0, import_editor_elements11.updateElementStyle)({
3879
3928
  elementId,
3880
3929
  styleId: localStyle.id,
3881
3930
  meta: {
@@ -3890,7 +3939,7 @@ var doUpdateElementProperty = (params) => {
3890
3939
  }
3891
3940
  return;
3892
3941
  }
3893
- const elementPropSchema = (0, import_editor_elements10.getWidgetsCache)()?.[elementType]?.atomic_props_schema;
3942
+ const elementPropSchema = (0, import_editor_elements11.getWidgetsCache)()?.[elementType]?.atomic_props_schema;
3894
3943
  if (!elementPropSchema) {
3895
3944
  throw new Error(`No prop schema found for element type: ${elementType}`);
3896
3945
  }
@@ -3904,7 +3953,7 @@ var doUpdateElementProperty = (params) => {
3904
3953
  }
3905
3954
  const propKey = elementPropSchema[propertyName].key;
3906
3955
  const value = resolvePropValue(propertyValue, propKey);
3907
- (0, import_editor_elements10.updateElementSettings)({
3956
+ (0, import_editor_elements11.updateElementSettings)({
3908
3957
  id: elementId,
3909
3958
  props: {
3910
3959
  [propertyName]: value
@@ -3914,7 +3963,7 @@ var doUpdateElementProperty = (params) => {
3914
3963
  };
3915
3964
 
3916
3965
  // src/mcp/utils/validate-input.ts
3917
- var import_editor_elements11 = require("@elementor/editor-elements");
3966
+ var import_editor_elements12 = require("@elementor/editor-elements");
3918
3967
  var import_editor_props7 = require("@elementor/editor-props");
3919
3968
  var import_editor_styles6 = require("@elementor/editor-styles");
3920
3969
  var _widgetsSchema = null;
@@ -3922,7 +3971,7 @@ var validateInput = {
3922
3971
  get widgetsSchema() {
3923
3972
  if (!_widgetsSchema) {
3924
3973
  const schema2 = {};
3925
- const cache = (0, import_editor_elements11.getWidgetsCache)();
3974
+ const cache = (0, import_editor_elements12.getWidgetsCache)();
3926
3975
  if (!cache) {
3927
3976
  return {};
3928
3977
  }
@@ -4005,10 +4054,10 @@ var CompositionBuilder = class _CompositionBuilder {
4005
4054
  elementCusomCSS = {};
4006
4055
  rootContainers = [];
4007
4056
  api = {
4008
- createElement: import_editor_elements12.createElement,
4009
- getWidgetsCache: import_editor_elements12.getWidgetsCache,
4010
- generateElementId: import_editor_elements12.generateElementId,
4011
- getContainer: import_editor_elements12.getContainer,
4057
+ createElement: import_editor_elements13.createElement,
4058
+ getWidgetsCache: import_editor_elements13.getWidgetsCache,
4059
+ generateElementId: import_editor_elements13.generateElementId,
4060
+ getContainer: import_editor_elements13.getContainer,
4012
4061
  doUpdateElementProperty
4013
4062
  };
4014
4063
  xml;
@@ -4449,13 +4498,13 @@ var initBuildCompositionsTool = (reg) => {
4449
4498
  let generatedXML = "";
4450
4499
  const errors = [];
4451
4500
  const rootContainers = [];
4452
- const documentContainer = (0, import_editor_elements13.getContainer)("document");
4501
+ const documentContainer = (0, import_editor_elements14.getContainer)("document");
4453
4502
  const currentDocument = (0, import_editor_documents3.getCurrentDocument)();
4454
4503
  const targetContainer = getCompositionTargetContainer(documentContainer, currentDocument?.type.value);
4455
4504
  try {
4456
4505
  const compositionBuilder = CompositionBuilder.fromXMLString(xmlStructure, {
4457
- createElement: import_editor_elements13.createElement,
4458
- getWidgetsCache: import_editor_elements13.getWidgetsCache
4506
+ createElement: import_editor_elements14.createElement,
4507
+ getWidgetsCache: import_editor_elements14.getWidgetsCache
4459
4508
  });
4460
4509
  compositionBuilder.setElementConfig(elementConfig);
4461
4510
  compositionBuilder.setStylesConfig(stylesConfig);
@@ -4483,7 +4532,7 @@ var initBuildCompositionsTool = (reg) => {
4483
4532
  }
4484
4533
  if (errors.length) {
4485
4534
  rootContainers.forEach((rootContainer) => {
4486
- (0, import_editor_elements13.deleteElement)({
4535
+ (0, import_editor_elements14.deleteElement)({
4487
4536
  container: rootContainer,
4488
4537
  options: { useHistory: false }
4489
4538
  });
@@ -4537,7 +4586,7 @@ function assertCompositionXmlUsesV4WidgetsOnly(xmlStructure) {
4537
4586
  if (doc.querySelector("parsererror")) {
4538
4587
  throw new Error("Failed to parse XML string: " + doc);
4539
4588
  }
4540
- const widgetsCache = (0, import_editor_elements13.getWidgetsCache)() ?? {};
4589
+ const widgetsCache = (0, import_editor_elements14.getWidgetsCache)() ?? {};
4541
4590
  for (const node of doc.querySelectorAll("*")) {
4542
4591
  const type = node.tagName;
4543
4592
  const widgetData = widgetsCache[type];
@@ -4556,7 +4605,7 @@ function assertCompositionXmlUsesV4WidgetsOnly(xmlStructure) {
4556
4605
  }
4557
4606
 
4558
4607
  // src/mcp/tools/configure-element/tool.ts
4559
- var import_editor_elements14 = require("@elementor/editor-elements");
4608
+ var import_editor_elements15 = require("@elementor/editor-elements");
4560
4609
 
4561
4610
  // src/mcp/tools/configure-element/prompt.ts
4562
4611
  var configureElementToolPrompt = `Configure an existing element on the page.
@@ -4696,7 +4745,7 @@ var initConfigureElementTool = (reg) => {
4696
4745
  speedPriority: 0.7
4697
4746
  },
4698
4747
  handler: ({ elementId, propertiesToChange, elementType, stylePropertiesToChange }) => {
4699
- const widgetData = (0, import_editor_elements14.getWidgetsCache)()?.[elementType];
4748
+ const widgetData = (0, import_editor_elements15.getWidgetsCache)()?.[elementType];
4700
4749
  if (!widgetData) {
4701
4750
  throw new Error(
4702
4751
  `Unknown element type: ${elementType}. Check the available-widgets resource for valid types.`
@@ -4788,7 +4837,7 @@ Check the styles schema at the resource [${STYLE_SCHEMA_URI.replace(
4788
4837
  }
4789
4838
 
4790
4839
  // src/mcp/tools/get-element-config/tool.ts
4791
- var import_editor_elements15 = require("@elementor/editor-elements");
4840
+ var import_editor_elements16 = require("@elementor/editor-elements");
4792
4841
  var import_editor_props8 = require("@elementor/editor-props");
4793
4842
  var import_schema5 = require("@elementor/schema");
4794
4843
  var schema = {
@@ -4827,12 +4876,12 @@ var initGetElementConfigTool = (reg) => {
4827
4876
  speedPriority: 0.9
4828
4877
  },
4829
4878
  handler: async ({ elementId }) => {
4830
- const element = (0, import_editor_elements15.getContainer)(elementId);
4879
+ const element = (0, import_editor_elements16.getContainer)(elementId);
4831
4880
  if (!element) {
4832
4881
  throw new Error(`Element with ID ${elementId} not found.`);
4833
4882
  }
4834
4883
  const elementType = element.model.get("widgetType") || element.model.get("elType") || "";
4835
- const widgetData = (0, import_editor_elements15.getWidgetsCache)()?.[elementType];
4884
+ const widgetData = (0, import_editor_elements16.getWidgetsCache)()?.[elementType];
4836
4885
  if (!widgetData) {
4837
4886
  throw new Error(
4838
4887
  `Unknown element type: ${elementType}. Check the available-widgets resource for valid types.`
@@ -4844,7 +4893,7 @@ var initGetElementConfigTool = (reg) => {
4844
4893
  );
4845
4894
  }
4846
4895
  const elementRawSettings = element.settings;
4847
- const propSchema = (0, import_editor_elements15.getWidgetsCache)()?.[elementType]?.atomic_props_schema;
4896
+ const propSchema = (0, import_editor_elements16.getWidgetsCache)()?.[elementType]?.atomic_props_schema;
4848
4897
  if (!elementRawSettings || !propSchema) {
4849
4898
  throw new Error(`No settings or prop schema found for element ID: ${elementId}`);
4850
4899
  }
@@ -4853,7 +4902,7 @@ var initGetElementConfigTool = (reg) => {
4853
4902
  import_editor_props8.Schema.configurableKeys(propSchema).forEach((key) => {
4854
4903
  propValues[key] = structuredClone(elementRawSettings.get(key));
4855
4904
  });
4856
- const elementStyles = (0, import_editor_elements15.getElementStyles)(elementId) || {};
4905
+ const elementStyles = (0, import_editor_elements16.getElementStyles)(elementId) || {};
4857
4906
  const localStyle = Object.values(elementStyles).find((style) => style.label === "local");
4858
4907
  if (localStyle) {
4859
4908
  const defaultVariant = localStyle.variants.find(
@@ -5020,7 +5069,7 @@ Note: The "size" property controls image resolution/loading, not visual size. Se
5020
5069
  `;
5021
5070
 
5022
5071
  // src/prevent-link-in-link-commands.ts
5023
- var import_editor_elements16 = require("@elementor/editor-elements");
5072
+ var import_editor_elements17 = require("@elementor/editor-elements");
5024
5073
  var import_editor_notifications3 = require("@elementor/editor-notifications");
5025
5074
  var import_editor_v1_adapters19 = require("@elementor/editor-v1-adapters");
5026
5075
  var import_i18n4 = require("@wordpress/i18n");
@@ -5091,24 +5140,24 @@ function shouldBlock(sourceElements, targetElements) {
5091
5140
  return false;
5092
5141
  }
5093
5142
  const isSourceContainsAnAnchor = sourceElements.some((src) => {
5094
- return src?.id ? (0, import_editor_elements16.isElementAnchored)(src.id) || !!(0, import_editor_elements16.getAnchoredDescendantId)(src.id) : false;
5143
+ return src?.id ? (0, import_editor_elements17.isElementAnchored)(src.id) || !!(0, import_editor_elements17.getAnchoredDescendantId)(src.id) : false;
5095
5144
  });
5096
5145
  if (!isSourceContainsAnAnchor) {
5097
5146
  return false;
5098
5147
  }
5099
5148
  const isTargetContainsAnAnchor = targetElements.some((target) => {
5100
- return target?.id ? (0, import_editor_elements16.isElementAnchored)(target.id) || !!(0, import_editor_elements16.getAnchoredAncestorId)(target.id) : false;
5149
+ return target?.id ? (0, import_editor_elements17.isElementAnchored)(target.id) || !!(0, import_editor_elements17.getAnchoredAncestorId)(target.id) : false;
5101
5150
  });
5102
5151
  return isTargetContainsAnAnchor;
5103
5152
  }
5104
5153
 
5105
5154
  // src/style-commands/paste-style.ts
5106
- var import_editor_elements19 = require("@elementor/editor-elements");
5155
+ var import_editor_elements20 = require("@elementor/editor-elements");
5107
5156
  var import_editor_props10 = require("@elementor/editor-props");
5108
5157
  var import_editor_v1_adapters21 = require("@elementor/editor-v1-adapters");
5109
5158
 
5110
5159
  // src/utils/command-utils.ts
5111
- var import_editor_elements17 = require("@elementor/editor-elements");
5160
+ var import_editor_elements18 = require("@elementor/editor-elements");
5112
5161
  var import_editor_props9 = require("@elementor/editor-props");
5113
5162
  var import_i18n5 = require("@wordpress/i18n");
5114
5163
  function hasAtomicWidgets(args) {
@@ -5133,7 +5182,7 @@ function getClassesProp(container) {
5133
5182
  }
5134
5183
  function getContainerSchema(container) {
5135
5184
  const type = container?.model.get("widgetType") || container?.model.get("elType");
5136
- const widgetsCache = (0, import_editor_elements17.getWidgetsCache)();
5185
+ const widgetsCache = (0, import_editor_elements18.getWidgetsCache)();
5137
5186
  const elementType = widgetsCache?.[type];
5138
5187
  return elementType?.atomic_props_schema ?? null;
5139
5188
  }
@@ -5146,11 +5195,11 @@ function getClipboardElements(storageKey = "clipboard") {
5146
5195
  }
5147
5196
  }
5148
5197
  function getTitleForContainers(containers) {
5149
- return containers.length > 1 ? (0, import_i18n5.__)("Elements", "elementor") : (0, import_editor_elements17.getElementLabel)(containers[0].id);
5198
+ return containers.length > 1 ? (0, import_i18n5.__)("Elements", "elementor") : (0, import_editor_elements18.getElementLabel)(containers[0].id);
5150
5199
  }
5151
5200
 
5152
5201
  // src/style-commands/undoable-actions/paste-element-style.ts
5153
- var import_editor_elements18 = require("@elementor/editor-elements");
5202
+ var import_editor_elements19 = require("@elementor/editor-elements");
5154
5203
  var import_editor_styles_repository4 = require("@elementor/editor-styles-repository");
5155
5204
  var import_editor_v1_adapters20 = require("@elementor/editor-v1-adapters");
5156
5205
  var import_i18n6 = require("@wordpress/i18n");
@@ -5163,7 +5212,7 @@ var undoablePasteElementStyle = () => (0, import_editor_v1_adapters20.undoable)(
5163
5212
  if (!classesProp) {
5164
5213
  return null;
5165
5214
  }
5166
- const originalStyles = (0, import_editor_elements18.getElementStyles)(container.id);
5215
+ const originalStyles = (0, import_editor_elements19.getElementStyles)(container.id);
5167
5216
  const [styleId, styleDef] = Object.entries(originalStyles ?? {})[0] ?? [];
5168
5217
  const originalStyle = Object.keys(styleDef ?? {}).length ? styleDef : null;
5169
5218
  const revertData = {
@@ -5172,7 +5221,7 @@ var undoablePasteElementStyle = () => (0, import_editor_v1_adapters20.undoable)(
5172
5221
  };
5173
5222
  if (styleId) {
5174
5223
  newStyle.variants.forEach(({ meta, props, custom_css: customCss }) => {
5175
- (0, import_editor_elements18.updateElementStyle)({
5224
+ (0, import_editor_elements19.updateElementStyle)({
5176
5225
  elementId,
5177
5226
  styleId,
5178
5227
  meta,
@@ -5183,7 +5232,7 @@ var undoablePasteElementStyle = () => (0, import_editor_v1_adapters20.undoable)(
5183
5232
  } else {
5184
5233
  const [firstVariant] = newStyle.variants;
5185
5234
  const additionalVariants = newStyle.variants.slice(1);
5186
- revertData.styleId = (0, import_editor_elements18.createElementStyle)({
5235
+ revertData.styleId = (0, import_editor_elements19.createElementStyle)({
5187
5236
  elementId,
5188
5237
  classesProp,
5189
5238
  label: import_editor_styles_repository4.ELEMENTS_STYLES_RESERVED_LABEL,
@@ -5201,7 +5250,7 @@ var undoablePasteElementStyle = () => (0, import_editor_v1_adapters20.undoable)(
5201
5250
  return;
5202
5251
  }
5203
5252
  if (!revertData.originalStyle) {
5204
- (0, import_editor_elements18.deleteElementStyle)(container.id, revertData.styleId);
5253
+ (0, import_editor_elements19.deleteElementStyle)(container.id, revertData.styleId);
5205
5254
  return;
5206
5255
  }
5207
5256
  const classesProp = getClassesProp(container);
@@ -5210,7 +5259,7 @@ var undoablePasteElementStyle = () => (0, import_editor_v1_adapters20.undoable)(
5210
5259
  }
5211
5260
  const [firstVariant] = revertData.originalStyle.variants;
5212
5261
  const additionalVariants = revertData.originalStyle.variants.slice(1);
5213
- (0, import_editor_elements18.createElementStyle)({
5262
+ (0, import_editor_elements19.createElementStyle)({
5214
5263
  elementId: container.id,
5215
5264
  classesProp,
5216
5265
  label: import_editor_styles_repository4.ELEMENTS_STYLES_RESERVED_LABEL,
@@ -5247,7 +5296,7 @@ function pasteStyles(args, pasteLocalStyle) {
5247
5296
  }
5248
5297
  const clipboardElements = getClipboardElements(storageKey);
5249
5298
  const [clipboardElement] = clipboardElements ?? [];
5250
- const clipboardContainer = (0, import_editor_elements19.getContainer)(clipboardElement.id);
5299
+ const clipboardContainer = (0, import_editor_elements20.getContainer)(clipboardElement.id);
5251
5300
  if (!clipboardElement || !clipboardContainer || !isAtomicWidget(clipboardContainer)) {
5252
5301
  return;
5253
5302
  }
@@ -5266,7 +5315,7 @@ function getClassesWithoutLocalStyle(clipboardContainer, style) {
5266
5315
  if (!classesProp) {
5267
5316
  return [];
5268
5317
  }
5269
- const classesSetting = (0, import_editor_elements19.getElementSetting)(clipboardContainer.id, classesProp);
5318
+ const classesSetting = (0, import_editor_elements20.getElementSetting)(clipboardContainer.id, classesProp);
5270
5319
  return classesSetting?.value.filter((styleId) => styleId !== style?.id) ?? [];
5271
5320
  }
5272
5321
  function pasteClasses(containers, classes) {
@@ -5275,10 +5324,10 @@ function pasteClasses(containers, classes) {
5275
5324
  if (!classesProp) {
5276
5325
  return;
5277
5326
  }
5278
- const classesSetting = (0, import_editor_elements19.getElementSetting)(container.id, classesProp);
5327
+ const classesSetting = (0, import_editor_elements20.getElementSetting)(container.id, classesProp);
5279
5328
  const currentClasses = import_editor_props10.classesPropTypeUtil.extract(classesSetting) ?? [];
5280
5329
  const newClasses = import_editor_props10.classesPropTypeUtil.create(Array.from(/* @__PURE__ */ new Set([...classes, ...currentClasses])));
5281
- (0, import_editor_elements19.updateElementSettings)({
5330
+ (0, import_editor_elements20.updateElementSettings)({
5282
5331
  id: container.id,
5283
5332
  props: { [classesProp]: newClasses }
5284
5333
  });
@@ -5289,7 +5338,7 @@ function pasteClasses(containers, classes) {
5289
5338
  var import_editor_v1_adapters23 = require("@elementor/editor-v1-adapters");
5290
5339
 
5291
5340
  // src/style-commands/undoable-actions/reset-element-style.ts
5292
- var import_editor_elements20 = require("@elementor/editor-elements");
5341
+ var import_editor_elements21 = require("@elementor/editor-elements");
5293
5342
  var import_editor_styles_repository5 = require("@elementor/editor-styles-repository");
5294
5343
  var import_editor_v1_adapters22 = require("@elementor/editor-v1-adapters");
5295
5344
  var import_i18n7 = require("@wordpress/i18n");
@@ -5298,9 +5347,9 @@ var undoableResetElementStyle = () => (0, import_editor_v1_adapters22.undoable)(
5298
5347
  do: ({ containers }) => {
5299
5348
  return containers.map((container) => {
5300
5349
  const elementId = container.model.get("id");
5301
- const containerStyles = (0, import_editor_elements20.getElementStyles)(elementId);
5350
+ const containerStyles = (0, import_editor_elements21.getElementStyles)(elementId);
5302
5351
  Object.keys(containerStyles ?? {}).forEach(
5303
- (styleId) => (0, import_editor_elements20.deleteElementStyle)(elementId, styleId)
5352
+ (styleId) => (0, import_editor_elements21.deleteElementStyle)(elementId, styleId)
5304
5353
  );
5305
5354
  return containerStyles;
5306
5355
  });
@@ -5316,7 +5365,7 @@ var undoableResetElementStyle = () => (0, import_editor_v1_adapters22.undoable)(
5316
5365
  Object.entries(containerStyles ?? {}).forEach(([styleId, style]) => {
5317
5366
  const [firstVariant] = style.variants;
5318
5367
  const additionalVariants = style.variants.slice(1);
5319
- (0, import_editor_elements20.createElementStyle)({
5368
+ (0, import_editor_elements21.createElementStyle)({
5320
5369
  elementId,
5321
5370
  classesProp,
5322
5371
  styleId,
@@ -5441,10 +5490,10 @@ var getLegacyPanelElementView = ({ settings, ...rest }) => {
5441
5490
  };
5442
5491
 
5443
5492
  // src/utils/after-render.ts
5444
- var import_editor_elements21 = require("@elementor/editor-elements");
5493
+ var import_editor_elements22 = require("@elementor/editor-elements");
5445
5494
  function doAfterRender(elementIds, callback) {
5446
5495
  const pending = elementIds.map((elementId) => {
5447
- const view = (0, import_editor_elements21.getContainer)(elementId)?.view;
5496
+ const view = (0, import_editor_elements22.getContainer)(elementId)?.view;
5448
5497
  if (!view || !hasDoAfterRender(view)) {
5449
5498
  return void 0;
5450
5499
  }
package/dist/index.mjs CHANGED
@@ -1138,8 +1138,9 @@ function createProviderSubscriber2({ provider, renderStyles, setStyleItems, getC
1138
1138
  ...style,
1139
1139
  cssName: provider.actions.resolveCssName(style.id)
1140
1140
  }));
1141
- return renderStyles({ styles: breakToBreakpoints(changedStyles), signal }).then((rendered) => {
1142
- updateCacheItems(cache, rendered);
1141
+ const breakpointSplit = breakToBreakpoints(changedStyles);
1142
+ return renderStyles({ styles: breakpointSplit, signal }).then((rendered) => {
1143
+ updateCacheItems(cache, changedIds, rendered);
1143
1144
  return getOrderedItems(cache);
1144
1145
  });
1145
1146
  }
@@ -1196,19 +1197,14 @@ function getChangedStyleIds(previous, current) {
1196
1197
  function getOrderedItems(cache) {
1197
1198
  return cache.orderedIds.map((id) => cache.itemsById.get(id)).filter((items) => items !== void 0).flat();
1198
1199
  }
1199
- function updateCacheItems(cache, changedItems) {
1200
+ function updateCacheItems(cache, changedIds, changedItems) {
1201
+ for (const id of changedIds) {
1202
+ cache.itemsById.delete(id);
1203
+ }
1200
1204
  for (const item of changedItems) {
1201
- const existing = cache.itemsById.get(item.id);
1202
- if (existing) {
1203
- const idx = existing.findIndex((e) => e.breakpoint === item.breakpoint && e.state === item.state);
1204
- if (idx >= 0) {
1205
- existing[idx] = item;
1206
- } else {
1207
- existing.push(item);
1208
- }
1209
- } else {
1210
- cache.itemsById.set(item.id, [item]);
1211
- }
1205
+ const existing = cache.itemsById.get(item.id) || [];
1206
+ existing.push(item);
1207
+ cache.itemsById.set(item.id, existing);
1212
1208
  }
1213
1209
  }
1214
1210
  function rebuildCache(cache, allStyles, items) {
@@ -2097,6 +2093,57 @@ function createElementViewClassDeclaration() {
2097
2093
  // src/legacy/create-nested-templated-element-type.ts
2098
2094
  import { ELEMENT_STYLE_CHANGE_EVENT } from "@elementor/editor-elements";
2099
2095
 
2096
+ // src/legacy/create-pending-element.ts
2097
+ import {
2098
+ addModelToParent,
2099
+ findModelInDocument,
2100
+ generateElementId,
2101
+ getContainer
2102
+ } from "@elementor/editor-elements";
2103
+ function createPendingElement(wrapperView, data, options = {}) {
2104
+ const parentContainer = wrapperView.getContainer();
2105
+ const model = { ...data };
2106
+ if (!model.id) {
2107
+ model.id = generateElementId();
2108
+ }
2109
+ if (!model.elements) {
2110
+ model.elements = [];
2111
+ }
2112
+ const added = addModelToParent(parentContainer.id, model, options);
2113
+ if (!added) {
2114
+ return void 0;
2115
+ }
2116
+ const childId = model.id;
2117
+ const childModel = findModelInDocument(childId);
2118
+ if (!childModel) {
2119
+ return void 0;
2120
+ }
2121
+ const pendingContainer = {
2122
+ id: childId,
2123
+ settings: { get: () => ({}), set: () => ({}), toJSON: () => ({}) },
2124
+ parent: parentContainer,
2125
+ model: childModel,
2126
+ view: void 0,
2127
+ lookup() {
2128
+ return getContainer(childId) ?? pendingContainer;
2129
+ }
2130
+ };
2131
+ if (options.edit !== false) {
2132
+ selectChildWhenWrapperRenders(wrapperView, childId);
2133
+ }
2134
+ return { getContainer: () => pendingContainer };
2135
+ }
2136
+ function selectChildWhenWrapperRenders(wrapperView, childId) {
2137
+ wrapperView.once("render", () => {
2138
+ const childContainer = getContainer(childId);
2139
+ if (childContainer?.model?.trigger) {
2140
+ childContainer.model.trigger("request:edit");
2141
+ return;
2142
+ }
2143
+ wrapperView.model?.trigger?.("request:edit");
2144
+ });
2145
+ }
2146
+
2100
2147
  // src/legacy/twig-rendering-utils.ts
2101
2148
  function setupTwigRenderer({ renderer, element }) {
2102
2149
  const templateKey = element.twig_main_template;
@@ -2314,6 +2361,7 @@ function createNestedTemplatedElementView({
2314
2361
  const AtomicElementBaseView = legacyWindow.elementor.modules.elements.views.createAtomicElementBase(type);
2315
2362
  const parentRenderChildren = AtomicElementBaseView.prototype._renderChildren;
2316
2363
  const parentOpenEditingPanel = AtomicElementBaseView.prototype._openEditingPanel;
2364
+ const parentAddElement = AtomicElementBaseView.prototype.addElement;
2317
2365
  return AtomicElementBaseView.extend({
2318
2366
  _abortController: null,
2319
2367
  _lastResolvedSettingsHash: null,
@@ -2513,6 +2561,12 @@ function createNestedTemplatedElementView({
2513
2561
  _openEditingPanel(options) {
2514
2562
  this._doAfterRender(() => parentOpenEditingPanel.call(this, options));
2515
2563
  },
2564
+ addElement(data, options) {
2565
+ if (this.isRendered) {
2566
+ return parentAddElement.call(this, data, options);
2567
+ }
2568
+ return createPendingElement(this, data, options);
2569
+ },
2516
2570
  getInteractionId() {
2517
2571
  const originId = this.model.get("originId");
2518
2572
  const id = this.model.get("id");
@@ -2589,7 +2643,7 @@ import { createRoot } from "react-dom/client";
2589
2643
 
2590
2644
  // src/legacy/replacements/inline-editing/inline-editing-elements.tsx
2591
2645
  import * as React6 from "react";
2592
- import { getContainer, getElementLabel, getElementType as getElementType2 } from "@elementor/editor-elements";
2646
+ import { getContainer as getContainer2, getElementLabel, getElementType as getElementType2 } from "@elementor/editor-elements";
2593
2647
  import {
2594
2648
  htmlV3PropTypeUtil as htmlV3PropTypeUtil2,
2595
2649
  parseHtmlChildren,
@@ -3036,7 +3090,7 @@ var InlineEditingReplacement = class extends ReplacementBase {
3036
3090
  runCommandSync(
3037
3091
  "document/elements/set-settings",
3038
3092
  {
3039
- container: getContainer(this.id),
3093
+ container: getContainer2(this.id),
3040
3094
  settings: {
3041
3095
  [key]: value
3042
3096
  }
@@ -3618,7 +3672,7 @@ var initGeneralContextResource = (reg) => {
3618
3672
  };
3619
3673
 
3620
3674
  // src/mcp/resources/selected-element-resource.ts
3621
- import { getContainer as getContainer2, getSelectedElements, getWidgetsCache as getWidgetsCache5 } from "@elementor/editor-elements";
3675
+ import { getContainer as getContainer3, getSelectedElements, getWidgetsCache as getWidgetsCache5 } from "@elementor/editor-elements";
3622
3676
  import {
3623
3677
  __privateListenTo as listenTo4,
3624
3678
  commandEndEvent as commandEndEvent7
@@ -3696,7 +3750,7 @@ function readSelectionFromEditor() {
3696
3750
  if (elements.length !== 1) {
3697
3751
  return createEmptySelectedElementPayload();
3698
3752
  }
3699
- const container = getContainer2(elements[0].id);
3753
+ const container = getContainer3(elements[0].id);
3700
3754
  return buildPayloadFromContainer(container);
3701
3755
  }
3702
3756
  function buildPayloadFromContainer(container) {
@@ -3771,15 +3825,15 @@ import { getCurrentDocument } from "@elementor/editor-documents";
3771
3825
  import {
3772
3826
  createElement as createElement8,
3773
3827
  deleteElement,
3774
- getContainer as getContainer4,
3828
+ getContainer as getContainer5,
3775
3829
  getWidgetsCache as getWidgetsCache9
3776
3830
  } from "@elementor/editor-elements";
3777
3831
 
3778
3832
  // src/composition-builder/composition-builder.ts
3779
3833
  import {
3780
3834
  createElement as createElement7,
3781
- generateElementId,
3782
- getContainer as getContainer3,
3835
+ generateElementId as generateElementId2,
3836
+ getContainer as getContainer4,
3783
3837
  getWidgetsCache as getWidgetsCache8
3784
3838
  } from "@elementor/editor-elements";
3785
3839
 
@@ -3997,8 +4051,8 @@ var CompositionBuilder = class _CompositionBuilder {
3997
4051
  api = {
3998
4052
  createElement: createElement7,
3999
4053
  getWidgetsCache: getWidgetsCache8,
4000
- generateElementId,
4001
- getContainer: getContainer3,
4054
+ generateElementId: generateElementId2,
4055
+ getContainer: getContainer4,
4002
4056
  doUpdateElementProperty
4003
4057
  };
4004
4058
  xml;
@@ -4439,7 +4493,7 @@ var initBuildCompositionsTool = (reg) => {
4439
4493
  let generatedXML = "";
4440
4494
  const errors = [];
4441
4495
  const rootContainers = [];
4442
- const documentContainer = getContainer4("document");
4496
+ const documentContainer = getContainer5("document");
4443
4497
  const currentDocument = getCurrentDocument();
4444
4498
  const targetContainer = getCompositionTargetContainer(documentContainer, currentDocument?.type.value);
4445
4499
  try {
@@ -4778,7 +4832,7 @@ Check the styles schema at the resource [${STYLE_SCHEMA_URI.replace(
4778
4832
  }
4779
4833
 
4780
4834
  // src/mcp/tools/get-element-config/tool.ts
4781
- import { getContainer as getContainer5, getElementStyles as getElementStyles2, getWidgetsCache as getWidgetsCache11 } from "@elementor/editor-elements";
4835
+ import { getContainer as getContainer6, getElementStyles as getElementStyles2, getWidgetsCache as getWidgetsCache11 } from "@elementor/editor-elements";
4782
4836
  import { Schema as Schema4 } from "@elementor/editor-props";
4783
4837
  import { z as z3 } from "@elementor/schema";
4784
4838
  var schema = {
@@ -4817,7 +4871,7 @@ var initGetElementConfigTool = (reg) => {
4817
4871
  speedPriority: 0.9
4818
4872
  },
4819
4873
  handler: async ({ elementId }) => {
4820
- const element = getContainer5(elementId);
4874
+ const element = getContainer6(elementId);
4821
4875
  if (!element) {
4822
4876
  throw new Error(`Element with ID ${elementId} not found.`);
4823
4877
  }
@@ -5097,7 +5151,7 @@ function shouldBlock(sourceElements, targetElements) {
5097
5151
  }
5098
5152
 
5099
5153
  // src/style-commands/paste-style.ts
5100
- import { getContainer as getContainer6, getElementSetting, updateElementSettings as updateElementSettings2 } from "@elementor/editor-elements";
5154
+ import { getContainer as getContainer7, getElementSetting, updateElementSettings as updateElementSettings2 } from "@elementor/editor-elements";
5101
5155
  import { classesPropTypeUtil } from "@elementor/editor-props";
5102
5156
  import {
5103
5157
  __privateListenTo as listenTo5,
@@ -5250,7 +5304,7 @@ function pasteStyles(args, pasteLocalStyle) {
5250
5304
  }
5251
5305
  const clipboardElements = getClipboardElements(storageKey);
5252
5306
  const [clipboardElement] = clipboardElements ?? [];
5253
- const clipboardContainer = getContainer6(clipboardElement.id);
5307
+ const clipboardContainer = getContainer7(clipboardElement.id);
5254
5308
  if (!clipboardElement || !clipboardContainer || !isAtomicWidget(clipboardContainer)) {
5255
5309
  return;
5256
5310
  }
@@ -5448,10 +5502,10 @@ var getLegacyPanelElementView = ({ settings, ...rest }) => {
5448
5502
  };
5449
5503
 
5450
5504
  // src/utils/after-render.ts
5451
- import { getContainer as getContainer7 } from "@elementor/editor-elements";
5505
+ import { getContainer as getContainer8 } from "@elementor/editor-elements";
5452
5506
  function doAfterRender(elementIds, callback) {
5453
5507
  const pending = elementIds.map((elementId) => {
5454
- const view = getContainer7(elementId)?.view;
5508
+ const view = getContainer8(elementId)?.view;
5455
5509
  if (!view || !hasDoAfterRender(view)) {
5456
5510
  return void 0;
5457
5511
  }
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.1.0-809",
4
+ "version": "4.1.0-811",
5
5
  "private": false,
6
6
  "author": "Elementor Team",
7
7
  "homepage": "https://elementor.com/",
@@ -37,25 +37,25 @@
37
37
  "react-dom": "^18.3.1"
38
38
  },
39
39
  "dependencies": {
40
- "@elementor/editor": "4.1.0-809",
40
+ "@elementor/editor": "4.1.0-811",
41
41
  "dompurify": "^3.2.6",
42
- "@elementor/editor-controls": "4.1.0-809",
43
- "@elementor/editor-documents": "4.1.0-809",
44
- "@elementor/editor-elements": "4.1.0-809",
45
- "@elementor/editor-interactions": "4.1.0-809",
46
- "@elementor/editor-mcp": "4.1.0-809",
47
- "@elementor/editor-notifications": "4.1.0-809",
48
- "@elementor/editor-props": "4.1.0-809",
49
- "@elementor/editor-responsive": "4.1.0-809",
50
- "@elementor/editor-styles": "4.1.0-809",
51
- "@elementor/editor-styles-repository": "4.1.0-809",
52
- "@elementor/editor-ui": "4.1.0-809",
53
- "@elementor/editor-v1-adapters": "4.1.0-809",
54
- "@elementor/schema": "4.1.0-809",
55
- "@elementor/twing": "4.1.0-809",
42
+ "@elementor/editor-controls": "4.1.0-811",
43
+ "@elementor/editor-documents": "4.1.0-811",
44
+ "@elementor/editor-elements": "4.1.0-811",
45
+ "@elementor/editor-interactions": "4.1.0-811",
46
+ "@elementor/editor-mcp": "4.1.0-811",
47
+ "@elementor/editor-notifications": "4.1.0-811",
48
+ "@elementor/editor-props": "4.1.0-811",
49
+ "@elementor/editor-responsive": "4.1.0-811",
50
+ "@elementor/editor-styles": "4.1.0-811",
51
+ "@elementor/editor-styles-repository": "4.1.0-811",
52
+ "@elementor/editor-ui": "4.1.0-811",
53
+ "@elementor/editor-v1-adapters": "4.1.0-811",
54
+ "@elementor/schema": "4.1.0-811",
55
+ "@elementor/twing": "4.1.0-811",
56
56
  "@elementor/ui": "1.37.5",
57
- "@elementor/utils": "4.1.0-809",
58
- "@elementor/wp-media": "4.1.0-809",
57
+ "@elementor/utils": "4.1.0-811",
58
+ "@elementor/wp-media": "4.1.0-811",
59
59
  "@floating-ui/react": "^0.27.5",
60
60
  "@wordpress/i18n": "^5.13.0"
61
61
  },
@@ -408,6 +408,61 @@ describe( 'useStyleItems', () => {
408
408
  ] );
409
409
  } );
410
410
 
411
+ it( 'should remove cached items for breakpoints whose variants no longer exist', async () => {
412
+ // Arrange.
413
+ const renderStylesMock = jest.fn().mockImplementation( ( { styles } ) =>
414
+ Promise.resolve(
415
+ styles.map( ( style: StyleDefinition ) => ( {
416
+ id: style.id,
417
+ breakpoint: style?.variants[ 0 ]?.meta.breakpoint || 'desktop',
418
+ } ) )
419
+ )
420
+ );
421
+
422
+ jest.mocked( useStyleRenderer ).mockReturnValue( renderStylesMock );
423
+
424
+ const styleWithTwoBreakpoints = createMockStyleDefinitionWithVariants( {
425
+ id: 'style1',
426
+ variants: [
427
+ { meta: { breakpoint: null, state: null }, props: { 'font-family': 'Arial' }, custom_css: null },
428
+ { meta: { breakpoint: 'tablet', state: null }, props: { 'font-family': 'Roboto' }, custom_css: null },
429
+ ],
430
+ } );
431
+
432
+ const mockProvider = createMockStylesProvider( { key: 'provider1', priority: 1 }, [ styleWithTwoBreakpoints ] );
433
+
434
+ jest.mocked( stylesRepository ).getProviders.mockReturnValue( [ mockProvider ] );
435
+
436
+ const { result } = renderHook( () => useStyleItems() );
437
+
438
+ await act( async () => {
439
+ mockProvider.actions.updateProps?.( {
440
+ id: 'style1',
441
+ meta: { breakpoint: null, state: null },
442
+ props: {},
443
+ } );
444
+ } );
445
+
446
+ expect( result.current ).toEqual( [
447
+ { id: 'style1', breakpoint: 'desktop' },
448
+ { id: 'style1', breakpoint: 'tablet' },
449
+ ] );
450
+
451
+ // Act - simulate the tablet variant being removed (e.g. user cleared its only prop,
452
+ // global-classes store calls getNonEmptyVariants which drops empty variants).
453
+ await act( async () => {
454
+ mockProvider.actions.update?.( {
455
+ id: 'style1',
456
+ variants: [
457
+ { meta: { breakpoint: null, state: null }, props: { 'font-family': 'Arial' }, custom_css: null },
458
+ ],
459
+ } );
460
+ } );
461
+
462
+ // Assert - the tablet item must be evicted from the cache.
463
+ expect( result.current ).toEqual( [ { id: 'style1', breakpoint: 'desktop' } ] );
464
+ } );
465
+
411
466
  it( 'should only re-render changed styles on differential update', async () => {
412
467
  // Arrange.
413
468
  const renderStylesMock = jest.fn().mockImplementation( ( { styles } ) =>
@@ -200,8 +200,10 @@ function createProviderSubscriber( { provider, renderStyles, setStyleItems, getC
200
200
  cssName: provider.actions.resolveCssName( style.id ),
201
201
  } ) );
202
202
 
203
- return renderStyles( { styles: breakToBreakpoints( changedStyles ), signal } ).then( ( rendered ) => {
204
- updateCacheItems( cache, rendered );
203
+ const breakpointSplit = breakToBreakpoints( changedStyles );
204
+
205
+ return renderStyles( { styles: breakpointSplit, signal } ).then( ( rendered ) => {
206
+ updateCacheItems( cache, changedIds, rendered );
205
207
 
206
208
  return getOrderedItems( cache );
207
209
  } );
@@ -277,19 +279,15 @@ function getOrderedItems( cache: StyleItemsCache ): StyleItem[] {
277
279
  .flat();
278
280
  }
279
281
 
280
- function updateCacheItems( cache: StyleItemsCache, changedItems: StyleItem[] ): void {
282
+ function updateCacheItems( cache: StyleItemsCache, changedIds: string[], changedItems: StyleItem[] ): void {
283
+ for ( const id of changedIds ) {
284
+ cache.itemsById.delete( id );
285
+ }
286
+
281
287
  for ( const item of changedItems ) {
282
- const existing = cache.itemsById.get( item.id );
283
- if ( existing ) {
284
- const idx = existing.findIndex( ( e ) => e.breakpoint === item.breakpoint && e.state === item.state );
285
- if ( idx >= 0 ) {
286
- existing[ idx ] = item;
287
- } else {
288
- existing.push( item );
289
- }
290
- } else {
291
- cache.itemsById.set( item.id, [ item ] );
292
- }
288
+ const existing = cache.itemsById.get( item.id ) || [];
289
+ existing.push( item );
290
+ cache.itemsById.set( item.id, existing );
293
291
  }
294
292
  }
295
293
 
@@ -1,7 +1,8 @@
1
- import { ELEMENT_STYLE_CHANGE_EVENT } from '@elementor/editor-elements';
1
+ import { ELEMENT_STYLE_CHANGE_EVENT, type V1ElementModelProps } from '@elementor/editor-elements';
2
2
 
3
3
  import { type DomRenderer } from '../renderers/create-dom-renderer';
4
4
  import { signalizedProcess } from '../utils/signalized-process';
5
+ import { createPendingElement } from './create-pending-element';
5
6
  import { canBeTemplated, type TemplatedElementConfig } from './create-templated-element-type';
6
7
  import {
7
8
  createAfterRender,
@@ -101,6 +102,7 @@ export function createNestedTemplatedElementView( {
101
102
  const AtomicElementBaseView = legacyWindow.elementor.modules.elements.views.createAtomicElementBase( type );
102
103
  const parentRenderChildren = AtomicElementBaseView.prototype._renderChildren;
103
104
  const parentOpenEditingPanel = AtomicElementBaseView.prototype._openEditingPanel;
105
+ const parentAddElement = AtomicElementBaseView.prototype.addElement;
104
106
 
105
107
  return AtomicElementBaseView.extend( {
106
108
  _abortController: null as AbortController | null,
@@ -381,6 +383,14 @@ export function createNestedTemplatedElementView( {
381
383
  this._doAfterRender( () => parentOpenEditingPanel.call( this, options ) );
382
384
  },
383
385
 
386
+ addElement( data: Partial< V1ElementModelProps >, options?: { edit?: boolean; at?: number } ) {
387
+ if ( this.isRendered ) {
388
+ return parentAddElement.call( this, data, options );
389
+ }
390
+
391
+ return createPendingElement( this, data, options );
392
+ },
393
+
384
394
  getInteractionId() {
385
395
  const originId = this.model.get( 'originId' );
386
396
  const id = this.model.get( 'id' );
@@ -0,0 +1,70 @@
1
+ import {
2
+ addModelToParent,
3
+ findModelInDocument,
4
+ generateElementId,
5
+ getContainer,
6
+ type V1Element,
7
+ type V1ElementModelProps,
8
+ } from '@elementor/editor-elements';
9
+
10
+ import { type ElementView } from './types';
11
+
12
+ export function createPendingElement(
13
+ wrapperView: ElementView,
14
+ data: Partial< V1ElementModelProps >,
15
+ options: { edit?: boolean; at?: number } = {}
16
+ ): { getContainer: () => V1Element } | undefined {
17
+ const parentContainer = wrapperView.getContainer();
18
+ const model: Partial< V1ElementModelProps > = { ...data };
19
+
20
+ if ( ! model.id ) {
21
+ model.id = generateElementId();
22
+ }
23
+
24
+ if ( ! model.elements ) {
25
+ model.elements = [];
26
+ }
27
+
28
+ const added = addModelToParent( parentContainer.id, model as V1ElementModelProps, options );
29
+
30
+ if ( ! added ) {
31
+ return undefined;
32
+ }
33
+
34
+ const childId = model.id;
35
+ const childModel = findModelInDocument( childId );
36
+
37
+ if ( ! childModel ) {
38
+ return undefined;
39
+ }
40
+
41
+ const pendingContainer: V1Element = {
42
+ id: childId,
43
+ settings: { get: () => ( {} ), set: () => ( {} ), toJSON: () => ( {} ) } as V1Element[ 'settings' ],
44
+ parent: parentContainer,
45
+ model: childModel as V1Element[ 'model' ],
46
+ view: undefined,
47
+ lookup() {
48
+ return getContainer( childId ) ?? pendingContainer;
49
+ },
50
+ };
51
+
52
+ if ( options.edit !== false ) {
53
+ selectChildWhenWrapperRenders( wrapperView, childId );
54
+ }
55
+
56
+ return { getContainer: () => pendingContainer };
57
+ }
58
+
59
+ function selectChildWhenWrapperRenders( wrapperView: ElementView, childId: string ): void {
60
+ wrapperView.once( 'render', () => {
61
+ const childContainer = getContainer( childId );
62
+
63
+ if ( childContainer?.model?.trigger ) {
64
+ childContainer.model.trigger( 'request:edit' );
65
+ return;
66
+ }
67
+
68
+ wrapperView.model?.trigger?.( 'request:edit' );
69
+ } );
70
+ }
@@ -1,5 +1,5 @@
1
1
  import { type Root } from 'react-dom/client';
2
- import { type V1Element } from '@elementor/editor-elements';
2
+ import { type V1Element, type V1ElementModelProps } from '@elementor/editor-elements';
3
3
  import { type Props, type PropValue } from '@elementor/editor-props';
4
4
 
5
5
  export type RenderContext< T = unknown > = Record< string, T >;
@@ -89,6 +89,8 @@ export declare class ElementView {
89
89
 
90
90
  constructor( ...args: unknown[] );
91
91
 
92
+ addElement( data: Partial< V1ElementModelProps >, options?: object ): unknown;
93
+
92
94
  onRender( ...args: unknown[] ): void;
93
95
 
94
96
  onDestroy( ...args: unknown[] ): void;
@@ -163,6 +165,8 @@ export declare class ElementView {
163
165
  _openEditingPanel( options?: { scrollIntoView: boolean } ): void;
164
166
 
165
167
  once: ( event: string, callback: () => void ) => void;
168
+
169
+ getContainer(): V1Element;
166
170
  }
167
171
 
168
172
  export declare class TemplatedElementView extends ElementView {