@elementor/editor-components 3.35.0-356 → 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.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) => ({ uid: item.uid, name: item.name })),
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 uid = generateUniqueId("component");
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(uid));
1134
+ dispatch3(slice.actions.addCreatedThisSession(generatedUid));
1129
1135
  replaceElementWithComponent(element, componentBase);
1130
1136
  trackComponentEvent({
1131
1137
  action: "created",
1132
- component_uid: uid,
1138
+ component_uid: generatedUid,
1133
1139
  component_name: name,
1134
1140
  ...eventData
1135
1141
  });
1136
1142
  runCommand2("document/save/auto");
1137
- return uid;
1143
+ return generatedUid;
1138
1144
  }
1139
1145
 
1140
1146
  // src/components/create-component-form/hooks/use-form.ts
@@ -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 { getContainer as getContainer2 } from "@elementor/editor-elements";
2277
- import { getMCPByDomain } from "@elementor/editor-mcp";
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: ${VALID_ELEMENT_TYPES.join(", ")}`,
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 (!VALID_ELEMENT_TYPES.includes(elType)) {
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 uid = createUnpublishedComponent(componentName, element, null);
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
- var initSaveAsComponentTool = () => {
2317
- return getMCPByDomain("components").addTool({
2318
- name: "save-as-component",
2319
- schema: InputSchema,
2320
- outputSchema: OutputSchema,
2321
- description: `Save an existing element as a reusable component in the Elementor editor.
2322
-
2323
- ## When NOT to use this tool:
2324
- - Do not use for elements that are already components (widgetType: 'e-component').
2325
- - Do not use for locked elements.
2326
- - Do not guess element IDs. Always use "list-elements" first to get valid IDs.
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
- ## Prerequisites:
2329
- - **Verify element type**: Ensure the element is not already a component (widgetType should not be 'e-component').
2330
- - **Check if element is unlocked**: Locked elements cannot be saved as components.
2331
- - **Check that the element is one of the following types**: ${VALID_ELEMENT_TYPES.join(", ")}
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
- ## Required parameters:
2334
- - **element_id**: The unique ID of the element to save.
2335
- - **component_name**: A descriptive name for the component (2-50 characters).
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
- ## Example tool call:
2558
+ Component with overridable properties:
2338
2559
  \`\`\`json
2339
- { "element_id": "abc123", "component_name": "Hero Section" }
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();