@elementor/editor-canvas 3.33.0-99 → 3.34.3

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.
Files changed (59) hide show
  1. package/dist/index.d.mts +133 -10
  2. package/dist/index.d.ts +133 -10
  3. package/dist/index.js +1413 -212
  4. package/dist/index.mjs +1399 -180
  5. package/package.json +18 -14
  6. package/src/__tests__/settings-props-resolver.test.ts +0 -40
  7. package/src/__tests__/styles-prop-resolver.test.ts +13 -0
  8. package/src/components/__tests__/__snapshots__/style-renderer.test.tsx.snap +2 -6
  9. package/src/components/__tests__/elements-overlays.test.tsx +96 -12
  10. package/src/components/__tests__/inline-editor-overlay.test.tsx +245 -0
  11. package/src/components/__tests__/style-renderer.test.tsx +2 -2
  12. package/src/components/elements-overlays.tsx +33 -10
  13. package/src/components/inline-editor-overlay.tsx +79 -0
  14. package/src/components/interactions-renderer.tsx +33 -0
  15. package/src/components/{element-overlay.tsx → outline-overlay.tsx} +8 -7
  16. package/src/components/style-renderer.tsx +2 -4
  17. package/src/hooks/__tests__/use-has-overlapping.test.ts +187 -0
  18. package/src/hooks/use-floating-on-element.ts +11 -8
  19. package/src/hooks/use-has-overlapping.ts +21 -0
  20. package/src/hooks/use-interactions-items.ts +108 -0
  21. package/src/hooks/use-style-items.ts +34 -8
  22. package/src/index.ts +9 -0
  23. package/src/init-settings-transformers.ts +4 -0
  24. package/src/init.tsx +18 -0
  25. package/src/legacy/create-templated-element-type.ts +67 -42
  26. package/src/legacy/init-legacy-views.ts +27 -5
  27. package/src/legacy/types.ts +44 -4
  28. package/src/mcp/canvas-mcp.ts +17 -0
  29. package/src/mcp/mcp-description.ts +40 -0
  30. package/src/mcp/resources/widgets-schema-resource.ts +173 -0
  31. package/src/mcp/tools/build-composition/prompt.ts +128 -0
  32. package/src/mcp/tools/build-composition/schema.ts +31 -0
  33. package/src/mcp/tools/build-composition/tool.ts +163 -0
  34. package/src/mcp/tools/configure-element/prompt.ts +93 -0
  35. package/src/mcp/tools/configure-element/schema.ts +25 -0
  36. package/src/mcp/tools/configure-element/tool.ts +67 -0
  37. package/src/mcp/tools/get-element-config/tool.ts +69 -0
  38. package/src/mcp/utils/do-update-element-property.ts +129 -0
  39. package/src/mcp/utils/generate-available-tags.ts +23 -0
  40. package/src/renderers/__tests__/__snapshots__/create-styles-renderer.test.ts.snap +2 -0
  41. package/src/renderers/__tests__/create-styles-renderer.test.ts +25 -0
  42. package/src/renderers/create-props-resolver.ts +8 -1
  43. package/src/renderers/create-styles-renderer.ts +20 -9
  44. package/src/renderers/errors.ts +6 -0
  45. package/src/sync/drag-element-from-panel.ts +49 -0
  46. package/src/sync/types.ts +32 -1
  47. package/src/transformers/settings/__tests__/attributes-transformer.test.ts +15 -0
  48. package/src/transformers/settings/__tests__/classes-transformer.test.ts +83 -0
  49. package/src/transformers/settings/attributes-transformer.ts +1 -23
  50. package/src/transformers/settings/classes-transformer.ts +21 -21
  51. package/src/transformers/settings/date-time-transformer.ts +12 -0
  52. package/src/transformers/settings/query-transformer.ts +10 -0
  53. package/src/transformers/styles/__tests__/transform-origin-transformer.test.ts +24 -0
  54. package/src/transformers/styles/__tests__/transition-transformer.test.ts +52 -0
  55. package/src/transformers/styles/background-transformer.ts +3 -1
  56. package/src/transformers/styles/transform-origin-transformer.ts +12 -2
  57. package/src/transformers/styles/transition-transformer.ts +34 -4
  58. package/src/types/element-overlay.ts +18 -0
  59. package/src/utils/inline-editing-utils.ts +43 -0
package/dist/index.js CHANGED
@@ -31,16 +31,23 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
31
31
  var index_exports = {};
32
32
  __export(index_exports, {
33
33
  createPropsResolver: () => createPropsResolver,
34
+ createTemplatedElementView: () => createTemplatedElementView,
34
35
  createTransformer: () => createTransformer,
35
36
  createTransformersRegistry: () => createTransformersRegistry,
37
+ endDragElementFromPanel: () => endDragElementFromPanel,
38
+ getCanvasIframeDocument: () => getCanvasIframeDocument,
36
39
  init: () => init,
40
+ registerElementType: () => registerElementType,
37
41
  settingsTransformersRegistry: () => settingsTransformersRegistry,
42
+ startDragElementFromPanel: () => startDragElementFromPanel,
38
43
  styleTransformersRegistry: () => styleTransformersRegistry
39
44
  });
40
45
  module.exports = __toCommonJS(index_exports);
41
46
 
42
47
  // src/init.tsx
43
48
  var import_editor = require("@elementor/editor");
49
+ var import_editor_interactions2 = require("@elementor/editor-interactions");
50
+ var import_editor_mcp3 = require("@elementor/editor-mcp");
44
51
 
45
52
  // src/components/classes-rename.tsx
46
53
  var import_react = require("react");
@@ -85,19 +92,102 @@ var renameClass = (oldClassName, newClassName) => {
85
92
  };
86
93
 
87
94
  // src/components/elements-overlays.tsx
88
- var React2 = __toESM(require("react"));
89
- var import_editor_elements = require("@elementor/editor-elements");
95
+ var React3 = __toESM(require("react"));
96
+ var import_editor_elements3 = require("@elementor/editor-elements");
90
97
  var import_editor_v1_adapters = require("@elementor/editor-v1-adapters");
91
98
 
92
- // src/components/element-overlay.tsx
99
+ // src/utils/inline-editing-utils.ts
100
+ var import_editor_elements = require("@elementor/editor-elements");
101
+ var WIDGET_PROPERTY_MAP = {
102
+ "e-heading": "title",
103
+ "e-paragraph": "paragraph"
104
+ };
105
+ var getHtmlPropertyName = (container) => {
106
+ const widgetType = container?.model?.get("widgetType") ?? container?.model?.get("elType");
107
+ if (!widgetType) {
108
+ return "";
109
+ }
110
+ if (WIDGET_PROPERTY_MAP[widgetType]) {
111
+ return WIDGET_PROPERTY_MAP[widgetType];
112
+ }
113
+ const propsSchema = (0, import_editor_elements.getElementType)(widgetType)?.propsSchema;
114
+ if (!propsSchema) {
115
+ return "";
116
+ }
117
+ const entry = Object.entries(propsSchema).find(([, propType]) => propType.key === "html");
118
+ return entry?.[0] ?? "";
119
+ };
120
+ var hasInlineEditableProperty = (containerId) => {
121
+ const container = (0, import_editor_elements.getContainer)(containerId);
122
+ const widgetType = container?.model?.get("widgetType") ?? container?.model?.get("elType");
123
+ if (!widgetType) {
124
+ return false;
125
+ }
126
+ return widgetType in WIDGET_PROPERTY_MAP;
127
+ };
128
+ var getInlineEditablePropertyName = (container) => {
129
+ return getHtmlPropertyName(container);
130
+ };
131
+
132
+ // src/components/inline-editor-overlay.tsx
133
+ var React2 = __toESM(require("react"));
134
+ var import_editor_controls = require("@elementor/editor-controls");
135
+ var import_editor_elements2 = require("@elementor/editor-elements");
136
+ var import_editor_props = require("@elementor/editor-props");
137
+ var import_ui2 = require("@elementor/ui");
138
+ var import_utils2 = require("@elementor/utils");
139
+ var import_react6 = require("@floating-ui/react");
140
+
141
+ // src/hooks/use-floating-on-element.ts
142
+ var import_react2 = require("react");
143
+ var import_react3 = require("@floating-ui/react");
144
+ function useFloatingOnElement({ element, isSelected }) {
145
+ const [isOpen, setIsOpen] = (0, import_react2.useState)(false);
146
+ const sizeModifier = 2;
147
+ const { refs, floatingStyles, context } = (0, import_react3.useFloating)({
148
+ // Must be controlled for interactions (like hover) to work.
149
+ open: isOpen || isSelected,
150
+ onOpenChange: setIsOpen,
151
+ whileElementsMounted: import_react3.autoUpdate,
152
+ middleware: [
153
+ // Match the floating element's size to the reference element.
154
+ (0, import_react3.size)(() => {
155
+ return {
156
+ apply({ elements, rects }) {
157
+ Object.assign(elements.floating.style, {
158
+ width: `${rects.reference.width + sizeModifier}px`,
159
+ height: `${rects.reference.height + sizeModifier}px`
160
+ });
161
+ }
162
+ };
163
+ }),
164
+ // Center the floating element on the reference element.
165
+ (0, import_react3.offset)(({ rects }) => -rects.reference.height / 2 - rects.floating.height / 2)
166
+ ]
167
+ });
168
+ (0, import_react2.useEffect)(() => {
169
+ refs.setReference(element);
170
+ }, [element, refs]);
171
+ return {
172
+ isVisible: isOpen || isSelected,
173
+ context,
174
+ floating: {
175
+ setRef: refs.setFloating,
176
+ ref: refs.floating,
177
+ styles: floatingStyles
178
+ }
179
+ };
180
+ }
181
+
182
+ // src/components/outline-overlay.tsx
93
183
  var React = __toESM(require("react"));
94
184
  var import_ui = require("@elementor/ui");
95
185
  var import_react5 = require("@floating-ui/react");
96
186
 
97
187
  // src/hooks/use-bind-react-props-to-element.ts
