@elementor/editor-components 3.35.0-355 → 3.35.0-357
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 +300 -44
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +298 -42
- package/dist/index.mjs.map +1 -1
- package/package.json +21 -21
- package/src/api.ts +27 -5
- package/src/components/create-component-form/utils/replace-element-with-component.ts +4 -0
- package/src/components/instance-editing-panel/instance-editing-panel.tsx +1 -1
- 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/dist/index.mjs
CHANGED
|
@@ -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
|
);
|
|
@@ -843,7 +848,8 @@ var createComponentModel = (component) => {
|
|
|
843
848
|
value: component.id ?? component.uid
|
|
844
849
|
}
|
|
845
850
|
}
|
|
846
|
-
}
|
|
851
|
+
},
|
|
852
|
+
overridable_props: component.overridableProps
|
|
847
853
|
},
|
|
848
854
|
editor_settings: {
|
|
849
855
|
title: component.name,
|
|
@@ -1116,25 +1122,25 @@ import { __ as __8 } from "@wordpress/i18n";
|
|
|
1116
1122
|
import { __privateRunCommand as runCommand2 } from "@elementor/editor-v1-adapters";
|
|
1117
1123
|
import { __dispatch as dispatch3 } from "@elementor/store";
|
|
1118
1124
|
import { generateUniqueId } from "@elementor/utils";
|
|
1119
|
-
function createUnpublishedComponent(name, element, eventData) {
|
|
1120
|
-
const
|
|
1121
|
-
const componentBase = { uid, name };
|
|
1125
|
+
function createUnpublishedComponent(name, element, eventData, overridableProps, uid) {
|
|
1126
|
+
const generatedUid = uid ?? generateUniqueId("component");
|
|
1127
|
+
const componentBase = { uid: generatedUid, name, overridableProps };
|
|
1122
1128
|
dispatch3(
|
|
1123
1129
|
slice.actions.addUnpublished({
|
|
1124
1130
|
...componentBase,
|
|
1125
1131
|
elements: [element]
|
|
1126
1132
|
})
|
|
1127
1133
|
);
|
|
1128
|
-
dispatch3(slice.actions.addCreatedThisSession(
|
|
1134
|
+
dispatch3(slice.actions.addCreatedThisSession(generatedUid));
|
|
1129
1135
|
replaceElementWithComponent(element, componentBase);
|
|
1130
1136
|
trackComponentEvent({
|
|
1131
1137
|
action: "created",
|
|
1132
|
-
component_uid:
|
|
1138
|
+
component_uid: generatedUid,
|
|
1133
1139
|
component_name: name,
|
|
1134
1140
|
...eventData
|
|
1135
1141
|
});
|
|
1136
1142
|
runCommand2("document/save/auto");
|
|
1137
|
-
return
|
|
1143
|
+
return generatedUid;
|
|
1138
1144
|
}
|
|
1139
1145
|
|
|
1140
1146
|
// src/components/create-component-form/hooks/use-form.ts
|
|
@@ -1792,7 +1798,7 @@ function InstanceEditingPanel() {
|
|
|
1792
1798
|
(groupId) => overridableProps.groups.items[groupId] ? overridableProps.groups.items[groupId] : null
|
|
1793
1799
|
).filter(Boolean);
|
|
1794
1800
|
const isEmpty = groups.length === 0 || Object.keys(overridableProps.props).length === 0;
|
|
1795
|
-
return /* @__PURE__ */ React15.createElement(React15.Fragment, null, /* @__PURE__ */ React15.createElement(PanelHeader, { sx: { justifyContent: "start" } }, /* @__PURE__ */ React15.createElement(Stack10, { direction: "row", alignContent: "space-between", flexGrow: 1 }, /* @__PURE__ */ React15.createElement(Stack10, { direction: "row", alignItems: "center", justifyContent: "start", gap: 1, flexGrow: 1 }, /* @__PURE__ */ React15.createElement(ComponentsIcon3, { fontSize: "small", sx: { color: "text.tertiary" } }), /* @__PURE__ */ React15.createElement(PanelHeaderTitle, null, component.name)), /* @__PURE__ */ React15.createElement(Tooltip2, { title: panelTitle }, /* @__PURE__ */ React15.createElement(IconButton3, { size: "tiny", onClick: handleEditComponent, "aria-label": panelTitle }, /* @__PURE__ */ React15.createElement(PencilIcon2, { fontSize: "tiny" }))))), /* @__PURE__ */ React15.createElement(PanelBody, null, isEmpty ? /* @__PURE__ */ React15.createElement(EmptyState2, { onEditComponent: handleEditComponent }) : /* @__PURE__ */ React15.createElement(Stack10, { direction: "column", alignItems: "stretch" }, groups.map((group) => /* @__PURE__ */ React15.createElement(OverridePropsGroup, { key: group.id, group, props: overridableProps.props })))));
|
|
1801
|
+
return /* @__PURE__ */ React15.createElement(React15.Fragment, null, /* @__PURE__ */ React15.createElement(PanelHeader, { sx: { justifyContent: "start", px: 2 } }, /* @__PURE__ */ React15.createElement(Stack10, { direction: "row", alignContent: "space-between", flexGrow: 1 }, /* @__PURE__ */ React15.createElement(Stack10, { direction: "row", alignItems: "center", justifyContent: "start", gap: 1, flexGrow: 1 }, /* @__PURE__ */ React15.createElement(ComponentsIcon3, { fontSize: "small", sx: { color: "text.tertiary" } }), /* @__PURE__ */ React15.createElement(PanelHeaderTitle, null, component.name)), /* @__PURE__ */ React15.createElement(Tooltip2, { title: panelTitle }, /* @__PURE__ */ React15.createElement(IconButton3, { size: "tiny", onClick: handleEditComponent, "aria-label": panelTitle }, /* @__PURE__ */ React15.createElement(PencilIcon2, { fontSize: "tiny" }))))), /* @__PURE__ */ React15.createElement(PanelBody, null, isEmpty ? /* @__PURE__ */ React15.createElement(EmptyState2, { onEditComponent: handleEditComponent }) : /* @__PURE__ */ React15.createElement(Stack10, { direction: "column", alignItems: "stretch" }, groups.map((group) => /* @__PURE__ */ React15.createElement(OverridePropsGroup, { key: group.id, group, props: overridableProps.props })))));
|
|
1796
1802
|
}
|
|
1797
1803
|
|
|
1798
1804
|
// src/components/overridable-props/overridable-prop-control.tsx
|
|
@@ -2273,72 +2279,320 @@ function isPropAllowed(bind) {
|
|
|
2273
2279
|
import { getMCPByDomain as getMCPByDomain2 } from "@elementor/editor-mcp";
|
|
2274
2280
|
|
|
2275
2281
|
// src/mcp/save-as-component-tool.ts
|
|
2276
|
-
import {
|
|
2277
|
-
import {
|
|
2282
|
+
import { DOCUMENT_STRUCTURE_URI, WIDGET_SCHEMA_URI } from "@elementor/editor-canvas";
|
|
2283
|
+
import { getContainer as getContainer2, getElementType, getWidgetsCache as getWidgetsCache2 } from "@elementor/editor-elements";
|
|
2284
|
+
import { getMCPByDomain, toolPrompts } from "@elementor/editor-mcp";
|
|
2285
|
+
import { AxiosError } from "@elementor/http-client";
|
|
2278
2286
|
import { z as z6 } from "@elementor/schema";
|
|
2287
|
+
import { generateUniqueId as generateUniqueId3 } from "@elementor/utils";
|
|
2279
2288
|
var InputSchema = {
|
|
2280
2289
|
element_id: z6.string().describe(
|
|
2281
2290
|
'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
2291
|
),
|
|
2283
|
-
component_name: z6.string().describe("The name for the new component. Should be descriptive and unique among existing components.")
|
|
2292
|
+
component_name: z6.string().describe("The name for the new component. Should be descriptive and unique among existing components."),
|
|
2293
|
+
overridable_props: z6.object({
|
|
2294
|
+
props: z6.record(
|
|
2295
|
+
z6.object({
|
|
2296
|
+
elementId: z6.string().describe("The id of the child element that you want to override its settings"),
|
|
2297
|
+
propKey: z6.string().describe(
|
|
2298
|
+
'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.'
|
|
2299
|
+
)
|
|
2300
|
+
})
|
|
2301
|
+
)
|
|
2302
|
+
}).optional().describe(
|
|
2303
|
+
'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.'
|
|
2304
|
+
)
|
|
2284
2305
|
};
|
|
2285
2306
|
var OutputSchema = {
|
|
2286
2307
|
message: z6.string().optional().describe("Additional information about the operation result"),
|
|
2287
2308
|
component_uid: z6.string().optional().describe("The unique identifier of the newly created component (only present on success)")
|
|
2288
2309
|
};
|
|
2289
|
-
var VALID_ELEMENT_TYPES = ["e-div-block", "e-flexbox", "e-tabs"];
|
|
2290
2310
|
var ERROR_MESSAGES = {
|
|
2291
2311
|
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: ${
|
|
2312
|
+
ELEMENT_NOT_ONE_OF_TYPES: (validTypes) => `Element is not one of the following types: ${validTypes.join(", ")}`,
|
|
2293
2313
|
ELEMENT_IS_LOCKED: "Cannot save a locked element as a component."
|
|
2294
2314
|
};
|
|
2295
2315
|
var handleSaveAsComponent = async (params) => {
|
|
2296
|
-
const { element_id: elementId, component_name: componentName } = params;
|
|
2316
|
+
const { element_id: elementId, component_name: componentName, overridable_props: overridablePropsInput } = params;
|
|
2317
|
+
const validElementTypes = getValidElementTypes();
|
|
2297
2318
|
const container = getContainer2(elementId);
|
|
2298
2319
|
if (!container) {
|
|
2299
2320
|
throw new Error(ERROR_MESSAGES.ELEMENT_NOT_FOUND);
|
|
2300
2321
|
}
|
|
2301
2322
|
const elType = container.model.get("elType");
|
|
2302
|
-
if (!
|
|
2303
|
-
throw new Error(ERROR_MESSAGES.ELEMENT_NOT_ONE_OF_TYPES);
|
|
2323
|
+
if (!validElementTypes.includes(elType)) {
|
|
2324
|
+
throw new Error(ERROR_MESSAGES.ELEMENT_NOT_ONE_OF_TYPES(validElementTypes));
|
|
2304
2325
|
}
|
|
2305
2326
|
const element = container.model.toJSON({ remove: ["default"] });
|
|
2306
2327
|
if (element?.isLocked) {
|
|
2307
2328
|
throw new Error(ERROR_MESSAGES.ELEMENT_IS_LOCKED);
|
|
2308
2329
|
}
|
|
2309
|
-
const
|
|
2330
|
+
const overridableProps = overridablePropsInput ? enrichOverridableProps(overridablePropsInput, element) : void 0;
|
|
2331
|
+
if (overridableProps) {
|
|
2332
|
+
updateElementDataWithOverridableProps(element, overridableProps);
|
|
2333
|
+
}
|
|
2334
|
+
const uid = generateUniqueId3("component");
|
|
2335
|
+
try {
|
|
2336
|
+
await apiClient.validate({
|
|
2337
|
+
items: [
|
|
2338
|
+
{ uid, title: componentName, elements: [element], settings: { overridable_props: overridableProps } }
|
|
2339
|
+
]
|
|
2340
|
+
});
|
|
2341
|
+
} catch (error) {
|
|
2342
|
+
if (error instanceof AxiosError) {
|
|
2343
|
+
throw new Error(error.response?.data.messge);
|
|
2344
|
+
}
|
|
2345
|
+
throw new Error("Unknown error");
|
|
2346
|
+
}
|
|
2347
|
+
createUnpublishedComponent(componentName, element, null, overridableProps, uid);
|
|
2310
2348
|
return {
|
|
2311
2349
|
status: "ok",
|
|
2312
2350
|
message: `Component "${componentName}" created successfully.`,
|
|
2313
2351
|
component_uid: uid
|
|
2314
2352
|
};
|
|
2315
2353
|
};
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2354
|
+
function enrichOverridableProps(input, rootElement) {
|
|
2355
|
+
const enrichedProps = {};
|
|
2356
|
+
const defaultGroupId = generateUniqueId3("group");
|
|
2357
|
+
Object.entries(input.props).forEach(([, prop]) => {
|
|
2358
|
+
const { elementId, propKey } = prop;
|
|
2359
|
+
const element = findElementById(rootElement, elementId);
|
|
2360
|
+
if (!element) {
|
|
2361
|
+
throw new Error(`Element with ID "${elementId}" not found in component`);
|
|
2362
|
+
}
|
|
2363
|
+
const elType = element.elType;
|
|
2364
|
+
const widgetType = element.widgetType || element.elType;
|
|
2365
|
+
const elementType = getElementType(widgetType);
|
|
2366
|
+
if (!elementType) {
|
|
2367
|
+
throw new Error(
|
|
2368
|
+
`Element type "${widgetType}" is not atomic or does not have a settings schema. Cannot expose property "${propKey}" for element "${elementId}".`
|
|
2369
|
+
);
|
|
2370
|
+
}
|
|
2371
|
+
if (!elementType.propsSchema[propKey]) {
|
|
2372
|
+
const availableProps = Object.keys(elementType.propsSchema).join(", ");
|
|
2373
|
+
throw new Error(
|
|
2374
|
+
`Property "${propKey}" does not exist in element "${elementId}" (type: ${widgetType}). Available properties: ${availableProps}`
|
|
2375
|
+
);
|
|
2376
|
+
}
|
|
2377
|
+
const overrideKey = generateUniqueId3("prop");
|
|
2378
|
+
const originValue = element.settings?.[propKey] ? element.settings[propKey] : elementType.propsSchema[propKey].default ?? null;
|
|
2379
|
+
const label = generateLabel(propKey);
|
|
2380
|
+
enrichedProps[overrideKey] = {
|
|
2381
|
+
overrideKey,
|
|
2382
|
+
label,
|
|
2383
|
+
elementId,
|
|
2384
|
+
propKey,
|
|
2385
|
+
elType,
|
|
2386
|
+
widgetType,
|
|
2387
|
+
originValue,
|
|
2388
|
+
groupId: defaultGroupId
|
|
2389
|
+
};
|
|
2390
|
+
});
|
|
2391
|
+
return {
|
|
2392
|
+
props: enrichedProps,
|
|
2393
|
+
groups: {
|
|
2394
|
+
items: {
|
|
2395
|
+
[defaultGroupId]: {
|
|
2396
|
+
id: defaultGroupId,
|
|
2397
|
+
label: "Default",
|
|
2398
|
+
props: Object.keys(enrichedProps)
|
|
2399
|
+
}
|
|
2400
|
+
},
|
|
2401
|
+
order: [defaultGroupId]
|
|
2402
|
+
}
|
|
2403
|
+
};
|
|
2404
|
+
}
|
|
2405
|
+
function updateElementDataWithOverridableProps(rootElement, overridableProps) {
|
|
2406
|
+
Object.values(overridableProps.props).forEach((prop) => {
|
|
2407
|
+
const element = findElementById(rootElement, prop.elementId);
|
|
2408
|
+
if (!element || !element.settings) {
|
|
2409
|
+
return;
|
|
2410
|
+
}
|
|
2411
|
+
element.settings[prop.propKey] = {
|
|
2412
|
+
$$type: "overridable",
|
|
2413
|
+
value: {
|
|
2414
|
+
override_key: prop.overrideKey,
|
|
2415
|
+
origin_value: prop.originValue
|
|
2416
|
+
}
|
|
2417
|
+
};
|
|
2418
|
+
});
|
|
2419
|
+
}
|
|
2420
|
+
function findElementById(root, targetId) {
|
|
2421
|
+
if (root.id === targetId) {
|
|
2422
|
+
return root;
|
|
2423
|
+
}
|
|
2424
|
+
if (root.elements) {
|
|
2425
|
+
for (const child of root.elements) {
|
|
2426
|
+
const found = findElementById(child, targetId);
|
|
2427
|
+
if (found) {
|
|
2428
|
+
return found;
|
|
2429
|
+
}
|
|
2430
|
+
}
|
|
2431
|
+
}
|
|
2432
|
+
return null;
|
|
2433
|
+
}
|
|
2434
|
+
function generateLabel(propKey) {
|
|
2435
|
+
const uniqueId = generateUniqueId3("prop");
|
|
2436
|
+
return `${uniqueId} - ${propKey}`;
|
|
2437
|
+
}
|
|
2438
|
+
function getValidElementTypes() {
|
|
2439
|
+
const types = getWidgetsCache2();
|
|
2440
|
+
if (!types) {
|
|
2441
|
+
return [];
|
|
2442
|
+
}
|
|
2443
|
+
return Object.entries(types).reduce((acc, [type, value]) => {
|
|
2444
|
+
if (!value.atomic_props_schema || !value.show_in_panel || value.elType === "widget") {
|
|
2445
|
+
return acc;
|
|
2446
|
+
}
|
|
2447
|
+
acc.push(type);
|
|
2448
|
+
return acc;
|
|
2449
|
+
}, []);
|
|
2450
|
+
}
|
|
2451
|
+
var generatePrompt = () => {
|
|
2452
|
+
const saveAsComponentPrompt = toolPrompts("save-as-component");
|
|
2453
|
+
saveAsComponentPrompt.description(`
|
|
2454
|
+
Save an existing element as a reusable component in the Elementor editor.
|
|
2455
|
+
|
|
2456
|
+
# When to use this tool
|
|
2457
|
+
Use this tool when the user wants to:
|
|
2458
|
+
- Create a reusable component from an existing element structure
|
|
2459
|
+
- Make specific child element properties customizable in component instances
|
|
2460
|
+
- Build a library of reusable design patterns
|
|
2461
|
+
|
|
2462
|
+
# When NOT to use this tool
|
|
2463
|
+
- Element is already a component (widgetType: 'e-component')
|
|
2464
|
+
- Element is locked
|
|
2465
|
+
- Element is not an atomic element (atomic_props_schema is not defined)
|
|
2466
|
+
- Element elType is a 'widget'
|
|
2467
|
+
|
|
2468
|
+
# **CRITICAL - REQUIRED RESOURCES (Must read before using this tool)**
|
|
2469
|
+
1. [${DOCUMENT_STRUCTURE_URI}]
|
|
2470
|
+
**MANDATORY** - Required to understand the document structure and identify child elements for overridable properties.
|
|
2471
|
+
Use this resource to find element IDs and understand the element hierarchy.
|
|
2472
|
+
|
|
2473
|
+
2. [${WIDGET_SCHEMA_URI}]
|
|
2474
|
+
**MANDATORY** - Required to understand which properties are available for each widget type.
|
|
2475
|
+
Use this to identify available propKeys in the atomic_props_schema for child elements.
|
|
2476
|
+
|
|
2477
|
+
# Instructions - MUST FOLLOW IN ORDER
|
|
2478
|
+
## Step 1: Identify the Target Element
|
|
2479
|
+
1. Read the [${DOCUMENT_STRUCTURE_URI}] resource to understand the document structure
|
|
2480
|
+
2. Locate the element you want to save as a component by its element_id
|
|
2481
|
+
3. Verify the element type is a valid element type
|
|
2482
|
+
4. Ensure the element is not locked and is not already a component
|
|
2483
|
+
|
|
2484
|
+
## Step 2: Define Overridable Properties
|
|
2485
|
+
Do this step to make child element properties customizable.
|
|
2486
|
+
Skip that step ONLY if the user explicitly requests to not make any properties customizable.
|
|
2487
|
+
|
|
2488
|
+
1. **Identify Child Elements**
|
|
2489
|
+
- Use the [${DOCUMENT_STRUCTURE_URI}] resource to find all child elements
|
|
2490
|
+
- Note the elementId and widgetType/elType of each child element you want to customize
|
|
2491
|
+
|
|
2492
|
+
2. **Find Available Properties**
|
|
2493
|
+
- Use the [${WIDGET_SCHEMA_URI}] resource to find the child element's widget type schema
|
|
2494
|
+
- Review the atomic_props_schema to find available propKeys (ONLY use top-level props)
|
|
2495
|
+
- Common propKeys include: "text", "url", "tag", "size", etc.
|
|
2496
|
+
- Use only the top level properties, do not use nested properties.
|
|
2497
|
+
|
|
2498
|
+
3. **Build the overridable_props Object**
|
|
2499
|
+
- For each property you want to make overridable, add an entry:
|
|
2500
|
+
\`{ "elementId": "<child-element-id>", "propKey": "<property-key>" }\`
|
|
2501
|
+
- Group all entries under the "props" object
|
|
2502
|
+
|
|
2503
|
+
## Step 3: Execute the Tool
|
|
2504
|
+
Call the tool with:
|
|
2505
|
+
- element_id: The ID of the parent element to save as component
|
|
2506
|
+
- component_name: A descriptive name for the component
|
|
2507
|
+
- overridable_props: (Optional) The properties configuration from Step 2
|
|
2508
|
+
|
|
2509
|
+
# CONSTRAINTS
|
|
2510
|
+
- NEVER try to override properties of the parent element itself - ONLY child elements
|
|
2511
|
+
- NEVER use invalid propKeys - always verify against the widget's atomic_props_schema in [${WIDGET_SCHEMA_URI}]
|
|
2512
|
+
- Property keys must exist in the child element's atomic_props_schema
|
|
2513
|
+
- Element IDs must exist within the target element's children
|
|
2514
|
+
- When tool execution fails, read the error message and adjust accordingly
|
|
2515
|
+
- The element being saved must not be inside another component
|
|
2516
|
+
`);
|
|
2517
|
+
saveAsComponentPrompt.parameter(
|
|
2518
|
+
"element_id",
|
|
2519
|
+
`**MANDATORY** The unique identifier of the element to save as a component.
|
|
2520
|
+
Use the [${DOCUMENT_STRUCTURE_URI}] resource to find available element IDs.`
|
|
2521
|
+
);
|
|
2522
|
+
saveAsComponentPrompt.parameter(
|
|
2523
|
+
"component_name",
|
|
2524
|
+
`**MANDATORY** A descriptive name for the new component.
|
|
2525
|
+
Should be unique and clearly describe the component's purpose (e.g., "Hero Section", "Feature Card").`
|
|
2526
|
+
);
|
|
2527
|
+
saveAsComponentPrompt.parameter(
|
|
2528
|
+
"overridable_props",
|
|
2529
|
+
`**OPTIONAL** Configuration for which child element properties can be customized in component instances.
|
|
2327
2530
|
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2531
|
+
Structure:
|
|
2532
|
+
\`\`\`json
|
|
2533
|
+
{
|
|
2534
|
+
"props": {
|
|
2535
|
+
"<unique-key>": {
|
|
2536
|
+
"elementId": "<child-element-id>",
|
|
2537
|
+
"propKey": "<property-key>"
|
|
2538
|
+
}
|
|
2539
|
+
}
|
|
2540
|
+
}
|
|
2541
|
+
\`\`\`
|
|
2332
2542
|
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2543
|
+
To populate this correctly:
|
|
2544
|
+
1. Use [${DOCUMENT_STRUCTURE_URI}] to find child element IDs and their widgetType
|
|
2545
|
+
2. Use [${WIDGET_SCHEMA_URI}] to find the atomic_props_schema for each child element's widgetType
|
|
2546
|
+
3. Only include properties you want to be customizable in component instances
|
|
2547
|
+
4. Common propKeys: "text", "url", "tag", "size", "align", etc.`
|
|
2548
|
+
);
|
|
2549
|
+
saveAsComponentPrompt.example(`
|
|
2550
|
+
Basic component without overridable properties:
|
|
2551
|
+
\`\`\`json
|
|
2552
|
+
{
|
|
2553
|
+
"element_id": "abc123",
|
|
2554
|
+
"component_name": "Hero Section"
|
|
2555
|
+
}
|
|
2556
|
+
\`\`\`
|
|
2336
2557
|
|
|
2337
|
-
|
|
2558
|
+
Component with overridable properties:
|
|
2338
2559
|
\`\`\`json
|
|
2339
|
-
{
|
|
2560
|
+
{
|
|
2561
|
+
"element_id": "abc123",
|
|
2562
|
+
"component_name": "Feature Card",
|
|
2563
|
+
"overridable_props": {
|
|
2564
|
+
"props": {
|
|
2565
|
+
"heading-text": {
|
|
2566
|
+
"elementId": "heading-123",
|
|
2567
|
+
"propKey": "text"
|
|
2568
|
+
},
|
|
2569
|
+
"button-text": {
|
|
2570
|
+
"elementId": "button-456",
|
|
2571
|
+
"propKey": "text"
|
|
2572
|
+
},
|
|
2573
|
+
"button-link": {
|
|
2574
|
+
"elementId": "button-456",
|
|
2575
|
+
"propKey": "url"
|
|
2576
|
+
}
|
|
2577
|
+
}
|
|
2578
|
+
}
|
|
2579
|
+
}
|
|
2340
2580
|
\`\`\`
|
|
2341
|
-
|
|
2581
|
+
`);
|
|
2582
|
+
saveAsComponentPrompt.instruction(
|
|
2583
|
+
`After successful creation, the component will be available in the components library and can be inserted into any page or template.`
|
|
2584
|
+
);
|
|
2585
|
+
saveAsComponentPrompt.instruction(
|
|
2586
|
+
`When overridable properties are defined, component instances will show customization controls for those specific properties in the editing panel.`
|
|
2587
|
+
);
|
|
2588
|
+
return saveAsComponentPrompt.prompt();
|
|
2589
|
+
};
|
|
2590
|
+
var initSaveAsComponentTool = () => {
|
|
2591
|
+
return getMCPByDomain("components").addTool({
|
|
2592
|
+
name: "save-as-component",
|
|
2593
|
+
schema: InputSchema,
|
|
2594
|
+
outputSchema: OutputSchema,
|
|
2595
|
+
description: generatePrompt(),
|
|
2342
2596
|
handler: handleSaveAsComponent
|
|
2343
2597
|
});
|
|
2344
2598
|
};
|
|
@@ -2411,7 +2665,8 @@ async function createComponentsBeforeSave({
|
|
|
2411
2665
|
unpublishedComponents.map((component) => ({
|
|
2412
2666
|
id: uidToComponentId.get(component.uid),
|
|
2413
2667
|
name: component.name,
|
|
2414
|
-
uid: component.uid
|
|
2668
|
+
uid: component.uid,
|
|
2669
|
+
overridableProps: component.overridableProps ? component.overridableProps : void 0
|
|
2415
2670
|
}))
|
|
2416
2671
|
)
|
|
2417
2672
|
);
|
|
@@ -2426,7 +2681,8 @@ async function createComponents(components, status) {
|
|
|
2426
2681
|
items: components.map((component) => ({
|
|
2427
2682
|
uid: component.uid,
|
|
2428
2683
|
title: component.name,
|
|
2429
|
-
elements: component.elements
|
|
2684
|
+
elements: component.elements,
|
|
2685
|
+
settings: component.overridableProps ? { overridable_props: component.overridableProps } : void 0
|
|
2430
2686
|
}))
|
|
2431
2687
|
});
|
|
2432
2688
|
const map = /* @__PURE__ */ new Map();
|