@elementor/editor-canvas 3.35.0-356 → 3.35.0-358

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -5,6 +5,7 @@ import { Props, PropTypeKey, PropsSchema, AnyTransformable } from '@elementor/ed
5
5
 
6
6
  declare const BREAKPOINTS_SCHEMA_URI = "elementor://breakpoints/list";
7
7
 
8
+ declare const WIDGET_SCHEMA_URI = "elementor://widgets/schema/{widgetType}";
8
9
  declare const STYLE_SCHEMA_URI = "elementor://styles/schema/{category}";
9
10
 
10
11
  declare function init(): void;
@@ -131,6 +132,17 @@ type ElementLegacyType = {
131
132
  };
132
133
  declare function registerElementType(type: string, elementTypeGenerator: ElementLegacyType[keyof ElementLegacyType]): void;
133
134
 
135
+ declare class RenderContext<TContext extends Record<string, unknown>> {
136
+ private key;
137
+ private context;
138
+ constructor(key: string, initialContext: TContext);
139
+ get(): TContext;
140
+ set(context: TContext): void;
141
+ update(updates: TContext): void;
142
+ delete(): void;
143
+ clear(): void;
144
+ }
145
+
134
146
  type UnbrandedTransformer<TValue> = (value: TValue, options: {
135
147
  key: string;
136
148
  signal?: AbortSignal;
@@ -190,6 +202,8 @@ declare const endDragElementFromPanel: () => void;
190
202
 
191
203
  declare function getCanvasIframeDocument(): Document | null | undefined;
192
204
 
205
+ declare const DOCUMENT_STRUCTURE_URI = "elementor://document/structure";
206
+
193
207
  declare function createTransformer<TValue = never>(cb: TValue extends AnyTransformable ? 'Transformable values are invalid, use the actual value instead.' : UnbrandedTransformer<TValue>): Transformer<NoInfer<TValue>>;
194
208
 
195
- export { type AnyTransformer, BREAKPOINTS_SCHEMA_URI, type BackboneModel, type CreateTemplatedElementTypeOptions, type ElementModel, ElementType, ElementView, type LegacyWindow, type PropsResolver, STYLE_SCHEMA_URI, createPropsResolver, createTemplatedElementView, createTransformer, createTransformersRegistry, endDragElementFromPanel, getCanvasIframeDocument, init, registerElementType, settingsTransformersRegistry, startDragElementFromPanel, styleTransformersRegistry };
209
+ export { type AnyTransformer, BREAKPOINTS_SCHEMA_URI, type BackboneModel, type CreateTemplatedElementTypeOptions, DOCUMENT_STRUCTURE_URI, type ElementModel, ElementType, ElementView, type LegacyWindow, type PropsResolver, RenderContext, STYLE_SCHEMA_URI, WIDGET_SCHEMA_URI, createPropsResolver, createTemplatedElementView, createTransformer, createTransformersRegistry, endDragElementFromPanel, getCanvasIframeDocument, init, registerElementType, settingsTransformersRegistry, startDragElementFromPanel, styleTransformersRegistry };
package/dist/index.d.ts CHANGED
@@ -5,6 +5,7 @@ import { Props, PropTypeKey, PropsSchema, AnyTransformable } from '@elementor/ed
5
5
 
6
6
  declare const BREAKPOINTS_SCHEMA_URI = "elementor://breakpoints/list";
7
7
 
8
+ declare const WIDGET_SCHEMA_URI = "elementor://widgets/schema/{widgetType}";
8
9
  declare const STYLE_SCHEMA_URI = "elementor://styles/schema/{category}";
9
10
 
10
11
  declare function init(): void;
@@ -131,6 +132,17 @@ type ElementLegacyType = {
131
132
  };
132
133
  declare function registerElementType(type: string, elementTypeGenerator: ElementLegacyType[keyof ElementLegacyType]): void;
133
134
 
135
+ declare class RenderContext<TContext extends Record<string, unknown>> {
136
+ private key;
137
+ private context;
138
+ constructor(key: string, initialContext: TContext);
139
+ get(): TContext;
140
+ set(context: TContext): void;
141
+ update(updates: TContext): void;
142
+ delete(): void;
143
+ clear(): void;
144
+ }
145
+
134
146
  type UnbrandedTransformer<TValue> = (value: TValue, options: {
135
147
  key: string;
136
148
  signal?: AbortSignal;
@@ -190,6 +202,8 @@ declare const endDragElementFromPanel: () => void;
190
202
 
191
203
  declare function getCanvasIframeDocument(): Document | null | undefined;
192
204
 
205
+ declare const DOCUMENT_STRUCTURE_URI = "elementor://document/structure";
206
+
193
207
  declare function createTransformer<TValue = never>(cb: TValue extends AnyTransformable ? 'Transformable values are invalid, use the actual value instead.' : UnbrandedTransformer<TValue>): Transformer<NoInfer<TValue>>;
194
208
 
195
- export { type AnyTransformer, BREAKPOINTS_SCHEMA_URI, type BackboneModel, type CreateTemplatedElementTypeOptions, type ElementModel, ElementType, ElementView, type LegacyWindow, type PropsResolver, STYLE_SCHEMA_URI, createPropsResolver, createTemplatedElementView, createTransformer, createTransformersRegistry, endDragElementFromPanel, getCanvasIframeDocument, init, registerElementType, settingsTransformersRegistry, startDragElementFromPanel, styleTransformersRegistry };
209
+ export { type AnyTransformer, BREAKPOINTS_SCHEMA_URI, type BackboneModel, type CreateTemplatedElementTypeOptions, DOCUMENT_STRUCTURE_URI, type ElementModel, ElementType, ElementView, type LegacyWindow, type PropsResolver, RenderContext, STYLE_SCHEMA_URI, WIDGET_SCHEMA_URI, createPropsResolver, createTemplatedElementView, createTransformer, createTransformersRegistry, endDragElementFromPanel, getCanvasIframeDocument, init, registerElementType, settingsTransformersRegistry, startDragElementFromPanel, styleTransformersRegistry };
package/dist/index.js CHANGED
@@ -31,7 +31,10 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
31
31
  var index_exports = {};
32
32
  __export(index_exports, {
33
33
  BREAKPOINTS_SCHEMA_URI: () => BREAKPOINTS_SCHEMA_URI,
34
+ DOCUMENT_STRUCTURE_URI: () => DOCUMENT_STRUCTURE_URI,
35
+ RenderContext: () => RenderContext,
34
36
  STYLE_SCHEMA_URI: () => STYLE_SCHEMA_URI,
37
+ WIDGET_SCHEMA_URI: () => WIDGET_SCHEMA_URI,
35
38
  createPropsResolver: () => createPropsResolver,
36
39
  createTemplatedElementView: () => createTemplatedElementView,
37
40
  createTransformer: () => createTransformer,
@@ -1943,6 +1946,81 @@ function initLegacyViews() {
1943
1946
  });
1944
1947
  }
1945
1948
 
1949
+ // src/mcp/resources/document-structure-resource.ts
1950
+ var import_editor_v1_adapters10 = require("@elementor/editor-v1-adapters");
1951
+ var DOCUMENT_STRUCTURE_URI = "elementor://document/structure";
1952
+ var initDocumentStructureResource = (reg) => {
1953
+ const { mcpServer, sendResourceUpdated } = reg;
1954
+ let currentDocumentStructure = null;
1955
+ const updateDocumentStructure = () => {
1956
+ const structure = getDocumentStructure();
1957
+ const newStructure = JSON.stringify(structure, null, 2);
1958
+ if (newStructure !== currentDocumentStructure) {
1959
+ currentDocumentStructure = newStructure;
1960
+ sendResourceUpdated({ uri: DOCUMENT_STRUCTURE_URI });
1961
+ }
1962
+ };
1963
+ (0, import_editor_v1_adapters10.__privateListenTo)(
1964
+ [
1965
+ (0, import_editor_v1_adapters10.commandEndEvent)("document/elements/create"),
1966
+ (0, import_editor_v1_adapters10.commandEndEvent)("document/elements/delete"),
1967
+ (0, import_editor_v1_adapters10.commandEndEvent)("document/elements/move"),
1968
+ (0, import_editor_v1_adapters10.commandEndEvent)("document/elements/copy"),
1969
+ (0, import_editor_v1_adapters10.commandEndEvent)("document/elements/paste"),
1970
+ (0, import_editor_v1_adapters10.commandEndEvent)("editor/documents/attach-preview")
1971
+ ],
1972
+ updateDocumentStructure
1973
+ );
1974
+ updateDocumentStructure();
1975
+ mcpServer.resource("document-structure", DOCUMENT_STRUCTURE_URI, async () => {
1976
+ const structure = getDocumentStructure();
1977
+ return {
1978
+ contents: [
1979
+ {
1980
+ uri: DOCUMENT_STRUCTURE_URI,
1981
+ text: JSON.stringify(structure, null, 2)
1982
+ }
1983
+ ]
1984
+ };
1985
+ });
1986
+ };
1987
+ function getDocumentStructure() {
1988
+ const extendedWindow = window;
1989
+ const document2 = extendedWindow.elementor?.documents?.getCurrent?.();
1990
+ if (!document2) {
1991
+ return { error: "No active document found" };
1992
+ }
1993
+ const containers = document2.container?.children || [];
1994
+ const elements = containers.map(
1995
+ (container) => extractElementData(container)
1996
+ );
1997
+ return {
1998
+ documentId: document2.id,
1999
+ documentType: document2.config.type,
2000
+ title: document2.config.settings?.post_title || "Untitled",
2001
+ elements: elements.filter((el) => el !== null)
2002
+ };
2003
+ }
2004
+ function extractElementData(element) {
2005
+ if (!element || !element.model) {
2006
+ return null;
2007
+ }
2008
+ const model = element.model.attributes;
2009
+ const result = {
2010
+ id: model.id,
2011
+ elType: model.elType,
2012
+ widgetType: model.widgetType || void 0
2013
+ };
2014
+ const title = model.title || element.model?.editor_settings?.title;
2015
+ if (title) {
2016
+ result.title = title;
2017
+ }
2018
+ if (element.children && element.children.length > 0) {
2019
+ result.children = element.children.map((child) => extractElementData(child)).filter((child) => child !== null);
2020
+ }
2021
+ return result;
2022
+ }
2023
+
1946
2024
  // src/mcp/tools/build-composition/tool.ts
1947
2025
  var import_editor_elements8 = require("@elementor/editor-elements");
1948
2026
 
@@ -2950,6 +3028,7 @@ var initCanvasMcp = (reg) => {
2950
3028
  'Everything related to creative design, layout, styling and building the pages, specifically element of type "widget"'
2951
3029
  );
2952
3030
  initWidgetsSchemaResource(reg);
3031
+ initDocumentStructureResource(reg);
2953
3032
  initBuildCompositionsTool(reg);
2954
3033
  initGetElementConfigTool(reg);
2955
3034
  initConfigureElementTool(reg);
@@ -3085,14 +3164,14 @@ An Example scenario of creating fully styled composition:
3085
3164
  // src/prevent-link-in-link-commands.ts
3086
3165
  var import_editor_elements10 = require("@elementor/editor-elements");
3087
3166
  var import_editor_notifications = require("@elementor/editor-notifications");
3088
- var import_editor_v1_adapters10 = require("@elementor/editor-v1-adapters");
3167
+ var import_editor_v1_adapters11 = require("@elementor/editor-v1-adapters");
3089
3168
  var import_i18n = require("@wordpress/i18n");
3090
3169
  function initLinkInLinkPrevention() {
3091
- (0, import_editor_v1_adapters10.blockCommand)({
3170
+ (0, import_editor_v1_adapters11.blockCommand)({
3092
3171
  command: "document/elements/paste",
3093
3172
  condition: blockLinkInLinkPaste
3094
3173
  });
3095
- (0, import_editor_v1_adapters10.blockCommand)({
3174
+ (0, import_editor_v1_adapters11.blockCommand)({
3096
3175
  command: "document/elements/move",
3097
3176
  condition: blockLinkInLinkMove
3098
3177
  });
@@ -3166,12 +3245,12 @@ function shouldBlock(sourceElements, targetElements) {
3166
3245
  }
3167
3246
 
3168
3247
  // src/style-commands/paste-style.ts
3169
- var import_editor_v1_adapters12 = require("@elementor/editor-v1-adapters");
3248
+ var import_editor_v1_adapters13 = require("@elementor/editor-v1-adapters");
3170
3249
 
3171
3250
  // src/style-commands/undoable-actions/paste-element-style.ts
3172
3251
  var import_editor_elements12 = require("@elementor/editor-elements");
3173
3252
  var import_editor_styles_repository4 = require("@elementor/editor-styles-repository");
3174
- var import_editor_v1_adapters11 = require("@elementor/editor-v1-adapters");
3253
+ var import_editor_v1_adapters12 = require("@elementor/editor-v1-adapters");
3175
3254
  var import_i18n3 = require("@wordpress/i18n");
3176
3255
 
3177
3256
  // src/style-commands/utils.ts
@@ -3217,7 +3296,7 @@ function getTitleForContainers(containers) {
3217
3296
  }
3218
3297
 
3219
3298
  // src/style-commands/undoable-actions/paste-element-style.ts
3220
- var undoablePasteElementStyle = () => (0, import_editor_v1_adapters11.undoable)(
3299
+ var undoablePasteElementStyle = () => (0, import_editor_v1_adapters12.undoable)(
3221
3300
  {
3222
3301
  do: ({ containers, newStyle }) => {
3223
3302
  return containers.map((container) => {
@@ -3293,12 +3372,12 @@ var undoablePasteElementStyle = () => (0, import_editor_v1_adapters11.undoable)(
3293
3372
  // src/style-commands/paste-style.ts
3294
3373
  function initPasteStyleCommand() {
3295
3374
  const pasteElementStyleCommand = undoablePasteElementStyle();
3296
- (0, import_editor_v1_adapters12.blockCommand)({
3375
+ (0, import_editor_v1_adapters13.blockCommand)({
3297
3376
  command: "document/elements/paste-style",
3298
3377
  condition: hasAtomicWidgets
3299
3378
  });
3300
- (0, import_editor_v1_adapters12.__privateListenTo)(
3301
- (0, import_editor_v1_adapters12.commandStartEvent)("document/elements/paste-style"),
3379
+ (0, import_editor_v1_adapters13.__privateListenTo)(
3380
+ (0, import_editor_v1_adapters13.commandStartEvent)("document/elements/paste-style"),
3302
3381
  (e) => pasteStyles(e.args, pasteElementStyleCommand)
3303
3382
  );
3304
3383
  }
@@ -3322,14 +3401,14 @@ function pasteStyles(args, pasteCallback) {
3322
3401
  }
3323
3402
 
3324
3403
  // src/style-commands/reset-style.ts
3325
- var import_editor_v1_adapters14 = require("@elementor/editor-v1-adapters");
3404
+ var import_editor_v1_adapters15 = require("@elementor/editor-v1-adapters");
3326
3405
 
3327
3406
  // src/style-commands/undoable-actions/reset-element-style.ts
3328
3407
  var import_editor_elements13 = require("@elementor/editor-elements");
3329
3408
  var import_editor_styles_repository5 = require("@elementor/editor-styles-repository");
3330
- var import_editor_v1_adapters13 = require("@elementor/editor-v1-adapters");
3409
+ var import_editor_v1_adapters14 = require("@elementor/editor-v1-adapters");
3331
3410
  var import_i18n4 = require("@wordpress/i18n");
3332
- var undoableResetElementStyle = () => (0, import_editor_v1_adapters13.undoable)(
3411
+ var undoableResetElementStyle = () => (0, import_editor_v1_adapters14.undoable)(
3333
3412
  {
3334
3413
  do: ({ containers }) => {
3335
3414
  return containers.map((container) => {
@@ -3373,12 +3452,12 @@ var undoableResetElementStyle = () => (0, import_editor_v1_adapters13.undoable)(
3373
3452
  // src/style-commands/reset-style.ts
3374
3453
  function initResetStyleCommand() {
3375
3454
  const resetElementStyles = undoableResetElementStyle();
3376
- (0, import_editor_v1_adapters14.blockCommand)({
3455
+ (0, import_editor_v1_adapters15.blockCommand)({
3377
3456
  command: "document/elements/reset-style",
3378
3457
  condition: hasAtomicWidgets
3379
3458
  });
3380
- (0, import_editor_v1_adapters14.__privateListenTo)(
3381
- (0, import_editor_v1_adapters14.commandStartEvent)("document/elements/reset-style"),
3459
+ (0, import_editor_v1_adapters15.__privateListenTo)(
3460
+ (0, import_editor_v1_adapters15.commandStartEvent)("document/elements/reset-style"),
3382
3461
  (e) => resetStyles(e.args, resetElementStyles)
3383
3462
  );
3384
3463
  }
@@ -3428,6 +3507,35 @@ function init() {
3428
3507
  );
3429
3508
  }
3430
3509
 
3510
+ // src/renderers/render-context.ts
3511
+ var RenderContext = class {
3512
+ key;
3513
+ context = /* @__PURE__ */ new Map();
3514
+ constructor(key, initialContext) {
3515
+ this.key = key;
3516
+ this.context.set(this.key, initialContext);
3517
+ }
3518
+ get() {
3519
+ return this.context.get(this.key);
3520
+ }
3521
+ set(context) {
3522
+ this.context.set(this.key, context);
3523
+ }
3524
+ update(updates) {
3525
+ const currentContext = this.context.get(this.key);
3526
+ if (!currentContext) {
3527
+ return this.set(updates);
3528
+ }
3529
+ this.context.set(this.key, { ...currentContext, ...updates });
3530
+ }
3531
+ delete() {
3532
+ this.context.delete(this.key);
3533
+ }
3534
+ clear() {
3535
+ this.context.clear();
3536
+ }
3537
+ };
3538
+
3431
3539
  // src/sync/drag-element-from-panel.ts
3432
3540
  var startDragElementFromPanel = (props) => {
3433
3541
  const channels = getElementorChannels();
@@ -3465,7 +3573,10 @@ var getLegacyPanelElementView = ({ settings, ...rest }) => {
3465
3573
  // Annotate the CommonJS export names for ESM import in node:
3466
3574
  0 && (module.exports = {
3467
3575
  BREAKPOINTS_SCHEMA_URI,
3576
+ DOCUMENT_STRUCTURE_URI,
3577
+ RenderContext,
3468
3578
  STYLE_SCHEMA_URI,
3579
+ WIDGET_SCHEMA_URI,
3469
3580
  createPropsResolver,
3470
3581
  createTemplatedElementView,
3471
3582
  createTransformer,
package/dist/index.mjs CHANGED
@@ -1911,6 +1911,81 @@ function initLegacyViews() {
1911
1911
  });
1912
1912
  }
1913
1913
 
1914
+ // src/mcp/resources/document-structure-resource.ts
1915
+ import { __privateListenTo as listenTo, commandEndEvent as commandEndEvent4 } from "@elementor/editor-v1-adapters";
1916
+ var DOCUMENT_STRUCTURE_URI = "elementor://document/structure";
1917
+ var initDocumentStructureResource = (reg) => {
1918
+ const { mcpServer, sendResourceUpdated } = reg;
1919
+ let currentDocumentStructure = null;
1920
+ const updateDocumentStructure = () => {
1921
+ const structure = getDocumentStructure();
1922
+ const newStructure = JSON.stringify(structure, null, 2);
1923
+ if (newStructure !== currentDocumentStructure) {
1924
+ currentDocumentStructure = newStructure;
1925
+ sendResourceUpdated({ uri: DOCUMENT_STRUCTURE_URI });
1926
+ }
1927
+ };
1928
+ listenTo(
1929
+ [
1930
+ commandEndEvent4("document/elements/create"),
1931
+ commandEndEvent4("document/elements/delete"),
1932
+ commandEndEvent4("document/elements/move"),
1933
+ commandEndEvent4("document/elements/copy"),
1934
+ commandEndEvent4("document/elements/paste"),
1935
+ commandEndEvent4("editor/documents/attach-preview")
1936
+ ],
1937
+ updateDocumentStructure
1938
+ );
1939
+ updateDocumentStructure();
1940
+ mcpServer.resource("document-structure", DOCUMENT_STRUCTURE_URI, async () => {
1941
+ const structure = getDocumentStructure();
1942
+ return {
1943
+ contents: [
1944
+ {
1945
+ uri: DOCUMENT_STRUCTURE_URI,
1946
+ text: JSON.stringify(structure, null, 2)
1947
+ }
1948
+ ]
1949
+ };
1950
+ });
1951
+ };
1952
+ function getDocumentStructure() {
1953
+ const extendedWindow = window;
1954
+ const document2 = extendedWindow.elementor?.documents?.getCurrent?.();
1955
+ if (!document2) {
1956
+ return { error: "No active document found" };
1957
+ }
1958
+ const containers = document2.container?.children || [];
1959
+ const elements = containers.map(
1960
+ (container) => extractElementData(container)
1961
+ );
1962
+ return {
1963
+ documentId: document2.id,
1964
+ documentType: document2.config.type,
1965
+ title: document2.config.settings?.post_title || "Untitled",
1966
+ elements: elements.filter((el) => el !== null)
1967
+ };
1968
+ }
1969
+ function extractElementData(element) {
1970
+ if (!element || !element.model) {
1971
+ return null;
1972
+ }
1973
+ const model = element.model.attributes;
1974
+ const result = {
1975
+ id: model.id,
1976
+ elType: model.elType,
1977
+ widgetType: model.widgetType || void 0
1978
+ };
1979
+ const title = model.title || element.model?.editor_settings?.title;
1980
+ if (title) {
1981
+ result.title = title;
1982
+ }
1983
+ if (element.children && element.children.length > 0) {
1984
+ result.children = element.children.map((child) => extractElementData(child)).filter((child) => child !== null);
1985
+ }
1986
+ return result;
1987
+ }
1988
+
1914
1989
  // src/mcp/tools/build-composition/tool.ts
1915
1990
  import {
1916
1991
  createElement as createElement6,
@@ -2930,6 +3005,7 @@ var initCanvasMcp = (reg) => {
2930
3005
  'Everything related to creative design, layout, styling and building the pages, specifically element of type "widget"'
2931
3006
  );
2932
3007
  initWidgetsSchemaResource(reg);
3008
+ initDocumentStructureResource(reg);
2933
3009
  initBuildCompositionsTool(reg);
2934
3010
  initGetElementConfigTool(reg);
2935
3011
  initConfigureElementTool(reg);
@@ -3151,7 +3227,7 @@ function shouldBlock(sourceElements, targetElements) {
3151
3227
 
3152
3228
  // src/style-commands/paste-style.ts
3153
3229
  import {
3154
- __privateListenTo as listenTo,
3230
+ __privateListenTo as listenTo2,
3155
3231
  blockCommand as blockCommand2,
3156
3232
  commandStartEvent
3157
3233
  } from "@elementor/editor-v1-adapters";
@@ -3290,7 +3366,7 @@ function initPasteStyleCommand() {
3290
3366
  command: "document/elements/paste-style",
3291
3367
  condition: hasAtomicWidgets
3292
3368
  });
3293
- listenTo(
3369
+ listenTo2(
3294
3370
  commandStartEvent("document/elements/paste-style"),
3295
3371
  (e) => pasteStyles(e.args, pasteElementStyleCommand)
3296
3372
  );
@@ -3316,7 +3392,7 @@ function pasteStyles(args, pasteCallback) {
3316
3392
 
3317
3393
  // src/style-commands/reset-style.ts
3318
3394
  import {
3319
- __privateListenTo as listenTo2,
3395
+ __privateListenTo as listenTo3,
3320
3396
  blockCommand as blockCommand3,
3321
3397
  commandStartEvent as commandStartEvent2
3322
3398
  } from "@elementor/editor-v1-adapters";
@@ -3374,7 +3450,7 @@ function initResetStyleCommand() {
3374
3450
  command: "document/elements/reset-style",
3375
3451
  condition: hasAtomicWidgets
3376
3452
  });
3377
- listenTo2(
3453
+ listenTo3(
3378
3454
  commandStartEvent2("document/elements/reset-style"),
3379
3455
  (e) => resetStyles(e.args, resetElementStyles)
3380
3456
  );
@@ -3425,6 +3501,35 @@ function init() {
3425
3501
  );
3426
3502
  }
3427
3503
 
3504
+ // src/renderers/render-context.ts
3505
+ var RenderContext = class {
3506
+ key;
3507
+ context = /* @__PURE__ */ new Map();
3508
+ constructor(key, initialContext) {
3509
+ this.key = key;
3510
+ this.context.set(this.key, initialContext);
3511
+ }
3512
+ get() {
3513
+ return this.context.get(this.key);
3514
+ }
3515
+ set(context) {
3516
+ this.context.set(this.key, context);
3517
+ }
3518
+ update(updates) {
3519
+ const currentContext = this.context.get(this.key);
3520
+ if (!currentContext) {
3521
+ return this.set(updates);
3522
+ }
3523
+ this.context.set(this.key, { ...currentContext, ...updates });
3524
+ }
3525
+ delete() {
3526
+ this.context.delete(this.key);
3527
+ }
3528
+ clear() {
3529
+ this.context.clear();
3530
+ }
3531
+ };
3532
+
3428
3533
  // src/sync/drag-element-from-panel.ts
3429
3534
  var startDragElementFromPanel = (props) => {
3430
3535
  const channels = getElementorChannels();
@@ -3461,7 +3566,10 @@ var getLegacyPanelElementView = ({ settings, ...rest }) => {
3461
3566
  };
3462
3567
  export {
3463
3568
  BREAKPOINTS_SCHEMA_URI,
3569
+ DOCUMENT_STRUCTURE_URI,
3570
+ RenderContext,
3464
3571
  STYLE_SCHEMA_URI,
3572
+ WIDGET_SCHEMA_URI,
3465
3573
  createPropsResolver,
3466
3574
  createTemplatedElementView,
3467
3575
  createTransformer,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@elementor/editor-canvas",
3
3
  "description": "Elementor Editor Canvas",
4
- "version": "3.35.0-356",
4
+ "version": "3.35.0-358",
5
5
  "private": false,
6
6
  "author": "Elementor Team",
7
7
  "homepage": "https://elementor.com/",
@@ -37,24 +37,24 @@
37
37
  "react-dom": "^18.3.1"
38
38
  },
39
39
  "dependencies": {
40
- "@elementor/editor": "3.35.0-356",
41
- "@elementor/editor-controls": "3.35.0-356",
42
- "@elementor/editor-documents": "3.35.0-356",
43
- "@elementor/editor-elements": "3.35.0-356",
44
- "@elementor/editor-interactions": "3.35.0-356",
45
- "@elementor/editor-mcp": "3.35.0-356",
46
- "@elementor/editor-notifications": "3.35.0-356",
47
- "@elementor/editor-props": "3.35.0-356",
48
- "@elementor/editor-responsive": "3.35.0-356",
49
- "@elementor/editor-styles": "3.35.0-356",
50
- "@elementor/editor-styles-repository": "3.35.0-356",
51
- "@elementor/editor-ui": "3.35.0-356",
52
- "@elementor/editor-v1-adapters": "3.35.0-356",
53
- "@elementor/schema": "3.35.0-356",
54
- "@elementor/twing": "3.35.0-356",
40
+ "@elementor/editor": "3.35.0-358",
41
+ "@elementor/editor-controls": "3.35.0-358",
42
+ "@elementor/editor-documents": "3.35.0-358",
43
+ "@elementor/editor-elements": "3.35.0-358",
44
+ "@elementor/editor-interactions": "3.35.0-358",
45
+ "@elementor/editor-mcp": "3.35.0-358",
46
+ "@elementor/editor-notifications": "3.35.0-358",
47
+ "@elementor/editor-props": "3.35.0-358",
48
+ "@elementor/editor-responsive": "3.35.0-358",
49
+ "@elementor/editor-styles": "3.35.0-358",
50
+ "@elementor/editor-styles-repository": "3.35.0-358",
51
+ "@elementor/editor-ui": "3.35.0-358",
52
+ "@elementor/editor-v1-adapters": "3.35.0-358",
53
+ "@elementor/schema": "3.35.0-358",
54
+ "@elementor/twing": "3.35.0-358",
55
55
  "@elementor/ui": "1.36.17",
56
- "@elementor/utils": "3.35.0-356",
57
- "@elementor/wp-media": "3.35.0-356",
56
+ "@elementor/utils": "3.35.0-358",
57
+ "@elementor/wp-media": "3.35.0-358",
58
58
  "@floating-ui/react": "^0.27.5",
59
59
  "@wordpress/i18n": "^5.13.0"
60
60
  },
package/src/index.ts CHANGED
@@ -9,11 +9,15 @@ export {
9
9
  } from './legacy/create-templated-element-type';
10
10
  export { registerElementType } from './legacy/init-legacy-views';
11
11
  export * from './legacy/types';
12
+ export { RenderContext } from './renderers/render-context';
12
13
  export { createPropsResolver, type PropsResolver } from './renderers/create-props-resolver';
13
14
  export { settingsTransformersRegistry } from './settings-transformers-registry';
14
15
  export { styleTransformersRegistry } from './style-transformers-registry';
15
16
  export { endDragElementFromPanel, startDragElementFromPanel } from './sync/drag-element-from-panel';
16
17
  export { getCanvasIframeDocument } from './sync/get-canvas-iframe-document';
18
+ export { DOCUMENT_STRUCTURE_URI } from './mcp/resources/document-structure-resource';
19
+ export { WIDGET_SCHEMA_URI } from './mcp/resources/widgets-schema-resource';
20
+ export * from './legacy/types';
17
21
  export { createTransformer } from './transformers/create-transformer';
18
22
  export { createTransformersRegistry } from './transformers/create-transformers-registry';
19
23
  export { type AnyTransformer } from './transformers/types';
@@ -1,6 +1,7 @@
1
1
  import { type MCPRegistryEntry } from '@elementor/editor-mcp';
2
2
 
3
3
  import { initBreakpointsResource } from './resources/breakpoints-resource';
4
+ import { initDocumentStructureResource } from './resources/document-structure-resource';
4
5
  import { initWidgetsSchemaResource } from './resources/widgets-schema-resource';
5
6
  import { initBuildCompositionsTool } from './tools/build-composition/tool';
6
7
  import { initConfigureElementTool } from './tools/configure-element/tool';
@@ -12,6 +13,7 @@ export const initCanvasMcp = ( reg: MCPRegistryEntry ) => {
12
13
  'Everything related to creative design, layout, styling and building the pages, specifically element of type "widget"'
13
14
  );
14
15
  initWidgetsSchemaResource( reg );
16
+ initDocumentStructureResource( reg );
15
17
  initBuildCompositionsTool( reg );
16
18
  initGetElementConfigTool( reg );
17
19
  initConfigureElementTool( reg );
@@ -0,0 +1,132 @@
1
+ import { type MCPRegistryEntry } from '@elementor/editor-mcp';
2
+ import { __privateListenTo as listenTo, commandEndEvent } from '@elementor/editor-v1-adapters';
3
+
4
+ type ExtendedWindow = Window & {
5
+ elementor?: {
6
+ documents?: {
7
+ getCurrent?: () => {
8
+ id: number;
9
+ config: {
10
+ type: string;
11
+ settings?: {
12
+ post_title?: string;
13
+ };
14
+ };
15
+ container: {
16
+ children?: ElementorContainer[];
17
+ };
18
+ };
19
+ };
20
+ };
21
+ };
22
+
23
+ type ElementorContainer = {
24
+ id: string;
25
+ model: {
26
+ attributes: {
27
+ id: string;
28
+ elType: string;
29
+ widgetType?: string;
30
+ title?: string;
31
+ };
32
+ editor_settings?: {
33
+ title?: string;
34
+ };
35
+ };
36
+ children?: ElementorContainer[];
37
+ };
38
+
39
+ export const DOCUMENT_STRUCTURE_URI = 'elementor://document/structure';
40
+
41
+ export const initDocumentStructureResource = ( reg: MCPRegistryEntry ) => {
42
+ const { mcpServer, sendResourceUpdated } = reg;
43
+
44
+ let currentDocumentStructure: string | null = null;
45
+
46
+ const updateDocumentStructure = () => {
47
+ const structure = getDocumentStructure();
48
+ const newStructure = JSON.stringify( structure, null, 2 );
49
+
50
+ if ( newStructure !== currentDocumentStructure ) {
51
+ currentDocumentStructure = newStructure;
52
+ sendResourceUpdated( { uri: DOCUMENT_STRUCTURE_URI } );
53
+ }
54
+ };
55
+
56
+ // Listen to document changes
57
+ listenTo(
58
+ [
59
+ commandEndEvent( 'document/elements/create' ),
60
+ commandEndEvent( 'document/elements/delete' ),
61
+ commandEndEvent( 'document/elements/move' ),
62
+ commandEndEvent( 'document/elements/copy' ),
63
+ commandEndEvent( 'document/elements/paste' ),
64
+ commandEndEvent( 'editor/documents/attach-preview' ),
65
+ ],
66
+ updateDocumentStructure
67
+ );
68
+
69
+ // Initialize on load
70
+ updateDocumentStructure();
71
+
72
+ mcpServer.resource( 'document-structure', DOCUMENT_STRUCTURE_URI, async () => {
73
+ const structure = getDocumentStructure();
74
+
75
+ return {
76
+ contents: [
77
+ {
78
+ uri: DOCUMENT_STRUCTURE_URI,
79
+ text: JSON.stringify( structure, null, 2 ),
80
+ },
81
+ ],
82
+ };
83
+ } );
84
+ };
85
+
86
+ function getDocumentStructure() {
87
+ const extendedWindow = window as ExtendedWindow;
88
+ const document = extendedWindow.elementor?.documents?.getCurrent?.();
89
+
90
+ if ( ! document ) {
91
+ return { error: 'No active document found' };
92
+ }
93
+
94
+ const containers = document.container?.children || [];
95
+ const elements = ( containers as ElementorContainer[] ).map( ( container: ElementorContainer ) =>
96
+ extractElementData( container )
97
+ );
98
+
99
+ return {
100
+ documentId: document.id,
101
+ documentType: document.config.type,
102
+ title: document.config.settings?.post_title || 'Untitled',
103
+ elements: elements.filter( ( el: Record< string, unknown > | null ) => el !== null ),
104
+ };
105
+ }
106
+
107
+ function extractElementData( element: ElementorContainer ): Record< string, unknown > | null {
108
+ if ( ! element || ! element.model ) {
109
+ return null;
110
+ }
111
+
112
+ const model = element.model.attributes;
113
+ const result: Record< string, unknown > = {
114
+ id: model.id,
115
+ elType: model.elType,
116
+ widgetType: model.widgetType || undefined,
117
+ };
118
+
119
+ const title = model.title || element.model?.editor_settings?.title;
120
+
121
+ if ( title ) {
122
+ result.title = title;
123
+ }
124
+
125
+ if ( element.children && element.children.length > 0 ) {
126
+ result.children = element.children
127
+ .map( ( child: ElementorContainer ) => extractElementData( child ) )
128
+ .filter( ( child: Record< string, unknown > | null ) => child !== null );
129
+ }
130
+
131
+ return result;
132
+ }
@@ -0,0 +1,35 @@
1
+ export class RenderContext< TContext extends Record< string, unknown > > {
2
+ private key: string;
3
+ private context = new Map< string, TContext >();
4
+
5
+ public constructor( key: string, initialContext: TContext ) {
6
+ this.key = key;
7
+ this.context.set( this.key, initialContext );
8
+ }
9
+
10
+ public get(): TContext {
11
+ return this.context.get( this.key ) as TContext;
12
+ }
13
+
14
+ public set( context: TContext ) {
15
+ this.context.set( this.key, context );
16
+ }
17
+
18
+ public update( updates: TContext ) {
19
+ const currentContext = this.context.get( this.key );
20
+
21
+ if ( ! currentContext ) {
22
+ return this.set( updates );
23
+ }
24
+
25
+ this.context.set( this.key, { ...currentContext, ...updates } );
26
+ }
27
+
28
+ public delete() {
29
+ this.context.delete( this.key );
30
+ }
31
+
32
+ public clear() {
33
+ this.context.clear();
34
+ }
35
+ }