98
- var import_react2 = require("react");
188
+ var import_react4 = require("react");
99
189
  function useBindReactPropsToElement(element, getProps) {
100
- (0, import_react2.useEffect)(() => {
190
+ (0, import_react4.useEffect)(() => {
101
191
  const el = element;
102
192
  const { events, attrs } = groupProps(getProps());
103
193
  events.forEach(([eventName, listener]) => el.addEventListener(eventName, listener));
@@ -128,45 +218,24 @@ function groupProps(props) {
128
218
  );
129
219
  }
130
220
 
131
- // src/hooks/use-floating-on-element.ts
132
- var import_react3 = require("react");
133
- var import_react4 = require("@floating-ui/react");
134
- function useFloatingOnElement({ element, isSelected }) {
135
- const [isOpen, setIsOpen] = (0, import_react3.useState)(false);
136
- const { refs, floatingStyles, context } = (0, import_react4.useFloating)({
137
- // Must be controlled for interactions (like hover) to work.
138
- open: isOpen || isSelected,
139
- onOpenChange: setIsOpen,
140
- whileElementsMounted: import_react4.autoUpdate,
141
- middleware: [
142
- // Match the floating element's size to the reference element.
143
- (0, import_react4.size)({
144
- apply({ elements, rects }) {
145
- Object.assign(elements.floating.style, {
146
- width: `${rects.reference.width + 2}px`,
147
- height: `${rects.reference.height + 2}px`
148
- });
149
- }
150
- }),
151
- // Center the floating element on the reference element.
152
- (0, import_react4.offset)(({ rects }) => -rects.reference.height / 2 - rects.floating.height / 2)
153
- ]
154
- });
155
- (0, import_react3.useEffect)(() => {
156
- refs.setReference(element);
157
- }, [element, refs]);
158
- return {
159
- isVisible: isOpen || isSelected,
160
- context,
161
- floating: {
162
- setRef: refs.setFloating,
163
- ref: refs.floating,
164
- styles: floatingStyles
165
- }
166
- };
167
- }
221
+ // src/hooks/use-has-overlapping.ts
222
+ var possibleOverlappingSelectors = [".e-off-canvas"];
223
+ var useHasOverlapping = () => {
224
+ const preview = window.elementor?.$preview?.[0];
225
+ if (!preview) {
226
+ return false;
227
+ }
228
+ const hasOverlapping = possibleOverlappingSelectors.map((selector) => Array.from(preview?.contentWindow?.document.body.querySelectorAll(selector) ?? [])).flat().some(
229
+ (elem) => elem.checkVisibility({
230
+ opacityProperty: true,
231
+ visibilityProperty: true,
232
+ contentVisibilityAuto: true
233
+ })
234
+ );
235
+ return hasOverlapping;
236
+ };
168
237
 
169
- // src/components/element-overlay.tsx
238
+ // src/components/outline-overlay.tsx
170
239
  var CANVAS_WRAPPER_ID = "elementor-preview-responsive-wrapper";
171
240
  var OverlayBox = (0, import_ui.styled)(import_ui.Box, {
172
241
  shouldForwardProp: (prop) => prop !== "isSelected" && prop !== "isSmallerOffset"
@@ -175,12 +244,13 @@ var OverlayBox = (0, import_ui.styled)(import_ui.Box, {
175
244
  outlineOffset: isSelected && !isSmallerOffset ? "-2px" : "-1px",
176
245
  pointerEvents: "none"
177
246
  }));
178
- function ElementOverlay({ element, isSelected, id }) {
247
+ var OutlineOverlay = ({ element, isSelected, id }) => {
179
248
  const { context, floating, isVisible } = useFloatingOnElement({ element, isSelected });
180
249
  const { getFloatingProps, getReferenceProps } = (0, import_react5.useInteractions)([(0, import_react5.useHover)(context)]);
250
+ const hasOverlapping = useHasOverlapping();
181
251
  useBindReactPropsToElement(element, getReferenceProps);
182
252
  const isSmallerOffset = element.offsetHeight <= 1;
183
- return isVisible && /* @__PURE__ */ React.createElement(import_react5.FloatingPortal, { id: CANVAS_WRAPPER_ID }, /* @__PURE__ */ React.createElement(
253
+ return isVisible && !hasOverlapping && /* @__PURE__ */ React.createElement(import_react5.FloatingPortal, { id: CANVAS_WRAPPER_ID }, /* @__PURE__ */ React.createElement(
184
254
  OverlayBox,
185
255
  {
186
256
  ref: floating.setRef,
@@ -192,49 +262,238 @@ function ElementOverlay({ element, isSelected, id }) {
192
262
  ...getFloatingProps()
193
263
  }
194
264
  ));
195
- }
265
+ };
266
+
267
+ // src/components/inline-editor-overlay.tsx
268
+ var OVERLAY_Z_INDEX = 1e3;
269
+ var DEBOUNCE_DELAY = 100;
270
+ var InlineEditorOverlay = ({ element, isSelected, id }) => {
271
+ const { floating, isVisible } = useFloatingOnElement({ element, isSelected });
272
+ const propertyName = React2.useMemo(() => {
273
+ const container = (0, import_editor_elements2.getContainer)(id);
274
+ return getInlineEditablePropertyName(container);
275
+ }, [id]);
276
+ const contentProp = (0, import_editor_elements2.useElementSetting)(id, propertyName);
277
+ const value = React2.useMemo(() => import_editor_props.htmlPropTypeUtil.extract(contentProp) || "", [contentProp]);
278
+ const debouncedUpdateRef = React2.useRef(null);
279
+ const lastValueRef = React2.useRef("");
280
+ React2.useEffect(() => {
281
+ debouncedUpdateRef.current = (0, import_utils2.debounce)((newValue) => {
282
+ const textContent = newValue.replace(/<[^>]*>/g, "").trim();
283
+ const valueToSave = textContent === "" ? "&nbsp;" : newValue;
284
+ (0, import_editor_elements2.updateElementSettings)({
285
+ id,
286
+ props: {
287
+ [propertyName]: import_editor_props.htmlPropTypeUtil.create(valueToSave)
288
+ },
289
+ withHistory: true
290
+ });
291
+ }, DEBOUNCE_DELAY);
292
+ return () => {
293
+ debouncedUpdateRef.current?.cancel?.();
294
+ };
295
+ }, [id, propertyName]);
296
+ const handleValueChange = React2.useCallback((newValue) => {
297
+ lastValueRef.current = newValue;
298
+ debouncedUpdateRef.current?.(newValue);
299
+ }, []);
300
+ React2.useEffect(() => {
301
+ if (!isVisible && debouncedUpdateRef.current?.pending?.()) {
302
+ debouncedUpdateRef.current.flush(lastValueRef.current);
303
+ }
304
+ }, [isVisible]);
305
+ if (!isVisible) {
306
+ return null;
307
+ }
308
+ return /* @__PURE__ */ React2.createElement(import_react6.FloatingPortal, { id: CANVAS_WRAPPER_ID }, /* @__PURE__ */ React2.createElement(
309
+ import_ui2.Box,
310
+ {
311
+ ref: floating.setRef,
312
+ style: {
313
+ ...floating.styles,
314
+ zIndex: OVERLAY_Z_INDEX,
315
+ pointerEvents: "auto"
316
+ }
317
+ },
318
+ /* @__PURE__ */ React2.createElement(import_editor_controls.InlineEditor, { value, setValue: handleValueChange, showToolbar: isSelected })
319
+ ));
320
+ };
196
321
 
197
322
  // src/components/elements-overlays.tsx
323
+ var ELEMENTS_DATA_ATTR = "atomic";
324
+ var overlayRegistry = [
325
+ {
326
+ component: OutlineOverlay,
327
+ shouldRender: () => true
328
+ },
329
+ {
330
+ component: InlineEditorOverlay,
331
+ shouldRender: ({ id, isSelected }) => isSelected && hasInlineEditableProperty(id) && (0, import_editor_v1_adapters.isExperimentActive)("v4-inline-text-editing")
332
+ }
333
+ ];
198
334
  function ElementsOverlays() {
199
- const selected = (0, import_editor_elements.useSelectedElement)();
335
+ const selected = (0, import_editor_elements3.useSelectedElement)();
200
336
  const elements = useElementsDom();
201
337
  const currentEditMode = (0, import_editor_v1_adapters.useEditMode)();
202
338
  const isEditMode = currentEditMode === "edit";
203
339
  const isKitRouteActive = (0, import_editor_v1_adapters.__privateUseIsRouteActive)("panel/global");
204
340
  const isActive = isEditMode && !isKitRouteActive;
205
- return isActive && elements.map(([id, element]) => /* @__PURE__ */ React2.createElement(ElementOverlay, { key: id, id, element, isSelected: selected.element?.id === id }));
341
+ if (!isActive) {
342
+ return null;
343
+ }
344
+ return elements.map(([id, element]) => {
345
+ const isSelected = selected.element?.id === id;
346
+ return overlayRegistry.map(
347
+ ({ shouldRender, component: Overlay }, index) => shouldRender({ id, element, isSelected }) && /* @__PURE__ */ React3.createElement(Overlay, { key: `${id}-${index}`, id, element, isSelected })
348
+ );
349
+ });
206
350
  }
207
- var ELEMENTS_DATA_ATTR = "atomic";
208
351
  function useElementsDom() {
209
352
  return (0, import_editor_v1_adapters.__privateUseListenTo)(
210
353
  [(0, import_editor_v1_adapters.windowEvent)("elementor/editor/element-rendered"), (0, import_editor_v1_adapters.windowEvent)("elementor/editor/element-destroyed")],
211
354
  () => {
212
- return (0, import_editor_elements.getElements)().filter((el) => ELEMENTS_DATA_ATTR in (el.view?.el?.dataset ?? {})).map((element) => [element.id, element.view?.getDomElement?.()?.get?.(0)]).filter((item) => !!item[1]);
355
+ return (0, import_editor_elements3.getElements)().filter((el) => ELEMENTS_DATA_ATTR in (el.view?.el?.dataset ?? {})).map((element) => [element.id, element.view?.getDomElement?.()?.get?.(0)]).filter((item) => !!item[1]);
213
356
  }
214
357
  );
215
358
  }
216
359
 
217
- // src/components/style-renderer.tsx
218
- var React3 = __toESM(require("react"));
219
- var import_editor_v1_adapters5 = require("@elementor/editor-v1-adapters");
220
- var import_ui2 = require("@elementor/ui");
360
+ // src/components/interactions-renderer.tsx
361
+ var React4 = __toESM(require("react"));
362
+ var import_editor_v1_adapters3 = require("@elementor/editor-v1-adapters");
363
+ var import_ui3 = require("@elementor/ui");
221
364
 
222
- // src/hooks/use-documents-css-links.ts
365
+ // src/hooks/use-interactions-items.ts
366
+ var import_react8 = require("react");
367
+ var import_editor_interactions = require("@elementor/editor-interactions");
223
368
  var import_editor_v1_adapters2 = require("@elementor/editor-v1-adapters");
224
369
 
370
+ // src/hooks/use-on-mount.ts
371
+ var import_react7 = require("react");
372
+ function useOnMount(cb) {
373
+ const mounted = (0, import_react7.useRef)(false);
374
+ (0, import_react7.useEffect)(() => {
375
+ if (!mounted.current) {
376
+ mounted.current = true;
377
+ cb();
378
+ }
379
+ }, []);
380
+ }
381
+
382
+ // src/hooks/use-interactions-items.ts
383
+ function useInteractionsItems() {
384
+ const [interactionItems, setInteractionItems] = (0, import_react8.useState)({});
385
+ const providerAndSubscribers = (0, import_react8.useMemo)(() => {
386
+ try {
387
+ const providers = import_editor_interactions.interactionsRepository.getProviders();
388
+ const mapped = providers.map((provider) => {
389
+ return {
390
+ provider,
391
+ subscriber: createProviderSubscriber({
392
+ provider,
393
+ setInteractionItems
394
+ })
395
+ };
396
+ });
397
+ return mapped;
398
+ } catch {
399
+ return [];
400
+ }
401
+ }, []);
402
+ (0, import_react8.useEffect)(() => {
403
+ if (providerAndSubscribers.length === 0) {
404
+ return;
405
+ }
406
+ const unsubscribes = providerAndSubscribers.map(({ provider, subscriber }) => {
407
+ const safeSubscriber = () => {
408
+ try {
409
+ subscriber();
410
+ } catch {
411
+ }
412
+ };
413
+ const unsubscribe = provider.subscribe(safeSubscriber);
414
+ return unsubscribe;
415
+ });
416
+ return () => {
417
+ unsubscribes.forEach((unsubscribe) => unsubscribe());
418
+ };
419
+ }, [providerAndSubscribers]);
420
+ useOnMount(() => {
421
+ if (providerAndSubscribers.length === 0) {
422
+ return;
423
+ }
424
+ (0, import_editor_v1_adapters2.registerDataHook)("after", "editor/documents/attach-preview", async () => {
425
+ providerAndSubscribers.forEach(({ subscriber }) => {
426
+ try {
427
+ subscriber();
428
+ } catch {
429
+ }
430
+ });
431
+ });
432
+ });
433
+ return (0, import_react8.useMemo)(() => {
434
+ const result = Object.values(interactionItems).sort(sortByProviderPriority).flatMap(({ items }) => items);
435
+ return result;
436
+ }, [interactionItems]);
437
+ }
438
+ function sortByProviderPriority({ provider: providerA }, { provider: providerB }) {
439
+ return providerA.priority - providerB.priority;
440
+ }
441
+ function createProviderSubscriber({ provider, setInteractionItems }) {
442
+ return () => {
443
+ try {
444
+ const items = provider.actions.all();
445
+ const providerKey = provider.getKey();
446
+ setInteractionItems((prev) => ({
447
+ ...prev,
448
+ [providerKey]: { provider, items }
449
+ }));
450
+ } catch {
451
+ }
452
+ };
453
+ }
454
+
225
455
  // src/sync/get-canvas-iframe-document.ts
226
456
  function getCanvasIframeDocument() {
227
457
  const extendedWindow = window;
228
458
  return extendedWindow.elementor?.$preview?.[0]?.contentDocument;
229
459
  }
230
460
 
461
+ // src/components/interactions-renderer.tsx
462
+ function InteractionsRenderer() {
463
+ const container = usePortalContainer();
464
+ const interactionItems = useInteractionsItems();
465
+ if (!container) {
466
+ return null;
467
+ }
468
+ const interactionsData = JSON.stringify(Array.isArray(interactionItems) ? interactionItems : []);
469
+ return /* @__PURE__ */ React4.createElement(import_ui3.Portal, { container }, /* @__PURE__ */ React4.createElement(
470
+ "script",
471
+ {
472
+ type: "application/json",
473
+ "data-e-interactions": "true",
474
+ dangerouslySetInnerHTML: {
475
+ __html: interactionsData
476
+ }
477
+ }
478
+ ));
479
+ }
480
+ function usePortalContainer() {
481
+ return (0, import_editor_v1_adapters3.__privateUseListenTo)((0, import_editor_v1_adapters3.commandEndEvent)("editor/documents/attach-preview"), () => getCanvasIframeDocument()?.head);
482
+ }
483
+
484
+ // src/components/style-renderer.tsx
485
+ var React5 = __toESM(require("react"));
486
+ var import_editor_v1_adapters6 = require("@elementor/editor-v1-adapters");
487
+ var import_ui4 = require("@elementor/ui");
488
+
231
489
  // src/hooks/use-documents-css-links.ts
490
+ var import_editor_v1_adapters4 = require("@elementor/editor-v1-adapters");
232
491
  var REMOVED_ATTR = "data-e-removed";
233
492
  var DOCUMENT_WRAPPER_ATTR = "data-elementor-id";
234
493
  var CSS_LINK_ID_PREFIX = "elementor-post-";
235
494
  var CSS_LINK_ID_SUFFIX = "-css";
236
495
  function useDocumentsCssLinks() {
237
- return (0, import_editor_v1_adapters2.__privateUseListenTo)((0, import_editor_v1_adapters2.commandEndEvent)("editor/documents/attach-preview"), () => {
496
+ return (0, import_editor_v1_adapters4.__privateUseListenTo)((0, import_editor_v1_adapters4.commandEndEvent)("editor/documents/attach-preview"), () => {
238
497
  const iframeDocument = getCanvasIframeDocument();
239
498
  if (!iframeDocument) {
240
499
  return [];
@@ -275,10 +534,11 @@ function getLinkAttrs(el) {
275
534
  }
276
535
 
277
536
  // src/hooks/use-style-items.ts
278
- var import_react9 = require("react");
537
+ var import_react11 = require("react");
279
538
  var import_editor_responsive2 = require("@elementor/editor-responsive");
539
+ var import_editor_styles3 = require("@elementor/editor-styles");
280
540
  var import_editor_styles_repository2 = require("@elementor/editor-styles-repository");
281
- var import_editor_v1_adapters4 = require("@elementor/editor-v1-adapters");
541
+ var import_editor_v1_adapters5 = require("@elementor/editor-v1-adapters");
282
542
 
283
543
  // src/utils/abort-previous-runs.ts
284
544
  function abortPreviousRuns(cb) {
@@ -311,24 +571,12 @@ function signalizedProcess(signal, steps = []) {
311
571
  };
312
572
  }
313
573
 
314
- // src/hooks/use-on-mount.ts
315
- var import_react6 = require("react");
316
- function useOnMount(cb) {
317
- const mounted = (0, import_react6.useRef)(false);
318
- (0, import_react6.useEffect)(() => {
319
- if (!mounted.current) {
320
- mounted.current = true;
321
- cb();
322
- }
323
- }, []);
324
- }
325
-
326
574
  // src/hooks/use-style-prop-resolver.ts
327
- var import_react7 = require("react");
575
+ var import_react9 = require("react");
328
576
  var import_editor_styles = require("@elementor/editor-styles");
329
577
 
330
578
  // src/renderers/create-props-resolver.ts
331
- var import_editor_props = require("@elementor/editor-props");
579
+ var import_editor_props2 = require("@elementor/editor-props");
332
580
 
333
581
  // src/renderers/multi-props.ts
334
582
  var isMultiProps = (propValue) => {
@@ -347,10 +595,10 @@ var getMultiPropsValue = (multiProps) => {
347
595
  // src/renderers/create-props-resolver.ts
348
596
  var TRANSFORM_DEPTH_LIMIT = 3;
349
597
  function createPropsResolver({ transformers, schema: initialSchema, onPropResolve }) {
350
- async function resolve({ props, schema, signal }) {
351
- schema = schema ?? initialSchema;
598
+ async function resolve({ props, schema: schema2, signal }) {
599
+ schema2 = schema2 ?? initialSchema;
352
600
  const promises = Promise.all(
353
- Object.entries(schema).map(async ([key, type]) => {
601
+ Object.entries(schema2).map(async ([key, type]) => {
354
602
  const value = props[key] ?? type.default;
355
603
  const transformed = await transform({ value, key, type, signal });
356
604
  onPropResolve?.({ key, value: transformed });
@@ -366,7 +614,7 @@ function createPropsResolver({ transformers, schema: initialSchema, onPropResolv
366
614
  if (value === null || value === void 0) {
367
615
  return null;
368
616
  }
369
- if (!(0, import_editor_props.isTransformable)(value)) {
617
+ if (!(0, import_editor_props2.isTransformable)(value)) {
370
618
  return value;
371
619
  }
372
620
  if (depth > TRANSFORM_DEPTH_LIMIT) {
@@ -375,6 +623,10 @@ function createPropsResolver({ transformers, schema: initialSchema, onPropResolv
375
623
  if (value.disabled === true) {
376
624
  return null;
377
625
  }
626
+ value = (0, import_editor_props2.migratePropValue)(value, type);
627
+ if (!(0, import_editor_props2.isTransformable)(value)) {
628
+ return value;
629
+ }
378
630
  if (type.kind === "union") {
379
631
  type = type.prop_types[value.$$type];
380
632
  if (!type) {
@@ -446,7 +698,7 @@ var enqueueFont = (fontFamily, context = "preview") => {
446
698
 
447
699
  // src/hooks/use-style-prop-resolver.ts
448
700
  function useStylePropResolver() {
449
- return (0, import_react7.useMemo)(() => {
701
+ return (0, import_react9.useMemo)(() => {
450
702
  return createPropsResolver({
451
703
  transformers: styleTransformersRegistry,
452
704
  schema: (0, import_editor_styles.getStylesSchema)(),
@@ -461,19 +713,23 @@ function useStylePropResolver() {
461
713
  }
462
714
 
463
715
  // src/hooks/use-style-renderer.ts
464
- var import_react8 = require("react");
716
+ var import_react10 = require("react");
465
717
  var import_editor_responsive = require("@elementor/editor-responsive");
466
718
 
467
719
  // src/renderers/create-styles-renderer.ts
468
- var import_editor_v1_adapters3 = require("@elementor/editor-v1-adapters");
469
- var import_utils3 = require("@elementor/utils");
720
+ var import_editor_styles2 = require("@elementor/editor-styles");
721
+ var import_utils4 = require("@elementor/utils");
470
722
 
471
723
  // src/renderers/errors.ts
472
- var import_utils2 = require("@elementor/utils");
473
- var UnknownStyleTypeError = (0, import_utils2.createError)({
724
+ var import_utils3 = require("@elementor/utils");
725
+ var UnknownStyleTypeError = (0, import_utils3.createError)({
474
726
  code: "unknown_style_type",
475
727
  message: "Unknown style type"
476
728
  });
729
+ var UnknownStyleStateError = (0, import_utils3.createError)({
730
+ code: "unknown_style_state",
731
+ message: "Unknown style state"
732
+ });
477
733
 
478
734
  // src/renderers/create-styles-renderer.ts
479
735
  var SELECTORS_MAP = {
@@ -491,7 +747,8 @@ function createStylesRenderer({ resolve, breakpoints, selectorPrefix = "" }) {
491
747
  return {
492
748
  id: style.id,
493
749
  breakpoint: style?.variants[0]?.meta?.breakpoint || "desktop",
494
- value: variantsCss.join("")
750
+ value: variantsCss.join(""),
751
+ state: style?.variants[0]?.meta?.state || null
495
752
  };
496
753
  });
497
754
  return await Promise.all(stylesCssPromises);
@@ -507,7 +764,18 @@ function createStyleWrapper(value = "", wrapper) {
507
764
  return createStyleWrapper(`${value}${symbol}${cssName}`, wrapper);
508
765
  },
509
766
  withPrefix: (prefix) => createStyleWrapper([prefix, value].filter(Boolean).join(" "), wrapper),
510
- withState: (state) => createStyleWrapper(state ? `${value}:${state}` : value, wrapper),
767
+ withState: (state) => {
768
+ if (!state) {
769
+ return createStyleWrapper(value, wrapper);
770
+ }
771
+ if ((0, import_editor_styles2.isClassState)(state)) {
772
+ return createStyleWrapper(`${value}.${state}`, wrapper);
773
+ }
774
+ if ((0, import_editor_styles2.isPseudoState)(state)) {
775
+ return createStyleWrapper(`${value}:${state}`, wrapper);
776
+ }
777
+ throw new UnknownStyleStateError({ context: { state } });
778
+ },
511
779
  withMediaQuery: (breakpoint) => {
512
780
  if (!breakpoint?.type) {
513
781
  return createStyleWrapper(value, wrapper);
@@ -535,10 +803,7 @@ async function propsToCss({ props, resolve, signal }) {
535
803
  }, []).join("");
536
804
  }
537
805
  function customCssToString(customCss) {
538
- if (!(0, import_editor_v1_adapters3.isExperimentActive)(import_editor_v1_adapters3.EXPERIMENTAL_FEATURES.CUSTOM_CSS) || !customCss?.raw) {
539
- return "";
540
- }
541
- const decoded = (0, import_utils3.decodeString)(customCss.raw);
806
+ const decoded = (0, import_utils4.decodeString)(customCss?.raw || "");
542
807
  if (!decoded.trim()) {
543
808
  return "";
544
809
  }
@@ -549,7 +814,7 @@ function customCssToString(customCss) {
549
814
  var SELECTOR_PREFIX = ".elementor";
550
815
  function useStyleRenderer(resolve) {
551
816
  const breakpoints = (0, import_editor_responsive.useBreakpointsMap)();
552
- return (0, import_react8.useMemo)(() => {
817
+ return (0, import_react10.useMemo)(() => {
553
818
  return createStylesRenderer({
554
819
  selectorPrefix: SELECTOR_PREFIX,
555
820
  breakpoints,
@@ -562,12 +827,12 @@ function useStyleRenderer(resolve) {
562
827
  function useStyleItems() {
563
828
  const resolve = useStylePropResolver();
564
829
  const renderStyles = useStyleRenderer(resolve);
565
- const [styleItems, setStyleItems] = (0, import_react9.useState)({});
566
- const providerAndSubscribers = (0, import_react9.useMemo)(() => {
830
+ const [styleItems, setStyleItems] = (0, import_react11.useState)({});
831
+ const providerAndSubscribers = (0, import_react11.useMemo)(() => {
567
832
  return import_editor_styles_repository2.stylesRepository.getProviders().map((provider) => {
568
833
  return {
569
834
  provider,
570
- subscriber: createProviderSubscriber({
835
+ subscriber: createProviderSubscriber2({
571
836
  provider,
572
837
  renderStyles,
573
838
  setStyleItems
@@ -575,7 +840,7 @@ function useStyleItems() {
575
840
  };
576
841
  });
577
842
  }, [renderStyles]);
578
- (0, import_react9.useEffect)(() => {
843
+ (0, import_react11.useEffect)(() => {
579
844
  const unsubscribes = providerAndSubscribers.map(
580
845
  ({ provider, subscriber }) => provider.subscribe(subscriber)
581
846
  );
@@ -584,22 +849,34 @@ function useStyleItems() {
584
849
  };
585
850
  }, [providerAndSubscribers]);
586
851
  useOnMount(() => {
587
- (0, import_editor_v1_adapters4.registerDataHook)("after", "editor/documents/attach-preview", async () => {
852
+ (0, import_editor_v1_adapters5.registerDataHook)("after", "editor/documents/attach-preview", async () => {
588
853
  const promises = providerAndSubscribers.map(async ({ subscriber }) => subscriber());
589
854
  await Promise.all(promises);
590
855
  });
591
856
  });
592
857
  const breakpointsOrder = (0, import_editor_responsive2.getBreakpoints)().map((breakpoint) => breakpoint.id);
593
- return (0, import_react9.useMemo)(
594
- () => Object.values(styleItems).sort(({ provider: providerA }, { provider: providerB }) => providerA.priority - providerB.priority).flatMap(({ items }) => items).sort(({ breakpoint: breakpointA }, { breakpoint: breakpointB }) => {
595
- return breakpointsOrder.indexOf(breakpointA) - breakpointsOrder.indexOf(breakpointB);
596
- }),
597
- // eslint-disable-next-line
858
+ return (0, import_react11.useMemo)(
859
+ () => Object.values(styleItems).sort(sortByProviderPriority2).flatMap(({ items }) => items).sort(sortByStateType).sort(sortByBreakpoint(breakpointsOrder)),
598
860
  // eslint-disable-next-line react-hooks/exhaustive-deps
599
861
  [styleItems, breakpointsOrder.join("-")]
600
862
  );
601
863
  }
602
- function createProviderSubscriber({ provider, renderStyles, setStyleItems }) {
864
+ function sortByProviderPriority2({ provider: providerA }, { provider: providerB }) {
865
+ return providerA.priority - providerB.priority;
866
+ }
867
+ function sortByBreakpoint(breakpointsOrder) {
868
+ return ({ breakpoint: breakpointA }, { breakpoint: breakpointB }) => breakpointsOrder.indexOf(breakpointA) - breakpointsOrder.indexOf(breakpointB);
869
+ }
870
+ function sortByStateType({ state: stateA }, { state: stateB }) {
871
+ if ((0, import_editor_styles3.isClassState)(stateA) && !(0, import_editor_styles3.isClassState)(stateB)) {
872
+ return -1;
873
+ }
874
+ if (!(0, import_editor_styles3.isClassState)(stateA) && (0, import_editor_styles3.isClassState)(stateB)) {
875
+ return 1;
876
+ }
877
+ return 0;
878
+ }
879
+ function createProviderSubscriber2({ provider, renderStyles, setStyleItems }) {
603
880
  return abortPreviousRuns(
604
881
  (abortController) => signalizedProcess(abortController.signal).then((_, signal) => {
605
882
  const styles = provider.actions.all().map((__5, index, items) => {
@@ -645,16 +922,16 @@ function createProviderSubscriber({ provider, renderStyles, setStyleItems }) {
645
922
 
646
923
  // src/components/style-renderer.tsx
647
924
  function StyleRenderer() {
648
- const container = usePortalContainer();
925
+ const container = usePortalContainer2();
649
926
  const styleItems = useStyleItems();
650
927
  const linksAttrs = useDocumentsCssLinks();
651
928
  if (!container) {
652
929
  return null;
653
930
  }
654
- return /* @__PURE__ */ React3.createElement(import_ui2.Portal, { container }, styleItems.map((item) => /* @__PURE__ */ React3.createElement("style", { "data-e-style-id": item.id, key: `${item.id}-${item.breakpoint}` }, item.value)), linksAttrs.map((attrs) => /* @__PURE__ */ React3.createElement("link", { ...attrs, key: attrs.id })));
931
+ return /* @__PURE__ */ React5.createElement(import_ui4.Portal, { container }, styleItems.map((item, i) => /* @__PURE__ */ React5.createElement("style", { key: `${item.id}-${i}-${item.breakpoint}` }, item.value)), linksAttrs.map((attrs) => /* @__PURE__ */ React5.createElement("link", { ...attrs, key: attrs.id })));
655
932
  }
656
- function usePortalContainer() {
657
- return (0, import_editor_v1_adapters5.__privateUseListenTo)((0, import_editor_v1_adapters5.commandEndEvent)("editor/documents/attach-preview"), () => getCanvasIframeDocument()?.head);
933
+ function usePortalContainer2() {
934
+ return (0, import_editor_v1_adapters6.__privateUseListenTo)((0, import_editor_v1_adapters6.commandEndEvent)("editor/documents/attach-preview"), () => getCanvasIframeDocument()?.head);
658
935
  }
659
936
 
660
937
  // src/settings-transformers-registry.ts
@@ -666,49 +943,40 @@ function createTransformer(cb) {
666
943
  }
667
944
 
668
945
  // src/transformers/settings/attributes-transformer.ts
669
- function escapeHtmlAttribute(value) {
670
- const specialChars = {
671
- "&": "&amp;",
672
- "<": "&lt;",
673
- ">": "&gt;",
674
- "'": "&#39;",
675
- '"': "&quot;"
676
- };
677
- return value.replace(/[&<>'"]/g, (char) => specialChars[char] || char);
678
- }
679
- var attributesTransformer = createTransformer((values) => {
680
- return values.map((value) => {
681
- if (!value.key || !value.value) {
682
- return "";
683
- }
684
- const escapedValue = escapeHtmlAttribute(value.value);
685
- return `${value.key}="${escapedValue}"`;
686
- }).join(" ");
687
- });
946
+ var attributesTransformer = createTransformer(() => "");
688
947
 
689
948
  // src/transformers/settings/classes-transformer.ts
690
949
  var import_editor_styles_repository3 = require("@elementor/editor-styles-repository");
950
+ function transformClassId(id, cache) {
951
+ if (!cache.has(id)) {
952
+ const provider2 = import_editor_styles_repository3.stylesRepository.getProviders().find((p) => {
953
+ return p.actions.all().find((style) => style.id === id);
954
+ });
955
+ if (!provider2) {
956
+ return id;
957
+ }
958
+ cache.set(id, provider2.getKey());
959
+ }
960
+ const providerKey = cache.get(id);
961
+ const provider = import_editor_styles_repository3.stylesRepository.getProviderByKey(providerKey);
962
+ return provider?.actions.resolveCssName(id) ?? id;
963
+ }
691
964
  function createClassesTransformer() {
692
965
  const cache = /* @__PURE__ */ new Map();
693
966
  return createTransformer((value) => {
694
- return value.map((id) => {
695
- if (!cache.has(id)) {
696
- cache.set(id, getCssName(id));
697
- }
698
- return cache.get(id);
699
- }).filter(Boolean);
700
- });
701
- }
702
- function getCssName(id) {
703
- const provider = import_editor_styles_repository3.stylesRepository.getProviders().find((p) => {
704
- return p.actions.all().find((style) => style.id === id);
967
+ return value.map((id) => transformClassId(id, cache)).filter(Boolean);
705
968
  });
706
- if (!provider) {
707
- return id;
708
- }
709
- return provider.actions.resolveCssName(id);
710
969
  }
711
970
 
971
+ // src/transformers/settings/date-time-transformer.ts
972
+ var dateTimeTransformer = createTransformer((values) => {
973
+ return values.map((value) => {
974
+ const date = (value.date || "").trim();
975
+ const time = (value.time || "").trim();
976
+ return !date && !time ? "" : `${date} ${time}`.trim();
977
+ }).join(" ");
978
+ });
979
+
712
980
  // src/transformers/settings/link-transformer.ts
713
981
  var linkTransformer = createTransformer(({ destination, isTargetBlank }) => {
714
982
  return {
@@ -718,6 +986,11 @@ var linkTransformer = createTransformer(({ destination, isTargetBlank }) => {
718
986
  };
719
987
  });
720
988
 
989
+ // src/transformers/settings/query-transformer.ts
990
+ var queryTransformer = createTransformer(({ id }) => {
991
+ return id ?? null;
992
+ });
993
+
721
994
  // src/transformers/shared/image-src-transformer.ts
722
995
  var imageSrcTransformer = createTransformer((value) => ({
723
996
  id: value.id ?? null,
@@ -757,7 +1030,7 @@ var plainTransformer = createTransformer((value) => {
757
1030
 
758
1031
  // src/init-settings-transformers.ts
759
1032
  function initSettingsTransformers() {
760
- settingsTransformersRegistry.register("classes", createClassesTransformer()).register("link", linkTransformer).register("image", imageTransformer).register("image-src", imageSrcTransformer).register("attributes", attributesTransformer).registerFallback(plainTransformer);
1033
+ settingsTransformersRegistry.register("classes", createClassesTransformer()).register("link", linkTransformer).register("query", queryTransformer).register("image", imageTransformer).register("image-src", imageSrcTransformer).register("attributes", attributesTransformer).register("date-time", dateTimeTransformer).registerFallback(plainTransformer);
761
1034
  }
762
1035
 
763
1036
  // src/transformers/styles/background-color-overlay-transformer.ts
@@ -855,10 +1128,11 @@ function getValuesString(items, prop, defaultValue, preventUnification = false)
855
1128
 
856
1129
  // src/transformers/styles/background-transformer.ts
857
1130
  var backgroundTransformer = createTransformer((value) => {
858
- const { color = null, "background-overlay": overlays = null } = value;
1131
+ const { color = null, "background-overlay": overlays = null, clip = null } = value;
859
1132
  return createMultiPropsValue({
860
1133
  ...overlays,
861
- "background-color": color
1134
+ "background-color": color,
1135
+ "background-clip": clip
862
1136
  });
863
1137
  });
864
1138
 
@@ -984,11 +1258,19 @@ var transformMoveTransformer = createTransformer((value) => {
984
1258
 
985
1259
  // src/transformers/styles/transform-origin-transformer.ts
986
1260
  var EMPTY_VALUE = "0px";
1261
+ var DEFAULT_XY = "50%";
1262
+ var DEFAULT_Z = EMPTY_VALUE;
987
1263
  function getVal2(val) {
988
1264
  return `${val ?? EMPTY_VALUE}`;
989
1265
  }
990
1266
  var transformOriginTransformer = createTransformer((value) => {
991
- return `${getVal2(value.x)} ${getVal2(value.y)} ${getVal2(value.z)}`;
1267
+ const x = getVal2(value.x);
1268
+ const y = getVal2(value.y);
1269
+ const z4 = getVal2(value.z);
1270
+ if (x === DEFAULT_XY && y === DEFAULT_XY && z4 === DEFAULT_Z) {
1271
+ return null;
1272
+ }
1273
+ return `${x} ${y} ${z4}`;
992
1274
  });
993
1275
 
994
1276
  // src/transformers/styles/transform-rotate-transformer.ts
@@ -1016,17 +1298,36 @@ var transformSkewTransformer = createTransformer((value) => {
1016
1298
  });
1017
1299
 
1018
1300
  // src/transformers/styles/transition-transformer.ts
1301
+ var import_editor_controls2 = require("@elementor/editor-controls");
1302
+ var getAllowedProperties = () => {
1303
+ const allowedProperties = /* @__PURE__ */ new Set();
1304
+ import_editor_controls2.transitionProperties.forEach((category) => {
1305
+ category.properties.forEach((property) => {
1306
+ allowedProperties.add(property.value);
1307
+ });
1308
+ });
1309
+ return allowedProperties;
1310
+ };
1019
1311
  var transitionTransformer = createTransformer((transitionValues) => {
1020
1312
  if (transitionValues?.length < 1) {
1021
1313
  return null;
1022
1314
  }
1023
- return transitionValues.filter(Boolean).map(mapToTransitionString).join(", ");
1315
+ const allowedProperties = getAllowedProperties();
1316
+ const validTransitions = transitionValues.map((value) => mapToTransitionString(value, allowedProperties)).filter(Boolean);
1317
+ if (validTransitions.length === 0) {
1318
+ return null;
1319
+ }
1320
+ return validTransitions.join(", ");
1024
1321
  });
1025
- var mapToTransitionString = (value) => {
1322
+ var mapToTransitionString = (value, allowedProperties) => {
1026
1323
  if (!value.selection || !value.size) {
1027
1324
  return "";
1028
1325
  }
1029
- return `${value.selection.value} ${value.size}`;
1326
+ const property = value.selection.value;
1327
+ if (!allowedProperties.has(property)) {
1328
+ return "";
1329
+ }
1330
+ return `${property} ${value.size}`;
1030
1331
  };
1031
1332
 
1032
1333
  // src/init-style-transformers.ts
@@ -1062,8 +1363,8 @@ function initStyleTransformers() {
1062
1363
  }
1063
1364
 
1064
1365
  // src/legacy/init-legacy-views.ts
1065
- var import_editor_elements2 = require("@elementor/editor-elements");
1066
- var import_editor_v1_adapters6 = require("@elementor/editor-v1-adapters");
1366
+ var import_editor_elements4 = require("@elementor/editor-elements");
1367
+ var import_editor_v1_adapters7 = require("@elementor/editor-v1-adapters");
1067
1368
 
1068
1369
  // src/renderers/create-dom-renderer.ts
1069
1370
  var import_twing = require("@elementor/twing");
@@ -1187,26 +1488,21 @@ function createElementViewClassDeclaration() {
1187
1488
  }
1188
1489
 
1189
1490
  // src/legacy/create-templated-element-type.ts
1190
- function createTemplatedElementType({ type, renderer, element }) {
1491
+ function createTemplatedElementType({
1492
+ type,
1493
+ renderer,
1494
+ element
1495
+ }) {
1191
1496
  const legacyWindow = window;
1192
- Object.entries(element.twig_templates).forEach(([key, template]) => {
1193
- renderer.register(key, template);
1194
- });
1195
- const propsResolver = createPropsResolver({
1196
- transformers: settingsTransformersRegistry,
1197
- schema: element.atomic_props_schema
1198
- });
1199
1497
  return class extends legacyWindow.elementor.modules.elements.types.Widget {
1200
1498
  getType() {
1201
1499
  return type;
1202
1500
  }
1203
1501
  getView() {
1204
- return createTemplatedElementViewClassDeclaration({
1502
+ return createTemplatedElementView({
1205
1503
  type,
1206
1504
  renderer,
1207
- propsResolver,
1208
- baseStylesDictionary: element.base_styles_dictionary,
1209
- templateKey: element.twig_main_template
1505
+ element
1210
1506
  });
1211
1507
  }
1212
1508
  };
@@ -1214,14 +1510,21 @@ function createTemplatedElementType({ type, renderer, element }) {
1214
1510
  function canBeTemplated(element) {
1215
1511
  return !!(element.atomic_props_schema && element.twig_templates && element.twig_main_template && element.base_styles_dictionary);
1216
1512
  }
1217
- function createTemplatedElementViewClassDeclaration({
1513
+ function createTemplatedElementView({
1218
1514
  type,
1219
1515
  renderer,
1220
- propsResolver: resolveProps,
1221
- templateKey,
1222
- baseStylesDictionary
1516
+ element
1223
1517
  }) {
1224
1518
  const BaseView = createElementViewClassDeclaration();
1519
+ const templateKey = element.twig_main_template;
1520
+ const baseStylesDictionary = element.base_styles_dictionary;
1521
+ Object.entries(element.twig_templates).forEach(([key, template]) => {
1522
+ renderer.register(key, template);
1523
+ });
1524
+ const resolveProps = createPropsResolver({
1525
+ transformers: settingsTransformersRegistry,
1526
+ schema: element.atomic_props_schema
1527
+ });
1225
1528
  return class extends BaseView {
1226
1529
  #abortController = null;
1227
1530
  getTemplateType() {
@@ -1230,67 +1533,915 @@ function createTemplatedElementViewClassDeclaration({
1230
1533
  renderOnChange() {
1231
1534
  this.render();
1232
1535
  }
1233
- // Overriding Marionette original render method to inject our renderer.
1234
- async _renderTemplate() {
1235
- this.#beforeRenderTemplate();
1536
+ // Override `render` function to support async `_renderTemplate`
1537
+ // Note that `_renderChildren` asynchronity is still NOT supported, so only the parent element rendering can be async
1538
+ render() {
1236
1539
  this.#abortController?.abort();
1237
1540
  this.#abortController = new AbortController();
1238
- const process = signalizedProcess(this.#abortController.signal).then((_, signal) => {
1541
+ const process = signalizedProcess(this.#abortController.signal).then(() => this.#beforeRender()).then(() => this._renderTemplate()).then(() => {
1542
+ this._renderChildren();
1543
+ this.#afterRender();
1544
+ });
1545
+ return process.execute();
1546
+ }
1547
+ // Overriding Marionette original `_renderTemplate` method to inject our renderer.
1548
+ async _renderTemplate() {
1549
+ this.triggerMethod("before:render:template");
1550
+ const process = signalizedProcess(this.#abortController?.signal).then((_, signal) => {
1239
1551
  const settings = this.model.get("settings").toJSON();
1240
1552
  return resolveProps({
1241
1553
  props: settings,
1242
1554
  signal
1243
1555
  });
1244
- }).then((resolvedSettings) => {
1556
+ }).then((settings) => {
1557
+ return this.afterSettingsResolve(settings);
1558
+ }).then(async (settings) => {
1245
1559
  const context = {
1246
1560
  id: this.model.get("id"),
1247
1561
  type,
1248
- settings: resolvedSettings,
1562
+ settings,
1249
1563
  base_styles: baseStylesDictionary
1250
1564
  };
1251
1565
  return renderer.render(templateKey, context);
1252
1566
  }).then((html) => this.$el.html(html));
1253
1567
  await process.execute();
1254
- this.#afterRenderTemplate();
1255
- }
1256
- // Emulating the original Marionette behavior.
1257
- #beforeRenderTemplate() {
1258
- this.triggerMethod("before:render:template");
1259
- }
1260
- #afterRenderTemplate() {
1261
1568
  this.bindUIElements();
1262
1569
  this.triggerMethod("render:template");
1263
1570
  }
1571
+ afterSettingsResolve(settings) {
1572
+ return settings;
1573
+ }
1574
+ #beforeRender() {
1575
+ this._ensureViewIsIntact();
1576
+ this._isRendering = true;
1577
+ this.resetChildViewContainer();
1578
+ this.triggerMethod("before:render", this);
1579
+ }
1580
+ #afterRender() {
1581
+ this._isRendering = false;
1582
+ this.isRendered = true;
1583
+ this.triggerMethod("render", this);
1584
+ }
1264
1585
  };
1265
1586
  }
1266
1587
 
1267
1588
  // src/legacy/init-legacy-views.ts
1589
+ var elementsLegacyTypes = {};
1590
+ function registerElementType(type, elementTypeGenerator) {
1591
+ elementsLegacyTypes[type] = elementTypeGenerator;
1592
+ }
1268
1593
  function initLegacyViews() {
1269
- (0, import_editor_v1_adapters6.__privateListenTo)((0, import_editor_v1_adapters6.v1ReadyEvent)(), () => {
1270
- const config = (0, import_editor_elements2.getWidgetsCache)() ?? {};
1594
+ (0, import_editor_v1_adapters7.__privateListenTo)((0, import_editor_v1_adapters7.v1ReadyEvent)(), () => {
1595
+ const config = (0, import_editor_elements4.getWidgetsCache)() ?? {};
1271
1596
  const legacyWindow = window;
1272
1597
  const renderer = createDomRenderer();
1273
1598
  Object.entries(config).forEach(([type, element]) => {
1274
1599
  if (!element.atomic) {
1275
1600
  return;
1276
1601
  }
1277
- const ElementType = canBeTemplated(element) ? createTemplatedElementType({ type, renderer, element }) : createElementType(type);
1602
+ let ElementType;
1603
+ if (!!elementsLegacyTypes[type] && canBeTemplated(element)) {
1604
+ ElementType = elementsLegacyTypes[type]({ type, renderer, element });
1605
+ } else if (canBeTemplated(element)) {
1606
+ ElementType = createTemplatedElementType({ type, renderer, element });
1607
+ } else {
1608
+ ElementType = createElementType(type);
1609
+ }
1278
1610
  legacyWindow.elementor.elementsManager.registerElementType(new ElementType());
1279
1611
  });
1280
1612
  });
1281
1613
  }
1282
1614
 
1615
+ // src/mcp/resources/widgets-schema-resource.ts
1616
+ var import_editor_elements5 = require("@elementor/editor-elements");
1617
+ var import_editor_mcp = require("@elementor/editor-mcp");
1618
+ var import_editor_props3 = require("@elementor/editor-props");
1619
+ var import_editor_styles4 = require("@elementor/editor-styles");
1620
+ var WIDGET_SCHEMA_URI = "elementor://widgets/schema/{widgetType}";
1621
+ var STYLE_SCHEMA_URI = "elementor://styles/schema/{category}";
1622
+ var BEST_PRACTICES_URI = "elementor://styles/best-practices";
1623
+ var initWidgetsSchemaResource = (reg) => {
1624
+ const { mcpServer } = reg;
1625
+ mcpServer.resource("styles-best-practices", BEST_PRACTICES_URI, async () => {
1626
+ return {
1627
+ contents: [
1628
+ {
1629
+ uri: BEST_PRACTICES_URI,
1630
+ text: `# Styling best practices
1631
+ Prefer using "em" and "rem" values for text-related sizes, padding and spacing. Use percentages for dynamic sizing relative to parent containers.
1632
+ This flexboxes are by default "flex" with "stretch" alignment. To ensure proper layout, define the "justify-content" and "align-items" as in the schema, or in custom_css, depends on your needs.
1633
+
1634
+ When applicable for styles, use the "custom_css" property for free-form CSS styling. This property accepts a string of CSS rules that will be applied directly to the element.
1635
+ The css string must follow standard CSS syntax, with properties and values separated by semicolons, no selectors, or nesting rules allowed.`
1636
+ }
1637
+ ]
1638
+ };
1639
+ });
1640
+ mcpServer.resource(
1641
+ "styles-schema",
1642
+ new import_editor_mcp.ResourceTemplate(STYLE_SCHEMA_URI, {
1643
+ list: () => {
1644
+ const categories = [...Object.keys((0, import_editor_styles4.getStylesSchema)()), "custom_css"];
1645
+ return {
1646
+ resources: categories.map((category) => ({
1647
+ uri: `elementor://styles/schema/${category}`,
1648
+ name: "Style schema for " + category
1649
+ }))
1650
+ };
1651
+ }
1652
+ }),
1653
+ {
1654
+ description: "Common styles schema for the specified category"
1655
+ },
1656
+ async (uri, variables) => {
1657
+ const category = typeof variables.category === "string" ? variables.category : variables.category?.[0];
1658
+ if (category === "custom_css") {
1659
+ return {
1660
+ contents: [
1661
+ {
1662
+ uri: uri.toString(),
1663
+ text: "Free style inline CSS string of properties and their values. Applicable for a single element, only the properties and values are accepted. Use this as a last resort for properties that are not covered with the schema."
1664
+ }
1665
+ ]
1666
+ };
1667
+ }
1668
+ const stylesSchema = (0, import_editor_styles4.getStylesSchema)()[category];
1669
+ if (!stylesSchema) {
1670
+ throw new Error(`No styles schema found for category: ${category}`);
1671
+ }
1672
+ const cleanedupPropSchema = cleanupPropType(stylesSchema);
1673
+ const asJson = import_editor_props3.Schema.propTypeToJsonSchema(cleanedupPropSchema);
1674
+ return {
1675
+ contents: [
1676
+ {
1677
+ uri: uri.toString(),
1678
+ text: JSON.stringify(asJson)
1679
+ }
1680
+ ]
1681
+ };
1682
+ }
1683
+ );
1684
+ mcpServer.resource(
1685
+ "widget-schema-by-type",
1686
+ new import_editor_mcp.ResourceTemplate(WIDGET_SCHEMA_URI, {
1687
+ list: () => {
1688
+ const cache = (0, import_editor_elements5.getWidgetsCache)() || {};
1689
+ const availableWidgets = Object.keys(cache || {}).filter(
1690
+ (widgetType) => cache[widgetType]?.atomic_props_schema
1691
+ );
1692
+ return {
1693
+ resources: availableWidgets.map((widgetType) => ({
1694
+ uri: `elementor://widgets/schema/${widgetType}`,
1695
+ name: "Widget schema for " + widgetType
1696
+ }))
1697
+ };
1698
+ }
1699
+ }),
1700
+ {
1701
+ description: "PropType schema for the specified widget type"
1702
+ },
1703
+ async (uri, variables) => {
1704
+ const widgetType = typeof variables.widgetType === "string" ? variables.widgetType : variables.widgetType?.[0];
1705
+ const propSchema = (0, import_editor_elements5.getWidgetsCache)()?.[widgetType]?.atomic_props_schema;
1706
+ if (!propSchema) {
1707
+ throw new Error(`No prop schema found for element type: ${widgetType}`);
1708
+ }
1709
+ const cleanedupPropSchema = cleanupPropSchema(propSchema);
1710
+ const asJson = Object.fromEntries(
1711
+ Object.entries(cleanedupPropSchema).map(([key, propType]) => [
1712
+ key,
1713
+ import_editor_props3.Schema.propTypeToJsonSchema(propType)
1714
+ ])
1715
+ );
1716
+ import_editor_props3.Schema.nonConfigurablePropKeys.forEach((key) => {
1717
+ delete asJson[key];
1718
+ });
1719
+ return {
1720
+ contents: [
1721
+ {
1722
+ uri: uri.toString(),
1723
+ text: JSON.stringify(asJson)
1724
+ }
1725
+ ]
1726
+ };
1727
+ }
1728
+ );
1729
+ };
1730
+ function cleanupPropSchema(propSchema) {
1731
+ const result = {};
1732
+ Object.keys(propSchema).forEach((propName) => {
1733
+ result[propName] = cleanupPropType(propSchema[propName]);
1734
+ });
1735
+ return result;
1736
+ }
1737
+ function cleanupPropType(propType) {
1738
+ const result = {};
1739
+ Object.keys(propType).forEach((property) => {
1740
+ switch (property) {
1741
+ case "key":
1742
+ case "kind":
1743
+ result[property] = propType[property];
1744
+ break;
1745
+ case "meta":
1746
+ case "settings":
1747
+ {
1748
+ if (Object.keys(propType[property] || {}).length > 0) {
1749
+ result[property] = propType[property];
1750
+ }
1751
+ }
1752
+ break;
1753
+ }
1754
+ });
1755
+ if (result.kind === "plain") {
1756
+ Object.defineProperty(result, "kind", { value: "string" });
1757
+ } else if (result.kind === "array") {
1758
+ result.item_prop_type = cleanupPropType(propType.item_prop_type);
1759
+ } else if (result.kind === "object") {
1760
+ const shape = propType.shape;
1761
+ const cleanedShape = cleanupPropSchema(shape);
1762
+ result.shape = cleanedShape;
1763
+ } else if (result.kind === "union") {
1764
+ const propTypes = propType.prop_types;
1765
+ const cleanedPropTypes = {};
1766
+ Object.keys(propTypes).forEach((key) => {
1767
+ cleanedPropTypes[key] = cleanupPropType(propTypes[key]);
1768
+ });
1769
+ result.prop_types = cleanedPropTypes;
1770
+ }
1771
+ return result;
1772
+ }
1773
+
1774
+ // src/mcp/tools/build-composition/tool.ts
1775
+ var import_editor_elements7 = require("@elementor/editor-elements");
1776
+
1777
+ // src/mcp/utils/do-update-element-property.ts
1778
+ var import_editor_elements6 = require("@elementor/editor-elements");
1779
+ var import_editor_props4 = require("@elementor/editor-props");
1780
+ var import_editor_styles5 = require("@elementor/editor-styles");
1781
+ function resolvePropValue(value, forceKey) {
1782
+ return import_editor_props4.Schema.adjustLlmPropValueSchema(value, forceKey);
1783
+ }
1784
+ var doUpdateElementProperty = (params) => {
1785
+ const { elementId, propertyName, propertyValue, elementType } = params;
1786
+ if (propertyName === "_styles") {
1787
+ const elementStyles = (0, import_editor_elements6.getElementStyles)(elementId) || {};
1788
+ const propertyMapValue = propertyValue;
1789
+ const styleSchema = (0, import_editor_styles5.getStylesSchema)();
1790
+ const transformedStyleValues = Object.fromEntries(
1791
+ Object.entries(propertyMapValue).map(([key, val]) => {
1792
+ if (key === "custom_css") {
1793
+ return [key, val];
1794
+ }
1795
+ const { key: propKey, kind } = styleSchema?.[key] || {};
1796
+ if (!propKey && kind !== "union") {
1797
+ throw new Error(`_styles property ${key} is not supported.`);
1798
+ }
1799
+ return [key, resolvePropValue(val, propKey)];
1800
+ })
1801
+ );
1802
+ let customCss;
1803
+ Object.keys(propertyMapValue).forEach((stylePropName) => {
1804
+ const propertyRawSchema = styleSchema[stylePropName];
1805
+ if (stylePropName === "custom_css") {
1806
+ let customCssValue = propertyMapValue[stylePropName];
1807
+ if (typeof customCssValue === "object") {
1808
+ customCssValue = import_editor_props4.stringPropTypeUtil.extract(customCssValue) || customCssValue?.value || "";
1809
+ }
1810
+ customCss = {
1811
+ raw: btoa(customCssValue)
1812
+ };
1813
+ return;
1814
+ }
1815
+ const isSupported = !!propertyRawSchema;
1816
+ if (!isSupported) {
1817
+ throw new Error(`_styles property ${stylePropName} is not supported.`);
1818
+ }
1819
+ if (propertyRawSchema.kind === "plain") {
1820
+ if (typeof propertyMapValue[stylePropName] !== "object") {
1821
+ const propUtil = (0, import_editor_props4.getPropSchemaFromCache)(propertyRawSchema.key);
1822
+ if (propUtil) {
1823
+ const plainValue = propUtil.create(propertyMapValue[stylePropName]);
1824
+ propertyMapValue[stylePropName] = plainValue;
1825
+ }
1826
+ }
1827
+ }
1828
+ });
1829
+ const localStyle = Object.values(elementStyles).find((style) => style.label === "local");
1830
+ if (!localStyle) {
1831
+ (0, import_editor_elements6.createElementStyle)({
1832
+ elementId,
1833
+ ...typeof customCss !== "undefined" ? { custom_css: customCss } : {},
1834
+ classesProp: "classes",
1835
+ label: "local",
1836
+ meta: {
1837
+ breakpoint: "desktop",
1838
+ state: null
1839
+ },
1840
+ props: {
1841
+ ...transformedStyleValues
1842
+ }
1843
+ });
1844
+ } else {
1845
+ (0, import_editor_elements6.updateElementStyle)({
1846
+ elementId,
1847
+ styleId: localStyle.id,
1848
+ meta: {
1849
+ breakpoint: "desktop",
1850
+ state: null
1851
+ },
1852
+ ...typeof customCss !== "undefined" ? { custom_css: customCss } : {},
1853
+ props: {
1854
+ ...transformedStyleValues
1855
+ }
1856
+ });
1857
+ }
1858
+ return;
1859
+ }
1860
+ const elementPropSchema = (0, import_editor_elements6.getWidgetsCache)()?.[elementType]?.atomic_props_schema;
1861
+ if (!elementPropSchema) {
1862
+ throw new Error(`No prop schema found for element type: ${elementType}`);
1863
+ }
1864
+ if (!elementPropSchema[propertyName]) {
1865
+ const propertyNames = Object.keys(elementPropSchema);
1866
+ throw new Error(
1867
+ `Property "${propertyName}" does not exist on element type "${elementType}". Available properties are: ${propertyNames.join(
1868
+ ", "
1869
+ )}`
1870
+ );
1871
+ }
1872
+ const value = resolvePropValue(propertyValue);
1873
+ (0, import_editor_elements6.updateElementSettings)({
1874
+ id: elementId,
1875
+ props: {
1876
+ [propertyName]: value
1877
+ },
1878
+ withHistory: false
1879
+ });
1880
+ };
1881
+
1882
+ // src/mcp/tools/build-composition/prompt.ts
1883
+ var import_editor_mcp2 = require("@elementor/editor-mcp");
1884
+ var generatePrompt = () => {
1885
+ const buildCompositionsToolPrompt = (0, import_editor_mcp2.toolPrompts)("build-compositions");
1886
+ buildCompositionsToolPrompt.description(`
1887
+ Build entire elementor widget comositions representing complex structures of nested elements.
1888
+
1889
+ # When to use this tool
1890
+ Always prefer this tool when the user requires to build a composition of elements, such as cards, heros, or inspired from other pages or HTML compositions.
1891
+ Prefer this tool over any other tool for building HTML structure, unless you are specified to use a different tool.
1892
+
1893
+ # **CRITICAL - REQUIRED RESOURCES (Must read before using this tool)**
1894
+ 1. [${WIDGET_SCHEMA_URI}]
1895
+ Required to understand which widgets are available, and what are their configuration schemas.
1896
+ Every widgetType (i.e. e-heading, e-button) that is supported has it's own property schema, that you must follow in order to apply property values correctly.
1897
+ 2. [${STYLE_SCHEMA_URI}]
1898
+ Required to understand the styles schema for the widgets. All widgets share the same styles schema.
1899
+ 3. List of allowed custom tags for building the structure is derived from the list of widgets schema resources.
1900
+
1901
+ # Instructions
1902
+ 1. Understand the user requirements carefully.
1903
+ 2. Build a valid XML structure using only the allowed custom tags provided. For example, if you
1904
+ use the "e-button" element, it would be represented as <e-button></e-button> in the XML structure.
1905
+ 3. Plan the configuration for each element according to the user requirements, using the configuration schema provided for each custom tag.
1906
+ Every widget type has it's own configuration schema, retreivable from the resource [${WIDGET_SCHEMA_URI}].
1907
+ PropValues must follow the exact PropType schema provided in the resource.
1908
+ 4. For every element, provide a "configuration-id" attribute. For example:
1909
+ \`<e-flexbox configuration-id="flex1"><e-heading configuration-id="heading2"></e-heading></e-flexbox>\`
1910
+ In the elementConfig property, provide the actual configuration object for each configuration-id used in the XML structure.
1911
+ In the stylesConfig property, provide the actual styles configuration object for each configuration-id used in the XML structure.
1912
+ 5. Ensure the XML structure is valid and parsable.
1913
+ 6. Do not add any attribute nodes, classes, id's, and no text nodes allowed.
1914
+ Layout properties, such as margin, padding, align, etc. must be applied using the [${STYLE_SCHEMA_URI}] PropValues.
1915
+ 7. Some elements allow nesting of other elements, and most of the DO NOT. The allowed elements that can have nested children are "e-div-block" and "e-flexbox".
1916
+ 8. Make sure that non-container elements do NOT have any nested elements.
1917
+ 9. Unsless the user specifically requires structure only, BE EXPRESSIVE AND VISUALLY CREATIVE AS POSSIBLE IN APPLYING STYLE CONFIGURATION.
1918
+ In the case of doubt, prefer adding more styles to make the composition visually appealing.
1919
+
1920
+ # Additional Guidelines
1921
+ - Most users expect the structure to be well designed and visually appealing.
1922
+ - Use layout properties, ensure "white space" design approach is followed, and make sure the composition is visually balanced.
1923
+ - Use appropriate spacing, alignment, and sizing to create a harmonious layout.
1924
+ - Consider the visual hierarchy of elements to guide the user's attention effectively.
1925
+ - You are encouraged to use colors, typography, and other style properties to enhance the visual appeal, as long as they are part of the configuration schema for the elements used.
1926
+ - Always aim for a clean and professional look that aligns with modern design principles.
1927
+ - When you are required to create placeholder texts, use texts that have a length that fits the goal. When long texts are required, use longer placeholder texts. When the user specifies exact texts, use the exact texts.
1928
+ - Image size does not affect the actual size on the screen, only which quality to use. If you use images, specifically add _styles PropValues to define the image sizes.
1929
+ - Attempt to use layout, margin, padding, size properties from the styles schema.
1930
+ - If your elements library is limited, encourage use of nesting containers to achieve complex layouts.
1931
+
1932
+ # CONSTRAINTS
1933
+ When a tool execution fails, retry up to 10 more times, read the error message carefully, and adjust the XML structure or the configurations accordingly.
1934
+ If a "$$type" is missing, update the invalid object, if the XML has parsing errors, fix it, etc. and RETRY.
1935
+ VALIDATE the XML structure before delivering it as the final result.
1936
+ VALIDATE the JSON structure used in the "configuration" attributes for each element before delivering the final result. The configuration must MATCH the PropValue schemas.
1937
+ NO LINKS ALLOWED. Never apply links to elements, even if they appear in the PropType schema.
1938
+ elementConfig values must align with the widget's PropType schema, available at the resource [${WIDGET_SCHEMA_URI}].
1939
+ stylesConfig values must align with the common styles PropType schema, available at the resource [${STYLE_SCHEMA_URI}].
1940
+
1941
+ # Parameters
1942
+ All parameters are MANDATORY.
1943
+ - xmlStructure
1944
+ - elementConfig
1945
+ - stylesConfig
1946
+
1947
+ If unsure about the configuration of a specific property, read the schema resources carefully.
1948
+
1949
+
1950
+ `);
1951
+ buildCompositionsToolPrompt.example(`
1952
+ A Heading and a button inside a flexbox
1953
+ {
1954
+ xmlStructure: "<e-flexbox configuration-id="flex1"><e-heading configuration-id="heading1"></e-heading><e-button configuration-id="button1"></e-button></e-flexbox>"
1955
+ elementConfig: {
1956
+ "flex1": {
1957
+ "tag": {
1958
+ "$$type": "string",
1959
+ "value": "section"
1960
+ },
1961
+ },
1962
+ stylesConfig: {
1963
+ "heading1": {
1964
+ "font-size": {
1965
+ "$$type": "size",
1966
+ "value": {
1967
+ "size": { "$$type": "number", "value": 24 },
1968
+ "unit": { "$$type": "string", "value": "px" }
1969
+ }
1970
+ },
1971
+ "color": {
1972
+ "$$type": "color",
1973
+ "value": { "$$type": "string", "value": "#333" }
1974
+ }
1975
+ }
1976
+ },
1977
+ }
1978
+ `);
1979
+ buildCompositionsToolPrompt.parameter(
1980
+ "xmlStructure",
1981
+ `**MANDATORY** A valid XML structure representing the composition to be built, using custom elementor tags, styling and configuration PropValues.`
1982
+ );
1983
+ buildCompositionsToolPrompt.parameter(
1984
+ "elementConfig",
1985
+ `**MANDATORY** A record mapping configuration IDs to their corresponding configuration objects, defining the PropValues for each element created.`
1986
+ );
1987
+ buildCompositionsToolPrompt.parameter(
1988
+ "stylesConfig",
1989
+ `**MANDATORY** A record mapping style PropTypes to their corresponding style configuration objects, defining the PropValues for styles to be applied to elements.`
1990
+ );
1991
+ buildCompositionsToolPrompt.instruction(
1992
+ `You will be provided the XML structure with element IDs. These IDs represent the actual elementor widgets created on the page/post.
1993
+ You should use these IDs as reference for further configuration, styling or changing elements later on.`
1994
+ );
1995
+ buildCompositionsToolPrompt.instruction(
1996
+ `You must use styles/variables/classes that are available in the project resources, you should prefer using them over inline styles, and you are welcome to execute relevant tools AFTER this tool execution, to apply global classes to the created elements.`
1997
+ );
1998
+ return buildCompositionsToolPrompt.prompt();
1999
+ };
2000
+
2001
+ // src/mcp/tools/build-composition/schema.ts
2002
+ var import_schema = require("@elementor/schema");
2003
+ var inputSchema = {
2004
+ xmlStructure: import_schema.z.string().describe("The XML structure representing the composition to be built"),
2005
+ elementConfig: import_schema.z.record(
2006
+ import_schema.z.string().describe("The configuration id"),
2007
+ import_schema.z.record(import_schema.z.string().describe("property name"), import_schema.z.any().describe("The PropValue for the property"))
2008
+ ).describe("A record mapping element IDs to their configuration objects. REQUIRED"),
2009
+ stylesConfig: import_schema.z.record(
2010
+ import_schema.z.string().describe("The configuration id"),
2011
+ import_schema.z.record(
2012
+ import_schema.z.string().describe("_styles property name"),
2013
+ import_schema.z.any().describe("The PropValue for the style property. MANDATORY")
2014
+ )
2015
+ ).describe(
2016
+ `A record mapping element IDs to their styles configuration objects. Use the actual styles schema from [${STYLE_SCHEMA_URI}].`
2017
+ ).default({})
2018
+ };
2019
+ var outputSchema = {
2020
+ errors: import_schema.z.string().describe("Error message if the composition building failed").optional(),
2021
+ xmlStructure: import_schema.z.string().describe("The built XML structure as a string").optional(),
2022
+ llmInstructions: import_schema.z.string().describe("Instructions used to further actions for you").optional()
2023
+ };
2024
+
2025
+ // src/mcp/tools/build-composition/tool.ts
2026
+ var initBuildCompositionsTool = (reg) => {
2027
+ const { addTool } = reg;
2028
+ addTool({
2029
+ name: "build-compositions",
2030
+ description: generatePrompt(),
2031
+ schema: inputSchema,
2032
+ outputSchema,
2033
+ handler: async (params) => {
2034
+ let xml = null;
2035
+ const { xmlStructure, elementConfig, stylesConfig } = params;
2036
+ const errors = [];
2037
+ const softErrors = [];
2038
+ const rootContainers = [];
2039
+ const widgetsCache = (0, import_editor_elements7.getWidgetsCache)() || {};
2040
+ const documentContainer = (0, import_editor_elements7.getContainer)("document");
2041
+ try {
2042
+ const parser = new DOMParser();
2043
+ xml = parser.parseFromString(xmlStructure, "application/xml");
2044
+ const errorNode = xml.querySelector("parsererror");
2045
+ if (errorNode) {
2046
+ throw new Error("Failed to parse XML structure: " + errorNode.textContent);
2047
+ }
2048
+ const children = Array.from(xml.children);
2049
+ const iterate = (node, containerElement = documentContainer) => {
2050
+ const elementTag = node.tagName;
2051
+ if (!widgetsCache[elementTag]) {
2052
+ errors.push(new Error(`Unknown widget type: ${elementTag}`));
2053
+ }
2054
+ const isContainer = elementTag === "e-flexbox" || elementTag === "e-div-block";
2055
+ const newElement = isContainer ? (0, import_editor_elements7.createElement)({
2056
+ containerId: containerElement.id,
2057
+ model: {
2058
+ elType: elementTag,
2059
+ id: (0, import_editor_elements7.generateElementId)()
2060
+ },
2061
+ options: { useHistory: false }
2062
+ }) : (0, import_editor_elements7.createElement)({
2063
+ containerId: containerElement.id,
2064
+ model: {
2065
+ elType: "widget",
2066
+ widgetType: elementTag,
2067
+ id: (0, import_editor_elements7.generateElementId)()
2068
+ },
2069
+ options: { useHistory: false }
2070
+ });
2071
+ if (containerElement === documentContainer) {
2072
+ rootContainers.push(newElement);
2073
+ }
2074
+ node.setAttribute("id", newElement.id);
2075
+ const configId = node.getAttribute("configuration-id") || "";
2076
+ try {
2077
+ const configObject = elementConfig[configId] || {};
2078
+ const styleObject = stylesConfig[configId] || {};
2079
+ configObject._styles = styleObject;
2080
+ for (const [propertyName, propertyValue] of Object.entries(configObject)) {
2081
+ const widgetSchema = widgetsCache[elementTag];
2082
+ if (!widgetSchema?.atomic_props_schema?.[propertyName] && propertyName !== "_styles" && propertyName !== "custom_css") {
2083
+ softErrors.push(
2084
+ new Error(
2085
+ `Property "${propertyName}" does not exist on element type "${elementTag}".`
2086
+ )
2087
+ );
2088
+ continue;
2089
+ }
2090
+ try {
2091
+ doUpdateElementProperty({
2092
+ elementId: newElement.id,
2093
+ propertyName,
2094
+ propertyValue: propertyName === "custom_css" ? { _styles: propertyValue } : propertyValue,
2095
+ elementType: elementTag
2096
+ });
2097
+ } catch (error) {
2098
+ softErrors.push(error);
2099
+ }
2100
+ }
2101
+ if (isContainer) {
2102
+ for (const child of node.children) {
2103
+ iterate(child, newElement);
2104
+ }
2105
+ } else {
2106
+ node.innerHTML = "";
2107
+ node.removeAttribute("configuration");
2108
+ }
2109
+ } finally {
2110
+ }
2111
+ };
2112
+ for (const childNode of children) {
2113
+ iterate(childNode, documentContainer);
2114
+ try {
2115
+ } catch (error) {
2116
+ errors.push(error);
2117
+ }
2118
+ }
2119
+ } catch (error) {
2120
+ errors.push(error);
2121
+ }
2122
+ if (errors.length) {
2123
+ rootContainers.forEach((rootContainer) => {
2124
+ (0, import_editor_elements7.deleteElement)({
2125
+ elementId: rootContainer.id,
2126
+ options: { useHistory: false }
2127
+ });
2128
+ });
2129
+ }
2130
+ if (errors.length > 0) {
2131
+ const errorText = `Failed to build composition with the following errors:
2132
+
2133
+
2134
+ ${errors.map((e) => typeof e === "string" ? e : e.message).join("\n\n")}
2135
+ "Missing $$type" errors indicate that the configuration objects are invalid. Try again and apply **ALL** object entries with correct $$type.
2136
+ Now that you have these errors, fix them and try again. Errors regarding configuration objects, please check again the PropType schemas`;
2137
+ throw new Error(errorText);
2138
+ }
2139
+ if (!xml) {
2140
+ throw new Error("XML structure is null after parsing.");
2141
+ }
2142
+ return {
2143
+ xmlStructure: new XMLSerializer().serializeToString(xml),
2144
+ llmInstructions: (softErrors.length ? `The composition was built successfully, but there were some issues with the provided configurations:
2145
+
2146
+ ${softErrors.map((e) => `- ${e.message}`).join("\n")}
2147
+
2148
+ Please use confiugure-element tool to fix these issues. Now that you have information about these issues, use the configure-element tool to fix them!` : "") + `
2149
+ Next Steps:
2150
+ - Use "apply-global-class" tool as there may be global styles ready to be applied to elements.
2151
+ - Use "configure-element" tool to further configure elements as needed, including styles.
2152
+ `
2153
+ };
2154
+ }
2155
+ });
2156
+ };
2157
+
2158
+ // src/mcp/tools/configure-element/prompt.ts
2159
+ var configureElementToolPrompt = `Configure an existing element on the page.
2160
+
2161
+ # **CRITICAL - REQUIRED INFORMATION (Must read before using this tool)**
2162
+ 1. [${WIDGET_SCHEMA_URI}]
2163
+ Required to understand which widgets are available, and what are their configuration schemas.
2164
+ Every widgetType (i.e. e-heading, e-button) that is supported has it's own property schema, that you must follow in order to apply property values correctly.
2165
+ 2. [${STYLE_SCHEMA_URI}]
2166
+ Required to understand the styles schema for the widgets. All widgets share the same styles schema, grouped by categories.
2167
+ Use this resource to understand which style properties are available for each element, and how to structure the "_styles" configuration property.
2168
+ 3. If not sure about the PropValues schema, you can use the "get-element-configuration-values" tool to retreive the current PropValues configuration of the element.
2169
+
2170
+ Before using this tool, check the definitions of the elements PropTypes at the resource "widget-schema-by-type" at editor-canvas__elementor://widgets/schema/{widgetType}
2171
+ All widgets share a common _style property for styling, which uses the common styles schema.
2172
+ Retreive and check the common styles schema at the resource list "styles-schema" at editor-canvas__elementor://styles/schema/{category}
2173
+
2174
+ # Parameters
2175
+ - propertiesToChange: An object containing the properties to change, with their new values. MANDATORY
2176
+ - elementId: The ID of the element to configure. MANDATORY
2177
+ - elementType: The type of the element to configure (i.e. e-heading, e-button). MANDATORY
2178
+
2179
+ # When to use this tool
2180
+ When a user requires to change anything in an element, such as updating text, colors, sizes, or other configurable properties.
2181
+ This tool handles elements of type "widget".
2182
+ This tool handles styling elements, using the _styles property in the configuration.
2183
+
2184
+ The element's schema must be known before using this tool.
2185
+
2186
+ Attached resource link describing how PropType schema should be parsed as PropValue for this tool.
2187
+
2188
+ Read carefully the PropType Schema of the element and it's styles, then apply correct PropValue according to the schema.
2189
+
2190
+ PropValue structure:
2191
+ {
2192
+ "$$type": string, // MANDATORY as defined in the PropType schema under the "key" property
2193
+ value: unknown // The value according to the PropType schema for kinds of "array", use array with PropValues items inside. For "object", read the shape property of the PropType schema. For "plain", use strings.
2194
+ }
2195
+
2196
+ <IMPORTANT>
2197
+ ALWAYS MAKE SURE you have the PropType schemas for the element you are configuring, and the common-styles schema for styling. If you are not sure, retreive the schema from the resources mentioned above.
2198
+ </IMPORTANT>
2199
+
2200
+ You can use multiple property changes at once by providing multiple entries in the propertiesToChange object, including _style alongside non-style props.
2201
+ Some properties are nested, use the root property name, then objects with nested values inside, as the complete schema suggests.
2202
+ Nested properties, such as for the _styles, should include a "_styles" property with object containing the definitions to change.
2203
+
2204
+ Make sure you have the "widget-schema-by-type" resource available to retreive the PropType schema for the element type you are configuring.
2205
+
2206
+ # How to configure elements
2207
+ We use a dedicated PropType Schema for configuring elements, including styles. When you configure an element, you must use the EXACT PropType Value as defined in the schema.
2208
+ For _styles, use the style schema provided, as it also uses the PropType format.
2209
+ For all non-primitive types, provide the key property as defined in the schema as $$type in the generated objecct, as it is MANDATORY for parsing.
2210
+
2211
+ Use the EXACT "PROP-TYPE" Schema given, and ALWAYS include the "key" property from the original configuration for every property you are changing.
2212
+
2213
+ # Example
2214
+ \`\`\`json
2215
+ {
2216
+ propertiesToChange: {
2217
+ // List of properties TO CHANGE, following the PropType schema for the element as defined in the resource [${WIDGET_SCHEMA_URI}]
2218
+ title: {
2219
+ $$type: 'string',
2220
+ value: 'New Title Text'
2221
+ },
2222
+ border: {
2223
+ $$type: 'boolean',
2224
+ value: false
2225
+ },
2226
+ _styles: {
2227
+ // List of available keys available at the [${STYLE_SCHEMA_URI}] dynamic resource
2228
+ 'line-height': {
2229
+ $$type: 'size', // MANDATORY do not forget to include the correct $$type for every property
2230
+ value: {
2231
+ size: {
2232
+ $$type: 'number',
2233
+ value: 20
2234
+ },
2235
+ unit: {
2236
+ $$type: 'string',
2237
+ value: 'px'
2238
+ }
2239
+ }
2240
+ }
2241
+ }
2242
+ }
2243
+ };
2244
+ \`\`\`
2245
+
2246
+ <IMPORTANT>
2247
+ The $$type property is MANDATORY for every value, it is required to parse the value and apply application-level effects.
2248
+ </IMPORTANT>
2249
+ `;
2250
+
2251
+ // src/mcp/tools/configure-element/schema.ts
2252
+ var import_schema3 = require("@elementor/schema");
2253
+ var inputSchema2 = {
2254
+ propertiesToChange: import_schema3.z.record(
2255
+ import_schema3.z.string().describe(
2256
+ "The property name. If nested property, provide the root property name, and the object delta only."
2257
+ ),
2258
+ import_schema3.z.any().describe("The property's value")
2259
+ ).describe("An object record containing property names and their new values to be set on the element").optional(),
2260
+ elementType: import_schema3.z.string().describe("The type of the element to retreive the schema"),
2261
+ elementId: import_schema3.z.string().describe("The unique id of the element to configure")
2262
+ };
2263
+ var outputSchema2 = {
2264
+ success: import_schema3.z.boolean().describe(
2265
+ "Whether the configuration change was successful, only if propertyName and propertyValue are provided"
2266
+ )
2267
+ };
2268
+
2269
+ // src/mcp/tools/configure-element/tool.ts
2270
+ var initConfigureElementTool = (reg) => {
2271
+ const { addTool } = reg;
2272
+ addTool({
2273
+ name: "configure-element",
2274
+ description: configureElementToolPrompt,
2275
+ schema: inputSchema2,
2276
+ outputSchema: outputSchema2,
2277
+ handler: ({ elementId, propertiesToChange, elementType }) => {
2278
+ if (!propertiesToChange) {
2279
+ throw new Error(
2280
+ "propertiesToChange is required to configure an element. Now that you have this information, ensure you have the schema and try again."
2281
+ );
2282
+ }
2283
+ const toUpdate = Object.entries(propertiesToChange);
2284
+ for (const [propertyName, propertyValue] of toUpdate) {
2285
+ if (!propertyName && !elementId && !elementType) {
2286
+ throw new Error(
2287
+ "propertyName, elementId, elementType are required to configure an element. If you want to retreive the schema, use the get-element-configuration-schema tool."
2288
+ );
2289
+ }
2290
+ try {
2291
+ doUpdateElementProperty({
2292
+ elementId,
2293
+ elementType,
2294
+ propertyName,
2295
+ propertyValue
2296
+ });
2297
+ } catch (error) {
2298
+ const errorMessage = createUpdateErrorMessage({
2299
+ propertyName,
2300
+ elementId,
2301
+ elementType,
2302
+ error
2303
+ });
2304
+ throw new Error(errorMessage);
2305
+ }
2306
+ }
2307
+ return {
2308
+ success: true
2309
+ };
2310
+ }
2311
+ });
2312
+ };
2313
+ function createUpdateErrorMessage(opts) {
2314
+ const { propertyName, elementId, elementType, error } = opts;
2315
+ return `Failed to update property "${propertyName}" on element "${elementId}": ${error.message}.
2316
+ Check the element's PropType schema at the resource [${WIDGET_SCHEMA_URI.replace(
2317
+ "{widgetType}",
2318
+ elementType
2319
+ )}] for type "${elementType}" to ensure the property exists and the value matches the expected PropType.
2320
+ Now that you have this information, ensure you have the schema and try again.`;
2321
+ }
2322
+
2323
+ // src/mcp/tools/get-element-config/tool.ts
2324
+ var import_editor_elements8 = require("@elementor/editor-elements");
2325
+ var import_editor_props5 = require("@elementor/editor-props");
2326
+ var import_schema5 = require("@elementor/schema");
2327
+ var schema = {
2328
+ elementId: import_schema5.z.string()
2329
+ };
2330
+ var outputSchema3 = {
2331
+ propValues: import_schema5.z.record(import_schema5.z.string(), import_schema5.z.any()).describe(
2332
+ "A record mapping PropTypes to their corresponding PropValues, with _styles record for style-related PropValues"
2333
+ )
2334
+ };
2335
+ var initGetElementConfigTool = (reg) => {
2336
+ const { addTool } = reg;
2337
+ addTool({
2338
+ name: "get-element-configuration-values",
2339
+ description: "Retrieve the element's configuration PropValues for a specific element by unique ID.",
2340
+ schema,
2341
+ outputSchema: outputSchema3,
2342
+ handler: async ({ elementId }) => {
2343
+ const element = (0, import_editor_elements8.getContainer)(elementId);
2344
+ if (!element) {
2345
+ throw new Error(`Element with ID ${elementId} not found.`);
2346
+ }
2347
+ const elementRawSettings = element.settings;
2348
+ const propSchema = (0, import_editor_elements8.getWidgetsCache)()?.[element.model.get("widgetType") || ""]?.atomic_props_schema;
2349
+ if (!elementRawSettings || !propSchema) {
2350
+ throw new Error(`No settings or prop schema found for element ID: ${elementId}`);
2351
+ }
2352
+ const propValues = {};
2353
+ const stylePropValues = {};
2354
+ import_editor_props5.Schema.configurableKeys(propSchema).forEach((key) => {
2355
+ propValues[key] = structuredClone(elementRawSettings.get(key));
2356
+ });
2357
+ const elementStyles = (0, import_editor_elements8.getElementStyles)(elementId) || {};
2358
+ const localStyle = Object.values(elementStyles).find((style) => style.label === "local");
2359
+ if (localStyle) {
2360
+ const defaultVariant = localStyle.variants.find(
2361
+ (variant) => variant.meta.breakpoint === "desktop" && !variant.meta.state
2362
+ );
2363
+ if (defaultVariant) {
2364
+ const styleProps = defaultVariant.props || {};
2365
+ Object.keys(styleProps).forEach((stylePropName) => {
2366
+ if (typeof styleProps[stylePropName] !== "undefined") {
2367
+ stylePropValues[stylePropName] = structuredClone(styleProps[stylePropName]);
2368
+ }
2369
+ });
2370
+ }
2371
+ }
2372
+ return {
2373
+ propValues: {
2374
+ ...propValues,
2375
+ _styles: stylePropValues
2376
+ }
2377
+ };
2378
+ }
2379
+ });
2380
+ };
2381
+
2382
+ // src/mcp/canvas-mcp.ts
2383
+ var initCanvasMcp = (reg) => {
2384
+ const { setMCPDescription } = reg;
2385
+ setMCPDescription(
2386
+ 'Everything related to creative design, layout, styling and building the pages, specifically element of type "widget"'
2387
+ );
2388
+ initWidgetsSchemaResource(reg);
2389
+ initBuildCompositionsTool(reg);
2390
+ initGetElementConfigTool(reg);
2391
+ initConfigureElementTool(reg);
2392
+ };
2393
+
2394
+ // src/mcp/mcp-description.ts
2395
+ var mcpDescription = `Canvas MCP - Working with widgets and styles: how to use the PropType schemas and generate PropValue structures
2396
+
2397
+ # Elementor's PropValue configuration system
2398
+
2399
+ Every widget in Elementor has a set of properties that can be configured, defined in a STRICT SCHEMA we call "PropType".
2400
+ All widget configuration values are represented using a structure we call "PropValue".
2401
+
2402
+ To correctly configure a widget's properties, FOLLOW THE PropType schema defined for that widget. This schema outlines the expected structure and types for each property, ensuring that the values you provide are valid and can be properly interpreted by Elementor.
2403
+ Every widget has it's own PropType schema, retreivable from the resource [${WIDGET_SCHEMA_URI}].
2404
+ ALL WIDGETS share a common _styles property with a uniform styles schema, retreivable from the resource [${STYLE_SCHEMA_URI}].
2405
+ The style schema is grouped by categories, such as "typography", "background", "border", etc.
2406
+
2407
+ # Tools and usage
2408
+ - Use the "get-element-configuration-values" tool to retrieve the current configuration of a specific element, including its PropValues and styles. It is recommended to use this tool when you are required to make changes to an existing element, to ensure you have the correct current configuration schema.
2409
+ If a PropValue changes it's type (only on union PropTypes), read the new schema from the resources mentioned above, and adjust the PropValue structure accordingly.
2410
+ - Use the "build-composition" tool to create a NEW ELEMENTS in a composition on the page. You can use this tool to also create a new single element.
2411
+ - Use the "configure-element" tool to update the configuration of an EXISTING element on the page.
2412
+
2413
+ All array types that can receive union types, are typed as mixed array, which means that each item in the array can be of any of the allowed types defined in the PropType schema.
2414
+ Example: the "background" can have a background-overlay property, which can contain multiple overlays, such as color, gradient, image, etc. Each item in the array must follow the PropType schema for each overlay type.
2415
+ All _style properties are OPTIONAL. When a _style is defined, we MERGE the values with existing styles, so only the properties you define will be changed, and the rest will remain as is.
2416
+
2417
+ # Styling best practices
2418
+ Prefer using "em" and "rem" values for text-related sizes, padding and spacing. Use percentages for dynamic sizing relative to parent containers.
2419
+ This flexboxes are by default "flex" with "stretch" alignment. To ensure proper layout, define the "justify-content" and "align-items" as in the schema.
2420
+
2421
+ Additionaly, some PropTypes have metadata information (meta property) that can help in understaind the PropType usage, such as description or other useful information.
2422
+
2423
+ Example of null values:
2424
+ {
2425
+ $$type: 'as-defined-for-propValue',
2426
+ value: null
2427
+ }
2428
+
2429
+ Example of "image" PropValue structure:
2430
+ {$$type:'image',value:{src:{$$type:'image-src',value:{url:{$$type:'url',value:'https://example.com/image.jpg'}}},size:{$$type:'string',value:'full'}}}
2431
+
2432
+ `;
2433
+
1283
2434
  // src/prevent-link-in-link-commands.ts
1284
- var import_editor_elements3 = require("@elementor/editor-elements");
2435
+ var import_editor_elements9 = require("@elementor/editor-elements");
1285
2436
  var import_editor_notifications = require("@elementor/editor-notifications");
1286
- var import_editor_v1_adapters7 = require("@elementor/editor-v1-adapters");
2437
+ var import_editor_v1_adapters8 = require("@elementor/editor-v1-adapters");
1287
2438
  var import_i18n = require("@wordpress/i18n");
1288
2439
  function initLinkInLinkPrevention() {
1289
- (0, import_editor_v1_adapters7.blockCommand)({
2440
+ (0, import_editor_v1_adapters8.blockCommand)({
1290
2441
  command: "document/elements/paste",
1291
2442
  condition: blockLinkInLinkPaste
1292
2443
  });
1293
- (0, import_editor_v1_adapters7.blockCommand)({
2444
+ (0, import_editor_v1_adapters8.blockCommand)({
1294
2445
  command: "document/elements/move",
1295
2446
  condition: blockLinkInLinkMove
1296
2447
  });
@@ -1352,29 +2503,29 @@ function shouldBlock(sourceElements, targetElements) {
1352
2503
  return false;
1353
2504
  }
1354
2505
  const isSourceContainsAnAnchor = sourceElements.some((src) => {
1355
- return src?.id ? (0, import_editor_elements3.isElementAnchored)(src.id) || !!(0, import_editor_elements3.getAnchoredDescendantId)(src.id) : false;
2506
+ return src?.id ? (0, import_editor_elements9.isElementAnchored)(src.id) || !!(0, import_editor_elements9.getAnchoredDescendantId)(src.id) : false;
1356
2507
  });
1357
2508
  if (!isSourceContainsAnAnchor) {
1358
2509
  return false;
1359
2510
  }
1360
2511
  const isTargetContainsAnAnchor = targetElements.some((target) => {
1361
- return target?.id ? (0, import_editor_elements3.isElementAnchored)(target.id) || !!(0, import_editor_elements3.getAnchoredAncestorId)(target.id) : false;
2512
+ return target?.id ? (0, import_editor_elements9.isElementAnchored)(target.id) || !!(0, import_editor_elements9.getAnchoredAncestorId)(target.id) : false;
1362
2513
  });
1363
2514
  return isTargetContainsAnAnchor;
1364
2515
  }
1365
2516
 
1366
2517
  // src/style-commands/paste-style.ts
1367
- var import_editor_v1_adapters9 = require("@elementor/editor-v1-adapters");
2518
+ var import_editor_v1_adapters10 = require("@elementor/editor-v1-adapters");
1368
2519
 
1369
2520
  // src/style-commands/undoable-actions/paste-element-style.ts
1370
- var import_editor_elements5 = require("@elementor/editor-elements");
2521
+ var import_editor_elements11 = require("@elementor/editor-elements");
1371
2522
  var import_editor_styles_repository4 = require("@elementor/editor-styles-repository");
1372
- var import_editor_v1_adapters8 = require("@elementor/editor-v1-adapters");
2523
+ var import_editor_v1_adapters9 = require("@elementor/editor-v1-adapters");
1373
2524
  var import_i18n3 = require("@wordpress/i18n");
1374
2525
 
1375
2526
  // src/style-commands/utils.ts
1376
- var import_editor_elements4 = require("@elementor/editor-elements");
1377
- var import_editor_props2 = require("@elementor/editor-props");
2527
+ var import_editor_elements10 = require("@elementor/editor-elements");
2528
+ var import_editor_props6 = require("@elementor/editor-props");
1378
2529
  var import_i18n2 = require("@wordpress/i18n");
1379
2530
  function hasAtomicWidgets(args) {
1380
2531
  const { containers = [args.container] } = args;
@@ -1392,13 +2543,13 @@ function getClassesProp(container) {
1392
2543
  return null;
1393
2544
  }
1394
2545
  const [propKey] = Object.entries(propsSchema).find(
1395
- ([, propType]) => propType.kind === "plain" && propType.key === import_editor_props2.CLASSES_PROP_KEY
2546
+ ([, propType]) => propType.kind === "plain" && propType.key === import_editor_props6.CLASSES_PROP_KEY
1396
2547
  ) ?? [];
1397
2548
  return propKey ?? null;
1398
2549
  }
1399
2550
  function getContainerSchema(container) {
1400
2551
  const type = container?.model.get("widgetType") || container?.model.get("elType");
1401
- const widgetsCache = (0, import_editor_elements4.getWidgetsCache)();
2552
+ const widgetsCache = (0, import_editor_elements10.getWidgetsCache)();
1402
2553
  const elementType = widgetsCache?.[type];
1403
2554
  return elementType?.atomic_props_schema ?? null;
1404
2555
  }
@@ -1411,11 +2562,11 @@ function getClipboardElements(storageKey = "clipboard") {
1411
2562
  }
1412
2563
  }
1413
2564
  function getTitleForContainers(containers) {
1414
- return containers.length > 1 ? (0, import_i18n2.__)("Elements", "elementor") : (0, import_editor_elements4.getElementLabel)(containers[0].id);
2565
+ return containers.length > 1 ? (0, import_i18n2.__)("Elements", "elementor") : (0, import_editor_elements10.getElementLabel)(containers[0].id);
1415
2566
  }
1416
2567
 
1417
2568
  // src/style-commands/undoable-actions/paste-element-style.ts
1418
- var undoablePasteElementStyle = () => (0, import_editor_v1_adapters8.undoable)(
2569
+ var undoablePasteElementStyle = () => (0, import_editor_v1_adapters9.undoable)(
1419
2570
  {
1420
2571
  do: ({ containers, newStyle }) => {
1421
2572
  return containers.map((container) => {
@@ -1424,7 +2575,7 @@ var undoablePasteElementStyle = () => (0, import_editor_v1_adapters8.undoable)(
1424
2575
  if (!classesProp) {
1425
2576
  return null;
1426
2577
  }
1427
- const originalStyles = (0, import_editor_elements5.getElementStyles)(container.id);
2578
+ const originalStyles = (0, import_editor_elements11.getElementStyles)(container.id);
1428
2579
  const [styleId, styleDef] = Object.entries(originalStyles ?? {})[0] ?? [];
1429
2580
  const originalStyle = Object.keys(styleDef ?? {}).length ? styleDef : null;
1430
2581
  const revertData = {
@@ -1433,7 +2584,7 @@ var undoablePasteElementStyle = () => (0, import_editor_v1_adapters8.undoable)(
1433
2584
  };
1434
2585
  if (styleId) {
1435
2586
  newStyle.variants.forEach(({ meta, props, custom_css: customCss }) => {
1436
- (0, import_editor_elements5.updateElementStyle)({
2587
+ (0, import_editor_elements11.updateElementStyle)({
1437
2588
  elementId,
1438
2589
  styleId,
1439
2590
  meta,
@@ -1444,7 +2595,7 @@ var undoablePasteElementStyle = () => (0, import_editor_v1_adapters8.undoable)(
1444
2595
  } else {
1445
2596
  const [firstVariant] = newStyle.variants;
1446
2597
  const additionalVariants = newStyle.variants.slice(1);
1447
- revertData.styleId = (0, import_editor_elements5.createElementStyle)({
2598
+ revertData.styleId = (0, import_editor_elements11.createElementStyle)({
1448
2599
  elementId,
1449
2600
  classesProp,
1450
2601
  label: import_editor_styles_repository4.ELEMENTS_STYLES_RESERVED_LABEL,
@@ -1462,7 +2613,7 @@ var undoablePasteElementStyle = () => (0, import_editor_v1_adapters8.undoable)(
1462
2613
  return;
1463
2614
  }
1464
2615
  if (!revertData.originalStyle) {
1465
- (0, import_editor_elements5.deleteElementStyle)(container.id, revertData.styleId);
2616
+ (0, import_editor_elements11.deleteElementStyle)(container.id, revertData.styleId);
1466
2617
  return;
1467
2618
  }
1468
2619
  const classesProp = getClassesProp(container);
@@ -1471,7 +2622,7 @@ var undoablePasteElementStyle = () => (0, import_editor_v1_adapters8.undoable)(
1471
2622
  }
1472
2623
  const [firstVariant] = revertData.originalStyle.variants;
1473
2624
  const additionalVariants = revertData.originalStyle.variants.slice(1);
1474
- (0, import_editor_elements5.createElementStyle)({
2625
+ (0, import_editor_elements11.createElementStyle)({
1475
2626
  elementId: container.id,
1476
2627
  classesProp,
1477
2628
  label: import_editor_styles_repository4.ELEMENTS_STYLES_RESERVED_LABEL,
@@ -1491,12 +2642,12 @@ var undoablePasteElementStyle = () => (0, import_editor_v1_adapters8.undoable)(
1491
2642
  // src/style-commands/paste-style.ts
1492
2643
  function initPasteStyleCommand() {
1493
2644
  const pasteElementStyleCommand = undoablePasteElementStyle();
1494
- (0, import_editor_v1_adapters9.blockCommand)({
2645
+ (0, import_editor_v1_adapters10.blockCommand)({
1495
2646
  command: "document/elements/paste-style",
1496
2647
  condition: hasAtomicWidgets
1497
2648
  });
1498
- (0, import_editor_v1_adapters9.__privateListenTo)(
1499
- (0, import_editor_v1_adapters9.commandStartEvent)("document/elements/paste-style"),
2649
+ (0, import_editor_v1_adapters10.__privateListenTo)(
2650
+ (0, import_editor_v1_adapters10.commandStartEvent)("document/elements/paste-style"),
1500
2651
  (e) => pasteStyles(e.args, pasteElementStyleCommand)
1501
2652
  );
1502
2653
  }
@@ -1520,21 +2671,21 @@ function pasteStyles(args, pasteCallback) {
1520
2671
  }
1521
2672
 
1522
2673
  // src/style-commands/reset-style.ts
1523
- var import_editor_v1_adapters11 = require("@elementor/editor-v1-adapters");
2674
+ var import_editor_v1_adapters12 = require("@elementor/editor-v1-adapters");
1524
2675
 
1525
2676
  // src/style-commands/undoable-actions/reset-element-style.ts
1526
- var import_editor_elements6 = require("@elementor/editor-elements");
2677
+ var import_editor_elements12 = require("@elementor/editor-elements");
1527
2678
  var import_editor_styles_repository5 = require("@elementor/editor-styles-repository");
1528
- var import_editor_v1_adapters10 = require("@elementor/editor-v1-adapters");
2679
+ var import_editor_v1_adapters11 = require("@elementor/editor-v1-adapters");
1529
2680
  var import_i18n4 = require("@wordpress/i18n");
1530
- var undoableResetElementStyle = () => (0, import_editor_v1_adapters10.undoable)(
2681
+ var undoableResetElementStyle = () => (0, import_editor_v1_adapters11.undoable)(
1531
2682
  {
1532
2683
  do: ({ containers }) => {
1533
2684
  return containers.map((container) => {
1534
2685
  const elementId = container.model.get("id");
1535
- const containerStyles = (0, import_editor_elements6.getElementStyles)(elementId);
2686
+ const containerStyles = (0, import_editor_elements12.getElementStyles)(elementId);
1536
2687
  Object.keys(containerStyles ?? {}).forEach(
1537
- (styleId) => (0, import_editor_elements6.deleteElementStyle)(elementId, styleId)
2688
+ (styleId) => (0, import_editor_elements12.deleteElementStyle)(elementId, styleId)
1538
2689
  );
1539
2690
  return containerStyles;
1540
2691
  });
@@ -1550,7 +2701,7 @@ var undoableResetElementStyle = () => (0, import_editor_v1_adapters10.undoable)(
1550
2701
  Object.entries(containerStyles ?? {}).forEach(([styleId, style]) => {
1551
2702
  const [firstVariant] = style.variants;
1552
2703
  const additionalVariants = style.variants.slice(1);
1553
- (0, import_editor_elements6.createElementStyle)({
2704
+ (0, import_editor_elements12.createElementStyle)({
1554
2705
  elementId,
1555
2706
  classesProp,
1556
2707
  styleId,
@@ -1571,12 +2722,12 @@ var undoableResetElementStyle = () => (0, import_editor_v1_adapters10.undoable)(
1571
2722
  // src/style-commands/reset-style.ts
1572
2723
  function initResetStyleCommand() {
1573
2724
  const resetElementStyles = undoableResetElementStyle();
1574
- (0, import_editor_v1_adapters11.blockCommand)({
2725
+ (0, import_editor_v1_adapters12.blockCommand)({
1575
2726
  command: "document/elements/reset-style",
1576
2727
  condition: hasAtomicWidgets
1577
2728
  });
1578
- (0, import_editor_v1_adapters11.__privateListenTo)(
1579
- (0, import_editor_v1_adapters11.commandStartEvent)("document/elements/reset-style"),
2729
+ (0, import_editor_v1_adapters12.__privateListenTo)(
2730
+ (0, import_editor_v1_adapters12.commandStartEvent)("document/elements/reset-style"),
1580
2731
  (e) => resetStyles(e.args, resetElementStyles)
1581
2732
  );
1582
2733
  }
@@ -1602,6 +2753,7 @@ function init() {
1602
2753
  initLinkInLinkPrevention();
1603
2754
  initLegacyViews();
1604
2755
  initSettingsTransformers();
2756
+ (0, import_editor_interactions2.init)();
1605
2757
  (0, import_editor.injectIntoTop)({
1606
2758
  id: "elements-overlays",
1607
2759
  component: ElementsOverlays
@@ -1610,18 +2762,67 @@ function init() {
1610
2762
  id: "canvas-style-render",
1611
2763
  component: StyleRenderer
1612
2764
  });
2765
+ (0, import_editor.injectIntoTop)({
2766
+ id: "canvas-interactions-render",
2767
+ component: InteractionsRenderer
2768
+ });
1613
2769
  (0, import_editor.injectIntoLogic)({
1614
2770
  id: "classes-rename",
1615
2771
  component: ClassesRename
1616
2772
  });
2773
+ initCanvasMcp(
2774
+ (0, import_editor_mcp3.getMCPByDomain)("canvas", {
2775
+ instructions: mcpDescription
2776
+ })
2777
+ );
1617
2778
  }
2779
+
2780
+ // src/sync/drag-element-from-panel.ts
2781
+ var startDragElementFromPanel = (props) => {
2782
+ const channels = getElementorChannels();
2783
+ channels?.editor.reply("element:dragged", null);
2784
+ channels?.panelElements.reply("element:selected", getLegacyPanelElementView(props)).trigger("element:drag:start");
2785
+ };
2786
+ var endDragElementFromPanel = () => {
2787
+ getElementorChannels()?.panelElements?.trigger("element:drag:end");
2788
+ };
2789
+ var getElementorChannels = () => {
2790
+ const extendedWindow = window;
2791
+ const channels = extendedWindow.elementor?.channels;
2792
+ if (!channels) {
2793
+ throw new Error(
2794
+ "Elementor channels not found: Elementor editor is not initialized or channels are unavailable."
2795
+ );
2796
+ }
2797
+ return channels;
2798
+ };
2799
+ var getLegacyPanelElementView = ({ settings, ...rest }) => {
2800
+ const extendedWindow = window;
2801
+ const LegacyElementModel = extendedWindow.elementor?.modules?.elements?.models?.Element;
2802
+ if (!LegacyElementModel) {
2803
+ throw new Error("Elementor legacy Element model not found in editor modules");
2804
+ }
2805
+ const elementModel = new LegacyElementModel({
2806
+ ...rest,
2807
+ custom: {
2808
+ isPreset: !!settings,
2809
+ preset_settings: settings
2810
+ }
2811
+ });
2812
+ return { model: elementModel };
2813
+ };
1618
2814
  // Annotate the CommonJS export names for ESM import in node:
1619
2815
  0 && (module.exports = {
1620
2816
  createPropsResolver,
2817
+ createTemplatedElementView,
1621
2818
  createTransformer,
1622
2819
  createTransformersRegistry,
2820
+ endDragElementFromPanel,
2821
+ getCanvasIframeDocument,
1623
2822
  init,
2823
+ registerElementType,
1624
2824
  settingsTransformersRegistry,
2825
+ startDragElementFromPanel,
1625
2826
  styleTransformersRegistry
1626
2827
  });
1627
2828
  //# sourceMappingURL=index.js.map