@elementor/editor-canvas 3.35.0-350 → 3.35.0-352
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 +8 -2
- package/dist/index.d.ts +8 -2
- package/dist/index.js +351 -216
- package/dist/index.mjs +321 -184
- package/package.json +18 -17
- package/src/components/__tests__/elements-overlays.test.tsx +0 -26
- package/src/components/elements-overlays.tsx +0 -8
- package/src/legacy/create-inline-editing-element-type.tsx +199 -0
- package/src/legacy/create-templated-element-type.ts +2 -2
- package/src/legacy/init-legacy-views.ts +5 -1
- package/src/legacy/types.ts +16 -7
- package/src/utils/__tests__/inline-editing.test.ts +553 -0
- package/src/utils/inline-editing-utils.ts +101 -6
- package/src/components/__tests__/inline-editor-overlay.test.tsx +0 -245
- package/src/components/inline-editor-overlay.tsx +0 -79
package/dist/index.mjs
CHANGED
|
@@ -197,8 +197,8 @@ var subscribeToStylesRepository = () => {
|
|
|
197
197
|
});
|
|
198
198
|
};
|
|
199
199
|
var renameClass = (oldClassName, newClassName) => {
|
|
200
|
-
Object.values(getV1DocumentsManager().documents).forEach((
|
|
201
|
-
const container =
|
|
200
|
+
Object.values(getV1DocumentsManager().documents).forEach((document2) => {
|
|
201
|
+
const container = document2.container;
|
|
202
202
|
container.view?.el?.querySelectorAll(`.elementor .${oldClassName}`).forEach((element) => {
|
|
203
203
|
element.classList.replace(oldClassName, newClassName);
|
|
204
204
|
});
|
|
@@ -206,60 +206,56 @@ var renameClass = (oldClassName, newClassName) => {
|
|
|
206
206
|
};
|
|
207
207
|
|
|
208
208
|
// src/components/elements-overlays.tsx
|
|
209
|
-
import * as
|
|
209
|
+
import * as React2 from "react";
|
|
210
210
|
import { getElements, useSelectedElement } from "@elementor/editor-elements";
|
|
211
211
|
import {
|
|
212
212
|
__privateUseIsRouteActive as useIsRouteActive,
|
|
213
213
|
__privateUseListenTo as useListenTo,
|
|
214
|
-
isExperimentActive,
|
|
215
214
|
useEditMode,
|
|
216
215
|
windowEvent
|
|
217
216
|
} from "@elementor/editor-v1-adapters";
|
|
218
217
|
|
|
219
|
-
// src/
|
|
220
|
-
import
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
"e-paragraph": "paragraph"
|
|
224
|
-
};
|
|
225
|
-
var getHtmlPropertyName = (container) => {
|
|
226
|
-
const widgetType = container?.model?.get("widgetType") ?? container?.model?.get("elType");
|
|
227
|
-
if (!widgetType) {
|
|
228
|
-
return "";
|
|
229
|
-
}
|
|
230
|
-
if (WIDGET_PROPERTY_MAP[widgetType]) {
|
|
231
|
-
return WIDGET_PROPERTY_MAP[widgetType];
|
|
232
|
-
}
|
|
233
|
-
const propsSchema = getElementType(widgetType)?.propsSchema;
|
|
234
|
-
if (!propsSchema) {
|
|
235
|
-
return "";
|
|
236
|
-
}
|
|
237
|
-
const entry = Object.entries(propsSchema).find(([, propType]) => propType.key === "html");
|
|
238
|
-
return entry?.[0] ?? "";
|
|
239
|
-
};
|
|
240
|
-
var hasInlineEditableProperty = (containerId) => {
|
|
241
|
-
const container = getContainer(containerId);
|
|
242
|
-
const widgetType = container?.model?.get("widgetType") ?? container?.model?.get("elType");
|
|
243
|
-
if (!widgetType) {
|
|
244
|
-
return false;
|
|
245
|
-
}
|
|
246
|
-
return widgetType in WIDGET_PROPERTY_MAP;
|
|
247
|
-
};
|
|
248
|
-
var getInlineEditablePropertyName = (container) => {
|
|
249
|
-
return getHtmlPropertyName(container);
|
|
250
|
-
};
|
|
218
|
+
// src/components/outline-overlay.tsx
|
|
219
|
+
import * as React from "react";
|
|
220
|
+
import { Box, styled } from "@elementor/ui";
|
|
221
|
+
import { FloatingPortal, useHover, useInteractions } from "@floating-ui/react";
|
|
251
222
|
|
|
252
|
-
// src/
|
|
253
|
-
import
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
223
|
+
// src/hooks/use-bind-react-props-to-element.ts
|
|
224
|
+
import { useEffect as useEffect2 } from "react";
|
|
225
|
+
function useBindReactPropsToElement(element, getProps) {
|
|
226
|
+
useEffect2(() => {
|
|
227
|
+
const el = element;
|
|
228
|
+
const { events, attrs } = groupProps(getProps());
|
|
229
|
+
events.forEach(([eventName, listener]) => el.addEventListener(eventName, listener));
|
|
230
|
+
attrs.forEach(([attrName, attrValue]) => el.setAttribute(attrName, attrValue));
|
|
231
|
+
return () => {
|
|
232
|
+
events.forEach(([eventName, listener]) => el.removeEventListener(eventName, listener));
|
|
233
|
+
attrs.forEach(([attrName]) => el.removeAttribute(attrName));
|
|
234
|
+
};
|
|
235
|
+
}, [getProps, element]);
|
|
236
|
+
}
|
|
237
|
+
function groupProps(props) {
|
|
238
|
+
const eventRegex = /^on(?=[A-Z])/;
|
|
239
|
+
return Object.entries(props).reduce(
|
|
240
|
+
(acc, [propName, propValue]) => {
|
|
241
|
+
if (!eventRegex.test(propName)) {
|
|
242
|
+
acc.attrs.push([propName, propValue]);
|
|
243
|
+
return acc;
|
|
244
|
+
}
|
|
245
|
+
const eventName = propName.replace(eventRegex, "").toLowerCase();
|
|
246
|
+
const listener = propValue;
|
|
247
|
+
acc.events.push([eventName, listener]);
|
|
248
|
+
return acc;
|
|
249
|
+
},
|
|
250
|
+
{
|
|
251
|
+
events: [],
|
|
252
|
+
attrs: []
|
|
253
|
+
}
|
|
254
|
+
);
|
|
255
|
+
}
|
|
260
256
|
|
|
261
257
|
// src/hooks/use-floating-on-element.ts
|
|
262
|
-
import { useEffect as
|
|
258
|
+
import { useEffect as useEffect3, useState } from "react";
|
|
263
259
|
import { autoUpdate, offset, size, useFloating } from "@floating-ui/react";
|
|
264
260
|
function useFloatingOnElement({ element, isSelected }) {
|
|
265
261
|
const [isOpen, setIsOpen] = useState(false);
|
|
@@ -285,7 +281,7 @@ function useFloatingOnElement({ element, isSelected }) {
|
|
|
285
281
|
offset(({ rects }) => -rects.reference.height / 2 - rects.floating.height / 2)
|
|
286
282
|
]
|
|
287
283
|
});
|
|
288
|
-
|
|
284
|
+
useEffect3(() => {
|
|
289
285
|
refs.setReference(element);
|
|
290
286
|
}, [element, refs]);
|
|
291
287
|
return {
|
|
@@ -299,45 +295,6 @@ function useFloatingOnElement({ element, isSelected }) {
|
|
|
299
295
|
};
|
|
300
296
|
}
|
|
301
297
|
|
|
302
|
-
// src/components/outline-overlay.tsx
|
|
303
|
-
import * as React from "react";
|
|
304
|
-
import { Box, styled } from "@elementor/ui";
|
|
305
|
-
import { FloatingPortal, useHover, useInteractions } from "@floating-ui/react";
|
|
306
|
-
|
|
307
|
-
// src/hooks/use-bind-react-props-to-element.ts
|
|
308
|
-
import { useEffect as useEffect3 } from "react";
|
|
309
|
-
function useBindReactPropsToElement(element, getProps) {
|
|
310
|
-
useEffect3(() => {
|
|
311
|
-
const el = element;
|
|
312
|
-
const { events, attrs } = groupProps(getProps());
|
|
313
|
-
events.forEach(([eventName, listener]) => el.addEventListener(eventName, listener));
|
|
314
|
-
attrs.forEach(([attrName, attrValue]) => el.setAttribute(attrName, attrValue));
|
|
315
|
-
return () => {
|
|
316
|
-
events.forEach(([eventName, listener]) => el.removeEventListener(eventName, listener));
|
|
317
|
-
attrs.forEach(([attrName]) => el.removeAttribute(attrName));
|
|
318
|
-
};
|
|
319
|
-
}, [getProps, element]);
|
|
320
|
-
}
|
|
321
|
-
function groupProps(props) {
|
|
322
|
-
const eventRegex = /^on(?=[A-Z])/;
|
|
323
|
-
return Object.entries(props).reduce(
|
|
324
|
-
(acc, [propName, propValue]) => {
|
|
325
|
-
if (!eventRegex.test(propName)) {
|
|
326
|
-
acc.attrs.push([propName, propValue]);
|
|
327
|
-
return acc;
|
|
328
|
-
}
|
|
329
|
-
const eventName = propName.replace(eventRegex, "").toLowerCase();
|
|
330
|
-
const listener = propValue;
|
|
331
|
-
acc.events.push([eventName, listener]);
|
|
332
|
-
return acc;
|
|
333
|
-
},
|
|
334
|
-
{
|
|
335
|
-
events: [],
|
|
336
|
-
attrs: []
|
|
337
|
-
}
|
|
338
|
-
);
|
|
339
|
-
}
|
|
340
|
-
|
|
341
298
|
// src/hooks/use-has-overlapping.ts
|
|
342
299
|
var possibleOverlappingSelectors = [".e-off-canvas"];
|
|
343
300
|
var useHasOverlapping = () => {
|
|
@@ -384,71 +341,12 @@ var OutlineOverlay = ({ element, isSelected, id }) => {
|
|
|
384
341
|
));
|
|
385
342
|
};
|
|
386
343
|
|
|
387
|
-
// src/components/inline-editor-overlay.tsx
|
|
388
|
-
var OVERLAY_Z_INDEX = 1e3;
|
|
389
|
-
var DEBOUNCE_DELAY = 100;
|
|
390
|
-
var InlineEditorOverlay = ({ element, isSelected, id }) => {
|
|
391
|
-
const { floating, isVisible } = useFloatingOnElement({ element, isSelected });
|
|
392
|
-
const propertyName = React2.useMemo(() => {
|
|
393
|
-
const container = getContainer2(id);
|
|
394
|
-
return getInlineEditablePropertyName(container);
|
|
395
|
-
}, [id]);
|
|
396
|
-
const contentProp = useElementSetting(id, propertyName);
|
|
397
|
-
const value = React2.useMemo(() => htmlPropTypeUtil.extract(contentProp) || "", [contentProp]);
|
|
398
|
-
const debouncedUpdateRef = React2.useRef(null);
|
|
399
|
-
const lastValueRef = React2.useRef("");
|
|
400
|
-
React2.useEffect(() => {
|
|
401
|
-
debouncedUpdateRef.current = debounce((newValue) => {
|
|
402
|
-
const textContent = newValue.replace(/<[^>]*>/g, "").trim();
|
|
403
|
-
const valueToSave = textContent === "" ? " " : newValue;
|
|
404
|
-
updateElementSettings({
|
|
405
|
-
id,
|
|
406
|
-
props: {
|
|
407
|
-
[propertyName]: htmlPropTypeUtil.create(valueToSave)
|
|
408
|
-
},
|
|
409
|
-
withHistory: true
|
|
410
|
-
});
|
|
411
|
-
}, DEBOUNCE_DELAY);
|
|
412
|
-
return () => {
|
|
413
|
-
debouncedUpdateRef.current?.cancel?.();
|
|
414
|
-
};
|
|
415
|
-
}, [id, propertyName]);
|
|
416
|
-
const handleValueChange = React2.useCallback((newValue) => {
|
|
417
|
-
lastValueRef.current = newValue;
|
|
418
|
-
debouncedUpdateRef.current?.(newValue);
|
|
419
|
-
}, []);
|
|
420
|
-
React2.useEffect(() => {
|
|
421
|
-
if (!isVisible && debouncedUpdateRef.current?.pending?.()) {
|
|
422
|
-
debouncedUpdateRef.current.flush(lastValueRef.current);
|
|
423
|
-
}
|
|
424
|
-
}, [isVisible]);
|
|
425
|
-
if (!isVisible) {
|
|
426
|
-
return null;
|
|
427
|
-
}
|
|
428
|
-
return /* @__PURE__ */ React2.createElement(FloatingPortal2, { id: CANVAS_WRAPPER_ID }, /* @__PURE__ */ React2.createElement(
|
|
429
|
-
Box2,
|
|
430
|
-
{
|
|
431
|
-
ref: floating.setRef,
|
|
432
|
-
style: {
|
|
433
|
-
...floating.styles,
|
|
434
|
-
zIndex: OVERLAY_Z_INDEX,
|
|
435
|
-
pointerEvents: "auto"
|
|
436
|
-
}
|
|
437
|
-
},
|
|
438
|
-
/* @__PURE__ */ React2.createElement(InlineEditor, { value, setValue: handleValueChange, showToolbar: isSelected })
|
|
439
|
-
));
|
|
440
|
-
};
|
|
441
|
-
|
|
442
344
|
// src/components/elements-overlays.tsx
|
|
443
345
|
var ELEMENTS_DATA_ATTR = "atomic";
|
|
444
346
|
var overlayRegistry = [
|
|
445
347
|
{
|
|
446
348
|
component: OutlineOverlay,
|
|
447
349
|
shouldRender: () => true
|
|
448
|
-
},
|
|
449
|
-
{
|
|
450
|
-
component: InlineEditorOverlay,
|
|
451
|
-
shouldRender: ({ id, isSelected }) => isSelected && hasInlineEditableProperty(id) && isExperimentActive("v4-inline-text-editing")
|
|
452
350
|
}
|
|
453
351
|
];
|
|
454
352
|
function ElementsOverlays() {
|
|
@@ -464,7 +362,7 @@ function ElementsOverlays() {
|
|
|
464
362
|
return elements.map(([id, element]) => {
|
|
465
363
|
const isSelected = selected.element?.id === id;
|
|
466
364
|
return overlayRegistry.map(
|
|
467
|
-
({ shouldRender, component: Overlay }, index) => shouldRender({ id, element, isSelected }) && /* @__PURE__ */
|
|
365
|
+
({ shouldRender, component: Overlay }, index) => shouldRender({ id, element, isSelected }) && /* @__PURE__ */ React2.createElement(Overlay, { key: `${id}-${index}`, id, element, isSelected })
|
|
468
366
|
);
|
|
469
367
|
});
|
|
470
368
|
}
|
|
@@ -478,20 +376,20 @@ function useElementsDom() {
|
|
|
478
376
|
}
|
|
479
377
|
|
|
480
378
|
// src/components/interactions-renderer.tsx
|
|
481
|
-
import * as
|
|
379
|
+
import * as React3 from "react";
|
|
482
380
|
import { __privateUseListenTo as useListenTo2, commandEndEvent } from "@elementor/editor-v1-adapters";
|
|
483
381
|
import { Portal } from "@elementor/ui";
|
|
484
382
|
|
|
485
383
|
// src/hooks/use-interactions-items.ts
|
|
486
|
-
import { useEffect as
|
|
384
|
+
import { useEffect as useEffect5, useMemo, useState as useState2 } from "react";
|
|
487
385
|
import { interactionsRepository } from "@elementor/editor-interactions";
|
|
488
386
|
import { registerDataHook } from "@elementor/editor-v1-adapters";
|
|
489
387
|
|
|
490
388
|
// src/hooks/use-on-mount.ts
|
|
491
|
-
import { useEffect as
|
|
389
|
+
import { useEffect as useEffect4, useRef } from "react";
|
|
492
390
|
function useOnMount(cb) {
|
|
493
|
-
const mounted =
|
|
494
|
-
|
|
391
|
+
const mounted = useRef(false);
|
|
392
|
+
useEffect4(() => {
|
|
495
393
|
if (!mounted.current) {
|
|
496
394
|
mounted.current = true;
|
|
497
395
|
cb();
|
|
@@ -502,7 +400,7 @@ function useOnMount(cb) {
|
|
|
502
400
|
// src/hooks/use-interactions-items.ts
|
|
503
401
|
function useInteractionsItems() {
|
|
504
402
|
const [interactionItems, setInteractionItems] = useState2({});
|
|
505
|
-
const providerAndSubscribers =
|
|
403
|
+
const providerAndSubscribers = useMemo(() => {
|
|
506
404
|
try {
|
|
507
405
|
const providers = interactionsRepository.getProviders();
|
|
508
406
|
const mapped = providers.map((provider) => {
|
|
@@ -519,7 +417,7 @@ function useInteractionsItems() {
|
|
|
519
417
|
return [];
|
|
520
418
|
}
|
|
521
419
|
}, []);
|
|
522
|
-
|
|
420
|
+
useEffect5(() => {
|
|
523
421
|
if (providerAndSubscribers.length === 0) {
|
|
524
422
|
return;
|
|
525
423
|
}
|
|
@@ -550,7 +448,7 @@ function useInteractionsItems() {
|
|
|
550
448
|
});
|
|
551
449
|
});
|
|
552
450
|
});
|
|
553
|
-
return
|
|
451
|
+
return useMemo(() => {
|
|
554
452
|
const result = Object.values(interactionItems).sort(sortByProviderPriority).flatMap(({ items }) => items);
|
|
555
453
|
return result;
|
|
556
454
|
}, [interactionItems]);
|
|
@@ -586,7 +484,7 @@ function InteractionsRenderer() {
|
|
|
586
484
|
return null;
|
|
587
485
|
}
|
|
588
486
|
const interactionsData = JSON.stringify(Array.isArray(interactionItems) ? interactionItems : []);
|
|
589
|
-
return /* @__PURE__ */
|
|
487
|
+
return /* @__PURE__ */ React3.createElement(Portal, { container }, /* @__PURE__ */ React3.createElement(
|
|
590
488
|
"script",
|
|
591
489
|
{
|
|
592
490
|
type: "application/json",
|
|
@@ -602,7 +500,7 @@ function usePortalContainer() {
|
|
|
602
500
|
}
|
|
603
501
|
|
|
604
502
|
// src/components/style-renderer.tsx
|
|
605
|
-
import * as
|
|
503
|
+
import * as React4 from "react";
|
|
606
504
|
import { __privateUseListenTo as useListenTo4, commandEndEvent as commandEndEvent3 } from "@elementor/editor-v1-adapters";
|
|
607
505
|
import { Portal as Portal2 } from "@elementor/ui";
|
|
608
506
|
|
|
@@ -636,14 +534,14 @@ function useDocumentsCssLinks() {
|
|
|
636
534
|
}));
|
|
637
535
|
});
|
|
638
536
|
}
|
|
639
|
-
function getDocumentsIdsInCanvas(
|
|
640
|
-
return [...
|
|
537
|
+
function getDocumentsIdsInCanvas(document2) {
|
|
538
|
+
return [...document2.body.querySelectorAll(`[${DOCUMENT_WRAPPER_ATTR}]`) ?? []].map(
|
|
641
539
|
(el) => el.getAttribute(DOCUMENT_WRAPPER_ATTR) || ""
|
|
642
540
|
);
|
|
643
541
|
}
|
|
644
|
-
function getDocumentsCssLinks(
|
|
542
|
+
function getDocumentsCssLinks(document2) {
|
|
645
543
|
return [
|
|
646
|
-
...
|
|
544
|
+
...document2.head.querySelectorAll(
|
|
647
545
|
`link[rel="stylesheet"][id^=${CSS_LINK_ID_PREFIX}][id$=${CSS_LINK_ID_SUFFIX}]`
|
|
648
546
|
) ?? []
|
|
649
547
|
];
|
|
@@ -654,7 +552,7 @@ function getLinkAttrs(el) {
|
|
|
654
552
|
}
|
|
655
553
|
|
|
656
554
|
// src/hooks/use-style-items.ts
|
|
657
|
-
import { useEffect as
|
|
555
|
+
import { useEffect as useEffect6, useMemo as useMemo4, useState as useState3 } from "react";
|
|
658
556
|
import { getBreakpoints } from "@elementor/editor-responsive";
|
|
659
557
|
import { isClassState as isClassState2 } from "@elementor/editor-styles";
|
|
660
558
|
import { stylesRepository as stylesRepository2 } from "@elementor/editor-styles-repository";
|
|
@@ -692,7 +590,7 @@ function signalizedProcess(signal, steps = []) {
|
|
|
692
590
|
}
|
|
693
591
|
|
|
694
592
|
// src/hooks/use-style-prop-resolver.ts
|
|
695
|
-
import { useMemo as
|
|
593
|
+
import { useMemo as useMemo2 } from "react";
|
|
696
594
|
import { getStylesSchema as getStylesSchema2 } from "@elementor/editor-styles";
|
|
697
595
|
|
|
698
596
|
// src/renderers/create-props-resolver.ts
|
|
@@ -823,7 +721,7 @@ var enqueueFont = (fontFamily, context = "preview") => {
|
|
|
823
721
|
|
|
824
722
|
// src/hooks/use-style-prop-resolver.ts
|
|
825
723
|
function useStylePropResolver() {
|
|
826
|
-
return
|
|
724
|
+
return useMemo2(() => {
|
|
827
725
|
return createPropsResolver({
|
|
828
726
|
transformers: styleTransformersRegistry,
|
|
829
727
|
schema: getStylesSchema2(),
|
|
@@ -838,7 +736,7 @@ function useStylePropResolver() {
|
|
|
838
736
|
}
|
|
839
737
|
|
|
840
738
|
// src/hooks/use-style-renderer.ts
|
|
841
|
-
import { useMemo as
|
|
739
|
+
import { useMemo as useMemo3 } from "react";
|
|
842
740
|
import { useBreakpointsMap } from "@elementor/editor-responsive";
|
|
843
741
|
|
|
844
742
|
// src/renderers/create-styles-renderer.ts
|
|
@@ -942,7 +840,7 @@ function customCssToString(customCss) {
|
|
|
942
840
|
var SELECTOR_PREFIX = ".elementor";
|
|
943
841
|
function useStyleRenderer(resolve) {
|
|
944
842
|
const breakpoints = useBreakpointsMap();
|
|
945
|
-
return
|
|
843
|
+
return useMemo3(() => {
|
|
946
844
|
return createStylesRenderer({
|
|
947
845
|
selectorPrefix: SELECTOR_PREFIX,
|
|
948
846
|
breakpoints,
|
|
@@ -956,7 +854,7 @@ function useStyleItems() {
|
|
|
956
854
|
const resolve = useStylePropResolver();
|
|
957
855
|
const renderStyles = useStyleRenderer(resolve);
|
|
958
856
|
const [styleItems, setStyleItems] = useState3({});
|
|
959
|
-
const providerAndSubscribers =
|
|
857
|
+
const providerAndSubscribers = useMemo4(() => {
|
|
960
858
|
return stylesRepository2.getProviders().map((provider) => {
|
|
961
859
|
return {
|
|
962
860
|
provider,
|
|
@@ -968,7 +866,7 @@ function useStyleItems() {
|
|
|
968
866
|
};
|
|
969
867
|
});
|
|
970
868
|
}, [renderStyles]);
|
|
971
|
-
|
|
869
|
+
useEffect6(() => {
|
|
972
870
|
const unsubscribes = providerAndSubscribers.map(
|
|
973
871
|
({ provider, subscriber }) => provider.subscribe(subscriber)
|
|
974
872
|
);
|
|
@@ -983,7 +881,7 @@ function useStyleItems() {
|
|
|
983
881
|
});
|
|
984
882
|
});
|
|
985
883
|
const breakpointsOrder = getBreakpoints().map((breakpoint) => breakpoint.id);
|
|
986
|
-
return
|
|
884
|
+
return useMemo4(
|
|
987
885
|
() => Object.values(styleItems).sort(sortByProviderPriority2).flatMap(({ items }) => items).sort(sortByStateType).sort(sortByBreakpoint(breakpointsOrder)),
|
|
988
886
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
989
887
|
[styleItems, breakpointsOrder.join("-")]
|
|
@@ -1056,7 +954,7 @@ function StyleRenderer() {
|
|
|
1056
954
|
if (!container) {
|
|
1057
955
|
return null;
|
|
1058
956
|
}
|
|
1059
|
-
return /* @__PURE__ */
|
|
957
|
+
return /* @__PURE__ */ React4.createElement(Portal2, { container }, styleItems.map((item, i) => /* @__PURE__ */ React4.createElement("style", { key: `${item.id}-${i}-${item.breakpoint}` }, item.value)), linksAttrs.map((attrs) => /* @__PURE__ */ React4.createElement("link", { ...attrs, key: attrs.id })));
|
|
1060
958
|
}
|
|
1061
959
|
function usePortalContainer2() {
|
|
1062
960
|
return useListenTo4(commandEndEvent3("editor/documents/attach-preview"), () => getCanvasIframeDocument()?.head);
|
|
@@ -1540,10 +1438,102 @@ function escapeURL(value) {
|
|
|
1540
1438
|
}
|
|
1541
1439
|
}
|
|
1542
1440
|
|
|
1441
|
+
// src/utils/inline-editing-utils.ts
|
|
1442
|
+
import { getContainer, getElementType } from "@elementor/editor-elements";
|
|
1443
|
+
import { isExperimentActive } from "@elementor/editor-v1-adapters";
|
|
1444
|
+
var WIDGET_PROPERTY_MAP = {
|
|
1445
|
+
"e-heading": "title",
|
|
1446
|
+
"e-paragraph": "paragraph"
|
|
1447
|
+
};
|
|
1448
|
+
var EXPERIMENT_KEY = "v4-inline-text-editing";
|
|
1449
|
+
var legacyWindow = window;
|
|
1450
|
+
var shouldRenderInlineEditingView = (elementType) => {
|
|
1451
|
+
return elementType in WIDGET_PROPERTY_MAP && isExperimentActive(EXPERIMENT_KEY);
|
|
1452
|
+
};
|
|
1453
|
+
var getWidgetType = (container) => {
|
|
1454
|
+
return container?.model?.get("widgetType") ?? container?.model?.get("elType") ?? null;
|
|
1455
|
+
};
|
|
1456
|
+
var getHtmlPropertyName = (container) => {
|
|
1457
|
+
const widgetType = getWidgetType(container);
|
|
1458
|
+
if (!widgetType) {
|
|
1459
|
+
return "";
|
|
1460
|
+
}
|
|
1461
|
+
const propsSchema = getElementType(widgetType)?.propsSchema;
|
|
1462
|
+
if (WIDGET_PROPERTY_MAP[widgetType]) {
|
|
1463
|
+
return WIDGET_PROPERTY_MAP[widgetType];
|
|
1464
|
+
}
|
|
1465
|
+
if (!propsSchema) {
|
|
1466
|
+
return "";
|
|
1467
|
+
}
|
|
1468
|
+
const entry = Object.entries(propsSchema).find(([, propType]) => {
|
|
1469
|
+
switch (propType.kind) {
|
|
1470
|
+
case "union":
|
|
1471
|
+
return propType.prop_types.html;
|
|
1472
|
+
case "object":
|
|
1473
|
+
return propType.shape.html;
|
|
1474
|
+
case "array":
|
|
1475
|
+
return "key" in propType.item_prop_type && propType.item_prop_type.key === "html";
|
|
1476
|
+
}
|
|
1477
|
+
return propType.key === "html";
|
|
1478
|
+
});
|
|
1479
|
+
return entry?.[0] ?? "";
|
|
1480
|
+
};
|
|
1481
|
+
var getHtmlPropType = (container) => {
|
|
1482
|
+
const widgetType = getWidgetType(container);
|
|
1483
|
+
if (!widgetType) {
|
|
1484
|
+
return null;
|
|
1485
|
+
}
|
|
1486
|
+
const propsSchema = getElementType(widgetType)?.propsSchema;
|
|
1487
|
+
const propertyName = getHtmlPropertyName(container) ?? null;
|
|
1488
|
+
return propsSchema?.[propertyName] ?? null;
|
|
1489
|
+
};
|
|
1490
|
+
var getInlineEditablePropertyName = (container) => {
|
|
1491
|
+
return getHtmlPropertyName(container) ?? "";
|
|
1492
|
+
};
|
|
1493
|
+
var getBlockedValue = (value, tag) => {
|
|
1494
|
+
if (!value) {
|
|
1495
|
+
return "";
|
|
1496
|
+
}
|
|
1497
|
+
if (!tag) {
|
|
1498
|
+
return value;
|
|
1499
|
+
}
|
|
1500
|
+
const pseudoElement = document.createElement("div");
|
|
1501
|
+
pseudoElement.innerHTML = value;
|
|
1502
|
+
if (!pseudoElement?.children.length) {
|
|
1503
|
+
return `<${tag}>${value}</${tag}>`;
|
|
1504
|
+
}
|
|
1505
|
+
const firstChild = pseudoElement.children[0];
|
|
1506
|
+
const lastChild = Array.from(pseudoElement.children).slice(-1)[0];
|
|
1507
|
+
if (firstChild === lastChild && pseudoElement.textContent === firstChild.textContent) {
|
|
1508
|
+
return compareTag(firstChild, tag) ? value : `<${tag}>${firstChild.innerHTML}</${tag}>`;
|
|
1509
|
+
}
|
|
1510
|
+
if (!value.startsWith(`<${tag}`) || !value.endsWith(`</${tag}>`)) {
|
|
1511
|
+
return `<${tag}>${value}</${tag}>`;
|
|
1512
|
+
}
|
|
1513
|
+
if (firstChild !== lastChild || !compareTag(firstChild, tag)) {
|
|
1514
|
+
return `<${tag}>${value}</${tag}>`;
|
|
1515
|
+
}
|
|
1516
|
+
return value;
|
|
1517
|
+
};
|
|
1518
|
+
var compareTag = (el, tag) => {
|
|
1519
|
+
return el.tagName.toUpperCase() === tag.toUpperCase();
|
|
1520
|
+
};
|
|
1521
|
+
var getInitialPopoverPosition = () => {
|
|
1522
|
+
const positionFallback = { left: 0, top: 0 };
|
|
1523
|
+
const iFrameElement = legacyWindow?.elementor?.$preview?.get(0);
|
|
1524
|
+
const iFramePosition = iFrameElement?.getBoundingClientRect() ?? positionFallback;
|
|
1525
|
+
const previewElement = legacyWindow?.elementor?.$previewWrapper?.get(0);
|
|
1526
|
+
const previewPosition = previewElement ? { left: previewElement.scrollLeft, top: previewElement.scrollTop } : positionFallback;
|
|
1527
|
+
return {
|
|
1528
|
+
left: iFramePosition.left + previewPosition.left,
|
|
1529
|
+
top: iFramePosition.top + previewPosition.top
|
|
1530
|
+
};
|
|
1531
|
+
};
|
|
1532
|
+
|
|
1543
1533
|
// src/legacy/create-element-type.ts
|
|
1544
1534
|
function createElementType(type) {
|
|
1545
|
-
const
|
|
1546
|
-
return class extends
|
|
1535
|
+
const legacyWindow2 = window;
|
|
1536
|
+
return class extends legacyWindow2.elementor.modules.elements.types.Widget {
|
|
1547
1537
|
getType() {
|
|
1548
1538
|
return type;
|
|
1549
1539
|
}
|
|
@@ -1553,8 +1543,8 @@ function createElementType(type) {
|
|
|
1553
1543
|
};
|
|
1554
1544
|
}
|
|
1555
1545
|
function createElementViewClassDeclaration() {
|
|
1556
|
-
const
|
|
1557
|
-
return class extends
|
|
1546
|
+
const legacyWindow2 = window;
|
|
1547
|
+
return class extends legacyWindow2.elementor.modules.elements.views.Widget {
|
|
1558
1548
|
// Dispatch `render` event so the overlay layer will be updated
|
|
1559
1549
|
onRender(...args) {
|
|
1560
1550
|
super.onRender(...args);
|
|
@@ -1600,7 +1590,7 @@ function createElementViewClassDeclaration() {
|
|
|
1600
1590
|
);
|
|
1601
1591
|
}
|
|
1602
1592
|
#dispatchPreviewEvent(eventType) {
|
|
1603
|
-
|
|
1593
|
+
legacyWindow2.elementor?.$preview?.[0]?.contentWindow.dispatchEvent(
|
|
1604
1594
|
new CustomEvent(eventType, {
|
|
1605
1595
|
detail: {
|
|
1606
1596
|
id: this.model.get("id"),
|
|
@@ -1616,14 +1606,25 @@ function createElementViewClassDeclaration() {
|
|
|
1616
1606
|
};
|
|
1617
1607
|
}
|
|
1618
1608
|
|
|
1609
|
+
// src/legacy/create-inline-editing-element-type.tsx
|
|
1610
|
+
import * as React5 from "react";
|
|
1611
|
+
import { createRoot } from "react-dom/client";
|
|
1612
|
+
import { InlineEditor } from "@elementor/editor-controls";
|
|
1613
|
+
import { getElementType as getElementType2 } from "@elementor/editor-elements";
|
|
1614
|
+
import {
|
|
1615
|
+
htmlPropTypeUtil,
|
|
1616
|
+
stringPropTypeUtil
|
|
1617
|
+
} from "@elementor/editor-props";
|
|
1618
|
+
import { ThemeProvider } from "@elementor/editor-ui";
|
|
1619
|
+
|
|
1619
1620
|
// src/legacy/create-templated-element-type.ts
|
|
1620
1621
|
function createTemplatedElementType({
|
|
1621
1622
|
type,
|
|
1622
1623
|
renderer,
|
|
1623
1624
|
element
|
|
1624
1625
|
}) {
|
|
1625
|
-
const
|
|
1626
|
-
return class extends
|
|
1626
|
+
const legacyWindow2 = window;
|
|
1627
|
+
return class extends legacyWindow2.elementor.modules.elements.types.Widget {
|
|
1627
1628
|
getType() {
|
|
1628
1629
|
return type;
|
|
1629
1630
|
}
|
|
@@ -1714,6 +1715,142 @@ function createTemplatedElementView({
|
|
|
1714
1715
|
};
|
|
1715
1716
|
}
|
|
1716
1717
|
|
|
1718
|
+
// src/legacy/create-inline-editing-element-type.tsx
|
|
1719
|
+
function createInlineEditingElementType({
|
|
1720
|
+
type,
|
|
1721
|
+
renderer,
|
|
1722
|
+
element
|
|
1723
|
+
}) {
|
|
1724
|
+
return class extends legacyWindow.elementor.modules.elements.types.Widget {
|
|
1725
|
+
getType() {
|
|
1726
|
+
return type;
|
|
1727
|
+
}
|
|
1728
|
+
getView() {
|
|
1729
|
+
return createInlineEditingElementView({
|
|
1730
|
+
type,
|
|
1731
|
+
renderer,
|
|
1732
|
+
element
|
|
1733
|
+
});
|
|
1734
|
+
}
|
|
1735
|
+
};
|
|
1736
|
+
}
|
|
1737
|
+
function createInlineEditingElementView({
|
|
1738
|
+
type,
|
|
1739
|
+
renderer,
|
|
1740
|
+
element
|
|
1741
|
+
}) {
|
|
1742
|
+
const TemplatedView = createTemplatedElementView({ type, renderer, element });
|
|
1743
|
+
Object.entries(element.twig_templates).forEach(([key, template]) => {
|
|
1744
|
+
renderer.register(key, template);
|
|
1745
|
+
});
|
|
1746
|
+
return class extends TemplatedView {
|
|
1747
|
+
inlineEditorRoot = null;
|
|
1748
|
+
handlerAttached = false;
|
|
1749
|
+
render() {
|
|
1750
|
+
if (this.inlineEditorRoot) {
|
|
1751
|
+
this.resetInlineEditorRoot();
|
|
1752
|
+
}
|
|
1753
|
+
if (!this.isValueDynamic() && !this.handlerAttached) {
|
|
1754
|
+
this.$el.on("dblclick", "*", this.handleRenderInlineEditor.bind(this));
|
|
1755
|
+
this.handlerAttached = true;
|
|
1756
|
+
}
|
|
1757
|
+
TemplatedView.prototype.render.apply(this);
|
|
1758
|
+
}
|
|
1759
|
+
handleRenderInlineEditor(event) {
|
|
1760
|
+
event.stopPropagation();
|
|
1761
|
+
this.$el.off("dblclick", "*");
|
|
1762
|
+
this.handlerAttached = false;
|
|
1763
|
+
if (!this.isValueDynamic()) {
|
|
1764
|
+
this.renderInlineEditor();
|
|
1765
|
+
}
|
|
1766
|
+
}
|
|
1767
|
+
handleUnmountInlineEditor(event) {
|
|
1768
|
+
event.stopPropagation();
|
|
1769
|
+
this.unmountInlineEditor();
|
|
1770
|
+
}
|
|
1771
|
+
onDestroy(...args) {
|
|
1772
|
+
this.resetInlineEditorRoot();
|
|
1773
|
+
TemplatedView.prototype.onDestroy.apply(this, args);
|
|
1774
|
+
}
|
|
1775
|
+
resetInlineEditorRoot() {
|
|
1776
|
+
this.$el.off("dblclick", "*");
|
|
1777
|
+
this.handlerAttached = false;
|
|
1778
|
+
this.inlineEditorRoot?.unmount?.();
|
|
1779
|
+
this.inlineEditorRoot = null;
|
|
1780
|
+
}
|
|
1781
|
+
unmountInlineEditor() {
|
|
1782
|
+
this.resetInlineEditorRoot();
|
|
1783
|
+
this.render();
|
|
1784
|
+
}
|
|
1785
|
+
isValueDynamic() {
|
|
1786
|
+
const settingKey = getInlineEditablePropertyName(this.container);
|
|
1787
|
+
const propValue = this.model.get("settings")?.get(settingKey);
|
|
1788
|
+
return propValue?.$$type === "dynamic";
|
|
1789
|
+
}
|
|
1790
|
+
getContentValue() {
|
|
1791
|
+
const prop = getHtmlPropType(this.container);
|
|
1792
|
+
const defaultValue = prop?.default?.value ?? "";
|
|
1793
|
+
const settingKey = getInlineEditablePropertyName(this.container);
|
|
1794
|
+
return htmlPropTypeUtil.extract(this.model.get("settings")?.get(settingKey) ?? null) ?? htmlPropTypeUtil.extract(prop?.default ?? null) ?? defaultValue ?? "";
|
|
1795
|
+
}
|
|
1796
|
+
setContentValue(value) {
|
|
1797
|
+
const settingKey = getInlineEditablePropertyName(this.container);
|
|
1798
|
+
const valueToSave = value ? htmlPropTypeUtil.create(value) : null;
|
|
1799
|
+
this.model.get("settings")?.set(settingKey, valueToSave);
|
|
1800
|
+
}
|
|
1801
|
+
getExpectedTag() {
|
|
1802
|
+
const widgetType = getWidgetType(this.container);
|
|
1803
|
+
if (!widgetType) {
|
|
1804
|
+
return null;
|
|
1805
|
+
}
|
|
1806
|
+
const propsSchema = getElementType2(widgetType)?.propsSchema;
|
|
1807
|
+
if (!propsSchema?.tag) {
|
|
1808
|
+
return null;
|
|
1809
|
+
}
|
|
1810
|
+
return stringPropTypeUtil.extract(this.model.get("settings").get("tag") ?? null) ?? stringPropTypeUtil.extract(propsSchema.tag.default ?? null) ?? null;
|
|
1811
|
+
}
|
|
1812
|
+
ensureProperValue() {
|
|
1813
|
+
const actualValue = this.getContentValue();
|
|
1814
|
+
const tagSettings = this.getExpectedTag();
|
|
1815
|
+
const wrappedValue = getBlockedValue(actualValue, tagSettings);
|
|
1816
|
+
if (actualValue !== wrappedValue) {
|
|
1817
|
+
this.setContentValue(wrappedValue);
|
|
1818
|
+
}
|
|
1819
|
+
}
|
|
1820
|
+
renderInlineEditor() {
|
|
1821
|
+
this.ensureProperValue();
|
|
1822
|
+
const propValue = this.getContentValue();
|
|
1823
|
+
const settingKey = getInlineEditablePropertyName(this.container);
|
|
1824
|
+
const classes = (this.el?.children?.[0]?.classList.toString() ?? "") + " strip-styles";
|
|
1825
|
+
const expectedTag = this.getExpectedTag();
|
|
1826
|
+
const setValue = (value) => {
|
|
1827
|
+
const valueToSave = value ? htmlPropTypeUtil.create(value) : null;
|
|
1828
|
+
this.model.get("settings")?.set(settingKey, valueToSave);
|
|
1829
|
+
};
|
|
1830
|
+
this.$el.html("");
|
|
1831
|
+
if (this.inlineEditorRoot) {
|
|
1832
|
+
this.resetInlineEditorRoot();
|
|
1833
|
+
}
|
|
1834
|
+
this.inlineEditorRoot = createRoot(this.el);
|
|
1835
|
+
this.inlineEditorRoot.render(
|
|
1836
|
+
/* @__PURE__ */ React5.createElement(ThemeProvider, null, /* @__PURE__ */ React5.createElement(
|
|
1837
|
+
InlineEditor,
|
|
1838
|
+
{
|
|
1839
|
+
attributes: { class: classes },
|
|
1840
|
+
value: propValue,
|
|
1841
|
+
setValue,
|
|
1842
|
+
onBlur: this.handleUnmountInlineEditor.bind(this),
|
|
1843
|
+
autofocus: true,
|
|
1844
|
+
showToolbar: true,
|
|
1845
|
+
getInitialPopoverPosition,
|
|
1846
|
+
expectedTag
|
|
1847
|
+
}
|
|
1848
|
+
))
|
|
1849
|
+
);
|
|
1850
|
+
}
|
|
1851
|
+
};
|
|
1852
|
+
}
|
|
1853
|
+
|
|
1717
1854
|
// src/legacy/init-legacy-views.ts
|
|
1718
1855
|
var elementsLegacyTypes = {};
|
|
1719
1856
|
function registerElementType(type, elementTypeGenerator) {
|
|
@@ -1722,7 +1859,7 @@ function registerElementType(type, elementTypeGenerator) {
|
|
|
1722
1859
|
function initLegacyViews() {
|
|
1723
1860
|
__privateListenTo(v1ReadyEvent2(), () => {
|
|
1724
1861
|
const config = getWidgetsCache2() ?? {};
|
|
1725
|
-
const
|
|
1862
|
+
const legacyWindow2 = window;
|
|
1726
1863
|
const renderer = createDomRenderer();
|
|
1727
1864
|
Object.entries(config).forEach(([type, element]) => {
|
|
1728
1865
|
if (!element.atomic) {
|
|
@@ -1732,11 +1869,11 @@ function initLegacyViews() {
|
|
|
1732
1869
|
if (!!elementsLegacyTypes[type] && canBeTemplated(element)) {
|
|
1733
1870
|
ElementType = elementsLegacyTypes[type]({ type, renderer, element });
|
|
1734
1871
|
} else if (canBeTemplated(element)) {
|
|
1735
|
-
ElementType = createTemplatedElementType({ type, renderer, element });
|
|
1872
|
+
ElementType = shouldRenderInlineEditingView(type) ? createInlineEditingElementType({ type, renderer, element }) : createTemplatedElementType({ type, renderer, element });
|
|
1736
1873
|
} else {
|
|
1737
1874
|
ElementType = createElementType(type);
|
|
1738
1875
|
}
|
|
1739
|
-
|
|
1876
|
+
legacyWindow2.elementor.elementsManager.registerElementType(new ElementType());
|
|
1740
1877
|
});
|
|
1741
1878
|
});
|
|
1742
1879
|
}
|
|
@@ -1746,7 +1883,7 @@ import {
|
|
|
1746
1883
|
createElement as createElement6,
|
|
1747
1884
|
deleteElement,
|
|
1748
1885
|
generateElementId,
|
|
1749
|
-
getContainer as
|
|
1886
|
+
getContainer as getContainer2,
|
|
1750
1887
|
getWidgetsCache as getWidgetsCache5
|
|
1751
1888
|
} from "@elementor/editor-elements";
|
|
1752
1889
|
|
|
@@ -1755,7 +1892,7 @@ import {
|
|
|
1755
1892
|
createElementStyle,
|
|
1756
1893
|
getElementStyles,
|
|
1757
1894
|
getWidgetsCache as getWidgetsCache3,
|
|
1758
|
-
updateElementSettings
|
|
1895
|
+
updateElementSettings,
|
|
1759
1896
|
updateElementStyle
|
|
1760
1897
|
} from "@elementor/editor-elements";
|
|
1761
1898
|
import { getPropSchemaFromCache, Schema as Schema2 } from "@elementor/editor-props";
|
|
@@ -1857,7 +1994,7 @@ var doUpdateElementProperty = (params) => {
|
|
|
1857
1994
|
}
|
|
1858
1995
|
const propKey = elementPropSchema[propertyName].key;
|
|
1859
1996
|
const value = resolvePropValue(propertyValue, propKey);
|
|
1860
|
-
|
|
1997
|
+
updateElementSettings({
|
|
1861
1998
|
id: elementId,
|
|
1862
1999
|
props: {
|
|
1863
2000
|
[propertyName]: value
|
|
@@ -2316,7 +2453,7 @@ var initBuildCompositionsTool = (reg) => {
|
|
|
2316
2453
|
const softErrors = [];
|
|
2317
2454
|
const rootContainers = [];
|
|
2318
2455
|
const widgetsCache = getWidgetsCache5() || {};
|
|
2319
|
-
const documentContainer =
|
|
2456
|
+
const documentContainer = getContainer2("document");
|
|
2320
2457
|
try {
|
|
2321
2458
|
const parser = new DOMParser();
|
|
2322
2459
|
xml = parser.parseFromString(xmlStructure, "application/xml");
|
|
@@ -2645,7 +2782,7 @@ Check the styles schema at the resource [${STYLE_SCHEMA_URI.replace(
|
|
|
2645
2782
|
}
|
|
2646
2783
|
|
|
2647
2784
|
// src/mcp/tools/get-element-config/tool.ts
|
|
2648
|
-
import { getContainer as
|
|
2785
|
+
import { getContainer as getContainer3, getElementStyles as getElementStyles2, getWidgetsCache as getWidgetsCache6 } from "@elementor/editor-elements";
|
|
2649
2786
|
import { Schema as Schema4 } from "@elementor/editor-props";
|
|
2650
2787
|
import { z as z3 } from "@elementor/schema";
|
|
2651
2788
|
var schema = {
|
|
@@ -2663,7 +2800,7 @@ var initGetElementConfigTool = (reg) => {
|
|
|
2663
2800
|
schema,
|
|
2664
2801
|
outputSchema: outputSchema3,
|
|
2665
2802
|
handler: async ({ elementId }) => {
|
|
2666
|
-
const element =
|
|
2803
|
+
const element = getContainer3(elementId);
|
|
2667
2804
|
if (!element) {
|
|
2668
2805
|
throw new Error(`Element with ID ${elementId} not found.`);
|
|
2669
2806
|
}
|