@elementor/editor-components 3.35.0-475 → 3.35.0-476
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +144 -45
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +141 -42
- package/dist/index.mjs.map +1 -1
- package/package.json +22 -22
- package/src/components/edit-component/component-modal.tsx +15 -11
- package/src/components/edit-component/edit-component.tsx +44 -10
- package/src/init.ts +3 -0
- package/src/prevent-non-atomic-nesting.ts +1 -12
- package/src/sync/handle-component-edit-mode-container.ts +114 -0
- package/src/utils/is-editing-component.ts +13 -0
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@elementor/editor-components",
|
|
3
3
|
"description": "Elementor editor components",
|
|
4
|
-
"version": "3.35.0-
|
|
4
|
+
"version": "3.35.0-476",
|
|
5
5
|
"private": false,
|
|
6
6
|
"author": "Elementor Team",
|
|
7
7
|
"homepage": "https://elementor.com/",
|
|
@@ -40,30 +40,30 @@
|
|
|
40
40
|
"dev": "tsup --config=../../tsup.dev.ts"
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
|
-
"@elementor/editor": "3.35.0-
|
|
44
|
-
"@elementor/editor-canvas": "3.35.0-
|
|
45
|
-
"@elementor/editor-controls": "3.35.0-
|
|
46
|
-
"@elementor/editor-documents": "3.35.0-
|
|
47
|
-
"@elementor/editor-editing-panel": "3.35.0-
|
|
48
|
-
"@elementor/editor-elements": "3.35.0-
|
|
49
|
-
"@elementor/editor-elements-panel": "3.35.0-
|
|
50
|
-
"@elementor/editor-mcp": "3.35.0-
|
|
51
|
-
"@elementor/editor-panels": "3.35.0-
|
|
52
|
-
"@elementor/editor-props": "3.35.0-
|
|
53
|
-
"@elementor/editor-styles-repository": "3.35.0-
|
|
54
|
-
"@elementor/editor-ui": "3.35.0-
|
|
55
|
-
"@elementor/editor-v1-adapters": "3.35.0-
|
|
56
|
-
"@elementor/http-client": "3.35.0-
|
|
43
|
+
"@elementor/editor": "3.35.0-476",
|
|
44
|
+
"@elementor/editor-canvas": "3.35.0-476",
|
|
45
|
+
"@elementor/editor-controls": "3.35.0-476",
|
|
46
|
+
"@elementor/editor-documents": "3.35.0-476",
|
|
47
|
+
"@elementor/editor-editing-panel": "3.35.0-476",
|
|
48
|
+
"@elementor/editor-elements": "3.35.0-476",
|
|
49
|
+
"@elementor/editor-elements-panel": "3.35.0-476",
|
|
50
|
+
"@elementor/editor-mcp": "3.35.0-476",
|
|
51
|
+
"@elementor/editor-panels": "3.35.0-476",
|
|
52
|
+
"@elementor/editor-props": "3.35.0-476",
|
|
53
|
+
"@elementor/editor-styles-repository": "3.35.0-476",
|
|
54
|
+
"@elementor/editor-ui": "3.35.0-476",
|
|
55
|
+
"@elementor/editor-v1-adapters": "3.35.0-476",
|
|
56
|
+
"@elementor/http-client": "3.35.0-476",
|
|
57
57
|
"@elementor/icons": "^1.63.0",
|
|
58
|
-
"@elementor/mixpanel": "3.35.0-
|
|
59
|
-
"@elementor/query": "3.35.0-
|
|
60
|
-
"@elementor/schema": "3.35.0-
|
|
61
|
-
"@elementor/store": "3.35.0-
|
|
58
|
+
"@elementor/mixpanel": "3.35.0-476",
|
|
59
|
+
"@elementor/query": "3.35.0-476",
|
|
60
|
+
"@elementor/schema": "3.35.0-476",
|
|
61
|
+
"@elementor/store": "3.35.0-476",
|
|
62
62
|
"@elementor/ui": "1.36.17",
|
|
63
|
-
"@elementor/utils": "3.35.0-
|
|
63
|
+
"@elementor/utils": "3.35.0-476",
|
|
64
64
|
"@wordpress/i18n": "^5.13.0",
|
|
65
|
-
"@elementor/editor-notifications": "3.35.0-
|
|
66
|
-
"@elementor/editor-current-user": "3.35.0-
|
|
65
|
+
"@elementor/editor-notifications": "3.35.0-476",
|
|
66
|
+
"@elementor/editor-current-user": "3.35.0-476"
|
|
67
67
|
},
|
|
68
68
|
"peerDependencies": {
|
|
69
69
|
"react": "^18.3.1",
|
|
@@ -7,11 +7,11 @@ import { useCanvasDocument } from '../../hooks/use-canvas-document';
|
|
|
7
7
|
import { useElementRect } from '../../hooks/use-element-rect';
|
|
8
8
|
|
|
9
9
|
type ModalProps = {
|
|
10
|
-
|
|
10
|
+
topLevelElementDom: HTMLElement | null;
|
|
11
11
|
onClose: () => void;
|
|
12
12
|
};
|
|
13
13
|
|
|
14
|
-
export function ComponentModal( {
|
|
14
|
+
export function ComponentModal( { topLevelElementDom, onClose }: ModalProps ) {
|
|
15
15
|
const canvasDocument = useCanvasDocument();
|
|
16
16
|
|
|
17
17
|
useEffect( () => {
|
|
@@ -35,14 +35,23 @@ export function ComponentModal( { element, onClose }: ModalProps ) {
|
|
|
35
35
|
return createPortal(
|
|
36
36
|
<>
|
|
37
37
|
<BlockEditPage />
|
|
38
|
-
<Backdrop canvas={ canvasDocument } element={
|
|
38
|
+
<Backdrop canvas={ canvasDocument } element={ topLevelElementDom } onClose={ onClose } />
|
|
39
39
|
</>,
|
|
40
40
|
canvasDocument.body
|
|
41
41
|
);
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
function Backdrop( {
|
|
44
|
+
function Backdrop( {
|
|
45
|
+
canvas,
|
|
46
|
+
element,
|
|
47
|
+
onClose,
|
|
48
|
+
}: {
|
|
49
|
+
canvas: HTMLDocument;
|
|
50
|
+
element: HTMLElement | null;
|
|
51
|
+
onClose: () => void;
|
|
52
|
+
} ) {
|
|
45
53
|
const rect = useElementRect( element );
|
|
54
|
+
const clipPath = element ? getRectPath( rect, canvas.defaultView as Window ) : undefined;
|
|
46
55
|
const backdropStyle: CSSProperties = {
|
|
47
56
|
position: 'fixed',
|
|
48
57
|
top: 0,
|
|
@@ -53,7 +62,7 @@ function Backdrop( { canvas, element, onClose }: { canvas: HTMLDocument; element
|
|
|
53
62
|
zIndex: 999,
|
|
54
63
|
pointerEvents: 'painted',
|
|
55
64
|
cursor: 'pointer',
|
|
56
|
-
clipPath
|
|
65
|
+
clipPath,
|
|
57
66
|
};
|
|
58
67
|
|
|
59
68
|
const handleKeyDown = ( event: React.KeyboardEvent ) => {
|
|
@@ -76,12 +85,7 @@ function Backdrop( { canvas, element, onClose }: { canvas: HTMLDocument; element
|
|
|
76
85
|
}
|
|
77
86
|
|
|
78
87
|
function getRectPath( rect: DOMRect, viewport: Window ) {
|
|
79
|
-
const { x
|
|
80
|
-
const x = originalX;
|
|
81
|
-
const y = originalY;
|
|
82
|
-
const width = originalWidth;
|
|
83
|
-
const height = originalHeight;
|
|
84
|
-
|
|
88
|
+
const { x, y, width, height } = rect;
|
|
85
89
|
const { innerWidth: vw, innerHeight: vh } = viewport;
|
|
86
90
|
|
|
87
91
|
const path = `path(evenodd, 'M 0 0
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import { useEffect } from 'react';
|
|
2
|
+
import { useEffect, useState } from 'react';
|
|
3
3
|
import { getV1DocumentsManager, type V1Document } from '@elementor/editor-documents';
|
|
4
4
|
import { type V1Element } from '@elementor/editor-elements';
|
|
5
5
|
import { __privateListenTo as listenTo, commandEndEvent } from '@elementor/editor-v1-adapters';
|
|
@@ -22,13 +22,13 @@ export function EditComponent() {
|
|
|
22
22
|
|
|
23
23
|
const onClose = throttle( navigateBack, 100 );
|
|
24
24
|
|
|
25
|
-
const
|
|
25
|
+
const topLevelElementDom = useComponentDOMElement( currentComponentId ?? undefined );
|
|
26
26
|
|
|
27
|
-
if ( !
|
|
27
|
+
if ( ! currentComponentId ) {
|
|
28
28
|
return null;
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
return <ComponentModal
|
|
31
|
+
return <ComponentModal topLevelElementDom={ topLevelElementDom } onClose={ onClose } />;
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
function useHandleDocumentSwitches() {
|
|
@@ -112,18 +112,52 @@ function getInstanceTitle( instanceId: string | undefined, path: ComponentsPathI
|
|
|
112
112
|
return editorSettings?.title;
|
|
113
113
|
}
|
|
114
114
|
|
|
115
|
-
function
|
|
115
|
+
function useComponentDOMElement( id: V1Document[ 'id' ] | undefined ) {
|
|
116
|
+
const { componentContainerDomElement, topLevelElementDom } = getComponentDOMElements( id );
|
|
117
|
+
|
|
118
|
+
const [ currentElementDom, setCurrentElementDom ] = useState< HTMLElement | null >( topLevelElementDom );
|
|
119
|
+
|
|
120
|
+
useEffect( () => {
|
|
121
|
+
setCurrentElementDom( topLevelElementDom );
|
|
122
|
+
}, [ topLevelElementDom ] );
|
|
123
|
+
|
|
124
|
+
useEffect( () => {
|
|
125
|
+
if ( ! componentContainerDomElement ) {
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const mutationObserver = new MutationObserver( () => {
|
|
130
|
+
const newElementDom = componentContainerDomElement.children[ 0 ] as HTMLElement | null;
|
|
131
|
+
setCurrentElementDom( newElementDom );
|
|
132
|
+
} );
|
|
133
|
+
|
|
134
|
+
mutationObserver.observe( componentContainerDomElement, { childList: true } );
|
|
135
|
+
|
|
136
|
+
return () => {
|
|
137
|
+
mutationObserver.disconnect();
|
|
138
|
+
};
|
|
139
|
+
}, [ componentContainerDomElement ] );
|
|
140
|
+
|
|
141
|
+
return currentElementDom;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
type ComponentDOMElements = {
|
|
145
|
+
componentContainerDomElement: HTMLElement | null;
|
|
146
|
+
topLevelElementDom: HTMLElement | null;
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
function getComponentDOMElements( id: V1Document[ 'id' ] | undefined ): ComponentDOMElements {
|
|
116
150
|
if ( ! id ) {
|
|
117
|
-
return null;
|
|
151
|
+
return { componentContainerDomElement: null, topLevelElementDom: null };
|
|
118
152
|
}
|
|
119
153
|
|
|
120
154
|
const documentsManager = getV1DocumentsManager();
|
|
121
155
|
|
|
122
156
|
const currentComponent = documentsManager.get( id );
|
|
123
157
|
|
|
124
|
-
const
|
|
125
|
-
const
|
|
126
|
-
const
|
|
158
|
+
const componentContainer = currentComponent?.container as V1Element;
|
|
159
|
+
const componentContainerDomElement = ( componentContainer?.view?.el?.children?.[ 0 ] as HTMLElement ) ?? null;
|
|
160
|
+
const topLevelElementDom = ( componentContainerDomElement?.children[ 0 ] as HTMLElement ) ?? null;
|
|
127
161
|
|
|
128
|
-
return
|
|
162
|
+
return { componentContainerDomElement, topLevelElementDom };
|
|
129
163
|
}
|
package/src/init.ts
CHANGED
|
@@ -45,6 +45,7 @@ import { componentsStylesProvider } from './store/components-styles-provider';
|
|
|
45
45
|
import { slice } from './store/store';
|
|
46
46
|
import { beforeSave } from './sync/before-save';
|
|
47
47
|
import { initCleanupOverridablePropsOnDelete } from './sync/cleanup-overridable-props-on-delete';
|
|
48
|
+
import { initHandleComponentEditModeContainer } from './sync/handle-component-edit-mode-container';
|
|
48
49
|
import { initLoadComponentDataAfterInstanceAdded } from './sync/load-component-data-after-instance-added';
|
|
49
50
|
import { initRegenerateOverrideKeys } from './sync/regenerate-override-keys';
|
|
50
51
|
import { type ExtendedWindow } from './types';
|
|
@@ -143,4 +144,6 @@ export function init() {
|
|
|
143
144
|
initNonAtomicNestingPrevention();
|
|
144
145
|
|
|
145
146
|
initLoadComponentDataAfterInstanceAdded();
|
|
147
|
+
|
|
148
|
+
initHandleComponentEditModeContainer();
|
|
146
149
|
}
|
|
@@ -2,11 +2,10 @@ import { isAtomicWidget } from '@elementor/editor-canvas';
|
|
|
2
2
|
import { getAllDescendants, getElementType, type V1Element } from '@elementor/editor-elements';
|
|
3
3
|
import { type NotificationData, notify } from '@elementor/editor-notifications';
|
|
4
4
|
import { blockCommand } from '@elementor/editor-v1-adapters';
|
|
5
|
-
import { __getStore as getStore } from '@elementor/store';
|
|
6
5
|
import { __ } from '@wordpress/i18n';
|
|
7
6
|
|
|
8
|
-
import { type ComponentsSlice, selectCurrentComponentId } from './store/store';
|
|
9
7
|
import { type ExtendedWindow } from './types';
|
|
8
|
+
import { isEditingComponent } from './utils/is-editing-component';
|
|
10
9
|
|
|
11
10
|
type CreateArgs = {
|
|
12
11
|
container?: V1Element;
|
|
@@ -63,16 +62,6 @@ export function initNonAtomicNestingPrevention() {
|
|
|
63
62
|
} );
|
|
64
63
|
}
|
|
65
64
|
|
|
66
|
-
function isEditingComponent(): boolean {
|
|
67
|
-
const state = getStore()?.getState() as ComponentsSlice | undefined;
|
|
68
|
-
|
|
69
|
-
if ( ! state ) {
|
|
70
|
-
return false;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
return selectCurrentComponentId( state ) !== null;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
65
|
export function isElementAtomic( elementType: string ): boolean {
|
|
77
66
|
return getElementType( elementType ) !== null;
|
|
78
67
|
}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { type V1Document } from '@elementor/editor-documents';
|
|
2
|
+
import { createElement, selectElement, type V1Element } from '@elementor/editor-elements';
|
|
3
|
+
import { registerDataHook } from '@elementor/editor-v1-adapters';
|
|
4
|
+
|
|
5
|
+
import { COMPONENT_DOCUMENT_TYPE } from '../components/consts';
|
|
6
|
+
import { isEditingComponent } from '../utils/is-editing-component';
|
|
7
|
+
|
|
8
|
+
const V4_DEFAULT_CONTAINER_TYPE = 'e-flexbox';
|
|
9
|
+
|
|
10
|
+
type Container = Omit< V1Element, 'children' | 'parent' > & {
|
|
11
|
+
document?: V1Document;
|
|
12
|
+
parent?: Container;
|
|
13
|
+
children?: Container[];
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export function initHandleComponentEditModeContainer() {
|
|
17
|
+
initRedirectDropIntoComponent();
|
|
18
|
+
initHandleTopLevelElementDelete();
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export type DeleteArgs = {
|
|
22
|
+
container?: Container;
|
|
23
|
+
containers?: Container[];
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
function initHandleTopLevelElementDelete() {
|
|
27
|
+
registerDataHook( 'after', 'document/elements/delete', ( args: DeleteArgs ) => {
|
|
28
|
+
if ( ! isEditingComponent() ) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const containers = args.containers ?? ( args.container ? [ args.container ] : [] );
|
|
33
|
+
|
|
34
|
+
for ( const container of containers ) {
|
|
35
|
+
if ( ! container.parent || ! isComponent( container.parent ) ) {
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const component = container.parent;
|
|
40
|
+
const isComponentEmpty = component.children?.length === 0;
|
|
41
|
+
|
|
42
|
+
if ( isComponentEmpty ) {
|
|
43
|
+
createEmptyTopLevelContainer( container.parent );
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
} );
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
type DropArgs = {
|
|
50
|
+
container?: Container;
|
|
51
|
+
containers?: Container[];
|
|
52
|
+
model?: unknown;
|
|
53
|
+
options?: unknown;
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
function initRedirectDropIntoComponent() {
|
|
57
|
+
registerDataHook( 'dependency', 'preview/drop', ( args: DropArgs ) => {
|
|
58
|
+
if ( ! isEditingComponent() ) {
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const containers = args.containers ?? ( args.container ? [ args.container ] : [] );
|
|
63
|
+
|
|
64
|
+
for ( const container of containers ) {
|
|
65
|
+
if ( ! isComponent( container ) ) {
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const { shouldRedirect, container: redirectedContainer } = getComponentContainer( container );
|
|
70
|
+
|
|
71
|
+
if ( ! shouldRedirect ) {
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if ( args.containers ) {
|
|
76
|
+
const index = args.containers.indexOf( container );
|
|
77
|
+
args.containers[ index ] = redirectedContainer;
|
|
78
|
+
} else {
|
|
79
|
+
args.container = redirectedContainer;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return true;
|
|
84
|
+
} );
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function createEmptyTopLevelContainer( container: Container ) {
|
|
88
|
+
const newContainer = createElement( {
|
|
89
|
+
containerId: container.id,
|
|
90
|
+
model: { elType: V4_DEFAULT_CONTAINER_TYPE },
|
|
91
|
+
} );
|
|
92
|
+
|
|
93
|
+
selectElement( newContainer.id );
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function getComponentContainer( container: Container ): { shouldRedirect: boolean; container: Container } {
|
|
97
|
+
const topLevelElement = container.children?.[ 0 ];
|
|
98
|
+
|
|
99
|
+
if ( topLevelElement ) {
|
|
100
|
+
return { shouldRedirect: true, container: topLevelElement };
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return { shouldRedirect: false, container };
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function isComponent( container: Container ): boolean {
|
|
107
|
+
const isDocument = container.id === 'document';
|
|
108
|
+
|
|
109
|
+
if ( ! isDocument ) {
|
|
110
|
+
return false;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return container.document?.config.type === COMPONENT_DOCUMENT_TYPE;
|
|
114
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { __getStore as getStore } from '@elementor/store';
|
|
2
|
+
|
|
3
|
+
import { type ComponentsSlice, selectCurrentComponentId } from '../store/store';
|
|
4
|
+
|
|
5
|
+
export function isEditingComponent(): boolean {
|
|
6
|
+
const state = getStore()?.getState() as ComponentsSlice | undefined;
|
|
7
|
+
|
|
8
|
+
if ( ! state ) {
|
|
9
|
+
return false;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
return selectCurrentComponentId( state ) !== null;
|
|
13
|
+
}
|