@elementor/editor-canvas 4.3.0-998 → 4.3.0-beta1

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 (50) hide show
  1. package/dist/index.d.mts +3 -1
  2. package/dist/index.d.ts +3 -1
  3. package/dist/index.js +452 -408
  4. package/dist/index.mjs +434 -386
  5. package/package.json +20 -20
  6. package/src/init-settings-transformers.ts +4 -0
  7. package/src/init-style-transformers.ts +2 -2
  8. package/src/init.tsx +5 -4
  9. package/src/legacy/__tests__/create-templated-element-type.test.ts +50 -0
  10. package/src/legacy/__tests__/list-type.test.ts +89 -0
  11. package/src/legacy/create-nested-templated-element-type.ts +3 -1
  12. package/src/legacy/create-templated-element-type.ts +5 -2
  13. package/src/legacy/list-type.ts +63 -0
  14. package/src/legacy/replacements/inline-editing/__tests__/inline-editing-eligibility.test.ts +7 -7
  15. package/src/legacy/replacements/inline-editing/inline-editing-elements.tsx +22 -9
  16. package/src/legacy/replacements/inline-editing/inline-editing-eligibility.ts +12 -3
  17. package/src/legacy/tabs-model-extensions.ts +2 -5
  18. package/src/legacy/twig-rendering-utils.ts +11 -2
  19. package/src/legacy/types.ts +4 -0
  20. package/src/mcp/canvas-mcp.ts +2 -6
  21. package/src/mcp/mcp-description.ts +18 -30
  22. package/src/mcp/resources/__tests__/available-widgets-resource.test.ts +22 -13
  23. package/src/mcp/resources/__tests__/dynamic-tags-resource.test.ts +22 -30
  24. package/src/mcp/resources/__tests__/widgets-schema-resource.test.ts +11 -6
  25. package/src/mcp/resources/available-widgets-resource.ts +13 -10
  26. package/src/mcp/resources/dynamic-tags-resource.ts +6 -15
  27. package/src/mcp/resources/widgets-schema-resource.ts +8 -5
  28. package/src/mcp/tools/configure-element/__tests__/tool.test.ts +130 -0
  29. package/src/mcp/tools/configure-element/prompt.ts +3 -6
  30. package/src/mcp/tools/configure-element/schema.ts +6 -0
  31. package/src/mcp/tools/configure-element/tool.ts +11 -1
  32. package/src/mcp/tools/get-page-structure/tool.ts +73 -0
  33. package/src/mcp/utils/__tests__/do-update-element-property.test.ts +27 -1
  34. package/src/mcp/utils/do-update-element-property.ts +18 -6
  35. package/src/mcp/utils/get-mcp-error-message.ts +16 -0
  36. package/src/renderers/__tests__/compute-html-tag.test.ts +55 -0
  37. package/src/renderers/__tests__/create-dom-renderer.test.ts +60 -0
  38. package/src/renderers/__tests__/fixtures/html-tag-computer-cases.json +87 -0
  39. package/src/renderers/compute-html-tag.ts +73 -0
  40. package/src/renderers/create-dom-renderer.ts +13 -22
  41. package/src/transformers/settings/escaped-html-transformer.ts +6 -0
  42. package/src/transformers/shared/__tests__/icon-transformer.test.ts +74 -0
  43. package/src/transformers/shared/icon-transformer.ts +122 -0
  44. package/src/transformers/shared/process-svg-content.ts +26 -0
  45. package/src/transformers/shared/svg-src-transformer.ts +1 -26
  46. package/src/utils/__tests__/sanitize-escaped-html.test.ts +105 -0
  47. package/src/utils/sanitize-escaped-html.ts +32 -0
  48. package/src/mcp/tools/build-composition/tool.ts +0 -133
  49. package/src/mcp/tools/create-element/tool.ts +0 -61
  50. package/src/mcp/tools/get-element-config/tool.ts +0 -114
package/dist/index.js CHANGED
@@ -81,10 +81,10 @@ var BEST_PRACTICES_FULL_URI = `${CANVAS_SERVER_NAME}_${BEST_PRACTICES_URI}`;
81
81
  var MCP_PROXY_URL = "elementor/v1/mcp-proxy";
82
82
  var listWidgetTypes = async () => {
83
83
  const { data } = await (0, import_http_client.httpService)().post(MCP_PROXY_URL, {
84
- tool: "list-widgets",
85
- input: {}
84
+ tool: "list-widget-schemas",
85
+ input: { summary: true }
86
86
  });
87
- return (data.data ?? []).map((widget) => widget.type);
87
+ return (data.data?.widgets ?? []).map((widget) => widget.type);
88
88
  };
