@elementor/editor-canvas 3.35.0-470 → 3.35.0-472

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
@@ -68,7 +68,7 @@ The css string must follow standard CSS syntax, with properties and values separ
68
68
  "styles-schema",
69
69
  new ResourceTemplate(STYLE_SCHEMA_URI, {
70
70
  list: () => {
71
- const categories = [...Object.keys(getStylesSchema())];
71
+ const categories = [...Object.keys(getStylesSchema())].filter((category) => category !== "all");
72
72
  return {
73
73
  resources: categories.map((category) => ({
74
74
  uri: `elementor://styles/schema/${category}`,
@@ -2212,8 +2212,15 @@ function extractElementData(element) {
2212
2212
 
2213
2213
  // src/mcp/tools/build-composition/tool.ts
2214
2214
  import {
2215
- createElement as createElement6,
2215
+ createElement as createElement7,
2216
2216
  deleteElement,
2217
+ getContainer as getContainer3,
2218
+ getWidgetsCache as getWidgetsCache6
2219
+ } from "@elementor/editor-elements";
2220
+
2221
+ // src/composition-builder/composition-builder.ts
2222
+ import {
2223
+ createElement as createElement6,
2217
2224
  generateElementId,
2218
2225
  getContainer as getContainer2,
2219
2226
  getWidgetsCache as getWidgetsCache5
@@ -2230,7 +2237,11 @@ import {
2230
2237
  import { getPropSchemaFromCache, Schema as Schema2 } from "@elementor/editor-props";
2231
2238
  import { getStylesSchema as getStylesSchema3 } from "@elementor/editor-styles";
2232
2239
  function resolvePropValue(value, forceKey) {
2233
- return Schema2.adjustLlmPropValueSchema(value, { forceKey });
2240
+ const Utils = window.elementorV2.editorVariables.Utils;
2241
+ return Schema2.adjustLlmPropValueSchema(value, {
2242
+ forceKey,
2243
+ transformers: Utils.globalVariablesLLMResolvers
2244
+ });
2234
2245
  }
2235
2246
  var doUpdateElementProperty = (params) => {
2236
2247
  const { elementId, propertyName, propertyValue, elementType } = params;
@@ -2374,9 +2385,14 @@ var validateInput = {
2374
2385
  } else if (!Schema3.isPropKeyConfigurable(propName)) {
2375
2386
  errors.push(`Property "${propName}" is not configurable.`);
2376
2387
  } else {
2377
- const { valid, jsonSchema } = Schema3.validatePropValue(propSchema, propValue);
2388
+ const { valid } = Schema3.validatePropValue(propSchema, propValue);
2378
2389
  if (!valid) {
2379
- errors.push(`Invalid property "${propName}". Expected schema: ${jsonSchema}`);
2390
+ errors.push(
2391
+ `Invalid property "${propName}". Validate input with resource [${STYLE_SCHEMA_URI.replace(
2392
+ "{category}",
2393
+ propName
2394
+ )}]`
2395
+ );
2380
2396
  }
2381
2397
  }
2382
2398
  });
@@ -2415,290 +2431,292 @@ var validateInput = {
2415
2431
  }
2416
2432
  };
2417
2433
 
2418
- // src/mcp/tools/build-composition/prompt.ts
2419
- import { toolPrompts } from "@elementor/editor-mcp";
2420
- var generatePrompt = () => {
2421
- const buildCompositionsToolPrompt = toolPrompts("build-compositions");
2422
- buildCompositionsToolPrompt.description(`
2423
- # **CRITICAL - REQUIRED RESOURCES (Must read before using this tool)**
2424
- 1. [${WIDGET_SCHEMA_URI}]
2425
- Required to understand which widgets are available, and what are their configuration schemas.
2426
- Every widgetType (i.e. e-heading, e-button) that is supported has it's own property schema, that you must follow in order to apply property values correctly.
2427
- 2. [${STYLE_SCHEMA_URI}]
2428
- Required to understand the styles schema for the widgets. All widgets share the same styles schema.
2429
- 3. List of allowed custom tags for building the structure is derived from the list of widgets schema resources.
2430
-
2431
- # DESIGN QUALITY IMPERATIVE
2432
- You are generating designs for real users who expect distinctive, intentional aesthetics - NOT generic AI output.
2433
- **The Core Challenge**: Large language models naturally converge toward statistically common design patterns during generation. This creates predictable, uninspired results that users describe as "AI slop": safe color schemes, default typography hierarchies, minimal contrast, and timid spacing.
2434
- **Your Mission**: Actively resist distributional convergence by making intentional, distinctive design choices across all aesthetic dimensions. Every design decision should have a clear purpose tied to visual hierarchy, brand personality, or user experience goals.
2435
- When in doubt between "safe" and "distinctive," choose distinctive - users can always request refinements, but they cannot salvage generic foundations.
2436
-
2437
- # When to use this tool
2438
- Always prefer this tool when the user requires to build a composition of elements, such as cards, heros, or inspired from other pages or HTML compositions.
2439
- Prefer this tool over any other tool for building HTML structure, unless you are specified to use a different tool.
2440
-
2441
- # **CRITICAL - REQUIRED RESOURCES (Must read before using this tool)**
2442
- 1. [${WIDGET_SCHEMA_URI}]
2443
- Required to understand which widgets are available, and what are their configuration schemas.
2444
- Every widgetType (i.e. e-heading, e-button) that is supported has it's own property schema, that you must follow in order to apply property values correctly.
2445
- 2. [${STYLE_SCHEMA_URI}]
2446
- Required to understand the styles schema for the widgets. All widgets share the same styles schema.
2447
- 3. List of allowed custom tags for building the structure is derived from the list of widgets schema resources.
2448
-
2449
- # DESIGN QUALITY IMPERATIVE
2450
- You are generating designs for real users who expect distinctive, intentional aesthetics - NOT generic AI output.
2451
- **The Core Challenge**: Large language models naturally converge toward statistically common design patterns during generation. This creates predictable, uninspired results that users describe as "AI slop": safe color schemes, default typography hierarchies, minimal contrast, and timid spacing.
2452
- **Your Mission**: Actively resist distributional convergence by making intentional, distinctive design choices across all aesthetic dimensions. Every design decision should have a clear purpose tied to visual hierarchy, brand personality, or user experience goals.
2453
- When in doubt between "safe" and "distinctive," choose distinctive - users can always request refinements, but they cannot salvage generic foundations.
2454
-
2455
- # When to use this tool
2456
- Always prefer this tool when the user requires to build a composition of elements, such as cards, heros, or inspired from other pages or HTML compositions.
2457
- Prefer this tool over any other tool for building HTML structure, unless you are specified to use a different tool.
2458
-
2459
- # Instructions
2460
- 1. Understand the user requirements carefully.
2461
- 2. Build a valid XML structure using only the allowed custom tags provided. For example, if you
2462
- use the "e-button" element, it would be represented as <e-button></e-button> in the XML structure.
2463
- 3. Plan the configuration for each element according to the user requirements, using the configuration schema provided for each custom tag.
2464
- Every widget type has it's own configuration schema, retreivable from the resource [${WIDGET_SCHEMA_URI}].
2465
- PropValues must follow the exact PropType schema provided in the resource.
2466
- 4. For every element, provide a "configuration-id" attribute. For example:
2467
- \`<e-flexbox configuration-id="flex1"><e-heading configuration-id="heading2"></e-heading></e-flexbox>\`
2468
- In the elementConfig property, provide the actual configuration object for each configuration-id used in the XML structure.
2469
- In the stylesConfig property, provide the actual styles configuration object for each configuration-id used in the XML structure.
2470
- 5. Ensure the XML structure is valid and parsable.
2471
- 6. Do not add any attribute nodes, classes, id's, and no text nodes allowed.
2472
- Layout properties, such as margin, padding, align, etc. must be applied using the [${STYLE_SCHEMA_URI}] PropValues.
2473
- 7. Some elements allow nesting of other elements, and most of the DO NOT. The allowed elements that can have nested children are "e-tabs", "e-div-block", and "e-flexbox".
2474
- 8. Make sure that non-container elements do NOT have any nested elements.
2475
-
2476
- # DESIGN VECTORS - Concrete Implementation Guidance
2477
-
2478
- ## 1. Typography & Visual Hierarchy
2479
-
2480
- **Avoid Distributional Defaults:**
2481
- - NO generic sans-serifs as primary typefaces (Inter, Roboto, Arial, Helvetica)
2482
- - NO timid size ratios (1.2x, 1.5x scaling)
2483
- - NO uniform font weights (everything at 400 or 600)
2484
-
2485
- **Intentional Alternatives:**
2486
- - **For Technical/Modern**: Consider monospace headlines (JetBrains Mono, SF Mono) paired with clean body text
2487
- - **For Editorial/Elegant**: Consider serif headlines (Playfair Display, Crimson Text) with sans-serif body
2488
- - **For Playful/Creative**: Consider display fonts with character, paired with highly legible body text
2489
-
2490
- **Scale & Contrast Implementation:**
2491
- - Headline-to-body size ratios: 3x minimum (e.g., 48px headline vs 16px body)
2492
- - Use extreme weight contrasts: pair weight-100 or 200 with weight-800 or 900
2493
- - Line height contrasts: tight headlines (1.1) vs. generous body (1.7)
2494
- - Letter spacing: compressed headlines (-0.02em to -0.05em) vs. open small text (0.03em+)
2495
-
2496
- **Hierarchy Mapping:**
2497
- /* Intentional hierarchy example */
2498
- H1: font-size: 3.5rem; font-weight: 900; line-height: 1.1; letter-spacing: -0.03em;
2499
- H2: font-size: 2rem; font-weight: 200; line-height: 1.2;
2500
- Body: font-size: 1rem; font-weight: 400; line-height: 1.7;
2501
- Caption: font-size: 0.75rem; font-weight: 600; letter-spacing: 0.05em; text-transform: uppercase;
2502
-
2503
- ## 2. Color & Theme Strategy
2504
-
2505
- **Avoid Distributional Defaults:**
2506
- - NO purple gradients or blue-purple color schemes (massively overrepresented in AI output)
2507
- - NO evenly-distributed color palettes (3-4 colors used equally)
2508
- - NO timid pastels or all-neutral schemes
2509
- - NO #333333, #666666, #999999 grays
2510
-
2511
- **Intentional Alternatives:**
2512
- - **Commit to a Dominant Color**: Choose ONE primary brand color that appears in 60-70% of colored elements
2513
- - **Sharp Accent Strategy**: Use 1-2 high-contrast accent colors sparingly (10-15% of colored elements)
2514
- - **Neutrals with Personality**: Replace pure grays with warm (#3d3228, #f5f1ed) or cool (#2a2f3d, #f0f2f5) tinted neutrals
2515
-
2516
- **Color Psychology Mapping:**
2517
- - Energy/Action \u2192 Warm reds, oranges, yellows (NOT purple/blue)
2518
- - Trust/Calm \u2192 Deep teals, forest greens (NOT generic blue)
2519
- - Luxury/Premium \u2192 Deep burgundy, emerald, charcoal with gold accents
2520
- - Playful/Creative \u2192 Unexpected combinations (coral + mint, mustard + navy)
2521
-
2522
- **Implementation:**
2523
- /* Intentional color system example */
2524
- --brand-primary: #d84315; /* Dominant: Deep orange */
2525
- --brand-accent: #00bfa5; /* Accent: Teal (complementary) */
2526
- --neutral-dark: #2d2622; /* Warm dark brown, not #333 */
2527
- --neutral-light: #faf8f6; /* Warm off-white, not pure white */
2528
- --background: linear-gradient(135deg, #faf8f6 0%, #f0ebe6 100%); /* Subtle warmth */
2529
-
2530
- ## 3. Spatial Design & White Space
2531
-
2532
- **Avoid Distributional Defaults:**
2533
- - NO uniform spacing (everything 16px or 24px)
2534
- - NO cramped layouts that maximize content density
2535
- - NO default container widths (1200px, 1440px)
2536
-
2537
- **Intentional Alternatives:**
2538
- - **Breathing Room**: Use generous white space as a design element (80-120px vertical spacing between sections)
2539
- - **Asymmetric Spacing**: Vary padding dramatically (small: 12px, medium: 48px, large: 96px)
2540
- - **Content Width Strategy**:
2541
- - Reading content: max 65-75 characters (600-700px)
2542
- - Hero sections: asymmetric layouts, not centered blocks
2543
- - Cards/components: vary sizes intentionally, not uniform grids
2544
-
2545
- **Implementation:**
2546
- /* Intentional spacing scale */
2547
- --space-xs: 0.5rem; /* 8px */
2548
- --space-sm: 1rem; /* 16px */
2549
- --space-md: 3rem; /* 48px */
2550
- --space-lg: 6rem; /* 96px */
2551
- --space-xl: 10rem; /* 160px */
2552
-
2553
- /* Use in combinations: */
2554
- padding: var(--space-lg) var(--space-md); /* Not uniform padding */
2555
- margin-bottom: var(--space-xl); /* Generous section breaks */
2556
-
2557
- ## 4. Backgrounds & Atmospheric Depth
2558
-
2559
- **Avoid Distributional Defaults:**
2560
- - NO solid white or light gray backgrounds
2561
- - NO single-color backgrounds
2562
- - NO generic gradient overlays
2563
-
2564
- **Intentional Alternatives:**
2565
- - **Layered Gradients**: Combine 2-3 subtle gradients for depth
2566
- - **Geometric Patterns**: SVG patterns, mesh gradients, or subtle noise textures
2567
- - **Strategic Contrast**: Alternate between light and dark sections for rhythm
2568
-
2569
- **Implementation:**
2570
- /* Intentional background example */
2571
- background:
2572
- radial-gradient(circle at 20% 30%, rgba(216, 67, 21, 0.08) 0%, transparent 50%),
2573
- radial-gradient(circle at 80% 70%, rgba(0, 191, 165, 0.06) 0%, transparent 50%),
2574
- linear-gradient(135deg, #faf8f6 0%, #f0ebe6 100%);
2575
-
2576
- ## 5. Visual Hierarchy Principles
2577
-
2578
- **Clear Priority System:**
2579
- 1. **Primary Focus (1 element)**: Largest, highest contrast, most visual weight
2580
- 2. **Secondary Elements (2-3 elements)**: 40-60% of primary size, reduced contrast
2581
- 3. **Tertiary/Support (everything else)**: Minimal visual weight, muted colors
2582
-
2583
- **Contrast Techniques:**
2584
- - Size: 3x+ differences between hierarchy levels
2585
- - Weight: 300+ difference in font-weight values
2586
- - Color: Primary gets brand color, secondary gets neutral, tertiary gets muted
2587
- - Space: Primary gets 2x+ surrounding white space vs. secondary
2588
-
2589
- ## 6. EXAMPLES - Intentional vs. Generic Design
2590
-
2591
- ### \u274C GENERIC (Distributional Convergence)
2592
-
2593
- {
2594
- "xmlStructure": "<e-flexbox configuration-id="flex1"><e-heading configuration-id="heading1"></e-heading><e-button configuration-id="button1"></e-button></e-flexbox>",
2595
- "elementConfig": {
2596
- "heading1": {
2597
- "title": { "$$type": "string", "value": "Welcome to Our Site" }
2598
- }
2599
- },
2600
- "stylesConfig": {
2601
- "heading1": {
2602
- "font-size": {
2603
- "$$type": "size",
2604
- "value": {
2605
- "size": { "$$type": "number", "value": 24 },
2606
- "unit": { "$$type": "string", "value": "px" }
2607
- }
2434
+ // src/composition-builder/composition-builder.ts
2435
+ var CompositionBuilder = class _CompositionBuilder {
2436
+ elementConfig = {};
2437
+ elementStylesConfig = {};
2438
+ rootContainers = [];
2439
+ containerElements = [];
2440
+ api = {
2441
+ createElement: createElement6,
2442
+ getWidgetsCache: getWidgetsCache5,
2443
+ generateElementId,
2444
+ getContainer: getContainer2,
2445
+ doUpdateElementProperty
2446
+ };
2447
+ xml;
2448
+ static fromXMLString(xmlString, api = {}) {
2449
+ const parser = new DOMParser();
2450
+ const xmlDoc = parser.parseFromString(xmlString, "application/xml");
2451
+ const errorNode = xmlDoc.querySelector("parsererror");
2452
+ if (errorNode) {
2453
+ throw new Error("Failed to parse XML string: " + errorNode.textContent);
2454
+ }
2455
+ return new _CompositionBuilder({
2456
+ xml: xmlDoc,
2457
+ api
2458
+ });
2459
+ }
2460
+ constructor(opts) {
2461
+ const { api = {}, elementConfig = {}, stylesConfig = {}, xml } = opts;
2462
+ this.xml = xml;
2463
+ Object.assign(this.api, api);
2464
+ this.setElementConfig(elementConfig);
2465
+ this.setStylesConfig(stylesConfig);
2466
+ }
2467
+ setElementConfig(config) {
2468
+ this.elementConfig = config;
2469
+ }
2470
+ setStylesConfig(config) {
2471
+ this.elementStylesConfig = config;
2472
+ }
2473
+ getXML() {
2474
+ return this.xml;
2475
+ }
2476
+ iterateBuild(node, containerElement, childIndex) {
2477
+ const elementTag = node.tagName;
2478
+ const isContainer = this.containerElements.includes(elementTag);
2479
+ const parentElType = containerElement.model.get("elType");
2480
+ let targetContainerId = parentElType === "e-tabs" ? containerElement.children?.[1].children?.[childIndex]?.id || containerElement.children?.[1].id : containerElement.id;
2481
+ if (!targetContainerId) {
2482
+ targetContainerId = containerElement.id;
2483
+ }
2484
+ const newElement = isContainer ? this.api.createElement({
2485
+ containerId: targetContainerId,
2486
+ model: {
2487
+ elType: elementTag,
2488
+ id: generateElementId()
2489
+ },
2490
+ options: { useHistory: false }
2491
+ }) : this.api.createElement({
2492
+ containerId: targetContainerId,
2493
+ model: {
2494
+ elType: "widget",
2495
+ widgetType: elementTag,
2496
+ id: generateElementId()
2608
2497
  },
2498
+ options: { useHistory: false }
2499
+ });
2500
+ if (containerElement.id === "document") {
2501
+ this.rootContainers.push(newElement);
2502
+ }
2503
+ node.setAttribute("id", newElement.id);
2504
+ let currentChild = 0;
2505
+ for (const childNode of Array.from(node.children)) {
2506
+ this.iterateBuild(childNode, newElement, currentChild);
2507
+ currentChild++;
2609
2508
  }
2610
2509
  }
2611
- }
2612
-
2613
- **Why Generic**: 24px default size, #333 safe gray, 600 weight (middle-ground), purple gradient (AI clich\xE9), uniform 12/24px padding
2614
-
2615
- ### \u2705 INTENTIONAL (Resisting Convergence)
2616
- {
2617
- "xmlStructure": "<e-flexbox configuration-id="hero-section"><e-heading configuration-id="hero-title"></e-heading><e-text configuration-id="hero-subtitle"></e-text><e-button configuration-id="hero-cta"></e-button></e-flexbox>",
2618
- "elementConfig": {
2619
- "hero-title": {
2620
- "title": { "$$type": "string", "value": "Transform Your Workflow" }
2621
- },
2622
- "hero-subtitle": {
2623
- "content": { "$$type": "string", "value": "Built for teams who refuse to compromise on quality" }
2510
+ findSchemaForNode(node) {
2511
+ const widgetsCache = this.api.getWidgetsCache() || {};
2512
+ const widgetType = node.tagName;
2513
+ const widgetData = widgetsCache[widgetType]?.atomic_props_schema;
2514
+ return widgetData || null;
2515
+ }
2516
+ matchNodeByConfigId(configId) {
2517
+ const node = this.xml.querySelector(`[configuration-id="${configId}"]`);
2518
+ if (!node) {
2519
+ throw new Error(`Configuration id "${configId}" does not have target node.`);
2624
2520
  }
2625
- },
2626
- "stylesConfig": {
2627
- "hero-section": {
2628
- "display": { "$$type": "string", "value": "flex" },
2629
- "flex-direction": { "$$type": "string", "value": "column" },
2630
- "align-items": { "$$type": "string", "value": "flex-start" },
2631
- "background": {
2632
- "$$type": "color",
2633
- "value": "#f0ebe6",
2634
- "$intention": "background: #f0ebe6",
2521
+ const id = node.getAttribute("id");
2522
+ if (!id) {
2523
+ throw new Error(`Node with configuration id "${configId}" does not have element id.`);
2524
+ }
2525
+ const element = this.api.getContainer(id);
2526
+ if (!element) {
2527
+ throw new Error(`Element with id "${id}" not found but should exist.`);
2528
+ }
2529
+ return {
2530
+ element,
2531
+ node
2532
+ };
2533
+ }
2534
+ applyStyles() {
2535
+ const errors = [];
2536
+ const invalidStyles = {};
2537
+ const validStylesPropValues = {};
2538
+ for (const [styleId, styleConfig] of Object.entries(this.elementStylesConfig)) {
2539
+ const { element, node } = this.matchNodeByConfigId(styleId);
2540
+ for (const [styleName, stylePropValue] of Object.entries(styleConfig)) {
2541
+ const { valid, errors: validationErrors } = validateInput.validateStyles({
2542
+ [styleName]: stylePropValue
2543
+ });
2544
+ if (!valid) {
2545
+ if (styleConfig.$intention) {
2546
+ invalidStyles[element.id] = invalidStyles[element.id] || [];
2547
+ invalidStyles[element.id].push(styleName);
2548
+ }
2549
+ errors.push(...validationErrors || []);
2550
+ } else {
2551
+ validStylesPropValues[styleName] = stylePropValue;
2552
+ }
2553
+ this.api.doUpdateElementProperty({
2554
+ elementId: element.id,
2555
+ propertyName: "_styles",
2556
+ propertyValue: validStylesPropValues,
2557
+ elementType: node.tagName
2558
+ });
2635
2559
  }
2636
- },
2637
- "hero-title": {
2638
- "font-size": {
2639
- "$$type": "size",
2640
- "value": {
2641
- "size": { "$$type": "number", "value": 72 },
2642
- "unit": { "$$type": "string", "value": "px" }
2560
+ }
2561
+ return {
2562
+ errors,
2563
+ invalidStyles
2564
+ };
2565
+ }
2566
+ applyConfigs() {
2567
+ const errors = [];
2568
+ for (const [configId, config] of Object.entries(this.elementConfig)) {
2569
+ const { element, node } = this.matchNodeByConfigId(configId);
2570
+ const propSchema = this.findSchemaForNode(node);
2571
+ const result = validateInput.validateProps(propSchema, config);
2572
+ if (!result.valid && result.errors?.length) {
2573
+ errors.push(...result.errors);
2574
+ } else {
2575
+ for (const [propertyName, propertyValue] of Object.entries(config)) {
2576
+ try {
2577
+ this.api.doUpdateElementProperty({
2578
+ elementId: element.id,
2579
+ propertyName,
2580
+ propertyValue,
2581
+ elementType: node.tagName
2582
+ });
2583
+ } catch (error) {
2584
+ errors.push(error.message);
2643
2585
  }
2644
- },
2586
+ }
2587
+ }
2645
2588
  }
2589
+ return errors;
2646
2590
  }
2647
- }
2648
-
2649
-
2650
- **Why Intentional**:
2651
- - Typography: 4.5rem headline (3.6x body), weight 900 vs 200 contrast, tight leading
2652
- - Color: Warm orange primary (#d84315), warm neutrals (#2d2622, #5a534d) NOT #333/#666
2653
- - Spacing: 10rem vertical padding (generous), 3rem gap, asymmetric alignment
2654
- - Background: Layered gradients with subtle brand color accent
2655
-
2656
- # CONSTRAINTS
2657
- When a tool execution fails, retry up to 10 more times, read the error message carefully, and adjust the XML structure or the configurations accordingly.
2658
- If a "$$type" is missing, update the invalid object, if the XML has parsing errors, fix it, etc. and RETRY.
2659
- VALIDATE the XML structure before delivering it as the final result.
2660
- VALIDATE the JSON structure used in the "configuration" attributes for each element before delivering the final result. The configuration must MATCH the PropValue schemas.
2661
- NO LINKS ALLOWED. Never apply links to elements, even if they appear in the PropType schema.
2662
- elementConfig values must align with the widget's PropType schema, available at the resource [${WIDGET_SCHEMA_URI}].
2663
- stylesConfig values must align with the common styles PropType schema, available at the resource [${STYLE_SCHEMA_URI}].
2664
-
2665
- # DESIGN QUALITY CONSTRAINTS
2666
-
2667
- **Typography Constraints:**
2668
- - NEVER use Inter, Roboto, Arial, or Helvetica as primary display fonts
2669
- - NEVER use font-size ratios smaller than 2.5x between headlines and body
2670
- - NEVER use font-weight values between 500-700 for headlines (go lighter or heavier)
2671
-
2672
- **Color Constraints:**
2673
- - NEVER use purple gradients or blue-purple color schemes
2674
- - NEVER use pure grays (#333, #666, #999) - use tinted neutrals instead
2675
- - NEVER distribute colors evenly - commit to ONE dominant color
2676
- - NEVER use more than 3 core colors (1 dominant, 1-2 accents)
2677
-
2678
- **Spacing Constraints:**
2679
- - NEVER use uniform spacing across all elements
2680
- - NEVER use section padding less than 4rem (64px) for hero/major sections
2681
- - NEVER center everything - use asymmetric layouts for visual interest
2682
-
2683
- **Background Constraints:**
2684
- - NEVER use solid white (#ffffff) or light gray (#f5f5f5) backgrounds without texture/gradients
2685
- - ALWAYS layer at least 2 gradient or color elements for atmospheric depth
2686
-
2687
- # Parameters
2688
- All parameters are MANDATORY.
2689
- - xmlStructure
2690
- - elementConfig
2691
- - stylesConfig
2692
-
2693
- If unsure about the configuration of a specific property, read the schema resources carefully.
2694
-
2695
- # About our widgets
2696
- Most widgets are self-explanatory by their name. Here is some additional information.
2697
- Check for available llm_guidance property in the widget's schema.
2698
- SVG elements are bound to internal content upload. Avoid usage, unless you have tools to upload SVG content.
2699
- When working with containers, do not forget to apply style schema for controlling the layout.
2700
-
2591
+ build(rootContainer) {
2592
+ const widgetsCache = this.api.getWidgetsCache() || {};
2593
+ const CONTAINER_ELEMENTS = Object.values(widgetsCache).filter((widget) => widget.meta?.is_container).map((widget) => widget.elType).filter((x) => typeof x === "string");
2594
+ this.containerElements = CONTAINER_ELEMENTS;
2595
+ new Set(this.xml.querySelectorAll("*")).forEach((node) => {
2596
+ if (!widgetsCache[node.tagName]) {
2597
+ throw new Error(`Unknown widget type: ${node.tagName}`);
2598
+ }
2599
+ });
2600
+ const children = Array.from(this.xml.children);
2601
+ let currentChild = 0;
2602
+ for (const childNode of children) {
2603
+ this.iterateBuild(childNode, rootContainer, currentChild);
2604
+ currentChild++;
2605
+ }
2606
+ const { errors: styleErrors, invalidStyles } = this.applyStyles();
2607
+ const configErrors = this.applyConfigs();
2608
+ return {
2609
+ configErrors,
2610
+ styleErrors,
2611
+ invalidStyles,
2612
+ rootContainers: [...this.rootContainers]
2613
+ };
2614
+ }
2615
+ };
2701
2616
 
2617
+ // src/mcp/tools/build-composition/prompt.ts
2618
+ import { toolPrompts } from "@elementor/editor-mcp";
2619
+ var generatePrompt = () => {
2620
+ const buildCompositionsToolPrompt = toolPrompts("build-compositions");
2621
+ buildCompositionsToolPrompt.description(`
2622
+ # REQUIRED RESOURCES (Read before use)
2623
+ 1. [${WIDGET_SCHEMA_URI}] - Widget types, configuration schemas, and PropType definitions
2624
+ 2. [${STYLE_SCHEMA_URI}] - Common styles schema shared by all widgets
2625
+ 3. [elementor://global-classes] - Existing global classes (check FIRST to reuse)
2626
+
2627
+ # THREE-PHASE WORKFLOW (MANDATORY)
2628
+
2629
+ ## Phase 1: Create Global Classes
2630
+ 1. Analyze requirements \u2192 identify reusable patterns (typography, colors, spacing)
2631
+ 2. Check [elementor://global-classes] for existing classes
2632
+ 3. Use "create-global-class" tool for NEW reusable styles BEFORE building
2633
+
2634
+ ## Phase 2: Build Composition (THIS TOOL)
2635
+ 4. Build valid XML with minimal inline styles (layout/positioning only)
2636
+ 5. Avoid duplicating styles that should be global classes
2637
+
2638
+ ## Phase 3: Apply Classes
2639
+ 6. Use "apply-global-class" tool to apply global classes to elements
2640
+
2641
+ # CORE INSTRUCTIONS
2642
+
2643
+ **Structure:**
2644
+ - Build valid XML using allowed widget tags (e.g., \`<e-button configuration-id="btn1"></e-button>\`)
2645
+ - Containers only: "e-flexbox", "e-div-block", "e-tabs"
2646
+ - Every element MUST have unique "configuration-id" attribute
2647
+ - No attributes, classes, IDs, or text nodes in XML
2648
+
2649
+ **Configuration:**
2650
+ - Map each configuration-id to elementConfig (widget props) and stylesConfig (styles)
2651
+ - Follow exact PropType schemas from resources above
2652
+ - All PropValues need \`$$type\` property matching schema
2653
+ - Keep stylesConfig MINIMAL - layout only, NOT reusable styles
2654
+
2655
+ **Validation:**
2656
+ - Parse XML before submission
2657
+ - Match all PropValues to schema (\`$$type\` required)
2658
+ - NO LINKS in any configuration
2659
+ - Retry on errors up to 10x, reading error messages carefully
2660
+
2661
+ # DESIGN QUALITY: AVOID AI SLOP
2662
+
2663
+ **Problem:** LLMs default to generic patterns (purple gradients, #333 grays, 24px headings, uniform spacing)
2664
+ **Solution:** Make intentional, distinctive choices. When unsure, choose bold over safe.
2665
+
2666
+ ## Typography Rules
2667
+ \u274C AVOID: Inter/Roboto/Arial, small ratios (1.5x), medium weights (500-700)
2668
+ \u2705 USE: 3x+ size ratios, extreme weight contrasts (100/200 vs 800/900), tight headlines (1.1 line-height)
2669
+
2670
+ ## Color Rules
2671
+ \u274C AVOID: Purple gradients, pure grays (#333/#666/#999), even distribution
2672
+ \u2705 USE: ONE dominant color (60-70%), 1-2 accent colors (10-15%), tinted neutrals (warm/cool grays)
2673
+
2674
+ ## Spacing Rules
2675
+ \u274C AVOID: Uniform spacing (all 16px/24px), cramped layouts, centered everything
2676
+ \u2705 USE: Generous spacing (80-120px sections), dramatic variation (12px/48px/96px), asymmetric layouts
2677
+
2678
+ ## Background Rules
2679
+ \u274C AVOID: Solid white/gray, single colors
2680
+ \u2705 USE: Layered gradients (2-3 layers), subtle patterns, alternating light/dark sections
2681
+
2682
+ ## Visual Hierarchy
2683
+ 1. **Primary** (1 element): Largest, highest contrast, most space
2684
+ 2. **Secondary** (2-3 elements): 40-60% of primary size
2685
+ 3. **Tertiary** (rest): Minimal weight, muted
2686
+
2687
+ **Contrast techniques:** 3x size differences, 300+ weight differences, color hierarchy (brand \u2192 neutral \u2192 muted)
2688
+
2689
+ # DESIGN CONSTRAINTS (NEVER VIOLATE)
2690
+
2691
+ **Typography:**
2692
+ - NEVER use Inter, Roboto, Arial, Helvetica as primary display fonts
2693
+ - NEVER use font-size ratios < 2.5x between headlines and body
2694
+ - NEVER use font-weight 500-700 for headlines (go lighter or heavier)
2695
+
2696
+ **Color:**
2697
+ - PREFER not to use pure grays - use tinted neutrals (#2d2622, #faf8f6, not #333/#f5f5f5)
2698
+ - NEVER distribute colors evenly - commit to ONE dominant
2699
+ - NEVER use more than 3 core colors - except for info/alert/badges
2700
+
2701
+ **Spacing:**
2702
+ - NEVER use uniform spacing
2703
+ - NEVER use < 4rem (64px) padding for major sections
2704
+ - NEVER center everything
2705
+ - PRIORITIZE rem based values over pixel based
2706
+
2707
+ **Background:**
2708
+ - NEVER use solid #ffffff or #f5f5f5 without texture/gradients
2709
+ - ALWAYS layer 2+ gradient/color elements
2710
+
2711
+ # WIDGET NOTES
2712
+ - Check \`llm_guidance\` property in widget schemas for context
2713
+ - Avoid SVG widgets (require content upload tools) - when must, prior to execution ensure assets uploaded
2714
+ - Apply style schema to containers for layout control
2715
+
2716
+ # PARAMETERS (ALL MANDATORY)
2717
+ - **xmlStructure**: Valid XML with configuration-id attributes
2718
+ - **elementConfig**: Record of configuration-id \u2192 widget PropValues
2719
+ - **stylesConfig**: Record of configuration-id \u2192 style PropValues (layout only)
2702
2720
  `);
2703
2721
  buildCompositionsToolPrompt.example(`
2704
2722
  A Heading and a button inside a flexbox
@@ -2745,7 +2763,12 @@ A Heading and a button inside a flexbox
2745
2763
  You should use these IDs as reference for further configuration, styling or changing elements later on.`
2746
2764
  );
2747
2765
  buildCompositionsToolPrompt.instruction(
2748
- `You must use styles/variables/classes that are available in the project resources, you should prefer using them over inline styles, and you are welcome to execute relevant tools AFTER this tool execution, to apply global classes to the created elements.`
2766
+ `**CRITICAL WORKFLOW REMINDER**:
2767
+ 1. FIRST: Create reusable global classes for typography, colors, spacing patterns using "create-global-class" tool
2768
+ 2. SECOND: Use THIS tool with minimal inline styles (only layout & unique properties)
2769
+ 3. THIRD: Apply global classes to elements using "apply-global-class" tool
2770
+
2771
+ This ensures maximum reusability and consistency across your design system. ALWAYS check [elementor://global-classes] for existing classes before creating new ones.`
2749
2772
  );
2750
2773
  return buildCompositionsToolPrompt.prompt();
2751
2774
  };
@@ -2775,8 +2798,7 @@ var outputSchema = {
2775
2798
  errors: z.string().describe("Error message if the composition building failed").optional(),
2776
2799
  xmlStructure: z.string().describe(
2777
2800
  "The built XML structure as a string. Must use this XML after completion of building the composition, it contains real IDs."
2778
- ).optional(),
2779
- llmInstructions: z.string().describe("Instructions for what to do next, Important to follow these instructions!")
2801
+ ).optional()
2780
2802
  };
2781
2803
 
2782
2804
  // src/mcp/tools/build-composition/tool.ts
@@ -2788,114 +2810,54 @@ var initBuildCompositionsTool = (reg) => {
2788
2810
  schema: inputSchema,
2789
2811
  requiredResources: [
2790
2812
  { description: "Widgets schema", uri: WIDGET_SCHEMA_URI },
2791
- { description: "Global Classes", uri: "elementor://global-classes" },
2792
2813
  { description: "Styles schema", uri: STYLE_SCHEMA_URI },
2814
+ { description: "Global Classes", uri: "elementor://global-classes" },
2793
2815
  { description: "Global Variables", uri: "elementor://global-variables" },
2794
2816
  { description: "Styles best practices", uri: BEST_PRACTICES_URI }
2795
2817
  ],
2796
2818
  outputSchema,
2797
2819
  modelPreferences: {
2798
- hints: [{ name: "claude-sonnet-4-5" }],
2799
- intelligencePriority: 0.95,
2800
- speedPriority: 0.5
2820
+ hints: [{ name: "claude-sonnet-4-5" }]
2801
2821
  },
2802
2822
  handler: async (params) => {
2803
- let xml = null;
2804
2823
  const { xmlStructure, elementConfig, stylesConfig } = params;
2824
+ let generatedXML = "";
2805
2825
  const errors = [];
2806
- const softErrors = [];
2807
2826
  const rootContainers = [];
2808
- const widgetsCache = getWidgetsCache5() || {};
2809
- const documentContainer = getContainer2("document");
2827
+ const documentContainer = getContainer3("document");
2810
2828
  try {
2811
- const parser = new DOMParser();
2812
- xml = parser.parseFromString(xmlStructure, "application/xml");
2813
- const errorNode = xml.querySelector("parsererror");
2814
- if (errorNode) {
2815
- throw new Error("Failed to parse XML structure: " + errorNode.textContent);
2829
+ const compositionBuilder = CompositionBuilder.fromXMLString(xmlStructure, {
2830
+ createElement: createElement7,
2831
+ getWidgetsCache: getWidgetsCache6
2832
+ });
2833
+ compositionBuilder.setElementConfig(elementConfig);
2834
+ compositionBuilder.setStylesConfig(stylesConfig);
2835
+ const {
2836
+ configErrors,
2837
+ invalidStyles,
2838
+ rootContainers: generatedRootContainers
2839
+ } = compositionBuilder.build(documentContainer);
2840
+ generatedXML = new XMLSerializer().serializeToString(compositionBuilder.getXML());
2841
+ if (configErrors.length) {
2842
+ errors.push(...configErrors.map((e) => new Error(e)));
2843
+ throw new Error("Configuration errors occurred during composition building.");
2816
2844
  }
2817
- const children = Array.from(xml.children);
2818
- const iterate = async (node, containerElement = documentContainer, childIndex) => {
2819
- const elementTag = node.tagName;
2820
- if (!widgetsCache[elementTag]) {
2821
- errors.push(new Error(`Unknown widget type: ${elementTag}`));
2822
- }
2823
- const CONTAINER_ELEMENTS = Object.values(widgetsCache).filter((widget) => widget.meta?.is_container).map((widget) => widget.elType);
2824
- const isContainer = CONTAINER_ELEMENTS.includes(elementTag);
2825
- const parentElType = containerElement.model.get("elType");
2826
- let targetContainerId = parentElType === "e-tabs" ? containerElement.children?.[1].children?.[childIndex]?.id || containerElement.children?.[1].id : containerElement.id;
2827
- if (!targetContainerId) {
2828
- targetContainerId = containerElement.id;
2829
- }
2830
- const newElement = isContainer ? createElement6({
2831
- containerId: targetContainerId,
2832
- model: {
2833
- elType: elementTag,
2834
- id: generateElementId()
2835
- },
2836
- options: { useHistory: false }
2837
- }) : createElement6({
2838
- containerId: targetContainerId,
2839
- model: {
2840
- elType: "widget",
2841
- widgetType: elementTag,
2842
- id: generateElementId()
2845
+ rootContainers.push(...generatedRootContainers);
2846
+ Object.entries(invalidStyles).forEach(([elementId, rawCssRules]) => {
2847
+ const customCss = {
2848
+ value: rawCssRules.join(";\n")
2849
+ };
2850
+ doUpdateElementProperty({
2851
+ elementId,
2852
+ propertyName: "_styles",
2853
+ propertyValue: {
2854
+ _styles: {
2855
+ custom_css: customCss
2856
+ }
2843
2857
  },
2844
- options: { useHistory: false }
2858
+ elementType: "widget"
2845
2859
  });
2846
- if (containerElement === documentContainer) {
2847
- rootContainers.push(newElement);
2848
- }
2849
- node.setAttribute("id", newElement.id);
2850
- const configId = node.getAttribute("configuration-id") || "";
2851
- try {
2852
- const configObject = elementConfig[configId] || {};
2853
- const styleObject = stylesConfig[configId] || {};
2854
- const { errors: propsValidationErrors } = validateInput.validatePropSchema(
2855
- elementTag,
2856
- configObject
2857
- );
2858
- errors.push(...(propsValidationErrors || []).map((msg) => new Error(msg)));
2859
- const { errors: stylesValidationErrors } = validateInput.validateStyles(styleObject);
2860
- errors.push(...(stylesValidationErrors || []).map((msg) => new Error(msg)));
2861
- if (propsValidationErrors?.length || stylesValidationErrors?.length) {
2862
- return;
2863
- }
2864
- configObject._styles = styleObject || {};
2865
- for (const [propertyName, propertyValue] of Object.entries(configObject)) {
2866
- try {
2867
- doUpdateElementProperty({
2868
- elementId: newElement.id,
2869
- propertyName,
2870
- propertyValue,
2871
- elementType: elementTag
2872
- });
2873
- } catch (error) {
2874
- softErrors.push(error);
2875
- }
2876
- }
2877
- if (isContainer) {
2878
- let currentChild2 = 0;
2879
- for (const child of node.children) {
2880
- iterate(child, newElement, currentChild2);
2881
- currentChild2++;
2882
- }
2883
- } else {
2884
- node.innerHTML = "";
2885
- node.removeAttribute("configuration");
2886
- }
2887
- } finally {
2888
- }
2889
- };
2890
- let currentChild = 0;
2891
- for await (const childNode of children) {
2892
- await iterate(childNode, documentContainer, currentChild);
2893
- currentChild++;
2894
- try {
2895
- } catch (error) {
2896
- errors.push(error);
2897
- }
2898
- }
2860
+ });
2899
2861
  } catch (error) {
2900
2862
  errors.push(error);
2901
2863
  }
@@ -2935,20 +2897,19 @@ ${errorMessages.join(
2935
2897
  Now that you have these errors, fix them and try again. Errors regarding configuration objects, please check against the PropType schemas`;
2936
2898
  throw new Error(errorText);
2937
2899
  }
2938
- if (!xml) {
2939
- throw new Error("XML structure is null after parsing.");
2940
- }
2941
2900
  return {
2942
- xmlStructure: new XMLSerializer().serializeToString(xml),
2901
+ xmlStructure: generatedXML,
2943
2902
  errors: errors?.length ? errors.map((e) => typeof e === "string" ? e : e.message).join("\n\n") : void 0,
2944
- llmInstructions: (softErrors.length ? `The composition was built successfully, but there were some issues with the provided configurations:
2903
+ llm_instructions: `The composition was built successfully with element IDs embedded in the XML.
2945
2904
 
2946
- ${softErrors.map((e) => `- ${e.message}`).join("\n")}
2905
+ **CRITICAL NEXT STEPS** (Follow in order):
2906
+ 1. **Apply Global Classes**: Use "apply-global-class" tool to apply the global classes you created BEFORE building this composition
2907
+ - Check the created element IDs in the returned XML
2908
+ - Apply semantic classes (heading-primary, button-cta, etc.) to appropriate elements
2947
2909
 
2948
- Please use configure-element tool to fix these issues. Now that you have information about these issues, use the configure-element tool to fix them!` : "") + `
2949
- Next Steps:
2950
- - Use "apply-global-class" tool as there may be global styles ready to be applied to elements.
2951
- - Use "configure-element" tool to further configure elements as needed, including styles.
2910
+ 2. **Fine-tune if needed**: Use "configure-element" tool only for element-specific adjustments that don't warrant global classes
2911
+
2912
+ Remember: Global classes ensure design consistency and reusability. Don't skip applying them!
2952
2913
  `
2953
2914
  };
2954
2915
  }
@@ -3174,7 +3135,7 @@ Check the styles schema at the resource [${STYLE_SCHEMA_URI.replace(
3174
3135
  }
3175
3136
 
3176
3137
  // src/mcp/tools/get-element-config/tool.ts
3177
- import { getContainer as getContainer3, getElementStyles as getElementStyles2, getWidgetsCache as getWidgetsCache6 } from "@elementor/editor-elements";
3138
+ import { getContainer as getContainer4, getElementStyles as getElementStyles2, getWidgetsCache as getWidgetsCache7 } from "@elementor/editor-elements";
3178
3139
  import { Schema as Schema4 } from "@elementor/editor-props";
3179
3140
  import { z as z3 } from "@elementor/schema";
3180
3141
  var schema = {
@@ -3213,12 +3174,12 @@ var initGetElementConfigTool = (reg) => {
3213
3174
  speedPriority: 0.9
3214
3175
  },
3215
3176
  handler: async ({ elementId }) => {
3216
- const element = getContainer3(elementId);
3177
+ const element = getContainer4(elementId);
3217
3178
  if (!element) {
3218
3179
  throw new Error(`Element with ID ${elementId} not found.`);
3219
3180
  }
3220
3181
  const elementRawSettings = element.settings;
3221
- const propSchema = getWidgetsCache6()?.[element.model.get("widgetType") || element.model.get("elType") || ""]?.atomic_props_schema;
3182
+ const propSchema = getWidgetsCache7()?.[element.model.get("widgetType") || element.model.get("elType") || ""]?.atomic_props_schema;
3222
3183
  if (!elementRawSettings || !propSchema) {
3223
3184
  throw new Error(`No settings or prop schema found for element ID: ${elementId}`);
3224
3185
  }
@@ -3274,123 +3235,114 @@ var initCanvasMcp = (reg) => {
3274
3235
 
3275
3236
  // src/mcp/mcp-description.ts
3276
3237
  var ELEMENT_SCHEMA_URI = WIDGET_SCHEMA_URI.replace("{widgetType}", "element-schema");
3277
- var mcpDescription = `Canvas MCP
3278
- This MCP enables everything related to creation, configuration, and styling of elements on the Elementor canvas.
3238
+ var mcpDescription = `Elementor Canvas MCP
3239
+ This MCP enables creation, configuration, and styling of elements on the Elementor canvas using the build_composition tool.
3240
+
3241
+ # Core Concepts
3279
3242
 
3280
- # Design Systems in Elementor
3281
- - Elementor presents global classes. Each global class is a a set of styles that can be applied to multiple elements. This allows for consistent styling across the design.
3282
- - Elementor also presents global variables, which can be colors, sizes or fonts. These variables can be used in any element's styles, or global classes, allowing for easy updates and consistency across the design.
3283
- - All data is stored in a PropValue structure, which is a wrapper for elementor values. The PropValues are derived from an internal "PropType" schema, which defines the structure and types of the values.
3243
+ ## PropValues Structure
3244
+ All data in Elementor uses PropValues - a typed wrapper for values:
3245
+ \`\`\`json
3246
+ {
3247
+ "$$type": "the-prop-type-schema-kind",
3248
+ "value": "the-actual-value-as-defined-for-the-propType"
3249
+ }
3250
+ \`\`\`
3251
+ The \`$$type\` defines how Elementor interprets the value. Providing the correct \`$$type\` is critical - incorrect types will be rejected.
3252
+
3253
+ ## Design System Resources
3254
+ - **Global Variables**: Reusable colors, sizes, and fonts (\`elementor://global-variables\`)
3255
+ - **Global Classes**: Reusable style sets that can be applied to elements (\`elementor://global-classes\`)
3256
+ - **Widget Schemas**: Configuration options for each widget type (\`${WIDGET_SCHEMA_URI}\`)
3257
+ - **Style Schema**: Common styles shared across all widgets and containers (\`${STYLE_SCHEMA_URI}\`)
3258
+
3259
+ # Building Compositions with build_composition
3260
+
3261
+ The \`build_composition\` tool is the primary way to create elements. It accepts structure (XML), configuration, and styling in a single operation.
3262
+
3263
+ ## Complete Workflow
3264
+
3265
+ ### 1. Parse User Requirements
3266
+ Understand what needs to be built: structure, content, and styling.
3267
+
3268
+ ### 2. Check Global Resources FIRST
3269
+ Always check existing resources before building:
3270
+ - List \`elementor://global-variables\` for available variables (colors, sizes, fonts)
3271
+ - List \`elementor://global-classes\` for available style sets
3272
+ - **Always prefer using existing global resources over creating inline styles**
3273
+
3274
+ ### 3. Retrieve Widget Schemas
3275
+ For each widget you'll use:
3276
+ - List \`${WIDGET_SCHEMA_URI}\` to see available widgets
3277
+ - Retrieve configuration schema from \`${ELEMENT_SCHEMA_URI}\` for each widget
3278
+ - Check the \`llm_guidance\` property to understand if a widget is a container (can have children)
3279
+
3280
+ ### 4. Build XML Structure
3281
+ Create valid XML with configuration-ids:
3282
+ - Each element must have a unique \`configuration-id\` attribute
3283
+ - No text nodes, classes, or IDs in XML - structure only
3284
+ - Example:
3285
+ \`\`\`xml
3286
+ <e-container configuration-id="container-1">
3287
+ <e-heading configuration-id="heading-1" />
3288
+ <e-text configuration-id="text-1" />
3289
+ </e-container>
3290
+ \`\`\`
3284
3291
 
3285
- # PropValues structure and usage
3292
+ ### 5. Create elementConfig
3293
+ Map each configuration-id to its widget properties using PropValues:
3294
+ - Use correct \`$$type\` matching the widget's schema
3295
+ - Use global variables in PropValues where applicable
3296
+ - Example:
3286
3297
  \`\`\`json
3287
3298
  {
3288
- $$type: 'the-prop-type-schema-kind',
3289
- value: 'the-actual-value-as-defined-for-the-propType'
3299
+ "heading-1": {
3300
+ "text": { "$$type": "string", "value": "Welcome" },
3301
+ "tag": { "$$type": "string", "value": "h1" }
3302
+ }
3290
3303
  }
3291
3304
  \`\`\`
3292
- The "value" property can be an object, string, number, boolean, array, etc. The $$type defines the kind of value, and the value is the actual value.
3293
- It is critical to provide the correct $$type for each value, as it defines how Elementor will interpret the value or reject it.
3294
-
3295
- All widgets properties and configuration is built from sets of PropValues, which can be retreived from the resource [${WIDGET_SCHEMA_URI}].
3296
- All styles are SHARED ACCROSS widgets, containers and components, and are defined in a common styles schema, retreivable from the resource [${STYLE_SCHEMA_URI}].
3297
- The style schema also defines the global classes.
3298
-
3299
- To understand the configuration options for an element, refer to the PropType schema for that specific element. For example: "e-heading" configuration schema is available at the resource [${WIDGET_SCHEMA_URI}/e-heading]
3300
-
3301
- # Modifying elements and styles
3302
- When configuring an element, elementor does a MERGE PROPERTIES operation, which means that only the properties you provide will be updated, and the rest will remain as is.
3303
- For deleting a property, the value must be set to null, instead of a PropValue. When adding a configuration, no need to provide the full configuration, only the properties you want to add or update.
3304
- The same rule applies to styles as well and modifications to global classes.
3305
-
3306
- # Building full compositions
3307
- The "build-composition" tool allows creating multiple elements in a single operation.
3308
- The tool accepts both the structure, the styling and the configuration of each element to be created.
3309
-
3310
- - First step: Retreive the available widgets by listing the [${WIDGET_SCHEMA_URI}] dynamic resource.
3311
- - Second step: decide which elements to create, and their configuration and styles.
3312
- Retrieve the used elements configuration schema from the resource [${ELEMENT_SCHEMA_URI}]
3313
- - Third step: define the styles for each element, using the common styles schema from the resource [${STYLE_SCHEMA_URI}]. List the resource to see all available style properties.
3314
-
3315
- ## Workflow for build-compositions tool
3316
- 1. **Parse user requirements** - Undestand what needs to be built (structure, content, styling).
3317
- 2. ** Check global resources FIRST** - Always check before building:
3318
- - List \`elementor://global-classes\` to see if the needed global classes already exist.
3319
- - List \`elementor://global-variables\` to see if the needed global variables already exist.
3320
- - **Preference**: Use existing global classes and variables over creating new inline styles.
3321
- 3. **Retreive widget schemas** - For each widget you will use:
3322
- - List [${WIDGET_SCHEMA_URI}] to see available widgets.
3323
- - Retrieve configuration schema from [${ELEMENT_SCHEMA_URI}] for each widget to understand required properties.
3324
- - Understand if a widget is a container (can have children) by checking the "llm_guidance" property in the widget's schema.
3325
- 4. **Build XML structure** - Create valid XML width configuration-ids:
3326
- - Every element has unique configuration-id attribute
3327
- - No text nodes, classes, IDs in XML.
3328
-
3329
- 5. **Create elementConfig** - For each configuration-id:
3330
- - Use PropValues with corrent \`$$type\` matching the schema.
3331
- - **Use global variables** in PropValues where applicable
3332
-
3333
- 6. **Create stylesConfig** - For each configuration-id:
3334
- - Use style schema PropValues from [${STYLE_SCHEMA_URI}]
3335
- - **Use global variables** for colors, sizes, fonts where applicable
3336
- - **Important**: Global classes are applied AFTER building the composition. Once built, apply classes using the "apply-global-class" tool - after completion of building the composition.
3337
-
3338
- 7. **Validate** - Ensure:
3339
- - XML structure is valid
3340
- - All PropValues have corrent \`$$type\`
3341
- - After building a composition, you can retreive each element configuration using the "get-element-configuration-values" tool to verify correctness, using the IDs returned from the build-composition tool.
3342
-
3343
- ## Key relationships:
3344
- - **XML structure**: Defines the hierarchy of elements/widgets
3345
- - **elementConfig**: Maps configuration-id to widget PropValues
3346
- - **stylesConfig**: Maps configuration-id to style PropValues
3347
-
3348
- ## Using global variables example:
3349
- Existing global variables can be used during composition
3305
+
3306
+ ### 6. Create stylesConfig
3307
+ Map each configuration-id to style PropValues from \`${STYLE_SCHEMA_URI}\`:
3308
+ - Use global variables for colors, sizes, and fonts
3309
+ - Example using global variable:
3350
3310
  \`\`\`json
3351
- { "color": { "$$type": "global-color-variable", "value": "global-variable-id" } }
3311
+ {
3312
+ "heading-1": {
3313
+ "color": { "$$type": "global-color-variable", "value": "primary-color-id" },
3314
+ "font-size": { "$$type": "size", "value": "2rem" }
3315
+ }
3316
+ }
3352
3317
  \`\`\`
3353
3318
 
3354
- # Configuring Elements / Adding Style to Elements
3355
- An element configuration can be retrieved using the "get-element-configuration-values" tool.
3356
- Updating an element requires only the UPDATED properties (including in the styles), as Elementor does a MERGE/PATCH operation.
3319
+ ### 7. Execute build_composition
3320
+ Call the tool with your XML structure, elementConfig, and stylesConfig. The response will contain the created element IDs.
3321
+ At the response you will also find llm_instructions for you to do afterwards, read and follow them!
3357
3322
 
3358
- <note>
3359
- for PropValue with array as value:
3360
- All array types that can receive union types, are typed as mixed array.
3361
- </note>
3323
+ ## Key Points
3362
3324
 
3363
- # Styling best practices
3364
- Prefer using "em" and "rem" values for text-related sizes, padding and spacing. Use percentages for dynamic sizing relative to parent containers.
3365
- This flexboxes are by default "flex" with "stretch" alignment. To ensure proper layout, define the "justify-content" and "align-items" as in the schema.
3325
+ - **PropValue Types**: Arrays that accept union types are typed as mixed arrays
3326
+ - **Visual Sizing**: Widget sizes MUST be defined in stylesConfig. Widget properties like image "size" control resolution, not visual appearance
3327
+ - **Global Variables**: Reference by ID in PropValues (e.g., \`{ "$$type": "global-color-variable", "value": "variable-id" }\`)
3328
+ - **Naming Conventions**: Use meaningful, purpose-based names (e.g., "primary-button", "heading-large"), not value-based names (e.g., "blue-style", "20px-padding")
3366
3329
 
3367
- # Examples:
3368
-
3369
- ## e-image PropValue structure:
3370
- {$$type:'image',value:{src:{$$type:'image-src',value:{url:{$$type:'url',value:'https://example.com/image.jpg'}}},size:{$$type:'string',value:'full'}}}
3371
-
3372
- Widgets' sizes MUST be defined using the style schema. Images, for example, have a "size" property, but it DOES NOT AFFECT THE VISUAL size, but rather the image size/resolution to load.
3373
-
3374
- # Working with Global Classes and Variables
3375
- - To get the list of available global classes, use the resource at uri elementor://global-classes
3376
- - To get the list of available global variables, use the resource at uri elementor://global-variables
3377
- - Before creating a global variable or class, refer to the list and see if it already exists.
3378
- - Naming conventions:
3379
- - Global classes and global variables should have meaningful names that reflect their purpose and usage.
3380
- - Avoid generic names like "style1" or "classA"; instead, use descriptive names like "primary-button" or "heading-level-1".
3381
- - Avoid names that reflect colors or values, use only purpose-based names.
3382
-
3383
- # Advanced operations
3384
- You are encouraged to run multiple times multiple tools to achieve the desired result.
3385
-
3386
- An Example scenario of creating fully styled composition:
3387
- 1. Get the list of availble widgets using dynamic resource [${WIDGET_SCHEMA_URI}]
3388
- 2. For each element to create, retreive its configuration schema from [${WIDGET_SCHEMA_URI}/element-name]
3389
- 3. Get the list of available global classes using the always up-to-date resource
3390
- 4. Get the list of available global variables using the dynamic resource
3391
- 5. Build a composition using the "build-composition" tool, providing the structure, configuration and styles for each element. You may want to style the elements later.
3392
- 6. Check you work: as you have the created IDs from the build-composition response, you can retreive each element configuration using the "get-element-configuration-values" tool.
3393
- 7. If needed, update styles using the "configure-element" tool, providing only the styles or widget's properties to update.
3330
+ ## Example: e-image PropValue Structure
3331
+ \`\`\`json
3332
+ {
3333
+ "$$type": "image",
3334
+ "value": {
3335
+ "src": {
3336
+ "$$type": "image-src",
3337
+ "value": {
3338
+ "url": { "$$type": "url", "value": "https://example.com/image.jpg" }
3339
+ }
3340
+ },
3341
+ "size": { "$$type": "string", "value": "full" }
3342
+ }
3343
+ }
3344
+ \`\`\`
3345
+ Note: The "size" property controls image resolution/loading, not visual size. Set visual dimensions in stylesConfig.
3394
3346
  `;
3395
3347
 
3396
3348
  // src/prevent-link-in-link-commands.ts
@@ -3499,7 +3451,7 @@ import { undoable as undoable2 } from "@elementor/editor-v1-adapters";
3499
3451
  import { __ as __4 } from "@wordpress/i18n";
3500
3452
 
3501
3453
  // src/style-commands/utils.ts
3502
- import { getElementLabel as getElementLabel2, getWidgetsCache as getWidgetsCache7 } from "@elementor/editor-elements";
3454
+ import { getElementLabel as getElementLabel2, getWidgetsCache as getWidgetsCache8 } from "@elementor/editor-elements";
3503
3455
  import { CLASSES_PROP_KEY } from "@elementor/editor-props";
3504
3456
  import { __ as __3 } from "@wordpress/i18n";
3505
3457
  function hasAtomicWidgets(args) {
@@ -3524,7 +3476,7 @@ function getClassesProp(container) {
3524
3476
  }
3525
3477
  function getContainerSchema(container) {
3526
3478
  const type = container?.model.get("widgetType") || container?.model.get("elType");
3527
- const widgetsCache = getWidgetsCache7();
3479
+ const widgetsCache = getWidgetsCache8();
3528
3480
  const elementType = widgetsCache?.[type];
3529
3481
  return elementType?.atomic_props_schema ?? null;
3530
3482
  }