@elementor/editor-canvas 3.33.0-291 → 3.33.0-293

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.
@@ -26,16 +26,9 @@ export const initBuildCompositionsTool = ( reg: MCPRegistryEntry ) => {
26
26
  const { xmlStructure, elementConfig, stylesConfig } = params;
27
27
  const errors: Error[] = [];
28
28
  const softErrors: Error[] = [];
29
+ const rootContainers: V1Element[] = [];
29
30
  const widgetsCache = getWidgetsCache() || {};
30
31
  const documentContainer = getContainer( 'document' ) as unknown as V1Element;
31
- const rootContainer = createElement( {
32
- containerId: documentContainer.id,
33
- model: {
34
- elType: 'container',
35
- id: generateElementId(),
36
- },
37
- options: { useHistory: false },
38
- } );
39
32
  try {
40
33
  const parser = new DOMParser();
41
34
  xml = parser.parseFromString( xmlStructure, 'application/xml' );
@@ -45,7 +38,7 @@ export const initBuildCompositionsTool = ( reg: MCPRegistryEntry ) => {
45
38
  }
46
39
 
47
40
  const children = Array.from( xml.children );
48
- const iterate = ( node: Element, containerElement: V1Element ) => {
41
+ const iterate = ( node: Element, containerElement: V1Element = documentContainer ) => {
49
42
  const elementTag = node.tagName;
50
43
  if ( ! widgetsCache[ elementTag ] ) {
51
44
  errors.push( new Error( `Unknown widget type: ${ elementTag }` ) );
@@ -69,6 +62,9 @@ export const initBuildCompositionsTool = ( reg: MCPRegistryEntry ) => {
69
62
  },
70
63
  options: { useHistory: false },
71
64
  } );
65
+ if ( containerElement === documentContainer ) {
66
+ rootContainers.push( newElement );
67
+ }
72
68
  node.setAttribute( 'id', newElement.id );
73
69
  const configId = node.getAttribute( 'configuration-id' ) || '';
74
70
  try {
@@ -78,7 +74,11 @@ export const initBuildCompositionsTool = ( reg: MCPRegistryEntry ) => {
78
74
  for ( const [ propertyName, propertyValue ] of Object.entries( configObject ) ) {
79
75
  // validate property existance
80
76
  const widgetSchema = widgetsCache[ elementTag ];
81
- if ( ! widgetSchema?.atomic_props_schema?.[ propertyName ] && propertyName !== '_styles' ) {
77
+ if (
78
+ ! widgetSchema?.atomic_props_schema?.[ propertyName ] &&
79
+ propertyName !== '_styles' &&
80
+ propertyName !== 'custom_css'
81
+ ) {
82
82
  softErrors.push(
83
83
  new Error(
84
84
  `Property "${ propertyName }" does not exist on element type "${ elementTag }".`
@@ -90,7 +90,10 @@ export const initBuildCompositionsTool = ( reg: MCPRegistryEntry ) => {
90
90
  doUpdateElementProperty( {
91
91
  elementId: newElement.id,
92
92
  propertyName,
93
- propertyValue: propertyValue as unknown as PropValue,
93
+ propertyValue:
94
+ propertyName === 'custom_css'
95
+ ? { _styles: propertyValue }
96
+ : ( propertyValue as unknown as PropValue ),
94
97
  elementType: elementTag,
95
98
  } );
96
99
  } catch ( error ) {
@@ -110,7 +113,7 @@ export const initBuildCompositionsTool = ( reg: MCPRegistryEntry ) => {
110
113
  };
111
114
 
112
115
  for ( const childNode of children ) {
113
- iterate( childNode, rootContainer );
116
+ iterate( childNode, documentContainer );
114
117
  try {
115
118
  } catch ( error ) {
116
119
  errors.push( error as Error );
@@ -121,9 +124,11 @@ export const initBuildCompositionsTool = ( reg: MCPRegistryEntry ) => {
121
124
  }
122
125
 
123
126
  if ( errors.length ) {
124
- deleteElement( {
125
- elementId: rootContainer.id,
126
- options: { useHistory: false },
127
+ rootContainers.forEach( ( rootContainer ) => {
128
+ deleteElement( {
129
+ elementId: rootContainer.id,
130
+ options: { useHistory: false },
131
+ } );
127
132
  } );
128
133
  }
129
134
 
@@ -2,19 +2,20 @@ import { STYLE_SCHEMA_URI, WIDGET_SCHEMA_URI } from '../../resources/widgets-sch
2
2
 
3
3
  export const configureElementToolPrompt = `Configure an existing element on the page.
4
4
 
5
- # **CRITICAL - REQUIRED RESOURCES (Must read before using this tool)**
5
+ # **CRITICAL - REQUIRED INFORMATION (Must read before using this tool)**
6
6
  1. [${ WIDGET_SCHEMA_URI }]
7
7
  Required to understand which widgets are available, and what are their configuration schemas.
8
8
  Every widgetType (i.e. e-heading, e-button) that is supported has it's own property schema, that you must follow in order to apply property values correctly.
9
9
  2. [${ STYLE_SCHEMA_URI }]
10
10
  Required to understand the styles schema for the widgets. All widgets share the same styles schema, grouped by categories.
11
11
  Use this resource to understand which style properties are available for each element, and how to structure the "_styles" configuration property.
12
+ 3. If not sure about the PropValues schema, you can use the "get-element-configuration-values" tool to retreive the current PropValues configuration of the element.
12
13
 
13
14
  Before using this tool, check the definitions of the elements PropTypes at the resource "widget-schema-by-type" at editor-canvas__elementor://widgets/schema/{widgetType}
14
15
  All widgets share a common _style property for styling, which uses the common styles schema.
15
16
  Retreive and check the common styles schema at the resource list "styles-schema" at editor-canvas__elementor://styles/schema/{category}
16
17
 
17
- Unless specifically noted, attempt to use the _style property "custom_css" for any styling, read the resource editor-canvas__elementor://styles/schema/custom_css for more information.
18
+ Attempt to use the _style property "custom_css" for any styling that have complicated schemas (such as backgrounds), read the resource editor-canvas__elementor://styles/schema/custom_css for more information.
18
19
 
19
20
  # Parameters
20
21
  - propertiesToChange: An object containing the properties to change, with their new values. MANDATORY
@@ -59,6 +60,7 @@ Use the EXACT "PROP-TYPE" Schema given, and ALWAYS include the "key" property fr
59
60
  \`\`\`json
60
61
  {
61
62
  propertiesToChange: {
63
+ // List of properties TO CHANGE, following the PropType schema for the element as defined in the resource [${ WIDGET_SCHEMA_URI }]
62
64
  title: {
63
65
  $$type: 'string',
64
66
  value: 'New Title Text'
@@ -68,8 +70,9 @@ Use the EXACT "PROP-TYPE" Schema given, and ALWAYS include the "key" property fr
68
70
  value: false
69
71
  },
70
72
  _styles: {
73
+ // List of available keys available at the [${ STYLE_SCHEMA_URI }] dynamic resource
71
74
  'line-height': {
72
- $$type: 'size',
75
+ $$type: 'size', // MANDATORY do not forget to include the correct $$type for every property
73
76
  value: {
74
77
  size: {
75
78
  $$type: 'number',
@@ -0,0 +1,75 @@
1
+ import { getContainer, getElementStyles, getWidgetsCache } from '@elementor/editor-elements';
2
+ import { type MCPRegistryEntry } from '@elementor/editor-mcp';
3
+ import { type PropValue, Schema } from '@elementor/editor-props';
4
+ import { z } from '@elementor/schema';
5
+ import { decodeString } from '@elementor/utils';
6
+
7
+ const schema = {
8
+ elementId: z.string(),
9
+ };
10
+
11
+ const outputSchema = {
12
+ propValues: z
13
+ .record( z.string(), z.any() )
14
+ .describe(
15
+ 'A record mapping PropTypes to their corresponding PropValues, with _styles record for style-related PropValues'
16
+ ),
17
+ customCss: z.string().optional().describe( 'The custom CSS string associated with the element, if any.' ),
18
+ };
19
+
20
+ export const initGetElementConfigTool = ( reg: MCPRegistryEntry ) => {
21
+ const { addTool } = reg;
22
+
23
+ addTool( {
24
+ name: 'get-element-configuration-values',
25
+ description: "Retrieve the element's configuration PropValues for a specific element by unique ID.",
26
+ schema,
27
+ outputSchema,
28
+ handler: async ( { elementId } ) => {
29
+ const element = getContainer( elementId );
30
+ if ( ! element ) {
31
+ throw new Error( `Element with ID ${ elementId } not found.` );
32
+ }
33
+ const elementRawSettings = element.settings;
34
+ const propSchema = getWidgetsCache()?.[ element.model.get( 'widgetType' ) || '' ]?.atomic_props_schema;
35
+
36
+ if ( ! elementRawSettings || ! propSchema ) {
37
+ throw new Error( `No settings or prop schema found for element ID: ${ elementId }` );
38
+ }
39
+
40
+ const propValues: Record< string, PropValue > = {};
41
+ const stylePropValues: Record< string, PropValue > = {};
42
+
43
+ Schema.configurableKeys( propSchema ).forEach( ( key ) => {
44
+ propValues[ key ] = structuredClone( elementRawSettings.get( key ) );
45
+ } );
46
+ const elementStyles = getElementStyles( elementId ) || {};
47
+ const localStyle = Object.values( elementStyles ).find( ( style ) => style.label === 'local' );
48
+
49
+ if ( localStyle ) {
50
+ const defaultVariant = localStyle.variants.find(
51
+ ( variant ) => variant.meta.breakpoint === 'desktop' && ! variant.meta.state
52
+ );
53
+ if ( defaultVariant ) {
54
+ const styleProps = defaultVariant.props || {};
55
+ Object.keys( styleProps ).forEach( ( stylePropName ) => {
56
+ if ( typeof styleProps[ stylePropName ] !== 'undefined' ) {
57
+ stylePropValues[ stylePropName ] = structuredClone( styleProps[ stylePropName ] );
58
+ }
59
+ } );
60
+
61
+ if ( defaultVariant.custom_css?.raw ) {
62
+ stylePropValues.custom_css = decodeString( defaultVariant.custom_css.raw, undefined );
63
+ }
64
+ }
65
+ }
66
+
67
+ return {
68
+ propValues: {
69
+ ...propValues,
70
+ _styles: stylePropValues,
71
+ },
72
+ };
73
+ },
74
+ } );
75
+ };
@@ -5,7 +5,13 @@ import {
5
5
  updateElementSettings,
6
6
  updateElementStyle,
7
7
  } from '@elementor/editor-elements';
8
- import { getPropSchemaFromCache, type PropValue, Schema, type TransformablePropValue } from '@elementor/editor-props';
8
+ import {
9
+ getPropSchemaFromCache,
10
+ type PropValue,
11
+ Schema,
12
+ stringPropTypeUtil,
13
+ type TransformablePropValue,
14
+ } from '@elementor/editor-props';
9
15
  import { type CustomCss, getStylesSchema } from '@elementor/editor-styles';
10
16
 
11
17
  type OwnParams = {
@@ -42,8 +48,15 @@ export const doUpdateElementProperty = ( params: OwnParams ) => {
42
48
  Object.keys( propertyMapValue as Record< string, unknown > ).forEach( ( stylePropName ) => {
43
49
  const propertyRawSchema = styleSchema[ stylePropName ];
44
50
  if ( stylePropName === 'custom_css' ) {
51
+ let customCssValue = propertyMapValue[ stylePropName ] as object | string;
52
+ if ( typeof customCssValue === 'object' ) {
53
+ customCssValue =
54
+ stringPropTypeUtil.extract( customCssValue ) ||
55
+ ( customCssValue as { value: unknown } )?.value ||
56
+ '';
57
+ }
45
58
  customCss = {
46
- raw: btoa( propertyMapValue[ stylePropName ] as string ),
59
+ raw: btoa( customCssValue as string ),
47
60
  };
48
61
  return;
49
62
  }
@@ -65,7 +78,7 @@ export const doUpdateElementProperty = ( params: OwnParams ) => {
65
78
  if ( ! localStyle ) {
66
79
  createElementStyle( {
67
80
  elementId,
68
- custom_css: customCss,
81
+ ...( typeof customCss !== 'undefined' ? { custom_css: customCss } : {} ),
69
82
  classesProp: 'classes',
70
83
  label: 'local',
71
84
  meta: {
@@ -84,6 +97,7 @@ export const doUpdateElementProperty = ( params: OwnParams ) => {
84
97
  breakpoint: 'desktop',
85
98
  state: null,
86
99
  },
100
+ ...( typeof customCss !== 'undefined' ? { custom_css: customCss } : {} ),
87
101
  props: {
88
102
  ...transformedStyleValues,
89
103
  },