89
89
  var fetchWidgetSchema = async (widgetType) => {
90
90
  const { data } = await (0, import_http_client.httpService)().post(MCP_PROXY_URL, {
@@ -116,13 +116,13 @@ var initWidgetsSchemaResource = (reg) => {
116
116
  if (!widgetType) {
117
117
  throw new Error("No widget type provided.");
118
118
  }
119
- const schema2 = await fetchWidgetSchema(widgetType);
119
+ const schema = await fetchWidgetSchema(widgetType);
120
120
  return {
121
121
  contents: [
122
122
  {
123
123
  uri: uri.toString(),
124
124
  mimeType: "application/json",
125
- text: JSON.stringify(schema2)
125
+ text: JSON.stringify(schema)
126
126
  }
127
127
  ]
128
128
  };
@@ -1310,10 +1310,10 @@ var getMultiPropsValue = (multiProps) => {
1310
1310
  // src/renderers/create-props-resolver.ts
1311
1311
  var TRANSFORM_DEPTH_LIMIT = 3;
1312
1312
  function createPropsResolver({ transformers, schema: initialSchema, onPropResolve }) {
1313
- async function resolve({ props, schema: schema2, signal, renderContext }) {
1314
- schema2 = schema2 ?? initialSchema;
1313
+ async function resolve({ props, schema, signal, renderContext }) {
1314
+ schema = schema ?? initialSchema;
1315
1315
  const promises = Promise.all(
1316
- Object.entries(schema2).map(async ([key, type]) => {
1316
+ Object.entries(schema).map(async ([key, type]) => {
1317
1317
  const value = props[key] ?? type.default;
1318
1318
  const transformed = await transform({ value, key, type, signal, renderContext });
1319
1319
  onPropResolve?.({ key, value: transformed, propValue: value, propType: type });
@@ -2037,6 +2037,40 @@ var dateTimeTransformer = createTransformer((values) => {
2037
2037
  }).join(" ");
2038
2038
  });
2039
2039
 
2040
+ // src/utils/sanitize-escaped-html.ts
2041
+ var import_dompurify = __toESM(require("dompurify"));
2042
+ var ALLOWED_NON_OPERATIONAL_ATTRS = [
2043
+ "href",
2044
+ "target",
2045
+ "class",
2046
+ "id",
2047
+ "style",
2048
+ "title",
2049
+ "lang",
2050
+ "dir",
2051
+ "role"
2052
+ ];
2053
+ function getAllowedHtmlWrapperTags() {
2054
+ return window.elementorCommon?.config?.allowedHTMLWrapperTags ?? [];
2055
+ }
2056
+ function sanitizeEscapedHtml(value) {
2057
+ if (!value) {
2058
+ return "";
2059
+ }
2060
+ const allowedTags = [...getAllowedHtmlWrapperTags()];
2061
+ return import_dompurify.default.sanitize(value, {
2062
+ ALLOWED_TAGS: allowedTags,
2063
+ ALLOWED_ATTR: [...ALLOWED_NON_OPERATIONAL_ATTRS],
2064
+ ALLOW_DATA_ATTR: true,
2065
+ ALLOW_ARIA_ATTR: true
2066
+ });
2067
+ }
2068
+
2069
+ // src/transformers/settings/escaped-html-transformer.ts
2070
+ var escapedHtmlTransformer = createTransformer((value) => {
2071
+ return sanitizeEscapedHtml(value);
2072
+ });
2073
+
2040
2074
  // src/transformers/settings/html-v2-transformer.ts
2041
2075
  var htmlV2Transformer = createTransformer((value) => {
2042
2076
  return value?.content ?? "";
@@ -2073,6 +2107,102 @@ var timeRangeTransformer = createTransformer((value) => {
2073
2107
  };
2074
2108
  });
2075
2109
 
2110
+ // src/transformers/shared/process-svg-content.ts
2111
+ var import_dompurify2 = __toESM(require("dompurify"));
2112
+ var SVG_INLINE_STYLES = "width: 100%; height: 100%; overflow: unset;";
2113
+ function processSvgContent(svgText) {
2114
+ const sanitized = import_dompurify2.default.sanitize(svgText, {
2115
+ USE_PROFILES: { svg: true, svgFilters: true }
2116
+ });
2117
+ const parser = new DOMParser();
2118
+ const doc = parser.parseFromString(sanitized, "image/svg+xml");
2119
+ const svgElement = doc.querySelector("svg");
2120
+ if (!svgElement) {
2121
+ return null;
2122
+ }
2123
+ svgElement.setAttribute("fill", "currentColor");
2124
+ const existingStyle = svgElement.getAttribute("style") ?? "";
2125
+ const trimmed = existingStyle.trim();
2126
+ const merged = trimmed ? `${trimmed.replace(/;$/, "")}; ${SVG_INLINE_STYLES}` : SVG_INLINE_STYLES;
2127
+ svgElement.setAttribute("style", merged);
2128
+ return svgElement.outerHTML;
2129
+ }
2130
+
2131
+ // src/transformers/shared/icon-transformer.ts
2132
+ var FONT_AWESOME_JSON = {
2133
+ width: 0,
2134
+ height: 1,
2135
+ path: 4
2136
+ };
2137
+ var fontAwesomeJsonCache = /* @__PURE__ */ new Map();
2138
+ var iconTransformer = createTransformer(async (value, { signal }) => {
2139
+ const iconValue = typeof value.value === "string" ? value.value : null;
2140
+ const library = typeof value.library === "string" ? value.library : null;
2141
+ if (!iconValue || !library) {
2142
+ return { html: null, url: null };
2143
+ }
2144
+ const iconName = getFontAwesomeIconName(iconValue);
2145
+ const jsonFileName = getFontAwesomeJsonFileName(library);
2146
+ if (!iconName || !jsonFileName) {
2147
+ return { html: null, url: null };
2148
+ }
2149
+ const icons = await fetchFontAwesomeIcons(jsonFileName, signal);
2150
+ const iconData = icons?.[iconName];
2151
+ if (!iconData) {
2152
+ return { html: null, url: null };
2153
+ }
2154
+ const svgText = buildFontAwesomeSvg(iconData);
2155
+ const html = processSvgContent(svgText);
2156
+ return { html, url: null };
2157
+ });
2158
+ function getFontAwesomeIconName(iconValue) {
2159
+ const match = iconValue.match(/^fa\S*\s+fa-(.+)$/);
2160
+ return match?.[1] ?? null;
2161
+ }
2162
+ function getFontAwesomeJsonFileName(library) {
2163
+ if (!library.startsWith("fa-")) {
2164
+ return null;
2165
+ }
2166
+ return library.replace(/^fa-/, "");
2167
+ }
2168
+ function getAssetsBaseUrl() {
2169
+ const assetsUrl = window.elementorCommon?.config?.urls?.assets;
2170
+ return typeof assetsUrl === "string" && assetsUrl !== "" ? assetsUrl : null;
2171
+ }
2172
+ async function fetchFontAwesomeIcons(jsonFileName, signal) {
2173
+ const cached = fontAwesomeJsonCache.get(jsonFileName);
2174
+ if (cached) {
2175
+ return cached;
2176
+ }
2177
+ const icons = await loadFontAwesomeIcons(jsonFileName, signal);
2178
+ if (icons) {
2179
+ fontAwesomeJsonCache.set(jsonFileName, icons);
2180
+ }
2181
+ return icons;
2182
+ }
2183
+ async function loadFontAwesomeIcons(jsonFileName, signal) {
2184
+ const assetsUrl = getAssetsBaseUrl();
2185
+ if (!assetsUrl) {
2186
+ return null;
2187
+ }
2188
+ try {
2189
+ const response = await fetch(`${assetsUrl}lib/font-awesome/json/${jsonFileName}.json`, { signal });
2190
+ if (!response.ok) {
2191
+ return null;
2192
+ }
2193
+ const data = await response.json();
2194
+ return data.icons ?? null;
2195
+ } catch {
2196
+ return null;
2197
+ }
2198
+ }
2199
+ function buildFontAwesomeSvg(iconData) {
2200
+ const width = iconData[FONT_AWESOME_JSON.width];
2201
+ const height = iconData[FONT_AWESOME_JSON.height];
2202
+ const path = iconData[FONT_AWESOME_JSON.path];
2203
+ return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${width} ${height}"><path d="${path}"></path></svg>`;
2204
+ }
2205
+
2076
2206
  // src/transformers/shared/image-src-transformer.ts
2077
2207
  var imageSrcTransformer = createTransformer((value) => ({
2078
2208
  id: value.id ?? null,
@@ -2114,26 +2244,7 @@ var plainTransformer = createTransformer((value) => {
2114
2244
  });
2115
2245
 
2116
2246
  // src/transformers/shared/svg-src-transformer.ts
2117
- var import_dompurify = __toESM(require("dompurify"));
2118
2247
  var import_wp_media2 = require("@elementor/wp-media");
2119
- var SVG_INLINE_STYLES = "width: 100%; height: 100%; overflow: unset;";
2120
- function processSvgContent(svgText) {
2121
- const sanitized = import_dompurify.default.sanitize(svgText, {
2122
- USE_PROFILES: { svg: true, svgFilters: true }
2123
- });
2124
- const parser = new DOMParser();
2125
- const doc = parser.parseFromString(sanitized, "image/svg+xml");
2126
- const svgElement = doc.querySelector("svg");
2127
- if (!svgElement) {
2128
- return null;
2129
- }
2130
- svgElement.setAttribute("fill", "currentColor");
2131
- const existingStyle = svgElement.getAttribute("style") ?? "";
2132
- const trimmed = existingStyle.trim();
2133
- const merged = trimmed ? `${trimmed.replace(/;$/, "")}; ${SVG_INLINE_STYLES}` : SVG_INLINE_STYLES;
2134
- svgElement.setAttribute("style", merged);
2135
- return svgElement.outerHTML;
2136
- }
2137
2248
  async function fetchSvgContent(url, signal) {
2138
2249
  try {
2139
2250
  const response = await fetch(url, { signal });
@@ -2189,7 +2300,7 @@ var videoSrcTransformer = createTransformer(async (value) => {
2189
2300
 
2190
2301
  // src/init-settings-transformers.ts
2191
2302
  function initSettingsTransformers() {
2192
- settingsTransformersRegistry.register("classes", createClassesTransformer()).register("link", linkTransformer).register("query", queryTransformer).register("image", imageTransformer).register("image-src", imageSrcTransformer).register("svg-src", svgSrcTransformer).register("video-src", videoSrcTransformer).register("attributes", attributesTransformer).register("date-time", dateTimeTransformer).register("html-v2", htmlV2Transformer).register("html-v3", htmlV3Transformer).register("date-range", dateRangeTransformer).register("time-range", timeRangeTransformer).registerFallback(plainTransformer);
2303
+ settingsTransformersRegistry.register("classes", createClassesTransformer()).register("link", linkTransformer).register("query", queryTransformer).register("image", imageTransformer).register("image-src", imageSrcTransformer).register("svg-src", svgSrcTransformer).register("icon", iconTransformer).register("video-src", videoSrcTransformer).register("attributes", attributesTransformer).register("date-time", dateTimeTransformer).register("html-v2", htmlV2Transformer).register("html-v3", htmlV3Transformer).register("escaped-html", escapedHtmlTransformer).register("date-range", dateRangeTransformer).register("time-range", timeRangeTransformer).registerFallback(plainTransformer);
2193
2304
  }
2194
2305
 
2195
2306
  // src/transformers/styles/background-color-overlay-transformer.ts
@@ -2466,11 +2577,11 @@ function getVal2(val) {
2466
2577
  var transformOriginTransformer = createTransformer((value) => {
2467
2578
  const x = getVal2(value.x);
2468
2579
  const y = getVal2(value.y);
2469
- const z5 = getVal2(value.z);
2470
- if (x === DEFAULT_XY && y === DEFAULT_XY && z5 === DEFAULT_Z) {
2580
+ const z3 = getVal2(value.z);
2581
+ if (x === DEFAULT_XY && y === DEFAULT_XY && z3 === DEFAULT_Z) {
2471
2582
  return null;
2472
2583
  }
2473
- return `${x} ${y} ${z5}`;
2584
+ return `${x} ${y} ${z3}`;
2474
2585
  });
2475
2586
 
2476
2587
  // src/transformers/styles/transform-rotate-transformer.ts
@@ -2548,13 +2659,13 @@ function initStyleTransformers() {
2548
2659
  "layout-direction",
2549
2660
  createMultiPropsTransformer(["row", "column"], ({ propKey, key }) => `${key}-${propKey}`)
2550
2661
  ).register("flex", flexTransformer).register(
2551
- "border-width",
2662
+ "border-width-v2",
2552
2663
  createMultiPropsTransformer(
2553
2664
  ["block-start", "block-end", "inline-start", "inline-end"],
2554
2665
  ({ key }) => `border-${key}-width`
2555
2666
  )
2556
2667
  ).register(
2557
- "border-radius",
2668
+ "border-radius-v2",
2558
2669
  createMultiPropsTransformer(
2559
2670
  ["start-start", "start-end", "end-start", "end-end"],
2560
2671
  ({ key }) => `border-${key}-radius`
@@ -2578,28 +2689,13 @@ function createDomRenderer() {
2578
2689
  render: environment.render
2579
2690
  };
2580
2691
  }
2692
+ function getAllowedHtmlWrapperTags2() {
2693
+ return window.elementorCommon?.config?.allowedHTMLWrapperTags ?? [];
2694
+ }
2581
2695
  function escapeHtmlTag(value) {
2582
- const allowedTags = [
2583
- "a",
2584
- "article",
2585
- "aside",
2586
- "button",
2587
- "div",
2588
- "footer",
2589
- "h1",
2590
- "h2",
2591
- "h3",
2592
- "h4",
2593
- "h5",
2594
- "h6",
2595
- "header",
2596
- "main",
2597
- "nav",
2598
- "p",
2599
- "section",
2600
- "span"
2601
- ];
2602
- return allowedTags.includes(value) ? value : "div";
2696
+ const allowedTags = getAllowedHtmlWrapperTags2();
2697
+ const normalizedTag = value?.toLowerCase?.() ?? "";
2698
+ return allowedTags.includes(normalizedTag) ? value : "div";
2603
2699
  }
2604
2700
  function escapeURL(value) {
2605
2701
  const allowedProtocols = ["http:", "https:", "mailto:", "tel:"];
@@ -2694,6 +2790,52 @@ function createElementViewClassDeclaration() {
2694
2790
  // src/legacy/create-nested-templated-element-type.ts
2695
2791
  var import_editor_elements6 = require("@elementor/editor-elements");
2696
2792
 
2793
+ // src/renderers/compute-html-tag.ts
2794
+ var DEFAULT_LINK_TAG = "a";
2795
+ function computeHtmlTag(settings, defaultTag, options = {}) {
2796
+ const followLink = options.followLink ?? true;
2797
+ if (followLink && settingsHaveActiveLink(settings)) {
2798
+ const link = settings.link;
2799
+ return extractLinkHtmlTag(isRecord(link) ? link : {});
2800
+ }
2801
+ const settingsTag = extractHtmlTagValue(settings.tag);
2802
+ if (null !== settingsTag && "" !== settingsTag) {
2803
+ return settingsTag;
2804
+ }
2805
+ return defaultTag;
2806
+ }
2807
+ function settingsHaveActiveLink(settings) {
2808
+ const link = settings.link;
2809
+ if (!isRecord(link)) {
2810
+ return false;
2811
+ }
2812
+ const href = extractHtmlTagValue(link.href);
2813
+ if (null !== href && "" !== href) {
2814
+ return true;
2815
+ }
2816
+ const attributes = link.attributes;
2817
+ return typeof attributes === "string" && "" !== attributes;
2818
+ }
2819
+ function extractLinkHtmlTag(link) {
2820
+ const tag = extractHtmlTagValue(link.tag);
2821
+ if (null !== tag && "" !== tag) {
2822
+ return tag;
2823
+ }
2824
+ return DEFAULT_LINK_TAG;
2825
+ }
2826
+ function extractHtmlTagValue(value) {
2827
+ if (isRecord(value) && typeof value.value === "string") {
2828
+ return value.value;
2829
+ }
2830
+ if (typeof value === "string") {
2831
+ return value;
2832
+ }
2833
+ return null;
2834
+ }
2835
+ function isRecord(value) {
2836
+ return typeof value === "object" && null !== value && !Array.isArray(value);
2837
+ }
2838
+
2697
2839
  // src/legacy/create-pending-element.ts
2698
2840
  var import_editor_elements5 = require("@elementor/editor-elements");
2699
2841
  function createPendingElement(wrapperView, data, options = {}) {
@@ -2754,7 +2896,13 @@ function setupTwigRenderer({ renderer, element }) {
2754
2896
  transformers: settingsTransformersRegistry,
2755
2897
  schema: element.atomic_props_schema
2756
2898
  });
2757
- return { templateKey, baseStylesDictionary, resolveProps };
2899
+ return {
2900
+ templateKey,
2901
+ baseStylesDictionary,
2902
+ resolveProps,
2903
+ defaultHtmlTag: element.default_html_tag ?? "div",
2904
+ htmlTagFollowsLink: element.html_tag_follows_link ?? true
2905
+ };
2758
2906
  }
2759
2907
  function createBeforeRender(view) {
2760
2908
  view._ensureViewIsIntact();
@@ -2794,7 +2942,7 @@ function createTemplatedElementView({
2794
2942
  element
2795
2943
  }) {
2796
2944
  const BaseView = createElementViewClassDeclaration();
2797
- const { templateKey, baseStylesDictionary, resolveProps } = setupTwigRenderer({
2945
+ const { templateKey, baseStylesDictionary, resolveProps, defaultHtmlTag, htmlTagFollowsLink } = setupTwigRenderer({
2798
2946
  type,
2799
2947
  renderer,
2800
2948
  element
@@ -2864,6 +3012,7 @@ function createTemplatedElementView({
2864
3012
  interaction_id: this.getInteractionId(),
2865
3013
  type,
2866
3014
  settings,
3015
+ tag: computeHtmlTag(settings, defaultHtmlTag, { followLink: htmlTagFollowsLink }),
2867
3016
  base_styles: baseStylesDictionary,
2868
3017
  ...this.getResolverRenderContext?.() ?? {}
2869
3018
  };
@@ -2953,7 +3102,7 @@ function createNestedTemplatedElementView({
2953
3102
  element
2954
3103
  }) {
2955
3104
  const legacyWindow = window;
2956
- const { templateKey, baseStylesDictionary, resolveProps } = setupTwigRenderer({
3105
+ const { templateKey, baseStylesDictionary, resolveProps, defaultHtmlTag, htmlTagFollowsLink } = setupTwigRenderer({
2957
3106
  type,
2958
3107
  renderer,
2959
3108
  element
@@ -3028,6 +3177,7 @@ function createNestedTemplatedElementView({
3028
3177
  interaction_id: this.getInteractionId(),
3029
3178
  type,
3030
3179
  settings: resolvedSettings,
3180
+ tag: computeHtmlTag(resolvedSettings, defaultHtmlTag, { followLink: htmlTagFollowsLink }),
3031
3181
  base_styles: baseStylesDictionary,
3032
3182
  editor_attributes: buildEditorAttributes(model),
3033
3183
  editor_classes: buildEditorClasses(model),
@@ -3531,7 +3681,7 @@ var import_editor_props3 = require("@elementor/editor-props");
3531
3681
  var hasKey = (propType) => {
3532
3682
  return "key" in propType;
3533
3683
  };
3534
- var TEXT_PROP_TYPE_KEYS = /* @__PURE__ */ new Set([import_editor_props3.htmlV3PropTypeUtil.key, import_editor_props3.stringPropTypeUtil.key]);
3684
+ var TEXT_PROP_TYPE_KEYS = /* @__PURE__ */ new Set([import_editor_props3.escapedHtmlPropTypeUtil.key, import_editor_props3.htmlV3PropTypeUtil.key, import_editor_props3.stringPropTypeUtil.key]);
3535
3685
  var isCoreTextPropTypeKey = (key) => {
3536
3686
  return TEXT_PROP_TYPE_KEYS.has(key);
3537
3687
  };
@@ -3551,7 +3701,7 @@ var isInlineEditingAllowed = ({ rawValue, propTypeFromSchema }) => {
3551
3701
  if (rawValue === null || rawValue === void 0) {
3552
3702
  return isAllowedBySchema(propTypeFromSchema);
3553
3703
  }
3554
- return import_editor_props3.htmlV3PropTypeUtil.isValid(rawValue) || import_editor_props3.stringPropTypeUtil.isValid(rawValue);
3704
+ return import_editor_props3.escapedHtmlPropTypeUtil.isValid(rawValue) || import_editor_props3.htmlV3PropTypeUtil.isValid(rawValue) || import_editor_props3.stringPropTypeUtil.isValid(rawValue);
3555
3705
  };
3556
3706
 
3557
3707
  // src/legacy/replacements/inline-editing/inline-editing-elements.tsx
@@ -3636,17 +3786,26 @@ var InlineEditingReplacement = class extends ReplacementBase {
3636
3786
  }
3637
3787
  getExtractedContentValue() {
3638
3788
  const propValue = this.getInlineEditablePropValue();
3789
+ if (import_editor_props4.escapedHtmlPropTypeUtil.isValid(propValue)) {
3790
+ return import_editor_props4.escapedHtmlPropTypeUtil.extract(propValue) ?? "";
3791
+ }
3639
3792
  const extracted = import_editor_props4.htmlV3PropTypeUtil.extract(propValue);
3640
3793
  return import_editor_props4.stringPropTypeUtil.extract(extracted?.content ?? null) ?? "";
3641
3794
  }
3795
+ createContentPropValue(value) {
3796
+ const content = value || "";
3797
+ const propTypeKey = this.getInlineEditablePropTypeKey();
3798
+ if (propTypeKey === import_editor_props4.htmlV3PropTypeUtil.key) {
3799
+ return import_editor_props4.htmlV3PropTypeUtil.create({
3800
+ content: import_editor_props4.stringPropTypeUtil.create(content),
3801
+ children: []
3802
+ });
3803
+ }
3804
+ return import_editor_props4.escapedHtmlPropTypeUtil.create(content);
3805
+ }
3642
3806
  setContentValue(value) {
3643
3807
  const settingKey = this.getInlineEditablePropertyName();
3644
- const html = value || "";
3645
- const parsed = (0, import_editor_props4.parseHtmlChildren)(html);
3646
- const valueToSave = import_editor_props4.htmlV3PropTypeUtil.create({
3647
- content: parsed.content ? import_editor_props4.stringPropTypeUtil.create(parsed.content) : null,
3648
- children: parsed.children
3649
- });
3808
+ const valueToSave = this.createContentPropValue(value);
3650
3809
  (0, import_editor_v1_adapters13.undoable)(
3651
3810
  {
3652
3811
  do: () => {
@@ -3675,7 +3834,7 @@ var InlineEditingReplacement = class extends ReplacementBase {
3675
3834
  return null;
3676
3835
  }
3677
3836
  if (propType.kind === "union") {
3678
- const textKeys = [import_editor_props4.htmlV3PropTypeUtil.key, import_editor_props4.stringPropTypeUtil.key];
3837
+ const textKeys = [import_editor_props4.escapedHtmlPropTypeUtil.key, import_editor_props4.htmlV3PropTypeUtil.key, import_editor_props4.stringPropTypeUtil.key];
3679
3838
  for (const key of textKeys) {
3680
3839
  if (propType.prop_types[key]) {
3681
3840
  return key;
@@ -3930,6 +4089,52 @@ function createNestedTemplatedType(type, renderer, element) {
3930
4089
  });
3931
4090
  }
3932
4091
 
4092
+ // src/legacy/list-type.ts
4093
+ var LIST_TYPE = "e-list";
4094
+ function initListType() {
4095
+ registerElementType(
4096
+ LIST_TYPE,
4097
+ (options) => createListType(options)
4098
+ );
4099
+ }
4100
+ function createListType(options) {
4101
+ const BaseType = createNestedTemplatedElementType(options);
4102
+ let ListView = null;
4103
+ return class extends BaseType {
4104
+ getView() {
4105
+ if (!ListView) {
4106
+ ListView = createListView(options);
4107
+ }
4108
+ return ListView;
4109
+ }
4110
+ };
4111
+ }
4112
+ function createListView(options) {
4113
+ const BaseView = createNestedTemplatedElementView(options);
4114
+ return BaseView.extend({
4115
+ getRenderContext() {
4116
+ const parentContext = this._parent?.getRenderContext?.();
4117
+ const settings = this.model.get("settings");
4118
+ const showMarkersProp = settings?.get?.("show_markers");
4119
+ const showMarkers = showMarkersProp?.value ?? showMarkersProp ?? true;
4120
+ return {
4121
+ ...parentContext,
4122
+ show_markers: showMarkers
4123
+ };
4124
+ },
4125
+ getResolverRenderContext() {
4126
+ const parentContext = this._parent?.getResolverRenderContext?.();
4127
+ const settings = this.model.get("settings");
4128
+ const showMarkersProp = settings?.get?.("show_markers");
4129
+ const showMarkers = showMarkersProp?.value ?? showMarkersProp ?? true;
4130
+ return {
4131
+ ...parentContext,
4132
+ show_markers: showMarkers
4133
+ };
4134
+ }
4135
+ });
4136
+ }
4137
+
3933
4138
  // src/legacy/tabs-model-extensions.ts
3934
4139
  var import_editor_props5 = require("@elementor/editor-props");
3935
4140
  var tabModelExtensions = {
@@ -3947,10 +4152,7 @@ var tabModelExtensions = {
3947
4152
  ...paragraphElement,
3948
4153
  settings: {
3949
4154
  ...paragraphElement.settings,
3950
- paragraph: import_editor_props5.htmlV3PropTypeUtil.create({
3951
- content: import_editor_props5.stringPropTypeUtil.create(`Tab ${position}`),
3952
- children: []
3953
- })
4155
+ paragraph: import_editor_props5.escapedHtmlPropTypeUtil.create(`Tab ${position}`)
3954
4156
  }
3955
4157
  };
3956
4158
  return [updatedParagraph, ...elements.slice(1)];
@@ -3961,22 +4163,22 @@ function initTabsModelExtensions() {
3961
4163
  }
3962
4164
 
3963
4165
  // src/mcp/canvas-mcp.ts
3964
- var import_editor_props9 = require("@elementor/editor-props");
4166
+ var import_editor_props8 = require("@elementor/editor-props");
3965
4167
 
3966
4168
  // src/mcp/resources/available-widgets-resource.ts
3967
4169
  var import_http_client3 = require("@elementor/http-client");
3968
4170
  var MCP_PROXY_URL2 = "elementor/v1/mcp-proxy";
3969
4171
  var AVAILABLE_WIDGETS_URI = "elementor://context/available-widgets";
3970
4172
  var AVAILABLE_WIDGETS_URI_V4 = "elementor://context/available-widgets/v4";
3971
- var fetchWidgets = async (version) => {
4173
+ var fetchWidgets = async () => {
3972
4174
  const { data } = await (0, import_http_client3.httpService)().post(MCP_PROXY_URL2, {
3973
- tool: "list-widgets",
3974
- input: version ? { version } : {}
4175
+ tool: "list-widget-schemas",
4176
+ input: { summary: true }
3975
4177
  });
3976
- return data.data ?? [];
4178
+ return data.data?.widgets ?? [];
3977
4179
  };
3978
- var buildContents = async (uri, version) => {
3979
- const widgets = await fetchWidgets(version);
4180
+ var buildContents = async (uri) => {
4181
+ const widgets = await fetchWidgets();
3980
4182
  return {
3981
4183
  contents: [
3982
4184
  {
@@ -3995,13 +4197,13 @@ var initAvailableWidgetsResource = (reg) => {
3995
4197
  {
3996
4198
  description: "All registered v4 version widgets"
3997
4199
  },
3998
- async () => buildContents(AVAILABLE_WIDGETS_URI_V4, "v4")
4200
+ async () => buildContents(AVAILABLE_WIDGETS_URI_V4)
3999
4201
  );
4000
4202
  resource(
4001
4203
  "available-widgets",
4002
4204
  AVAILABLE_WIDGETS_URI,
4003
4205
  {
4004
- description: "All registered widget types with v3/v4 version metadata and description."
4206
+ description: "All registered v4 widget types with description."
4005
4207
  },
4006
4208
  async () => buildContents(AVAILABLE_WIDGETS_URI)
4007
4209
  );
@@ -4134,11 +4336,10 @@ var import_http_client5 = require("@elementor/http-client");
4134
4336
  var DYNAMIC_TAGS_URI = "elementor://dynamic-tags";
4135
4337
  var MCP_PROXY_URL4 = "elementor/v1/mcp-proxy";
4136
4338
  var fetchDynamicTags = async () => {
4137
- const { data } = await (0, import_http_client5.httpService)().post(MCP_PROXY_URL4, {
4138
- tool: "list-dynamic-tags",
4139
- input: {}
4339
+ const { data } = await (0, import_http_client5.httpService)().get(MCP_PROXY_URL4, {
4340
+ params: { uri: DYNAMIC_TAGS_URI }
4140
4341
  });
4141
- return data.data ?? [];
4342
+ return data.data ?? "[]";
4142
4343
  };
4143
4344
  var initDynamicTagsResource = (reg) => {
4144
4345
  const { resource } = reg;
@@ -4150,13 +4351,12 @@ var initDynamicTagsResource = (reg) => {
4150
4351
  mimeType: "application/json"
4151
4352
  },
4152
4353
  async (uri) => {
4153
- const tags = await fetchDynamicTags();
4154
4354
  return {
4155
4355
  contents: [
4156
4356
  {
4157
4357
  uri: uri.href,
4158
4358
  mimeType: "application/json",
4159
- text: JSON.stringify(tags)
4359
+ text: await fetchDynamicTags()
4160
4360
  }
4161
4361
  ]
4162
4362
  };
@@ -4479,104 +4679,13 @@ function getElementDisplayName(container) {
4479
4679
  }
4480
4680
  }
4481
4681
 
4482
- // src/mcp/tools/build-composition/tool.ts
4483
- var import_editor_documents2 = require("@elementor/editor-documents");
4484
- var import_editor_elements11 = require("@elementor/editor-elements");
4485
- var import_http_client6 = require("@elementor/http-client");
4486
- var import_schema = require("@elementor/schema");
4487
- var MCP_PROXY_URL5 = "elementor/v1/mcp-proxy";
4488
- var initBuildCompositionTool = (reg) => {
4489
- const { addTool } = reg;
4490
- addTool({
4491
- name: "build-composition",
4492
- description: "Build a V4 element composition on the Elementor canvas via the server-side MCP ability. Pass the raw XML tags directly as xmlStructure \u2014 do NOT wrap the value in <![CDATA[ ... ]]>, code fences, or quotes. The document is saved as a draft. Reload the editor after calling this tool to see the result.",
4493
- schema: {
4494
- xmlStructure: import_schema.z.string().describe(
4495
- 'Valid XML structure with custom Elementor widget tags. Every element MUST have a unique configuration-id attribute (e.g. <e-heading configuration-id="hero-title"></e-heading>). No attributes, classes, IDs, or text nodes in XML. Pass raw XML \u2014 do not wrap in CDATA.'
4496
- ),
4497
- elementConfig: import_schema.z.record(
4498
- import_schema.z.string().describe("configuration-id"),
4499
- import_schema.z.record(import_schema.z.string().describe("property name"), import_schema.z.any().describe("PropValue"))
4500
- ).optional().describe("Map configuration-id \u2192 widget PropValues ($$type + value)."),
4501
- style: import_schema.z.record(
4502
- import_schema.z.string().describe("configuration-id"),
4503
- import_schema.z.record(import_schema.z.string().describe("CSS property name"), import_schema.z.string().describe("CSS value"))
4504
- ).optional().describe(
4505
- "Map configuration-id \u2192 raw CSS declarations (property \u2192 value strings; no selectors). Server converts to native styles; unconvertible declarations become the element custom CSS."
4506
- ),
4507
- parentId: import_schema.z.string().optional().describe("ID of the parent container. Omit or pass 'document' to insert at document root."),
4508
- dryRun: import_schema.z.boolean().optional().describe("If true, validate and return the resolved tree without persisting.")
4509
- },
4510
- outputSchema: {
4511
- rootElementIds: import_schema.z.array(import_schema.z.string()),
4512
- previewUrl: import_schema.z.string(),
4513
- version: import_schema.z.string(),
4514
- resolvedXml: import_schema.z.string(),
4515
- llmInstructions: import_schema.z.string(),
4516
- warnings: import_schema.z.array(import_schema.z.string()).optional()
4517
- },
4518
- handler: async ({ xmlStructure, elementConfig, style, parentId, dryRun }) => {
4519
- const document2 = (0, import_editor_documents2.getCurrentDocument)();
4520
- if (!document2?.id) {
4521
- throw new Error("No active document found.");
4522
- }
4523
- try {
4524
- const { data } = await (0, import_http_client6.httpService)().post(MCP_PROXY_URL5, {
4525
- tool: "build-composition",
4526
- input: {
4527
- post_id: document2.id,
4528
- xml_structure: xmlStructure,
4529
- element_config: elementConfig ?? {},
4530
- style: style ?? {},
4531
- parent_id: parentId ?? "document",
4532
- dry_run: dryRun ?? false
4533
- }
4534
- });
4535
- if (!dryRun) {
4536
- await (0, import_editor_documents2.reloadCurrentDocument)();
4537
- const [firstRootId] = data.data.root_element_ids;
4538
- if (firstRootId) {
4539
- (0, import_editor_elements11.selectElement)(firstRootId);
4540
- (0, import_editor_elements11.getContainer)(firstRootId)?.view?.el?.scrollIntoView({
4541
- behavior: "smooth",
4542
- block: "center"
4543
- });
4544
- }
4545
- }
4546
- return {
4547
- rootElementIds: data.data.root_element_ids,
4548
- previewUrl: data.data.preview_url,
4549
- version: data.data.version,
4550
- resolvedXml: data.data.resolved_xml,
4551
- llmInstructions: data.data.llm_instructions,
4552
- warnings: data.data.warnings
4553
- };
4554
- } catch (error) {
4555
- throw new Error(getErrorMessage(error));
4556
- }
4557
- }
4558
- });
4559
- };
4560
- function getErrorMessage(error) {
4561
- if (error instanceof import_http_client6.AxiosError) {
4562
- const data = error.response?.data;
4563
- if (data?.message) {
4564
- return data.code ? `${data.code}: ${data.message}` : data.message;
4565
- }
4566
- }
4567
- if (error instanceof Error) {
4568
- return error.message;
4569
- }
4570
- return "build-composition failed with an unknown error.";
4571
- }
4572
-
4573
4682
  // src/mcp/tools/configure-element/tool.ts
4574
- var import_editor_elements14 = require("@elementor/editor-elements");
4683
+ var import_editor_elements13 = require("@elementor/editor-elements");
4575
4684
  var import_editor_mcp3 = require("@elementor/editor-mcp");
4576
4685
  var import_editor_props7 = require("@elementor/editor-props");
4577
4686
 
4578
4687
  // src/mcp/utils/do-update-element-property.ts
4579
- var import_editor_elements13 = require("@elementor/editor-elements");
4688
+ var import_editor_elements12 = require("@elementor/editor-elements");
4580
4689
  var import_editor_props6 = require("@elementor/editor-props");
4581
4690
  var import_editor_styles4 = require("@elementor/editor-styles");
4582
4691
  var import_editor_v1_adapters20 = require("@elementor/editor-v1-adapters");
@@ -4596,10 +4705,10 @@ var readStoredCustomCssText = (raw) => {
4596
4705
  };
4597
4706
 
4598
4707
  // src/mcp/utils/resolve-canonical-prop-name.ts
4599
- var import_editor_elements12 = require("@elementor/editor-elements");
4600
- function buildAliasToCanonicalMap(schema2) {
4708
+ var import_editor_elements11 = require("@elementor/editor-elements");
4709
+ function buildAliasToCanonicalMap(schema) {
4601
4710
  const aliasToCanonical = {};
4602
- for (const [canonical, propType] of Object.entries(schema2)) {
4711
+ for (const [canonical, propType] of Object.entries(schema)) {
4603
4712
  const aliases = propType.meta?.aliases;
4604
4713
  if (!Array.isArray(aliases)) {
4605
4714
  continue;
@@ -4613,26 +4722,26 @@ function buildAliasToCanonicalMap(schema2) {
4613
4722
  return aliasToCanonical;
4614
4723
  }
4615
4724
  function resolveCanonicalPropName(elementType, propertyName) {
4616
- const schema2 = (0, import_editor_elements12.getWidgetsCache)()?.[elementType]?.atomic_props_schema;
4617
- if (!schema2 || schema2[propertyName]) {
4725
+ const schema = (0, import_editor_elements11.getWidgetsCache)()?.[elementType]?.atomic_props_schema;
4726
+ if (!schema || schema[propertyName]) {
4618
4727
  return propertyName;
4619
4728
  }
4620
- return buildAliasToCanonicalMap(schema2)[propertyName] ?? propertyName;
4729
+ return buildAliasToCanonicalMap(schema)[propertyName] ?? propertyName;
4621
4730
  }
4622
4731
  function resolveCanonicalPropKeys(elementType, props) {
4623
- const schema2 = (0, import_editor_elements12.getWidgetsCache)()?.[elementType]?.atomic_props_schema;
4624
- if (!schema2) {
4732
+ const schema = (0, import_editor_elements11.getWidgetsCache)()?.[elementType]?.atomic_props_schema;
4733
+ if (!schema) {
4625
4734
  return { ...props };
4626
4735
  }
4627
- const aliasToCanonical = buildAliasToCanonicalMap(schema2);
4736
+ const aliasToCanonical = buildAliasToCanonicalMap(schema);
4628
4737
  const resolved = {};
4629
4738
  for (const [key, value] of Object.entries(props)) {
4630
- if (schema2[key]) {
4739
+ if (schema[key]) {
4631
4740
  resolved[key] = value;
4632
4741
  }
4633
4742
  }
4634
4743
  for (const [key, value] of Object.entries(props)) {
4635
- if (schema2[key]) {
4744
+ if (schema[key]) {
4636
4745
  continue;
4637
4746
  }
4638
4747
  const canonical = aliasToCanonical[key];
@@ -4680,9 +4789,9 @@ var dynamicTagLLMResolver = (value) => {
4680
4789
  }
4681
4790
  };
4682
4791
  };
4683
- var buildStrictSettings = (schema2, provided) => {
4792
+ var buildStrictSettings = (schema, provided) => {
4684
4793
  const settings = {};
4685
- for (const [key, propType] of Object.entries(schema2)) {
4794
+ for (const [key, propType] of Object.entries(schema)) {
4686
4795
  if (OMITTED_DYNAMIC_SETTING_KEYS.includes(key)) {
4687
4796
  continue;
4688
4797
  }
@@ -4714,6 +4823,20 @@ var LOCAL_STYLE_META = {
4714
4823
  breakpoint: "desktop",
4715
4824
  state: null
4716
4825
  };
4826
+ var UnsupportedPropertyError = class extends Error {
4827
+ elementType;
4828
+ propertyName;
4829
+ constructor(elementType, propertyName, availableProperties) {
4830
+ super(
4831
+ `Property "${propertyName}" does not exist on element type "${elementType}". Available properties are: ${availableProperties.join(
4832
+ ", "
4833
+ )}`
4834
+ );
4835
+ this.name = "UnsupportedPropertyError";
4836
+ this.elementType = elementType;
4837
+ this.propertyName = propertyName;
4838
+ }
4839
+ };
4717
4840
  function resolvePropValue(value, forceKey) {
4718
4841
  const Utils = window.elementorV2.editorVariables.Utils;
4719
4842
  return import_editor_props6.Schema.adjustLlmPropValueSchema(value, {
@@ -4728,7 +4851,7 @@ var doUpdateElementProperty = (params) => {
4728
4851
  const { elementId, propertyValue, elementType, customCssWriteMode = "replace" } = params;
4729
4852
  const propertyName = params.propertyName === "_styles" ? params.propertyName : resolveCanonicalPropName(elementType, params.propertyName);
4730
4853
  if (propertyName === "_styles") {
4731
- const elementStyles = (0, import_editor_elements13.getElementStyles)(elementId) || {};
4854
+ const elementStyles = (0, import_editor_elements12.getElementStyles)(elementId) || {};
4732
4855
  const propertyMapValue = propertyValue;
4733
4856
  const styleSchema = (0, import_editor_styles4.getStylesSchema)();
4734
4857
  const transformedStyleValues = Object.fromEntries(
@@ -4785,7 +4908,7 @@ var doUpdateElementProperty = (params) => {
4785
4908
  });
4786
4909
  delete transformedStyleValues.custom_css;
4787
4910
  if (!localStyle) {
4788
- (0, import_editor_elements13.createElementStyle)({
4911
+ (0, import_editor_elements12.createElementStyle)({
4789
4912
  elementId,
4790
4913
  ...typeof customCss !== "undefined" ? { custom_css: customCss } : {},
4791
4914
  classesProp: "classes",
@@ -4799,7 +4922,7 @@ var doUpdateElementProperty = (params) => {
4799
4922
  }
4800
4923
  });
4801
4924
  } else {
4802
- (0, import_editor_elements13.updateElementStyle)({
4925
+ (0, import_editor_elements12.updateElementStyle)({
4803
4926
  elementId,
4804
4927
  styleId: localStyle.id,
4805
4928
  meta: {
@@ -4814,17 +4937,12 @@ var doUpdateElementProperty = (params) => {
4814
4937
  }
4815
4938
  return;
4816
4939
  }
4817
- const elementPropSchema = (0, import_editor_elements13.getWidgetsCache)()?.[elementType]?.atomic_props_schema;
4940
+ const elementPropSchema = (0, import_editor_elements12.getWidgetsCache)()?.[elementType]?.atomic_props_schema;
4818
4941
  if (!elementPropSchema) {
4819
4942
  throw new Error(`No prop schema found for element type: ${elementType}`);
4820
4943
  }
4821
4944
  if (!elementPropSchema[propertyName]) {
4822
- const propertyNames = Object.keys(elementPropSchema);
4823
- throw new Error(
4824
- `Property "${propertyName}" does not exist on element type "${elementType}". Available properties are: ${propertyNames.join(
4825
- ", "
4826
- )}`
4827
- );
4945
+ throw new UnsupportedPropertyError(elementType, propertyName, Object.keys(elementPropSchema));
4828
4946
  }
4829
4947
  const propKey = elementPropSchema[propertyName].key;
4830
4948
  const value = resolvePropValue(propertyValue, propKey);
@@ -4837,7 +4955,7 @@ var doUpdateElementProperty = (params) => {
4837
4955
  Expected Schema: ${jsonSchema}`
4838
4956
  );
4839
4957
  }
4840
- (0, import_editor_elements13.updateElementSettings)({
4958
+ (0, import_editor_elements12.updateElementSettings)({
4841
4959
  id: elementId,
4842
4960
  props: {
4843
4961
  [propertyName]: value
@@ -4894,8 +5012,6 @@ For all non-primitive entries in \`propertiesToChange\`, provide the schema \`ke
4894
5012
 
4895
5013
  Use the EXACT PropType schema given, and ALWAYS include the \`key\` from the schema for every property you are changing in \`propertiesToChange\`.
4896
5014
 
4897
- Check \`llm_guidance.default_settings\` in the widget schema \u2014 include a key in \`propertiesToChange\` only when the user explicitly asks to change it.
4898
-
4899
5015
  # Dynamic tags
4900
5016
  A value can be made dynamic wherever its schema exposes a variant with "$$type": "dynamic". This may be the property root OR a NESTED field: for example an image is made dynamic on its "src" (the root stays "image"), NOT on the whole "image" value.
4901
5017
  Put the dynamic object EXACTLY at the node whose schema offers the "dynamic" variant, in place of the static variant. The variant's "name" enumerates the tags allowed at that node.
@@ -4922,7 +5038,7 @@ Do NOT send "group" (it is resolved automatically). Use { "settings": {} } only
4922
5038
  );
4923
5039
  configureElementToolPrompt.parameter(
4924
5040
  "style",
4925
- 'A flat map of raw CSS declarations (property \u2192 value), e.g. { "line-height": "1.25rem", "color": "var(--primary-text, #000)" }. Set a value to null to reset that property to its default. OPTIONAL.'
5041
+ 'A flat map of raw CSS declarations (property \u2192 value), e.g. { "line-height": "1.25rem", "color": "var(--primary-text, #000)" }. font-family must be a single Google Font name or a var(--label) \u2014 no fallback stacks. Set a value to null to reset that property to its default. OPTIONAL.'
4926
5042
  );
4927
5043
  configureElementToolPrompt.example(`
4928
5044
  \`\`\`json
@@ -4954,36 +5070,39 @@ Do NOT send "group" (it is resolved automatically). Use { "settings": {} } only
4954
5070
  V4 only: If MCP fails, give manual steps using V4 UI.
4955
5071
 
4956
5072
  V4 Editor structure:
4957
- Panel tabs: General (\u2192 Settings section: ID, Tag, Link), Style, Interactions.
5073
+ Panel tabs: General (\u2192 Settings section: ID, Tag, and Link where the widget supports it), Style, Interactions.
4958
5074
  NO Advanced tab. Never mention Advanced tab.
5075
+ Note: \`link\` is valid only when the element's PropType schema (which you must already have) includes a \`link\` property. Sending \`link\` to a widget whose schema lacks it is skipped and reported in the response \`warnings\` (other changes still apply) and the link is lost.
4959
5076
  `);
4960
5077
  return configureElementToolPrompt.prompt();
4961
5078
  };
4962
- var CONFIGURE_ELEMENT_GUIDE_TEXT = generatePrompt();
4963
5079
 
4964
5080
  // src/mcp/tools/configure-element/schema.ts
4965
- var import_schema2 = require("@elementor/schema");
5081
+ var import_schema = require("@elementor/schema");
4966
5082
  var inputSchema = {
4967
- propertiesToChange: import_schema2.z.record(
4968
- import_schema2.z.string().describe("The property name."),
4969
- import_schema2.z.any().describe(`PropValue, refer to [${WIDGET_SCHEMA_URI}] by correct type, as appears in elementType`),
4970
- import_schema2.z.any()
5083
+ propertiesToChange: import_schema.z.record(
5084
+ import_schema.z.string().describe("The property name."),
5085
+ import_schema.z.any().describe(`PropValue, refer to [${WIDGET_SCHEMA_URI}] by correct type, as appears in elementType`),
5086
+ import_schema.z.any()
4971
5087
  ).describe("An object record containing property names and their new values to be set on the element"),
4972
- style: import_schema2.z.record(
4973
- import_schema2.z.string().describe('A CSS property name, e.g. "color", "margin-top".'),
4974
- import_schema2.z.string().nullable().describe(
5088
+ style: import_schema.z.record(
5089
+ import_schema.z.string().describe('A CSS property name, e.g. "color", "margin-top".'),
5090
+ import_schema.z.string().nullable().describe(
4975
5091
  'A CSS value, e.g. "red", "10px", "1px solid #000". Use null to reset the property to its default.'
4976
5092
  )
4977
5093
  ).describe(
4978
5094
  "Raw CSS declarations as a flat property\u2192value map. Converted to native styles server-side; any declaration that cannot be converted is stored as the element custom CSS. A null value resets that property to its default."
4979
5095
  ).default({}),
4980
- elementType: import_schema2.z.string().describe("The type of the element to retrieve the schema"),
4981
- elementId: import_schema2.z.string().describe("The unique id of the element to configure")
5096
+ elementType: import_schema.z.string().describe("The type of the element to retrieve the schema"),
5097
+ elementId: import_schema.z.string().describe("The unique id of the element to configure")
4982
5098
  };
4983
5099
  var outputSchema = {
4984
- success: import_schema2.z.boolean().describe(
5100
+ success: import_schema.z.boolean().describe(
4985
5101
  "Whether the configuration change was successful, only if propertyName and propertyValue are provided"
4986
- )
5102
+ ),
5103
+ warnings: import_schema.z.string().describe(
5104
+ 'Non-fatal notices. Present when some props were skipped because they are not in the element schema (e.g. a "link" on a widget with no link prop). Other changes were still applied.'
5105
+ ).optional()
4987
5106
  };
4988
5107
 
4989
5108
  // src/mcp/tools/configure-element/tool.ts
@@ -5012,13 +5131,13 @@ var initConfigureElementTool = (reg) => {
5012
5131
  { description: "Dynamic tags catalog", uri: DYNAMIC_TAGS_URI }
5013
5132
  ],
5014
5133
  handler: async ({ elementId, propertiesToChange, elementType, style }) => {
5015
- const widgetData = (0, import_editor_elements14.getWidgetsCache)()?.[elementType];
5134
+ const widgetData = (0, import_editor_elements13.getWidgetsCache)()?.[elementType];
5016
5135
  if (!widgetData) {
5017
5136
  throw new Error(
5018
5137
  `Unknown element type: ${elementType}. Check the available-widgets resource for valid types.`
5019
5138
  );
5020
5139
  }
5021
- const container = (0, import_editor_elements14.getContainer)(elementId);
5140
+ const container = (0, import_editor_elements13.getContainer)(elementId);
5022
5141
  if (!container) {
5023
5142
  throw new Error(`Element with id ${elementId} not found`);
5024
5143
  }
@@ -5033,6 +5152,7 @@ var initConfigureElementTool = (reg) => {
5033
5152
  }
5034
5153
  const propertiesToUpdate = resolveCanonicalPropKeys(elementType, propertiesToChange);
5035
5154
  const toUpdate = Object.entries(propertiesToUpdate);
5155
+ const skippedProps = [];
5036
5156
  for (const [propertyName, propertyValue] of toUpdate) {
5037
5157
  if (!import_editor_props7.Schema.isPropKeyConfigurable(propertyName)) {
5038
5158
  throw new Error(`Not allowed to update ${propertyName}`);
@@ -5045,6 +5165,10 @@ var initConfigureElementTool = (reg) => {
5045
5165
  propertyValue
5046
5166
  });
5047
5167
  } catch (error) {
5168
+ if (error instanceof UnsupportedPropertyError) {
5169
+ skippedProps.push(error.propertyName);
5170
+ continue;
5171
+ }
5048
5172
  const errorMessage = createUpdateErrorMessage({
5049
5173
  propertyName,
5050
5174
  elementId,
@@ -5057,7 +5181,10 @@ var initConfigureElementTool = (reg) => {
5057
5181
  }
5058
5182
  await applyStyleFromCss({ elementId, elementType, style });
5059
5183
  return {
5060
- success: true
5184
+ success: true,
5185
+ warnings: skippedProps.length ? `Skipped unsupported props (not in the "${elementType}" schema; other changes were applied): ${skippedProps.join(
5186
+ ", "
5187
+ )}.` : void 0
5061
5188
  };
5062
5189
  }
5063
5190
  });
@@ -5109,143 +5236,74 @@ Provide styling as raw CSS via the "style" parameter (a flat map of CSS property
5109
5236
  }`;
5110
5237
  }
5111
5238
 
5112
- // src/mcp/tools/create-element/tool.ts
5113
- var import_editor_documents3 = require("@elementor/editor-documents");
5239
+ // src/mcp/tools/get-page-structure/tool.ts
5240
+ var import_editor_documents2 = require("@elementor/editor-documents");
5114
5241
  var import_http_client7 = require("@elementor/http-client");
5115
- var import_schema4 = require("@elementor/schema");
5116
- var MCP_PROXY_URL6 = "elementor/v1/mcp-proxy";
5117
- var initCreateElementTool = (reg) => {
5242
+ var import_schema3 = require("@elementor/schema");
5243
+
5244
+ // src/mcp/utils/get-mcp-error-message.ts
5245
+ var import_http_client6 = require("@elementor/http-client");
5246
+ function getMcpErrorMessage(error, toolName) {
5247
+ if (error instanceof import_http_client6.AxiosError) {
5248
+ const data = error.response?.data;
5249
+ if (data?.message) {
5250
+ return data.code ? `${data.code}: ${data.message}` : data.message;
5251
+ }
5252
+ }
5253
+ if (error instanceof Error) {
5254
+ return error.message;
5255
+ }
5256
+ return `${toolName} failed with an unknown error.`;
5257
+ }
5258
+
5259
+ // src/mcp/tools/get-page-structure/tool.ts
5260
+ var MCP_PROXY_URL5 = "elementor/v1/mcp-proxy";
5261
+ var initGetPageStructureTool = (reg) => {
5118
5262
  const { addTool } = reg;
5119
5263
  addTool({
5120
- name: "create-element",
5121
- description: "Insert a new element into the current Elementor document via the server-side MCP ability. The document is saved as a draft. Reload the editor after calling this tool to see the result.",
5264
+ name: "get-page-structure",
5265
+ description: "Returns a lean Elementor element tree skeleton (id, elType, widgetType, title, nested elements) for a post or page. If no postId is provided, uses the currently open document. Optionally scope to a subtree with elementId. Set includeContent=true (requires elementId) to also return each node's settings and styles.",
5122
5266
  schema: {
5123
- elementType: import_schema4.z.string().describe("Registry identifier of the element to create, e.g. 'e-heading', 'e-flexbox'."),
5124
- parentId: import_schema4.z.string().optional().describe("ID of the parent container. Omit or pass 'document' to insert at the document root.")
5267
+ postId: import_schema3.z.number().optional().describe(
5268
+ "WordPress post ID of the Elementor document. If omitted, uses the currently open document."
5269
+ ),
5270
+ elementId: import_schema3.z.string().optional().describe("If provided, returns only the subtree rooted at that element id."),
5271
+ includeContent: import_schema3.z.boolean().optional().describe(
5272
+ "If true, includes each node's settings and styles (same shape build-composition accepts as input). Requires elementId."
5273
+ )
5125
5274
  },
5126
5275
  outputSchema: {
5127
- elementId: import_schema4.z.string(),
5128
- previewUrl: import_schema4.z.string(),
5129
- version: import_schema4.z.string()
5276
+ elements: import_schema3.z.array(import_schema3.z.any()).describe(
5277
+ "Skeleton of Elementor elements (id, elType, widgetType, title, nested elements). When includeContent is true, each node also includes settings and styles."
5278
+ )
5130
5279
  },
5131
- handler: async ({ elementType, parentId }) => {
5132
- const document2 = (0, import_editor_documents3.getCurrentDocument)();
5133
- if (!document2?.id) {
5134
- throw new Error("No active document found.");
5135
- }
5136
- const { data } = await (0, import_http_client7.httpService)().post(MCP_PROXY_URL6, {
5137
- tool: "create-element",
5138
- input: {
5139
- parent_id: parentId ?? "document",
5140
- element: { type: elementType },
5141
- post_id: document2.id
5142
- }
5143
- });
5144
- return {
5145
- elementId: data.data.element_id,
5146
- previewUrl: data.data.preview_url,
5147
- version: data.data.version
5148
- };
5149
- }
5150
- });
5151
- };
5152
-
5153
- // src/mcp/tools/get-element-config/tool.ts
5154
- var import_editor_elements15 = require("@elementor/editor-elements");
5155
- var import_editor_props8 = require("@elementor/editor-props");
5156
- var import_schema5 = require("@elementor/schema");
5157
- var schema = {
5158
- elementId: import_schema5.z.string()
5159
- };
5160
- var outputSchema2 = {
5161
- properties: import_schema5.z.record(import_schema5.z.string(), import_schema5.z.any()).describe("A record mapping PropTypes to their corresponding PropValues"),
5162
- style: import_schema5.z.record(import_schema5.z.string(), import_schema5.z.any()).describe("A record mapping StyleSchema properties to their corresponding PropValues"),
5163
- childElements: import_schema5.z.array(
5164
- import_schema5.z.object({
5165
- id: import_schema5.z.string(),
5166
- elementType: import_schema5.z.string(),
5167
- childElements: import_schema5.z.array(import_schema5.z.any()).describe("An array of child element IDs, when applicable, same structure recursively")
5168
- })
5169
- ).describe("An array of child element IDs, when applicable, with recursive structure")
5170
- };
5171
- var structuredElements = (element) => {
5172
- const children = element.children || [];
5173
- return children.map((child) => {
5174
- return {
5175
- id: child.id,
5176
- elementType: child.model.get("elType") || child.model.get("widgetType") || "unknown",
5177
- childElements: structuredElements(child)
5178
- };
5179
- });
5180
- };
5181
- var initGetElementConfigTool = (reg) => {
5182
- const { addTool } = reg;
5183
- addTool({
5184
- name: "get-element-configuration-values",
5185
- description: "Retrieve the element's configuration PropValues for a specific element by unique ID.",
5186
- schema,
5187
- outputSchema: outputSchema2,
5188
- handler: async ({ elementId }) => {
5189
- const element = (0, import_editor_elements15.getContainer)(elementId);
5190
- if (!element) {
5191
- throw new Error(`Element with ID ${elementId} not found.`);
5192
- }
5193
- const elementType = element.model.get("widgetType") || element.model.get("elType") || "";
5194
- const widgetData = (0, import_editor_elements15.getWidgetsCache)()?.[elementType];
5195
- if (!widgetData) {
5196
- throw new Error(
5197
- `Unknown element type: ${elementType}. Check the available-widgets resource for valid types.`
5198
- );
5199
- }
5200
- if (!widgetData.atomic_props_schema) {
5201
- throw new Error(
5202
- `This tool does not support V3 elements. Please use the elementor-v3-mcp tools instead for element type: ${elementType}`
5203
- );
5204
- }
5205
- const elementRawSettings = element.settings;
5206
- const propSchema = (0, import_editor_elements15.getWidgetsCache)()?.[elementType]?.atomic_props_schema;
5207
- if (!elementRawSettings || !propSchema) {
5208
- throw new Error(`No settings or prop schema found for element ID: ${elementId}`);
5280
+ handler: async ({ postId, elementId, includeContent }) => {
5281
+ const resolvedPostId = postId ?? (0, import_editor_documents2.getCurrentDocument)()?.id;
5282
+ if (!resolvedPostId) {
5283
+ throw new Error("No post ID provided and no active document found.");
5209
5284
  }
5210
- const propValues = {};
5211
- const stylePropValues = {};
5212
- import_editor_props8.Schema.configurableKeys(propSchema).forEach((key) => {
5213
- propValues[key] = structuredClone(elementRawSettings.get(key));
5214
- });
5215
- const elementStyles = (0, import_editor_elements15.getElementStyles)(elementId) || {};
5216
- const localStyle = Object.values(elementStyles).find((style) => style.label === "local");
5217
- if (localStyle) {
5218
- const defaultVariant = localStyle.variants.find(
5219
- (variant) => variant.meta.breakpoint === "desktop" && !variant.meta.state
5220
- );
5221
- if (defaultVariant) {
5222
- const styleProps = defaultVariant.props || {};
5223
- Object.keys(styleProps).forEach((stylePropName) => {
5224
- if (typeof styleProps[stylePropName] !== "undefined") {
5225
- stylePropValues[stylePropName] = structuredClone(styleProps[stylePropName]);
5226
- }
5227
- });
5228
- if (defaultVariant.custom_css) {
5229
- stylePropValues.custom_css = atob(defaultVariant.custom_css.raw);
5285
+ try {
5286
+ const { data } = await (0, import_http_client7.httpService)().post(MCP_PROXY_URL5, {
5287
+ tool: "get-page-structure",
5288
+ input: {
5289
+ post_id: resolvedPostId,
5290
+ ...elementId ? { element_id: elementId } : {},
5291
+ ...includeContent ? { include_content: true } : {}
5230
5292
  }
5231
- }
5293
+ });
5294
+ return {
5295
+ elements: data.data.elements
5296
+ };
5297
+ } catch (error) {
5298
+ throw new Error(getMcpErrorMessage(error, "get-page-structure"));
5232
5299
  }
5233
- return {
5234
- properties: {
5235
- ...propValues
5236
- },
5237
- style: {
5238
- ...stylePropValues
5239
- },
5240
- childElements: structuredElements(element)
5241
- };
5242
5300
  }
5243
5301
  });
5244
5302
  };
5245
5303
 
5246
5304
  // src/mcp/canvas-mcp.ts
5247
5305
  var initCanvasMcp = (reg) => {
5248
- import_editor_props9.Schema.setDynamicTagNamesResolver(getDynamicTagNamesByCategories);
5306
+ import_editor_props8.Schema.setDynamicTagNamesResolver(getDynamicTagNamesByCategories);
5249
5307
  initWidgetsSchemaResource(reg);
5250
5308
  initAvailableWidgetsResource(reg);
5251
5309
  initDocumentStructureResource(reg);
@@ -5254,17 +5312,15 @@ var initCanvasMcp = (reg) => {
5254
5312
  initEditorStateResource(reg);
5255
5313
  initGeneralContextResource(reg);
5256
5314
  initBestPracticesResource(reg);
5257
- initGetElementConfigTool(reg);
5258
5315
  initConfigureElementTool(reg);
5259
- initCreateElementTool(reg);
5260
- initBuildCompositionTool(reg);
5316
+ initGetPageStructureTool(reg);
5261
5317
  initBreakpointsResource(reg);
5262
5318
  };
5263
5319
 
5264
5320
  // src/mcp/mcp-description.ts
5265
5321
  var ELEMENT_SCHEMA_URI = WIDGET_SCHEMA_URI.replace("{widgetType}", "element-schema");
5266
5322
  var mcpDescription = `Elementor Canvas MCP
5267
- This MCP enables creation, configuration, and styling of elements on the Elementor canvas using the build_composition tool.
5323
+ This MCP enables configuration and styling of existing V4 elements on the Elementor canvas using the configure-element tool.
5268
5324
 
5269
5325
  # Core Concepts
5270
5326
 
@@ -5283,66 +5339,54 @@ The \`$$type\` defines how Elementor interprets the value. Providing the correct
5283
5339
  - **Global Classes**: Reusable style sets that can be applied to elements (\`elementor://global-classes\`)
5284
5340
  - **Widget Schemas**: Configuration options for each widget type (\`${WIDGET_SCHEMA_URI}\`)
5285
5341
 
5286
- # Building Compositions with build_composition
5342
+ # Configuring Elements with configure-element
5287
5343
 
5288
- The \`build_composition\` tool is the primary way to create elements. It accepts structure (XML), configuration, and styling in a single operation.
5344
+ The \`configure-element\` tool updates settings and styles on existing V4 elements. Read the configure-element guide resource before use.
5289
5345
 
5290
5346
  ## Complete Workflow
5291
5347
 
5292
5348
  ### 1. Parse User Requirements
5293
- Understand what needs to be built: structure, content, and styling.
5349
+ Understand what needs to change: content, settings, or styling on existing elements.
5294
5350
 
5295
5351
  ### 2. Check Global Resources FIRST
5296
- Always check existing resources before building:
5352
+ Always check existing resources before styling:
5297
5353
  - List \`elementor://global-variables\` for available variables (colors, sizes, fonts)
5298
5354
  - List \`elementor://global-classes\` for available style sets
5299
5355
  - **Always prefer using existing global resources over creating inline styles**
5300
5356
 
5301
5357
  ### 3. Retrieve Widget Schemas
5302
- For each widget you'll use:
5358
+ For each element you will configure:
5303
5359
  - List \`${WIDGET_SCHEMA_URI}\` to see available widgets
5304
5360
  - Retrieve configuration schema from \`${ELEMENT_SCHEMA_URI}\` for each widget
5305
- - Check the \`llm_guidance\` property for container nesting, \`default_styles\`, and \`default_settings\` (omit default_settings from elementConfig unless the user asks to change them)
5361
+ - Check the \`llm_guidance\` property for container nesting, \`default_styles\`, and \`default_settings\`
5306
5362
 
5307
- ### 4. Build XML Structure
5308
- Create valid XML with configuration-ids:
5309
- - Each element must have a unique \`configuration-id\` attribute
5310
- - No text nodes, classes, or IDs in XML - structure only
5311
- - Example:
5312
- \`\`\`xml
5313
- <e-container configuration-id="container-1">
5314
- <e-heading configuration-id="heading-1" />
5315
- <e-text configuration-id="text-1" />
5316
- </e-container>
5317
- \`\`\`
5363
+ ### 4. Get Current Element State
5364
+ Use page structure and element configuration resources to find element IDs and current values.
5318
5365
 
5319
- ### 5. Create elementConfig
5320
- Map each configuration-id to its widget properties using PropValues:
5366
+ ### 5. Create propertiesToChange
5367
+ Map property names to PropValues using the widget schema:
5321
5368
  - Use correct \`$$type\` matching the widget's schema
5322
5369
  - Use global variables in PropValues where applicable
5323
5370
  - Example:
5324
5371
  \`\`\`json
5325
5372
  {
5326
- "heading-1": {
5327
- "text": { "$$type": "string", "value": "Welcome" },
5328
- "tag": { "$$type": "string", "value": "h1" }
5329
- }
5373
+ "text": { "$$type": "string", "value": "Welcome" },
5374
+ "tag": { "$$type": "string", "value": "h1" }
5330
5375
  }
5331
5376
  \`\`\`
5332
5377
 
5333
5378
  ### 6. Create style
5334
- Map each configuration-id to raw CSS declarations (property \u2192 value strings). The server converts them to native styles and stores any unconvertible declarations as the element custom CSS.
5379
+ Provide raw CSS declarations (property \u2192 value strings). The server converts them to native styles and stores any unconvertible declarations as the element custom CSS.
5335
5380
  - Example:
5336
5381
  \`\`\`json
5337
5382
  {
5338
- "heading-1": "color: #1a1a1a; font-size: 2rem;"
5339
- }
5383
+ "color": "#1a1a1a",
5384
+ "font-size": "2rem"
5340
5385
  }
5341
5386
  \`\`\`
5342
5387
 
5343
- ### 7. Execute build_composition
5344
- Call the tool with your XML structure, elementConfig, and style. The response will contain the created element IDs.
5345
- At the response you will also find llm_instructions for you to do afterwards, read and follow them!
5388
+ ### 7. Execute configure-element
5389
+ Call the tool with elementId, elementType, propertiesToChange, and style as needed.
5346
5390
 
5347
5391
  ## Key Points
5348
5392
 
@@ -5370,7 +5414,7 @@ Note: The "size" property controls image resolution/loading, not visual size. Se
5370
5414
  `;
5371
5415
 
5372
5416
  // src/prevent-link-in-link-commands.ts
5373
- var import_editor_elements16 = require("@elementor/editor-elements");
5417
+ var import_editor_elements14 = require("@elementor/editor-elements");
5374
5418
  var import_editor_notifications3 = require("@elementor/editor-notifications");
5375
5419
  var import_editor_v1_adapters21 = require("@elementor/editor-v1-adapters");
5376
5420
  var import_i18n4 = require("@wordpress/i18n");
@@ -5441,25 +5485,25 @@ function shouldBlock(sourceElements, targetElements) {
5441
5485
  return false;
5442
5486
  }
5443
5487
  const isSourceContainsAnAnchor = sourceElements.some((src) => {
5444
- return src?.id ? (0, import_editor_elements16.isElementAnchored)(src.id) || !!(0, import_editor_elements16.getAnchoredDescendantId)(src.id) : false;
5488
+ return src?.id ? (0, import_editor_elements14.isElementAnchored)(src.id) || !!(0, import_editor_elements14.getAnchoredDescendantId)(src.id) : false;
5445
5489
  });
5446
5490
  if (!isSourceContainsAnAnchor) {
5447
5491
  return false;
5448
5492
  }
5449
5493
  const isTargetContainsAnAnchor = targetElements.some((target) => {
5450
- return target?.id ? (0, import_editor_elements16.isElementAnchored)(target.id) || !!(0, import_editor_elements16.getAnchoredAncestorId)(target.id) : false;
5494
+ return target?.id ? (0, import_editor_elements14.isElementAnchored)(target.id) || !!(0, import_editor_elements14.getAnchoredAncestorId)(target.id) : false;
5451
5495
  });
5452
5496
  return isTargetContainsAnAnchor;
5453
5497
  }
5454
5498
 
5455
5499
  // src/style-commands/paste-style.ts
5456
- var import_editor_elements19 = require("@elementor/editor-elements");
5457
- var import_editor_props11 = require("@elementor/editor-props");
5500
+ var import_editor_elements17 = require("@elementor/editor-elements");
5501
+ var import_editor_props10 = require("@elementor/editor-props");
5458
5502
  var import_editor_v1_adapters23 = require("@elementor/editor-v1-adapters");
5459
5503
 
5460
5504
  // src/utils/command-utils.ts
5461
- var import_editor_elements17 = require("@elementor/editor-elements");
5462
- var import_editor_props10 = require("@elementor/editor-props");
5505
+ var import_editor_elements15 = require("@elementor/editor-elements");
5506
+ var import_editor_props9 = require("@elementor/editor-props");
5463
5507
  var import_i18n5 = require("@wordpress/i18n");
5464
5508
  function hasAtomicWidgets(args) {
5465
5509
  const { containers = [args.container] } = args;
@@ -5477,13 +5521,13 @@ function getClassesProp(container) {
5477
5521
  return null;
5478
5522
  }
5479
5523
  const [propKey] = Object.entries(propsSchema).find(
5480
- ([, propType]) => propType.kind === "plain" && propType.key === import_editor_props10.CLASSES_PROP_KEY
5524
+ ([, propType]) => propType.kind === "plain" && propType.key === import_editor_props9.CLASSES_PROP_KEY
5481
5525
  ) ?? [];
5482
5526
  return propKey ?? null;
5483
5527
  }
5484
5528
  function getContainerSchema(container) {
5485
5529
  const type = container?.model.get("widgetType") || container?.model.get("elType");
5486
- const widgetsCache = (0, import_editor_elements17.getWidgetsCache)();
5530
+ const widgetsCache = (0, import_editor_elements15.getWidgetsCache)();
5487
5531
  const elementType = widgetsCache?.[type];
5488
5532
  return elementType?.atomic_props_schema ?? null;
5489
5533
  }
@@ -5496,11 +5540,11 @@ function getClipboardElements(storageKey = "clipboard") {
5496
5540
  }
5497
5541
  }
5498
5542
  function getTitleForContainers(containers) {
5499
- return containers.length > 1 ? (0, import_i18n5.__)("Elements", "elementor") : (0, import_editor_elements17.getElementLabel)(containers[0].id);
5543
+ return containers.length > 1 ? (0, import_i18n5.__)("Elements", "elementor") : (0, import_editor_elements15.getElementLabel)(containers[0].id);
5500
5544
  }
5501
5545
 
5502
5546
  // src/style-commands/undoable-actions/paste-element-style.ts
5503
- var import_editor_elements18 = require("@elementor/editor-elements");
5547
+ var import_editor_elements16 = require("@elementor/editor-elements");
5504
5548
  var import_editor_styles_repository4 = require("@elementor/editor-styles-repository");
5505
5549
  var import_editor_v1_adapters22 = require("@elementor/editor-v1-adapters");
5506
5550
  var import_i18n6 = require("@wordpress/i18n");
@@ -5513,7 +5557,7 @@ var undoablePasteElementStyle = () => (0, import_editor_v1_adapters22.undoable)(
5513
5557
  if (!classesProp) {
5514
5558
  return null;
5515
5559
  }
5516
- const originalStyles = (0, import_editor_elements18.getElementStyles)(container.id);
5560
+ const originalStyles = (0, import_editor_elements16.getElementStyles)(container.id);
5517
5561
  const [styleId, styleDef] = Object.entries(originalStyles ?? {})[0] ?? [];
5518
5562
  const originalStyle = Object.keys(styleDef ?? {}).length ? styleDef : null;
5519
5563
  const revertData = {
@@ -5522,7 +5566,7 @@ var undoablePasteElementStyle = () => (0, import_editor_v1_adapters22.undoable)(
5522
5566
  };
5523
5567
  if (styleId) {
5524
5568
  newStyle.variants.forEach(({ meta, props, custom_css: customCss }) => {
5525
- (0, import_editor_elements18.updateElementStyle)({
5569
+ (0, import_editor_elements16.updateElementStyle)({
5526
5570
  elementId,
5527
5571
  styleId,
5528
5572
  meta,
@@ -5533,7 +5577,7 @@ var undoablePasteElementStyle = () => (0, import_editor_v1_adapters22.undoable)(
5533
5577
  } else {
5534
5578
  const [firstVariant] = newStyle.variants;
5535
5579
  const additionalVariants = newStyle.variants.slice(1);
5536
- revertData.styleId = (0, import_editor_elements18.createElementStyle)({
5580
+ revertData.styleId = (0, import_editor_elements16.createElementStyle)({
5537
5581
  elementId,
5538
5582
  classesProp,
5539
5583
  label: import_editor_styles_repository4.ELEMENTS_STYLES_RESERVED_LABEL,
@@ -5551,7 +5595,7 @@ var undoablePasteElementStyle = () => (0, import_editor_v1_adapters22.undoable)(
5551
5595
  return;
5552
5596
  }
5553
5597
  if (!revertData.originalStyle) {
5554
- (0, import_editor_elements18.deleteElementStyle)(container.id, revertData.styleId);
5598
+ (0, import_editor_elements16.deleteElementStyle)(container.id, revertData.styleId);
5555
5599
  return;
5556
5600
  }
5557
5601
  const classesProp = getClassesProp(container);
@@ -5560,7 +5604,7 @@ var undoablePasteElementStyle = () => (0, import_editor_v1_adapters22.undoable)(
5560
5604
  }
5561
5605
  const [firstVariant] = revertData.originalStyle.variants;
5562
5606
  const additionalVariants = revertData.originalStyle.variants.slice(1);
5563
- (0, import_editor_elements18.createElementStyle)({
5607
+ (0, import_editor_elements16.createElementStyle)({
5564
5608
  elementId: container.id,
5565
5609
  classesProp,
5566
5610
  label: import_editor_styles_repository4.ELEMENTS_STYLES_RESERVED_LABEL,
@@ -5597,7 +5641,7 @@ function pasteStyles(args, pasteLocalStyle) {
5597
5641
  }
5598
5642
  const clipboardElements = getClipboardElements(storageKey);
5599
5643
  const [clipboardElement] = clipboardElements ?? [];
5600
- const clipboardContainer = (0, import_editor_elements19.getContainer)(clipboardElement.id);
5644
+ const clipboardContainer = (0, import_editor_elements17.getContainer)(clipboardElement.id);
5601
5645
  if (!clipboardElement || !clipboardContainer || !isAtomicWidget(clipboardContainer)) {
5602
5646
  return;
5603
5647
  }
@@ -5616,7 +5660,7 @@ function getClassesWithoutLocalStyle(clipboardContainer, style) {
5616
5660
  if (!classesProp) {
5617
5661
  return [];
5618
5662
  }
5619
- const classesSetting = (0, import_editor_elements19.getElementSetting)(clipboardContainer.id, classesProp);
5663
+ const classesSetting = (0, import_editor_elements17.getElementSetting)(clipboardContainer.id, classesProp);
5620
5664
  return classesSetting?.value.filter((styleId) => styleId !== style?.id) ?? [];
5621
5665
  }
5622
5666
  function pasteClasses(containers, classes) {
@@ -5625,10 +5669,10 @@ function pasteClasses(containers, classes) {
5625
5669
  if (!classesProp) {
5626
5670
  return;
5627
5671
  }
5628
- const classesSetting = (0, import_editor_elements19.getElementSetting)(container.id, classesProp);
5629
- const currentClasses = import_editor_props11.classesPropTypeUtil.extract(classesSetting) ?? [];
5630
- const newClasses = import_editor_props11.classesPropTypeUtil.create(Array.from(/* @__PURE__ */ new Set([...classes, ...currentClasses])));
5631
- (0, import_editor_elements19.updateElementSettings)({
5672
+ const classesSetting = (0, import_editor_elements17.getElementSetting)(container.id, classesProp);
5673
+ const currentClasses = import_editor_props10.classesPropTypeUtil.extract(classesSetting) ?? [];
5674
+ const newClasses = import_editor_props10.classesPropTypeUtil.create(Array.from(/* @__PURE__ */ new Set([...classes, ...currentClasses])));
5675
+ (0, import_editor_elements17.updateElementSettings)({
5632
5676
  id: container.id,
5633
5677
  props: { [classesProp]: newClasses }
5634
5678
  });
@@ -5639,7 +5683,7 @@ function pasteClasses(containers, classes) {
5639
5683
  var import_editor_v1_adapters25 = require("@elementor/editor-v1-adapters");
5640
5684
 
5641
5685
  // src/style-commands/undoable-actions/reset-element-style.ts
5642
- var import_editor_elements20 = require("@elementor/editor-elements");
5686
+ var import_editor_elements18 = require("@elementor/editor-elements");
5643
5687
  var import_editor_styles_repository5 = require("@elementor/editor-styles-repository");
5644
5688
  var import_editor_v1_adapters24 = require("@elementor/editor-v1-adapters");
5645
5689
  var import_i18n7 = require("@wordpress/i18n");
@@ -5648,9 +5692,9 @@ var undoableResetElementStyle = () => (0, import_editor_v1_adapters24.undoable)(
5648
5692
  do: ({ containers }) => {
5649
5693
  return containers.map((container) => {
5650
5694
  const elementId = container.model.get("id");
5651
- const containerStyles = (0, import_editor_elements20.getElementStyles)(elementId);
5695
+ const containerStyles = (0, import_editor_elements18.getElementStyles)(elementId);
5652
5696
  Object.keys(containerStyles ?? {}).forEach(
5653
- (styleId) => (0, import_editor_elements20.deleteElementStyle)(elementId, styleId)
5697
+ (styleId) => (0, import_editor_elements18.deleteElementStyle)(elementId, styleId)
5654
5698
  );
5655
5699
  return containerStyles;
5656
5700
  });
@@ -5666,7 +5710,7 @@ var undoableResetElementStyle = () => (0, import_editor_v1_adapters24.undoable)(
5666
5710
  Object.entries(containerStyles ?? {}).forEach(([styleId, style]) => {
5667
5711
  const [firstVariant] = style.variants;
5668
5712
  const additionalVariants = style.variants.slice(1);
5669
- (0, import_editor_elements20.createElementStyle)({
5713
+ (0, import_editor_elements18.createElementStyle)({
5670
5714
  elementId,
5671
5715
  classesProp,
5672
5716
  styleId,
@@ -5740,15 +5784,15 @@ function init() {
5740
5784
  initCanvasMcp(
5741
5785
  (0, import_editor_mcp4.getMCPByDomain)("canvas", {
5742
5786
  instructions: `Everything related to V4 ( Atomic ) canvas.
5743
- # Canvas workflow for new compositions
5744
- - Configure elements settings and styles
5745
- - Build compositions/sections out of V4 atomic elements using context aware designs using the website resources
5746
- - Get and retrieve element configuration values
5787
+ # Canvas workflow
5788
+ - Configure element settings and styles with configure-element
5789
+ - Get page structure and element configuration values
5747
5790
  `,
5748
5791
  docs: mcpDescription
5749
5792
  })
5750
5793
  );
5751
5794
  initTabsModelExtensions();
5795
+ initListType();
5752
5796
  }
5753
5797
 
5754
5798
  // src/sync/drag-element-from-panel.ts
@@ -5866,10 +5910,10 @@ function useEscapeOnCanvas(canvasDocument, onEscape) {
5866
5910
  }
5867
5911
 
5868
5912
  // src/utils/after-render.ts
5869
- var import_editor_elements21 = require("@elementor/editor-elements");
5913
+ var import_editor_elements19 = require("@elementor/editor-elements");
5870
5914
  function doAfterRender(elementIds, callback) {
5871
5915
  const pending = elementIds.map((elementId) => {
5872
- const view = (0, import_editor_elements21.getContainer)(elementId)?.view;
5916
+ const view = (0, import_editor_elements19.getContainer)(elementId)?.view;
5873
5917
  if (!view || !hasDoAfterRender(view)) {
5874
5918
  return void 0;
5875
5919
  }