@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 CHANGED
@@ -36,7 +36,7 @@ module.exports = __toCommonJS(index_exports);
36
36
 
37
37
  // src/init.ts
38
38
  var import_editor = require("@elementor/editor");
39
- var import_editor_canvas6 = require("@elementor/editor-canvas");
39
+ var import_editor_canvas8 = require("@elementor/editor-canvas");
40
40
  var import_editor_documents10 = require("@elementor/editor-documents");
41
41
  var import_editor_editing_panel5 = require("@elementor/editor-editing-panel");
42
42
  var import_editor_elements_panel = require("@elementor/editor-elements-panel");
@@ -97,7 +97,8 @@ var apiClient = {
97
97
  {
98
98
  componentIds
99
99
  }
100
- ).then((res) => res.data.data)
100
+ ).then((res) => res.data.data),
101
+ validate: async (payload) => await (0, import_http_client.httpService)().post(`${BASE_URL}/create-validate`, payload).then((res) => res.data)
101
102
  };
102
103
 
103
104
  // src/store/thunks.ts
@@ -197,7 +198,11 @@ var selectComponents = (0, import_store2.__createSelector)(
197
198
  selectData,
198
199
  selectUnpublishedData,
199
200
  (data, unpublishedData) => [
200
- ...unpublishedData.map((item) => ({ uid: item.uid, name: item.name })),
201
+ ...unpublishedData.map((item) => ({
202
+ uid: item.uid,
203
+ name: item.name,
204
+ overridableProps: item.overridableProps
205
+ })),
201
206
  ...data
202
207
  ]
203
208
  );
@@ -261,25 +266,73 @@ var invalidateComponentDocumentData = (id) => {
261
266
  };
262
267
 
263
268
  // src/component-instance-transformer.ts
