@elementor/editor-canvas 4.3.0-992 → 4.3.0-994
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +181 -901
- package/dist/index.mjs +124 -855
- package/package.json +20 -20
- package/src/index.ts +1 -1
- package/src/mcp/canvas-mcp.ts +2 -2
- package/src/mcp/tools/build-composition/tool.ts +107 -218
- package/src/sync/element-added-event.ts +8 -0
- package/src/composition-builder/__tests__/composition-builder.test.ts +0 -352
- package/src/composition-builder/composition-builder.ts +0 -350
- package/src/composition-builder/utils/__tests__/required-children-enforcer.test.ts +0 -79
- package/src/composition-builder/utils/__tests__/required-default-child-tags.test.ts +0 -35
- package/src/composition-builder/utils/required-children-enforcer.ts +0 -56
- package/src/composition-builder/utils/required-default-child-tags.ts +0 -22
- package/src/mcp/tools/build-composition/__tests__/xml-leaf-wrapper.test.ts +0 -117
- package/src/mcp/tools/build-composition/prompt.ts +0 -167
- package/src/mcp/tools/build-composition/schema.ts +0 -42
- package/src/mcp/tools/build-composition/xml-leaf-wrapper.ts +0 -68
- package/src/mcp/utils/__tests__/get-composition-target-container.test.ts +0 -59
- package/src/mcp/utils/get-composition-target-container.ts +0 -15
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@elementor/editor-canvas",
|
|
3
3
|
"description": "Elementor Editor Canvas",
|
|
4
|
-
"version": "4.3.0-
|
|
4
|
+
"version": "4.3.0-994",
|
|
5
5
|
"private": false,
|
|
6
6
|
"author": "Elementor Team",
|
|
7
7
|
"homepage": "https://elementor.com/",
|
|
@@ -37,26 +37,26 @@
|
|
|
37
37
|
"react-dom": "^18.3.1"
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@elementor/editor": "4.3.0-
|
|
41
|
-
"@elementor/editor-controls": "4.3.0-
|
|
42
|
-
"@elementor/editor-documents": "4.3.0-
|
|
43
|
-
"@elementor/editor-elements": "4.3.0-
|
|
44
|
-
"@elementor/editor-interactions": "4.3.0-
|
|
45
|
-
"@elementor/editor-mcp": "4.3.0-
|
|
46
|
-
"@elementor/editor-notifications": "4.3.0-
|
|
47
|
-
"@elementor/editor-props": "4.3.0-
|
|
48
|
-
"@elementor/editor-responsive": "4.3.0-
|
|
49
|
-
"@elementor/editor-styles": "4.3.0-
|
|
50
|
-
"@elementor/editor-styles-repository": "4.3.0-
|
|
51
|
-
"@elementor/editor-ui": "4.3.0-
|
|
52
|
-
"@elementor/editor-v1-adapters": "4.3.0-
|
|
53
|
-
"@elementor/events": "4.3.0-
|
|
54
|
-
"@elementor/http-client": "4.3.0-
|
|
55
|
-
"@elementor/schema": "4.3.0-
|
|
56
|
-
"@elementor/twing": "4.3.0-
|
|
40
|
+
"@elementor/editor": "4.3.0-994",
|
|
41
|
+
"@elementor/editor-controls": "4.3.0-994",
|
|
42
|
+
"@elementor/editor-documents": "4.3.0-994",
|
|
43
|
+
"@elementor/editor-elements": "4.3.0-994",
|
|
44
|
+
"@elementor/editor-interactions": "4.3.0-994",
|
|
45
|
+
"@elementor/editor-mcp": "4.3.0-994",
|
|
46
|
+
"@elementor/editor-notifications": "4.3.0-994",
|
|
47
|
+
"@elementor/editor-props": "4.3.0-994",
|
|
48
|
+
"@elementor/editor-responsive": "4.3.0-994",
|
|
49
|
+
"@elementor/editor-styles": "4.3.0-994",
|
|
50
|
+
"@elementor/editor-styles-repository": "4.3.0-994",
|
|
51
|
+
"@elementor/editor-ui": "4.3.0-994",
|
|
52
|
+
"@elementor/editor-v1-adapters": "4.3.0-994",
|
|
53
|
+
"@elementor/events": "4.3.0-994",
|
|
54
|
+
"@elementor/http-client": "4.3.0-994",
|
|
55
|
+
"@elementor/schema": "4.3.0-994",
|
|
56
|
+
"@elementor/twing": "4.3.0-994",
|
|
57
57
|
"@elementor/ui": "1.37.5",
|
|
58
|
-
"@elementor/utils": "4.3.0-
|
|
59
|
-
"@elementor/wp-media": "4.3.0-
|
|
58
|
+
"@elementor/utils": "4.3.0-994",
|
|
59
|
+
"@elementor/wp-media": "4.3.0-994",
|
|
60
60
|
"@floating-ui/react": "^0.27.5",
|
|
61
61
|
"@wordpress/i18n": "^5.13.0",
|
|
62
62
|
"dompurify": "^3.2.6"
|
package/src/index.ts
CHANGED
|
@@ -44,4 +44,4 @@ export { UnknownStyleTypeError, UnknownStyleStateError } from './renderers/error
|
|
|
44
44
|
export { useCanvasDocument } from './hooks/use-canvas-document';
|
|
45
45
|
export { useEscapeOnCanvas } from './hooks/use-escape-on-canvas';
|
|
46
46
|
export { doAfterRender } from './utils/after-render';
|
|
47
|
-
export { ELEMENT_ADDED_EVENT, type ElementAddedEvent } from './
|
|
47
|
+
export { ELEMENT_ADDED_EVENT, type ElementAddedEvent } from './sync/element-added-event';
|
package/src/mcp/canvas-mcp.ts
CHANGED
|
@@ -10,7 +10,7 @@ import { initEditorStateResource } from './resources/editor-state-resource';
|
|
|
10
10
|
import { initGeneralContextResource } from './resources/general-context-resource';
|
|
11
11
|
import { initSelectedElementResource } from './resources/selected-element-resource';
|
|
12
12
|
import { initWidgetsSchemaResource } from './resources/widgets-schema-resource';
|
|
13
|
-
import {
|
|
13
|
+
import { initBuildCompositionTool } from './tools/build-composition/tool';
|
|
14
14
|
import { initConfigureElementTool } from './tools/configure-element/tool';
|
|
15
15
|
import { initCreateElementTool } from './tools/create-element/tool';
|
|
16
16
|
import { initGetElementConfigTool } from './tools/get-element-config/tool';
|
|
@@ -29,9 +29,9 @@ export const initCanvasMcp = ( reg: MCPRegistryEntry ) => {
|
|
|
29
29
|
initEditorStateResource( reg );
|
|
30
30
|
initGeneralContextResource( reg );
|
|
31
31
|
initBestPracticesResource( reg );
|
|
32
|
-
initBuildCompositionsTool( reg );
|
|
33
32
|
initGetElementConfigTool( reg );
|
|
34
33
|
initConfigureElementTool( reg );
|
|
35
34
|
initCreateElementTool( reg );
|
|
35
|
+
initBuildCompositionTool( reg );
|
|
36
36
|
initBreakpointsResource( reg );
|
|
37
37
|
};
|
|
@@ -1,244 +1,133 @@
|
|
|
1
|
-
import { getCurrentDocument } from '@elementor/editor-documents';
|
|
2
|
-
import {
|
|
3
|
-
createElement,
|
|
4
|
-
deleteElement,
|
|
5
|
-
getContainer,
|
|
6
|
-
getWidgetsCache,
|
|
7
|
-
type V1Element,
|
|
8
|
-
type V1ElementData,
|
|
9
|
-
} from '@elementor/editor-elements';
|
|
1
|
+
import { getCurrentDocument, reloadCurrentDocument } from '@elementor/editor-documents';
|
|
2
|
+
import { getContainer, selectElement } from '@elementor/editor-elements';
|
|
10
3
|
import { type MCPRegistryEntry } from '@elementor/editor-mcp';
|
|
11
|
-
import {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
export type ElementAddedEvent = {
|
|
26
|
-
element: V1ElementData;
|
|
27
|
-
executedBy: 'mcp_tool' | 'user';
|
|
4
|
+
import { AxiosError, type HttpResponse, httpService } from '@elementor/http-client';
|
|
5
|
+
import { z } from '@elementor/schema';
|
|
6
|
+
|
|
7
|
+
const MCP_PROXY_URL = 'elementor/v1/mcp-proxy';
|
|
8
|
+
|
|
9
|
+
type BuildCompositionResponse = {
|
|
10
|
+
success: boolean;
|
|
11
|
+
post_id: number;
|
|
12
|
+
root_element_ids: string[];
|
|
13
|
+
preview_url: string;
|
|
14
|
+
version: string;
|
|
15
|
+
resolved_xml: string;
|
|
16
|
+
llm_instructions: string;
|
|
17
|
+
warnings?: string[];
|
|
28
18
|
};
|
|
29
19
|
|
|
30
|
-
export const
|
|
31
|
-
|
|
32
|
-
export const initBuildCompositionsTool = ( reg: MCPRegistryEntry ) => {
|
|
33
|
-
const { addTool, resource } = reg;
|
|
20
|
+
export const initBuildCompositionTool = ( reg: MCPRegistryEntry ) => {
|
|
21
|
+
const { addTool } = reg;
|
|
34
22
|
|
|
35
|
-
|
|
36
|
-
'build-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
23
|
+
addTool( {
|
|
24
|
+
name: 'build-composition',
|
|
25
|
+
description:
|
|
26
|
+
'Build a V4 element composition on the Elementor canvas via the server-side MCP ability. ' +
|
|
27
|
+
'Pass the raw XML tags directly as xmlStructure — do NOT wrap the value in <![CDATA[ ... ]]>, ' +
|
|
28
|
+
'code fences, or quotes. The document is saved as a draft. Reload the editor after calling ' +
|
|
29
|
+
'this tool to see the result.',
|
|
30
|
+
schema: {
|
|
31
|
+
xmlStructure: z
|
|
32
|
+
.string()
|
|
33
|
+
.describe(
|
|
34
|
+
'Valid XML structure with custom Elementor widget tags. Every element MUST have a unique ' +
|
|
35
|
+
'configuration-id attribute (e.g. <e-heading configuration-id="hero-title"></e-heading>). ' +
|
|
36
|
+
'No attributes, classes, IDs, or text nodes in XML. Pass raw XML — do not wrap in CDATA.'
|
|
37
|
+
),
|
|
38
|
+
elementConfig: z
|
|
39
|
+
.record(
|
|
40
|
+
z.string().describe( 'configuration-id' ),
|
|
41
|
+
z.record( z.string().describe( 'property name' ), z.any().describe( 'PropValue' ) )
|
|
42
|
+
)
|
|
43
|
+
.optional()
|
|
44
|
+
.describe( 'Map configuration-id → widget PropValues ($$type + value).' ),
|
|
45
|
+
style: z
|
|
46
|
+
.record(
|
|
47
|
+
z.string().describe( 'configuration-id' ),
|
|
48
|
+
z.record( z.string().describe( 'CSS property name' ), z.string().describe( 'CSS value' ) )
|
|
49
|
+
)
|
|
50
|
+
.optional()
|
|
51
|
+
.describe(
|
|
52
|
+
'Map configuration-id → raw CSS declarations (property → value strings; no selectors). ' +
|
|
53
|
+
'Server converts to native styles; unconvertible declarations become the element custom CSS.'
|
|
54
|
+
),
|
|
55
|
+
parentId: z
|
|
56
|
+
.string()
|
|
57
|
+
.optional()
|
|
58
|
+
.describe( "ID of the parent container. Omit or pass 'document' to insert at document root." ),
|
|
59
|
+
dryRun: z
|
|
60
|
+
.boolean()
|
|
61
|
+
.optional()
|
|
62
|
+
.describe( 'If true, validate and return the resolved tree without persisting.' ),
|
|
63
|
+
},
|
|
64
|
+
outputSchema: {
|
|
65
|
+
rootElementIds: z.array( z.string() ),
|
|
66
|
+
previewUrl: z.string(),
|
|
67
|
+
version: z.string(),
|
|
68
|
+
resolvedXml: z.string(),
|
|
69
|
+
llmInstructions: z.string(),
|
|
70
|
+
warnings: z.array( z.string() ).optional(),
|
|
42
71
|
},
|
|
43
|
-
async (
|
|
44
|
-
|
|
45
|
-
} )
|
|
46
|
-
);
|
|
72
|
+
handler: async ( { xmlStructure, elementConfig, style, parentId, dryRun } ) => {
|
|
73
|
+
const document = getCurrentDocument();
|
|
47
74
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
schema,
|
|
52
|
-
requiredResources: [
|
|
53
|
-
{ description: 'Build compositions guide', uri: BUILD_COMPOSITIONS_GUIDE_URI },
|
|
54
|
-
{ description: 'Widgets schema', uri: WIDGET_SCHEMA_URI },
|
|
55
|
-
{ description: 'Global Classes', uri: 'elementor://global-classes' },
|
|
56
|
-
{ description: 'Global Variables', uri: 'elementor://global-variables' },
|
|
57
|
-
{ description: 'Styles best practices', uri: BEST_PRACTICES_URI },
|
|
58
|
-
{ description: 'Available widgets for this tool', uri: AVAILABLE_WIDGETS_URI_V4 },
|
|
59
|
-
{ description: 'Dynamic tags catalog', uri: DYNAMIC_TAGS_URI },
|
|
60
|
-
],
|
|
61
|
-
outputSchema,
|
|
62
|
-
handler: async ( rawParams ) => {
|
|
63
|
-
assertCompositionXmlUsesV4WidgetsOnly( rawParams.xmlStructure );
|
|
64
|
-
const { stylesConfig: convertedStyles, customCSS } = await convertCompositionStyles( rawParams.style );
|
|
65
|
-
const { xmlStructure, elementConfig, stylesConfig } = adaptLeafRootParams( {
|
|
66
|
-
...rawParams,
|
|
67
|
-
stylesConfig: convertedStyles,
|
|
68
|
-
widgetsCache: getWidgetsCache() ?? {},
|
|
69
|
-
} );
|
|
75
|
+
if ( ! document?.id ) {
|
|
76
|
+
throw new Error( 'No active document found.' );
|
|
77
|
+
}
|
|
70
78
|
|
|
71
|
-
let generatedXML: string = '';
|
|
72
|
-
const errors: Error[] = [];
|
|
73
|
-
const rootContainers: V1Element[] = [];
|
|
74
|
-
const documentContainer = getContainer( 'document' ) as unknown as V1Element;
|
|
75
|
-
const currentDocument = getCurrentDocument();
|
|
76
|
-
const targetContainer = getCompositionTargetContainer( documentContainer, currentDocument?.type.value );
|
|
77
79
|
try {
|
|
78
|
-
const
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
80
|
+
const { data } = await httpService().post< HttpResponse< BuildCompositionResponse > >( MCP_PROXY_URL, {
|
|
81
|
+
tool: 'build-composition',
|
|
82
|
+
input: {
|
|
83
|
+
post_id: document.id,
|
|
84
|
+
xml_structure: xmlStructure,
|
|
85
|
+
element_config: elementConfig ?? {},
|
|
86
|
+
style: style ?? {},
|
|
87
|
+
parent_id: parentId ?? 'document',
|
|
88
|
+
dry_run: dryRun ?? false,
|
|
89
|
+
},
|
|
82
90
|
} );
|
|
83
|
-
compositionBuilder.setElementConfig( elementConfig );
|
|
84
|
-
compositionBuilder.setStylesConfig( stylesConfig );
|
|
85
|
-
compositionBuilder.setCustomCSS( customCSS );
|
|
86
|
-
|
|
87
|
-
const {
|
|
88
|
-
configErrors,
|
|
89
|
-
formErrors,
|
|
90
|
-
rootContainers: generatedRootContainers,
|
|
91
|
-
} = await compositionBuilder.build( targetContainer );
|
|
92
|
-
|
|
93
|
-
rootContainers.push( ...generatedRootContainers );
|
|
94
|
-
generatedXML = new XMLSerializer().serializeToString( compositionBuilder.getXML() );
|
|
95
91
|
|
|
96
|
-
|
|
97
|
-
|
|
92
|
+
if ( ! dryRun ) {
|
|
93
|
+
await reloadCurrentDocument();
|
|
98
94
|
|
|
99
|
-
|
|
100
|
-
|
|
95
|
+
const [ firstRootId ] = data.data.root_element_ids;
|
|
96
|
+
if ( firstRootId ) {
|
|
97
|
+
selectElement( firstRootId );
|
|
98
|
+
getContainer( firstRootId )?.view?.el?.scrollIntoView( {
|
|
99
|
+
behavior: 'smooth',
|
|
100
|
+
block: 'center',
|
|
101
|
+
} );
|
|
101
102
|
}
|
|
102
|
-
} );
|
|
103
|
-
|
|
104
|
-
Object.values( stylesConfig ).forEach( ( styleValue ) => {
|
|
105
|
-
dispatchMcpStylesAppliedEvent( { styleValue } );
|
|
106
|
-
} );
|
|
107
|
-
|
|
108
|
-
if ( configErrors.length ) {
|
|
109
|
-
errors.push( ...configErrors.map( ( msg ) => new Error( msg ) ) );
|
|
110
103
|
}
|
|
111
104
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
105
|
+
return {
|
|
106
|
+
rootElementIds: data.data.root_element_ids,
|
|
107
|
+
previewUrl: data.data.preview_url,
|
|
108
|
+
version: data.data.version,
|
|
109
|
+
resolvedXml: data.data.resolved_xml,
|
|
110
|
+
llmInstructions: data.data.llm_instructions,
|
|
111
|
+
warnings: data.data.warnings,
|
|
112
|
+
};
|
|
115
113
|
} catch ( error ) {
|
|
116
|
-
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
if ( errors.length ) {
|
|
120
|
-
rootContainers.forEach( ( rootContainer ) => {
|
|
121
|
-
deleteElement( {
|
|
122
|
-
container: rootContainer,
|
|
123
|
-
options: { useHistory: false },
|
|
124
|
-
} );
|
|
125
|
-
} );
|
|
126
|
-
|
|
127
|
-
const errorMessages = errors
|
|
128
|
-
.map( ( e ) => {
|
|
129
|
-
if ( typeof e === 'string' ) {
|
|
130
|
-
return e;
|
|
131
|
-
}
|
|
132
|
-
if ( e instanceof Error ) {
|
|
133
|
-
return e.message || String( e );
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
if ( typeof e === 'object' && e !== null ) {
|
|
137
|
-
return JSON.stringify( e );
|
|
138
|
-
}
|
|
139
|
-
return String( e );
|
|
140
|
-
} )
|
|
141
|
-
.filter(
|
|
142
|
-
( msg ) => msg && msg.trim() !== '' && msg !== '{}' && msg !== 'null' && msg !== 'undefined'
|
|
143
|
-
);
|
|
144
|
-
|
|
145
|
-
if ( errorMessages.length === 0 ) {
|
|
146
|
-
throw new Error(
|
|
147
|
-
'Failed to build composition: Unknown error occurred. No error details available.'
|
|
148
|
-
);
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
const errorText = `Failed to build composition with the following errors:\n\n${ errorMessages.join(
|
|
152
|
-
'\n\n'
|
|
153
|
-
) }`;
|
|
154
|
-
throw new Error( errorText );
|
|
114
|
+
throw new Error( getErrorMessage( error ) );
|
|
155
115
|
}
|
|
156
|
-
return {
|
|
157
|
-
xmlStructure: generatedXML,
|
|
158
|
-
errors: errors?.length
|
|
159
|
-
? errors.map( ( e ) => ( typeof e === 'string' ? e : e.message ) ).join( '\n\n' )
|
|
160
|
-
: undefined,
|
|
161
|
-
llm_instructions: `The composition was built successfully with element IDs embedded in the XML.
|
|
162
|
-
|
|
163
|
-
**CRITICAL NEXT STEPS** (Follow in order):
|
|
164
|
-
1. **Apply Global Classes**: Use "apply-global-class" tool to apply the global classes you created BEFORE building this composition
|
|
165
|
-
- Check the created element IDs in the returned XML
|
|
166
|
-
- Apply semantic classes (heading-primary, button-cta, etc.) to appropriate elements
|
|
167
|
-
|
|
168
|
-
2. **Fine-tune if needed**: Use "configure-element" tool only for element-specific adjustments that don't warrant global classes
|
|
169
|
-
|
|
170
|
-
Remember: Global classes ensure design consistency and reusability. Don't skip applying them!
|
|
171
|
-
`,
|
|
172
|
-
};
|
|
173
116
|
},
|
|
174
117
|
} );
|
|
175
118
|
};
|
|
176
119
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
return { stylesConfig, customCSS };
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
const results = await convertStyleBlocksToAtomic( style );
|
|
186
|
-
|
|
187
|
-
for ( const [ configId, { props, customCss } ] of Object.entries( results ) ) {
|
|
188
|
-
stylesConfig[ configId ] = props;
|
|
189
|
-
if ( customCss ) {
|
|
190
|
-
customCSS[ configId ] = customCss;
|
|
120
|
+
function getErrorMessage( error: unknown ): string {
|
|
121
|
+
if ( error instanceof AxiosError ) {
|
|
122
|
+
const data = error.response?.data as { message?: string; code?: string } | undefined;
|
|
123
|
+
if ( data?.message ) {
|
|
124
|
+
return data.code ? `${ data.code }: ${ data.message }` : data.message;
|
|
191
125
|
}
|
|
192
126
|
}
|
|
193
127
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
function assertCompositionXmlUsesV4WidgetsOnly( xmlStructure: string ) {
|
|
198
|
-
const doc = new DOMParser().parseFromString( xmlStructure, 'application/xml' );
|
|
199
|
-
if ( doc.querySelector( 'parsererror' ) ) {
|
|
200
|
-
throw new Error( 'Failed to parse XML string: ' + doc );
|
|
128
|
+
if ( error instanceof Error ) {
|
|
129
|
+
return error.message;
|
|
201
130
|
}
|
|
202
|
-
const widgetsCache = getWidgetsCache() ?? {};
|
|
203
|
-
for ( const node of doc.querySelectorAll( '*' ) ) {
|
|
204
|
-
const type = node.tagName;
|
|
205
|
-
const widgetData = widgetsCache[ type ];
|
|
206
131
|
|
|
207
|
-
|
|
208
|
-
continue;
|
|
209
|
-
}
|
|
210
|
-
if ( widgetData.elType !== 'widget' ) {
|
|
211
|
-
continue;
|
|
212
|
-
}
|
|
213
|
-
if ( ! isWidgetAvailableForLLM( widgetData ) || ! widgetData.atomic_props_schema ) {
|
|
214
|
-
throw new Error( `This tool does not support element type: ${ type }` );
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
function onElementAdded( element: V1ElementData ) {
|
|
220
|
-
const elType = element.elType ?? '';
|
|
221
|
-
const widgetType = element.widgetType ?? '';
|
|
222
|
-
const elementName = elType === 'widget' ? widgetType : elType;
|
|
223
|
-
|
|
224
|
-
trackCanvasEvent( {
|
|
225
|
-
eventName: 'add_element',
|
|
226
|
-
executed_by: 'mcp_tool',
|
|
227
|
-
element_name: elementName,
|
|
228
|
-
element_type: elType,
|
|
229
|
-
widget_type: widgetType,
|
|
230
|
-
} );
|
|
231
|
-
|
|
232
|
-
const event: ElementAddedEvent = {
|
|
233
|
-
element,
|
|
234
|
-
executedBy: 'mcp_tool',
|
|
235
|
-
};
|
|
236
|
-
|
|
237
|
-
window.dispatchEvent( new CustomEvent( ELEMENT_ADDED_EVENT, { detail: event } ) );
|
|
238
|
-
|
|
239
|
-
if ( element.elements?.length ) {
|
|
240
|
-
element.elements?.forEach( ( childElement ) => {
|
|
241
|
-
onElementAdded( childElement );
|
|
242
|
-
} );
|
|
243
|
-
}
|
|
132
|
+
return 'build-composition failed with an unknown error.';
|
|
244
133
|
}
|