@elementor/editor-canvas 4.2.0-935 → 4.2.0-937

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
@@ -74,18 +74,6 @@ var import_editor_elements2 = require("@elementor/editor-elements");
74
74
  var import_editor_mcp = require("@elementor/editor-mcp");
75
75
  var import_editor_props = require("@elementor/editor-props");
76
76
 
77
- // src/composition-builder/utils/required-default-child-tags.ts
78
- function getRequiredDefaultChildTemplates(elementConfig) {
79
- const defaultChildren = elementConfig?.default_children;
80
- if (!Array.isArray(defaultChildren)) {
81
- return [];
82
- }
83
- return defaultChildren.filter((child) => child?.meta?.required ?? false);
84
- }
85
- function getRequiredDefaultChildTypes(elementConfig) {
86
- return getRequiredDefaultChildTemplates(elementConfig).map((child) => child.widgetType ?? child.elType ?? "").filter((type) => Boolean(type));
87
- }
88
-
89
77
  // src/mcp/utils/element-data-util.ts
90
78
  var import_editor_elements = require("@elementor/editor-elements");
91
79
  function hasV3Controls(controls) {
@@ -122,6 +110,84 @@ function getAvailableWidgets() {
122
110
  });
123
111
  }
124
112
 
113
+ // src/composition-builder/utils/required-default-child-tags.ts
114
+ function getRequiredDefaultChildTemplates(elementConfig) {
115
+ const defaultChildren = elementConfig?.default_children;
116
+ if (!Array.isArray(defaultChildren)) {
117
+ return [];
118
+ }
119
+ return defaultChildren.filter((child) => child?.meta?.required ?? false);
120
+ }
121
+ function getRequiredDefaultChildTypes(elementConfig) {
122
+ return getRequiredDefaultChildTemplates(elementConfig).map((child) => child.widgetType ?? child.elType ?? "").filter((type) => Boolean(type));
123
+ }
124
+
125
+ // src/mcp/resources/build-llm-guidance.ts
126
+ var DEFAULT_STYLES_INSTRUCTION = "These are the default styles applied to the widget. Override only when necessary.";
127
+ var DEFAULT_SETTINGS_INSTRUCTION = "These are the default settings applied to the widget. Omit them from elementConfig unless the user explicitly asks to change them.";
128
+ var BASE_SETTING_PROP_HINT = "Has a widget default \u2014 omit unless user explicitly requests a change. See llm_guidance.default_settings.";
129
+ function mergeInstructions(existing, additional) {
130
+ if (typeof existing === "string" && existing.length > 0) {
131
+ return `${existing} ${additional}`;
132
+ }
133
+ return additional;
134
+ }
135
+ function enrichPropertiesWithBaseSettingsHints(properties, baseSettingsKeys) {
136
+ if (!baseSettingsKeys.length) {
137
+ return properties;
138
+ }
139
+ const enriched = { ...properties };
140
+ for (const key of baseSettingsKeys) {
141
+ const propSchema = enriched[key];
142
+ if (!propSchema) {
143
+ continue;
144
+ }
145
+ enriched[key] = {
146
+ ...propSchema,
147
+ description: propSchema.description ? `${propSchema.description} ${BASE_SETTING_PROP_HINT}` : BASE_SETTING_PROP_HINT
148
+ };
149
+ }
150
+ return enriched;
151
+ }
152
+ function buildLlmGuidance(widgetData, widgetType, allWidgets) {
153
+ const defaultStyles = {};
154
+ const baseStyleSchema = widgetData?.base_styles;
155
+ if (baseStyleSchema) {
156
+ Object.values(baseStyleSchema).forEach((stylePropType) => {
157
+ stylePropType.variants.forEach((variant) => {
158
+ Object.assign(defaultStyles, variant.props);
159
+ });
160
+ });
161
+ }
162
+ const baseSettings = widgetData?.base_settings ?? {};
163
+ const hasDefaultStyles = Object.keys(defaultStyles).length > 0;
164
+ const hasDefaultSettings = Object.keys(baseSettings).length > 0;
165
+ const llmGuidance = {
166
+ can_have_children: !!widgetData?.meta?.is_container
167
+ };
168
+ if (hasDefaultStyles) {
169
+ llmGuidance.instructions = DEFAULT_STYLES_INSTRUCTION;
170
+ llmGuidance.default_styles = defaultStyles;
171
+ }
172
+ if (hasDefaultSettings) {
173
+ llmGuidance.instructions = mergeInstructions(llmGuidance.instructions, DEFAULT_SETTINGS_INSTRUCTION);
174
+ llmGuidance.default_settings = baseSettings;
175
+ }
176
+ const allowedChildTypes = widgetData.allowed_child_types;
177
+ const allowedParents = Object.entries(allWidgets).filter(([, parentConfig]) => parentConfig.allowed_child_types?.includes(widgetType)).map(([parentType]) => parentType);
178
+ if (allowedChildTypes?.length || allowedParents.length) {
179
+ llmGuidance.nesting = {
180
+ ...allowedChildTypes?.length ? { allowed_child_types: allowedChildTypes } : {},
181
+ ...allowedParents.length ? { allowed_parents: allowedParents } : {}
182
+ };
183
+ }
184
+ const requiredDirectChildTags = getRequiredDefaultChildTypes(widgetData);
185
+ if (requiredDirectChildTags.length) {
186
+ llmGuidance.required_direct_children = requiredDirectChildTags;
187
+ }
188
+ return llmGuidance;
189
+ }
190
+
125
191
  // src/mcp/resources/widgets-schema-resource.ts
