@elementor/editor-canvas 3.33.0-99 → 3.34.2
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.d.mts +133 -10
- package/dist/index.d.ts +133 -10
- package/dist/index.js +1413 -212
- package/dist/index.mjs +1399 -180
- package/package.json +18 -14
- package/src/__tests__/settings-props-resolver.test.ts +0 -40
- package/src/__tests__/styles-prop-resolver.test.ts +13 -0
- package/src/components/__tests__/__snapshots__/style-renderer.test.tsx.snap +2 -6
- package/src/components/__tests__/elements-overlays.test.tsx +96 -12
- package/src/components/__tests__/inline-editor-overlay.test.tsx +245 -0
- package/src/components/__tests__/style-renderer.test.tsx +2 -2
- package/src/components/elements-overlays.tsx +33 -10
- package/src/components/inline-editor-overlay.tsx +79 -0
- package/src/components/interactions-renderer.tsx +33 -0
- package/src/components/{element-overlay.tsx → outline-overlay.tsx} +8 -7
- package/src/components/style-renderer.tsx +2 -4
- package/src/hooks/__tests__/use-has-overlapping.test.ts +187 -0
- package/src/hooks/use-floating-on-element.ts +11 -8
- package/src/hooks/use-has-overlapping.ts +21 -0
- package/src/hooks/use-interactions-items.ts +108 -0
- package/src/hooks/use-style-items.ts +34 -8
- package/src/index.ts +9 -0
- package/src/init-settings-transformers.ts +4 -0
- package/src/init.tsx +18 -0
- package/src/legacy/create-templated-element-type.ts +67 -42
- package/src/legacy/init-legacy-views.ts +27 -5
- package/src/legacy/types.ts +44 -4
- package/src/mcp/canvas-mcp.ts +17 -0
- package/src/mcp/mcp-description.ts +40 -0
- package/src/mcp/resources/widgets-schema-resource.ts +173 -0
- package/src/mcp/tools/build-composition/prompt.ts +128 -0
- package/src/mcp/tools/build-composition/schema.ts +31 -0
- package/src/mcp/tools/build-composition/tool.ts +163 -0
- package/src/mcp/tools/configure-element/prompt.ts +93 -0
- package/src/mcp/tools/configure-element/schema.ts +25 -0
- package/src/mcp/tools/configure-element/tool.ts +67 -0
- package/src/mcp/tools/get-element-config/tool.ts +69 -0
- package/src/mcp/utils/do-update-element-property.ts +129 -0
- package/src/mcp/utils/generate-available-tags.ts +23 -0
- package/src/renderers/__tests__/__snapshots__/create-styles-renderer.test.ts.snap +2 -0
- package/src/renderers/__tests__/create-styles-renderer.test.ts +25 -0
- package/src/renderers/create-props-resolver.ts +8 -1
- package/src/renderers/create-styles-renderer.ts +20 -9
- package/src/renderers/errors.ts +6 -0
- package/src/sync/drag-element-from-panel.ts +49 -0
- package/src/sync/types.ts +32 -1
- package/src/transformers/settings/__tests__/attributes-transformer.test.ts +15 -0
- package/src/transformers/settings/__tests__/classes-transformer.test.ts +83 -0
- package/src/transformers/settings/attributes-transformer.ts +1 -23
- package/src/transformers/settings/classes-transformer.ts +21 -21
- package/src/transformers/settings/date-time-transformer.ts +12 -0
- package/src/transformers/settings/query-transformer.ts +10 -0
- package/src/transformers/styles/__tests__/transform-origin-transformer.test.ts +24 -0
- package/src/transformers/styles/__tests__/transition-transformer.test.ts +52 -0
- package/src/transformers/styles/background-transformer.ts +3 -1
- package/src/transformers/styles/transform-origin-transformer.ts +12 -2
- package/src/transformers/styles/transition-transformer.ts +34 -4
- package/src/types/element-overlay.ts +18 -0
- package/src/utils/inline-editing-utils.ts +43 -0
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
// src/init.tsx
|
|
2
2
|
import { injectIntoLogic, injectIntoTop } from "@elementor/editor";
|
|
3
|
+
import { init as initInteractionsRepository } from "@elementor/editor-interactions";
|
|
4
|
+
import { getMCPByDomain } from "@elementor/editor-mcp";
|
|
3
5
|
|
|
4
6
|
// src/components/classes-rename.tsx
|
|
5
7
|
import { useEffect } from "react";
|
|
@@ -44,24 +46,108 @@ var renameClass = (oldClassName, newClassName) => {
|
|
|
44
46
|
};
|
|
45
47
|
|
|
46
48
|
// src/components/elements-overlays.tsx
|
|
47
|
-
import * as
|
|
49
|
+
import * as React3 from "react";
|
|
48
50
|
import { getElements, useSelectedElement } from "@elementor/editor-elements";
|
|
49
51
|
import {
|
|
50
52
|
__privateUseIsRouteActive as useIsRouteActive,
|
|
51
53
|
__privateUseListenTo as useListenTo,
|
|
54
|
+
isExperimentActive,
|
|
52
55
|
useEditMode,
|
|
53
56
|
windowEvent
|
|
54
57
|
} from "@elementor/editor-v1-adapters";
|
|
55
58
|
|
|
56
|
-
// src/
|
|
59
|
+
// src/utils/inline-editing-utils.ts
|
|
60
|
+
import { getContainer, getElementType } from "@elementor/editor-elements";
|
|
61
|
+
var WIDGET_PROPERTY_MAP = {
|
|
62
|
+
"e-heading": "title",
|
|
63
|
+
"e-paragraph": "paragraph"
|
|
64
|
+
};
|
|
65
|
+
var getHtmlPropertyName = (container) => {
|
|
66
|
+
const widgetType = container?.model?.get("widgetType") ?? container?.model?.get("elType");
|
|
67
|
+
if (!widgetType) {
|
|
68
|
+
return "";
|
|
69
|
+
}
|
|
70
|
+
if (WIDGET_PROPERTY_MAP[widgetType]) {
|
|
71
|
+
return WIDGET_PROPERTY_MAP[widgetType];
|
|
72
|
+
}
|
|
73
|
+
const propsSchema = getElementType(widgetType)?.propsSchema;
|
|
74
|
+
if (!propsSchema) {
|
|
75
|
+
return "";
|
|
76
|
+
}
|
|
77
|
+
const entry = Object.entries(propsSchema).find(([, propType]) => propType.key === "html");
|
|
78
|
+
return entry?.[0] ?? "";
|
|
79
|
+
};
|
|
80
|
+
var hasInlineEditableProperty = (containerId) => {
|
|
81
|
+
const container = getContainer(containerId);
|
|
82
|
+
const widgetType = container?.model?.get("widgetType") ?? container?.model?.get("elType");
|
|
83
|
+
if (!widgetType) {
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
return widgetType in WIDGET_PROPERTY_MAP;
|
|
87
|
+
};
|
|
88
|
+
var getInlineEditablePropertyName = (container) => {
|
|
89
|
+
return getHtmlPropertyName(container);
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
// src/components/inline-editor-overlay.tsx
|
|
93
|
+
import * as React2 from "react";
|
|
94
|
+
import { InlineEditor } from "@elementor/editor-controls";
|
|
95
|
+
import { getContainer as getContainer2, updateElementSettings, useElementSetting } from "@elementor/editor-elements";
|
|
96
|
+
import { htmlPropTypeUtil } from "@elementor/editor-props";
|
|
97
|
+
import { Box as Box2 } from "@elementor/ui";
|
|
98
|
+
import { debounce } from "@elementor/utils";
|
|
99
|
+
import { FloatingPortal as FloatingPortal2 } from "@floating-ui/react";
|
|
100
|
+
|
|
101
|
+
// src/hooks/use-floating-on-element.ts
|
|
102
|
+
import { useEffect as useEffect2, useState } from "react";
|
|
103
|
+
import { autoUpdate, offset, size, useFloating } from "@floating-ui/react";
|
|
104
|
+
function useFloatingOnElement({ element, isSelected }) {
|
|
105
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
106
|
+
const sizeModifier = 2;
|
|
107
|
+
const { refs, floatingStyles, context } = useFloating({
|
|
108
|
+
// Must be controlled for interactions (like hover) to work.
|
|
109
|
+
open: isOpen || isSelected,
|
|
110
|
+
onOpenChange: setIsOpen,
|
|
111
|
+
whileElementsMounted: autoUpdate,
|
|
112
|
+
middleware: [
|
|
113
|
+
// Match the floating element's size to the reference element.
|
|
114
|
+
size(() => {
|
|
115
|
+
return {
|
|
116
|
+
apply({ elements, rects }) {
|
|
117
|
+
Object.assign(elements.floating.style, {
|
|
118
|
+
width: `${rects.reference.width + sizeModifier}px`,
|
|
119
|
+
height: `${rects.reference.height + sizeModifier}px`
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
}),
|
|
124
|
+
// Center the floating element on the reference element.
|
|
125
|
+
offset(({ rects }) => -rects.reference.height / 2 - rects.floating.height / 2)
|
|
126
|
+
]
|
|
127
|
+
});
|
|
128
|
+
useEffect2(() => {
|
|
129
|
+
refs.setReference(element);
|
|
130
|
+
}, [element, refs]);
|
|
131
|
+
return {
|
|
132
|
+
isVisible: isOpen || isSelected,
|
|
133
|
+
context,
|
|
134
|
+
floating: {
|
|
135
|
+
setRef: refs.setFloating,
|
|
136
|
+
ref: refs.floating,
|
|
137
|
+
styles: floatingStyles
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// src/components/outline-overlay.tsx
|
|
57
143
|
import * as React from "react";
|
|
58
144
|
import { Box, styled } from "@elementor/ui";
|
|
59
145
|
import { FloatingPortal, useHover, useInteractions } from "@floating-ui/react";
|
|
60
146
|
|
|
61
147
|
// src/hooks/use-bind-react-props-to-element.ts
|
|
62
|
-
import { useEffect as
|
|
148
|
+
import { useEffect as useEffect3 } from "react";
|
|
63
149
|
function useBindReactPropsToElement(element, getProps) {
|
|
64
|
-
|
|
150
|
+
useEffect3(() => {
|
|
65
151
|
const el = element;
|
|
66
152
|
const { events, attrs } = groupProps(getProps());
|
|
67
153
|
events.forEach(([eventName, listener]) => el.addEventListener(eventName, listener));
|
|
@@ -92,45 +178,24 @@ function groupProps(props) {
|
|
|
92
178
|
);
|
|
93
179
|
}
|
|
94
180
|
|
|
95
|
-
// src/hooks/use-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
height: `${rects.reference.height + 2}px`
|
|
112
|
-
});
|
|
113
|
-
}
|
|
114
|
-
}),
|
|
115
|
-
// Center the floating element on the reference element.
|
|
116
|
-
offset(({ rects }) => -rects.reference.height / 2 - rects.floating.height / 2)
|
|
117
|
-
]
|
|
118
|
-
});
|
|
119
|
-
useEffect3(() => {
|
|
120
|
-
refs.setReference(element);
|
|
121
|
-
}, [element, refs]);
|
|
122
|
-
return {
|
|
123
|
-
isVisible: isOpen || isSelected,
|
|
124
|
-
context,
|
|
125
|
-
floating: {
|
|
126
|
-
setRef: refs.setFloating,
|
|
127
|
-
ref: refs.floating,
|
|
128
|
-
styles: floatingStyles
|
|
129
|
-
}
|
|
130
|
-
};
|
|
131
|
-
}
|
|
181
|
+
// src/hooks/use-has-overlapping.ts
|
|
182
|
+
var possibleOverlappingSelectors = [".e-off-canvas"];
|
|
183
|
+
var useHasOverlapping = () => {
|
|
184
|
+
const preview = window.elementor?.$preview?.[0];
|
|
185
|
+
if (!preview) {
|
|
186
|
+
return false;
|
|
187
|
+
}
|
|
188
|
+
const hasOverlapping = possibleOverlappingSelectors.map((selector) => Array.from(preview?.contentWindow?.document.body.querySelectorAll(selector) ?? [])).flat().some(
|
|
189
|
+
(elem) => elem.checkVisibility({
|
|
190
|
+
opacityProperty: true,
|
|
191
|
+
visibilityProperty: true,
|
|
192
|
+
contentVisibilityAuto: true
|
|
193
|
+
})
|
|
194
|
+
);
|
|
195
|
+
return hasOverlapping;
|
|
196
|
+
};
|
|
132
197
|
|
|
133
|
-
// src/components/
|
|
198
|
+
// src/components/outline-overlay.tsx
|
|
134
199
|
var CANVAS_WRAPPER_ID = "elementor-preview-responsive-wrapper";
|
|
135
200
|
var OverlayBox = styled(Box, {
|
|
136
201
|
shouldForwardProp: (prop) => prop !== "isSelected" && prop !== "isSmallerOffset"
|
|
@@ -139,12 +204,13 @@ var OverlayBox = styled(Box, {
|
|
|
139
204
|
outlineOffset: isSelected && !isSmallerOffset ? "-2px" : "-1px",
|
|
140
205
|
pointerEvents: "none"
|
|
141
206
|
}));
|
|
142
|
-
|
|
207
|
+
var OutlineOverlay = ({ element, isSelected, id }) => {
|
|
143
208
|
const { context, floating, isVisible } = useFloatingOnElement({ element, isSelected });
|
|
144
209
|
const { getFloatingProps, getReferenceProps } = useInteractions([useHover(context)]);
|
|
210
|
+
const hasOverlapping = useHasOverlapping();
|
|
145
211
|
useBindReactPropsToElement(element, getReferenceProps);
|
|
146
212
|
const isSmallerOffset = element.offsetHeight <= 1;
|
|
147
|
-
return isVisible && /* @__PURE__ */ React.createElement(FloatingPortal, { id: CANVAS_WRAPPER_ID }, /* @__PURE__ */ React.createElement(
|
|
213
|
+
return isVisible && !hasOverlapping && /* @__PURE__ */ React.createElement(FloatingPortal, { id: CANVAS_WRAPPER_ID }, /* @__PURE__ */ React.createElement(
|
|
148
214
|
OverlayBox,
|
|
149
215
|
{
|
|
150
216
|
ref: floating.setRef,
|
|
@@ -156,9 +222,75 @@ function ElementOverlay({ element, isSelected, id }) {
|
|
|
156
222
|
...getFloatingProps()
|
|
157
223
|
}
|
|
158
224
|
));
|
|
159
|
-
}
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
// src/components/inline-editor-overlay.tsx
|
|
228
|
+
var OVERLAY_Z_INDEX = 1e3;
|
|
229
|
+
var DEBOUNCE_DELAY = 100;
|
|
230
|
+
var InlineEditorOverlay = ({ element, isSelected, id }) => {
|
|
231
|
+
const { floating, isVisible } = useFloatingOnElement({ element, isSelected });
|
|
232
|
+
const propertyName = React2.useMemo(() => {
|
|
233
|
+
const container = getContainer2(id);
|
|
234
|
+
return getInlineEditablePropertyName(container);
|
|
235
|
+
}, [id]);
|
|
236
|
+
const contentProp = useElementSetting(id, propertyName);
|
|
237
|
+
const value = React2.useMemo(() => htmlPropTypeUtil.extract(contentProp) || "", [contentProp]);
|
|
238
|
+
const debouncedUpdateRef = React2.useRef(null);
|
|
239
|
+
const lastValueRef = React2.useRef("");
|
|
240
|
+
React2.useEffect(() => {
|
|
241
|
+
debouncedUpdateRef.current = debounce((newValue) => {
|
|
242
|
+
const textContent = newValue.replace(/<[^>]*>/g, "").trim();
|
|
243
|
+
const valueToSave = textContent === "" ? " " : newValue;
|
|
244
|
+
updateElementSettings({
|
|
245
|
+
id,
|
|
246
|
+
props: {
|
|
247
|
+
[propertyName]: htmlPropTypeUtil.create(valueToSave)
|
|
248
|
+
},
|
|
249
|
+
withHistory: true
|
|
250
|
+
});
|
|
251
|
+
}, DEBOUNCE_DELAY);
|
|
252
|
+
return () => {
|
|
253
|
+
debouncedUpdateRef.current?.cancel?.();
|
|
254
|
+
};
|
|
255
|
+
}, [id, propertyName]);
|
|
256
|
+
const handleValueChange = React2.useCallback((newValue) => {
|
|
257
|
+
lastValueRef.current = newValue;
|
|
258
|
+
debouncedUpdateRef.current?.(newValue);
|
|
259
|
+
}, []);
|
|
260
|
+
React2.useEffect(() => {
|
|
261
|
+
if (!isVisible && debouncedUpdateRef.current?.pending?.()) {
|
|
262
|
+
debouncedUpdateRef.current.flush(lastValueRef.current);
|
|
263
|
+
}
|
|
264
|
+
}, [isVisible]);
|
|
265
|
+
if (!isVisible) {
|
|
266
|
+
return null;
|
|
267
|
+
}
|
|
268
|
+
return /* @__PURE__ */ React2.createElement(FloatingPortal2, { id: CANVAS_WRAPPER_ID }, /* @__PURE__ */ React2.createElement(
|
|
269
|
+
Box2,
|
|
270
|
+
{
|
|
271
|
+
ref: floating.setRef,
|
|
272
|
+
style: {
|
|
273
|
+
...floating.styles,
|
|
274
|
+
zIndex: OVERLAY_Z_INDEX,
|
|
275
|
+
pointerEvents: "auto"
|
|
276
|
+
}
|
|
277
|
+
},
|
|
278
|
+
/* @__PURE__ */ React2.createElement(InlineEditor, { value, setValue: handleValueChange, showToolbar: isSelected })
|
|
279
|
+
));
|
|
280
|
+
};
|
|
160
281
|
|
|
161
282
|
// src/components/elements-overlays.tsx
|
|
283
|
+
var ELEMENTS_DATA_ATTR = "atomic";
|
|
284
|
+
var overlayRegistry = [
|
|
285
|
+
{
|
|
286
|
+
component: OutlineOverlay,
|
|
287
|
+
shouldRender: () => true
|
|
288
|
+
},
|
|
289
|
+
{
|
|
290
|
+
component: InlineEditorOverlay,
|
|
291
|
+
shouldRender: ({ id, isSelected }) => isSelected && hasInlineEditableProperty(id) && isExperimentActive("v4-inline-text-editing")
|
|
292
|
+
}
|
|
293
|
+
];
|
|
162
294
|
function ElementsOverlays() {
|
|
163
295
|
const selected = useSelectedElement();
|
|
164
296
|
const elements = useElementsDom();
|
|
@@ -166,9 +298,16 @@ function ElementsOverlays() {
|
|
|
166
298
|
const isEditMode = currentEditMode === "edit";
|
|
167
299
|
const isKitRouteActive = useIsRouteActive("panel/global");
|
|
168
300
|
const isActive = isEditMode && !isKitRouteActive;
|
|
169
|
-
|
|
301
|
+
if (!isActive) {
|
|
302
|
+
return null;
|
|
303
|
+
}
|
|
304
|
+
return elements.map(([id, element]) => {
|
|
305
|
+
const isSelected = selected.element?.id === id;
|
|
306
|
+
return overlayRegistry.map(
|
|
307
|
+
({ shouldRender, component: Overlay }, index) => shouldRender({ id, element, isSelected }) && /* @__PURE__ */ React3.createElement(Overlay, { key: `${id}-${index}`, id, element, isSelected })
|
|
308
|
+
);
|
|
309
|
+
});
|
|
170
310
|
}
|
|
171
|
-
var ELEMENTS_DATA_ATTR = "atomic";
|
|
172
311
|
function useElementsDom() {
|
|
173
312
|
return useListenTo(
|
|
174
313
|
[windowEvent("elementor/editor/element-rendered"), windowEvent("elementor/editor/element-destroyed")],
|
|
@@ -178,13 +317,100 @@ function useElementsDom() {
|
|
|
178
317
|
);
|
|
179
318
|
}
|
|
180
319
|
|
|
181
|
-
// src/components/
|
|
182
|
-
import * as
|
|
183
|
-
import { __privateUseListenTo as
|
|
320
|
+
// src/components/interactions-renderer.tsx
|
|
321
|
+
import * as React4 from "react";
|
|
322
|
+
import { __privateUseListenTo as useListenTo2, commandEndEvent } from "@elementor/editor-v1-adapters";
|
|
184
323
|
import { Portal } from "@elementor/ui";
|
|
185
324
|
|
|
186
|
-
// src/hooks/use-
|
|
187
|
-
import {
|
|
325
|
+
// src/hooks/use-interactions-items.ts
|
|
326
|
+
import { useEffect as useEffect6, useMemo as useMemo2, useState as useState2 } from "react";
|
|
327
|
+
import { interactionsRepository } from "@elementor/editor-interactions";
|
|
328
|
+
import { registerDataHook } from "@elementor/editor-v1-adapters";
|
|
329
|
+
|
|
330
|
+
// src/hooks/use-on-mount.ts
|
|
331
|
+
import { useEffect as useEffect5, useRef as useRef2 } from "react";
|
|
332
|
+
function useOnMount(cb) {
|
|
333
|
+
const mounted = useRef2(false);
|
|
334
|
+
useEffect5(() => {
|
|
335
|
+
if (!mounted.current) {
|
|
336
|
+
mounted.current = true;
|
|
337
|
+
cb();
|
|
338
|
+
}
|
|
339
|
+
}, []);
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
// src/hooks/use-interactions-items.ts
|
|
343
|
+
function useInteractionsItems() {
|
|
344
|
+
const [interactionItems, setInteractionItems] = useState2({});
|
|
345
|
+
const providerAndSubscribers = useMemo2(() => {
|
|
346
|
+
try {
|
|
347
|
+
const providers = interactionsRepository.getProviders();
|
|
348
|
+
const mapped = providers.map((provider) => {
|
|
349
|
+
return {
|
|
350
|
+
provider,
|
|
351
|
+
subscriber: createProviderSubscriber({
|
|
352
|
+
provider,
|
|
353
|
+
setInteractionItems
|
|
354
|
+
})
|
|
355
|
+
};
|
|
356
|
+
});
|
|
357
|
+
return mapped;
|
|
358
|
+
} catch {
|
|
359
|
+
return [];
|
|
360
|
+
}
|
|
361
|
+
}, []);
|
|
362
|
+
useEffect6(() => {
|
|
363
|
+
if (providerAndSubscribers.length === 0) {
|
|
364
|
+
return;
|
|
365
|
+
}
|
|
366
|
+
const unsubscribes = providerAndSubscribers.map(({ provider, subscriber }) => {
|
|
367
|
+
const safeSubscriber = () => {
|
|
368
|
+
try {
|
|
369
|
+
subscriber();
|
|
370
|
+
} catch {
|
|
371
|
+
}
|
|
372
|
+
};
|
|
373
|
+
const unsubscribe = provider.subscribe(safeSubscriber);
|
|
374
|
+
return unsubscribe;
|
|
375
|
+
});
|
|
376
|
+
return () => {
|
|
377
|
+
unsubscribes.forEach((unsubscribe) => unsubscribe());
|
|
378
|
+
};
|
|
379
|
+
}, [providerAndSubscribers]);
|
|
380
|
+
useOnMount(() => {
|
|
381
|
+
if (providerAndSubscribers.length === 0) {
|
|
382
|
+
return;
|
|
383
|
+
}
|
|
384
|
+
registerDataHook("after", "editor/documents/attach-preview", async () => {
|
|
385
|
+
providerAndSubscribers.forEach(({ subscriber }) => {
|
|
386
|
+
try {
|
|
387
|
+
subscriber();
|
|
388
|
+
} catch {
|
|
389
|
+
}
|
|
390
|
+
});
|
|
391
|
+
});
|
|
392
|
+
});
|
|
393
|
+
return useMemo2(() => {
|
|
394
|
+
const result = Object.values(interactionItems).sort(sortByProviderPriority).flatMap(({ items }) => items);
|
|
395
|
+
return result;
|
|
396
|
+
}, [interactionItems]);
|
|
397
|
+
}
|
|
398
|
+
function sortByProviderPriority({ provider: providerA }, { provider: providerB }) {
|
|
399
|
+
return providerA.priority - providerB.priority;
|
|
400
|
+
}
|
|
401
|
+
function createProviderSubscriber({ provider, setInteractionItems }) {
|
|
402
|
+
return () => {
|
|
403
|
+
try {
|
|
404
|
+
const items = provider.actions.all();
|
|
405
|
+
const providerKey = provider.getKey();
|
|
406
|
+
setInteractionItems((prev) => ({
|
|
407
|
+
...prev,
|
|
408
|
+
[providerKey]: { provider, items }
|
|
409
|
+
}));
|
|
410
|
+
} catch {
|
|
411
|
+
}
|
|
412
|
+
};
|
|
413
|
+
}
|
|
188
414
|
|
|
189
415
|
// src/sync/get-canvas-iframe-document.ts
|
|
190
416
|
function getCanvasIframeDocument() {
|
|
@@ -192,13 +418,42 @@ function getCanvasIframeDocument() {
|
|
|
192
418
|
return extendedWindow.elementor?.$preview?.[0]?.contentDocument;
|
|
193
419
|
}
|
|
194
420
|
|
|
421
|
+
// src/components/interactions-renderer.tsx
|
|
422
|
+
function InteractionsRenderer() {
|
|
423
|
+
const container = usePortalContainer();
|
|
424
|
+
const interactionItems = useInteractionsItems();
|
|
425
|
+
if (!container) {
|
|
426
|
+
return null;
|
|
427
|
+
}
|
|
428
|
+
const interactionsData = JSON.stringify(Array.isArray(interactionItems) ? interactionItems : []);
|
|
429
|
+
return /* @__PURE__ */ React4.createElement(Portal, { container }, /* @__PURE__ */ React4.createElement(
|
|
430
|
+
"script",
|
|
431
|
+
{
|
|
432
|
+
type: "application/json",
|
|
433
|
+
"data-e-interactions": "true",
|
|
434
|
+
dangerouslySetInnerHTML: {
|
|
435
|
+
__html: interactionsData
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
));
|
|
439
|
+
}
|
|
440
|
+
function usePortalContainer() {
|
|
441
|
+
return useListenTo2(commandEndEvent("editor/documents/attach-preview"), () => getCanvasIframeDocument()?.head);
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
// src/components/style-renderer.tsx
|
|
445
|
+
import * as React5 from "react";
|
|
446
|
+
import { __privateUseListenTo as useListenTo4, commandEndEvent as commandEndEvent3 } from "@elementor/editor-v1-adapters";
|
|
447
|
+
import { Portal as Portal2 } from "@elementor/ui";
|
|
448
|
+
|
|
195
449
|
// src/hooks/use-documents-css-links.ts
|
|
450
|
+
import { __privateUseListenTo as useListenTo3, commandEndEvent as commandEndEvent2 } from "@elementor/editor-v1-adapters";
|
|
196
451
|
var REMOVED_ATTR = "data-e-removed";
|
|
197
452
|
var DOCUMENT_WRAPPER_ATTR = "data-elementor-id";
|
|
198
453
|
var CSS_LINK_ID_PREFIX = "elementor-post-";
|
|
199
454
|
var CSS_LINK_ID_SUFFIX = "-css";
|
|
200
455
|
function useDocumentsCssLinks() {
|
|
201
|
-
return
|
|
456
|
+
return useListenTo3(commandEndEvent2("editor/documents/attach-preview"), () => {
|
|
202
457
|
const iframeDocument = getCanvasIframeDocument();
|
|
203
458
|
if (!iframeDocument) {
|
|
204
459
|
return [];
|
|
@@ -239,10 +494,11 @@ function getLinkAttrs(el) {
|
|
|
239
494
|
}
|
|
240
495
|
|
|
241
496
|
// src/hooks/use-style-items.ts
|
|
242
|
-
import { useEffect as
|
|
497
|
+
import { useEffect as useEffect7, useMemo as useMemo5, useState as useState3 } from "react";
|
|
243
498
|
import { getBreakpoints } from "@elementor/editor-responsive";
|
|
499
|
+
import { isClassState as isClassState2 } from "@elementor/editor-styles";
|
|
244
500
|
import { stylesRepository as stylesRepository2 } from "@elementor/editor-styles-repository";
|
|
245
|
-
import { registerDataHook } from "@elementor/editor-v1-adapters";
|
|
501
|
+
import { registerDataHook as registerDataHook2 } from "@elementor/editor-v1-adapters";
|
|
246
502
|
|
|
247
503
|
// src/utils/abort-previous-runs.ts
|
|
248
504
|
function abortPreviousRuns(cb) {
|
|
@@ -275,25 +531,14 @@ function signalizedProcess(signal, steps = []) {
|
|
|
275
531
|
};
|
|
276
532
|
}
|
|
277
533
|
|
|
278
|
-
// src/hooks/use-on-mount.ts
|
|
279
|
-
import { useEffect as useEffect4, useRef } from "react";
|
|
280
|
-
function useOnMount(cb) {
|
|
281
|
-
const mounted = useRef(false);
|
|
282
|
-
useEffect4(() => {
|
|
283
|
-
if (!mounted.current) {
|
|
284
|
-
mounted.current = true;
|
|
285
|
-
cb();
|
|
286
|
-
}
|
|
287
|
-
}, []);
|
|
288
|
-
}
|
|
289
|
-
|
|
290
534
|
// src/hooks/use-style-prop-resolver.ts
|
|
291
|
-
import { useMemo } from "react";
|
|
535
|
+
import { useMemo as useMemo3 } from "react";
|
|
292
536
|
import { getStylesSchema } from "@elementor/editor-styles";
|
|
293
537
|
|
|
294
538
|
// src/renderers/create-props-resolver.ts
|
|
295
539
|
import {
|
|
296
|
-
isTransformable
|
|
540
|
+
isTransformable,
|
|
541
|
+
migratePropValue
|
|
297
542
|
} from "@elementor/editor-props";
|
|
298
543
|
|
|
299
544
|
// src/renderers/multi-props.ts
|
|
@@ -313,10 +558,10 @@ var getMultiPropsValue = (multiProps) => {
|
|
|
313
558
|
// src/renderers/create-props-resolver.ts
|
|
314
559
|
var TRANSFORM_DEPTH_LIMIT = 3;
|
|
315
560
|
function createPropsResolver({ transformers, schema: initialSchema, onPropResolve }) {
|
|
316
|
-
async function resolve({ props, schema, signal }) {
|
|
317
|
-
|
|
561
|
+
async function resolve({ props, schema: schema2, signal }) {
|
|
562
|
+
schema2 = schema2 ?? initialSchema;
|
|
318
563
|
const promises = Promise.all(
|
|
319
|
-
Object.entries(
|
|
564
|
+
Object.entries(schema2).map(async ([key, type]) => {
|
|
320
565
|
const value = props[key] ?? type.default;
|
|
321
566
|
const transformed = await transform({ value, key, type, signal });
|
|
322
567
|
onPropResolve?.({ key, value: transformed });
|
|
@@ -341,6 +586,10 @@ function createPropsResolver({ transformers, schema: initialSchema, onPropResolv
|
|
|
341
586
|
if (value.disabled === true) {
|
|
342
587
|
return null;
|
|
343
588
|
}
|
|
589
|
+
value = migratePropValue(value, type);
|
|
590
|
+
if (!isTransformable(value)) {
|
|
591
|
+
return value;
|
|
592
|
+
}
|
|
344
593
|
if (type.kind === "union") {
|
|
345
594
|
type = type.prop_types[value.$$type];
|
|
346
595
|
if (!type) {
|
|
@@ -412,7 +661,7 @@ var enqueueFont = (fontFamily, context = "preview") => {
|
|
|
412
661
|
|
|
413
662
|
// src/hooks/use-style-prop-resolver.ts
|
|
414
663
|
function useStylePropResolver() {
|
|
415
|
-
return
|
|
664
|
+
return useMemo3(() => {
|
|
416
665
|
return createPropsResolver({
|
|
417
666
|
transformers: styleTransformersRegistry,
|
|
418
667
|
schema: getStylesSchema(),
|
|
@@ -427,11 +676,14 @@ function useStylePropResolver() {
|
|
|
427
676
|
}
|
|
428
677
|
|
|
429
678
|
// src/hooks/use-style-renderer.ts
|
|
430
|
-
import { useMemo as
|
|
679
|
+
import { useMemo as useMemo4 } from "react";
|
|
431
680
|
import { useBreakpointsMap } from "@elementor/editor-responsive";
|
|
432
681
|
|
|
433
682
|
// src/renderers/create-styles-renderer.ts
|
|
434
|
-
import {
|
|
683
|
+
import {
|
|
684
|
+
isClassState,
|
|
685
|
+
isPseudoState
|
|
686
|
+
} from "@elementor/editor-styles";
|
|
435
687
|
import { decodeString } from "@elementor/utils";
|
|
436
688
|
|
|
437
689
|
// src/renderers/errors.ts
|
|
@@ -440,6 +692,10 @@ var UnknownStyleTypeError = createError({
|
|
|
440
692
|
code: "unknown_style_type",
|
|
441
693
|
message: "Unknown style type"
|
|
442
694
|
});
|
|
695
|
+
var UnknownStyleStateError = createError({
|
|
696
|
+
code: "unknown_style_state",
|
|
697
|
+
message: "Unknown style state"
|
|
698
|
+
});
|
|
443
699
|
|
|
444
700
|
// src/renderers/create-styles-renderer.ts
|
|
445
701
|
var SELECTORS_MAP = {
|
|
@@ -457,7 +713,8 @@ function createStylesRenderer({ resolve, breakpoints, selectorPrefix = "" }) {
|
|
|
457
713
|
return {
|
|
458
714
|
id: style.id,
|
|
459
715
|
breakpoint: style?.variants[0]?.meta?.breakpoint || "desktop",
|
|
460
|
-
value: variantsCss.join("")
|
|
716
|
+
value: variantsCss.join(""),
|
|
717
|
+
state: style?.variants[0]?.meta?.state || null
|
|
461
718
|
};
|
|
462
719
|
});
|
|
463
720
|
return await Promise.all(stylesCssPromises);
|
|
@@ -473,7 +730,18 @@ function createStyleWrapper(value = "", wrapper) {
|
|
|
473
730
|
return createStyleWrapper(`${value}${symbol}${cssName}`, wrapper);
|
|
474
731
|
},
|
|
475
732
|
withPrefix: (prefix) => createStyleWrapper([prefix, value].filter(Boolean).join(" "), wrapper),
|
|
476
|
-
withState: (state) =>
|
|
733
|
+
withState: (state) => {
|
|
734
|
+
if (!state) {
|
|
735
|
+
return createStyleWrapper(value, wrapper);
|
|
736
|
+
}
|
|
737
|
+
if (isClassState(state)) {
|
|
738
|
+
return createStyleWrapper(`${value}.${state}`, wrapper);
|
|
739
|
+
}
|
|
740
|
+
if (isPseudoState(state)) {
|
|
741
|
+
return createStyleWrapper(`${value}:${state}`, wrapper);
|
|
742
|
+
}
|
|
743
|
+
throw new UnknownStyleStateError({ context: { state } });
|
|
744
|
+
},
|
|
477
745
|
withMediaQuery: (breakpoint) => {
|
|
478
746
|
if (!breakpoint?.type) {
|
|
479
747
|
return createStyleWrapper(value, wrapper);
|
|
@@ -501,10 +769,7 @@ async function propsToCss({ props, resolve, signal }) {
|
|
|
501
769
|
}, []).join("");
|
|
502
770
|
}
|
|
503
771
|
function customCssToString(customCss) {
|
|
504
|
-
|
|
505
|
-
return "";
|
|
506
|
-
}
|
|
507
|
-
const decoded = decodeString(customCss.raw);
|
|
772
|
+
const decoded = decodeString(customCss?.raw || "");
|
|
508
773
|
if (!decoded.trim()) {
|
|
509
774
|
return "";
|
|
510
775
|
}
|
|
@@ -515,7 +780,7 @@ function customCssToString(customCss) {
|
|
|
515
780
|
var SELECTOR_PREFIX = ".elementor";
|
|
516
781
|
function useStyleRenderer(resolve) {
|
|
517
782
|
const breakpoints = useBreakpointsMap();
|
|
518
|
-
return
|
|
783
|
+
return useMemo4(() => {
|
|
519
784
|
return createStylesRenderer({
|
|
520
785
|
selectorPrefix: SELECTOR_PREFIX,
|
|
521
786
|
breakpoints,
|
|
@@ -528,12 +793,12 @@ function useStyleRenderer(resolve) {
|
|
|
528
793
|
function useStyleItems() {
|
|
529
794
|
const resolve = useStylePropResolver();
|
|
530
795
|
const renderStyles = useStyleRenderer(resolve);
|
|
531
|
-
const [styleItems, setStyleItems] =
|
|
532
|
-
const providerAndSubscribers =
|
|
796
|
+
const [styleItems, setStyleItems] = useState3({});
|
|
797
|
+
const providerAndSubscribers = useMemo5(() => {
|
|
533
798
|
return stylesRepository2.getProviders().map((provider) => {
|
|
534
799
|
return {
|
|
535
800
|
provider,
|
|
536
|
-
subscriber:
|
|
801
|
+
subscriber: createProviderSubscriber2({
|
|
537
802
|
provider,
|
|
538
803
|
renderStyles,
|
|
539
804
|
setStyleItems
|
|
@@ -541,7 +806,7 @@ function useStyleItems() {
|
|
|
541
806
|
};
|
|
542
807
|
});
|
|
543
808
|
}, [renderStyles]);
|
|
544
|
-
|
|
809
|
+
useEffect7(() => {
|
|
545
810
|
const unsubscribes = providerAndSubscribers.map(
|
|
546
811
|
({ provider, subscriber }) => provider.subscribe(subscriber)
|
|
547
812
|
);
|
|
@@ -550,22 +815,34 @@ function useStyleItems() {
|
|
|
550
815
|
};
|
|
551
816
|
}, [providerAndSubscribers]);
|
|
552
817
|
useOnMount(() => {
|
|
553
|
-
|
|
818
|
+
registerDataHook2("after", "editor/documents/attach-preview", async () => {
|
|
554
819
|
const promises = providerAndSubscribers.map(async ({ subscriber }) => subscriber());
|
|
555
820
|
await Promise.all(promises);
|
|
556
821
|
});
|
|
557
822
|
});
|
|
558
823
|
const breakpointsOrder = getBreakpoints().map((breakpoint) => breakpoint.id);
|
|
559
|
-
return
|
|
560
|
-
() => Object.values(styleItems).sort(
|
|
561
|
-
return breakpointsOrder.indexOf(breakpointA) - breakpointsOrder.indexOf(breakpointB);
|
|
562
|
-
}),
|
|
563
|
-
// eslint-disable-next-line
|
|
824
|
+
return useMemo5(
|
|
825
|
+
() => Object.values(styleItems).sort(sortByProviderPriority2).flatMap(({ items }) => items).sort(sortByStateType).sort(sortByBreakpoint(breakpointsOrder)),
|
|
564
826
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
565
827
|
[styleItems, breakpointsOrder.join("-")]
|
|
566
828
|
);
|
|
567
829
|
}
|
|
568
|
-
function
|
|
830
|
+
function sortByProviderPriority2({ provider: providerA }, { provider: providerB }) {
|
|
831
|
+
return providerA.priority - providerB.priority;
|
|
832
|
+
}
|
|
833
|
+
function sortByBreakpoint(breakpointsOrder) {
|
|
834
|
+
return ({ breakpoint: breakpointA }, { breakpoint: breakpointB }) => breakpointsOrder.indexOf(breakpointA) - breakpointsOrder.indexOf(breakpointB);
|
|
835
|
+
}
|
|
836
|
+
function sortByStateType({ state: stateA }, { state: stateB }) {
|
|
837
|
+
if (isClassState2(stateA) && !isClassState2(stateB)) {
|
|
838
|
+
return -1;
|
|
839
|
+
}
|
|
840
|
+
if (!isClassState2(stateA) && isClassState2(stateB)) {
|
|
841
|
+
return 1;
|
|
842
|
+
}
|
|
843
|
+
return 0;
|
|
844
|
+
}
|
|
845
|
+
function createProviderSubscriber2({ provider, renderStyles, setStyleItems }) {
|
|
569
846
|
return abortPreviousRuns(
|
|
570
847
|
(abortController) => signalizedProcess(abortController.signal).then((_, signal) => {
|
|
571
848
|
const styles = provider.actions.all().map((__5, index, items) => {
|
|
@@ -611,16 +888,16 @@ function createProviderSubscriber({ provider, renderStyles, setStyleItems }) {
|
|
|
611
888
|
|
|
612
889
|
// src/components/style-renderer.tsx
|
|
613
890
|
function StyleRenderer() {
|
|
614
|
-
const container =
|
|
891
|
+
const container = usePortalContainer2();
|
|
615
892
|
const styleItems = useStyleItems();
|
|
616
893
|
const linksAttrs = useDocumentsCssLinks();
|
|
617
894
|
if (!container) {
|
|
618
895
|
return null;
|
|
619
896
|
}
|
|
620
|
-
return /* @__PURE__ */
|
|
897
|
+
return /* @__PURE__ */ React5.createElement(Portal2, { container }, styleItems.map((item, i) => /* @__PURE__ */ React5.createElement("style", { key: `${item.id}-${i}-${item.breakpoint}` }, item.value)), linksAttrs.map((attrs) => /* @__PURE__ */ React5.createElement("link", { ...attrs, key: attrs.id })));
|
|
621
898
|
}
|
|
622
|
-
function
|
|
623
|
-
return
|
|
899
|
+
function usePortalContainer2() {
|
|
900
|
+
return useListenTo4(commandEndEvent3("editor/documents/attach-preview"), () => getCanvasIframeDocument()?.head);
|
|
624
901
|
}
|
|
625
902
|
|
|
626
903
|
// src/settings-transformers-registry.ts
|
|
@@ -632,49 +909,40 @@ function createTransformer(cb) {
|
|
|
632
909
|
}
|
|
633
910
|
|
|
634
911
|
// src/transformers/settings/attributes-transformer.ts
|
|
635
|
-
|
|
636
|
-
const specialChars = {
|
|
637
|
-
"&": "&",
|
|
638
|
-
"<": "<",
|
|
639
|
-
">": ">",
|
|
640
|
-
"'": "'",
|
|
641
|
-
'"': """
|
|
642
|
-
};
|
|
643
|
-
return value.replace(/[&<>'"]/g, (char) => specialChars[char] || char);
|
|
644
|
-
}
|
|
645
|
-
var attributesTransformer = createTransformer((values) => {
|
|
646
|
-
return values.map((value) => {
|
|
647
|
-
if (!value.key || !value.value) {
|
|
648
|
-
return "";
|
|
649
|
-
}
|
|
650
|
-
const escapedValue = escapeHtmlAttribute(value.value);
|
|
651
|
-
return `${value.key}="${escapedValue}"`;
|
|
652
|
-
}).join(" ");
|
|
653
|
-
});
|
|
912
|
+
var attributesTransformer = createTransformer(() => "");
|
|
654
913
|
|
|
655
914
|
// src/transformers/settings/classes-transformer.ts
|
|
656
915
|
import { stylesRepository as stylesRepository3 } from "@elementor/editor-styles-repository";
|
|
916
|
+
function transformClassId(id, cache) {
|
|
917
|
+
if (!cache.has(id)) {
|
|
918
|
+
const provider2 = stylesRepository3.getProviders().find((p) => {
|
|
919
|
+
return p.actions.all().find((style) => style.id === id);
|
|
920
|
+
});
|
|
921
|
+
if (!provider2) {
|
|
922
|
+
return id;
|
|
923
|
+
}
|
|
924
|
+
cache.set(id, provider2.getKey());
|
|
925
|
+
}
|
|
926
|
+
const providerKey = cache.get(id);
|
|
927
|
+
const provider = stylesRepository3.getProviderByKey(providerKey);
|
|
928
|
+
return provider?.actions.resolveCssName(id) ?? id;
|
|
929
|
+
}
|
|
657
930
|
function createClassesTransformer() {
|
|
658
931
|
const cache = /* @__PURE__ */ new Map();
|
|
659
932
|
return createTransformer((value) => {
|
|
660
|
-
return value.map((id) =>
|
|
661
|
-
if (!cache.has(id)) {
|
|
662
|
-
cache.set(id, getCssName(id));
|
|
663
|
-
}
|
|
664
|
-
return cache.get(id);
|
|
665
|
-
}).filter(Boolean);
|
|
666
|
-
});
|
|
667
|
-
}
|
|
668
|
-
function getCssName(id) {
|
|
669
|
-
const provider = stylesRepository3.getProviders().find((p) => {
|
|
670
|
-
return p.actions.all().find((style) => style.id === id);
|
|
933
|
+
return value.map((id) => transformClassId(id, cache)).filter(Boolean);
|
|
671
934
|
});
|
|
672
|
-
if (!provider) {
|
|
673
|
-
return id;
|
|
674
|
-
}
|
|
675
|
-
return provider.actions.resolveCssName(id);
|
|
676
935
|
}
|
|
677
936
|
|
|
937
|
+
// src/transformers/settings/date-time-transformer.ts
|
|
938
|
+
var dateTimeTransformer = createTransformer((values) => {
|
|
939
|
+
return values.map((value) => {
|
|
940
|
+
const date = (value.date || "").trim();
|
|
941
|
+
const time = (value.time || "").trim();
|
|
942
|
+
return !date && !time ? "" : `${date} ${time}`.trim();
|
|
943
|
+
}).join(" ");
|
|
944
|
+
});
|
|
945
|
+
|
|
678
946
|
// src/transformers/settings/link-transformer.ts
|
|
679
947
|
var linkTransformer = createTransformer(({ destination, isTargetBlank }) => {
|
|
680
948
|
return {
|
|
@@ -684,6 +952,11 @@ var linkTransformer = createTransformer(({ destination, isTargetBlank }) => {
|
|
|
684
952
|
};
|
|
685
953
|
});
|
|
686
954
|
|
|
955
|
+
// src/transformers/settings/query-transformer.ts
|
|
956
|
+
var queryTransformer = createTransformer(({ id }) => {
|
|
957
|
+
return id ?? null;
|
|
958
|
+
});
|
|
959
|
+
|
|
687
960
|
// src/transformers/shared/image-src-transformer.ts
|
|
688
961
|
var imageSrcTransformer = createTransformer((value) => ({
|
|
689
962
|
id: value.id ?? null,
|
|
@@ -723,7 +996,7 @@ var plainTransformer = createTransformer((value) => {
|
|
|
723
996
|
|
|
724
997
|
// src/init-settings-transformers.ts
|
|
725
998
|
function initSettingsTransformers() {
|
|
726
|
-
settingsTransformersRegistry.register("classes", createClassesTransformer()).register("link", linkTransformer).register("image", imageTransformer).register("image-src", imageSrcTransformer).register("attributes", attributesTransformer).registerFallback(plainTransformer);
|
|
999
|
+
settingsTransformersRegistry.register("classes", createClassesTransformer()).register("link", linkTransformer).register("query", queryTransformer).register("image", imageTransformer).register("image-src", imageSrcTransformer).register("attributes", attributesTransformer).register("date-time", dateTimeTransformer).registerFallback(plainTransformer);
|
|
727
1000
|
}
|
|
728
1001
|
|
|
729
1002
|
// src/transformers/styles/background-color-overlay-transformer.ts
|
|
@@ -821,10 +1094,11 @@ function getValuesString(items, prop, defaultValue, preventUnification = false)
|
|
|
821
1094
|
|
|
822
1095
|
// src/transformers/styles/background-transformer.ts
|
|
823
1096
|
var backgroundTransformer = createTransformer((value) => {
|
|
824
|
-
const { color = null, "background-overlay": overlays = null } = value;
|
|
1097
|
+
const { color = null, "background-overlay": overlays = null, clip = null } = value;
|
|
825
1098
|
return createMultiPropsValue({
|
|
826
1099
|
...overlays,
|
|
827
|
-
"background-color": color
|
|
1100
|
+
"background-color": color,
|
|
1101
|
+
"background-clip": clip
|
|
828
1102
|
});
|
|
829
1103
|
});
|
|
830
1104
|
|
|
@@ -950,11 +1224,19 @@ var transformMoveTransformer = createTransformer((value) => {
|
|
|
950
1224
|
|
|
951
1225
|
// src/transformers/styles/transform-origin-transformer.ts
|
|
952
1226
|
var EMPTY_VALUE = "0px";
|
|
1227
|
+
var DEFAULT_XY = "50%";
|
|
1228
|
+
var DEFAULT_Z = EMPTY_VALUE;
|
|
953
1229
|
function getVal2(val) {
|
|
954
1230
|
return `${val ?? EMPTY_VALUE}`;
|
|
955
1231
|
}
|
|
956
1232
|
var transformOriginTransformer = createTransformer((value) => {
|
|
957
|
-
|
|
1233
|
+
const x = getVal2(value.x);
|
|
1234
|
+
const y = getVal2(value.y);
|
|
1235
|
+
const z4 = getVal2(value.z);
|
|
1236
|
+
if (x === DEFAULT_XY && y === DEFAULT_XY && z4 === DEFAULT_Z) {
|
|
1237
|
+
return null;
|
|
1238
|
+
}
|
|
1239
|
+
return `${x} ${y} ${z4}`;
|
|
958
1240
|
});
|
|
959
1241
|
|
|
960
1242
|
// src/transformers/styles/transform-rotate-transformer.ts
|
|
@@ -982,17 +1264,36 @@ var transformSkewTransformer = createTransformer((value) => {
|
|
|
982
1264
|
});
|
|
983
1265
|
|
|
984
1266
|
// src/transformers/styles/transition-transformer.ts
|
|
1267
|
+
import { transitionProperties } from "@elementor/editor-controls";
|
|
1268
|
+
var getAllowedProperties = () => {
|
|
1269
|
+
const allowedProperties = /* @__PURE__ */ new Set();
|
|
1270
|
+
transitionProperties.forEach((category) => {
|
|
1271
|
+
category.properties.forEach((property) => {
|
|
1272
|
+
allowedProperties.add(property.value);
|
|
1273
|
+
});
|
|
1274
|
+
});
|
|
1275
|
+
return allowedProperties;
|
|
1276
|
+
};
|
|
985
1277
|
var transitionTransformer = createTransformer((transitionValues) => {
|
|
986
1278
|
if (transitionValues?.length < 1) {
|
|
987
1279
|
return null;
|
|
988
1280
|
}
|
|
989
|
-
|
|
1281
|
+
const allowedProperties = getAllowedProperties();
|
|
1282
|
+
const validTransitions = transitionValues.map((value) => mapToTransitionString(value, allowedProperties)).filter(Boolean);
|
|
1283
|
+
if (validTransitions.length === 0) {
|
|
1284
|
+
return null;
|
|
1285
|
+
}
|
|
1286
|
+
return validTransitions.join(", ");
|
|
990
1287
|
});
|
|
991
|
-
var mapToTransitionString = (value) => {
|
|
1288
|
+
var mapToTransitionString = (value, allowedProperties) => {
|
|
992
1289
|
if (!value.selection || !value.size) {
|
|
993
1290
|
return "";
|
|
994
1291
|
}
|
|
995
|
-
|
|
1292
|
+
const property = value.selection.value;
|
|
1293
|
+
if (!allowedProperties.has(property)) {
|
|
1294
|
+
return "";
|
|
1295
|
+
}
|
|
1296
|
+
return `${property} ${value.size}`;
|
|
996
1297
|
};
|
|
997
1298
|
|
|
998
1299
|
// src/init-style-transformers.ts
|
|
@@ -1153,26 +1454,21 @@ function createElementViewClassDeclaration() {
|
|
|
1153
1454
|
}
|
|
1154
1455
|
|
|
1155
1456
|
// src/legacy/create-templated-element-type.ts
|
|
1156
|
-
function createTemplatedElementType({
|
|
1457
|
+
function createTemplatedElementType({
|
|
1458
|
+
type,
|
|
1459
|
+
renderer,
|
|
1460
|
+
element
|
|
1461
|
+
}) {
|
|
1157
1462
|
const legacyWindow = window;
|
|
1158
|
-
Object.entries(element.twig_templates).forEach(([key, template]) => {
|
|
1159
|
-
renderer.register(key, template);
|
|
1160
|
-
});
|
|
1161
|
-
const propsResolver = createPropsResolver({
|
|
1162
|
-
transformers: settingsTransformersRegistry,
|
|
1163
|
-
schema: element.atomic_props_schema
|
|
1164
|
-
});
|
|
1165
1463
|
return class extends legacyWindow.elementor.modules.elements.types.Widget {
|
|
1166
1464
|
getType() {
|
|
1167
1465
|
return type;
|
|
1168
1466
|
}
|
|
1169
1467
|
getView() {
|
|
1170
|
-
return
|
|
1468
|
+
return createTemplatedElementView({
|
|
1171
1469
|
type,
|
|
1172
1470
|
renderer,
|
|
1173
|
-
|
|
1174
|
-
baseStylesDictionary: element.base_styles_dictionary,
|
|
1175
|
-
templateKey: element.twig_main_template
|
|
1471
|
+
element
|
|
1176
1472
|
});
|
|
1177
1473
|
}
|
|
1178
1474
|
};
|
|
@@ -1180,14 +1476,21 @@ function createTemplatedElementType({ type, renderer, element }) {
|
|
|
1180
1476
|
function canBeTemplated(element) {
|
|
1181
1477
|
return !!(element.atomic_props_schema && element.twig_templates && element.twig_main_template && element.base_styles_dictionary);
|
|
1182
1478
|
}
|
|
1183
|
-
function
|
|
1479
|
+
function createTemplatedElementView({
|
|
1184
1480
|
type,
|
|
1185
1481
|
renderer,
|
|
1186
|
-
|
|
1187
|
-
templateKey,
|
|
1188
|
-
baseStylesDictionary
|
|
1482
|
+
element
|
|
1189
1483
|
}) {
|
|
1190
1484
|
const BaseView = createElementViewClassDeclaration();
|
|
1485
|
+
const templateKey = element.twig_main_template;
|
|
1486
|
+
const baseStylesDictionary = element.base_styles_dictionary;
|
|
1487
|
+
Object.entries(element.twig_templates).forEach(([key, template]) => {
|
|
1488
|
+
renderer.register(key, template);
|
|
1489
|
+
});
|
|
1490
|
+
const resolveProps = createPropsResolver({
|
|
1491
|
+
transformers: settingsTransformersRegistry,
|
|
1492
|
+
schema: element.atomic_props_schema
|
|
1493
|
+
});
|
|
1191
1494
|
return class extends BaseView {
|
|
1192
1495
|
#abortController = null;
|
|
1193
1496
|
getTemplateType() {
|
|
@@ -1196,41 +1499,63 @@ function createTemplatedElementViewClassDeclaration({
|
|
|
1196
1499
|
renderOnChange() {
|
|
1197
1500
|
this.render();
|
|
1198
1501
|
}
|
|
1199
|
-
//
|
|
1200
|
-
|
|
1201
|
-
|
|
1502
|
+
// Override `render` function to support async `_renderTemplate`
|
|
1503
|
+
// Note that `_renderChildren` asynchronity is still NOT supported, so only the parent element rendering can be async
|
|
1504
|
+
render() {
|
|
1202
1505
|
this.#abortController?.abort();
|
|
1203
1506
|
this.#abortController = new AbortController();
|
|
1204
|
-
const process = signalizedProcess(this.#abortController.signal).then((
|
|
1507
|
+
const process = signalizedProcess(this.#abortController.signal).then(() => this.#beforeRender()).then(() => this._renderTemplate()).then(() => {
|
|
1508
|
+
this._renderChildren();
|
|
1509
|
+
this.#afterRender();
|
|
1510
|
+
});
|
|
1511
|
+
return process.execute();
|
|
1512
|
+
}
|
|
1513
|
+
// Overriding Marionette original `_renderTemplate` method to inject our renderer.
|
|
1514
|
+
async _renderTemplate() {
|
|
1515
|
+
this.triggerMethod("before:render:template");
|
|
1516
|
+
const process = signalizedProcess(this.#abortController?.signal).then((_, signal) => {
|
|
1205
1517
|
const settings = this.model.get("settings").toJSON();
|
|
1206
1518
|
return resolveProps({
|
|
1207
1519
|
props: settings,
|
|
1208
1520
|
signal
|
|
1209
1521
|
});
|
|
1210
|
-
}).then((
|
|
1522
|
+
}).then((settings) => {
|
|
1523
|
+
return this.afterSettingsResolve(settings);
|
|
1524
|
+
}).then(async (settings) => {
|
|
1211
1525
|
const context = {
|
|
1212
1526
|
id: this.model.get("id"),
|
|
1213
1527
|
type,
|
|
1214
|
-
settings
|
|
1528
|
+
settings,
|
|
1215
1529
|
base_styles: baseStylesDictionary
|
|
1216
1530
|
};
|
|
1217
1531
|
return renderer.render(templateKey, context);
|
|
1218
1532
|
}).then((html) => this.$el.html(html));
|
|
1219
1533
|
await process.execute();
|
|
1220
|
-
this.#afterRenderTemplate();
|
|
1221
|
-
}
|
|
1222
|
-
// Emulating the original Marionette behavior.
|
|
1223
|
-
#beforeRenderTemplate() {
|
|
1224
|
-
this.triggerMethod("before:render:template");
|
|
1225
|
-
}
|
|
1226
|
-
#afterRenderTemplate() {
|
|
1227
1534
|
this.bindUIElements();
|
|
1228
1535
|
this.triggerMethod("render:template");
|
|
1229
1536
|
}
|
|
1537
|
+
afterSettingsResolve(settings) {
|
|
1538
|
+
return settings;
|
|
1539
|
+
}
|
|
1540
|
+
#beforeRender() {
|
|
1541
|
+
this._ensureViewIsIntact();
|
|
1542
|
+
this._isRendering = true;
|
|
1543
|
+
this.resetChildViewContainer();
|
|
1544
|
+
this.triggerMethod("before:render", this);
|
|
1545
|
+
}
|
|
1546
|
+
#afterRender() {
|
|
1547
|
+
this._isRendering = false;
|
|
1548
|
+
this.isRendered = true;
|
|
1549
|
+
this.triggerMethod("render", this);
|
|
1550
|
+
}
|
|
1230
1551
|
};
|
|
1231
1552
|
}
|
|
1232
1553
|
|
|
1233
1554
|
// src/legacy/init-legacy-views.ts
|
|
1555
|
+
var elementsLegacyTypes = {};
|
|
1556
|
+
function registerElementType(type, elementTypeGenerator) {
|
|
1557
|
+
elementsLegacyTypes[type] = elementTypeGenerator;
|
|
1558
|
+
}
|
|
1234
1559
|
function initLegacyViews() {
|
|
1235
1560
|
__privateListenTo(v1ReadyEvent(), () => {
|
|
1236
1561
|
const config = getWidgetsCache() ?? {};
|
|
@@ -1240,12 +1565,856 @@ function initLegacyViews() {
|
|
|
1240
1565
|
if (!element.atomic) {
|
|
1241
1566
|
return;
|
|
1242
1567
|
}
|
|
1243
|
-
|
|
1568
|
+
let ElementType;
|
|
1569
|
+
if (!!elementsLegacyTypes[type] && canBeTemplated(element)) {
|
|
1570
|
+
ElementType = elementsLegacyTypes[type]({ type, renderer, element });
|
|
1571
|
+
} else if (canBeTemplated(element)) {
|
|
1572
|
+
ElementType = createTemplatedElementType({ type, renderer, element });
|
|
1573
|
+
} else {
|
|
1574
|
+
ElementType = createElementType(type);
|
|
1575
|
+
}
|
|
1244
1576
|
legacyWindow.elementor.elementsManager.registerElementType(new ElementType());
|
|
1245
1577
|
});
|
|
1246
1578
|
});
|
|
1247
1579
|
}
|
|
1248
1580
|
|
|
1581
|
+
// src/mcp/resources/widgets-schema-resource.ts
|
|
1582
|
+
import { getWidgetsCache as getWidgetsCache2 } from "@elementor/editor-elements";
|
|
1583
|
+
import { ResourceTemplate } from "@elementor/editor-mcp";
|
|
1584
|
+
import {
|
|
1585
|
+
Schema
|
|
1586
|
+
} from "@elementor/editor-props";
|
|
1587
|
+
import { getStylesSchema as getStylesSchema2 } from "@elementor/editor-styles";
|
|
1588
|
+
var WIDGET_SCHEMA_URI = "elementor://widgets/schema/{widgetType}";
|
|
1589
|
+
var STYLE_SCHEMA_URI = "elementor://styles/schema/{category}";
|
|
1590
|
+
var BEST_PRACTICES_URI = "elementor://styles/best-practices";
|
|
1591
|
+
var initWidgetsSchemaResource = (reg) => {
|
|
1592
|
+
const { mcpServer } = reg;
|
|
1593
|
+
mcpServer.resource("styles-best-practices", BEST_PRACTICES_URI, async () => {
|
|
1594
|
+
return {
|
|
1595
|
+
contents: [
|
|
1596
|
+
{
|
|
1597
|
+
uri: BEST_PRACTICES_URI,
|
|
1598
|
+
text: `# Styling best practices
|
|
1599
|
+
Prefer using "em" and "rem" values for text-related sizes, padding and spacing. Use percentages for dynamic sizing relative to parent containers.
|
|
1600
|
+
This flexboxes are by default "flex" with "stretch" alignment. To ensure proper layout, define the "justify-content" and "align-items" as in the schema, or in custom_css, depends on your needs.
|
|
1601
|
+
|
|
1602
|
+
When applicable for styles, use the "custom_css" property for free-form CSS styling. This property accepts a string of CSS rules that will be applied directly to the element.
|
|
1603
|
+
The css string must follow standard CSS syntax, with properties and values separated by semicolons, no selectors, or nesting rules allowed.`
|
|
1604
|
+
}
|
|
1605
|
+
]
|
|
1606
|
+
};
|
|
1607
|
+
});
|
|
1608
|
+
mcpServer.resource(
|
|
1609
|
+
"styles-schema",
|
|
1610
|
+
new ResourceTemplate(STYLE_SCHEMA_URI, {
|
|
1611
|
+
list: () => {
|
|
1612
|
+
const categories = [...Object.keys(getStylesSchema2()), "custom_css"];
|
|
1613
|
+
return {
|
|
1614
|
+
resources: categories.map((category) => ({
|
|
1615
|
+
uri: `elementor://styles/schema/${category}`,
|
|
1616
|
+
name: "Style schema for " + category
|
|
1617
|
+
}))
|
|
1618
|
+
};
|
|
1619
|
+
}
|
|
1620
|
+
}),
|
|
1621
|
+
{
|
|
1622
|
+
description: "Common styles schema for the specified category"
|
|
1623
|
+
},
|
|
1624
|
+
async (uri, variables) => {
|
|
1625
|
+
const category = typeof variables.category === "string" ? variables.category : variables.category?.[0];
|
|
1626
|
+
if (category === "custom_css") {
|
|
1627
|
+
return {
|
|
1628
|
+
contents: [
|
|
1629
|
+
{
|
|
1630
|
+
uri: uri.toString(),
|
|
1631
|
+
text: "Free style inline CSS string of properties and their values. Applicable for a single element, only the properties and values are accepted. Use this as a last resort for properties that are not covered with the schema."
|
|
1632
|
+
}
|
|
1633
|
+
]
|
|
1634
|
+
};
|
|
1635
|
+
}
|
|
1636
|
+
const stylesSchema = getStylesSchema2()[category];
|
|
1637
|
+
if (!stylesSchema) {
|
|
1638
|
+
throw new Error(`No styles schema found for category: ${category}`);
|
|
1639
|
+
}
|
|
1640
|
+
const cleanedupPropSchema = cleanupPropType(stylesSchema);
|
|
1641
|
+
const asJson = Schema.propTypeToJsonSchema(cleanedupPropSchema);
|
|
1642
|
+
return {
|
|
1643
|
+
contents: [
|
|
1644
|
+
{
|
|
1645
|
+
uri: uri.toString(),
|
|
1646
|
+
text: JSON.stringify(asJson)
|
|
1647
|
+
}
|
|
1648
|
+
]
|
|
1649
|
+
};
|
|
1650
|
+
}
|
|
1651
|
+
);
|
|
1652
|
+
mcpServer.resource(
|
|
1653
|
+
"widget-schema-by-type",
|
|
1654
|
+
new ResourceTemplate(WIDGET_SCHEMA_URI, {
|
|
1655
|
+
list: () => {
|
|
1656
|
+
const cache = getWidgetsCache2() || {};
|
|
1657
|
+
const availableWidgets = Object.keys(cache || {}).filter(
|
|
1658
|
+
(widgetType) => cache[widgetType]?.atomic_props_schema
|
|
1659
|
+
);
|
|
1660
|
+
return {
|
|
1661
|
+
resources: availableWidgets.map((widgetType) => ({
|
|
1662
|
+
uri: `elementor://widgets/schema/${widgetType}`,
|
|
1663
|
+
name: "Widget schema for " + widgetType
|
|
1664
|
+
}))
|
|
1665
|
+
};
|
|
1666
|
+
}
|
|
1667
|
+
}),
|
|
1668
|
+
{
|
|
1669
|
+
description: "PropType schema for the specified widget type"
|
|
1670
|
+
},
|
|
1671
|
+
async (uri, variables) => {
|
|
1672
|
+
const widgetType = typeof variables.widgetType === "string" ? variables.widgetType : variables.widgetType?.[0];
|
|
1673
|
+
const propSchema = getWidgetsCache2()?.[widgetType]?.atomic_props_schema;
|
|
1674
|
+
if (!propSchema) {
|
|
1675
|
+
throw new Error(`No prop schema found for element type: ${widgetType}`);
|
|
1676
|
+
}
|
|
1677
|
+
const cleanedupPropSchema = cleanupPropSchema(propSchema);
|
|
1678
|
+
const asJson = Object.fromEntries(
|
|
1679
|
+
Object.entries(cleanedupPropSchema).map(([key, propType]) => [
|
|
1680
|
+
key,
|
|
1681
|
+
Schema.propTypeToJsonSchema(propType)
|
|
1682
|
+
])
|
|
1683
|
+
);
|
|
1684
|
+
Schema.nonConfigurablePropKeys.forEach((key) => {
|
|
1685
|
+
delete asJson[key];
|
|
1686
|
+
});
|
|
1687
|
+
return {
|
|
1688
|
+
contents: [
|
|
1689
|
+
{
|
|
1690
|
+
uri: uri.toString(),
|
|
1691
|
+
text: JSON.stringify(asJson)
|
|
1692
|
+
}
|
|
1693
|
+
]
|
|
1694
|
+
};
|
|
1695
|
+
}
|
|
1696
|
+
);
|
|
1697
|
+
};
|
|
1698
|
+
function cleanupPropSchema(propSchema) {
|
|
1699
|
+
const result = {};
|
|
1700
|
+
Object.keys(propSchema).forEach((propName) => {
|
|
1701
|
+
result[propName] = cleanupPropType(propSchema[propName]);
|
|
1702
|
+
});
|
|
1703
|
+
return result;
|
|
1704
|
+
}
|
|
1705
|
+
function cleanupPropType(propType) {
|
|
1706
|
+
const result = {};
|
|
1707
|
+
Object.keys(propType).forEach((property) => {
|
|
1708
|
+
switch (property) {
|
|
1709
|
+
case "key":
|
|
1710
|
+
case "kind":
|
|
1711
|
+
result[property] = propType[property];
|
|
1712
|
+
break;
|
|
1713
|
+
case "meta":
|
|
1714
|
+
case "settings":
|
|
1715
|
+
{
|
|
1716
|
+
if (Object.keys(propType[property] || {}).length > 0) {
|
|
1717
|
+
result[property] = propType[property];
|
|
1718
|
+
}
|
|
1719
|
+
}
|
|
1720
|
+
break;
|
|
1721
|
+
}
|
|
1722
|
+
});
|
|
1723
|
+
if (result.kind === "plain") {
|
|
1724
|
+
Object.defineProperty(result, "kind", { value: "string" });
|
|
1725
|
+
} else if (result.kind === "array") {
|
|
1726
|
+
result.item_prop_type = cleanupPropType(propType.item_prop_type);
|
|
1727
|
+
} else if (result.kind === "object") {
|
|
1728
|
+
const shape = propType.shape;
|
|
1729
|
+
const cleanedShape = cleanupPropSchema(shape);
|
|
1730
|
+
result.shape = cleanedShape;
|
|
1731
|
+
} else if (result.kind === "union") {
|
|
1732
|
+
const propTypes = propType.prop_types;
|
|
1733
|
+
const cleanedPropTypes = {};
|
|
1734
|
+
Object.keys(propTypes).forEach((key) => {
|
|
1735
|
+
cleanedPropTypes[key] = cleanupPropType(propTypes[key]);
|
|
1736
|
+
});
|
|
1737
|
+
result.prop_types = cleanedPropTypes;
|
|
1738
|
+
}
|
|
1739
|
+
return result;
|
|
1740
|
+
}
|
|
1741
|
+
|
|
1742
|
+
// src/mcp/tools/build-composition/tool.ts
|
|
1743
|
+
import {
|
|
1744
|
+
createElement as createElement6,
|
|
1745
|
+
deleteElement,
|
|
1746
|
+
generateElementId,
|
|
1747
|
+
getContainer as getContainer3,
|
|
1748
|
+
getWidgetsCache as getWidgetsCache4
|
|
1749
|
+
} from "@elementor/editor-elements";
|
|
1750
|
+
|
|
1751
|
+
// src/mcp/utils/do-update-element-property.ts
|
|
1752
|
+
import {
|
|
1753
|
+
createElementStyle,
|
|
1754
|
+
getElementStyles,
|
|
1755
|
+
getWidgetsCache as getWidgetsCache3,
|
|
1756
|
+
updateElementSettings as updateElementSettings2,
|
|
1757
|
+
updateElementStyle
|
|
1758
|
+
} from "@elementor/editor-elements";
|
|
1759
|
+
import {
|
|
1760
|
+
getPropSchemaFromCache,
|
|
1761
|
+
Schema as Schema2,
|
|
1762
|
+
stringPropTypeUtil
|
|
1763
|
+
} from "@elementor/editor-props";
|
|
1764
|
+
import { getStylesSchema as getStylesSchema3 } from "@elementor/editor-styles";
|
|
1765
|
+
function resolvePropValue(value, forceKey) {
|
|
1766
|
+
return Schema2.adjustLlmPropValueSchema(value, forceKey);
|
|
1767
|
+
}
|
|
1768
|
+
var doUpdateElementProperty = (params) => {
|
|
1769
|
+
const { elementId, propertyName, propertyValue, elementType } = params;
|
|
1770
|
+
if (propertyName === "_styles") {
|
|
1771
|
+
const elementStyles = getElementStyles(elementId) || {};
|
|
1772
|
+
const propertyMapValue = propertyValue;
|
|
1773
|
+
const styleSchema = getStylesSchema3();
|
|
1774
|
+
const transformedStyleValues = Object.fromEntries(
|
|
1775
|
+
Object.entries(propertyMapValue).map(([key, val]) => {
|
|
1776
|
+
if (key === "custom_css") {
|
|
1777
|
+
return [key, val];
|
|
1778
|
+
}
|
|
1779
|
+
const { key: propKey, kind } = styleSchema?.[key] || {};
|
|
1780
|
+
if (!propKey && kind !== "union") {
|
|
1781
|
+
throw new Error(`_styles property ${key} is not supported.`);
|
|
1782
|
+
}
|
|
1783
|
+
return [key, resolvePropValue(val, propKey)];
|
|
1784
|
+
})
|
|
1785
|
+
);
|
|
1786
|
+
let customCss;
|
|
1787
|
+
Object.keys(propertyMapValue).forEach((stylePropName) => {
|
|
1788
|
+
const propertyRawSchema = styleSchema[stylePropName];
|
|
1789
|
+
if (stylePropName === "custom_css") {
|
|
1790
|
+
let customCssValue = propertyMapValue[stylePropName];
|
|
1791
|
+
if (typeof customCssValue === "object") {
|
|
1792
|
+
customCssValue = stringPropTypeUtil.extract(customCssValue) || customCssValue?.value || "";
|
|
1793
|
+
}
|
|
1794
|
+
customCss = {
|
|
1795
|
+
raw: btoa(customCssValue)
|
|
1796
|
+
};
|
|
1797
|
+
return;
|
|
1798
|
+
}
|
|
1799
|
+
const isSupported = !!propertyRawSchema;
|
|
1800
|
+
if (!isSupported) {
|
|
1801
|
+
throw new Error(`_styles property ${stylePropName} is not supported.`);
|
|
1802
|
+
}
|
|
1803
|
+
if (propertyRawSchema.kind === "plain") {
|
|
1804
|
+
if (typeof propertyMapValue[stylePropName] !== "object") {
|
|
1805
|
+
const propUtil = getPropSchemaFromCache(propertyRawSchema.key);
|
|
1806
|
+
if (propUtil) {
|
|
1807
|
+
const plainValue = propUtil.create(propertyMapValue[stylePropName]);
|
|
1808
|
+
propertyMapValue[stylePropName] = plainValue;
|
|
1809
|
+
}
|
|
1810
|
+
}
|
|
1811
|
+
}
|
|
1812
|
+
});
|
|
1813
|
+
const localStyle = Object.values(elementStyles).find((style) => style.label === "local");
|
|
1814
|
+
if (!localStyle) {
|
|
1815
|
+
createElementStyle({
|
|
1816
|
+
elementId,
|
|
1817
|
+
...typeof customCss !== "undefined" ? { custom_css: customCss } : {},
|
|
1818
|
+
classesProp: "classes",
|
|
1819
|
+
label: "local",
|
|
1820
|
+
meta: {
|
|
1821
|
+
breakpoint: "desktop",
|
|
1822
|
+
state: null
|
|
1823
|
+
},
|
|
1824
|
+
props: {
|
|
1825
|
+
...transformedStyleValues
|
|
1826
|
+
}
|
|
1827
|
+
});
|
|
1828
|
+
} else {
|
|
1829
|
+
updateElementStyle({
|
|
1830
|
+
elementId,
|
|
1831
|
+
styleId: localStyle.id,
|
|
1832
|
+
meta: {
|
|
1833
|
+
breakpoint: "desktop",
|
|
1834
|
+
state: null
|
|
1835
|
+
},
|
|
1836
|
+
...typeof customCss !== "undefined" ? { custom_css: customCss } : {},
|
|
1837
|
+
props: {
|
|
1838
|
+
...transformedStyleValues
|
|
1839
|
+
}
|
|
1840
|
+
});
|
|
1841
|
+
}
|
|
1842
|
+
return;
|
|
1843
|
+
}
|
|
1844
|
+
const elementPropSchema = getWidgetsCache3()?.[elementType]?.atomic_props_schema;
|
|
1845
|
+
if (!elementPropSchema) {
|
|
1846
|
+
throw new Error(`No prop schema found for element type: ${elementType}`);
|
|
1847
|
+
}
|
|
1848
|
+
if (!elementPropSchema[propertyName]) {
|
|
1849
|
+
const propertyNames = Object.keys(elementPropSchema);
|
|
1850
|
+
throw new Error(
|
|
1851
|
+
`Property "${propertyName}" does not exist on element type "${elementType}". Available properties are: ${propertyNames.join(
|
|
1852
|
+
", "
|
|
1853
|
+
)}`
|
|
1854
|
+
);
|
|
1855
|
+
}
|
|
1856
|
+
const value = resolvePropValue(propertyValue);
|
|
1857
|
+
updateElementSettings2({
|
|
1858
|
+
id: elementId,
|
|
1859
|
+
props: {
|
|
1860
|
+
[propertyName]: value
|
|
1861
|
+
},
|
|
1862
|
+
withHistory: false
|
|
1863
|
+
});
|
|
1864
|
+
};
|
|
1865
|
+
|
|
1866
|
+
// src/mcp/tools/build-composition/prompt.ts
|
|
1867
|
+
import { toolPrompts } from "@elementor/editor-mcp";
|
|
1868
|
+
var generatePrompt = () => {
|
|
1869
|
+
const buildCompositionsToolPrompt = toolPrompts("build-compositions");
|
|
1870
|
+
buildCompositionsToolPrompt.description(`
|
|
1871
|
+
Build entire elementor widget comositions representing complex structures of nested elements.
|
|
1872
|
+
|
|
1873
|
+
# When to use this tool
|
|
1874
|
+
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.
|
|
1875
|
+
Prefer this tool over any other tool for building HTML structure, unless you are specified to use a different tool.
|
|
1876
|
+
|
|
1877
|
+
# **CRITICAL - REQUIRED RESOURCES (Must read before using this tool)**
|
|
1878
|
+
1. [${WIDGET_SCHEMA_URI}]
|
|
1879
|
+
Required to understand which widgets are available, and what are their configuration schemas.
|
|
1880
|
+
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.
|
|
1881
|
+
2. [${STYLE_SCHEMA_URI}]
|
|
1882
|
+
Required to understand the styles schema for the widgets. All widgets share the same styles schema.
|
|
1883
|
+
3. List of allowed custom tags for building the structure is derived from the list of widgets schema resources.
|
|
1884
|
+
|
|
1885
|
+
# Instructions
|
|
1886
|
+
1. Understand the user requirements carefully.
|
|
1887
|
+
2. Build a valid XML structure using only the allowed custom tags provided. For example, if you
|
|
1888
|
+
use the "e-button" element, it would be represented as <e-button></e-button> in the XML structure.
|
|
1889
|
+
3. Plan the configuration for each element according to the user requirements, using the configuration schema provided for each custom tag.
|
|
1890
|
+
Every widget type has it's own configuration schema, retreivable from the resource [${WIDGET_SCHEMA_URI}].
|
|
1891
|
+
PropValues must follow the exact PropType schema provided in the resource.
|
|
1892
|
+
4. For every element, provide a "configuration-id" attribute. For example:
|
|
1893
|
+
\`<e-flexbox configuration-id="flex1"><e-heading configuration-id="heading2"></e-heading></e-flexbox>\`
|
|
1894
|
+
In the elementConfig property, provide the actual configuration object for each configuration-id used in the XML structure.
|
|
1895
|
+
In the stylesConfig property, provide the actual styles configuration object for each configuration-id used in the XML structure.
|
|
1896
|
+
5. Ensure the XML structure is valid and parsable.
|
|
1897
|
+
6. Do not add any attribute nodes, classes, id's, and no text nodes allowed.
|
|
1898
|
+
Layout properties, such as margin, padding, align, etc. must be applied using the [${STYLE_SCHEMA_URI}] PropValues.
|
|
1899
|
+
7. Some elements allow nesting of other elements, and most of the DO NOT. The allowed elements that can have nested children are "e-div-block" and "e-flexbox".
|
|
1900
|
+
8. Make sure that non-container elements do NOT have any nested elements.
|
|
1901
|
+
9. Unsless the user specifically requires structure only, BE EXPRESSIVE AND VISUALLY CREATIVE AS POSSIBLE IN APPLYING STYLE CONFIGURATION.
|
|
1902
|
+
In the case of doubt, prefer adding more styles to make the composition visually appealing.
|
|
1903
|
+
|
|
1904
|
+
# Additional Guidelines
|
|
1905
|
+
- Most users expect the structure to be well designed and visually appealing.
|
|
1906
|
+
- Use layout properties, ensure "white space" design approach is followed, and make sure the composition is visually balanced.
|
|
1907
|
+
- Use appropriate spacing, alignment, and sizing to create a harmonious layout.
|
|
1908
|
+
- Consider the visual hierarchy of elements to guide the user's attention effectively.
|
|
1909
|
+
- You are encouraged to use colors, typography, and other style properties to enhance the visual appeal, as long as they are part of the configuration schema for the elements used.
|
|
1910
|
+
- Always aim for a clean and professional look that aligns with modern design principles.
|
|
1911
|
+
- When you are required to create placeholder texts, use texts that have a length that fits the goal. When long texts are required, use longer placeholder texts. When the user specifies exact texts, use the exact texts.
|
|
1912
|
+
- Image size does not affect the actual size on the screen, only which quality to use. If you use images, specifically add _styles PropValues to define the image sizes.
|
|
1913
|
+
- Attempt to use layout, margin, padding, size properties from the styles schema.
|
|
1914
|
+
- If your elements library is limited, encourage use of nesting containers to achieve complex layouts.
|
|
1915
|
+
|
|
1916
|
+
# CONSTRAINTS
|
|
1917
|
+
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.
|
|
1918
|
+
If a "$$type" is missing, update the invalid object, if the XML has parsing errors, fix it, etc. and RETRY.
|
|
1919
|
+
VALIDATE the XML structure before delivering it as the final result.
|
|
1920
|
+
VALIDATE the JSON structure used in the "configuration" attributes for each element before delivering the final result. The configuration must MATCH the PropValue schemas.
|
|
1921
|
+
NO LINKS ALLOWED. Never apply links to elements, even if they appear in the PropType schema.
|
|
1922
|
+
elementConfig values must align with the widget's PropType schema, available at the resource [${WIDGET_SCHEMA_URI}].
|
|
1923
|
+
stylesConfig values must align with the common styles PropType schema, available at the resource [${STYLE_SCHEMA_URI}].
|
|
1924
|
+
|
|
1925
|
+
# Parameters
|
|
1926
|
+
All parameters are MANDATORY.
|
|
1927
|
+
- xmlStructure
|
|
1928
|
+
- elementConfig
|
|
1929
|
+
- stylesConfig
|
|
1930
|
+
|
|
1931
|
+
If unsure about the configuration of a specific property, read the schema resources carefully.
|
|
1932
|
+
|
|
1933
|
+
|
|
1934
|
+
`);
|
|
1935
|
+
buildCompositionsToolPrompt.example(`
|
|
1936
|
+
A Heading and a button inside a flexbox
|
|
1937
|
+
{
|
|
1938
|
+
xmlStructure: "<e-flexbox configuration-id="flex1"><e-heading configuration-id="heading1"></e-heading><e-button configuration-id="button1"></e-button></e-flexbox>"
|
|
1939
|
+
elementConfig: {
|
|
1940
|
+
"flex1": {
|
|
1941
|
+
"tag": {
|
|
1942
|
+
"$$type": "string",
|
|
1943
|
+
"value": "section"
|
|
1944
|
+
},
|
|
1945
|
+
},
|
|
1946
|
+
stylesConfig: {
|
|
1947
|
+
"heading1": {
|
|
1948
|
+
"font-size": {
|
|
1949
|
+
"$$type": "size",
|
|
1950
|
+
"value": {
|
|
1951
|
+
"size": { "$$type": "number", "value": 24 },
|
|
1952
|
+
"unit": { "$$type": "string", "value": "px" }
|
|
1953
|
+
}
|
|
1954
|
+
},
|
|
1955
|
+
"color": {
|
|
1956
|
+
"$$type": "color",
|
|
1957
|
+
"value": { "$$type": "string", "value": "#333" }
|
|
1958
|
+
}
|
|
1959
|
+
}
|
|
1960
|
+
},
|
|
1961
|
+
}
|
|
1962
|
+
`);
|
|
1963
|
+
buildCompositionsToolPrompt.parameter(
|
|
1964
|
+
"xmlStructure",
|
|
1965
|
+
`**MANDATORY** A valid XML structure representing the composition to be built, using custom elementor tags, styling and configuration PropValues.`
|
|
1966
|
+
);
|
|
1967
|
+
buildCompositionsToolPrompt.parameter(
|
|
1968
|
+
"elementConfig",
|
|
1969
|
+
`**MANDATORY** A record mapping configuration IDs to their corresponding configuration objects, defining the PropValues for each element created.`
|
|
1970
|
+
);
|
|
1971
|
+
buildCompositionsToolPrompt.parameter(
|
|
1972
|
+
"stylesConfig",
|
|
1973
|
+
`**MANDATORY** A record mapping style PropTypes to their corresponding style configuration objects, defining the PropValues for styles to be applied to elements.`
|
|
1974
|
+
);
|
|
1975
|
+
buildCompositionsToolPrompt.instruction(
|
|
1976
|
+
`You will be provided the XML structure with element IDs. These IDs represent the actual elementor widgets created on the page/post.
|
|
1977
|
+
You should use these IDs as reference for further configuration, styling or changing elements later on.`
|
|
1978
|
+
);
|
|
1979
|
+
buildCompositionsToolPrompt.instruction(
|
|
1980
|
+
`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.`
|
|
1981
|
+
);
|
|
1982
|
+
return buildCompositionsToolPrompt.prompt();
|
|
1983
|
+
};
|
|
1984
|
+
|
|
1985
|
+
// src/mcp/tools/build-composition/schema.ts
|
|
1986
|
+
import { z } from "@elementor/schema";
|
|
1987
|
+
var inputSchema = {
|
|
1988
|
+
xmlStructure: z.string().describe("The XML structure representing the composition to be built"),
|
|
1989
|
+
elementConfig: z.record(
|
|
1990
|
+
z.string().describe("The configuration id"),
|
|
1991
|
+
z.record(z.string().describe("property name"), z.any().describe("The PropValue for the property"))
|
|
1992
|
+
).describe("A record mapping element IDs to their configuration objects. REQUIRED"),
|
|
1993
|
+
stylesConfig: z.record(
|
|
1994
|
+
z.string().describe("The configuration id"),
|
|
1995
|
+
z.record(
|
|
1996
|
+
z.string().describe("_styles property name"),
|
|
1997
|
+
z.any().describe("The PropValue for the style property. MANDATORY")
|
|
1998
|
+
)
|
|
1999
|
+
).describe(
|
|
2000
|
+
`A record mapping element IDs to their styles configuration objects. Use the actual styles schema from [${STYLE_SCHEMA_URI}].`
|
|
2001
|
+
).default({})
|
|
2002
|
+
};
|
|
2003
|
+
var outputSchema = {
|
|
2004
|
+
errors: z.string().describe("Error message if the composition building failed").optional(),
|
|
2005
|
+
xmlStructure: z.string().describe("The built XML structure as a string").optional(),
|
|
2006
|
+
llmInstructions: z.string().describe("Instructions used to further actions for you").optional()
|
|
2007
|
+
};
|
|
2008
|
+
|
|
2009
|
+
// src/mcp/tools/build-composition/tool.ts
|
|
2010
|
+
var initBuildCompositionsTool = (reg) => {
|
|
2011
|
+
const { addTool } = reg;
|
|
2012
|
+
addTool({
|
|
2013
|
+
name: "build-compositions",
|
|
2014
|
+
description: generatePrompt(),
|
|
2015
|
+
schema: inputSchema,
|
|
2016
|
+
outputSchema,
|
|
2017
|
+
handler: async (params) => {
|
|
2018
|
+
let xml = null;
|
|
2019
|
+
const { xmlStructure, elementConfig, stylesConfig } = params;
|
|
2020
|
+
const errors = [];
|
|
2021
|
+
const softErrors = [];
|
|
2022
|
+
const rootContainers = [];
|
|
2023
|
+
const widgetsCache = getWidgetsCache4() || {};
|
|
2024
|
+
const documentContainer = getContainer3("document");
|
|
2025
|
+
try {
|
|
2026
|
+
const parser = new DOMParser();
|
|
2027
|
+
xml = parser.parseFromString(xmlStructure, "application/xml");
|
|
2028
|
+
const errorNode = xml.querySelector("parsererror");
|
|
2029
|
+
if (errorNode) {
|
|
2030
|
+
throw new Error("Failed to parse XML structure: " + errorNode.textContent);
|
|
2031
|
+
}
|
|
2032
|
+
const children = Array.from(xml.children);
|
|
2033
|
+
const iterate = (node, containerElement = documentContainer) => {
|
|
2034
|
+
const elementTag = node.tagName;
|
|
2035
|
+
if (!widgetsCache[elementTag]) {
|
|
2036
|
+
errors.push(new Error(`Unknown widget type: ${elementTag}`));
|
|
2037
|
+
}
|
|
2038
|
+
const isContainer = elementTag === "e-flexbox" || elementTag === "e-div-block";
|
|
2039
|
+
const newElement = isContainer ? createElement6({
|
|
2040
|
+
containerId: containerElement.id,
|
|
2041
|
+
model: {
|
|
2042
|
+
elType: elementTag,
|
|
2043
|
+
id: generateElementId()
|
|
2044
|
+
},
|
|
2045
|
+
options: { useHistory: false }
|
|
2046
|
+
}) : createElement6({
|
|
2047
|
+
containerId: containerElement.id,
|
|
2048
|
+
model: {
|
|
2049
|
+
elType: "widget",
|
|
2050
|
+
widgetType: elementTag,
|
|
2051
|
+
id: generateElementId()
|
|
2052
|
+
},
|
|
2053
|
+
options: { useHistory: false }
|
|
2054
|
+
});
|
|
2055
|
+
if (containerElement === documentContainer) {
|
|
2056
|
+
rootContainers.push(newElement);
|
|
2057
|
+
}
|
|
2058
|
+
node.setAttribute("id", newElement.id);
|
|
2059
|
+
const configId = node.getAttribute("configuration-id") || "";
|
|
2060
|
+
try {
|
|
2061
|
+
const configObject = elementConfig[configId] || {};
|
|
2062
|
+
const styleObject = stylesConfig[configId] || {};
|
|
2063
|
+
configObject._styles = styleObject;
|
|
2064
|
+
for (const [propertyName, propertyValue] of Object.entries(configObject)) {
|
|
2065
|
+
const widgetSchema = widgetsCache[elementTag];
|
|
2066
|
+
if (!widgetSchema?.atomic_props_schema?.[propertyName] && propertyName !== "_styles" && propertyName !== "custom_css") {
|
|
2067
|
+
softErrors.push(
|
|
2068
|
+
new Error(
|
|
2069
|
+
`Property "${propertyName}" does not exist on element type "${elementTag}".`
|
|
2070
|
+
)
|
|
2071
|
+
);
|
|
2072
|
+
continue;
|
|
2073
|
+
}
|
|
2074
|
+
try {
|
|
2075
|
+
doUpdateElementProperty({
|
|
2076
|
+
elementId: newElement.id,
|
|
2077
|
+
propertyName,
|
|
2078
|
+
propertyValue: propertyName === "custom_css" ? { _styles: propertyValue } : propertyValue,
|
|
2079
|
+
elementType: elementTag
|
|
2080
|
+
});
|
|
2081
|
+
} catch (error) {
|
|
2082
|
+
softErrors.push(error);
|
|
2083
|
+
}
|
|
2084
|
+
}
|
|
2085
|
+
if (isContainer) {
|
|
2086
|
+
for (const child of node.children) {
|
|
2087
|
+
iterate(child, newElement);
|
|
2088
|
+
}
|
|
2089
|
+
} else {
|
|
2090
|
+
node.innerHTML = "";
|
|
2091
|
+
node.removeAttribute("configuration");
|
|
2092
|
+
}
|
|
2093
|
+
} finally {
|
|
2094
|
+
}
|
|
2095
|
+
};
|
|
2096
|
+
for (const childNode of children) {
|
|
2097
|
+
iterate(childNode, documentContainer);
|
|
2098
|
+
try {
|
|
2099
|
+
} catch (error) {
|
|
2100
|
+
errors.push(error);
|
|
2101
|
+
}
|
|
2102
|
+
}
|
|
2103
|
+
} catch (error) {
|
|
2104
|
+
errors.push(error);
|
|
2105
|
+
}
|
|
2106
|
+
if (errors.length) {
|
|
2107
|
+
rootContainers.forEach((rootContainer) => {
|
|
2108
|
+
deleteElement({
|
|
2109
|
+
elementId: rootContainer.id,
|
|
2110
|
+
options: { useHistory: false }
|
|
2111
|
+
});
|
|
2112
|
+
});
|
|
2113
|
+
}
|
|
2114
|
+
if (errors.length > 0) {
|
|
2115
|
+
const errorText = `Failed to build composition with the following errors:
|
|
2116
|
+
|
|
2117
|
+
|
|
2118
|
+
${errors.map((e) => typeof e === "string" ? e : e.message).join("\n\n")}
|
|
2119
|
+
"Missing $$type" errors indicate that the configuration objects are invalid. Try again and apply **ALL** object entries with correct $$type.
|
|
2120
|
+
Now that you have these errors, fix them and try again. Errors regarding configuration objects, please check again the PropType schemas`;
|
|
2121
|
+
throw new Error(errorText);
|
|
2122
|
+
}
|
|
2123
|
+
if (!xml) {
|
|
2124
|
+
throw new Error("XML structure is null after parsing.");
|
|
2125
|
+
}
|
|
2126
|
+
return {
|
|
2127
|
+
xmlStructure: new XMLSerializer().serializeToString(xml),
|
|
2128
|
+
llmInstructions: (softErrors.length ? `The composition was built successfully, but there were some issues with the provided configurations:
|
|
2129
|
+
|
|
2130
|
+
${softErrors.map((e) => `- ${e.message}`).join("\n")}
|
|
2131
|
+
|
|
2132
|
+
Please use confiugure-element tool to fix these issues. Now that you have information about these issues, use the configure-element tool to fix them!` : "") + `
|
|
2133
|
+
Next Steps:
|
|
2134
|
+
- Use "apply-global-class" tool as there may be global styles ready to be applied to elements.
|
|
2135
|
+
- Use "configure-element" tool to further configure elements as needed, including styles.
|
|
2136
|
+
`
|
|
2137
|
+
};
|
|
2138
|
+
}
|
|
2139
|
+
});
|
|
2140
|
+
};
|
|
2141
|
+
|
|
2142
|
+
// src/mcp/tools/configure-element/prompt.ts
|
|
2143
|
+
var configureElementToolPrompt = `Configure an existing element on the page.
|
|
2144
|
+
|
|
2145
|
+
# **CRITICAL - REQUIRED INFORMATION (Must read before using this tool)**
|
|
2146
|
+
1. [${WIDGET_SCHEMA_URI}]
|
|
2147
|
+
Required to understand which widgets are available, and what are their configuration schemas.
|
|
2148
|
+
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.
|
|
2149
|
+
2. [${STYLE_SCHEMA_URI}]
|
|
2150
|
+
Required to understand the styles schema for the widgets. All widgets share the same styles schema, grouped by categories.
|
|
2151
|
+
Use this resource to understand which style properties are available for each element, and how to structure the "_styles" configuration property.
|
|
2152
|
+
3. If not sure about the PropValues schema, you can use the "get-element-configuration-values" tool to retreive the current PropValues configuration of the element.
|
|
2153
|
+
|
|
2154
|
+
Before using this tool, check the definitions of the elements PropTypes at the resource "widget-schema-by-type" at editor-canvas__elementor://widgets/schema/{widgetType}
|
|
2155
|
+
All widgets share a common _style property for styling, which uses the common styles schema.
|
|
2156
|
+
Retreive and check the common styles schema at the resource list "styles-schema" at editor-canvas__elementor://styles/schema/{category}
|
|
2157
|
+
|
|
2158
|
+
# Parameters
|
|
2159
|
+
- propertiesToChange: An object containing the properties to change, with their new values. MANDATORY
|
|
2160
|
+
- elementId: The ID of the element to configure. MANDATORY
|
|
2161
|
+
- elementType: The type of the element to configure (i.e. e-heading, e-button). MANDATORY
|
|
2162
|
+
|
|
2163
|
+
# When to use this tool
|
|
2164
|
+
When a user requires to change anything in an element, such as updating text, colors, sizes, or other configurable properties.
|
|
2165
|
+
This tool handles elements of type "widget".
|
|
2166
|
+
This tool handles styling elements, using the _styles property in the configuration.
|
|
2167
|
+
|
|
2168
|
+
The element's schema must be known before using this tool.
|
|
2169
|
+
|
|
2170
|
+
Attached resource link describing how PropType schema should be parsed as PropValue for this tool.
|
|
2171
|
+
|
|
2172
|
+
Read carefully the PropType Schema of the element and it's styles, then apply correct PropValue according to the schema.
|
|
2173
|
+
|
|
2174
|
+
PropValue structure:
|
|
2175
|
+
{
|
|
2176
|
+
"$$type": string, // MANDATORY as defined in the PropType schema under the "key" property
|
|
2177
|
+
value: unknown // The value according to the PropType schema for kinds of "array", use array with PropValues items inside. For "object", read the shape property of the PropType schema. For "plain", use strings.
|
|
2178
|
+
}
|
|
2179
|
+
|
|
2180
|
+
<IMPORTANT>
|
|
2181
|
+
ALWAYS MAKE SURE you have the PropType schemas for the element you are configuring, and the common-styles schema for styling. If you are not sure, retreive the schema from the resources mentioned above.
|
|
2182
|
+
</IMPORTANT>
|
|
2183
|
+
|
|
2184
|
+
You can use multiple property changes at once by providing multiple entries in the propertiesToChange object, including _style alongside non-style props.
|
|
2185
|
+
Some properties are nested, use the root property name, then objects with nested values inside, as the complete schema suggests.
|
|
2186
|
+
Nested properties, such as for the _styles, should include a "_styles" property with object containing the definitions to change.
|
|
2187
|
+
|
|
2188
|
+
Make sure you have the "widget-schema-by-type" resource available to retreive the PropType schema for the element type you are configuring.
|
|
2189
|
+
|
|
2190
|
+
# How to configure elements
|
|
2191
|
+
We use a dedicated PropType Schema for configuring elements, including styles. When you configure an element, you must use the EXACT PropType Value as defined in the schema.
|
|
2192
|
+
For _styles, use the style schema provided, as it also uses the PropType format.
|
|
2193
|
+
For all non-primitive types, provide the key property as defined in the schema as $$type in the generated objecct, as it is MANDATORY for parsing.
|
|
2194
|
+
|
|
2195
|
+
Use the EXACT "PROP-TYPE" Schema given, and ALWAYS include the "key" property from the original configuration for every property you are changing.
|
|
2196
|
+
|
|
2197
|
+
# Example
|
|
2198
|
+
\`\`\`json
|
|
2199
|
+
{
|
|
2200
|
+
propertiesToChange: {
|
|
2201
|
+
// List of properties TO CHANGE, following the PropType schema for the element as defined in the resource [${WIDGET_SCHEMA_URI}]
|
|
2202
|
+
title: {
|
|
2203
|
+
$$type: 'string',
|
|
2204
|
+
value: 'New Title Text'
|
|
2205
|
+
},
|
|
2206
|
+
border: {
|
|
2207
|
+
$$type: 'boolean',
|
|
2208
|
+
value: false
|
|
2209
|
+
},
|
|
2210
|
+
_styles: {
|
|
2211
|
+
// List of available keys available at the [${STYLE_SCHEMA_URI}] dynamic resource
|
|
2212
|
+
'line-height': {
|
|
2213
|
+
$$type: 'size', // MANDATORY do not forget to include the correct $$type for every property
|
|
2214
|
+
value: {
|
|
2215
|
+
size: {
|
|
2216
|
+
$$type: 'number',
|
|
2217
|
+
value: 20
|
|
2218
|
+
},
|
|
2219
|
+
unit: {
|
|
2220
|
+
$$type: 'string',
|
|
2221
|
+
value: 'px'
|
|
2222
|
+
}
|
|
2223
|
+
}
|
|
2224
|
+
}
|
|
2225
|
+
}
|
|
2226
|
+
}
|
|
2227
|
+
};
|
|
2228
|
+
\`\`\`
|
|
2229
|
+
|
|
2230
|
+
<IMPORTANT>
|
|
2231
|
+
The $$type property is MANDATORY for every value, it is required to parse the value and apply application-level effects.
|
|
2232
|
+
</IMPORTANT>
|
|
2233
|
+
`;
|
|
2234
|
+
|
|
2235
|
+
// src/mcp/tools/configure-element/schema.ts
|
|
2236
|
+
import { z as z2 } from "@elementor/schema";
|
|
2237
|
+
var inputSchema2 = {
|
|
2238
|
+
propertiesToChange: z2.record(
|
|
2239
|
+
z2.string().describe(
|
|
2240
|
+
"The property name. If nested property, provide the root property name, and the object delta only."
|
|
2241
|
+
),
|
|
2242
|
+
z2.any().describe("The property's value")
|
|
2243
|
+
).describe("An object record containing property names and their new values to be set on the element").optional(),
|
|
2244
|
+
elementType: z2.string().describe("The type of the element to retreive the schema"),
|
|
2245
|
+
elementId: z2.string().describe("The unique id of the element to configure")
|
|
2246
|
+
};
|
|
2247
|
+
var outputSchema2 = {
|
|
2248
|
+
success: z2.boolean().describe(
|
|
2249
|
+
"Whether the configuration change was successful, only if propertyName and propertyValue are provided"
|
|
2250
|
+
)
|
|
2251
|
+
};
|
|
2252
|
+
|
|
2253
|
+
// src/mcp/tools/configure-element/tool.ts
|
|
2254
|
+
var initConfigureElementTool = (reg) => {
|
|
2255
|
+
const { addTool } = reg;
|
|
2256
|
+
addTool({
|
|
2257
|
+
name: "configure-element",
|
|
2258
|
+
description: configureElementToolPrompt,
|
|
2259
|
+
schema: inputSchema2,
|
|
2260
|
+
outputSchema: outputSchema2,
|
|
2261
|
+
handler: ({ elementId, propertiesToChange, elementType }) => {
|
|
2262
|
+
if (!propertiesToChange) {
|
|
2263
|
+
throw new Error(
|
|
2264
|
+
"propertiesToChange is required to configure an element. Now that you have this information, ensure you have the schema and try again."
|
|
2265
|
+
);
|
|
2266
|
+
}
|
|
2267
|
+
const toUpdate = Object.entries(propertiesToChange);
|
|
2268
|
+
for (const [propertyName, propertyValue] of toUpdate) {
|
|
2269
|
+
if (!propertyName && !elementId && !elementType) {
|
|
2270
|
+
throw new Error(
|
|
2271
|
+
"propertyName, elementId, elementType are required to configure an element. If you want to retreive the schema, use the get-element-configuration-schema tool."
|
|
2272
|
+
);
|
|
2273
|
+
}
|
|
2274
|
+
try {
|
|
2275
|
+
doUpdateElementProperty({
|
|
2276
|
+
elementId,
|
|
2277
|
+
elementType,
|
|
2278
|
+
propertyName,
|
|
2279
|
+
propertyValue
|
|
2280
|
+
});
|
|
2281
|
+
} catch (error) {
|
|
2282
|
+
const errorMessage = createUpdateErrorMessage({
|
|
2283
|
+
propertyName,
|
|
2284
|
+
elementId,
|
|
2285
|
+
elementType,
|
|
2286
|
+
error
|
|
2287
|
+
});
|
|
2288
|
+
throw new Error(errorMessage);
|
|
2289
|
+
}
|
|
2290
|
+
}
|
|
2291
|
+
return {
|
|
2292
|
+
success: true
|
|
2293
|
+
};
|
|
2294
|
+
}
|
|
2295
|
+
});
|
|
2296
|
+
};
|
|
2297
|
+
function createUpdateErrorMessage(opts) {
|
|
2298
|
+
const { propertyName, elementId, elementType, error } = opts;
|
|
2299
|
+
return `Failed to update property "${propertyName}" on element "${elementId}": ${error.message}.
|
|
2300
|
+
Check the element's PropType schema at the resource [${WIDGET_SCHEMA_URI.replace(
|
|
2301
|
+
"{widgetType}",
|
|
2302
|
+
elementType
|
|
2303
|
+
)}] for type "${elementType}" to ensure the property exists and the value matches the expected PropType.
|
|
2304
|
+
Now that you have this information, ensure you have the schema and try again.`;
|
|
2305
|
+
}
|
|
2306
|
+
|
|
2307
|
+
// src/mcp/tools/get-element-config/tool.ts
|
|
2308
|
+
import { getContainer as getContainer4, getElementStyles as getElementStyles2, getWidgetsCache as getWidgetsCache5 } from "@elementor/editor-elements";
|
|
2309
|
+
import { Schema as Schema3 } from "@elementor/editor-props";
|
|
2310
|
+
import { z as z3 } from "@elementor/schema";
|
|
2311
|
+
var schema = {
|
|
2312
|
+
elementId: z3.string()
|
|
2313
|
+
};
|
|
2314
|
+
var outputSchema3 = {
|
|
2315
|
+
propValues: z3.record(z3.string(), z3.any()).describe(
|
|
2316
|
+
"A record mapping PropTypes to their corresponding PropValues, with _styles record for style-related PropValues"
|
|
2317
|
+
)
|
|
2318
|
+
};
|
|
2319
|
+
var initGetElementConfigTool = (reg) => {
|
|
2320
|
+
const { addTool } = reg;
|
|
2321
|
+
addTool({
|
|
2322
|
+
name: "get-element-configuration-values",
|
|
2323
|
+
description: "Retrieve the element's configuration PropValues for a specific element by unique ID.",
|
|
2324
|
+
schema,
|
|
2325
|
+
outputSchema: outputSchema3,
|
|
2326
|
+
handler: async ({ elementId }) => {
|
|
2327
|
+
const element = getContainer4(elementId);
|
|
2328
|
+
if (!element) {
|
|
2329
|
+
throw new Error(`Element with ID ${elementId} not found.`);
|
|
2330
|
+
}
|
|
2331
|
+
const elementRawSettings = element.settings;
|
|
2332
|
+
const propSchema = getWidgetsCache5()?.[element.model.get("widgetType") || ""]?.atomic_props_schema;
|
|
2333
|
+
if (!elementRawSettings || !propSchema) {
|
|
2334
|
+
throw new Error(`No settings or prop schema found for element ID: ${elementId}`);
|
|
2335
|
+
}
|
|
2336
|
+
const propValues = {};
|
|
2337
|
+
const stylePropValues = {};
|
|
2338
|
+
Schema3.configurableKeys(propSchema).forEach((key) => {
|
|
2339
|
+
propValues[key] = structuredClone(elementRawSettings.get(key));
|
|
2340
|
+
});
|
|
2341
|
+
const elementStyles = getElementStyles2(elementId) || {};
|
|
2342
|
+
const localStyle = Object.values(elementStyles).find((style) => style.label === "local");
|
|
2343
|
+
if (localStyle) {
|
|
2344
|
+
const defaultVariant = localStyle.variants.find(
|
|
2345
|
+
(variant) => variant.meta.breakpoint === "desktop" && !variant.meta.state
|
|
2346
|
+
);
|
|
2347
|
+
if (defaultVariant) {
|
|
2348
|
+
const styleProps = defaultVariant.props || {};
|
|
2349
|
+
Object.keys(styleProps).forEach((stylePropName) => {
|
|
2350
|
+
if (typeof styleProps[stylePropName] !== "undefined") {
|
|
2351
|
+
stylePropValues[stylePropName] = structuredClone(styleProps[stylePropName]);
|
|
2352
|
+
}
|
|
2353
|
+
});
|
|
2354
|
+
}
|
|
2355
|
+
}
|
|
2356
|
+
return {
|
|
2357
|
+
propValues: {
|
|
2358
|
+
...propValues,
|
|
2359
|
+
_styles: stylePropValues
|
|
2360
|
+
}
|
|
2361
|
+
};
|
|
2362
|
+
}
|
|
2363
|
+
});
|
|
2364
|
+
};
|
|
2365
|
+
|
|
2366
|
+
// src/mcp/canvas-mcp.ts
|
|
2367
|
+
var initCanvasMcp = (reg) => {
|
|
2368
|
+
const { setMCPDescription } = reg;
|
|
2369
|
+
setMCPDescription(
|
|
2370
|
+
'Everything related to creative design, layout, styling and building the pages, specifically element of type "widget"'
|
|
2371
|
+
);
|
|
2372
|
+
initWidgetsSchemaResource(reg);
|
|
2373
|
+
initBuildCompositionsTool(reg);
|
|
2374
|
+
initGetElementConfigTool(reg);
|
|
2375
|
+
initConfigureElementTool(reg);
|
|
2376
|
+
};
|
|
2377
|
+
|
|
2378
|
+
// src/mcp/mcp-description.ts
|
|
2379
|
+
var mcpDescription = `Canvas MCP - Working with widgets and styles: how to use the PropType schemas and generate PropValue structures
|
|
2380
|
+
|
|
2381
|
+
# Elementor's PropValue configuration system
|
|
2382
|
+
|
|
2383
|
+
Every widget in Elementor has a set of properties that can be configured, defined in a STRICT SCHEMA we call "PropType".
|
|
2384
|
+
All widget configuration values are represented using a structure we call "PropValue".
|
|
2385
|
+
|
|
2386
|
+
To correctly configure a widget's properties, FOLLOW THE PropType schema defined for that widget. This schema outlines the expected structure and types for each property, ensuring that the values you provide are valid and can be properly interpreted by Elementor.
|
|
2387
|
+
Every widget has it's own PropType schema, retreivable from the resource [${WIDGET_SCHEMA_URI}].
|
|
2388
|
+
ALL WIDGETS share a common _styles property with a uniform styles schema, retreivable from the resource [${STYLE_SCHEMA_URI}].
|
|
2389
|
+
The style schema is grouped by categories, such as "typography", "background", "border", etc.
|
|
2390
|
+
|
|
2391
|
+
# Tools and usage
|
|
2392
|
+
- Use the "get-element-configuration-values" tool to retrieve the current configuration of a specific element, including its PropValues and styles. It is recommended to use this tool when you are required to make changes to an existing element, to ensure you have the correct current configuration schema.
|
|
2393
|
+
If a PropValue changes it's type (only on union PropTypes), read the new schema from the resources mentioned above, and adjust the PropValue structure accordingly.
|
|
2394
|
+
- Use the "build-composition" tool to create a NEW ELEMENTS in a composition on the page. You can use this tool to also create a new single element.
|
|
2395
|
+
- Use the "configure-element" tool to update the configuration of an EXISTING element on the page.
|
|
2396
|
+
|
|
2397
|
+
All array types that can receive union types, are typed as mixed array, which means that each item in the array can be of any of the allowed types defined in the PropType schema.
|
|
2398
|
+
Example: the "background" can have a background-overlay property, which can contain multiple overlays, such as color, gradient, image, etc. Each item in the array must follow the PropType schema for each overlay type.
|
|
2399
|
+
All _style properties are OPTIONAL. When a _style is defined, we MERGE the values with existing styles, so only the properties you define will be changed, and the rest will remain as is.
|
|
2400
|
+
|
|
2401
|
+
# Styling best practices
|
|
2402
|
+
Prefer using "em" and "rem" values for text-related sizes, padding and spacing. Use percentages for dynamic sizing relative to parent containers.
|
|
2403
|
+
This flexboxes are by default "flex" with "stretch" alignment. To ensure proper layout, define the "justify-content" and "align-items" as in the schema.
|
|
2404
|
+
|
|
2405
|
+
Additionaly, some PropTypes have metadata information (meta property) that can help in understaind the PropType usage, such as description or other useful information.
|
|
2406
|
+
|
|
2407
|
+
Example of null values:
|
|
2408
|
+
{
|
|
2409
|
+
$$type: 'as-defined-for-propValue',
|
|
2410
|
+
value: null
|
|
2411
|
+
}
|
|
2412
|
+
|
|
2413
|
+
Example of "image" PropValue structure:
|
|
2414
|
+
{$$type:'image',value:{src:{$$type:'image-src',value:{url:{$$type:'url',value:'https://example.com/image.jpg'}}},size:{$$type:'string',value:'full'}}}
|
|
2415
|
+
|
|
2416
|
+
`;
|
|
2417
|
+
|
|
1249
2418
|
// src/prevent-link-in-link-commands.ts
|
|
1250
2419
|
import {
|
|
1251
2420
|
getAnchoredAncestorId,
|
|
@@ -1342,17 +2511,17 @@ import {
|
|
|
1342
2511
|
|
|
1343
2512
|
// src/style-commands/undoable-actions/paste-element-style.ts
|
|
1344
2513
|
import {
|
|
1345
|
-
createElementStyle,
|
|
2514
|
+
createElementStyle as createElementStyle2,
|
|
1346
2515
|
deleteElementStyle,
|
|
1347
|
-
getElementStyles,
|
|
1348
|
-
updateElementStyle
|
|
2516
|
+
getElementStyles as getElementStyles3,
|
|
2517
|
+
updateElementStyle as updateElementStyle2
|
|
1349
2518
|
} from "@elementor/editor-elements";
|
|
1350
2519
|
import { ELEMENTS_STYLES_RESERVED_LABEL } from "@elementor/editor-styles-repository";
|
|
1351
2520
|
import { undoable } from "@elementor/editor-v1-adapters";
|
|
1352
2521
|
import { __ as __3 } from "@wordpress/i18n";
|
|
1353
2522
|
|
|
1354
2523
|
// src/style-commands/utils.ts
|
|
1355
|
-
import { getElementLabel, getWidgetsCache as
|
|
2524
|
+
import { getElementLabel, getWidgetsCache as getWidgetsCache6 } from "@elementor/editor-elements";
|
|
1356
2525
|
import { CLASSES_PROP_KEY } from "@elementor/editor-props";
|
|
1357
2526
|
import { __ as __2 } from "@wordpress/i18n";
|
|
1358
2527
|
function hasAtomicWidgets(args) {
|
|
@@ -1377,7 +2546,7 @@ function getClassesProp(container) {
|
|
|
1377
2546
|
}
|
|
1378
2547
|
function getContainerSchema(container) {
|
|
1379
2548
|
const type = container?.model.get("widgetType") || container?.model.get("elType");
|
|
1380
|
-
const widgetsCache =
|
|
2549
|
+
const widgetsCache = getWidgetsCache6();
|
|
1381
2550
|
const elementType = widgetsCache?.[type];
|
|
1382
2551
|
return elementType?.atomic_props_schema ?? null;
|
|
1383
2552
|
}
|
|
@@ -1403,7 +2572,7 @@ var undoablePasteElementStyle = () => undoable(
|
|
|
1403
2572
|
if (!classesProp) {
|
|
1404
2573
|
return null;
|
|
1405
2574
|
}
|
|
1406
|
-
const originalStyles =
|
|
2575
|
+
const originalStyles = getElementStyles3(container.id);
|
|
1407
2576
|
const [styleId, styleDef] = Object.entries(originalStyles ?? {})[0] ?? [];
|
|
1408
2577
|
const originalStyle = Object.keys(styleDef ?? {}).length ? styleDef : null;
|
|
1409
2578
|
const revertData = {
|
|
@@ -1412,7 +2581,7 @@ var undoablePasteElementStyle = () => undoable(
|
|
|
1412
2581
|
};
|
|
1413
2582
|
if (styleId) {
|
|
1414
2583
|
newStyle.variants.forEach(({ meta, props, custom_css: customCss }) => {
|
|
1415
|
-
|
|
2584
|
+
updateElementStyle2({
|
|
1416
2585
|
elementId,
|
|
1417
2586
|
styleId,
|
|
1418
2587
|
meta,
|
|
@@ -1423,7 +2592,7 @@ var undoablePasteElementStyle = () => undoable(
|
|
|
1423
2592
|
} else {
|
|
1424
2593
|
const [firstVariant] = newStyle.variants;
|
|
1425
2594
|
const additionalVariants = newStyle.variants.slice(1);
|
|
1426
|
-
revertData.styleId =
|
|
2595
|
+
revertData.styleId = createElementStyle2({
|
|
1427
2596
|
elementId,
|
|
1428
2597
|
classesProp,
|
|
1429
2598
|
label: ELEMENTS_STYLES_RESERVED_LABEL,
|
|
@@ -1450,7 +2619,7 @@ var undoablePasteElementStyle = () => undoable(
|
|
|
1450
2619
|
}
|
|
1451
2620
|
const [firstVariant] = revertData.originalStyle.variants;
|
|
1452
2621
|
const additionalVariants = revertData.originalStyle.variants.slice(1);
|
|
1453
|
-
|
|
2622
|
+
createElementStyle2({
|
|
1454
2623
|
elementId: container.id,
|
|
1455
2624
|
classesProp,
|
|
1456
2625
|
label: ELEMENTS_STYLES_RESERVED_LABEL,
|
|
@@ -1506,7 +2675,7 @@ import {
|
|
|
1506
2675
|
} from "@elementor/editor-v1-adapters";
|
|
1507
2676
|
|
|
1508
2677
|
// src/style-commands/undoable-actions/reset-element-style.ts
|
|
1509
|
-
import { createElementStyle as
|
|
2678
|
+
import { createElementStyle as createElementStyle3, deleteElementStyle as deleteElementStyle2, getElementStyles as getElementStyles4 } from "@elementor/editor-elements";
|
|
1510
2679
|
import { ELEMENTS_STYLES_RESERVED_LABEL as ELEMENTS_STYLES_RESERVED_LABEL2 } from "@elementor/editor-styles-repository";
|
|
1511
2680
|
import { undoable as undoable2 } from "@elementor/editor-v1-adapters";
|
|
1512
2681
|
import { __ as __4 } from "@wordpress/i18n";
|
|
@@ -1515,7 +2684,7 @@ var undoableResetElementStyle = () => undoable2(
|
|
|
1515
2684
|
do: ({ containers }) => {
|
|
1516
2685
|
return containers.map((container) => {
|
|
1517
2686
|
const elementId = container.model.get("id");
|
|
1518
|
-
const containerStyles =
|
|
2687
|
+
const containerStyles = getElementStyles4(elementId);
|
|
1519
2688
|
Object.keys(containerStyles ?? {}).forEach(
|
|
1520
2689
|
(styleId) => deleteElementStyle2(elementId, styleId)
|
|
1521
2690
|
);
|
|
@@ -1533,7 +2702,7 @@ var undoableResetElementStyle = () => undoable2(
|
|
|
1533
2702
|
Object.entries(containerStyles ?? {}).forEach(([styleId, style]) => {
|
|
1534
2703
|
const [firstVariant] = style.variants;
|
|
1535
2704
|
const additionalVariants = style.variants.slice(1);
|
|
1536
|
-
|
|
2705
|
+
createElementStyle3({
|
|
1537
2706
|
elementId,
|
|
1538
2707
|
classesProp,
|
|
1539
2708
|
styleId,
|
|
@@ -1585,6 +2754,7 @@ function init() {
|
|
|
1585
2754
|
initLinkInLinkPrevention();
|
|
1586
2755
|
initLegacyViews();
|
|
1587
2756
|
initSettingsTransformers();
|
|
2757
|
+
initInteractionsRepository();
|
|
1588
2758
|
injectIntoTop({
|
|
1589
2759
|
id: "elements-overlays",
|
|
1590
2760
|
component: ElementsOverlays
|
|
@@ -1593,17 +2763,66 @@ function init() {
|
|
|
1593
2763
|
id: "canvas-style-render",
|
|
1594
2764
|
component: StyleRenderer
|
|
1595
2765
|
});
|
|
2766
|
+
injectIntoTop({
|
|
2767
|
+
id: "canvas-interactions-render",
|
|
2768
|
+
component: InteractionsRenderer
|
|
2769
|
+
});
|
|
1596
2770
|
injectIntoLogic({
|
|
1597
2771
|
id: "classes-rename",
|
|
1598
2772
|
component: ClassesRename
|
|
1599
2773
|
});
|
|
2774
|
+
initCanvasMcp(
|
|
2775
|
+
getMCPByDomain("canvas", {
|
|
2776
|
+
instructions: mcpDescription
|
|
2777
|
+
})
|
|
2778
|
+
);
|
|
1600
2779
|
}
|
|
2780
|
+
|
|
2781
|
+
// src/sync/drag-element-from-panel.ts
|
|
2782
|
+
var startDragElementFromPanel = (props) => {
|
|
2783
|
+
const channels = getElementorChannels();
|
|
2784
|
+
channels?.editor.reply("element:dragged", null);
|
|
2785
|
+
channels?.panelElements.reply("element:selected", getLegacyPanelElementView(props)).trigger("element:drag:start");
|
|
2786
|
+
};
|
|
2787
|
+
var endDragElementFromPanel = () => {
|
|
2788
|
+
getElementorChannels()?.panelElements?.trigger("element:drag:end");
|
|
2789
|
+
};
|
|
2790
|
+
var getElementorChannels = () => {
|
|
2791
|
+
const extendedWindow = window;
|
|
2792
|
+
const channels = extendedWindow.elementor?.channels;
|
|
2793
|
+
if (!channels) {
|
|
2794
|
+
throw new Error(
|
|
2795
|
+
"Elementor channels not found: Elementor editor is not initialized or channels are unavailable."
|
|
2796
|
+
);
|
|
2797
|
+
}
|
|
2798
|
+
return channels;
|
|
2799
|
+
};
|
|
2800
|
+
var getLegacyPanelElementView = ({ settings, ...rest }) => {
|
|
2801
|
+
const extendedWindow = window;
|
|
2802
|
+
const LegacyElementModel = extendedWindow.elementor?.modules?.elements?.models?.Element;
|
|
2803
|
+
if (!LegacyElementModel) {
|
|
2804
|
+
throw new Error("Elementor legacy Element model not found in editor modules");
|
|
2805
|
+
}
|
|
2806
|
+
const elementModel = new LegacyElementModel({
|
|
2807
|
+
...rest,
|
|
2808
|
+
custom: {
|
|
2809
|
+
isPreset: !!settings,
|
|
2810
|
+
preset_settings: settings
|
|
2811
|
+
}
|
|
2812
|
+
});
|
|
2813
|
+
return { model: elementModel };
|
|
2814
|
+
};
|
|
1601
2815
|
export {
|
|
1602
2816
|
createPropsResolver,
|
|
2817
|
+
createTemplatedElementView,
|
|
1603
2818
|
createTransformer,
|
|
1604
2819
|
createTransformersRegistry,
|
|
2820
|
+
endDragElementFromPanel,
|
|
2821
|
+
getCanvasIframeDocument,
|
|
1605
2822
|
init,
|
|
2823
|
+
registerElementType,
|
|
1606
2824
|
settingsTransformersRegistry,
|
|
2825
|
+
startDragElementFromPanel,
|
|
1607
2826
|
styleTransformersRegistry
|
|
1608
2827
|
};
|
|
1609
2828
|
//# sourceMappingURL=index.mjs.map
|