@elementor/editor-components 3.35.0-356 → 3.35.0-358
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +364 -58
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +360 -54
- package/dist/index.mjs.map +1 -1
- package/package.json +21 -21
- package/src/api.ts +27 -5
- package/src/component-instance-transformer.ts +29 -5
- package/src/component-overridable-transformer.ts +52 -5
- package/src/component-override-transformer.ts +9 -0
- package/src/components/create-component-form/utils/replace-element-with-component.ts +4 -0
- package/src/create-component-type.ts +9 -2
- package/src/init.ts +2 -0
- package/src/mcp/save-as-component-tool.ts +333 -29
- package/src/store/actions/create-unpublished-component.ts +9 -6
- package/src/store/store.ts +5 -1
- package/src/sync/create-components-before-save.ts +2 -0
- package/src/types.ts +1 -1
package/dist/index.mjs
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { injectIntoLogic, injectIntoTop } from "@elementor/editor";
|
|
3
3
|
import {
|
|
4
4
|
registerElementType,
|
|
5
|
-
settingsTransformersRegistry
|
|
5
|
+
settingsTransformersRegistry as settingsTransformersRegistry2
|
|
6
6
|
} from "@elementor/editor-canvas";
|
|
7
7
|
import { getV1CurrentDocument } from "@elementor/editor-documents";
|
|
8
8
|
import {
|
|
@@ -19,7 +19,7 @@ import { __registerSlice as registerSlice } from "@elementor/store";
|
|
|
19
19
|
import { __ as __17 } from "@wordpress/i18n";
|
|
20
20
|
|
|
21
21
|
// src/component-instance-transformer.ts
|
|
22
|
-
import { createTransformer } from "@elementor/editor-canvas";
|
|
22
|
+
import { createTransformer, RenderContext } from "@elementor/editor-canvas";
|
|
23
23
|
import { __getState as getState } from "@elementor/store";
|
|
24
24
|
|
|
25
25
|
// src/store/store.ts
|
|
@@ -73,7 +73,8 @@ var apiClient = {
|
|
|
73
73
|
{
|
|
74
74
|
componentIds
|
|
75
75
|
}
|
|
76
|
-
).then((res) => res.data.data)
|
|
76
|
+
).then((res) => res.data.data),
|
|
77
|
+
validate: async (payload) => await httpService().post(`${BASE_URL}/create-validate`, payload).then((res) => res.data)
|
|
77
78
|
};
|
|
78
79
|
|
|
79
80
|
// src/store/thunks.ts
|
|
@@ -173,7 +174,11 @@ var selectComponents = createSelector(
|
|
|
173
174
|
selectData,
|
|
174
175
|
selectUnpublishedData,
|
|
175
176
|
(data, unpublishedData) => [
|
|
176
|
-
...unpublishedData.map((item) => ({
|
|
177
|
+
...unpublishedData.map((item) => ({
|
|
178
|
+
uid: item.uid,
|
|
179
|
+
name: item.name,
|
|
180
|
+
overridableProps: item.overridableProps
|
|
181
|
+
})),
|
|
177
182
|
...data
|
|
178
183
|
]
|
|
179
184
|
);
|
|
@@ -237,25 +242,73 @@ var invalidateComponentDocumentData = (id) => {
|
|
|
237
242
|
};
|
|
238
243
|
|
|
239
244
|
// src/component-instance-transformer.ts
|
|
245
|
+
var componentInstanceContext = new RenderContext("component-instance", {
|
|
246
|
+
overrides: {}
|
|
247
|
+
});
|
|
240
248
|
var componentInstanceTransformer = createTransformer(
|
|
241
|
-
async ({
|
|
249
|
+
async ({
|
|
250
|
+
component_id: id,
|
|
251
|
+
overrides: overridesValue
|
|
252
|
+
}) => {
|
|
242
253
|
const unpublishedComponents = selectUnpublishedComponents(getState());
|
|
243
254
|
const unpublishedComponent = unpublishedComponents.find(({ uid }) => uid === id);
|
|
255
|
+
const overrides = overridesValue?.reduce((acc, override) => ({ ...acc, ...override }), {});
|
|
244
256
|
if (unpublishedComponent) {
|
|
245
|
-
return
|
|
257
|
+
return {
|
|
258
|
+
elements: structuredClone(unpublishedComponent.elements),
|
|
259
|
+
overrides
|
|
260
|
+
};
|
|
246
261
|
}
|
|
247
262
|
if (typeof id !== "number") {
|
|
248
|
-
throw new Error(`Component ID "${id}" not
|
|
263
|
+
throw new Error(`Component ID "${id}" not valid.`);
|
|
249
264
|
}
|
|
250
265
|
const data = await getComponentDocumentData(id);
|
|
251
|
-
return
|
|
266
|
+
return {
|
|
267
|
+
elements: data?.elements ?? [],
|
|
268
|
+
overrides
|
|
269
|
+
};
|
|
252
270
|
}
|
|
253
271
|
);
|
|
254
272
|
|
|
255
273
|
// src/component-overridable-transformer.ts
|
|
256
|
-
import { createTransformer as createTransformer2 } from "@elementor/editor-canvas";
|
|
257
|
-
var componentOverridableTransformer = createTransformer2(
|
|
258
|
-
|
|
274
|
+
import { createTransformer as createTransformer2, settingsTransformersRegistry } from "@elementor/editor-canvas";
|
|
275
|
+
var componentOverridableTransformer = createTransformer2(
|
|
276
|
+
(value, options) => {
|
|
277
|
+
const { overrides } = componentInstanceContext.get();
|
|
278
|
+
const overrideValue = overrides?.[value.override_key];
|
|
279
|
+
if (overrideValue) {
|
|
280
|
+
const isOverride = isOriginValueOverride(value.origin_value);
|
|
281
|
+
if (isOverride) {
|
|
282
|
+
return transformOverride(value, options, overrideValue);
|
|
283
|
+
}
|
|
284
|
+
return overrideValue;
|
|
285
|
+
}
|
|
286
|
+
return value.origin_value;
|
|
287
|
+
}
|
|
288
|
+
);
|
|
289
|
+
function transformOverride(value, options, overrideValue) {
|
|
290
|
+
const transformer = settingsTransformersRegistry.get("override");
|
|
291
|
+
if (!transformer) {
|
|
292
|
+
return null;
|
|
293
|
+
}
|
|
294
|
+
const transformedValue = transformer(value.origin_value.value, options);
|
|
295
|
+
if (!transformedValue) {
|
|
296
|
+
return null;
|
|
297
|
+
}
|
|
298
|
+
const [key] = Object.keys(transformedValue);
|
|
299
|
+
return {
|
|
300
|
+
[key]: overrideValue
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
function isOriginValueOverride(originValue) {
|
|
304
|
+
return originValue.$$type === "override";
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
// src/component-override-transformer.ts
|
|
308
|
+
import { createTransformer as createTransformer3 } from "@elementor/editor-canvas";
|
|
309
|
+
var componentOverrideTransformer = createTransformer3((override) => {
|
|
310
|
+
const { override_key: key, override_value: overrideValue } = override;
|
|
311
|
+
return { [key]: overrideValue };
|
|
259
312
|
});
|
|
260
313
|
|
|
261
314
|
// src/components/component-panel-header/component-panel-header.tsx
|
|
@@ -567,9 +620,10 @@ function createComponentView(options) {
|
|
|
567
620
|
return currentDocument?.id === this.getComponentId();
|
|
568
621
|
}
|
|
569
622
|
afterSettingsResolve(settings) {
|
|
570
|
-
|
|
623
|
+
const componentInstance = settings.component_instance;
|
|
624
|
+
if (componentInstance) {
|
|
571
625
|
this.collection = this.legacyWindow.elementor.createBackboneElementsCollection(
|
|
572
|
-
|
|
626
|
+
componentInstance.elements
|
|
573
627
|
);
|
|
574
628
|
this.collection.models.forEach(setInactiveRecursively);
|
|
575
629
|
settings.component_instance = "<template data-children-placeholder></template>";
|
|
@@ -843,7 +897,8 @@ var createComponentModel = (component) => {
|
|
|
843
897
|
value: component.id ?? component.uid
|
|
844
898
|
}
|
|
845
899
|
}
|
|
846
|
-
}
|
|
900
|
+
},
|
|
901
|
+
overridable_props: component.overridableProps
|
|
847
902
|
},
|
|
848
903
|
editor_settings: {
|
|
849
904
|
title: component.name,
|
|
@@ -1116,25 +1171,25 @@ import { __ as __8 } from "@wordpress/i18n";
|
|
|
1116
1171
|
import { __privateRunCommand as runCommand2 } from "@elementor/editor-v1-adapters";
|
|
1117
1172
|
import { __dispatch as dispatch3 } from "@elementor/store";
|
|
1118
1173
|
import { generateUniqueId } from "@elementor/utils";
|
|
1119
|
-
function createUnpublishedComponent(name, element, eventData) {
|
|
1120
|
-
const
|
|
1121
|
-
const componentBase = { uid, name };
|
|
1174
|
+
function createUnpublishedComponent(name, element, eventData, overridableProps, uid) {
|
|
1175
|
+
const generatedUid = uid ?? generateUniqueId("component");
|
|
1176
|
+
const componentBase = { uid: generatedUid, name, overridableProps };
|
|
1122
1177
|
dispatch3(
|
|
1123
1178
|
slice.actions.addUnpublished({
|
|
1124
1179
|
...componentBase,
|
|
1125
1180
|
elements: [element]
|
|
1126
1181
|
})
|
|
1127
1182
|
);
|
|
1128
|
-
dispatch3(slice.actions.addCreatedThisSession(
|
|
1183
|
+
dispatch3(slice.actions.addCreatedThisSession(generatedUid));
|
|
1129
1184
|
replaceElementWithComponent(element, componentBase);
|
|
1130
1185
|
trackComponentEvent({
|
|
1131
1186
|
action: "created",
|
|
1132
|
-
component_uid:
|
|
1187
|
+
component_uid: generatedUid,
|
|
1133
1188
|
component_name: name,
|
|
1134
1189
|
...eventData
|
|
1135
1190
|
});
|
|
1136
1191
|
runCommand2("document/save/auto");
|
|
1137
|
-
return
|
|
1192
|
+
return generatedUid;
|
|
1138
1193
|
}
|
|
1139
1194
|
|
|
1140
1195
|
// src/components/create-component-form/hooks/use-form.ts
|
|
@@ -2273,72 +2328,320 @@ function isPropAllowed(bind) {
|
|
|
2273
2328
|
import { getMCPByDomain as getMCPByDomain2 } from "@elementor/editor-mcp";
|
|
2274
2329
|
|
|
2275
2330
|
// src/mcp/save-as-component-tool.ts
|
|
2276
|
-
import {
|
|
2277
|
-
import {
|
|
2331
|
+
import { DOCUMENT_STRUCTURE_URI, WIDGET_SCHEMA_URI } from "@elementor/editor-canvas";
|
|
2332
|
+
import { getContainer as getContainer2, getElementType, getWidgetsCache as getWidgetsCache2 } from "@elementor/editor-elements";
|
|
2333
|
+
import { getMCPByDomain, toolPrompts } from "@elementor/editor-mcp";
|
|
2334
|
+
import { AxiosError } from "@elementor/http-client";
|
|
2278
2335
|
import { z as z6 } from "@elementor/schema";
|
|
2336
|
+
import { generateUniqueId as generateUniqueId3 } from "@elementor/utils";
|
|
2279
2337
|
var InputSchema = {
|
|
2280
2338
|
element_id: z6.string().describe(
|
|
2281
2339
|
'The unique identifier of the element to save as a component. Use the "list-elements" tool to find available element IDs in the current document.'
|
|
2282
2340
|
),
|
|
2283
|
-
component_name: z6.string().describe("The name for the new component. Should be descriptive and unique among existing components.")
|
|
2341
|
+
component_name: z6.string().describe("The name for the new component. Should be descriptive and unique among existing components."),
|
|
2342
|
+
overridable_props: z6.object({
|
|
2343
|
+
props: z6.record(
|
|
2344
|
+
z6.object({
|
|
2345
|
+
elementId: z6.string().describe("The id of the child element that you want to override its settings"),
|
|
2346
|
+
propKey: z6.string().describe(
|
|
2347
|
+
'The property key of the child element that you want to override its settings (e.g., "text", "url", "tag"). To get the available propKeys for an element, use the "get-element-type-config" tool.'
|
|
2348
|
+
)
|
|
2349
|
+
})
|
|
2350
|
+
)
|
|
2351
|
+
}).optional().describe(
|
|
2352
|
+
'Overridable properties configuration. Specify which CHILD element properties can be customized. Only elementId and propKey are required; To get the available propKeys for a child element you must use the "get-element-type-config" tool.'
|
|
2353
|
+
)
|
|
2284
2354
|
};
|
|
2285
2355
|
var OutputSchema = {
|
|
2286
2356
|
message: z6.string().optional().describe("Additional information about the operation result"),
|
|
2287
2357
|
component_uid: z6.string().optional().describe("The unique identifier of the newly created component (only present on success)")
|
|
2288
2358
|
};
|
|
2289
|
-
var VALID_ELEMENT_TYPES = ["e-div-block", "e-flexbox", "e-tabs"];
|
|
2290
2359
|
var ERROR_MESSAGES = {
|
|
2291
2360
|
ELEMENT_NOT_FOUND: "Element not found. Use 'list-elements' to get valid element IDs.",
|
|
2292
|
-
ELEMENT_NOT_ONE_OF_TYPES: `Element is not one of the following types: ${
|
|
2361
|
+
ELEMENT_NOT_ONE_OF_TYPES: (validTypes) => `Element is not one of the following types: ${validTypes.join(", ")}`,
|
|
2293
2362
|
ELEMENT_IS_LOCKED: "Cannot save a locked element as a component."
|
|
2294
2363
|
};
|
|
2295
2364
|
var handleSaveAsComponent = async (params) => {
|
|
2296
|
-
const { element_id: elementId, component_name: componentName } = params;
|
|
2365
|
+
const { element_id: elementId, component_name: componentName, overridable_props: overridablePropsInput } = params;
|
|
2366
|
+
const validElementTypes = getValidElementTypes();
|
|
2297
2367
|
const container = getContainer2(elementId);
|
|
2298
2368
|
if (!container) {
|
|
2299
2369
|
throw new Error(ERROR_MESSAGES.ELEMENT_NOT_FOUND);
|
|
2300
2370
|
}
|
|
2301
2371
|
const elType = container.model.get("elType");
|
|
2302
|
-
if (!
|
|
2303
|
-
throw new Error(ERROR_MESSAGES.ELEMENT_NOT_ONE_OF_TYPES);
|
|
2372
|
+
if (!validElementTypes.includes(elType)) {
|
|
2373
|
+
throw new Error(ERROR_MESSAGES.ELEMENT_NOT_ONE_OF_TYPES(validElementTypes));
|
|
2304
2374
|
}
|
|
2305
2375
|
const element = container.model.toJSON({ remove: ["default"] });
|
|
2306
2376
|
if (element?.isLocked) {
|
|
2307
2377
|
throw new Error(ERROR_MESSAGES.ELEMENT_IS_LOCKED);
|
|
2308
2378
|
}
|
|
2309
|
-
const
|
|
2379
|
+
const overridableProps = overridablePropsInput ? enrichOverridableProps(overridablePropsInput, element) : void 0;
|
|
2380
|
+
if (overridableProps) {
|
|
2381
|
+
updateElementDataWithOverridableProps(element, overridableProps);
|
|
2382
|
+
}
|
|
2383
|
+
const uid = generateUniqueId3("component");
|
|
2384
|
+
try {
|
|
2385
|
+
await apiClient.validate({
|
|
2386
|
+
items: [
|
|
2387
|
+
{ uid, title: componentName, elements: [element], settings: { overridable_props: overridableProps } }
|
|
2388
|
+
]
|
|
2389
|
+
});
|
|
2390
|
+
} catch (error) {
|
|
2391
|
+
if (error instanceof AxiosError) {
|
|
2392
|
+
throw new Error(error.response?.data.messge);
|
|
2393
|
+
}
|
|
2394
|
+
throw new Error("Unknown error");
|
|
2395
|
+
}
|
|
2396
|
+
createUnpublishedComponent(componentName, element, null, overridableProps, uid);
|
|
2310
2397
|
return {
|
|
2311
2398
|
status: "ok",
|
|
2312
2399
|
message: `Component "${componentName}" created successfully.`,
|
|
2313
2400
|
component_uid: uid
|
|
2314
2401
|
};
|
|
2315
2402
|
};
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2403
|
+
function enrichOverridableProps(input, rootElement) {
|
|
2404
|
+
const enrichedProps = {};
|
|
2405
|
+
const defaultGroupId = generateUniqueId3("group");
|
|
2406
|
+
Object.entries(input.props).forEach(([, prop]) => {
|
|
2407
|
+
const { elementId, propKey } = prop;
|
|
2408
|
+
const element = findElementById(rootElement, elementId);
|
|
2409
|
+
if (!element) {
|
|
2410
|
+
throw new Error(`Element with ID "${elementId}" not found in component`);
|
|
2411
|
+
}
|
|
2412
|
+
const elType = element.elType;
|
|
2413
|
+
const widgetType = element.widgetType || element.elType;
|
|
2414
|
+
const elementType = getElementType(widgetType);
|
|
2415
|
+
if (!elementType) {
|
|
2416
|
+
throw new Error(
|
|
2417
|
+
`Element type "${widgetType}" is not atomic or does not have a settings schema. Cannot expose property "${propKey}" for element "${elementId}".`
|
|
2418
|
+
);
|
|
2419
|
+
}
|
|
2420
|
+
if (!elementType.propsSchema[propKey]) {
|
|
2421
|
+
const availableProps = Object.keys(elementType.propsSchema).join(", ");
|
|
2422
|
+
throw new Error(
|
|
2423
|
+
`Property "${propKey}" does not exist in element "${elementId}" (type: ${widgetType}). Available properties: ${availableProps}`
|
|
2424
|
+
);
|
|
2425
|
+
}
|
|
2426
|
+
const overrideKey = generateUniqueId3("prop");
|
|
2427
|
+
const originValue = element.settings?.[propKey] ? element.settings[propKey] : elementType.propsSchema[propKey].default ?? null;
|
|
2428
|
+
const label = generateLabel(propKey);
|
|
2429
|
+
enrichedProps[overrideKey] = {
|
|
2430
|
+
overrideKey,
|
|
2431
|
+
label,
|
|
2432
|
+
elementId,
|
|
2433
|
+
propKey,
|
|
2434
|
+
elType,
|
|
2435
|
+
widgetType,
|
|
2436
|
+
originValue,
|
|
2437
|
+
groupId: defaultGroupId
|
|
2438
|
+
};
|
|
2439
|
+
});
|
|
2440
|
+
return {
|
|
2441
|
+
props: enrichedProps,
|
|
2442
|
+
groups: {
|
|
2443
|
+
items: {
|
|
2444
|
+
[defaultGroupId]: {
|
|
2445
|
+
id: defaultGroupId,
|
|
2446
|
+
label: "Default",
|
|
2447
|
+
props: Object.keys(enrichedProps)
|
|
2448
|
+
}
|
|
2449
|
+
},
|
|
2450
|
+
order: [defaultGroupId]
|
|
2451
|
+
}
|
|
2452
|
+
};
|
|
2453
|
+
}
|
|
2454
|
+
function updateElementDataWithOverridableProps(rootElement, overridableProps) {
|
|
2455
|
+
Object.values(overridableProps.props).forEach((prop) => {
|
|
2456
|
+
const element = findElementById(rootElement, prop.elementId);
|
|
2457
|
+
if (!element || !element.settings) {
|
|
2458
|
+
return;
|
|
2459
|
+
}
|
|
2460
|
+
element.settings[prop.propKey] = {
|
|
2461
|
+
$$type: "overridable",
|
|
2462
|
+
value: {
|
|
2463
|
+
override_key: prop.overrideKey,
|
|
2464
|
+
origin_value: prop.originValue
|
|
2465
|
+
}
|
|
2466
|
+
};
|
|
2467
|
+
});
|
|
2468
|
+
}
|
|
2469
|
+
function findElementById(root, targetId) {
|
|
2470
|
+
if (root.id === targetId) {
|
|
2471
|
+
return root;
|
|
2472
|
+
}
|
|
2473
|
+
if (root.elements) {
|
|
2474
|
+
for (const child of root.elements) {
|
|
2475
|
+
const found = findElementById(child, targetId);
|
|
2476
|
+
if (found) {
|
|
2477
|
+
return found;
|
|
2478
|
+
}
|
|
2479
|
+
}
|
|
2480
|
+
}
|
|
2481
|
+
return null;
|
|
2482
|
+
}
|
|
2483
|
+
function generateLabel(propKey) {
|
|
2484
|
+
const uniqueId = generateUniqueId3("prop");
|
|
2485
|
+
return `${uniqueId} - ${propKey}`;
|
|
2486
|
+
}
|
|
2487
|
+
function getValidElementTypes() {
|
|
2488
|
+
const types = getWidgetsCache2();
|
|
2489
|
+
if (!types) {
|
|
2490
|
+
return [];
|
|
2491
|
+
}
|
|
2492
|
+
return Object.entries(types).reduce((acc, [type, value]) => {
|
|
2493
|
+
if (!value.atomic_props_schema || !value.show_in_panel || value.elType === "widget") {
|
|
2494
|
+
return acc;
|
|
2495
|
+
}
|
|
2496
|
+
acc.push(type);
|
|
2497
|
+
return acc;
|
|
2498
|
+
}, []);
|
|
2499
|
+
}
|
|
2500
|
+
var generatePrompt = () => {
|
|
2501
|
+
const saveAsComponentPrompt = toolPrompts("save-as-component");
|
|
2502
|
+
saveAsComponentPrompt.description(`
|
|
2503
|
+
Save an existing element as a reusable component in the Elementor editor.
|
|
2504
|
+
|
|
2505
|
+
# When to use this tool
|
|
2506
|
+
Use this tool when the user wants to:
|
|
2507
|
+
- Create a reusable component from an existing element structure
|
|
2508
|
+
- Make specific child element properties customizable in component instances
|
|
2509
|
+
- Build a library of reusable design patterns
|
|
2510
|
+
|
|
2511
|
+
# When NOT to use this tool
|
|
2512
|
+
- Element is already a component (widgetType: 'e-component')
|
|
2513
|
+
- Element is locked
|
|
2514
|
+
- Element is not an atomic element (atomic_props_schema is not defined)
|
|
2515
|
+
- Element elType is a 'widget'
|
|
2516
|
+
|
|
2517
|
+
# **CRITICAL - REQUIRED RESOURCES (Must read before using this tool)**
|
|
2518
|
+
1. [${DOCUMENT_STRUCTURE_URI}]
|
|
2519
|
+
**MANDATORY** - Required to understand the document structure and identify child elements for overridable properties.
|
|
2520
|
+
Use this resource to find element IDs and understand the element hierarchy.
|
|
2521
|
+
|
|
2522
|
+
2. [${WIDGET_SCHEMA_URI}]
|
|
2523
|
+
**MANDATORY** - Required to understand which properties are available for each widget type.
|
|
2524
|
+
Use this to identify available propKeys in the atomic_props_schema for child elements.
|
|
2525
|
+
|
|
2526
|
+
# Instructions - MUST FOLLOW IN ORDER
|
|
2527
|
+
## Step 1: Identify the Target Element
|
|
2528
|
+
1. Read the [${DOCUMENT_STRUCTURE_URI}] resource to understand the document structure
|
|
2529
|
+
2. Locate the element you want to save as a component by its element_id
|
|
2530
|
+
3. Verify the element type is a valid element type
|
|
2531
|
+
4. Ensure the element is not locked and is not already a component
|
|
2532
|
+
|
|
2533
|
+
## Step 2: Define Overridable Properties
|
|
2534
|
+
Do this step to make child element properties customizable.
|
|
2535
|
+
Skip that step ONLY if the user explicitly requests to not make any properties customizable.
|
|
2536
|
+
|
|
2537
|
+
1. **Identify Child Elements**
|
|
2538
|
+
- Use the [${DOCUMENT_STRUCTURE_URI}] resource to find all child elements
|
|
2539
|
+
- Note the elementId and widgetType/elType of each child element you want to customize
|
|
2540
|
+
|
|
2541
|
+
2. **Find Available Properties**
|
|
2542
|
+
- Use the [${WIDGET_SCHEMA_URI}] resource to find the child element's widget type schema
|
|
2543
|
+
- Review the atomic_props_schema to find available propKeys (ONLY use top-level props)
|
|
2544
|
+
- Common propKeys include: "text", "url", "tag", "size", etc.
|
|
2545
|
+
- Use only the top level properties, do not use nested properties.
|
|
2546
|
+
|
|
2547
|
+
3. **Build the overridable_props Object**
|
|
2548
|
+
- For each property you want to make overridable, add an entry:
|
|
2549
|
+
\`{ "elementId": "<child-element-id>", "propKey": "<property-key>" }\`
|
|
2550
|
+
- Group all entries under the "props" object
|
|
2551
|
+
|
|
2552
|
+
## Step 3: Execute the Tool
|
|
2553
|
+
Call the tool with:
|
|
2554
|
+
- element_id: The ID of the parent element to save as component
|
|
2555
|
+
- component_name: A descriptive name for the component
|
|
2556
|
+
- overridable_props: (Optional) The properties configuration from Step 2
|
|
2557
|
+
|
|
2558
|
+
# CONSTRAINTS
|
|
2559
|
+
- NEVER try to override properties of the parent element itself - ONLY child elements
|
|
2560
|
+
- NEVER use invalid propKeys - always verify against the widget's atomic_props_schema in [${WIDGET_SCHEMA_URI}]
|
|
2561
|
+
- Property keys must exist in the child element's atomic_props_schema
|
|
2562
|
+
- Element IDs must exist within the target element's children
|
|
2563
|
+
- When tool execution fails, read the error message and adjust accordingly
|
|
2564
|
+
- The element being saved must not be inside another component
|
|
2565
|
+
`);
|
|
2566
|
+
saveAsComponentPrompt.parameter(
|
|
2567
|
+
"element_id",
|
|
2568
|
+
`**MANDATORY** The unique identifier of the element to save as a component.
|
|
2569
|
+
Use the [${DOCUMENT_STRUCTURE_URI}] resource to find available element IDs.`
|
|
2570
|
+
);
|
|
2571
|
+
saveAsComponentPrompt.parameter(
|
|
2572
|
+
"component_name",
|
|
2573
|
+
`**MANDATORY** A descriptive name for the new component.
|
|
2574
|
+
Should be unique and clearly describe the component's purpose (e.g., "Hero Section", "Feature Card").`
|
|
2575
|
+
);
|
|
2576
|
+
saveAsComponentPrompt.parameter(
|
|
2577
|
+
"overridable_props",
|
|
2578
|
+
`**OPTIONAL** Configuration for which child element properties can be customized in component instances.
|
|
2327
2579
|
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2580
|
+
Structure:
|
|
2581
|
+
\`\`\`json
|
|
2582
|
+
{
|
|
2583
|
+
"props": {
|
|
2584
|
+
"<unique-key>": {
|
|
2585
|
+
"elementId": "<child-element-id>",
|
|
2586
|
+
"propKey": "<property-key>"
|
|
2587
|
+
}
|
|
2588
|
+
}
|
|
2589
|
+
}
|
|
2590
|
+
\`\`\`
|
|
2332
2591
|
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2592
|
+
To populate this correctly:
|
|
2593
|
+
1. Use [${DOCUMENT_STRUCTURE_URI}] to find child element IDs and their widgetType
|
|
2594
|
+
2. Use [${WIDGET_SCHEMA_URI}] to find the atomic_props_schema for each child element's widgetType
|
|
2595
|
+
3. Only include properties you want to be customizable in component instances
|
|
2596
|
+
4. Common propKeys: "text", "url", "tag", "size", "align", etc.`
|
|
2597
|
+
);
|
|
2598
|
+
saveAsComponentPrompt.example(`
|
|
2599
|
+
Basic component without overridable properties:
|
|
2600
|
+
\`\`\`json
|
|
2601
|
+
{
|
|
2602
|
+
"element_id": "abc123",
|
|
2603
|
+
"component_name": "Hero Section"
|
|
2604
|
+
}
|
|
2605
|
+
\`\`\`
|
|
2336
2606
|
|
|
2337
|
-
|
|
2607
|
+
Component with overridable properties:
|
|
2338
2608
|
\`\`\`json
|
|
2339
|
-
{
|
|
2609
|
+
{
|
|
2610
|
+
"element_id": "abc123",
|
|
2611
|
+
"component_name": "Feature Card",
|
|
2612
|
+
"overridable_props": {
|
|
2613
|
+
"props": {
|
|
2614
|
+
"heading-text": {
|
|
2615
|
+
"elementId": "heading-123",
|
|
2616
|
+
"propKey": "text"
|
|
2617
|
+
},
|
|
2618
|
+
"button-text": {
|
|
2619
|
+
"elementId": "button-456",
|
|
2620
|
+
"propKey": "text"
|
|
2621
|
+
},
|
|
2622
|
+
"button-link": {
|
|
2623
|
+
"elementId": "button-456",
|
|
2624
|
+
"propKey": "url"
|
|
2625
|
+
}
|
|
2626
|
+
}
|
|
2627
|
+
}
|
|
2628
|
+
}
|
|
2340
2629
|
\`\`\`
|
|
2341
|
-
|
|
2630
|
+
`);
|
|
2631
|
+
saveAsComponentPrompt.instruction(
|
|
2632
|
+
`After successful creation, the component will be available in the components library and can be inserted into any page or template.`
|
|
2633
|
+
);
|
|
2634
|
+
saveAsComponentPrompt.instruction(
|
|
2635
|
+
`When overridable properties are defined, component instances will show customization controls for those specific properties in the editing panel.`
|
|
2636
|
+
);
|
|
2637
|
+
return saveAsComponentPrompt.prompt();
|
|
2638
|
+
};
|
|
2639
|
+
var initSaveAsComponentTool = () => {
|
|
2640
|
+
return getMCPByDomain("components").addTool({
|
|
2641
|
+
name: "save-as-component",
|
|
2642
|
+
schema: InputSchema,
|
|
2643
|
+
outputSchema: OutputSchema,
|
|
2644
|
+
description: generatePrompt(),
|
|
2342
2645
|
handler: handleSaveAsComponent
|
|
2343
2646
|
});
|
|
2344
2647
|
};
|
|
@@ -2411,7 +2714,8 @@ async function createComponentsBeforeSave({
|
|
|
2411
2714
|
unpublishedComponents.map((component) => ({
|
|
2412
2715
|
id: uidToComponentId.get(component.uid),
|
|
2413
2716
|
name: component.name,
|
|
2414
|
-
uid: component.uid
|
|
2717
|
+
uid: component.uid,
|
|
2718
|
+
overridableProps: component.overridableProps ? component.overridableProps : void 0
|
|
2415
2719
|
}))
|
|
2416
2720
|
)
|
|
2417
2721
|
);
|
|
@@ -2426,7 +2730,8 @@ async function createComponents(components, status) {
|
|
|
2426
2730
|
items: components.map((component) => ({
|
|
2427
2731
|
uid: component.uid,
|
|
2428
2732
|
title: component.name,
|
|
2429
|
-
elements: component.elements
|
|
2733
|
+
elements: component.elements,
|
|
2734
|
+
settings: component.overridableProps ? { overridable_props: component.overridableProps } : void 0
|
|
2430
2735
|
}))
|
|
2431
2736
|
});
|
|
2432
2737
|
const map = /* @__PURE__ */ new Map();
|
|
@@ -2607,8 +2912,9 @@ function init() {
|
|
|
2607
2912
|
condition: (_, elementType) => elementType.key === "e-component",
|
|
2608
2913
|
component: InstanceEditingPanel
|
|
2609
2914
|
});
|
|
2610
|
-
|
|
2611
|
-
|
|
2915
|
+
settingsTransformersRegistry2.register("component-instance", componentInstanceTransformer);
|
|
2916
|
+
settingsTransformersRegistry2.register("overridable", componentOverridableTransformer);
|
|
2917
|
+
settingsTransformersRegistry2.register("override", componentOverrideTransformer);
|
|
2612
2918
|
initMcp();
|
|
2613
2919
|
}
|
|
2614
2920
|
export {
|