126
192
  var V3_LAYOUT_CONTROL_TYPES = /* @__PURE__ */ new Set(["section", "tab", "tabs"]);
127
193
  function extractV3ControlsMetadata(controls) {
@@ -238,40 +304,16 @@ Variables from the user context ARE NOT SUPPORTED AND WILL RESOLVE IN ERROR.
238
304
  ]
239
305
  };
240
306
  }
241
- const asJson = Object.fromEntries(
242
- Object.entries(propSchema).filter(([key, propType]) => import_editor_props.Schema.isPropKeyConfigurable(key, propType)).map(([key, propType]) => [key, import_editor_props.Schema.propTypeToJsonSchema(propType)])
307
+ const baseSettingsKeys = Object.keys(widgetData?.base_settings ?? {});
308
+ const asJson = enrichPropertiesWithBaseSettingsHints(
309
+ Object.fromEntries(
310
+ Object.entries(propSchema).filter(([key, propType]) => import_editor_props.Schema.isPropKeyConfigurable(key, propType)).map(([key, propType]) => [key, import_editor_props.Schema.propTypeToJsonSchema(propType)])
311
+ ),
312
+ baseSettingsKeys
243
313
  );
244
314
  const description = typeof widgetData?.meta?.description === "string" ? widgetData.meta.description : void 0;
245
- const defaultStyles = {};
246
- const baseStyleSchema = widgetData?.base_styles;
247
- if (baseStyleSchema) {
248
- Object.values(baseStyleSchema).forEach((stylePropType) => {
249
- stylePropType.variants.forEach((variant) => {
250
- Object.assign(defaultStyles, variant.props);
251
- });
252
- });
253
- }
254
- const hasDefaultStyles = Object.keys(defaultStyles).length > 0;
255
- const llmGuidance = {
256
- can_have_children: !!widgetData?.meta?.is_container
257
- };
258
- if (hasDefaultStyles) {
259
- llmGuidance.instructions = "These are the default styles applied to the widget. Override only when necessary.";
260
- llmGuidance.default_styles = defaultStyles;
261
- }
262
- const allowedChildTypes = widgetData.allowed_child_types;
263
315
  const allWidgets = (0, import_editor_elements2.getWidgetsCache)() || {};
264
- const allowedParents = Object.entries(allWidgets).filter(([, parentConfig]) => parentConfig.allowed_child_types?.includes(widgetType)).map(([parentType]) => parentType);
265
- if (allowedChildTypes?.length || allowedParents.length) {
266
- llmGuidance.nesting = {
267
- ...allowedChildTypes?.length ? { allowed_child_types: allowedChildTypes } : {},
268
- ...allowedParents.length ? { allowed_parents: allowedParents } : {}
269
- };
270
- }
271
- const requiredDirectChildTags = getRequiredDefaultChildTypes(widgetData);
272
- if (requiredDirectChildTags.length) {
273
- llmGuidance.required_direct_children = requiredDirectChildTags;
274
- }
316
+ const llmGuidance = buildLlmGuidance(widgetData, widgetType, allWidgets);
275
317
  return {
276
318
  contents: [
277
319
  {
@@ -5085,6 +5127,7 @@ Some elements have internal tree structures (nesting). When using these elements
5085
5127
  - style is raw CSS (property \u2192 value strings); the server converts it to native styles and stores any unconvertible declarations as the element custom CSS
5086
5128
  - NO LINKS in configuration
5087
5129
  - Retry on errors up to 10x
5130
+ - Check \`llm_guidance.default_settings\` in widget schemas \u2014 omit only keys listed there from elementConfig unless the user explicitly asks to change them
5088
5131
 
5089
5132
  # DYNAMIC TAGS
5090
5133
  - A value can be made dynamic wherever its schema exposes a \`"$$type": "dynamic"\` variant. This may be the property root OR a NESTED field (e.g. an image's \`src\`, not the whole \`image\`).
@@ -5163,7 +5206,7 @@ BAD: \`<e-flexbox style="height:100vh"><e-div-block style="height:100vh">overflo
5163
5206
  # HARD CONSTRAINTS
5164
5207
  - Variables ONLY from [elementor://global-variables] (others throw errors)
5165
5208
  - Avoid SVG widgets unless assets are pre-uploaded
5166
- - Check \`llm_guidance\` in widget schemas
5209
+ - Check \`llm_guidance\` in widget schemas (\`default_styles\`, nesting, required children)
5167
5210
 
5168
5211
  # PARAMETERS
5169
5212
  - **xmlStructure**: Valid XML with configuration-id attributes
@@ -5565,6 +5608,8 @@ For all non-primitive entries in \`propertiesToChange\`, provide the schema \`ke
5565
5608
 
5566
5609
  Use the EXACT PropType schema given, and ALWAYS include the \`key\` from the schema for every property you are changing in \`propertiesToChange\`.
5567
5610
 
5611
+ Check \`llm_guidance.default_settings\` in the widget schema \u2014 include a key in \`propertiesToChange\` only when the user explicitly asks to change it.
5612
+
5568
5613
  # Dynamic tags
5569
5614
  A value can be made dynamic wherever its schema exposes a variant with "$$type": "dynamic". This may be the property root OR a NESTED field: for example an image is made dynamic on its "src" (the root stays "image"), NOT on the whole "image" value.
5570
5615
  Put the dynamic object EXACTLY at the node whose schema offers the "dynamic" variant, in place of the static variant. The variant's "name" enumerates the tags allowed at that node.
@@ -5922,7 +5967,7 @@ Always check existing resources before building:
5922
5967
  For each widget you'll use:
5923
5968
  - List \`${WIDGET_SCHEMA_URI}\` to see available widgets
5924
5969
  - Retrieve configuration schema from \`${ELEMENT_SCHEMA_URI}\` for each widget
5925
- - Check the \`llm_guidance\` property to understand if a widget is a container (can have children)
5970
+ - Check the \`llm_guidance\` property for container nesting, \`default_styles\`, and \`default_settings\` (omit default_settings from elementConfig unless the user asks to change them)
5926
5971
 
5927
5972
  ### 4. Build XML Structure
5928
5973
  Create valid XML with configuration-ids:
package/dist/index.mjs CHANGED
@@ -8,18 +8,6 @@ import {
8
8
  Schema
9
9
  } from "@elementor/editor-props";
10
10
 
11
- // src/composition-builder/utils/required-default-child-tags.ts
12
- function getRequiredDefaultChildTemplates(elementConfig) {
13
- const defaultChildren = elementConfig?.default_children;
14
- if (!Array.isArray(defaultChildren)) {
15
- return [];
16
- }
17
- return defaultChildren.filter((child) => child?.meta?.required ?? false);
18
- }
19
- function getRequiredDefaultChildTypes(elementConfig) {
20
- return getRequiredDefaultChildTemplates(elementConfig).map((child) => child.widgetType ?? child.elType ?? "").filter((type) => Boolean(type));
21
- }
22
-
23
11
  // src/mcp/utils/element-data-util.ts
24
12
  import { getWidgetsCache } from "@elementor/editor-elements";
25
13
  function hasV3Controls(controls) {
@@ -56,6 +44,84 @@ function getAvailableWidgets() {
56
44
  });
57
45
  }
58
46
 
47
+ // src/composition-builder/utils/required-default-child-tags.ts
48
+ function getRequiredDefaultChildTemplates(elementConfig) {
49
+ const defaultChildren = elementConfig?.default_children;
50
+ if (!Array.isArray(defaultChildren)) {
51
+ return [];
52
+ }
53
+ return defaultChildren.filter((child) => child?.meta?.required ?? false);
54
+ }
55
+ function getRequiredDefaultChildTypes(elementConfig) {
56
+ return getRequiredDefaultChildTemplates(elementConfig).map((child) => child.widgetType ?? child.elType ?? "").filter((type) => Boolean(type));
57
+ }
58
+
59
+ // src/mcp/resources/build-llm-guidance.ts
60
+ var DEFAULT_STYLES_INSTRUCTION = "These are the default styles applied to the widget. Override only when necessary.";
61
+ var DEFAULT_SETTINGS_INSTRUCTION = "These are the default settings applied to the widget. Omit them from elementConfig unless the user explicitly asks to change them.";
62
+ var BASE_SETTING_PROP_HINT = "Has a widget default \u2014 omit unless user explicitly requests a change. See llm_guidance.default_settings.";
63
+ function mergeInstructions(existing, additional) {
64
+ if (typeof existing === "string" && existing.length > 0) {
65
+ return `${existing} ${additional}`;
66
+ }
67
+ return additional;
68
+ }
69
+ function enrichPropertiesWithBaseSettingsHints(properties, baseSettingsKeys) {
70
+ if (!baseSettingsKeys.length) {
71
+ return properties;
72
+ }
73
+ const enriched = { ...properties };
74
+ for (const key of baseSettingsKeys) {
75
+ const propSchema = enriched[key];
76
+ if (!propSchema) {
77
+ continue;
78
+ }
79
+ enriched[key] = {
80
+ ...propSchema,
81
+ description: propSchema.description ? `${propSchema.description} ${BASE_SETTING_PROP_HINT}` : BASE_SETTING_PROP_HINT
82
+ };
83
+ }
84
+ return enriched;
85
+ }
86
+ function buildLlmGuidance(widgetData, widgetType, allWidgets) {
87
+ const defaultStyles = {};
88
+ const baseStyleSchema = widgetData?.base_styles;
89
+ if (baseStyleSchema) {
90
+ Object.values(baseStyleSchema).forEach((stylePropType) => {
91
+ stylePropType.variants.forEach((variant) => {
92
+ Object.assign(defaultStyles, variant.props);
93
+ });
94
+ });
95
+ }
96
+ const baseSettings = widgetData?.base_settings ?? {};
97
+ const hasDefaultStyles = Object.keys(defaultStyles).length > 0;
98
+ const hasDefaultSettings = Object.keys(baseSettings).length > 0;
99
+ const llmGuidance = {
100
+ can_have_children: !!widgetData?.meta?.is_container
101
+ };
102
+ if (hasDefaultStyles) {
103
+ llmGuidance.instructions = DEFAULT_STYLES_INSTRUCTION;
104
+ llmGuidance.default_styles = defaultStyles;
105
+ }
106
+ if (hasDefaultSettings) {
107
+ llmGuidance.instructions = mergeInstructions(llmGuidance.instructions, DEFAULT_SETTINGS_INSTRUCTION);
108
+ llmGuidance.default_settings = baseSettings;
109
+ }
110
+ const allowedChildTypes = widgetData.allowed_child_types;
111
+ const allowedParents = Object.entries(allWidgets).filter(([, parentConfig]) => parentConfig.allowed_child_types?.includes(widgetType)).map(([parentType]) => parentType);
112
+ if (allowedChildTypes?.length || allowedParents.length) {
113
+ llmGuidance.nesting = {
114
+ ...allowedChildTypes?.length ? { allowed_child_types: allowedChildTypes } : {},
115
+ ...allowedParents.length ? { allowed_parents: allowedParents } : {}
116
+ };
117
+ }
118
+ const requiredDirectChildTags = getRequiredDefaultChildTypes(widgetData);
119
+ if (requiredDirectChildTags.length) {
120
+ llmGuidance.required_direct_children = requiredDirectChildTags;
121
+ }
122
+ return llmGuidance;
123
+ }
124
+
59
125
  // src/mcp/resources/widgets-schema-resource.ts
60
126
  var V3_LAYOUT_CONTROL_TYPES = /* @__PURE__ */ new Set(["section", "tab", "tabs"]);
61
127
  function extractV3ControlsMetadata(controls) {
@@ -172,40 +238,16 @@ Variables from the user context ARE NOT SUPPORTED AND WILL RESOLVE IN ERROR.
172
238
  ]
173
239
  };
174
240
  }
175
- const asJson = Object.fromEntries(
176
- Object.entries(propSchema).filter(([key, propType]) => Schema.isPropKeyConfigurable(key, propType)).map(([key, propType]) => [key, Schema.propTypeToJsonSchema(propType)])
241
+ const baseSettingsKeys = Object.keys(widgetData?.base_settings ?? {});
242
+ const asJson = enrichPropertiesWithBaseSettingsHints(
243
+ Object.fromEntries(
244
+ Object.entries(propSchema).filter(([key, propType]) => Schema.isPropKeyConfigurable(key, propType)).map(([key, propType]) => [key, Schema.propTypeToJsonSchema(propType)])
245
+ ),
246
+ baseSettingsKeys
177
247
  );
178
248
  const description = typeof widgetData?.meta?.description === "string" ? widgetData.meta.description : void 0;
179
- const defaultStyles = {};
180
- const baseStyleSchema = widgetData?.base_styles;
181
- if (baseStyleSchema) {
182
- Object.values(baseStyleSchema).forEach((stylePropType) => {
183
- stylePropType.variants.forEach((variant) => {
184
- Object.assign(defaultStyles, variant.props);
185
- });
186
- });
187
- }
188
- const hasDefaultStyles = Object.keys(defaultStyles).length > 0;
189
- const llmGuidance = {
190
- can_have_children: !!widgetData?.meta?.is_container
191
- };
192
- if (hasDefaultStyles) {
193
- llmGuidance.instructions = "These are the default styles applied to the widget. Override only when necessary.";
194
- llmGuidance.default_styles = defaultStyles;
195
- }
196
- const allowedChildTypes = widgetData.allowed_child_types;
197
249
  const allWidgets = getWidgetsCache2() || {};
198
- const allowedParents = Object.entries(allWidgets).filter(([, parentConfig]) => parentConfig.allowed_child_types?.includes(widgetType)).map(([parentType]) => parentType);
199
- if (allowedChildTypes?.length || allowedParents.length) {
200
- llmGuidance.nesting = {
201
- ...allowedChildTypes?.length ? { allowed_child_types: allowedChildTypes } : {},
202
- ...allowedParents.length ? { allowed_parents: allowedParents } : {}
203
- };
204
- }
205
- const requiredDirectChildTags = getRequiredDefaultChildTypes(widgetData);
206
- if (requiredDirectChildTags.length) {
207
- llmGuidance.required_direct_children = requiredDirectChildTags;
208
- }
250
+ const llmGuidance = buildLlmGuidance(widgetData, widgetType, allWidgets);
209
251
  return {
210
252
  contents: [
211
253
  {
@@ -5071,6 +5113,7 @@ Some elements have internal tree structures (nesting). When using these elements
5071
5113
  - style is raw CSS (property \u2192 value strings); the server converts it to native styles and stores any unconvertible declarations as the element custom CSS
5072
5114
  - NO LINKS in configuration
5073
5115
  - Retry on errors up to 10x
5116
+ - Check \`llm_guidance.default_settings\` in widget schemas \u2014 omit only keys listed there from elementConfig unless the user explicitly asks to change them
5074
5117
 
5075
5118
  # DYNAMIC TAGS
5076
5119
  - A value can be made dynamic wherever its schema exposes a \`"$$type": "dynamic"\` variant. This may be the property root OR a NESTED field (e.g. an image's \`src\`, not the whole \`image\`).
@@ -5149,7 +5192,7 @@ BAD: \`<e-flexbox style="height:100vh"><e-div-block style="height:100vh">overflo
5149
5192
  # HARD CONSTRAINTS
5150
5193
  - Variables ONLY from [elementor://global-variables] (others throw errors)
5151
5194
  - Avoid SVG widgets unless assets are pre-uploaded
5152
- - Check \`llm_guidance\` in widget schemas
5195
+ - Check \`llm_guidance\` in widget schemas (\`default_styles\`, nesting, required children)
5153
5196
 
5154
5197
  # PARAMETERS
5155
5198
  - **xmlStructure**: Valid XML with configuration-id attributes
@@ -5551,6 +5594,8 @@ For all non-primitive entries in \`propertiesToChange\`, provide the schema \`ke
5551
5594
 
5552
5595
  Use the EXACT PropType schema given, and ALWAYS include the \`key\` from the schema for every property you are changing in \`propertiesToChange\`.
5553
5596
 
5597
+ Check \`llm_guidance.default_settings\` in the widget schema \u2014 include a key in \`propertiesToChange\` only when the user explicitly asks to change it.
5598
+
5554
5599
  # Dynamic tags
5555
5600
  A value can be made dynamic wherever its schema exposes a variant with "$$type": "dynamic". This may be the property root OR a NESTED field: for example an image is made dynamic on its "src" (the root stays "image"), NOT on the whole "image" value.
5556
5601
  Put the dynamic object EXACTLY at the node whose schema offers the "dynamic" variant, in place of the static variant. The variant's "name" enumerates the tags allowed at that node.
@@ -5908,7 +5953,7 @@ Always check existing resources before building:
5908
5953
  For each widget you'll use:
5909
5954
  - List \`${WIDGET_SCHEMA_URI}\` to see available widgets
5910
5955
  - Retrieve configuration schema from \`${ELEMENT_SCHEMA_URI}\` for each widget
5911
- - Check the \`llm_guidance\` property to understand if a widget is a container (can have children)
5956
+ - Check the \`llm_guidance\` property for container nesting, \`default_styles\`, and \`default_settings\` (omit default_settings from elementConfig unless the user asks to change them)
5912
5957
 
5913
5958
  ### 4. Build XML Structure
5914
5959
  Create valid XML with configuration-ids:
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@elementor/editor-canvas",
3
3
  "description": "Elementor Editor Canvas",
4
- "version": "4.2.0-935",
4
+ "version": "4.2.0-937",
5
5
  "private": false,
6
6
  "author": "Elementor Team",
7
7
  "homepage": "https://elementor.com/",
@@ -37,26 +37,26 @@
37
37
  "react-dom": "^18.3.1"
38
38
  },
39
39
  "dependencies": {
40
- "@elementor/editor": "4.2.0-935",
40
+ "@elementor/editor": "4.2.0-937",
41
41
  "dompurify": "^3.2.6",
42
- "@elementor/editor-controls": "4.2.0-935",
43
- "@elementor/editor-documents": "4.2.0-935",
44
- "@elementor/editor-elements": "4.2.0-935",
45
- "@elementor/editor-interactions": "4.2.0-935",
46
- "@elementor/editor-mcp": "4.2.0-935",
47
- "@elementor/editor-notifications": "4.2.0-935",
48
- "@elementor/editor-props": "4.2.0-935",
49
- "@elementor/editor-responsive": "4.2.0-935",
50
- "@elementor/editor-styles": "4.2.0-935",
51
- "@elementor/editor-styles-repository": "4.2.0-935",
52
- "@elementor/editor-ui": "4.2.0-935",
53
- "@elementor/editor-v1-adapters": "4.2.0-935",
54
- "@elementor/http-client": "4.2.0-935",
55
- "@elementor/schema": "4.2.0-935",
56
- "@elementor/twing": "4.2.0-935",
42
+ "@elementor/editor-controls": "4.2.0-937",
43
+ "@elementor/editor-documents": "4.2.0-937",
44
+ "@elementor/editor-elements": "4.2.0-937",
45
+ "@elementor/editor-interactions": "4.2.0-937",
46
+ "@elementor/editor-mcp": "4.2.0-937",
47
+ "@elementor/editor-notifications": "4.2.0-937",
48
+ "@elementor/editor-props": "4.2.0-937",
49
+ "@elementor/editor-responsive": "4.2.0-937",
50
+ "@elementor/editor-styles": "4.2.0-937",
51
+ "@elementor/editor-styles-repository": "4.2.0-937",
52
+ "@elementor/editor-ui": "4.2.0-937",
53
+ "@elementor/editor-v1-adapters": "4.2.0-937",
54
+ "@elementor/http-client": "4.2.0-937",
55
+ "@elementor/schema": "4.2.0-937",
56
+ "@elementor/twing": "4.2.0-937",
57
57
  "@elementor/ui": "1.37.5",
58
- "@elementor/utils": "4.2.0-935",
59
- "@elementor/wp-media": "4.2.0-935",
58
+ "@elementor/utils": "4.2.0-937",
59
+ "@elementor/wp-media": "4.2.0-937",
60
60
  "@floating-ui/react": "^0.27.5",
61
61
  "@wordpress/i18n": "^5.13.0"
62
62
  },
@@ -41,7 +41,7 @@ Always check existing resources before building:
41
41
  For each widget you'll use:
42
42
  - List \`${ WIDGET_SCHEMA_URI }\` to see available widgets
43
43
  - Retrieve configuration schema from \`${ ELEMENT_SCHEMA_URI }\` for each widget
44
- - Check the \`llm_guidance\` property to understand if a widget is a container (can have children)
44
+ - Check the \`llm_guidance\` property for container nesting, \`default_styles\`, and \`default_settings\` (omit default_settings from elementConfig unless the user asks to change them)
45
45
 
46
46
  ### 4. Build XML Structure
47
47
  Create valid XML with configuration-ids:
@@ -0,0 +1,95 @@
1
+ import { type V1ElementConfig } from '@elementor/editor-elements';
2
+
3
+ import { buildLlmGuidance, enrichPropertiesWithBaseSettingsHints, mergeInstructions } from '../build-llm-guidance';
4
+
5
+ const mockEmailBaseSettings = {
6
+ email: {
7
+ $$type: 'emails',
8
+ value: {
9
+ to: {
10
+ $$type: 'string-array',
11
+ value: [ { $$type: 'string', value: 'admin@example.com' } ],
12
+ },
13
+ from: { $$type: 'string', value: 'email@example.com' },
14
+ message: { $$type: 'string', value: '[all-fields]' },
15
+ },
16
+ },
17
+ };
18
+
19
+ const mockFormWidgetData = {
20
+ title: 'Form',
21
+ controls: {},
22
+ elType: 'widget',
23
+ meta: { is_container: true },
24
+ base_settings: mockEmailBaseSettings,
25
+ atomic_props_schema: {
26
+ email: { kind: 'object', key: 'emails' },
27
+ 'form-name': { kind: 'string', key: 'string' },
28
+ },
29
+ } as unknown as V1ElementConfig;
30
+
31
+ describe( 'build-llm-guidance', () => {
32
+ it( 'mergeInstructions combines existing and additional instructions', () => {
33
+ expect( mergeInstructions( 'First.', 'Second.' ) ).toBe( 'First. Second.' );
34
+ expect( mergeInstructions( undefined, 'Only.' ) ).toBe( 'Only.' );
35
+ } );
36
+
37
+ it( 'buildLlmGuidance exposes default_settings for widgets with base_settings', () => {
38
+ const guidance = buildLlmGuidance( mockFormWidgetData, 'e-form', {} );
39
+
40
+ expect( guidance.default_settings ).toEqual( mockEmailBaseSettings );
41
+ expect( guidance.instructions ).toContain( 'Omit them from elementConfig unless the user explicitly asks' );
42
+ expect( guidance.can_have_children ).toBe( true );
43
+ } );
44
+
45
+ it( 'buildLlmGuidance merges style and settings instructions when both exist', () => {
46
+ const widgetData = {
47
+ ...mockFormWidgetData,
48
+ base_styles: {
49
+ 'e-form-base': {
50
+ variants: [
51
+ {
52
+ props: {
53
+ display: { $$type: 'string', value: 'flex' },
54
+ },
55
+ },
56
+ ],
57
+ },
58
+ },
59
+ } as unknown as V1ElementConfig;
60
+
61
+ const guidance = buildLlmGuidance( widgetData, 'e-form', {} );
62
+
63
+ expect( guidance.default_styles ).toEqual( { display: { $$type: 'string', value: 'flex' } } );
64
+ expect( guidance.default_settings ).toEqual( mockEmailBaseSettings );
65
+ expect( guidance.instructions ).toContain( 'default styles' );
66
+ expect( guidance.instructions ).toContain( 'default settings' );
67
+ } );
68
+
69
+ it( 'enrichPropertiesWithBaseSettingsHints adds omit guidance to base setting props', () => {
70
+ const enriched = enrichPropertiesWithBaseSettingsHints(
71
+ {
72
+ email: { type: 'object' },
73
+ 'form-name': { type: 'object' },
74
+ },
75
+ [ 'email' ]
76
+ );
77
+
78
+ expect( enriched.email.description ).toContain( 'llm_guidance.default_settings' );
79
+ expect( enriched[ 'form-name' ].description ).toBeUndefined();
80
+ } );
81
+ } );
82
+
83
+ describe( 'widgets-schema-resource base_settings integration', () => {
84
+ it( 'keeps base setting props in schema while enriching descriptions', () => {
85
+ const properties = enrichPropertiesWithBaseSettingsHints(
86
+ {
87
+ email: { type: 'object', properties: {} },
88
+ },
89
+ Object.keys( mockEmailBaseSettings )
90
+ );
91
+
92
+ expect( properties ).toHaveProperty( 'email' );
93
+ expect( properties.email.description ).toContain( 'omit unless user explicitly requests' );
94
+ } );
95
+ } );
@@ -0,0 +1,110 @@
1
+ import { type V1ElementConfig } from '@elementor/editor-elements';
2
+ import { type Props, type PropValue } from '@elementor/editor-props';
3
+
4
+ import { getRequiredDefaultChildTypes } from '../../composition-builder/utils/required-default-child-tags';
5
+
6
+ const DEFAULT_STYLES_INSTRUCTION = 'These are the default styles applied to the widget. Override only when necessary.';
7
+
8
+ const DEFAULT_SETTINGS_INSTRUCTION =
9
+ 'These are the default settings applied to the widget. Omit them from elementConfig unless the user explicitly asks to change them.';
10
+
11
+ const BASE_SETTING_PROP_HINT =
12
+ 'Has a widget default — omit unless user explicitly requests a change. See llm_guidance.default_settings.';
13
+
14
+ export type LlmGuidance = Record< string, unknown >;
15
+
16
+ export type JsonSchemaProperty = {
17
+ description?: string;
18
+ [ key: string ]: unknown;
19
+ };
20
+
21
+ export function mergeInstructions( existing: unknown, additional: string ): string {
22
+ if ( typeof existing === 'string' && existing.length > 0 ) {
23
+ return `${ existing } ${ additional }`;
24
+ }
25
+
26
+ return additional;
27
+ }
28
+
29
+ export function enrichPropertiesWithBaseSettingsHints(
30
+ properties: Record< string, JsonSchemaProperty >,
31
+ baseSettingsKeys: string[]
32
+ ): Record< string, JsonSchemaProperty > {
33
+ if ( ! baseSettingsKeys.length ) {
34
+ return properties;
35
+ }
36
+
37
+ const enriched: Record< string, JsonSchemaProperty > = { ...properties };
38
+
39
+ for ( const key of baseSettingsKeys ) {
40
+ const propSchema = enriched[ key ];
41
+
42
+ if ( ! propSchema ) {
43
+ continue;
44
+ }
45
+
46
+ enriched[ key ] = {
47
+ ...propSchema,
48
+ description: propSchema.description
49
+ ? `${ propSchema.description } ${ BASE_SETTING_PROP_HINT }`
50
+ : BASE_SETTING_PROP_HINT,
51
+ };
52
+ }
53
+
54
+ return enriched;
55
+ }
56
+
57
+ export function buildLlmGuidance(
58
+ widgetData: V1ElementConfig,
59
+ widgetType: string,
60
+ allWidgets: Record< string, V1ElementConfig >
61
+ ): LlmGuidance {
62
+ const defaultStyles: Record< string, Props > = {};
63
+ const baseStyleSchema = widgetData?.base_styles;
64
+
65
+ if ( baseStyleSchema ) {
66
+ Object.values( baseStyleSchema ).forEach( ( stylePropType ) => {
67
+ stylePropType.variants.forEach( ( variant ) => {
68
+ Object.assign( defaultStyles, variant.props );
69
+ } );
70
+ } );
71
+ }
72
+
73
+ const baseSettings = ( widgetData?.base_settings ?? {} ) as Record< string, PropValue >;
74
+ const hasDefaultStyles = Object.keys( defaultStyles ).length > 0;
75
+ const hasDefaultSettings = Object.keys( baseSettings ).length > 0;
76
+
77
+ const llmGuidance: LlmGuidance = {
78
+ can_have_children: !! widgetData?.meta?.is_container,
79
+ };
80
+
81
+ if ( hasDefaultStyles ) {
82
+ llmGuidance.instructions = DEFAULT_STYLES_INSTRUCTION;
83
+ llmGuidance.default_styles = defaultStyles;
84
+ }
85
+
86
+ if ( hasDefaultSettings ) {
87
+ llmGuidance.instructions = mergeInstructions( llmGuidance.instructions, DEFAULT_SETTINGS_INSTRUCTION );
88
+ llmGuidance.default_settings = baseSettings;
89
+ }
90
+
91
+ const allowedChildTypes = widgetData.allowed_child_types;
92
+ const allowedParents = Object.entries( allWidgets )
93
+ .filter( ( [ , parentConfig ] ) => parentConfig.allowed_child_types?.includes( widgetType ) )
94
+ .map( ( [ parentType ] ) => parentType );
95
+
96
+ if ( allowedChildTypes?.length || allowedParents.length ) {
97
+ llmGuidance.nesting = {
98
+ ...( allowedChildTypes?.length ? { allowed_child_types: allowedChildTypes } : {} ),
99
+ ...( allowedParents.length ? { allowed_parents: allowedParents } : {} ),
100
+ };
101
+ }
102
+
103
+ const requiredDirectChildTags = getRequiredDefaultChildTypes( widgetData );
104
+
105
+ if ( requiredDirectChildTags.length ) {
106
+ llmGuidance.required_direct_children = requiredDirectChildTags;
107
+ }
108
+
109
+ return llmGuidance;
110
+ }
@@ -3,15 +3,14 @@ import { type MCPRegistryEntry, ResourceTemplate } from '@elementor/editor-mcp';
3
3
  import {
4
4
  type ArrayPropType,
5
5
  type ObjectPropType,
6
- type Props,
7
6
  type PropType,
8
7
  Schema,
9
8
  type TransformablePropType,
10
9
  type UnionPropType,
11
10
  } from '@elementor/editor-props';
12
11
 
13
- import { getRequiredDefaultChildTypes } from '../../composition-builder/utils/required-default-child-tags';
14
12
  import { hasV3Controls, isWidgetAvailableForLLM } from '../utils/element-data-util';
13
+ import { buildLlmGuidance, enrichPropertiesWithBaseSettingsHints } from './build-llm-guidance';
15
14
 
16
15
  const V3_LAYOUT_CONTROL_TYPES = new Set( [ 'section', 'tab', 'tabs' ] );
17
16
 
@@ -143,55 +142,22 @@ Variables from the user context ARE NOT SUPPORTED AND WILL RESOLVE IN ERROR.
143
142
  ],
144
143
  };
145
144
  }
146
- const asJson = Object.fromEntries(
147
- Object.entries( propSchema )
148
- .filter( ( [ key, propType ] ) => Schema.isPropKeyConfigurable( key, propType as PropType ) )
149
- .map( ( [ key, propType ] ) => [ key, Schema.propTypeToJsonSchema( propType ) ] )
145
+ const baseSettingsKeys = Object.keys( widgetData?.base_settings ?? {} );
146
+
147
+ const asJson = enrichPropertiesWithBaseSettingsHints(
148
+ Object.fromEntries(
149
+ Object.entries( propSchema )
150
+ .filter( ( [ key, propType ] ) => Schema.isPropKeyConfigurable( key, propType as PropType ) )
151
+ .map( ( [ key, propType ] ) => [ key, Schema.propTypeToJsonSchema( propType ) ] )
152
+ ),
153
+ baseSettingsKeys
150
154
  );
151
155
 
152
156
  const description =
153
157
  typeof widgetData?.meta?.description === 'string' ? widgetData.meta.description : undefined;
154
158
 
155
- const defaultStyles: Record< string, Props > = {};
156
- const baseStyleSchema = widgetData?.base_styles;
157
- if ( baseStyleSchema ) {
158
- Object.values( baseStyleSchema ).forEach( ( stylePropType ) => {
159
- stylePropType.variants.forEach( ( variant ) => {
160
- Object.assign( defaultStyles, variant.props );
161
- } );
162
- } );
163
- }
164
-
165
- // build llm instructions
166
- const hasDefaultStyles = Object.keys( defaultStyles ).length > 0;
167
- const llmGuidance: Record< string, unknown > = {
168
- can_have_children: !! widgetData?.meta?.is_container,
169
- };
170
-
171
- if ( hasDefaultStyles ) {
172
- llmGuidance.instructions =
173
- 'These are the default styles applied to the widget. Override only when necessary.';
174
- llmGuidance.default_styles = defaultStyles;
175
- }
176
-
177
- const allowedChildTypes = widgetData.allowed_child_types;
178
-
179
159
  const allWidgets = getWidgetsCache() || {};
180
- const allowedParents = Object.entries( allWidgets )
181
- .filter( ( [ , parentConfig ] ) => parentConfig.allowed_child_types?.includes( widgetType ) )
182
- .map( ( [ parentType ] ) => parentType );
183
-
184
- if ( allowedChildTypes?.length || allowedParents.length ) {
185
- llmGuidance.nesting = {
186
- ...( allowedChildTypes?.length ? { allowed_child_types: allowedChildTypes } : {} ),
187
- ...( allowedParents.length ? { allowed_parents: allowedParents } : {} ),
188
- };
189
- }
190
-
191
- const requiredDirectChildTags = getRequiredDefaultChildTypes( widgetData );
192
- if ( requiredDirectChildTags.length ) {
193
- llmGuidance.required_direct_children = requiredDirectChildTags;
194
- }
160
+ const llmGuidance = buildLlmGuidance( widgetData, widgetType, allWidgets );
195
161
 
196
162
  return {
197
163
  contents: [
@@ -41,6 +41,7 @@ Some elements have internal tree structures (nesting). When using these elements
41
41
  - style is raw CSS (property → value strings); the server converts it to native styles and stores any unconvertible declarations as the element custom CSS
42
42
  - NO LINKS in configuration
43
43
  - Retry on errors up to 10x
44
+ - Check \`llm_guidance.default_settings\` in widget schemas — omit only keys listed there from elementConfig unless the user explicitly asks to change them
44
45
 
45
46
  # DYNAMIC TAGS
46
47
  - A value can be made dynamic wherever its schema exposes a \`"$$type": "dynamic"\` variant. This may be the property root OR a NESTED field (e.g. an image's \`src\`, not the whole \`image\`).
@@ -119,7 +120,7 @@ BAD: \`<e-flexbox style="height:100vh"><e-div-block style="height:100vh">overflo
119
120
  # HARD CONSTRAINTS
120
121
  - Variables ONLY from [elementor://global-variables] (others throw errors)
121
122
  - Avoid SVG widgets unless assets are pre-uploaded
122
- - Check \`llm_guidance\` in widget schemas
123
+ - Check \`llm_guidance\` in widget schemas (\`default_styles\`, nesting, required children)
123
124
 
124
125
  # PARAMETERS
125
126
  - **xmlStructure**: Valid XML with configuration-id attributes
@@ -50,6 +50,8 @@ For all non-primitive entries in \`propertiesToChange\`, provide the schema \`ke
50
50
 
51
51
  Use the EXACT PropType schema given, and ALWAYS include the \`key\` from the schema for every property you are changing in \`propertiesToChange\`.
52
52
 
53
+ Check \`llm_guidance.default_settings\` in the widget schema — include a key in \`propertiesToChange\` only when the user explicitly asks to change it.
54
+
53
55
  # Dynamic tags
54
56
  A value can be made dynamic wherever its schema exposes a variant with "$$type": "dynamic". This may be the property root OR a NESTED field: for example an image is made dynamic on its "src" (the root stays "image"), NOT on the whole "image" value.
55
57
  Put the dynamic object EXACTLY at the node whose schema offers the "dynamic" variant, in place of the static variant. The variant's "name" enumerates the tags allowed at that node.