@elementor/editor-canvas 3.33.0-271 → 3.33.0-273
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.js +747 -21
- package/dist/index.mjs +755 -15
- package/package.json +17 -15
- package/src/init.tsx +9 -0
- package/src/mcp/canvas-mcp.ts +15 -0
- package/src/mcp/mcp-description.ts +33 -0
- package/src/mcp/resources/widgets-schema-resource.ts +154 -0
- package/src/mcp/tools/build-composition/prompt.ts +119 -0
- package/src/mcp/tools/build-composition/schema.ts +27 -0
- package/src/mcp/tools/build-composition/tool.ts +158 -0
- package/src/mcp/tools/configure-element/prompt.ts +92 -0
- package/src/mcp/tools/configure-element/schema.ts +25 -0
- package/src/mcp/tools/configure-element/tool.ts +67 -0
- package/src/mcp/utils/do-update-element-property.ts +115 -0
- package/src/mcp/utils/generate-available-tags.ts +23 -0
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { STYLE_SCHEMA_URI, WIDGET_SCHEMA_URI } from '../../resources/widgets-schema-resource';
|
|
2
|
+
|
|
3
|
+
export const configureElementToolPrompt = `Configure an existing element on the page.
|
|
4
|
+
|
|
5
|
+
# **CRITICAL - REQUIRED RESOURCES (Must read before using this tool)**
|
|
6
|
+
1. [${ WIDGET_SCHEMA_URI }]
|
|
7
|
+
Required to understand which widgets are available, and what are their configuration schemas.
|
|
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
|
+
2. [${ STYLE_SCHEMA_URI }]
|
|
10
|
+
Required to understand the styles schema for the widgets. All widgets share the same styles schema, grouped by categories.
|
|
11
|
+
Use this resource to understand which style properties are available for each element, and how to structure the "_styles" configuration property.
|
|
12
|
+
|
|
13
|
+
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
|
+
All widgets share a common _style property for styling, which uses the common styles schema.
|
|
15
|
+
Retreive and check the common styles schema at the resource list "styles-schema" at editor-canvas__elementor://styles/schema/{category}
|
|
16
|
+
|
|
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
|
+
|
|
19
|
+
# Parameters
|
|
20
|
+
- propertiesToChange: An object containing the properties to change, with their new values. MANDATORY
|
|
21
|
+
- elementId: The ID of the element to configure. MANDATORY
|
|
22
|
+
- elementType: The type of the element to configure (i.e. e-heading, e-button). MANDATORY
|
|
23
|
+
|
|
24
|
+
# When to use this tool
|
|
25
|
+
When a user requires to change anything in an element, such as updating text, colors, sizes, or other configurable properties.
|
|
26
|
+
This tool handles elements of type "widget".
|
|
27
|
+
This tool handles styling elements, using the _styles property in the configuration.
|
|
28
|
+
|
|
29
|
+
The element's schema must be known before using this tool.
|
|
30
|
+
|
|
31
|
+
Attached resource link describing how PropType schema should be parsed as PropValue for this tool.
|
|
32
|
+
|
|
33
|
+
Read carefully the PropType Schema of the element and it's styles, then apply correct PropValue according to the schema.
|
|
34
|
+
|
|
35
|
+
PropValue structure:
|
|
36
|
+
{
|
|
37
|
+
"$$type": string, // MANDATORY as defined in the PropType schema under the "key" property
|
|
38
|
+
value: unknown // The value according to the PropType schema for kinds of "array", use array with PropValues items inside. For "object", read the shape property of the PropType schema. For "plain", use strings.
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
<IMPORTANT>
|
|
42
|
+
ALWAYS MAKE SURE you have the PropType schemas for the element you are configuring, and the common-styles schema for styling. If you are not sure, retreive the schema from the resources mentioned above.
|
|
43
|
+
</IMPORTANT>
|
|
44
|
+
|
|
45
|
+
You can use multiple property changes at once by providing multiple entries in the propertiesToChange object, including _style alongside non-style props.
|
|
46
|
+
Some properties are nested, use the root property name, then objects with nested values inside, as the complete schema suggests.
|
|
47
|
+
Nested properties, such as for the _styles, should include a "_styles" property with object containing the definitions to change.
|
|
48
|
+
|
|
49
|
+
Make sure you have the "widget-schema-by-type" resource available to retreive the PropType schema for the element type you are configuring.
|
|
50
|
+
|
|
51
|
+
# How to configure elements
|
|
52
|
+
We use a dedicated PropType Schema for configuring elements, including styles. When you configure an element, you must use the EXACT PropType Value as defined in the schema.
|
|
53
|
+
For _styles, use the style schema provided, as it also uses the PropType format.
|
|
54
|
+
For all non-primitive types, provide the key property as defined in the schema as $$type in the generated objecct, as it is MANDATORY for parsing.
|
|
55
|
+
|
|
56
|
+
Use the EXACT "PROP-TYPE" Schema given, and ALWAYS include the "key" property from the original configuration for every property you are changing.
|
|
57
|
+
|
|
58
|
+
# Example
|
|
59
|
+
\`\`\`json
|
|
60
|
+
{
|
|
61
|
+
propertiesToChange: {
|
|
62
|
+
title: {
|
|
63
|
+
$$type: 'string',
|
|
64
|
+
value: 'New Title Text'
|
|
65
|
+
},
|
|
66
|
+
border: {
|
|
67
|
+
$$type: 'boolean',
|
|
68
|
+
value: false
|
|
69
|
+
},
|
|
70
|
+
_styles: {
|
|
71
|
+
'line-height': {
|
|
72
|
+
$$type: 'size',
|
|
73
|
+
value: {
|
|
74
|
+
size: {
|
|
75
|
+
$$type: 'number',
|
|
76
|
+
value: 20
|
|
77
|
+
},
|
|
78
|
+
unit: {
|
|
79
|
+
$$type: 'string',
|
|
80
|
+
value: 'px'
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
\`\`\`
|
|
88
|
+
|
|
89
|
+
<IMPORTANT>
|
|
90
|
+
The $$type property is MANDATORY for every value, it is required to parse the value and apply application-level effects.
|
|
91
|
+
</IMPORTANT>
|
|
92
|
+
`;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { z } from '@elementor/schema';
|
|
2
|
+
|
|
3
|
+
export const inputSchema = {
|
|
4
|
+
propertiesToChange: z
|
|
5
|
+
.record(
|
|
6
|
+
z
|
|
7
|
+
.string()
|
|
8
|
+
.describe(
|
|
9
|
+
'The property name. If nested property, provide the root property name, and the object delta only.'
|
|
10
|
+
),
|
|
11
|
+
z.any().describe( "The property's value" )
|
|
12
|
+
)
|
|
13
|
+
.describe( 'An object record containing property names and their new values to be set on the element' )
|
|
14
|
+
.optional(),
|
|
15
|
+
elementType: z.string().describe( 'The type of the element to retreive the schema' ),
|
|
16
|
+
elementId: z.string().describe( 'The unique id of the element to configure' ),
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export const outputSchema = {
|
|
20
|
+
success: z
|
|
21
|
+
.boolean()
|
|
22
|
+
.describe(
|
|
23
|
+
'Whether the configuration change was successful, only if propertyName and propertyValue are provided'
|
|
24
|
+
),
|
|
25
|
+
};
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { type MCPRegistryEntry } from '@elementor/editor-mcp';
|
|
2
|
+
|
|
3
|
+
import { WIDGET_SCHEMA_URI } from '../../resources/widgets-schema-resource';
|
|
4
|
+
import { doUpdateElementProperty } from '../../utils/do-update-element-property';
|
|
5
|
+
import { configureElementToolPrompt } from './prompt';
|
|
6
|
+
import { inputSchema as schema, outputSchema } from './schema';
|
|
7
|
+
|
|
8
|
+
export const initConfigureElementTool = ( reg: MCPRegistryEntry ) => {
|
|
9
|
+
const { addTool } = reg;
|
|
10
|
+
|
|
11
|
+
addTool( {
|
|
12
|
+
name: 'configure-element',
|
|
13
|
+
description: configureElementToolPrompt,
|
|
14
|
+
schema,
|
|
15
|
+
outputSchema,
|
|
16
|
+
handler: ( { elementId, propertiesToChange, elementType } ) => {
|
|
17
|
+
if ( ! propertiesToChange ) {
|
|
18
|
+
throw new Error(
|
|
19
|
+
'propertiesToChange is required to configure an element. Now that you have this information, ensure you have the schema and try again.'
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
const toUpdate = Object.entries( propertiesToChange );
|
|
23
|
+
for ( const [ propertyName, propertyValue ] of toUpdate ) {
|
|
24
|
+
if ( ! propertyName && ! elementId && ! elementType ) {
|
|
25
|
+
throw new Error(
|
|
26
|
+
'propertyName, elementId, elementType are required to configure an element. If you want to retreive the schema, use the get-element-configuration-schema tool.'
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
try {
|
|
31
|
+
doUpdateElementProperty( {
|
|
32
|
+
elementId,
|
|
33
|
+
elementType,
|
|
34
|
+
propertyName,
|
|
35
|
+
propertyValue,
|
|
36
|
+
} );
|
|
37
|
+
} catch ( error ) {
|
|
38
|
+
const errorMessage = createUpdateErrorMessage( {
|
|
39
|
+
propertyName,
|
|
40
|
+
elementId,
|
|
41
|
+
elementType,
|
|
42
|
+
error: error as Error,
|
|
43
|
+
} );
|
|
44
|
+
throw new Error( errorMessage );
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return {
|
|
48
|
+
success: true,
|
|
49
|
+
};
|
|
50
|
+
},
|
|
51
|
+
} );
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
function createUpdateErrorMessage( opts: {
|
|
55
|
+
propertyName: string;
|
|
56
|
+
elementId: string;
|
|
57
|
+
elementType: string;
|
|
58
|
+
error: Error;
|
|
59
|
+
} ) {
|
|
60
|
+
const { propertyName, elementId, elementType, error } = opts;
|
|
61
|
+
return `Failed to update property "${ propertyName }" on element "${ elementId }": ${ error.message }.
|
|
62
|
+
Check the element's PropType schema at the resource [${ WIDGET_SCHEMA_URI.replace(
|
|
63
|
+
'{widgetType}',
|
|
64
|
+
elementType
|
|
65
|
+
) }] for type "${ elementType }" to ensure the property exists and the value matches the expected PropType.
|
|
66
|
+
Now that you have this information, ensure you have the schema and try again.`;
|
|
67
|
+
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createElementStyle,
|
|
3
|
+
getElementStyles,
|
|
4
|
+
getWidgetsCache,
|
|
5
|
+
updateElementSettings,
|
|
6
|
+
updateElementStyle,
|
|
7
|
+
} from '@elementor/editor-elements';
|
|
8
|
+
import { getPropSchemaFromCache, type PropValue, Schema, type TransformablePropValue } from '@elementor/editor-props';
|
|
9
|
+
import { type CustomCss, getStylesSchema } from '@elementor/editor-styles';
|
|
10
|
+
|
|
11
|
+
type OwnParams = {
|
|
12
|
+
elementId: string;
|
|
13
|
+
elementType: string;
|
|
14
|
+
propertyName: string;
|
|
15
|
+
propertyValue: string | PropValue | TransformablePropValue< string, unknown >;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
function resolvePropValue( value: unknown, forceKey?: string ): PropValue {
|
|
19
|
+
return Schema.adjustLlmPropValueSchema( value as PropValue, forceKey );
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export const doUpdateElementProperty = ( params: OwnParams ) => {
|
|
23
|
+
const { elementId, propertyName, propertyValue, elementType } = params;
|
|
24
|
+
|
|
25
|
+
if ( propertyName === '_styles' ) {
|
|
26
|
+
const elementStyles = getElementStyles( elementId ) || {};
|
|
27
|
+
const propertyMapValue = propertyValue as Record< string, PropValue >;
|
|
28
|
+
const styleSchema = getStylesSchema();
|
|
29
|
+
const transformedStyleValues = Object.fromEntries(
|
|
30
|
+
Object.entries( propertyMapValue ).map( ( [ key, val ] ) => {
|
|
31
|
+
if ( key === 'custom_css' ) {
|
|
32
|
+
return [ key, val ];
|
|
33
|
+
}
|
|
34
|
+
const { key: propKey, kind } = styleSchema?.[ key ] || {};
|
|
35
|
+
if ( ! propKey && kind !== 'union' ) {
|
|
36
|
+
throw new Error( `_styles property ${ key } is not supported.` );
|
|
37
|
+
}
|
|
38
|
+
return [ key, resolvePropValue( val, propKey ) ];
|
|
39
|
+
} )
|
|
40
|
+
);
|
|
41
|
+
let customCss: CustomCss | undefined;
|
|
42
|
+
Object.keys( propertyMapValue as Record< string, unknown > ).forEach( ( stylePropName ) => {
|
|
43
|
+
const propertyRawSchema = styleSchema[ stylePropName ];
|
|
44
|
+
if ( stylePropName === 'custom_css' ) {
|
|
45
|
+
customCss = {
|
|
46
|
+
raw: btoa( propertyMapValue[ stylePropName ] as string ),
|
|
47
|
+
};
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
const isSupported = !! propertyRawSchema;
|
|
51
|
+
if ( ! isSupported ) {
|
|
52
|
+
throw new Error( `_styles property ${ stylePropName } is not supported.` );
|
|
53
|
+
}
|
|
54
|
+
if ( propertyRawSchema.kind === 'plain' ) {
|
|
55
|
+
if ( typeof ( propertyMapValue as Record< string, unknown > )[ stylePropName ] !== 'object' ) {
|
|
56
|
+
const propUtil = getPropSchemaFromCache( propertyRawSchema.key );
|
|
57
|
+
if ( propUtil ) {
|
|
58
|
+
const plainValue = propUtil.create( propertyMapValue[ stylePropName ] );
|
|
59
|
+
propertyMapValue[ stylePropName ] = plainValue;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
} );
|
|
64
|
+
const localStyle = Object.values( elementStyles ).find( ( style ) => style.label === 'local' );
|
|
65
|
+
if ( ! localStyle ) {
|
|
66
|
+
createElementStyle( {
|
|
67
|
+
elementId,
|
|
68
|
+
custom_css: customCss,
|
|
69
|
+
classesProp: 'classes',
|
|
70
|
+
label: 'local',
|
|
71
|
+
meta: {
|
|
72
|
+
breakpoint: 'desktop',
|
|
73
|
+
state: null,
|
|
74
|
+
},
|
|
75
|
+
props: {
|
|
76
|
+
...transformedStyleValues,
|
|
77
|
+
},
|
|
78
|
+
} );
|
|
79
|
+
} else {
|
|
80
|
+
updateElementStyle( {
|
|
81
|
+
elementId,
|
|
82
|
+
styleId: localStyle.id,
|
|
83
|
+
meta: {
|
|
84
|
+
breakpoint: 'desktop',
|
|
85
|
+
state: null,
|
|
86
|
+
},
|
|
87
|
+
props: {
|
|
88
|
+
...transformedStyleValues,
|
|
89
|
+
},
|
|
90
|
+
} );
|
|
91
|
+
}
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const elementPropSchema = getWidgetsCache()?.[ elementType ]?.atomic_props_schema;
|
|
96
|
+
if ( ! elementPropSchema ) {
|
|
97
|
+
throw new Error( `No prop schema found for element type: ${ elementType }` );
|
|
98
|
+
}
|
|
99
|
+
if ( ! elementPropSchema[ propertyName ] ) {
|
|
100
|
+
const propertyNames = Object.keys( elementPropSchema );
|
|
101
|
+
throw new Error(
|
|
102
|
+
`Property "${ propertyName }" does not exist on element type "${ elementType }". Available properties are: ${ propertyNames.join(
|
|
103
|
+
', '
|
|
104
|
+
) }`
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
const value = resolvePropValue( propertyValue );
|
|
108
|
+
updateElementSettings( {
|
|
109
|
+
id: elementId,
|
|
110
|
+
props: {
|
|
111
|
+
[ propertyName ]: value,
|
|
112
|
+
},
|
|
113
|
+
withHistory: false,
|
|
114
|
+
} );
|
|
115
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { getWidgetsCache, type V1ElementConfig } from '@elementor/editor-elements';
|
|
2
|
+
|
|
3
|
+
type ElTypedElementConfig = V1ElementConfig< {
|
|
4
|
+
elType?: string;
|
|
5
|
+
} >;
|
|
6
|
+
|
|
7
|
+
export const generateAvailableTags = () => {
|
|
8
|
+
const cache = getWidgetsCache< ElTypedElementConfig >();
|
|
9
|
+
if ( ! cache ) {
|
|
10
|
+
return [];
|
|
11
|
+
}
|
|
12
|
+
const customTags = Object.entries( cache )
|
|
13
|
+
.filter( ( [ , widgetData ] ) => !! widgetData.atomic_controls )
|
|
14
|
+
.map( ( [ widgetType, widgetData ] ) => {
|
|
15
|
+
const configurationSchema = widgetData; //getElementSchemaAsJsonSchema( widgetType );
|
|
16
|
+
return {
|
|
17
|
+
tag: `${ widgetType }`,
|
|
18
|
+
description: widgetData.title || widgetData.elType || `A ${ widgetType } element`,
|
|
19
|
+
configurationSchema: JSON.stringify( configurationSchema ),
|
|
20
|
+
};
|
|
21
|
+
} );
|
|
22
|
+
return customTags;
|
|
23
|
+
};
|