@elementor/editor-canvas 4.0.0-573 → 4.0.0-597

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
@@ -993,7 +993,13 @@ import { __ } from "@wordpress/i18n";
993
993
  // src/form-structure/utils.ts
994
994
  import { getAllDescendants } from "@elementor/editor-elements";
995
995
  var FORM_ELEMENT_TYPE = "e-form";
996
- var FORM_FIELD_ELEMENT_TYPES = /* @__PURE__ */ new Set(["e-form-input", "e-form-textarea", "e-form-label"]);
996
+ var FORM_FIELD_ELEMENT_TYPES = /* @__PURE__ */ new Set([
997
+ "e-form-input",
998
+ "e-form-textarea",
999
+ "e-form-label",
1000
+ "e-form-checkbox",
1001
+ "e-form-submit-button"
1002
+ ]);
997
1003
  function getArgsElementType(args) {
998
1004
  return args.model?.widgetType || args.model?.elType;
999
1005
  }
@@ -1209,6 +1215,11 @@ var htmlV2Transformer = createTransformer((value) => {
1209
1215
  return value?.content ?? "";
1210
1216
  });
1211
1217
 
1218
+ // src/transformers/settings/html-v3-transformer.ts
1219
+ var htmlV3Transformer = createTransformer((value) => {
1220
+ return value?.content ?? "";
1221
+ });
1222
+
1212
1223
  // src/transformers/settings/link-transformer.ts