269
+ var componentInstanceContext = new import_editor_canvas.RenderContext("component-instance", {
270
+ overrides: {}
271
+ });
264
272
  var componentInstanceTransformer = (0, import_editor_canvas.createTransformer)(
265
- async ({ component_id: id }) => {
273
+ async ({
274
+ component_id: id,
275
+ overrides: overridesValue
276
+ }) => {
266
277
  const unpublishedComponents = selectUnpublishedComponents((0, import_store3.__getState)());
267
278
  const unpublishedComponent = unpublishedComponents.find(({ uid }) => uid === id);
279
+ const overrides = overridesValue?.reduce((acc, override) => ({ ...acc, ...override }), {});
268
280
  if (unpublishedComponent) {
269
- return structuredClone(unpublishedComponent.elements);
281
+ return {
282
+ elements: structuredClone(unpublishedComponent.elements),
283
+ overrides
284
+ };
270
285
  }
271
286
  if (typeof id !== "number") {
272
- throw new Error(`Component ID "${id}" not found.`);
287
+ throw new Error(`Component ID "${id}" not valid.`);
273
288
  }
274
289
  const data = await getComponentDocumentData(id);
275
- return data?.elements ?? [];
290
+ return {
291
+ elements: data?.elements ?? [],
292
+ overrides
293
+ };
276
294
  }
277
295
  );
278
296
 
279
297
  // src/component-overridable-transformer.ts
280
298
  var import_editor_canvas2 = require("@elementor/editor-canvas");
281
- var componentOverridableTransformer = (0, import_editor_canvas2.createTransformer)((value) => {
282
- return value.origin_value;
299
+ var componentOverridableTransformer = (0, import_editor_canvas2.createTransformer)(
300
+ (value, options) => {
301
+ const { overrides } = componentInstanceContext.get();
302
+ const overrideValue = overrides?.[value.override_key];
303
+ if (overrideValue) {
304
+ const isOverride = isOriginValueOverride(value.origin_value);
305
+ if (isOverride) {
306
+ return transformOverride(value, options, overrideValue);
307
+ }
308
+ return overrideValue;
309
+ }
310
+ return value.origin_value;
311
+ }
312
+ );
313
+ function transformOverride(value, options, overrideValue) {
314
+ const transformer = import_editor_canvas2.settingsTransformersRegistry.get("override");
315
+ if (!transformer) {
316
+ return null;
317
+ }
318
+ const transformedValue = transformer(value.origin_value.value, options);
319
+ if (!transformedValue) {
320
+ return null;
321
+ }
322
+ const [key] = Object.keys(transformedValue);
323
+ return {
324
+ [key]: overrideValue
325
+ };
326
+ }
327
+ function isOriginValueOverride(originValue) {
328
+ return originValue.$$type === "override";
329
+ }
330
+
331
+ // src/component-override-transformer.ts
332
+ var import_editor_canvas3 = require("@elementor/editor-canvas");
333
+ var componentOverrideTransformer = (0, import_editor_canvas3.createTransformer)((override) => {
334
+ const { override_key: key, override_value: overrideValue } = override;
335
+ return { [key]: overrideValue };
283
336
  });
284
337
 
285
338
  // src/components/component-panel-header/component-panel-header.tsx
@@ -479,7 +532,7 @@ var useComponents = () => {
479
532
 
480
533
  // src/components/components-tab/components-item.tsx
481
534
  var React5 = __toESM(require("react"));
482
- var import_editor_canvas4 = require("@elementor/editor-canvas");
535
+ var import_editor_canvas5 = require("@elementor/editor-canvas");
483
536
  var import_editor_elements3 = require("@elementor/editor-elements");
484
537
  var import_editor_ui = require("@elementor/editor-ui");
485
538
  var import_icons4 = require("@elementor/icons");
@@ -503,7 +556,7 @@ var archiveComponent = (componentId) => {
503
556
  var import_editor_documents6 = require("@elementor/editor-documents");
504
557
 
505
558
  // src/create-component-type.ts
506
- var import_editor_canvas3 = require("@elementor/editor-canvas");
559
+ var import_editor_canvas4 = require("@elementor/editor-canvas");
507
560
  var import_editor_documents5 = require("@elementor/editor-documents");
508
561
  var import_i18n4 = require("@wordpress/i18n");
509
562
 
@@ -570,7 +623,7 @@ function createComponentType(options) {
570
623
  };
571
624
  }
572
625
  function createComponentView(options) {
573
- return class extends (0, import_editor_canvas3.createTemplatedElementView)(options) {
626
+ return class extends (0, import_editor_canvas4.createTemplatedElementView)(options) {
574
627
  legacyWindow = window;
575
628
  eventsManagerConfig = this.legacyWindow.elementorCommon.eventsManager.config;
576
629
  isComponentCurrentlyEdited() {
@@ -578,9 +631,10 @@ function createComponentView(options) {
578
631
  return currentDocument?.id === this.getComponentId();
579
632
  }
580
633
  afterSettingsResolve(settings) {
581
- if (settings.component_instance) {
634
+ const componentInstance = settings.component_instance;
635
+ if (componentInstance) {
582
636
  this.collection = this.legacyWindow.elementor.createBackboneElementsCollection(
583
- settings.component_instance
637
+ componentInstance.elements
584
638
  );
585
639
  this.collection.models.forEach(setInactiveRecursively);
586
640
  settings.component_instance = "<template data-children-placeholder></template>";
@@ -850,7 +904,8 @@ var createComponentModel = (component) => {
850
904
  value: component.id ?? component.uid
851
905
  }
852
906
  }
853
- }
907
+ },
908
+ overridable_props: component.overridableProps
854
909
  },
855
910
  editor_settings: {
856
911
  title: component.name,
@@ -871,7 +926,7 @@ var ComponentItem = ({ component }) => {
871
926
  };
872
927
  const handleDragEnd = () => {
873
928
  loadComponentsAssets([componentModel]);
874
- (0, import_editor_canvas4.endDragElementFromPanel)();
929
+ (0, import_editor_canvas5.endDragElementFromPanel)();
875
930
  };
876
931
  const handleArchiveClick = () => {
877
932
  popupState.close();
@@ -884,7 +939,7 @@ var ComponentItem = ({ component }) => {
884
939
  import_ui4.ListItemButton,
885
940
  {
886
941
  draggable: true,
887
- onDragStart: () => (0, import_editor_canvas4.startDragElementFromPanel)(componentModel),
942
+ onDragStart: () => (0, import_editor_canvas5.startDragElementFromPanel)(componentModel),
888
943
  onDragEnd: handleDragEnd,
889
944
  shape: "rounded",
890
945
  sx: {
@@ -1123,25 +1178,25 @@ var import_i18n8 = require("@wordpress/i18n");
1123
1178
  var import_editor_v1_adapters3 = require("@elementor/editor-v1-adapters");
1124
1179
  var import_store21 = require("@elementor/store");
1125
1180
  var import_utils2 = require("@elementor/utils");
1126
- function createUnpublishedComponent(name, element, eventData) {
1127
- const uid = (0, import_utils2.generateUniqueId)("component");
1128
- const componentBase = { uid, name };
1181
+ function createUnpublishedComponent(name, element, eventData, overridableProps, uid) {
1182
+ const generatedUid = uid ?? (0, import_utils2.generateUniqueId)("component");
1183
+ const componentBase = { uid: generatedUid, name, overridableProps };
1129
1184
  (0, import_store21.__dispatch)(
1130
1185
  slice.actions.addUnpublished({
1131
1186
  ...componentBase,
1132
1187
  elements: [element]
1133
1188
  })
1134
1189
  );
1135
- (0, import_store21.__dispatch)(slice.actions.addCreatedThisSession(uid));
1190
+ (0, import_store21.__dispatch)(slice.actions.addCreatedThisSession(generatedUid));
1136
1191
  replaceElementWithComponent(element, componentBase);
1137
1192
  trackComponentEvent({
1138
1193
  action: "created",
1139
- component_uid: uid,
1194
+ component_uid: generatedUid,
1140
1195
  component_name: name,
1141
1196
  ...eventData
1142
1197
  });
1143
1198
  (0, import_editor_v1_adapters3.__privateRunCommand)("document/save/auto");
1144
- return uid;
1199
+ return generatedUid;
1145
1200
  }
1146
1201
 
1147
1202
  // src/components/create-component-form/hooks/use-form.ts
@@ -1416,10 +1471,10 @@ var import_react_dom = require("react-dom");
1416
1471
  var import_i18n9 = require("@wordpress/i18n");
1417
1472
 
1418
1473
  // src/hooks/use-canvas-document.ts
1419
- var import_editor_canvas5 = require("@elementor/editor-canvas");
1474
+ var import_editor_canvas6 = require("@elementor/editor-canvas");
1420
1475
  var import_editor_v1_adapters4 = require("@elementor/editor-v1-adapters");
1421
1476
  function useCanvasDocument() {
1422
- return (0, import_editor_v1_adapters4.__privateUseListenTo)((0, import_editor_v1_adapters4.commandEndEvent)("editor/documents/attach-preview"), () => (0, import_editor_canvas5.getCanvasIframeDocument)());
1477
+ return (0, import_editor_v1_adapters4.__privateUseListenTo)((0, import_editor_v1_adapters4.commandEndEvent)("editor/documents/attach-preview"), () => (0, import_editor_canvas6.getCanvasIframeDocument)());
1423
1478
  }
1424
1479
 
1425
1480
  // src/hooks/use-element-rect.ts
@@ -2280,72 +2335,320 @@ function isPropAllowed(bind) {
2280
2335
  var import_editor_mcp2 = require("@elementor/editor-mcp");
2281
2336
 
2282
2337
  // src/mcp/save-as-component-tool.ts
2338
+ var import_editor_canvas7 = require("@elementor/editor-canvas");
2283
2339
  var import_editor_elements7 = require("@elementor/editor-elements");
2284
2340
  var import_editor_mcp = require("@elementor/editor-mcp");
2341
+ var import_http_client2 = require("@elementor/http-client");
2285
2342
  var import_schema6 = require("@elementor/schema");
2343
+ var import_utils5 = require("@elementor/utils");
2286
2344
  var InputSchema = {
2287
2345
  element_id: import_schema6.z.string().describe(
2288
2346
  '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.'
2289
2347
  ),
2290
- component_name: import_schema6.z.string().describe("The name for the new component. Should be descriptive and unique among existing components.")
2348
+ component_name: import_schema6.z.string().describe("The name for the new component. Should be descriptive and unique among existing components."),
2349
+ overridable_props: import_schema6.z.object({
2350
+ props: import_schema6.z.record(
2351
+ import_schema6.z.object({
2352
+ elementId: import_schema6.z.string().describe("The id of the child element that you want to override its settings"),
2353
+ propKey: import_schema6.z.string().describe(
2354
+ '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.'
2355
+ )
2356
+ })
2357
+ )
2358
+ }).optional().describe(
2359
+ '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.'
2360
+ )
2291
2361
  };
2292
2362
  var OutputSchema = {
2293
2363
  message: import_schema6.z.string().optional().describe("Additional information about the operation result"),
2294
2364
  component_uid: import_schema6.z.string().optional().describe("The unique identifier of the newly created component (only present on success)")
2295
2365
  };
2296
- var VALID_ELEMENT_TYPES = ["e-div-block", "e-flexbox", "e-tabs"];
2297
2366
  var ERROR_MESSAGES = {
2298
2367
  ELEMENT_NOT_FOUND: "Element not found. Use 'list-elements' to get valid element IDs.",
2299
- ELEMENT_NOT_ONE_OF_TYPES: `Element is not one of the following types: ${VALID_ELEMENT_TYPES.join(", ")}`,
2368
+ ELEMENT_NOT_ONE_OF_TYPES: (validTypes) => `Element is not one of the following types: ${validTypes.join(", ")}`,
2300
2369
  ELEMENT_IS_LOCKED: "Cannot save a locked element as a component."
2301
2370
  };
2302
2371
  var handleSaveAsComponent = async (params) => {
2303
- const { element_id: elementId, component_name: componentName } = params;
2372
+ const { element_id: elementId, component_name: componentName, overridable_props: overridablePropsInput } = params;
2373
+ const validElementTypes = getValidElementTypes();
2304
2374
  const container = (0, import_editor_elements7.getContainer)(elementId);
2305
2375
  if (!container) {
2306
2376
  throw new Error(ERROR_MESSAGES.ELEMENT_NOT_FOUND);
2307
2377
  }
2308
2378
  const elType = container.model.get("elType");
2309
- if (!VALID_ELEMENT_TYPES.includes(elType)) {
2310
- throw new Error(ERROR_MESSAGES.ELEMENT_NOT_ONE_OF_TYPES);
2379
+ if (!validElementTypes.includes(elType)) {
2380
+ throw new Error(ERROR_MESSAGES.ELEMENT_NOT_ONE_OF_TYPES(validElementTypes));
2311
2381
  }
2312
2382
  const element = container.model.toJSON({ remove: ["default"] });
2313
2383
  if (element?.isLocked) {
2314
2384
  throw new Error(ERROR_MESSAGES.ELEMENT_IS_LOCKED);
2315
2385
  }
2316
- const uid = createUnpublishedComponent(componentName, element, null);
2386
+ const overridableProps = overridablePropsInput ? enrichOverridableProps(overridablePropsInput, element) : void 0;
2387
+ if (overridableProps) {
2388
+ updateElementDataWithOverridableProps(element, overridableProps);
2389
+ }
2390
+ const uid = (0, import_utils5.generateUniqueId)("component");
2391
+ try {
2392
+ await apiClient.validate({
2393
+ items: [
2394
+ { uid, title: componentName, elements: [element], settings: { overridable_props: overridableProps } }
2395
+ ]
2396
+ });
2397
+ } catch (error) {
2398
+ if (error instanceof import_http_client2.AxiosError) {
2399
+ throw new Error(error.response?.data.messge);
2400
+ }
2401
+ throw new Error("Unknown error");
2402
+ }
2403
+ createUnpublishedComponent(componentName, element, null, overridableProps, uid);
2317
2404
  return {
2318
2405
  status: "ok",
2319
2406
  message: `Component "${componentName}" created successfully.`,
2320
2407
  component_uid: uid
2321
2408
  };
2322
2409
  };
2323
- var initSaveAsComponentTool = () => {
2324
- return (0, import_editor_mcp.getMCPByDomain)("components").addTool({
2325
- name: "save-as-component",
2326
- schema: InputSchema,
2327
- outputSchema: OutputSchema,
2328
- description: `Save an existing element as a reusable component in the Elementor editor.
2329
-
2330
- ## When NOT to use this tool:
2331
- - Do not use for elements that are already components (widgetType: 'e-component').
2332
- - Do not use for locked elements.
2333
- - Do not guess element IDs. Always use "list-elements" first to get valid IDs.
2410
+ function enrichOverridableProps(input, rootElement) {
2411
+ const enrichedProps = {};
2412
+ const defaultGroupId = (0, import_utils5.generateUniqueId)("group");
2413
+ Object.entries(input.props).forEach(([, prop]) => {
2414
+ const { elementId, propKey } = prop;
2415
+ const element = findElementById(rootElement, elementId);
2416
+ if (!element) {
2417
+ throw new Error(`Element with ID "${elementId}" not found in component`);
2418
+ }
2419
+ const elType = element.elType;
2420
+ const widgetType = element.widgetType || element.elType;
2421
+ const elementType = (0, import_editor_elements7.getElementType)(widgetType);
2422
+ if (!elementType) {
2423
+ throw new Error(
2424
+ `Element type "${widgetType}" is not atomic or does not have a settings schema. Cannot expose property "${propKey}" for element "${elementId}".`
2425
+ );
2426
+ }
2427
+ if (!elementType.propsSchema[propKey]) {
2428
+ const availableProps = Object.keys(elementType.propsSchema).join(", ");
2429
+ throw new Error(
2430
+ `Property "${propKey}" does not exist in element "${elementId}" (type: ${widgetType}). Available properties: ${availableProps}`
2431
+ );
2432
+ }
2433
+ const overrideKey = (0, import_utils5.generateUniqueId)("prop");
2434
+ const originValue = element.settings?.[propKey] ? element.settings[propKey] : elementType.propsSchema[propKey].default ?? null;
2435
+ const label = generateLabel(propKey);
2436
+ enrichedProps[overrideKey] = {
2437
+ overrideKey,
2438
+ label,
2439
+ elementId,
2440
+ propKey,
2441
+ elType,
2442
+ widgetType,
2443
+ originValue,
2444
+ groupId: defaultGroupId
2445
+ };
2446
+ });
2447
+ return {
2448
+ props: enrichedProps,
2449
+ groups: {
2450
+ items: {
2451
+ [defaultGroupId]: {
2452
+ id: defaultGroupId,
2453
+ label: "Default",
2454
+ props: Object.keys(enrichedProps)
2455
+ }
2456
+ },
2457
+ order: [defaultGroupId]
2458
+ }
2459
+ };
2460
+ }
2461
+ function updateElementDataWithOverridableProps(rootElement, overridableProps) {
2462
+ Object.values(overridableProps.props).forEach((prop) => {
2463
+ const element = findElementById(rootElement, prop.elementId);
2464
+ if (!element || !element.settings) {
2465
+ return;
2466
+ }
2467
+ element.settings[prop.propKey] = {
2468
+ $$type: "overridable",
2469
+ value: {
2470
+ override_key: prop.overrideKey,
2471
+ origin_value: prop.originValue
2472
+ }
2473
+ };
2474
+ });
2475
+ }
2476
+ function findElementById(root, targetId) {
2477
+ if (root.id === targetId) {
2478
+ return root;
2479
+ }
2480
+ if (root.elements) {
2481
+ for (const child of root.elements) {
2482
+ const found = findElementById(child, targetId);
2483
+ if (found) {
2484
+ return found;
2485
+ }
2486
+ }
2487
+ }
2488
+ return null;
2489
+ }
2490
+ function generateLabel(propKey) {
2491
+ const uniqueId = (0, import_utils5.generateUniqueId)("prop");
2492
+ return `${uniqueId} - ${propKey}`;
2493
+ }
2494
+ function getValidElementTypes() {
2495
+ const types = (0, import_editor_elements7.getWidgetsCache)();
2496
+ if (!types) {
2497
+ return [];
2498
+ }
2499
+ return Object.entries(types).reduce((acc, [type, value]) => {
2500
+ if (!value.atomic_props_schema || !value.show_in_panel || value.elType === "widget") {
2501
+ return acc;
2502
+ }
2503
+ acc.push(type);
2504
+ return acc;
2505
+ }, []);
2506
+ }
2507
+ var generatePrompt = () => {
2508
+ const saveAsComponentPrompt = (0, import_editor_mcp.toolPrompts)("save-as-component");
2509
+ saveAsComponentPrompt.description(`
2510
+ Save an existing element as a reusable component in the Elementor editor.
2511
+
2512
+ # When to use this tool
2513
+ Use this tool when the user wants to:
2514
+ - Create a reusable component from an existing element structure
2515
+ - Make specific child element properties customizable in component instances
2516
+ - Build a library of reusable design patterns
2517
+
2518
+ # When NOT to use this tool
2519
+ - Element is already a component (widgetType: 'e-component')
2520
+ - Element is locked
2521
+ - Element is not an atomic element (atomic_props_schema is not defined)
2522
+ - Element elType is a 'widget'
2523
+
2524
+ # **CRITICAL - REQUIRED RESOURCES (Must read before using this tool)**
2525
+ 1. [${import_editor_canvas7.DOCUMENT_STRUCTURE_URI}]
2526
+ **MANDATORY** - Required to understand the document structure and identify child elements for overridable properties.
2527
+ Use this resource to find element IDs and understand the element hierarchy.
2528
+
2529
+ 2. [${import_editor_canvas7.WIDGET_SCHEMA_URI}]
2530
+ **MANDATORY** - Required to understand which properties are available for each widget type.
2531
+ Use this to identify available propKeys in the atomic_props_schema for child elements.
2532
+
2533
+ # Instructions - MUST FOLLOW IN ORDER
2534
+ ## Step 1: Identify the Target Element
2535
+ 1. Read the [${import_editor_canvas7.DOCUMENT_STRUCTURE_URI}] resource to understand the document structure
2536
+ 2. Locate the element you want to save as a component by its element_id
2537
+ 3. Verify the element type is a valid element type
2538
+ 4. Ensure the element is not locked and is not already a component
2539
+
2540
+ ## Step 2: Define Overridable Properties
2541
+ Do this step to make child element properties customizable.
2542
+ Skip that step ONLY if the user explicitly requests to not make any properties customizable.
2543
+
2544
+ 1. **Identify Child Elements**
2545
+ - Use the [${import_editor_canvas7.DOCUMENT_STRUCTURE_URI}] resource to find all child elements
2546
+ - Note the elementId and widgetType/elType of each child element you want to customize
2547
+
2548
+ 2. **Find Available Properties**
2549
+ - Use the [${import_editor_canvas7.WIDGET_SCHEMA_URI}] resource to find the child element's widget type schema
2550
+ - Review the atomic_props_schema to find available propKeys (ONLY use top-level props)
2551
+ - Common propKeys include: "text", "url", "tag", "size", etc.
2552
+ - Use only the top level properties, do not use nested properties.
2553
+
2554
+ 3. **Build the overridable_props Object**
2555
+ - For each property you want to make overridable, add an entry:
2556
+ \`{ "elementId": "<child-element-id>", "propKey": "<property-key>" }\`
2557
+ - Group all entries under the "props" object
2558
+
2559
+ ## Step 3: Execute the Tool
2560
+ Call the tool with:
2561
+ - element_id: The ID of the parent element to save as component
2562
+ - component_name: A descriptive name for the component
2563
+ - overridable_props: (Optional) The properties configuration from Step 2
2564
+
2565
+ # CONSTRAINTS
2566
+ - NEVER try to override properties of the parent element itself - ONLY child elements
2567
+ - NEVER use invalid propKeys - always verify against the widget's atomic_props_schema in [${import_editor_canvas7.WIDGET_SCHEMA_URI}]
2568
+ - Property keys must exist in the child element's atomic_props_schema
2569
+ - Element IDs must exist within the target element's children
2570
+ - When tool execution fails, read the error message and adjust accordingly
2571
+ - The element being saved must not be inside another component
2572
+ `);
2573
+ saveAsComponentPrompt.parameter(
2574
+ "element_id",
2575
+ `**MANDATORY** The unique identifier of the element to save as a component.
2576
+ Use the [${import_editor_canvas7.DOCUMENT_STRUCTURE_URI}] resource to find available element IDs.`
2577
+ );
2578
+ saveAsComponentPrompt.parameter(
2579
+ "component_name",
2580
+ `**MANDATORY** A descriptive name for the new component.
2581
+ Should be unique and clearly describe the component's purpose (e.g., "Hero Section", "Feature Card").`
2582
+ );
2583
+ saveAsComponentPrompt.parameter(
2584
+ "overridable_props",
2585
+ `**OPTIONAL** Configuration for which child element properties can be customized in component instances.
2334
2586
 
2335
- ## Prerequisites:
2336
- - **Verify element type**: Ensure the element is not already a component (widgetType should not be 'e-component').
2337
- - **Check if element is unlocked**: Locked elements cannot be saved as components.
2338
- - **Check that the element is one of the following types**: ${VALID_ELEMENT_TYPES.join(", ")}
2587
+ Structure:
2588
+ \`\`\`json
2589
+ {
2590
+ "props": {
2591
+ "<unique-key>": {
2592
+ "elementId": "<child-element-id>",
2593
+ "propKey": "<property-key>"
2594
+ }
2595
+ }
2596
+ }
2597
+ \`\`\`
2339
2598
 
2340
- ## Required parameters:
2341
- - **element_id**: The unique ID of the element to save.
2342
- - **component_name**: A descriptive name for the component (2-50 characters).
2599
+ To populate this correctly:
2600
+ 1. Use [${import_editor_canvas7.DOCUMENT_STRUCTURE_URI}] to find child element IDs and their widgetType
2601
+ 2. Use [${import_editor_canvas7.WIDGET_SCHEMA_URI}] to find the atomic_props_schema for each child element's widgetType
2602
+ 3. Only include properties you want to be customizable in component instances
2603
+ 4. Common propKeys: "text", "url", "tag", "size", "align", etc.`
2604
+ );
2605
+ saveAsComponentPrompt.example(`
2606
+ Basic component without overridable properties:
2607
+ \`\`\`json
2608
+ {
2609
+ "element_id": "abc123",
2610
+ "component_name": "Hero Section"
2611
+ }
2612
+ \`\`\`
2343
2613
 
2344
- ## Example tool call:
2614
+ Component with overridable properties:
2345
2615
  \`\`\`json
2346
- { "element_id": "abc123", "component_name": "Hero Section" }
2616
+ {
2617
+ "element_id": "abc123",
2618
+ "component_name": "Feature Card",
2619
+ "overridable_props": {
2620
+ "props": {
2621
+ "heading-text": {
2622
+ "elementId": "heading-123",
2623
+ "propKey": "text"
2624
+ },
2625
+ "button-text": {
2626
+ "elementId": "button-456",
2627
+ "propKey": "text"
2628
+ },
2629
+ "button-link": {
2630
+ "elementId": "button-456",
2631
+ "propKey": "url"
2632
+ }
2633
+ }
2634
+ }
2635
+ }
2347
2636
  \`\`\`
2348
- `,
2637
+ `);
2638
+ saveAsComponentPrompt.instruction(
2639
+ `After successful creation, the component will be available in the components library and can be inserted into any page or template.`
2640
+ );
2641
+ saveAsComponentPrompt.instruction(
2642
+ `When overridable properties are defined, component instances will show customization controls for those specific properties in the editing panel.`
2643
+ );
2644
+ return saveAsComponentPrompt.prompt();
2645
+ };
2646
+ var initSaveAsComponentTool = () => {
2647
+ return (0, import_editor_mcp.getMCPByDomain)("components").addTool({
2648
+ name: "save-as-component",
2649
+ schema: InputSchema,
2650
+ outputSchema: OutputSchema,
2651
+ description: generatePrompt(),
2349
2652
  handler: handleSaveAsComponent
2350
2653
  });
2351
2654
  };
@@ -2418,7 +2721,8 @@ async function createComponentsBeforeSave({
2418
2721
  unpublishedComponents.map((component) => ({
2419
2722
  id: uidToComponentId.get(component.uid),
2420
2723
  name: component.name,
2421
- uid: component.uid
2724
+ uid: component.uid,
2725
+ overridableProps: component.overridableProps ? component.overridableProps : void 0
2422
2726
  }))
2423
2727
  )
2424
2728
  );
@@ -2433,7 +2737,8 @@ async function createComponents(components, status) {
2433
2737
  items: components.map((component) => ({
2434
2738
  uid: component.uid,
2435
2739
  title: component.name,
2436
- elements: component.elements
2740
+ elements: component.elements,
2741
+ settings: component.overridableProps ? { overridable_props: component.overridableProps } : void 0
2437
2742
  }))
2438
2743
  });
2439
2744
  const map = /* @__PURE__ */ new Map();
@@ -2558,7 +2863,7 @@ var beforeSave = ({ container, status }) => {
2558
2863
  function init() {
2559
2864
  import_editor_styles_repository2.stylesRepository.register(componentsStylesProvider);
2560
2865
  (0, import_store50.__registerSlice)(slice);
2561
- (0, import_editor_canvas6.registerElementType)(
2866
+ (0, import_editor_canvas8.registerElementType)(
2562
2867
  TYPE,
2563
2868
  (options) => createComponentType({ ...options, showLockedByModal: openEditModeDialog })
2564
2869
  );
@@ -2614,8 +2919,9 @@ function init() {
2614
2919
  condition: (_, elementType) => elementType.key === "e-component",
2615
2920
  component: InstanceEditingPanel
2616
2921
  });
2617
- import_editor_canvas6.settingsTransformersRegistry.register("component-instance", componentInstanceTransformer);
2618
- import_editor_canvas6.settingsTransformersRegistry.register("overridable", componentOverridableTransformer);
2922
+ import_editor_canvas8.settingsTransformersRegistry.register("component-instance", componentInstanceTransformer);
2923
+ import_editor_canvas8.settingsTransformersRegistry.register("overridable", componentOverridableTransformer);
2924
+ import_editor_canvas8.settingsTransformersRegistry.register("override", componentOverrideTransformer);
2619
2925
  initMcp();
2620
2926
  }
2621
2927
  // Annotate the CommonJS export names for ESM import in node: