@elementor/editor-canvas 4.1.0-739 → 4.1.0-741
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 +3 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +88 -34
- package/dist/index.mjs +89 -35
- package/package.json +18 -18
- package/src/legacy/replacements/base.ts +4 -0
- package/src/legacy/replacements/inline-editing/canvas-inline-editor.tsx +49 -27
- package/src/legacy/replacements/inline-editing/inline-editing-elements.tsx +16 -10
- package/src/legacy/replacements/inline-editing/inline-editing-utils.ts +12 -1
- package/src/legacy/replacements/manager.ts +13 -0
- package/src/legacy/types.ts +3 -0
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { V1Element, V1ElementConfig, V1ElementModelProps } from '@elementor/editor-elements';
|
|
2
2
|
import { TwingArrayLoader, TwingEnvironment } from '@elementor/twing';
|
|
3
|
+
import { Root } from 'react-dom/client';
|
|
3
4
|
import * as _elementor_editor_props from '@elementor/editor-props';
|
|
4
5
|
import { Props, PropValue, PropType, PropTypeKey, PropsSchema, AnyTransformable } from '@elementor/editor-props';
|
|
5
6
|
import * as _elementor_utils from '@elementor/utils';
|
|
@@ -204,6 +205,8 @@ type ReplacementSettings = {
|
|
|
204
205
|
id: string;
|
|
205
206
|
element: HTMLElement;
|
|
206
207
|
refreshView: () => void;
|
|
208
|
+
reactRoot: Root;
|
|
209
|
+
reactContainer: HTMLElement;
|
|
207
210
|
};
|
|
208
211
|
|
|
209
212
|
type CreateTemplatedElementTypeOptions = {
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { V1Element, V1ElementConfig, V1ElementModelProps } from '@elementor/editor-elements';
|
|
2
2
|
import { TwingArrayLoader, TwingEnvironment } from '@elementor/twing';
|
|
3
|
+
import { Root } from 'react-dom/client';
|
|
3
4
|
import * as _elementor_editor_props from '@elementor/editor-props';
|
|
4
5
|
import { Props, PropValue, PropType, PropTypeKey, PropsSchema, AnyTransformable } from '@elementor/editor-props';
|
|
5
6
|
import * as _elementor_utils from '@elementor/utils';
|
|
@@ -204,6 +205,8 @@ type ReplacementSettings = {
|
|
|
204
205
|
id: string;
|
|
205
206
|
element: HTMLElement;
|
|
206
207
|
refreshView: () => void;
|
|
208
|
+
reactRoot: Root;
|
|
209
|
+
reactContainer: HTMLElement;
|
|
207
210
|
};
|
|
208
211
|
|
|
209
212
|
type CreateTemplatedElementTypeOptions = {
|
package/dist/index.js
CHANGED
|
@@ -2421,9 +2421,11 @@ function createNestedTemplatedElementView({
|
|
|
2421
2421
|
});
|
|
2422
2422
|
}
|
|
2423
2423
|
|
|
2424
|
+
// src/legacy/replacements/manager.ts
|
|
2425
|
+
var import_client = require("react-dom/client");
|
|
2426
|
+
|
|
2424
2427
|
// src/legacy/replacements/inline-editing/inline-editing-elements.tsx
|
|
2425
2428
|
var React6 = __toESM(require("react"));
|
|
2426
|
-
var import_client = require("react-dom/client");
|
|
2427
2429
|
var import_editor_elements5 = require("@elementor/editor-elements");
|
|
2428
2430
|
var import_editor_props4 = require("@elementor/editor-props");
|
|
2429
2431
|
var import_editor_v1_adapters12 = require("@elementor/editor-v1-adapters");
|
|
@@ -2442,6 +2444,8 @@ var ReplacementBase = class {
|
|
|
2442
2444
|
type;
|
|
2443
2445
|
id;
|
|
2444
2446
|
refreshView;
|
|
2447
|
+
reactRoot;
|
|
2448
|
+
reactContainer;
|
|
2445
2449
|
constructor(settings) {
|
|
2446
2450
|
this.getSetting = settings.getSetting;
|
|
2447
2451
|
this.setSetting = settings.setSetting;
|
|
@@ -2449,6 +2453,8 @@ var ReplacementBase = class {
|
|
|
2449
2453
|
this.type = settings.type;
|
|
2450
2454
|
this.id = settings.id;
|
|
2451
2455
|
this.refreshView = settings.refreshView;
|
|
2456
|
+
this.reactRoot = settings.reactRoot;
|
|
2457
|
+
this.reactContainer = settings.reactContainer;
|
|
2452
2458
|
}
|
|
2453
2459
|
static getTypes() {
|
|
2454
2460
|
return null;
|
|
@@ -2499,7 +2505,8 @@ var INLINE_EDITING_PROPERTY_PER_TYPE = {
|
|
|
2499
2505
|
"e-button": "text",
|
|
2500
2506
|
"e-form-label": "text",
|
|
2501
2507
|
"e-heading": "title",
|
|
2502
|
-
"e-paragraph": "paragraph"
|
|
2508
|
+
"e-paragraph": "paragraph",
|
|
2509
|
+
"e-form-submit-button": "text"
|
|
2503
2510
|
};
|
|
2504
2511
|
var getInlineEditorElement = (elementWrapper, expectedTag) => {
|
|
2505
2512
|
return !expectedTag ? null : elementWrapper.querySelector(expectedTag);
|
|
@@ -2517,6 +2524,11 @@ var useOnClickOutsideIframe = (handleUnmount) => {
|
|
|
2517
2524
|
};
|
|
2518
2525
|
var useRenderToolbar = (ownerDocument, id) => {
|
|
2519
2526
|
const [anchor, setAnchor] = (0, import_react11.useState)(null);
|
|
2527
|
+
(0, import_react11.useEffect)(() => {
|
|
2528
|
+
if (!anchor) {
|
|
2529
|
+
removeToolbarAnchor(ownerDocument, id);
|
|
2530
|
+
}
|
|
2531
|
+
}, [anchor, ownerDocument, id]);
|
|
2520
2532
|
const onSelectionEnd = (view) => {
|
|
2521
2533
|
const hasSelection = !view.state.selection.empty;
|
|
2522
2534
|
removeToolbarAnchor(ownerDocument, id);
|
|
@@ -2526,7 +2538,10 @@ var useRenderToolbar = (ownerDocument, id) => {
|
|
|
2526
2538
|
setAnchor(null);
|
|
2527
2539
|
}
|
|
2528
2540
|
};
|
|
2529
|
-
|
|
2541
|
+
const clearAnchor = (0, import_react11.useCallback)(() => {
|
|
2542
|
+
setAnchor(null);
|
|
2543
|
+
}, []);
|
|
2544
|
+
return { onSelectionEnd, anchor, clearAnchor };
|
|
2530
2545
|
};
|
|
2531
2546
|
var createAnchorBasedOnSelection = (ownerDocument, id) => {
|
|
2532
2547
|
const frameWindow = ownerDocument.defaultView;
|
|
@@ -2593,46 +2608,59 @@ var horizontalShifterMiddleware = {
|
|
|
2593
2608
|
};
|
|
2594
2609
|
|
|
2595
2610
|
// src/legacy/replacements/inline-editing/canvas-inline-editor.tsx
|
|
2596
|
-
var EDITOR_WRAPPER_SELECTOR = "inline-editor-wrapper";
|
|
2597
2611
|
var CanvasInlineEditor = ({
|
|
2598
2612
|
elementClasses,
|
|
2599
2613
|
initialValue,
|
|
2600
2614
|
expectedTag,
|
|
2601
2615
|
rootElement,
|
|
2616
|
+
contentElement,
|
|
2602
2617
|
id,
|
|
2603
2618
|
setValue,
|
|
2604
|
-
|
|
2619
|
+
requestDestroy
|
|
2605
2620
|
}) => {
|
|
2621
|
+
const [active, setActive] = (0, import_react12.useState)(true);
|
|
2606
2622
|
const [editor, setEditor] = (0, import_react12.useState)(null);
|
|
2607
|
-
const { onSelectionEnd, anchor: toolbarAnchor } = useRenderToolbar(rootElement.ownerDocument, id);
|
|
2608
|
-
|
|
2609
|
-
|
|
2610
|
-
|
|
2611
|
-
|
|
2612
|
-
|
|
2613
|
-
|
|
2614
|
-
|
|
2615
|
-
|
|
2616
|
-
|
|
2617
|
-
|
|
2618
|
-
|
|
2619
|
-
|
|
2620
|
-
|
|
2621
|
-
|
|
2623
|
+
const { onSelectionEnd, anchor: toolbarAnchor, clearAnchor } = useRenderToolbar(rootElement.ownerDocument, id);
|
|
2624
|
+
(0, import_react12.useEffect)(() => {
|
|
2625
|
+
if (!active) {
|
|
2626
|
+
clearAnchor();
|
|
2627
|
+
requestDestroy();
|
|
2628
|
+
}
|
|
2629
|
+
}, [active, clearAnchor, requestDestroy]);
|
|
2630
|
+
const dismiss = (0, import_react12.useCallback)(() => {
|
|
2631
|
+
setEditor(null);
|
|
2632
|
+
setActive(false);
|
|
2633
|
+
}, []);
|
|
2634
|
+
useOnClickOutsideIframe(dismiss);
|
|
2635
|
+
(0, import_react12.useEffect)(() => {
|
|
2636
|
+
const ownerDocument = contentElement.ownerDocument;
|
|
2637
|
+
const handleClickAway = (event) => {
|
|
2638
|
+
if (contentElement.contains(event.target)) {
|
|
2639
|
+
return;
|
|
2640
|
+
}
|
|
2641
|
+
dismiss();
|
|
2642
|
+
};
|
|
2643
|
+
ownerDocument.addEventListener("mousedown", handleClickAway);
|
|
2644
|
+
return () => ownerDocument.removeEventListener("mousedown", handleClickAway);
|
|
2645
|
+
}, [contentElement, dismiss]);
|
|
2646
|
+
if (!active) {
|
|
2647
|
+
return null;
|
|
2648
|
+
}
|
|
2649
|
+
return /* @__PURE__ */ React5.createElement(import_ui4.ThemeProvider, null, /* @__PURE__ */ React5.createElement(InlineEditingOverlay, { expectedTag, rootElement, id }), /* @__PURE__ */ React5.createElement(
|
|
2622
2650
|
import_editor_controls2.InlineEditor,
|
|
2623
2651
|
{
|
|
2624
2652
|
onEditorCreate: setEditor,
|
|
2653
|
+
mountElement: contentElement,
|
|
2625
2654
|
editorProps: {
|
|
2626
2655
|
attributes: {
|
|
2627
|
-
style: "outline: none;
|
|
2656
|
+
style: "outline: none; display: inherit; justify-content: inherit; align-items: inherit; flex-direction: inherit; text-align: inherit;"
|
|
2628
2657
|
}
|
|
2629
2658
|
},
|
|
2630
2659
|
elementClasses,
|
|
2631
2660
|
value: initialValue,
|
|
2632
2661
|
setValue,
|
|
2633
|
-
onBlur,
|
|
2662
|
+
onBlur: dismiss,
|
|
2634
2663
|
autofocus: true,
|
|
2635
|
-
expectedTag,
|
|
2636
2664
|
onSelectionEnd
|
|
2637
2665
|
}
|
|
2638
2666
|
), toolbarAnchor && editor && /* @__PURE__ */ React5.createElement(InlineEditingToolbar, { anchor: toolbarAnchor, editor, id }));
|
|
@@ -2661,7 +2689,18 @@ var InlineEditingToolbar = ({ anchor, editor, id }) => {
|
|
|
2661
2689
|
refs.setReference(anchor);
|
|
2662
2690
|
return () => refs.setReference(null);
|
|
2663
2691
|
}, [anchor, refs]);
|
|
2664
|
-
return /* @__PURE__ */ React5.createElement(import_react13.FloatingPortal, { id: CANVAS_WRAPPER_ID }, /* @__PURE__ */ React5.createElement(
|
|
2692
|
+
return /* @__PURE__ */ React5.createElement(import_react13.FloatingPortal, { id: CANVAS_WRAPPER_ID }, /* @__PURE__ */ React5.createElement(
|
|
2693
|
+
import_ui4.Box,
|
|
2694
|
+
{
|
|
2695
|
+
ref: refs.setFloating,
|
|
2696
|
+
role: "presentation",
|
|
2697
|
+
style: {
|
|
2698
|
+
...floatingStyles,
|
|
2699
|
+
pointerEvents: "none"
|
|
2700
|
+
}
|
|
2701
|
+
},
|
|
2702
|
+
/* @__PURE__ */ React5.createElement(import_editor_controls2.InlineEditorToolbar, { editor, elementId: id })
|
|
2703
|
+
));
|
|
2665
2704
|
};
|
|
2666
2705
|
|
|
2667
2706
|
// src/legacy/replacements/inline-editing/inline-editing-eligibility.ts
|
|
@@ -2695,8 +2734,8 @@ var isInlineEditingAllowed = ({ rawValue, propTypeFromSchema }) => {
|
|
|
2695
2734
|
// src/legacy/replacements/inline-editing/inline-editing-elements.tsx
|
|
2696
2735
|
var HISTORY_DEBOUNCE_WAIT = 800;
|
|
2697
2736
|
var InlineEditingReplacement = class extends ReplacementBase {
|
|
2698
|
-
inlineEditorRoot = null;
|
|
2699
2737
|
handlerAttached = false;
|
|
2738
|
+
editing = false;
|
|
2700
2739
|
getReplacementKey() {
|
|
2701
2740
|
return "inline-editing";
|
|
2702
2741
|
}
|
|
@@ -2704,7 +2743,7 @@ var InlineEditingReplacement = class extends ReplacementBase {
|
|
|
2704
2743
|
return Object.keys(INLINE_EDITING_PROPERTY_PER_TYPE);
|
|
2705
2744
|
}
|
|
2706
2745
|
isEditingModeActive() {
|
|
2707
|
-
return
|
|
2746
|
+
return this.editing;
|
|
2708
2747
|
}
|
|
2709
2748
|
shouldRenderReplacement() {
|
|
2710
2749
|
return this.isInlineEditingEligible() && (0, import_editor_v1_adapters12.getCurrentEditMode)() === "edit";
|
|
@@ -2747,8 +2786,8 @@ var InlineEditingReplacement = class extends ReplacementBase {
|
|
|
2747
2786
|
resetInlineEditorRoot() {
|
|
2748
2787
|
this.element.removeEventListener("click", this.handleRenderInlineEditor);
|
|
2749
2788
|
this.handlerAttached = false;
|
|
2750
|
-
this.
|
|
2751
|
-
this.
|
|
2789
|
+
this.reactRoot.render(null);
|
|
2790
|
+
this.editing = false;
|
|
2752
2791
|
}
|
|
2753
2792
|
unmountInlineEditor() {
|
|
2754
2793
|
this.resetInlineEditorRoot();
|
|
@@ -2859,12 +2898,16 @@ var InlineEditingReplacement = class extends ReplacementBase {
|
|
|
2859
2898
|
if (this.isEditingModeActive()) {
|
|
2860
2899
|
this.resetInlineEditorRoot();
|
|
2861
2900
|
}
|
|
2862
|
-
const
|
|
2901
|
+
const contentElement = this.element.children?.[0];
|
|
2902
|
+
if (!contentElement) {
|
|
2903
|
+
return;
|
|
2904
|
+
}
|
|
2905
|
+
const elementClasses = contentElement.classList.toString();
|
|
2863
2906
|
const propValue = this.getExtractedContentValue();
|
|
2864
2907
|
const expectedTag = this.getExpectedTag();
|
|
2865
|
-
|
|
2866
|
-
this.
|
|
2867
|
-
this.
|
|
2908
|
+
contentElement.innerHTML = "";
|
|
2909
|
+
this.editing = true;
|
|
2910
|
+
this.reactRoot.render(
|
|
2868
2911
|
/* @__PURE__ */ React6.createElement(
|
|
2869
2912
|
CanvasInlineEditor,
|
|
2870
2913
|
{
|
|
@@ -2872,9 +2915,10 @@ var InlineEditingReplacement = class extends ReplacementBase {
|
|
|
2872
2915
|
initialValue: propValue,
|
|
2873
2916
|
expectedTag,
|
|
2874
2917
|
rootElement: this.element,
|
|
2918
|
+
contentElement,
|
|
2875
2919
|
id: this.id,
|
|
2876
2920
|
setValue: this.setContentValue.bind(this),
|
|
2877
|
-
|
|
2921
|
+
requestDestroy: this.unmountInlineEditor.bind(this)
|
|
2878
2922
|
}
|
|
2879
2923
|
)
|
|
2880
2924
|
);
|
|
@@ -2903,16 +2947,24 @@ var createViewWithReplacements = (options) => {
|
|
|
2903
2947
|
return class extends TemplatedView {
|
|
2904
2948
|
#replacement = null;
|
|
2905
2949
|
#config;
|
|
2950
|
+
#reactContainer;
|
|
2951
|
+
#reactRoot;
|
|
2906
2952
|
constructor(...args) {
|
|
2907
2953
|
super(...args);
|
|
2908
2954
|
const settings = this.model.get("settings");
|
|
2955
|
+
this.#reactContainer = this.el.ownerDocument.createElement("div");
|
|
2956
|
+
this.#reactContainer.style.display = "none";
|
|
2957
|
+
this.el.ownerDocument.body.appendChild(this.#reactContainer);
|
|
2958
|
+
this.#reactRoot = (0, import_client.createRoot)(this.#reactContainer);
|
|
2909
2959
|
this.#config = {
|
|
2910
2960
|
getSetting: settings.get.bind(settings),
|
|
2911
2961
|
setSetting: settings.set.bind(settings),
|
|
2912
2962
|
element: this.el,
|
|
2913
2963
|
type: this?.model?.get("widgetType") ?? this.container?.model?.get("elType") ?? null,
|
|
2914
2964
|
id: this?.model?.get("id") ?? null,
|
|
2915
|
-
refreshView: this.refreshView.bind(this)
|
|
2965
|
+
refreshView: this.refreshView.bind(this),
|
|
2966
|
+
reactRoot: this.#reactRoot,
|
|
2967
|
+
reactContainer: this.#reactContainer
|
|
2916
2968
|
};
|
|
2917
2969
|
}
|
|
2918
2970
|
refreshView() {
|
|
@@ -2933,6 +2985,8 @@ var createViewWithReplacements = (options) => {
|
|
|
2933
2985
|
}
|
|
2934
2986
|
onDestroy() {
|
|
2935
2987
|
this.#triggerAltMethod("onDestroy");
|
|
2988
|
+
this.#reactRoot.unmount();
|
|
2989
|
+
this.#reactContainer.remove();
|
|
2936
2990
|
}
|
|
2937
2991
|
_afterRender() {
|
|
2938
2992
|
this.#triggerAltMethod("_afterRender");
|
package/dist/index.mjs
CHANGED
|
@@ -2387,9 +2387,11 @@ function createNestedTemplatedElementView({
|
|
|
2387
2387
|
});
|
|
2388
2388
|
}
|
|
2389
2389
|
|
|
2390
|
+
// src/legacy/replacements/manager.ts
|
|
2391
|
+
import { createRoot } from "react-dom/client";
|
|
2392
|
+
|
|
2390
2393
|
// src/legacy/replacements/inline-editing/inline-editing-elements.tsx
|
|
2391
2394
|
import * as React6 from "react";
|
|
2392
|
-
import { createRoot } from "react-dom/client";
|
|
2393
2395
|
import { getContainer, getElementLabel, getElementType as getElementType2 } from "@elementor/editor-elements";
|
|
2394
2396
|
import {
|
|
2395
2397
|
htmlV3PropTypeUtil as htmlV3PropTypeUtil2,
|
|
@@ -2412,6 +2414,8 @@ var ReplacementBase = class {
|
|
|
2412
2414
|
type;
|
|
2413
2415
|
id;
|
|
2414
2416
|
refreshView;
|
|
2417
|
+
reactRoot;
|
|
2418
|
+
reactContainer;
|
|
2415
2419
|
constructor(settings) {
|
|
2416
2420
|
this.getSetting = settings.getSetting;
|
|
2417
2421
|
this.setSetting = settings.setSetting;
|
|
@@ -2419,6 +2423,8 @@ var ReplacementBase = class {
|
|
|
2419
2423
|
this.type = settings.type;
|
|
2420
2424
|
this.id = settings.id;
|
|
2421
2425
|
this.refreshView = settings.refreshView;
|
|
2426
|
+
this.reactRoot = settings.reactRoot;
|
|
2427
|
+
this.reactContainer = settings.reactContainer;
|
|
2422
2428
|
}
|
|
2423
2429
|
static getTypes() {
|
|
2424
2430
|
return null;
|
|
@@ -2439,7 +2445,7 @@ var ReplacementBase = class {
|
|
|
2439
2445
|
|
|
2440
2446
|
// src/legacy/replacements/inline-editing/canvas-inline-editor.tsx
|
|
2441
2447
|
import * as React5 from "react";
|
|
2442
|
-
import { useEffect as useEffect8, useLayoutEffect, useState as useState5 } from "react";
|
|
2448
|
+
import { useCallback as useCallback2, useEffect as useEffect8, useLayoutEffect, useState as useState5 } from "react";
|
|
2443
2449
|
import { InlineEditor, InlineEditorToolbar } from "@elementor/editor-controls";
|
|
2444
2450
|
import { Box as Box2, ThemeProvider } from "@elementor/ui";
|
|
2445
2451
|
import { autoUpdate as autoUpdate2, flip, FloatingPortal as FloatingPortal2, useFloating as useFloating2 } from "@floating-ui/react";
|
|
@@ -2469,7 +2475,8 @@ var INLINE_EDITING_PROPERTY_PER_TYPE = {
|
|
|
2469
2475
|
"e-button": "text",
|
|
2470
2476
|
"e-form-label": "text",
|
|
2471
2477
|
"e-heading": "title",
|
|
2472
|
-
"e-paragraph": "paragraph"
|
|
2478
|
+
"e-paragraph": "paragraph",
|
|
2479
|
+
"e-form-submit-button": "text"
|
|
2473
2480
|
};
|
|
2474
2481
|
var getInlineEditorElement = (elementWrapper, expectedTag) => {
|
|
2475
2482
|
return !expectedTag ? null : elementWrapper.querySelector(expectedTag);
|
|
@@ -2487,6 +2494,11 @@ var useOnClickOutsideIframe = (handleUnmount) => {
|
|
|
2487
2494
|
};
|
|
2488
2495
|
var useRenderToolbar = (ownerDocument, id) => {
|
|
2489
2496
|
const [anchor, setAnchor] = useState4(null);
|
|
2497
|
+
useEffect7(() => {
|
|
2498
|
+
if (!anchor) {
|
|
2499
|
+
removeToolbarAnchor(ownerDocument, id);
|
|
2500
|
+
}
|
|
2501
|
+
}, [anchor, ownerDocument, id]);
|
|
2490
2502
|
const onSelectionEnd = (view) => {
|
|
2491
2503
|
const hasSelection = !view.state.selection.empty;
|
|
2492
2504
|
removeToolbarAnchor(ownerDocument, id);
|
|
@@ -2496,7 +2508,10 @@ var useRenderToolbar = (ownerDocument, id) => {
|
|
|
2496
2508
|
setAnchor(null);
|
|
2497
2509
|
}
|
|
2498
2510
|
};
|
|
2499
|
-
|
|
2511
|
+
const clearAnchor = useCallback(() => {
|
|
2512
|
+
setAnchor(null);
|
|
2513
|
+
}, []);
|
|
2514
|
+
return { onSelectionEnd, anchor, clearAnchor };
|
|
2500
2515
|
};
|
|
2501
2516
|
var createAnchorBasedOnSelection = (ownerDocument, id) => {
|
|
2502
2517
|
const frameWindow = ownerDocument.defaultView;
|
|
@@ -2563,46 +2578,59 @@ var horizontalShifterMiddleware = {
|
|
|
2563
2578
|
};
|
|
2564
2579
|
|
|
2565
2580
|
// src/legacy/replacements/inline-editing/canvas-inline-editor.tsx
|
|
2566
|
-
var EDITOR_WRAPPER_SELECTOR = "inline-editor-wrapper";
|
|
2567
2581
|
var CanvasInlineEditor = ({
|
|
2568
2582
|
elementClasses,
|
|
2569
2583
|
initialValue,
|
|
2570
2584
|
expectedTag,
|
|
2571
2585
|
rootElement,
|
|
2586
|
+
contentElement,
|
|
2572
2587
|
id,
|
|
2573
2588
|
setValue,
|
|
2574
|
-
|
|
2589
|
+
requestDestroy
|
|
2575
2590
|
}) => {
|
|
2591
|
+
const [active, setActive] = useState5(true);
|
|
2576
2592
|
const [editor, setEditor] = useState5(null);
|
|
2577
|
-
const { onSelectionEnd, anchor: toolbarAnchor } = useRenderToolbar(rootElement.ownerDocument, id);
|
|
2578
|
-
|
|
2579
|
-
|
|
2580
|
-
|
|
2581
|
-
|
|
2582
|
-
|
|
2583
|
-
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
|
|
2588
|
-
|
|
2589
|
-
|
|
2590
|
-
|
|
2591
|
-
|
|
2593
|
+
const { onSelectionEnd, anchor: toolbarAnchor, clearAnchor } = useRenderToolbar(rootElement.ownerDocument, id);
|
|
2594
|
+
useEffect8(() => {
|
|
2595
|
+
if (!active) {
|
|
2596
|
+
clearAnchor();
|
|
2597
|
+
requestDestroy();
|
|
2598
|
+
}
|
|
2599
|
+
}, [active, clearAnchor, requestDestroy]);
|
|
2600
|
+
const dismiss = useCallback2(() => {
|
|
2601
|
+
setEditor(null);
|
|
2602
|
+
setActive(false);
|
|
2603
|
+
}, []);
|
|
2604
|
+
useOnClickOutsideIframe(dismiss);
|
|
2605
|
+
useEffect8(() => {
|
|
2606
|
+
const ownerDocument = contentElement.ownerDocument;
|
|
2607
|
+
const handleClickAway = (event) => {
|
|
2608
|
+
if (contentElement.contains(event.target)) {
|
|
2609
|
+
return;
|
|
2610
|
+
}
|
|
2611
|
+
dismiss();
|
|
2612
|
+
};
|
|
2613
|
+
ownerDocument.addEventListener("mousedown", handleClickAway);
|
|
2614
|
+
return () => ownerDocument.removeEventListener("mousedown", handleClickAway);
|
|
2615
|
+
}, [contentElement, dismiss]);
|
|
2616
|
+
if (!active) {
|
|
2617
|
+
return null;
|
|
2618
|
+
}
|
|
2619
|
+
return /* @__PURE__ */ React5.createElement(ThemeProvider, null, /* @__PURE__ */ React5.createElement(InlineEditingOverlay, { expectedTag, rootElement, id }), /* @__PURE__ */ React5.createElement(
|
|
2592
2620
|
InlineEditor,
|
|
2593
2621
|
{
|
|
2594
2622
|
onEditorCreate: setEditor,
|
|
2623
|
+
mountElement: contentElement,
|
|
2595
2624
|
editorProps: {
|
|
2596
2625
|
attributes: {
|
|
2597
|
-
style: "outline: none;
|
|
2626
|
+
style: "outline: none; display: inherit; justify-content: inherit; align-items: inherit; flex-direction: inherit; text-align: inherit;"
|
|
2598
2627
|
}
|
|
2599
2628
|
},
|
|
2600
2629
|
elementClasses,
|
|
2601
2630
|
value: initialValue,
|
|
2602
2631
|
setValue,
|
|
2603
|
-
onBlur,
|
|
2632
|
+
onBlur: dismiss,
|
|
2604
2633
|
autofocus: true,
|
|
2605
|
-
expectedTag,
|
|
2606
2634
|
onSelectionEnd
|
|
2607
2635
|
}
|
|
2608
2636
|
), toolbarAnchor && editor && /* @__PURE__ */ React5.createElement(InlineEditingToolbar, { anchor: toolbarAnchor, editor, id }));
|
|
@@ -2631,7 +2659,18 @@ var InlineEditingToolbar = ({ anchor, editor, id }) => {
|
|
|
2631
2659
|
refs.setReference(anchor);
|
|
2632
2660
|
return () => refs.setReference(null);
|
|
2633
2661
|
}, [anchor, refs]);
|
|
2634
|
-
return /* @__PURE__ */ React5.createElement(FloatingPortal2, { id: CANVAS_WRAPPER_ID }, /* @__PURE__ */ React5.createElement(
|
|
2662
|
+
return /* @__PURE__ */ React5.createElement(FloatingPortal2, { id: CANVAS_WRAPPER_ID }, /* @__PURE__ */ React5.createElement(
|
|
2663
|
+
Box2,
|
|
2664
|
+
{
|
|
2665
|
+
ref: refs.setFloating,
|
|
2666
|
+
role: "presentation",
|
|
2667
|
+
style: {
|
|
2668
|
+
...floatingStyles,
|
|
2669
|
+
pointerEvents: "none"
|
|
2670
|
+
}
|
|
2671
|
+
},
|
|
2672
|
+
/* @__PURE__ */ React5.createElement(InlineEditorToolbar, { editor, elementId: id })
|
|
2673
|
+
));
|
|
2635
2674
|
};
|
|
2636
2675
|
|
|
2637
2676
|
// src/legacy/replacements/inline-editing/inline-editing-eligibility.ts
|
|
@@ -2665,8 +2704,8 @@ var isInlineEditingAllowed = ({ rawValue, propTypeFromSchema }) => {
|
|
|
2665
2704
|
// src/legacy/replacements/inline-editing/inline-editing-elements.tsx
|
|
2666
2705
|
var HISTORY_DEBOUNCE_WAIT = 800;
|
|
2667
2706
|
var InlineEditingReplacement = class extends ReplacementBase {
|
|
2668
|
-
inlineEditorRoot = null;
|
|
2669
2707
|
handlerAttached = false;
|
|
2708
|
+
editing = false;
|
|
2670
2709
|
getReplacementKey() {
|
|
2671
2710
|
return "inline-editing";
|
|
2672
2711
|
}
|
|
@@ -2674,7 +2713,7 @@ var InlineEditingReplacement = class extends ReplacementBase {
|
|
|
2674
2713
|
return Object.keys(INLINE_EDITING_PROPERTY_PER_TYPE);
|
|
2675
2714
|
}
|
|
2676
2715
|
isEditingModeActive() {
|
|
2677
|
-
return
|
|
2716
|
+
return this.editing;
|
|
2678
2717
|
}
|
|
2679
2718
|
shouldRenderReplacement() {
|
|
2680
2719
|
return this.isInlineEditingEligible() && getCurrentEditMode() === "edit";
|
|
@@ -2717,8 +2756,8 @@ var InlineEditingReplacement = class extends ReplacementBase {
|
|
|
2717
2756
|
resetInlineEditorRoot() {
|
|
2718
2757
|
this.element.removeEventListener("click", this.handleRenderInlineEditor);
|
|
2719
2758
|
this.handlerAttached = false;
|
|
2720
|
-
this.
|
|
2721
|
-
this.
|
|
2759
|
+
this.reactRoot.render(null);
|
|
2760
|
+
this.editing = false;
|
|
2722
2761
|
}
|
|
2723
2762
|
unmountInlineEditor() {
|
|
2724
2763
|
this.resetInlineEditorRoot();
|
|
@@ -2829,12 +2868,16 @@ var InlineEditingReplacement = class extends ReplacementBase {
|
|
|
2829
2868
|
if (this.isEditingModeActive()) {
|
|
2830
2869
|
this.resetInlineEditorRoot();
|
|
2831
2870
|
}
|
|
2832
|
-
const
|
|
2871
|
+
const contentElement = this.element.children?.[0];
|
|
2872
|
+
if (!contentElement) {
|
|
2873
|
+
return;
|
|
2874
|
+
}
|
|
2875
|
+
const elementClasses = contentElement.classList.toString();
|
|
2833
2876
|
const propValue = this.getExtractedContentValue();
|
|
2834
2877
|
const expectedTag = this.getExpectedTag();
|
|
2835
|
-
|
|
2836
|
-
this.
|
|
2837
|
-
this.
|
|
2878
|
+
contentElement.innerHTML = "";
|
|
2879
|
+
this.editing = true;
|
|
2880
|
+
this.reactRoot.render(
|
|
2838
2881
|
/* @__PURE__ */ React6.createElement(
|
|
2839
2882
|
CanvasInlineEditor,
|
|
2840
2883
|
{
|
|
@@ -2842,9 +2885,10 @@ var InlineEditingReplacement = class extends ReplacementBase {
|
|
|
2842
2885
|
initialValue: propValue,
|
|
2843
2886
|
expectedTag,
|
|
2844
2887
|
rootElement: this.element,
|
|
2888
|
+
contentElement,
|
|
2845
2889
|
id: this.id,
|
|
2846
2890
|
setValue: this.setContentValue.bind(this),
|
|
2847
|
-
|
|
2891
|
+
requestDestroy: this.unmountInlineEditor.bind(this)
|
|
2848
2892
|
}
|
|
2849
2893
|
)
|
|
2850
2894
|
);
|
|
@@ -2873,16 +2917,24 @@ var createViewWithReplacements = (options) => {
|
|
|
2873
2917
|
return class extends TemplatedView {
|
|
2874
2918
|
#replacement = null;
|
|
2875
2919
|
#config;
|
|
2920
|
+
#reactContainer;
|
|
2921
|
+
#reactRoot;
|
|
2876
2922
|
constructor(...args) {
|
|
2877
2923
|
super(...args);
|
|
2878
2924
|
const settings = this.model.get("settings");
|
|
2925
|
+
this.#reactContainer = this.el.ownerDocument.createElement("div");
|
|
2926
|
+
this.#reactContainer.style.display = "none";
|
|
2927
|
+
this.el.ownerDocument.body.appendChild(this.#reactContainer);
|
|
2928
|
+
this.#reactRoot = createRoot(this.#reactContainer);
|
|
2879
2929
|
this.#config = {
|
|
2880
2930
|
getSetting: settings.get.bind(settings),
|
|
2881
2931
|
setSetting: settings.set.bind(settings),
|
|
2882
2932
|
element: this.el,
|
|
2883
2933
|
type: this?.model?.get("widgetType") ?? this.container?.model?.get("elType") ?? null,
|
|
2884
2934
|
id: this?.model?.get("id") ?? null,
|
|
2885
|
-
refreshView: this.refreshView.bind(this)
|
|
2935
|
+
refreshView: this.refreshView.bind(this),
|
|
2936
|
+
reactRoot: this.#reactRoot,
|
|
2937
|
+
reactContainer: this.#reactContainer
|
|
2886
2938
|
};
|
|
2887
2939
|
}
|
|
2888
2940
|
refreshView() {
|
|
@@ -2903,6 +2955,8 @@ var createViewWithReplacements = (options) => {
|
|
|
2903
2955
|
}
|
|
2904
2956
|
onDestroy() {
|
|
2905
2957
|
this.#triggerAltMethod("onDestroy");
|
|
2958
|
+
this.#reactRoot.unmount();
|
|
2959
|
+
this.#reactContainer.remove();
|
|
2906
2960
|
}
|
|
2907
2961
|
_afterRender() {
|
|
2908
2962
|
this.#triggerAltMethod("_afterRender");
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@elementor/editor-canvas",
|
|
3
3
|
"description": "Elementor Editor Canvas",
|
|
4
|
-
"version": "4.1.0-
|
|
4
|
+
"version": "4.1.0-741",
|
|
5
5
|
"private": false,
|
|
6
6
|
"author": "Elementor Team",
|
|
7
7
|
"homepage": "https://elementor.com/",
|
|
@@ -37,25 +37,25 @@
|
|
|
37
37
|
"react-dom": "^18.3.1"
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@elementor/editor": "4.1.0-
|
|
40
|
+
"@elementor/editor": "4.1.0-741",
|
|
41
41
|
"dompurify": "^3.2.6",
|
|
42
|
-
"@elementor/editor-controls": "4.1.0-
|
|
43
|
-
"@elementor/editor-documents": "4.1.0-
|
|
44
|
-
"@elementor/editor-elements": "4.1.0-
|
|
45
|
-
"@elementor/editor-interactions": "4.1.0-
|
|
46
|
-
"@elementor/editor-mcp": "4.1.0-
|
|
47
|
-
"@elementor/editor-notifications": "4.1.0-
|
|
48
|
-
"@elementor/editor-props": "4.1.0-
|
|
49
|
-
"@elementor/editor-responsive": "4.1.0-
|
|
50
|
-
"@elementor/editor-styles": "4.1.0-
|
|
51
|
-
"@elementor/editor-styles-repository": "4.1.0-
|
|
52
|
-
"@elementor/editor-ui": "4.1.0-
|
|
53
|
-
"@elementor/editor-v1-adapters": "4.1.0-
|
|
54
|
-
"@elementor/schema": "4.1.0-
|
|
55
|
-
"@elementor/twing": "4.1.0-
|
|
42
|
+
"@elementor/editor-controls": "4.1.0-741",
|
|
43
|
+
"@elementor/editor-documents": "4.1.0-741",
|
|
44
|
+
"@elementor/editor-elements": "4.1.0-741",
|
|
45
|
+
"@elementor/editor-interactions": "4.1.0-741",
|
|
46
|
+
"@elementor/editor-mcp": "4.1.0-741",
|
|
47
|
+
"@elementor/editor-notifications": "4.1.0-741",
|
|
48
|
+
"@elementor/editor-props": "4.1.0-741",
|
|
49
|
+
"@elementor/editor-responsive": "4.1.0-741",
|
|
50
|
+
"@elementor/editor-styles": "4.1.0-741",
|
|
51
|
+
"@elementor/editor-styles-repository": "4.1.0-741",
|
|
52
|
+
"@elementor/editor-ui": "4.1.0-741",
|
|
53
|
+
"@elementor/editor-v1-adapters": "4.1.0-741",
|
|
54
|
+
"@elementor/schema": "4.1.0-741",
|
|
55
|
+
"@elementor/twing": "4.1.0-741",
|
|
56
56
|
"@elementor/ui": "1.36.17",
|
|
57
|
-
"@elementor/utils": "4.1.0-
|
|
58
|
-
"@elementor/wp-media": "4.1.0-
|
|
57
|
+
"@elementor/utils": "4.1.0-741",
|
|
58
|
+
"@elementor/wp-media": "4.1.0-741",
|
|
59
59
|
"@floating-ui/react": "^0.27.5",
|
|
60
60
|
"@wordpress/i18n": "^5.13.0"
|
|
61
61
|
},
|
|
@@ -26,6 +26,8 @@ export class ReplacementBase implements ReplacementBaseInterface {
|
|
|
26
26
|
protected type: ReplacementSettings[ 'type' ];
|
|
27
27
|
protected id: ReplacementSettings[ 'id' ];
|
|
28
28
|
protected refreshView: ReplacementSettings[ 'refreshView' ];
|
|
29
|
+
protected reactRoot: ReplacementSettings[ 'reactRoot' ];
|
|
30
|
+
protected reactContainer: ReplacementSettings[ 'reactContainer' ];
|
|
29
31
|
|
|
30
32
|
constructor( settings: ReplacementSettings ) {
|
|
31
33
|
this.getSetting = settings.getSetting;
|
|
@@ -34,6 +36,8 @@ export class ReplacementBase implements ReplacementBaseInterface {
|
|
|
34
36
|
this.type = settings.type;
|
|
35
37
|
this.id = settings.id;
|
|
36
38
|
this.refreshView = settings.refreshView;
|
|
39
|
+
this.reactRoot = settings.reactRoot;
|
|
40
|
+
this.reactContainer = settings.reactContainer;
|
|
37
41
|
}
|
|
38
42
|
|
|
39
43
|
static getTypes(): string[] | null {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import { useEffect, useLayoutEffect, useState } from 'react';
|
|
2
|
+
import { useCallback, useEffect, useLayoutEffect, useState } from 'react';
|
|
3
3
|
import { InlineEditor, InlineEditorToolbar } from '@elementor/editor-controls';
|
|
4
4
|
import { Box, ThemeProvider } from '@elementor/ui';
|
|
5
5
|
import { autoUpdate, flip, FloatingPortal, useFloating } from '@floating-ui/react';
|
|
@@ -9,68 +9,83 @@ import {
|
|
|
9
9
|
type Editor,
|
|
10
10
|
getInlineEditorElement,
|
|
11
11
|
horizontalShifterMiddleware as horizontalShifter,
|
|
12
|
-
removeToolbarAnchor,
|
|
13
12
|
useOnClickOutsideIframe,
|
|
14
13
|
useRenderToolbar,
|
|
15
14
|
} from './inline-editing-utils';
|
|
16
15
|
|
|
17
|
-
const EDITOR_WRAPPER_SELECTOR = 'inline-editor-wrapper';
|
|
18
|
-
|
|
19
16
|
export const CanvasInlineEditor = ( {
|
|
20
17
|
elementClasses,
|
|
21
18
|
initialValue,
|
|
22
19
|
expectedTag,
|
|
23
20
|
rootElement,
|
|
21
|
+
contentElement,
|
|
24
22
|
id,
|
|
25
23
|
setValue,
|
|
26
|
-
|
|
24
|
+
requestDestroy,
|
|
27
25
|
}: {
|
|
28
26
|
elementClasses: string;
|
|
29
27
|
initialValue: string | null;
|
|
30
28
|
expectedTag: string | null;
|
|
31
29
|
rootElement: HTMLElement;
|
|
30
|
+
contentElement: HTMLElement;
|
|
32
31
|
id: string;
|
|
33
32
|
setValue: ( value: string | null ) => void;
|
|
34
|
-
|
|
33
|
+
requestDestroy: () => void;
|
|
35
34
|
} ) => {
|
|
35
|
+
const [ active, setActive ] = useState( true );
|
|
36
36
|
const [ editor, setEditor ] = useState< Editor | null >( null );
|
|
37
|
-
const { onSelectionEnd, anchor: toolbarAnchor } = useRenderToolbar( rootElement.ownerDocument, id );
|
|
37
|
+
const { onSelectionEnd, anchor: toolbarAnchor, clearAnchor } = useRenderToolbar( rootElement.ownerDocument, id );
|
|
38
|
+
|
|
39
|
+
useEffect( () => {
|
|
40
|
+
if ( ! active ) {
|
|
41
|
+
clearAnchor();
|
|
42
|
+
requestDestroy();
|
|
43
|
+
}
|
|
44
|
+
}, [ active, clearAnchor, requestDestroy ] );
|
|
45
|
+
|
|
46
|
+
const dismiss = useCallback( () => {
|
|
47
|
+
setEditor( null );
|
|
48
|
+
setActive( false );
|
|
49
|
+
}, [] );
|
|
38
50
|
|
|
39
|
-
|
|
40
|
-
removeToolbarAnchor( rootElement.ownerDocument, id );
|
|
51
|
+
useOnClickOutsideIframe( dismiss );
|
|
41
52
|
|
|
42
|
-
|
|
43
|
-
|
|
53
|
+
useEffect( () => {
|
|
54
|
+
const ownerDocument = contentElement.ownerDocument;
|
|
55
|
+
|
|
56
|
+
const handleClickAway = ( event: MouseEvent ) => {
|
|
57
|
+
if ( contentElement.contains( event.target as Node ) ) {
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
44
60
|
|
|
45
|
-
|
|
61
|
+
dismiss();
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
ownerDocument.addEventListener( 'mousedown', handleClickAway );
|
|
65
|
+
|
|
66
|
+
return () => ownerDocument.removeEventListener( 'mousedown', handleClickAway );
|
|
67
|
+
}, [ contentElement, dismiss ] );
|
|
68
|
+
|
|
69
|
+
if ( ! active ) {
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
46
72
|
|
|
47
73
|
return (
|
|
48
74
|
<ThemeProvider>
|
|
49
75
|
<InlineEditingOverlay expectedTag={ expectedTag } rootElement={ rootElement } id={ id } />
|
|
50
|
-
<style>
|
|
51
|
-
{ `
|
|
52
|
-
.ProseMirror > * {
|
|
53
|
-
height: 100%;
|
|
54
|
-
}
|
|
55
|
-
.${ EDITOR_WRAPPER_SELECTOR } .ProseMirror > button[contenteditable="true"] {
|
|
56
|
-
height: auto;
|
|
57
|
-
cursor: text;
|
|
58
|
-
}
|
|
59
|
-
` }
|
|
60
|
-
</style>
|
|
61
76
|
<InlineEditor
|
|
62
77
|
onEditorCreate={ setEditor }
|
|
78
|
+
mountElement={ contentElement }
|
|
63
79
|
editorProps={ {
|
|
64
80
|
attributes: {
|
|
65
|
-
style: 'outline: none;
|
|
81
|
+
style: 'outline: none; display: inherit; justify-content: inherit; align-items: inherit; flex-direction: inherit; text-align: inherit;',
|
|
66
82
|
},
|
|
67
83
|
} }
|
|
68
84
|
elementClasses={ elementClasses }
|
|
69
85
|
value={ initialValue }
|
|
70
86
|
setValue={ setValue }
|
|
71
|
-
onBlur={
|
|
87
|
+
onBlur={ dismiss }
|
|
72
88
|
autofocus
|
|
73
|
-
expectedTag={ expectedTag }
|
|
74
89
|
onSelectionEnd={ onSelectionEnd }
|
|
75
90
|
/>
|
|
76
91
|
{ toolbarAnchor && editor && <InlineEditingToolbar anchor={ toolbarAnchor } editor={ editor } id={ id } /> }
|
|
@@ -114,7 +129,14 @@ const InlineEditingToolbar = ( { anchor, editor, id }: { anchor: HTMLElement; ed
|
|
|
114
129
|
|
|
115
130
|
return (
|
|
116
131
|
<FloatingPortal id={ CANVAS_WRAPPER_ID }>
|
|
117
|
-
<Box
|
|
132
|
+
<Box
|
|
133
|
+
ref={ refs.setFloating }
|
|
134
|
+
role="presentation"
|
|
135
|
+
style={ {
|
|
136
|
+
...floatingStyles,
|
|
137
|
+
pointerEvents: 'none',
|
|
138
|
+
} }
|
|
139
|
+
>
|
|
118
140
|
<InlineEditorToolbar editor={ editor } elementId={ id } />
|
|
119
141
|
</Box>
|
|
120
142
|
</FloatingPortal>
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import { createRoot, type Root } from 'react-dom/client';
|
|
3
2
|
import { getContainer, getElementLabel, getElementType } from '@elementor/editor-elements';
|
|
4
3
|
import {
|
|
5
4
|
htmlV3PropTypeUtil,
|
|
@@ -25,8 +24,8 @@ type TagPropType = PropType< 'tag' > & {
|
|
|
25
24
|
const HISTORY_DEBOUNCE_WAIT = 800;
|
|
26
25
|
|
|
27
26
|
export default class InlineEditingReplacement extends ReplacementBase {
|
|
28
|
-
private inlineEditorRoot: Root | null = null;
|
|
29
27
|
private handlerAttached = false;
|
|
28
|
+
private editing = false;
|
|
30
29
|
|
|
31
30
|
getReplacementKey() {
|
|
32
31
|
return 'inline-editing';
|
|
@@ -37,7 +36,7 @@ export default class InlineEditingReplacement extends ReplacementBase {
|
|
|
37
36
|
}
|
|
38
37
|
|
|
39
38
|
isEditingModeActive() {
|
|
40
|
-
return
|
|
39
|
+
return this.editing;
|
|
41
40
|
}
|
|
42
41
|
|
|
43
42
|
shouldRenderReplacement() {
|
|
@@ -91,8 +90,8 @@ export default class InlineEditingReplacement extends ReplacementBase {
|
|
|
91
90
|
resetInlineEditorRoot() {
|
|
92
91
|
this.element.removeEventListener( 'click', this.handleRenderInlineEditor );
|
|
93
92
|
this.handlerAttached = false;
|
|
94
|
-
this.
|
|
95
|
-
this.
|
|
93
|
+
this.reactRoot.render( null );
|
|
94
|
+
this.editing = false;
|
|
96
95
|
}
|
|
97
96
|
|
|
98
97
|
unmountInlineEditor() {
|
|
@@ -239,22 +238,29 @@ export default class InlineEditingReplacement extends ReplacementBase {
|
|
|
239
238
|
this.resetInlineEditorRoot();
|
|
240
239
|
}
|
|
241
240
|
|
|
242
|
-
const
|
|
241
|
+
const contentElement = this.element.children?.[ 0 ] as HTMLElement | undefined;
|
|
242
|
+
|
|
243
|
+
if ( ! contentElement ) {
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
const elementClasses = contentElement.classList.toString();
|
|
243
248
|
const propValue = this.getExtractedContentValue();
|
|
244
249
|
const expectedTag = this.getExpectedTag();
|
|
245
250
|
|
|
246
|
-
|
|
251
|
+
contentElement.innerHTML = '';
|
|
252
|
+
this.editing = true;
|
|
247
253
|
|
|
248
|
-
this.
|
|
249
|
-
this.inlineEditorRoot.render(
|
|
254
|
+
this.reactRoot.render(
|
|
250
255
|
<CanvasInlineEditor
|
|
251
256
|
elementClasses={ elementClasses }
|
|
252
257
|
initialValue={ propValue }
|
|
253
258
|
expectedTag={ expectedTag }
|
|
254
259
|
rootElement={ this.element }
|
|
260
|
+
contentElement={ contentElement }
|
|
255
261
|
id={ this.id }
|
|
256
262
|
setValue={ this.setContentValue.bind( this ) }
|
|
257
|
-
|
|
263
|
+
requestDestroy={ this.unmountInlineEditor.bind( this ) }
|
|
258
264
|
/>
|
|
259
265
|
);
|
|
260
266
|
}
|
|
@@ -43,6 +43,7 @@ export const INLINE_EDITING_PROPERTY_PER_TYPE: Record< string, string > = {
|
|
|
43
43
|
'e-form-label': 'text',
|
|
44
44
|
'e-heading': 'title',
|
|
45
45
|
'e-paragraph': 'paragraph',
|
|
46
|
+
'e-form-submit-button': 'text',
|
|
46
47
|
};
|
|
47
48
|
|
|
48
49
|
export const legacyWindow = window as unknown as LegacyWindow;
|
|
@@ -79,6 +80,12 @@ export const useOnClickOutsideIframe = ( handleUnmount: () => void ) => {
|
|
|
79
80
|
export const useRenderToolbar = ( ownerDocument: Document, id: string ) => {
|
|
80
81
|
const [ anchor, setAnchor ] = useState< HTMLElement | null >( null );
|
|
81
82
|
|
|
83
|
+
useEffect( () => {
|
|
84
|
+
if ( ! anchor ) {
|
|
85
|
+
removeToolbarAnchor( ownerDocument, id );
|
|
86
|
+
}
|
|
87
|
+
}, [ anchor, ownerDocument, id ] );
|
|
88
|
+
|
|
82
89
|
const onSelectionEnd = ( view: EditorView ) => {
|
|
83
90
|
const hasSelection = ! view.state.selection.empty;
|
|
84
91
|
|
|
@@ -91,7 +98,11 @@ export const useRenderToolbar = ( ownerDocument: Document, id: string ) => {
|
|
|
91
98
|
}
|
|
92
99
|
};
|
|
93
100
|
|
|
94
|
-
|
|
101
|
+
const clearAnchor = useCallback( () => {
|
|
102
|
+
setAnchor( null );
|
|
103
|
+
}, [] );
|
|
104
|
+
|
|
105
|
+
return { onSelectionEnd, anchor, clearAnchor };
|
|
95
106
|
};
|
|
96
107
|
|
|
97
108
|
const createAnchorBasedOnSelection = ( ownerDocument: Document, id: string ): HTMLElement | null => {
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { createRoot, type Root } from 'react-dom/client';
|
|
2
|
+
|
|
1
3
|
import type { CreateTemplatedElementTypeOptions } from '../create-templated-element-type';
|
|
2
4
|
import { createTemplatedElementView } from '../create-templated-element-type';
|
|
3
5
|
import type { ElementType, ElementView, LegacyWindow, ReplacementSettings } from '../types';
|
|
@@ -34,11 +36,18 @@ export const createViewWithReplacements = ( options: CreateTemplatedElementTypeO
|
|
|
34
36
|
return class extends TemplatedView {
|
|
35
37
|
#replacement: ReplacementBaseInterface | null = null;
|
|
36
38
|
#config: ReplacementSettings;
|
|
39
|
+
#reactContainer: HTMLElement;
|
|
40
|
+
#reactRoot: Root;
|
|
37
41
|
|
|
38
42
|
constructor( ...args: unknown[] ) {
|
|
39
43
|
super( ...args );
|
|
40
44
|
const settings = this.model.get( 'settings' );
|
|
41
45
|
|
|
46
|
+
this.#reactContainer = this.el.ownerDocument.createElement( 'div' );
|
|
47
|
+
this.#reactContainer.style.display = 'none';
|
|
48
|
+
this.el.ownerDocument.body.appendChild( this.#reactContainer );
|
|
49
|
+
this.#reactRoot = createRoot( this.#reactContainer );
|
|
50
|
+
|
|
42
51
|
this.#config = {
|
|
43
52
|
getSetting: settings.get.bind( settings ),
|
|
44
53
|
setSetting: settings.set.bind( settings ),
|
|
@@ -46,6 +55,8 @@ export const createViewWithReplacements = ( options: CreateTemplatedElementTypeO
|
|
|
46
55
|
type: this?.model?.get( 'widgetType' ) ?? this.container?.model?.get( 'elType' ) ?? null,
|
|
47
56
|
id: this?.model?.get( 'id' ) ?? null,
|
|
48
57
|
refreshView: this.refreshView.bind( this ),
|
|
58
|
+
reactRoot: this.#reactRoot,
|
|
59
|
+
reactContainer: this.#reactContainer,
|
|
49
60
|
};
|
|
50
61
|
}
|
|
51
62
|
|
|
@@ -72,6 +83,8 @@ export const createViewWithReplacements = ( options: CreateTemplatedElementTypeO
|
|
|
72
83
|
|
|
73
84
|
onDestroy() {
|
|
74
85
|
this.#triggerAltMethod( 'onDestroy' );
|
|
86
|
+
this.#reactRoot.unmount();
|
|
87
|
+
this.#reactContainer.remove();
|
|
75
88
|
}
|
|
76
89
|
|
|
77
90
|
_afterRender() {
|
package/src/legacy/types.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type Root } from 'react-dom/client';
|
|
1
2
|
import { type V1Element } from '@elementor/editor-elements';
|
|
2
3
|
import { type Props, type PropValue } from '@elementor/editor-props';
|
|
3
4
|
|
|
@@ -241,4 +242,6 @@ export type ReplacementSettings = {
|
|
|
241
242
|
id: string;
|
|
242
243
|
element: HTMLElement;
|
|
243
244
|
refreshView: () => void;
|
|
245
|
+
reactRoot: Root;
|
|
246
|
+
reactContainer: HTMLElement;
|
|
244
247
|
};
|