1213
1224
  var linkTransformer = createTransformer(({ destination, isTargetBlank, tag }) => {
1214
1225
  return {
@@ -1263,7 +1274,7 @@ var plainTransformer = createTransformer((value) => {
1263
1274
 
1264
1275
  // src/init-settings-transformers.ts
1265
1276
  function initSettingsTransformers() {
1266
- settingsTransformersRegistry.register("classes", createClassesTransformer()).register("link", linkTransformer).register("query", queryTransformer).register("image", imageTransformer).register("image-src", imageSrcTransformer).register("attributes", attributesTransformer).register("date-time", dateTimeTransformer).register("html-v2", htmlV2Transformer).registerFallback(plainTransformer);
1277
+ settingsTransformersRegistry.register("classes", createClassesTransformer()).register("link", linkTransformer).register("query", queryTransformer).register("image", imageTransformer).register("image-src", imageSrcTransformer).register("attributes", attributesTransformer).register("date-time", dateTimeTransformer).register("html-v2", htmlV2Transformer).register("html-v3", htmlV3Transformer).registerFallback(plainTransformer);
1267
1278
  }
1268
1279
 
1269
1280
  // src/transformers/styles/background-color-overlay-transformer.ts
@@ -2129,7 +2140,7 @@ import * as React6 from "react";
2129
2140
  import { createRoot } from "react-dom/client";
2130
2141
  import { getContainer, getElementLabel, getElementType as getElementType2 } from "@elementor/editor-elements";
2131
2142
  import {
2132
- htmlV2PropTypeUtil as htmlV2PropTypeUtil2,
2143
+ htmlV3PropTypeUtil as htmlV3PropTypeUtil2,
2133
2144
  parseHtmlChildren,
2134
2145
  stringPropTypeUtil as stringPropTypeUtil2
2135
2146
  } from "@elementor/editor-props";
@@ -2176,67 +2187,130 @@ var ReplacementBase = class {
2176
2187
 
2177
2188
  // src/legacy/replacements/inline-editing/canvas-inline-editor.tsx
2178
2189
  import * as React5 from "react";
2179
- import { useEffect as useEffect7, useState as useState4 } from "react";
2190
+ import { useEffect as useEffect8, useLayoutEffect, useState as useState5 } from "react";
2180
2191
  import { InlineEditor, InlineEditorToolbar } from "@elementor/editor-controls";
2181
2192
  import { Box as Box2, ThemeProvider } from "@elementor/ui";
2182
- import { FloatingPortal as FloatingPortal2, useInteractions as useInteractions2 } from "@floating-ui/react";
2193
+ import { autoUpdate as autoUpdate2, flip, FloatingPortal as FloatingPortal2, useFloating as useFloating2 } from "@floating-ui/react";
2183
2194
 
2184
2195
  // src/legacy/replacements/inline-editing/inline-editing-utils.ts
2196
+ import { useCallback, useEffect as useEffect7, useState as useState4 } from "react";
2197
+ var TOP_BAR_SELECTOR = "#elementor-editor-wrapper-v2";
2198
+ var NAVIGATOR_SELECTOR = "#elementor-navigator";
2199
+ var EDITING_PANEL = "#elementor-panel";
2200
+ var EDITOR_ELEMENTS_OUT_OF_IFRAME = [TOP_BAR_SELECTOR, NAVIGATOR_SELECTOR, EDITING_PANEL];
2201
+ var TOOLBAR_ANCHOR_ID_PREFIX = "inline-editing-toolbar-anchor";
2202
+ var TOOLBAR_ANCHOR_STATIC_STYLES = {
2203
+ backgroundColor: "transparent",
2204
+ border: "none",
2205
+ outline: "none",
2206
+ boxShadow: "none",
2207
+ padding: "0",
2208
+ margin: "0",
2209
+ borderRadius: "0",
2210
+ overflow: "hidden",
2211
+ opacity: "0",
2212
+ pointerEvents: "none",
2213
+ position: "absolute",
2214
+ display: "block"
2215
+ };
2185
2216
  var INLINE_EDITING_PROPERTY_PER_TYPE = {
2186
2217
  "e-button": "text",
2187
2218
  "e-form-label": "text",
2188
2219
  "e-heading": "title",
2189
2220
  "e-paragraph": "paragraph"
2190
2221
  };
2191
- var calcSelectionCenterOffsets = (view) => {
2192
- const frameWindow = view.root?.defaultView;
2222
+ var getInlineEditorElement = (elementWrapper, expectedTag) => {
2223
+ return !expectedTag ? null : elementWrapper.querySelector(expectedTag);
2224
+ };
2225
+ var useOnClickOutsideIframe = (handleUnmount) => {
2226
+ const asyncUnmountInlineEditor = useCallback(() => queueMicrotask(handleUnmount), [handleUnmount]);
2227
+ useEffect7(() => {
2228
+ EDITOR_ELEMENTS_OUT_OF_IFRAME.forEach(
2229
+ (selector) => document?.querySelector(selector)?.addEventListener("mousedown", asyncUnmountInlineEditor)
2230
+ );
2231
+ return () => EDITOR_ELEMENTS_OUT_OF_IFRAME.forEach(
2232
+ (selector) => document?.querySelector(selector)?.removeEventListener("mousedown", asyncUnmountInlineEditor)
2233
+ );
2234
+ }, []);
2235
+ };
2236
+ var useRenderToolbar = (ownerDocument, id) => {
2237
+ const [anchor, setAnchor] = useState4(null);
2238
+ const onSelectionEnd = (view) => {
2239
+ const hasSelection = !view.state.selection.empty;
2240
+ removeToolbarAnchor(ownerDocument, id);
2241
+ if (hasSelection) {
2242
+ setAnchor(createAnchorBasedOnSelection(ownerDocument, id));
2243
+ } else {
2244
+ setAnchor(null);
2245
+ }
2246
+ };
2247
+ return { onSelectionEnd, anchor };
2248
+ };
2249
+ var createAnchorBasedOnSelection = (ownerDocument, id) => {
2250
+ const frameWindow = ownerDocument.defaultView;
2193
2251
  const selection = frameWindow?.getSelection();
2194
- const editorContainer = view.dom;
2195
- if (!selection || !editorContainer) {
2252
+ if (!selection) {
2196
2253
  return null;
2197
2254
  }
2198
2255
  const range = selection.getRangeAt(0);
2199
2256
  const selectionRect = range.getBoundingClientRect();
2200
- const editorContainerRect = editorContainer.getBoundingClientRect();
2201
- if (!selectionRect || !editorContainerRect) {
2202
- return null;
2257
+ const bodyRect = ownerDocument.body.getBoundingClientRect();
2258
+ const toolbarAnchor = ownerDocument.createElement("span");
2259
+ styleToolbarAnchor(toolbarAnchor, selectionRect, bodyRect);
2260
+ toolbarAnchor.setAttribute("id", getToolbarAnchorId(id));
2261
+ ownerDocument.body.appendChild(toolbarAnchor);
2262
+ return toolbarAnchor;
2263
+ };
2264
+ var removeToolbarAnchor = (ownerDocument, id) => {
2265
+ const toolbarAnchor = getToolbarAnchor(ownerDocument, id);
2266
+ if (toolbarAnchor) {
2267
+ ownerDocument.body.removeChild(toolbarAnchor);
2203
2268
  }
2204
- const verticalOffset = selectionRect.top - editorContainerRect.top;
2205
- const selectionCenter = selectionRect?.left + selectionRect?.width / 2;
2206
- const horizontalOffset = selectionCenter - editorContainerRect.left;
2207
- return { left: horizontalOffset, top: verticalOffset };
2208
2269
  };
2209
- var getComputedStyle = (styles, offsets) => {
2210
- const transform = extractTransformValue(styles);
2211
- return transform ? {
2212
- ...styles,
2213
- marginLeft: `${offsets.left}px`,
2214
- marginTop: `${offsets.top}px`,
2215
- pointerEvents: "none"
2216
- } : {
2217
- display: "none"
2218
- };
2270
+ var getToolbarAnchorId = (id) => `${TOOLBAR_ANCHOR_ID_PREFIX}-${id}`;
2271
+ var getToolbarAnchor = (ownerDocument, id) => ownerDocument.getElementById(getToolbarAnchorId(id));
2272
+ var styleToolbarAnchor = (anchor, selectionRect, bodyRect) => {
2273
+ const { width, height } = selectionRect;
2274
+ Object.assign(anchor.style, {
2275
+ ...TOOLBAR_ANCHOR_STATIC_STYLES,
2276
+ top: `${selectionRect.top - bodyRect.top}px`,
2277
+ left: `${selectionRect.left - bodyRect.left}px`,
2278
+ width: `${width}px`,
2279
+ height: `${height}px`
2280
+ });
2219
2281
  };
2220
- var extractTransformValue = (styles) => {
2221
- const translateRegex = /translate\([^)]*\)\s?/g;
2222
- const numericValuesRegex = /(-?\d+\.?\d*)/g;
2223
- const translateValue = styles?.transform?.match(translateRegex)?.[0];
2224
- const values = translateValue?.match(numericValuesRegex);
2225
- if (!translateValue || !values) {
2226
- return null;
2227
- }
2228
- const [numericX, numericY] = values.map(Number);
2229
- if (!numericX || !numericY) {
2230
- return null;
2282
+ var horizontalShifterMiddleware = {
2283
+ name: "horizontalShifter",
2284
+ fn(state) {
2285
+ const {
2286
+ x: left,
2287
+ y: top,
2288
+ elements: { reference: anchor, floating }
2289
+ } = state;
2290
+ const newState = {
2291
+ ...state,
2292
+ x: left,
2293
+ y: top
2294
+ };
2295
+ const isLeftOverflown = left < 0;
2296
+ if (isLeftOverflown) {
2297
+ newState.x = 0;
2298
+ return newState;
2299
+ }
2300
+ const anchorRect = anchor.getBoundingClientRect();
2301
+ const right = left + floating.offsetWidth;
2302
+ const documentWidth = anchor.ownerDocument.body.offsetWidth;
2303
+ const isRightOverflown = right > documentWidth && anchorRect.right < right;
2304
+ if (isRightOverflown) {
2305
+ const diff = right - documentWidth;
2306
+ newState.x = left - diff;
2307
+ return newState;
2308
+ }
2309
+ return newState;
2231
2310
  }
2232
- return styles.transform;
2233
2311
  };
2234
2312
 
2235
2313
  // src/legacy/replacements/inline-editing/canvas-inline-editor.tsx
2236
- var TOP_BAR_SELECTOR = "#elementor-editor-wrapper-v2";
2237
- var NAVIGATOR_SELECTOR = "#elementor-navigator";
2238
- var EDITING_PANEL = "#elementor-panel";
2239
- var EDITOR_ELEMENTS_OUT_OF_IFRAME = [TOP_BAR_SELECTOR, NAVIGATOR_SELECTOR, EDITING_PANEL];
2240
2314
  var EDITOR_WRAPPER_SELECTOR = "inline-editor-wrapper";
2241
2315
  var CanvasInlineEditor = ({
2242
2316
  elementClasses,
@@ -2245,23 +2319,23 @@ var CanvasInlineEditor = ({
2245
2319
  rootElement,
2246
2320
  id,
2247
2321
  setValue,
2248
- onBlur
2322
+ ...props
2249
2323
  }) => {
2250
- const [selectionOffsets, setSelectionOffsets] = useState4(null);
2251
- const [editor, setEditor] = useState4(null);
2252
- const onSelectionEnd = (view) => {
2253
- const hasSelection = !view.state.selection.empty;
2254
- setSelectionOffsets(hasSelection ? calcSelectionCenterOffsets(view) : null);
2324
+ const [editor, setEditor] = useState5(null);
2325
+ const { onSelectionEnd, anchor: toolbarAnchor } = useRenderToolbar(rootElement.ownerDocument, id);
2326
+ const onBlur = () => {
2327
+ removeToolbarAnchor(rootElement.ownerDocument, id);
2328
+ props.onBlur();
2255
2329
  };
2256
2330
  useOnClickOutsideIframe(onBlur);
2257
2331
  return /* @__PURE__ */ React5.createElement(ThemeProvider, null, /* @__PURE__ */ React5.createElement(InlineEditingOverlay, { expectedTag, rootElement, id }), /* @__PURE__ */ React5.createElement("style", null, `
2258
2332
  .ProseMirror > * {
2259
2333
  height: 100%;
2260
2334
  }
2261
- .${EDITOR_WRAPPER_SELECTOR} .ProseMirror > button[contenteditable="true"] {
2262
- height: auto;
2263
- cursor: text;
2264
- }
2335
+ .${EDITOR_WRAPPER_SELECTOR} .ProseMirror > button[contenteditable="true"] {
2336
+ height: auto;
2337
+ cursor: text;
2338
+ }
2265
2339
  `), /* @__PURE__ */ React5.createElement(
2266
2340
  InlineEditor,
2267
2341
  {
@@ -2277,19 +2351,9 @@ var CanvasInlineEditor = ({
2277
2351
  onBlur,
2278
2352
  autofocus: true,
2279
2353
  expectedTag,
2280
- wrapperClassName: EDITOR_WRAPPER_SELECTOR,
2281
2354
  onSelectionEnd
2282
2355
  }
2283
- ), selectionOffsets && editor && /* @__PURE__ */ React5.createElement(
2284
- InlineEditingToolbarWrapper,
2285
- {
2286
- expectedTag,
2287
- editor,
2288
- rootElement,
2289
- id,
2290
- selectionOffsets
2291
- }
2292
- ));
2356
+ ), toolbarAnchor && editor && /* @__PURE__ */ React5.createElement(InlineEditingToolbar, { anchor: toolbarAnchor, editor, id }));
2293
2357
  };
2294
2358
  var InlineEditingOverlay = ({
2295
2359
  expectedTag,
@@ -2297,92 +2361,33 @@ var InlineEditingOverlay = ({
2297
2361
  id
2298
2362
  }) => {
2299
2363
  const inlineEditedElement = getInlineEditorElement(rootElement, expectedTag);
2300
- const [overlayRefElement, setOverlayElement] = useState4(inlineEditedElement);
2301
- useEffect7(() => {
2364
+ const [overlayRefElement, setOverlayElement] = useState5(inlineEditedElement);
2365
+ useEffect8(() => {
2302
2366
  setOverlayElement(getInlineEditorElement(rootElement, expectedTag));
2303
2367
  }, [expectedTag, rootElement]);
2304
2368
  return overlayRefElement ? /* @__PURE__ */ React5.createElement(OutlineOverlay, { element: overlayRefElement, id, isSelected: true }) : null;
2305
2369
  };
2306
- var InlineEditingToolbarWrapper = ({
2307
- expectedTag,
2308
- editor,
2309
- rootElement,
2310
- id,
2311
- selectionOffsets
2312
- }) => {
2313
- const [element, setElement] = useState4(null);
2314
- useEffect7(() => {
2315
- setElement(getInlineEditorElement(rootElement, expectedTag));
2316
- }, [expectedTag, rootElement]);
2317
- return element ? /* @__PURE__ */ React5.createElement(InlineEditingToolbar, { element, editor, id, selectionOffsets }) : null;
2318
- };
2319
- var InlineEditingToolbar = ({
2320
- element,
2321
- editor,
2322
- id,
2323
- selectionOffsets
2324
- }) => {
2325
- const { floating } = useFloatingOnElement({
2326
- element,
2327
- isSelected: true
2370
+ var InlineEditingToolbar = ({ anchor, editor, id }) => {
2371
+ const { refs, floatingStyles } = useFloating2({
2372
+ placement: "top",
2373
+ strategy: "fixed",
2374
+ transform: false,
2375
+ whileElementsMounted: autoUpdate2,
2376
+ middleware: [horizontalShifterMiddleware, flip()]
2328
2377
  });
2329
- const { getFloatingProps, getReferenceProps } = useInteractions2();
2330
- const style = getComputedStyle(floating.styles, selectionOffsets);
2331
- useBindReactPropsToElement(element, getReferenceProps);
2332
- return /* @__PURE__ */ React5.createElement(FloatingPortal2, { id: CANVAS_WRAPPER_ID }, /* @__PURE__ */ React5.createElement(
2333
- Box2,
2334
- {
2335
- ref: floating.setRef,
2336
- style: {
2337
- ...floating.styles,
2338
- pointerEvents: "none"
2339
- },
2340
- role: "presentation",
2341
- ...getFloatingProps({ style })
2342
- },
2343
- floating.styles.transform && /* @__PURE__ */ React5.createElement(
2344
- Box2,
2345
- {
2346
- sx: {
2347
- position: "relative",
2348
- transform: "translateY(-100%)",
2349
- height: "max-content"
2350
- }
2351
- },
2352
- /* @__PURE__ */ React5.createElement(
2353
- InlineEditorToolbar,
2354
- {
2355
- editor,
2356
- elementId: id,
2357
- sx: {
2358
- transform: "translateX(-50%)"
2359
- }
2360
- }
2361
- )
2362
- )
2363
- ));
2364
- };
2365
- var getInlineEditorElement = (elementWrapper, expectedTag) => {
2366
- return !expectedTag ? null : elementWrapper.querySelector(expectedTag);
2367
- };
2368
- var useOnClickOutsideIframe = (handleUnmount) => {
2369
- const asyncUnmountInlineEditor = React5.useCallback(() => queueMicrotask(handleUnmount), [handleUnmount]);
2370
- useEffect7(() => {
2371
- EDITOR_ELEMENTS_OUT_OF_IFRAME.forEach(
2372
- (selector) => document?.querySelector(selector)?.addEventListener("mousedown", asyncUnmountInlineEditor)
2373
- );
2374
- return () => EDITOR_ELEMENTS_OUT_OF_IFRAME.forEach(
2375
- (selector) => document?.querySelector(selector)?.removeEventListener("mousedown", asyncUnmountInlineEditor)
2376
- );
2377
- }, []);
2378
+ useLayoutEffect(() => {
2379
+ refs.setReference(anchor);
2380
+ return () => refs.setReference(null);
2381
+ }, [anchor, refs]);
2382
+ return /* @__PURE__ */ React5.createElement(FloatingPortal2, { id: CANVAS_WRAPPER_ID }, /* @__PURE__ */ React5.createElement(Box2, { ref: refs.setFloating, role: "presentation", style: { ...floatingStyles, pointerEvents: "none" } }, /* @__PURE__ */ React5.createElement(InlineEditorToolbar, { editor, elementId: id })));
2378
2383
  };
2379
2384
 
2380
2385
  // src/legacy/replacements/inline-editing/inline-editing-eligibility.ts
2381
- import { htmlV2PropTypeUtil, stringPropTypeUtil } from "@elementor/editor-props";
2386
+ import { htmlV3PropTypeUtil, stringPropTypeUtil } from "@elementor/editor-props";
2382
2387
  var hasKey = (propType) => {
2383
2388
  return "key" in propType;
2384
2389
  };
2385
- var TEXT_PROP_TYPE_KEYS = /* @__PURE__ */ new Set([htmlV2PropTypeUtil.key, stringPropTypeUtil.key]);
2390
+ var TEXT_PROP_TYPE_KEYS = /* @__PURE__ */ new Set([htmlV3PropTypeUtil.key, stringPropTypeUtil.key]);
2386
2391
  var isCoreTextPropTypeKey = (key) => {
2387
2392
  return TEXT_PROP_TYPE_KEYS.has(key);
2388
2393
  };
@@ -2402,7 +2407,7 @@ var isInlineEditingAllowed = ({ rawValue, propTypeFromSchema }) => {
2402
2407
  if (rawValue === null || rawValue === void 0) {
2403
2408
  return isAllowedBySchema(propTypeFromSchema);
2404
2409
  }
2405
- return htmlV2PropTypeUtil.isValid(rawValue) || stringPropTypeUtil.isValid(rawValue);
2410
+ return htmlV3PropTypeUtil.isValid(rawValue) || stringPropTypeUtil.isValid(rawValue);
2406
2411
  };
2407
2412
 
2408
2413
  // src/legacy/replacements/inline-editing/inline-editing-elements.tsx
@@ -2487,14 +2492,15 @@ var InlineEditingReplacement = class extends ReplacementBase {
2487
2492
  }
2488
2493
  getExtractedContentValue() {
2489
2494
  const propValue = this.getInlineEditablePropValue();
2490
- return htmlV2PropTypeUtil2.extract(propValue)?.content ?? "";
2495
+ const extracted = htmlV3PropTypeUtil2.extract(propValue);
2496
+ return stringPropTypeUtil2.extract(extracted?.content ?? null) ?? "";
2491
2497
  }
2492
2498
  setContentValue(value) {
2493
2499
  const settingKey = this.getInlineEditablePropertyName();
2494
2500
  const html = value || "";
2495
2501
  const parsed = parseHtmlChildren(html);
2496
- const valueToSave = htmlV2PropTypeUtil2.create({
2497
- content: parsed.content || null,
2502
+ const valueToSave = htmlV3PropTypeUtil2.create({
2503
+ content: parsed.content ? stringPropTypeUtil2.create(parsed.content) : null,
2498
2504
  children: parsed.children
2499
2505
  });
2500
2506
  undoable(
@@ -2525,7 +2531,7 @@ var InlineEditingReplacement = class extends ReplacementBase {
2525
2531
  return null;
2526
2532
  }
2527
2533
  if (propType.kind === "union") {
2528
- const textKeys = [htmlV2PropTypeUtil2.key, stringPropTypeUtil2.key];
2534
+ const textKeys = [htmlV3PropTypeUtil2.key, stringPropTypeUtil2.key];
2529
2535
  for (const key of textKeys) {
2530
2536
  if (propType.prop_types[key]) {
2531
2537
  return key;
@@ -2750,7 +2756,7 @@ function createNestedTemplatedType(type, renderer, element) {
2750
2756
  }
2751
2757
 
2752
2758
  // src/legacy/tabs-model-extensions.ts
2753
- import { htmlV2PropTypeUtil as htmlV2PropTypeUtil3 } from "@elementor/editor-props";
2759
+ import { htmlV3PropTypeUtil as htmlV3PropTypeUtil3, stringPropTypeUtil as stringPropTypeUtil3 } from "@elementor/editor-props";
2754
2760
  var tabModelExtensions = {
2755
2761
  modifyDefaultChildren(elements) {
2756
2762
  if (!Array.isArray(elements) || elements.length === 0) {
@@ -2766,7 +2772,10 @@ var tabModelExtensions = {
2766
2772
  ...paragraphElement,
2767
2773
  settings: {
2768
2774
  ...paragraphElement.settings,
2769
- paragraph: htmlV2PropTypeUtil3.create({ content: `Tab ${position}`, children: [] })
2775
+ paragraph: htmlV3PropTypeUtil3.create({
2776
+ content: stringPropTypeUtil3.create(`Tab ${position}`),
2777
+ children: []
2778
+ })
2770
2779
  }
2771
2780
  };
2772
2781
  return [updatedParagraph, ...elements.slice(1)];
@@ -3435,6 +3444,13 @@ var inputSchema = {
3435
3444
  `A record mapping element IDs to their styles configuration objects. Use the actual styles schema from [${STYLE_SCHEMA_URI}].`
3436
3445
  ).default({})
3437
3446
  };
3447
+ var outputSchema = {
3448
+ errors: z.string().describe("Error message if the composition building failed").optional(),
3449
+ xmlStructure: z.string().describe(
3450
+ "The built XML structure as a string. Must use this XML after completion of building the composition, it contains real IDs."
3451
+ ).optional(),
3452
+ llm_instructions: z.string().describe("Instructions what to do next, Important to follow these instructions!").optional()
3453
+ };
3438
3454
 
3439
3455
  // src/mcp/tools/build-composition/tool.ts
3440
3456
  var initBuildCompositionsTool = (reg) => {
@@ -3450,7 +3466,7 @@ var initBuildCompositionsTool = (reg) => {
3450
3466
  { description: "Global Variables", uri: "elementor://global-variables" },
3451
3467
  { description: "Styles best practices", uri: BEST_PRACTICES_URI }
3452
3468
  ],
3453
- // outputSchema: '',
3469
+ outputSchema,
3454
3470
  modelPreferences: {
3455
3471
  hints: [{ name: "claude-sonnet-4-5" }]
3456
3472
  },
@@ -3532,10 +3548,10 @@ ${errorMessages.join(
3532
3548
  Now that you have these errors, fix them and try again. Errors regarding configuration objects, please check against the PropType schemas`;
3533
3549
  throw new Error(errorText);
3534
3550
  }
3535
- if (errors.length) {
3536
- throw new Error(errors.map((e) => typeof e === "string" ? e : e.message).join("\n"));
3537
- }
3538
- return `The composition was built successfully with element IDs embedded in the XML.
3551
+ return {
3552
+ xmlStructure: generatedXML,
3553
+ errors: errors?.length ? errors.map((e) => typeof e === "string" ? e : e.message).join("\n\n") : void 0,
3554
+ llm_instructions: `The composition was built successfully with element IDs embedded in the XML.
3539
3555
 
3540
3556
  **CRITICAL NEXT STEPS** (Follow in order):
3541
3557
  1. **Apply Global Classes**: Use "apply-global-class" tool to apply the global classes you created BEFORE building this composition
@@ -3545,10 +3561,8 @@ Now that you have these errors, fix them and try again. Errors regarding configu
3545
3561
  2. **Fine-tune if needed**: Use "configure-element" tool only for element-specific adjustments that don't warrant global classes
3546
3562
 
3547
3563
  Remember: Global classes ensure design consistency and reusability. Don't skip applying them!
3548
-
3549
- Updated XML structure:
3550
- ${generatedXML}
3551
- `;
3564
+ `
3565
+ };
3552
3566
  }
3553
3567
  });
3554
3568
  };
@@ -3667,7 +3681,7 @@ var inputSchema2 = {
3667
3681
  elementType: z2.string().describe("The type of the element to retreive the schema"),
3668
3682
  elementId: z2.string().describe("The unique id of the element to configure")
3669
3683
  };
3670
- var outputSchema = {
3684
+ var outputSchema2 = {
3671
3685
  success: z2.boolean().describe(
3672
3686
  "Whether the configuration change was successful, only if propertyName and propertyValue are provided"
3673
3687
  )
@@ -3680,7 +3694,7 @@ var initConfigureElementTool = (reg) => {
3680
3694
  name: "configure-element",
3681
3695
  description: configureElementToolPrompt,
3682
3696
  schema: inputSchema2,
3683
- outputSchema,
3697
+ outputSchema: outputSchema2,
3684
3698
  requiredResources: [
3685
3699
  { description: "Widgets schema", uri: WIDGET_SCHEMA_URI },
3686
3700
  { description: "Styles schema", uri: STYLE_SCHEMA_URI }
@@ -3778,7 +3792,7 @@ import { z as z3 } from "@elementor/schema";
3778
3792
  var schema = {
3779
3793
  elementId: z3.string()
3780
3794
  };
3781
- var outputSchema2 = {
3795
+ var outputSchema3 = {
3782
3796
  properties: z3.record(z3.string(), z3.any()).describe("A record mapping PropTypes to their corresponding PropValues"),
3783
3797
  style: z3.record(z3.string(), z3.any()).describe("A record mapping StyleSchema properties to their corresponding PropValues"),
3784
3798
  childElements: z3.array(
@@ -3805,7 +3819,7 @@ var initGetElementConfigTool = (reg) => {
3805
3819
  name: "get-element-configuration-values",
3806
3820
  description: "Retrieve the element's configuration PropValues for a specific element by unique ID.",
3807
3821
  schema,
3808
- outputSchema: outputSchema2,
3822
+ outputSchema: outputSchema3,
3809
3823
  modelPreferences: {
3810
3824
  intelligencePriority: 0.6,
3811
3825
  speedPriority: 0.9
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.0.0-573",
4
+ "version": "4.0.0-597",
5
5
  "private": false,
6
6
  "author": "Elementor Team",
7
7
  "homepage": "https://elementor.com/",
@@ -37,24 +37,24 @@
37
37
  "react-dom": "^18.3.1"
38
38
  },
39
39
  "dependencies": {
40
- "@elementor/editor": "4.0.0-573",
41
- "@elementor/editor-controls": "4.0.0-573",
42
- "@elementor/editor-documents": "4.0.0-573",
43
- "@elementor/editor-elements": "4.0.0-573",
44
- "@elementor/editor-interactions": "4.0.0-573",
45
- "@elementor/editor-mcp": "4.0.0-573",
46
- "@elementor/editor-notifications": "4.0.0-573",
47
- "@elementor/editor-props": "4.0.0-573",
48
- "@elementor/editor-responsive": "4.0.0-573",
49
- "@elementor/editor-styles": "4.0.0-573",
50
- "@elementor/editor-styles-repository": "4.0.0-573",
51
- "@elementor/editor-ui": "4.0.0-573",
52
- "@elementor/editor-v1-adapters": "4.0.0-573",
53
- "@elementor/schema": "4.0.0-573",
54
- "@elementor/twing": "4.0.0-573",
40
+ "@elementor/editor": "4.0.0-597",
41
+ "@elementor/editor-controls": "4.0.0-597",
42
+ "@elementor/editor-documents": "4.0.0-597",
43
+ "@elementor/editor-elements": "4.0.0-597",
44
+ "@elementor/editor-interactions": "4.0.0-597",
45
+ "@elementor/editor-mcp": "4.0.0-597",
46
+ "@elementor/editor-notifications": "4.0.0-597",
47
+ "@elementor/editor-props": "4.0.0-597",
48
+ "@elementor/editor-responsive": "4.0.0-597",
49
+ "@elementor/editor-styles": "4.0.0-597",
50
+ "@elementor/editor-styles-repository": "4.0.0-597",
51
+ "@elementor/editor-ui": "4.0.0-597",
52
+ "@elementor/editor-v1-adapters": "4.0.0-597",
53
+ "@elementor/schema": "4.0.0-597",
54
+ "@elementor/twing": "4.0.0-597",
55
55
  "@elementor/ui": "1.36.17",
56
- "@elementor/utils": "4.0.0-573",
57
- "@elementor/wp-media": "4.0.0-573",
56
+ "@elementor/utils": "4.0.0-597",
57
+ "@elementor/wp-media": "4.0.0-597",
58
58
  "@floating-ui/react": "^0.27.5",
59
59
  "@wordpress/i18n": "^5.13.0"
60
60
  },
@@ -32,7 +32,13 @@ export type StorageContent = {
32
32
  };
33
33
 
34
34
  export const FORM_ELEMENT_TYPE = 'e-form';
35
- export const FORM_FIELD_ELEMENT_TYPES = new Set( [ 'e-form-input', 'e-form-textarea', 'e-form-label' ] );
35
+ export const FORM_FIELD_ELEMENT_TYPES = new Set( [
36
+ 'e-form-input',
37
+ 'e-form-textarea',
38
+ 'e-form-label',
39
+ 'e-form-checkbox',
40
+ 'e-form-submit-button',
41
+ ] );
36
42
 
37
43
  export function getArgsElementType( args: CreateArgs ): string | undefined {
38
44
  return args.model?.widgetType || args.model?.elType;
@@ -3,6 +3,7 @@ import { attributesTransformer } from './transformers/settings/attributes-transf
3
3
  import { createClassesTransformer } from './transformers/settings/classes-transformer';
4
4
  import { dateTimeTransformer } from './transformers/settings/date-time-transformer';
5
5
  import { htmlV2Transformer } from './transformers/settings/html-v2-transformer';
6
+ import { htmlV3Transformer } from './transformers/settings/html-v3-transformer';
6
7
  import { linkTransformer } from './transformers/settings/link-transformer';
7
8
  import { queryTransformer } from './transformers/settings/query-transformer';
8
9
  import { imageSrcTransformer } from './transformers/shared/image-src-transformer';
@@ -19,5 +20,6 @@ export function initSettingsTransformers() {
19
20
  .register( 'attributes', attributesTransformer )
20
21
  .register( 'date-time', dateTimeTransformer )
21
22
  .register( 'html-v2', htmlV2Transformer )
23
+ .register( 'html-v3', htmlV3Transformer )
22
24
  .registerFallback( plainTransformer );
23
25
  }
@@ -13,10 +13,10 @@ const createUnionPropType = ( keys: string[] ): PropType =>
13
13
  } ) as PropType;
14
14
 
15
15
  describe( 'isInlineEditingAllowed', () => {
16
- it( 'should allow inline editing for html-v2 prop values', () => {
16
+ it( 'should allow inline editing for html-v3 prop values', () => {
17
17
  expect(
18
18
  isInlineEditingAllowed( {
19
- rawValue: { $$type: 'html-v2', value: { content: 'Hello', children: [] } },
19
+ rawValue: { $$type: 'html-v3', value: { content: { $$type: 'string', value: 'Hello' }, children: [] } },
20
20
  propTypeFromSchema: null,
21
21
  } )
22
22
  ).toBe( true );
@@ -40,11 +40,11 @@ describe( 'isInlineEditingAllowed', () => {
40
40
  ).toBe( false );
41
41
  } );
42
42
 
43
- it( 'should allow when value is unset but schema key is html-v2', () => {
43
+ it( 'should allow when value is unset but schema key is html-v3', () => {
44
44
  expect(
45
45
  isInlineEditingAllowed( {
46
46
  rawValue: undefined,
47
- propTypeFromSchema: createPlainPropType( 'html-v2' ),
47
+ propTypeFromSchema: createPlainPropType( 'html-v3' ),
48
48
  } )
49
49
  ).toBe( true );
50
50
  } );
@@ -67,16 +67,16 @@ describe( 'isInlineEditingAllowed', () => {
67
67
  ).toBe( false );
68
68
  } );
69
69
 
70
- it( 'should allow when value is unset and union schema includes html-v2', () => {
70
+ it( 'should allow when value is unset and union schema includes html-v3', () => {
71
71
  expect(
72
72
  isInlineEditingAllowed( {
73
73
  rawValue: undefined,
74
- propTypeFromSchema: createUnionPropType( [ 'dynamic', 'html-v2' ] ),
74
+ propTypeFromSchema: createUnionPropType( [ 'dynamic', 'html-v3' ] ),
75
75
  } )
76
76
  ).toBe( true );
77
77
  } );
78
78
 
79
- it( 'should disallow when value is unset and union schema does not include html-v2/string', () => {
79
+ it( 'should disallow when value is unset and union schema does not include html-v3/string', () => {
80
80
  expect(
81
81
  isInlineEditingAllowed( {
82
82
  rawValue: undefined,