@elementor/editor-elements 4.0.0-543 → 4.0.0-545
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 +40 -36
- package/dist/index.d.ts +40 -36
- package/dist/index.js +174 -183
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +174 -182
- package/dist/index.mjs.map +1 -1
- package/package.json +7 -7
- package/src/hooks/use-element-children.ts +1 -1
- package/src/index.ts +2 -8
- package/src/sync/create-element.ts +3 -10
- package/src/sync/create-elements.ts +42 -35
- package/src/sync/delete-element.ts +5 -12
- package/src/sync/duplicate-element.ts +4 -12
- package/src/sync/duplicate-elements.ts +40 -44
- package/src/sync/{get-model.ts → model-utils.ts} +8 -22
- package/src/sync/move-element.ts +13 -15
- package/src/sync/move-elements.ts +73 -51
- package/src/sync/remove-elements.ts +37 -29
- package/src/sync/replace-element.ts +20 -21
- package/src/sync/types.ts +1 -0
- package/src/sync/update-element-editor-settings.ts +1 -5
- package/src/sync/update-element-interactions.ts +1 -5
- package/src/sync/update-element-settings.ts +4 -0
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { __privateRunCommandSync as runCommandSync } from '@elementor/editor-v1-adapters';
|
|
2
2
|
|
|
3
|
-
import { getContainer } from './get-container';
|
|
4
3
|
import { type V1Element } from './types';
|
|
5
4
|
|
|
6
5
|
type Options = {
|
|
@@ -10,23 +9,16 @@ type Options = {
|
|
|
10
9
|
};
|
|
11
10
|
|
|
12
11
|
export type DuplicateElementParams = {
|
|
13
|
-
|
|
12
|
+
element: V1Element;
|
|
14
13
|
options?: Options;
|
|
15
14
|
};
|
|
16
15
|
|
|
17
|
-
export function duplicateElement( {
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
if ( ! elementToDuplicate ) {
|
|
21
|
-
throw new Error( `Element with ID "${ elementId }" not found` );
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
// Get the position after the original element (only when cloning)
|
|
25
|
-
const currentIndex = elementToDuplicate.view?._index ?? 0;
|
|
16
|
+
export function duplicateElement( { element, options = {} }: DuplicateElementParams ): V1Element {
|
|
17
|
+
const currentIndex = element.view?._index ?? 0;
|
|
26
18
|
const insertPosition = options.clone !== false ? currentIndex + 1 : undefined;
|
|
27
19
|
|
|
28
20
|
return runCommandSync< V1Element >( 'document/elements/duplicate', {
|
|
29
|
-
container:
|
|
21
|
+
container: element,
|
|
30
22
|
options: { at: insertPosition, edit: false, ...options },
|
|
31
23
|
} );
|
|
32
24
|
}
|
|
@@ -5,7 +5,7 @@ import { createElement } from './create-element';
|
|
|
5
5
|
import { deleteElement } from './delete-element';
|
|
6
6
|
import { duplicateElement } from './duplicate-element';
|
|
7
7
|
import { getContainer } from './get-container';
|
|
8
|
-
import { type V1ElementModelProps } from './types';
|
|
8
|
+
import { type V1Element, type V1ElementModelProps } from './types';
|
|
9
9
|
|
|
10
10
|
type DuplicateElementsParams = {
|
|
11
11
|
elementIds: string[];
|
|
@@ -16,11 +16,9 @@ type DuplicateElementsParams = {
|
|
|
16
16
|
};
|
|
17
17
|
|
|
18
18
|
type DuplicatedElement = {
|
|
19
|
-
|
|
19
|
+
container: V1Element;
|
|
20
|
+
parentContainer: V1Element;
|
|
20
21
|
model: V1ElementModelProps;
|
|
21
|
-
originalElementId: string;
|
|
22
|
-
modelToRestore?: V1ElementModelProps;
|
|
23
|
-
parentContainerId?: string;
|
|
24
22
|
at?: number;
|
|
25
23
|
};
|
|
26
24
|
|
|
@@ -40,38 +38,40 @@ export const duplicateElements = ( {
|
|
|
40
38
|
const undoableDuplicate = undoable(
|
|
41
39
|
{
|
|
42
40
|
do: ( { elementIds: elementIdsToDuplicate }: { elementIds: string[] } ): DuplicatedElementsResult => {
|
|
43
|
-
// Call onCreate before duplicating elements to avoid conflicts between commands
|
|
44
41
|
onDuplicateElements?.();
|
|
45
|
-
const duplicatedElements: DuplicatedElement[] =
|
|
42
|
+
const duplicatedElements: DuplicatedElement[] = [];
|
|
43
|
+
|
|
44
|
+
elementIdsToDuplicate.forEach( ( elementId ) => {
|
|
46
45
|
const originalContainer = getContainer( elementId );
|
|
47
46
|
|
|
48
|
-
if ( originalContainer?.parent ) {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
options: { useHistory: false },
|
|
52
|
-
} );
|
|
47
|
+
if ( ! originalContainer?.parent ) {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
53
50
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
} );
|
|
51
|
+
const duplicatedElement = duplicateElement( {
|
|
52
|
+
element: originalContainer,
|
|
53
|
+
options: { useHistory: false },
|
|
54
|
+
} );
|
|
55
|
+
|
|
56
|
+
if ( ! duplicatedElement.parent ) {
|
|
57
|
+
return;
|
|
62
58
|
}
|
|
63
59
|
|
|
64
|
-
|
|
65
|
-
|
|
60
|
+
duplicatedElements.push( {
|
|
61
|
+
container: duplicatedElement,
|
|
62
|
+
parentContainer: duplicatedElement.parent,
|
|
63
|
+
model: duplicatedElement.model.toJSON(),
|
|
64
|
+
at: duplicatedElement.view?._index,
|
|
65
|
+
} );
|
|
66
|
+
} );
|
|
66
67
|
|
|
67
68
|
return { duplicatedElements };
|
|
68
69
|
},
|
|
69
70
|
undo: ( _: { elementIds: string[] }, { duplicatedElements }: DuplicatedElementsResult ) => {
|
|
70
71
|
onRestoreElements?.();
|
|
71
|
-
|
|
72
|
-
[ ...duplicatedElements ].reverse().forEach( ( { id } ) => {
|
|
72
|
+
[ ...duplicatedElements ].reverse().forEach( ( { container } ) => {
|
|
73
73
|
deleteElement( {
|
|
74
|
-
|
|
74
|
+
container,
|
|
75
75
|
options: { useHistory: false },
|
|
76
76
|
} );
|
|
77
77
|
} );
|
|
@@ -81,30 +81,26 @@ export const duplicateElements = ( {
|
|
|
81
81
|
{ duplicatedElements: previousElements }: DuplicatedElementsResult
|
|
82
82
|
): DuplicatedElementsResult => {
|
|
83
83
|
onDuplicateElements?.();
|
|
84
|
-
const duplicatedElements: DuplicatedElement[] =
|
|
85
|
-
|
|
84
|
+
const duplicatedElements: DuplicatedElement[] = [];
|
|
85
|
+
|
|
86
|
+
previousElements.forEach( ( { parentContainer, model, at } ) => {
|
|
87
|
+
const freshParent = parentContainer.lookup?.();
|
|
88
|
+
|
|
89
|
+
if ( freshParent ) {
|
|
86
90
|
const createdElement = createElement( {
|
|
87
|
-
|
|
88
|
-
model
|
|
89
|
-
options: {
|
|
90
|
-
useHistory: false,
|
|
91
|
-
clone: false,
|
|
92
|
-
at: previousElement.at,
|
|
93
|
-
},
|
|
91
|
+
container: freshParent,
|
|
92
|
+
model,
|
|
93
|
+
options: { useHistory: false, clone: false, at },
|
|
94
94
|
} );
|
|
95
95
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
parentContainerId: previousElement.parentContainerId,
|
|
102
|
-
at: previousElement.at,
|
|
96
|
+
duplicatedElements.push( {
|
|
97
|
+
container: createdElement,
|
|
98
|
+
parentContainer: freshParent,
|
|
99
|
+
model,
|
|
100
|
+
at,
|
|
103
101
|
} );
|
|
104
102
|
}
|
|
105
|
-
|
|
106
|
-
return acc;
|
|
107
|
-
}, [] as DuplicatedElement[] );
|
|
103
|
+
} );
|
|
108
104
|
|
|
109
105
|
return { duplicatedElements };
|
|
110
106
|
},
|
|
@@ -1,31 +1,17 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type V1Element } from './types';
|
|
2
2
|
|
|
3
|
-
type V1Model = V1Element[ 'model' ];
|
|
3
|
+
export type V1Model = V1Element[ 'model' ];
|
|
4
|
+
|
|
5
|
+
export type V1Collection = V1Model[] & {
|
|
6
|
+
remove: ( model: V1Model ) => void;
|
|
7
|
+
add: ( model: V1Model, options?: { at?: number }, silent?: boolean ) => void;
|
|
8
|
+
indexOf: ( model: V1Model ) => number;
|
|
9
|
+
};
|
|
4
10
|
|
|
5
11
|
export type ModelResult = {
|
|
6
12
|
model: V1Model;
|
|
7
13
|
};
|
|
8
14
|
|
|
9
|
-
export function getModel( id: string, parentModel?: V1Model ): ModelResult | null {
|
|
10
|
-
const extendedWindow = window as unknown as ExtendedWindow;
|
|
11
|
-
const container = extendedWindow.elementor?.getContainer?.( id ) ?? null;
|
|
12
|
-
|
|
13
|
-
if ( container ) {
|
|
14
|
-
return { model: container.model };
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
if ( parentModel ) {
|
|
18
|
-
const childModels = parentModel.get( 'elements' ) ?? [];
|
|
19
|
-
const model = childModels.find( ( m ) => m.get( 'id' ) === id );
|
|
20
|
-
|
|
21
|
-
if ( model ) {
|
|
22
|
-
return { model };
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
return null;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
15
|
export function findChildRecursive( model: V1Model, predicate: ( model: V1Model ) => boolean ): ModelResult | null {
|
|
30
16
|
const childModels = ( model.get( 'elements' ) ?? [] ) as V1Model[];
|
|
31
17
|
|
package/src/sync/move-element.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createElement } from './create-element';
|
|
2
2
|
import { deleteElement } from './delete-element';
|
|
3
|
-
import {
|
|
3
|
+
import { type V1Element } from './types';
|
|
4
4
|
|
|
5
5
|
type Options = {
|
|
6
6
|
useHistory?: boolean;
|
|
@@ -9,35 +9,33 @@ type Options = {
|
|
|
9
9
|
};
|
|
10
10
|
|
|
11
11
|
export type MoveElementParams = {
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
element: V1Element;
|
|
13
|
+
targetContainer: V1Element;
|
|
14
14
|
options?: Options;
|
|
15
15
|
};
|
|
16
16
|
|
|
17
|
-
export function moveElement( {
|
|
18
|
-
const
|
|
19
|
-
const
|
|
17
|
+
export function moveElement( { element, targetContainer, options = {} }: MoveElementParams ): V1Element {
|
|
18
|
+
const resolvedElement = element.lookup?.();
|
|
19
|
+
const resolvedTarget = targetContainer.lookup?.();
|
|
20
20
|
|
|
21
|
-
if ( !
|
|
22
|
-
throw new Error( `Element
|
|
21
|
+
if ( ! resolvedElement ) {
|
|
22
|
+
throw new Error( `Element not found: ${ element.id }` );
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
if ( !
|
|
26
|
-
throw new Error( `Target container
|
|
25
|
+
if ( ! resolvedTarget ) {
|
|
26
|
+
throw new Error( `Target container not found: ${ targetContainer.id }` );
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
const modelToRecreate =
|
|
29
|
+
const modelToRecreate = resolvedElement.model.toJSON();
|
|
30
30
|
|
|
31
31
|
deleteElement( {
|
|
32
|
-
|
|
33
|
-
// prevent inner history from being created
|
|
32
|
+
container: resolvedElement,
|
|
34
33
|
options: { ...options, useHistory: false },
|
|
35
34
|
} );
|
|
36
35
|
|
|
37
36
|
const newContainer = createElement( {
|
|
38
|
-
|
|
37
|
+
container: resolvedTarget,
|
|
39
38
|
model: modelToRecreate,
|
|
40
|
-
// prevent inner history from being created
|
|
41
39
|
options: { edit: false, ...options, useHistory: false },
|
|
42
40
|
} );
|
|
43
41
|
|
|
@@ -1,36 +1,42 @@
|
|
|
1
1
|
import { undoable } from '@elementor/editor-v1-adapters';
|
|
2
2
|
import { __ } from '@wordpress/i18n';
|
|
3
3
|
|
|
4
|
-
import {
|
|
5
|
-
import { moveElement, type MoveElementParams } from './move-element';
|
|
4
|
+
import { moveElement } from './move-element';
|
|
6
5
|
import { type V1Element } from './types';
|
|
7
6
|
|
|
7
|
+
type MoveOptions = {
|
|
8
|
+
useHistory?: boolean;
|
|
9
|
+
at?: number;
|
|
10
|
+
edit?: boolean;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
type MoveInput = {
|
|
14
|
+
element: V1Element;
|
|
15
|
+
targetContainer: V1Element;
|
|
16
|
+
options?: MoveOptions;
|
|
17
|
+
};
|
|
18
|
+
|
|
8
19
|
type MoveElementsParams = {
|
|
9
|
-
moves:
|
|
20
|
+
moves: MoveInput[];
|
|
10
21
|
title: string;
|
|
11
22
|
subtitle?: string;
|
|
12
23
|
onMoveElements?: () => void;
|
|
13
24
|
onRestoreElements?: () => void;
|
|
14
25
|
};
|
|
15
26
|
|
|
16
|
-
type OriginalPosition = {
|
|
17
|
-
elementId: string;
|
|
18
|
-
originalContainerId: string;
|
|
19
|
-
originalIndex: number;
|
|
20
|
-
};
|
|
21
|
-
|
|
22
27
|
type MovedElement = {
|
|
23
|
-
elementId: string;
|
|
24
|
-
originalPosition: OriginalPosition;
|
|
25
|
-
move: MoveElementParams;
|
|
26
28
|
element: V1Element;
|
|
29
|
+
originalContainer: V1Element;
|
|
30
|
+
originalIndex: number;
|
|
31
|
+
targetContainer: V1Element;
|
|
32
|
+
options?: MoveOptions;
|
|
27
33
|
};
|
|
28
34
|
|
|
29
35
|
type MovedElementsResult = {
|
|
30
36
|
movedElements: MovedElement[];
|
|
31
37
|
};
|
|
32
38
|
|
|
33
|
-
export type { MoveElementsParams, MovedElement, MovedElementsResult };
|
|
39
|
+
export type { MoveElementsParams, MoveInput, MovedElement, MovedElementsResult };
|
|
34
40
|
|
|
35
41
|
export const moveElements = ( {
|
|
36
42
|
moves: movesToMake,
|
|
@@ -41,51 +47,60 @@ export const moveElements = ( {
|
|
|
41
47
|
}: MoveElementsParams ): MovedElementsResult => {
|
|
42
48
|
const undoableMove = undoable(
|
|
43
49
|
{
|
|
44
|
-
do: ( { moves }: { moves:
|
|
50
|
+
do: ( { moves }: { moves: MoveInput[] } ): MovedElementsResult => {
|
|
45
51
|
const movedElements: MovedElement[] = [];
|
|
46
|
-
// Call onMoveElements before moving element to avoid conflicts between commands
|
|
47
52
|
onMoveElements?.();
|
|
48
|
-
moves.forEach( ( move ) => {
|
|
49
|
-
const { elementId } = move;
|
|
50
|
-
const sourceContainer = getContainer( elementId );
|
|
51
53
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
+
moves.forEach( ( { element, targetContainer, options } ) => {
|
|
55
|
+
const sourceElement = element.lookup?.() ?? element;
|
|
56
|
+
const target = targetContainer.lookup?.() ?? targetContainer;
|
|
57
|
+
|
|
58
|
+
if ( ! sourceElement ) {
|
|
59
|
+
throw new Error( 'Element not found' );
|
|
54
60
|
}
|
|
55
61
|
|
|
56
|
-
|
|
57
|
-
|
|
62
|
+
if ( ! target ) {
|
|
63
|
+
throw new Error( 'Target container not found' );
|
|
64
|
+
}
|
|
58
65
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
66
|
+
if ( ! sourceElement.parent ) {
|
|
67
|
+
throw new Error( 'Element has no parent container' );
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const originalContainer = sourceElement.parent;
|
|
71
|
+
const originalIndex = originalContainer.children?.indexOf( sourceElement ) ?? -1;
|
|
64
72
|
|
|
65
|
-
const
|
|
66
|
-
|
|
67
|
-
|
|
73
|
+
const newElement = moveElement( {
|
|
74
|
+
element: sourceElement,
|
|
75
|
+
targetContainer: target,
|
|
76
|
+
options: { ...options, useHistory: false },
|
|
68
77
|
} );
|
|
69
78
|
|
|
70
79
|
movedElements.push( {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
80
|
+
element: newElement,
|
|
81
|
+
originalContainer,
|
|
82
|
+
originalIndex,
|
|
83
|
+
targetContainer: target,
|
|
84
|
+
options,
|
|
75
85
|
} );
|
|
76
86
|
} );
|
|
77
87
|
|
|
78
88
|
return { movedElements };
|
|
79
89
|
},
|
|
80
|
-
undo: ( _: { moves:
|
|
90
|
+
undo: ( _: { moves: MoveInput[] }, { movedElements }: MovedElementsResult ) => {
|
|
81
91
|
onRestoreElements?.();
|
|
82
92
|
|
|
83
|
-
[ ...movedElements ].reverse().forEach( ( {
|
|
84
|
-
const
|
|
93
|
+
[ ...movedElements ].reverse().forEach( ( { element, originalContainer, originalIndex } ) => {
|
|
94
|
+
const freshElement = element.lookup?.();
|
|
95
|
+
const freshOriginalContainer = originalContainer.lookup?.();
|
|
96
|
+
|
|
97
|
+
if ( ! freshElement || ! freshOriginalContainer ) {
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
85
100
|
|
|
86
101
|
moveElement( {
|
|
87
|
-
|
|
88
|
-
|
|
102
|
+
element: freshElement,
|
|
103
|
+
targetContainer: freshOriginalContainer,
|
|
89
104
|
options: {
|
|
90
105
|
useHistory: false,
|
|
91
106
|
at: originalIndex >= 0 ? originalIndex : undefined,
|
|
@@ -93,24 +108,31 @@ export const moveElements = ( {
|
|
|
93
108
|
} );
|
|
94
109
|
} );
|
|
95
110
|
},
|
|
96
|
-
redo: (
|
|
97
|
-
_: { moves: MoveElementParams[] },
|
|
98
|
-
{ movedElements }: MovedElementsResult
|
|
99
|
-
): MovedElementsResult => {
|
|
111
|
+
redo: ( _: { moves: MoveInput[] }, { movedElements }: MovedElementsResult ): MovedElementsResult => {
|
|
100
112
|
const newMovedElements: MovedElement[] = [];
|
|
101
113
|
onMoveElements?.();
|
|
102
114
|
|
|
103
|
-
movedElements.forEach( ( {
|
|
104
|
-
const
|
|
105
|
-
|
|
106
|
-
|
|
115
|
+
movedElements.forEach( ( { element, originalContainer, originalIndex, targetContainer, options } ) => {
|
|
116
|
+
const freshElement = element.lookup?.();
|
|
117
|
+
const freshOriginalContainer = originalContainer.lookup?.();
|
|
118
|
+
const freshTarget = targetContainer.lookup?.();
|
|
119
|
+
|
|
120
|
+
if ( ! freshElement || ! freshOriginalContainer || ! freshTarget ) {
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const newElement = moveElement( {
|
|
125
|
+
element: freshElement,
|
|
126
|
+
targetContainer: freshTarget,
|
|
127
|
+
options: { ...options, useHistory: false },
|
|
107
128
|
} );
|
|
108
129
|
|
|
109
130
|
newMovedElements.push( {
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
131
|
+
element: newElement,
|
|
132
|
+
originalContainer: freshOriginalContainer,
|
|
133
|
+
originalIndex,
|
|
134
|
+
targetContainer: freshTarget,
|
|
135
|
+
options,
|
|
114
136
|
} );
|
|
115
137
|
} );
|
|
116
138
|
|
|
@@ -6,7 +6,7 @@ import { deleteElement } from './delete-element';
|
|
|
6
6
|
import { getContainer } from './get-container';
|
|
7
7
|
import { type V1Element, type V1ElementModelProps } from './types';
|
|
8
8
|
|
|
9
|
-
type
|
|
9
|
+
type RemoveElementsParams = {
|
|
10
10
|
elementIds: string[];
|
|
11
11
|
title: string;
|
|
12
12
|
subtitle?: string;
|
|
@@ -15,26 +15,23 @@ type RemoveNestedElementsParams = {
|
|
|
15
15
|
};
|
|
16
16
|
|
|
17
17
|
type RemovedElement = {
|
|
18
|
-
|
|
18
|
+
container: V1Element;
|
|
19
|
+
parent: V1Element;
|
|
19
20
|
model: V1ElementModelProps;
|
|
20
|
-
parent: V1Element | null;
|
|
21
21
|
at: number;
|
|
22
22
|
};
|
|
23
23
|
|
|
24
24
|
type RemovedElementsResult = {
|
|
25
|
-
elementIds: string[];
|
|
26
25
|
removedElements: RemovedElement[];
|
|
27
26
|
};
|
|
28
27
|
|
|
29
|
-
export type { RemoveNestedElementsParams, RemovedElement, RemovedElementsResult };
|
|
30
|
-
|
|
31
28
|
export const removeElements = ( {
|
|
32
29
|
elementIds,
|
|
33
30
|
title,
|
|
34
31
|
subtitle = __( 'Item removed', 'elementor' ),
|
|
35
32
|
onRemoveElements,
|
|
36
33
|
onRestoreElements,
|
|
37
|
-
}:
|
|
34
|
+
}: RemoveElementsParams ): RemovedElementsResult => {
|
|
38
35
|
const undoableRemove = undoable(
|
|
39
36
|
{
|
|
40
37
|
do: ( { elementIds: elementIdsParam }: { elementIds: string[] } ): RemovedElementsResult => {
|
|
@@ -43,41 +40,36 @@ export const removeElements = ( {
|
|
|
43
40
|
elementIdsParam.forEach( ( elementId ) => {
|
|
44
41
|
const container = getContainer( elementId );
|
|
45
42
|
|
|
46
|
-
if ( container ) {
|
|
47
|
-
const model = container.model.toJSON();
|
|
48
|
-
const parent = container.parent;
|
|
49
|
-
|
|
50
|
-
const at = container.view?._index ?? 0;
|
|
51
|
-
|
|
43
|
+
if ( container?.parent ) {
|
|
52
44
|
removedElements.push( {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
at,
|
|
45
|
+
container,
|
|
46
|
+
parent: container.parent,
|
|
47
|
+
model: container.model.toJSON(),
|
|
48
|
+
at: container.view?._index ?? 0,
|
|
57
49
|
} );
|
|
58
50
|
}
|
|
59
51
|
} );
|
|
60
52
|
|
|
61
|
-
// Call onRemoveElements before deleting elements to avoid conflicts between commands
|
|
62
53
|
onRemoveElements?.();
|
|
63
54
|
|
|
64
|
-
|
|
55
|
+
removedElements.forEach( ( { container } ) => {
|
|
65
56
|
deleteElement( {
|
|
66
|
-
|
|
57
|
+
container,
|
|
67
58
|
options: { useHistory: false },
|
|
68
59
|
} );
|
|
69
60
|
} );
|
|
70
61
|
|
|
71
|
-
return {
|
|
62
|
+
return { removedElements };
|
|
72
63
|
},
|
|
73
64
|
undo: ( _: { elementIds: string[] }, { removedElements }: RemovedElementsResult ) => {
|
|
74
65
|
onRestoreElements?.();
|
|
75
66
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
67
|
+
[ ...removedElements ].reverse().forEach( ( { parent, model, at } ) => {
|
|
68
|
+
const freshParent = parent.lookup?.();
|
|
69
|
+
|
|
70
|
+
if ( freshParent ) {
|
|
79
71
|
createElement( {
|
|
80
|
-
|
|
72
|
+
container: freshParent,
|
|
81
73
|
model,
|
|
82
74
|
options: { useHistory: false, at },
|
|
83
75
|
} );
|
|
@@ -86,18 +78,34 @@ export const removeElements = ( {
|
|
|
86
78
|
},
|
|
87
79
|
redo: (
|
|
88
80
|
_: { elementIds: string[] },
|
|
89
|
-
{
|
|
81
|
+
{ removedElements }: RemovedElementsResult
|
|
90
82
|
): RemovedElementsResult => {
|
|
91
83
|
onRemoveElements?.();
|
|
92
84
|
|
|
93
|
-
|
|
85
|
+
const newRemovedElements: RemovedElement[] = [];
|
|
86
|
+
|
|
87
|
+
removedElements.forEach( ( { container, parent, model, at } ) => {
|
|
88
|
+
const freshContainer = container.lookup?.();
|
|
89
|
+
const freshParent = parent.lookup?.();
|
|
90
|
+
|
|
91
|
+
if ( ! freshContainer || ! freshParent ) {
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
|
|
94
95
|
deleteElement( {
|
|
95
|
-
|
|
96
|
+
container: freshContainer,
|
|
96
97
|
options: { useHistory: false },
|
|
97
98
|
} );
|
|
99
|
+
|
|
100
|
+
newRemovedElements.push( {
|
|
101
|
+
container: freshContainer,
|
|
102
|
+
parent: freshParent,
|
|
103
|
+
model,
|
|
104
|
+
at,
|
|
105
|
+
} );
|
|
98
106
|
} );
|
|
99
107
|
|
|
100
|
-
return {
|
|
108
|
+
return { removedElements: newRemovedElements };
|
|
101
109
|
},
|
|
102
110
|
},
|
|
103
111
|
{
|
|
@@ -2,10 +2,10 @@ import { ElementIndexNotFoundError, ElementNotFoundError, ElementParentNotFoundE
|
|
|
2
2
|
import { createElement } from './create-element';
|
|
3
3
|
import { deleteElement } from './delete-element';
|
|
4
4
|
import { getContainer } from './get-container';
|
|
5
|
-
import { type V1ElementData, type V1ElementModelProps } from './types';
|
|
5
|
+
import { type V1Element, type V1ElementData, type V1ElementModelProps } from './types';
|
|
6
6
|
|
|
7
7
|
type ElementLocation = {
|
|
8
|
-
|
|
8
|
+
container: V1Element;
|
|
9
9
|
index: number;
|
|
10
10
|
};
|
|
11
11
|
|
|
@@ -16,59 +16,58 @@ type ReplaceElementArgs = {
|
|
|
16
16
|
};
|
|
17
17
|
|
|
18
18
|
export const replaceElement = async ( { currentElement, newElement, withHistory = true }: ReplaceElementArgs ) => {
|
|
19
|
-
const
|
|
19
|
+
const currentElementContainer = getContainer( currentElement.id );
|
|
20
|
+
|
|
21
|
+
if ( ! currentElementContainer ) {
|
|
22
|
+
throw new ElementNotFoundError( { context: { elementId: currentElement.id } } );
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const { container, index } = getNewElementContainer( currentElementContainer, newElement );
|
|
20
26
|
|
|
21
27
|
const newElementInstance = createElement( {
|
|
22
|
-
|
|
28
|
+
container,
|
|
23
29
|
model: newElement,
|
|
24
30
|
options: { at: index, useHistory: withHistory },
|
|
25
31
|
} );
|
|
26
32
|
|
|
27
|
-
await deleteElement( {
|
|
33
|
+
await deleteElement( { container: currentElementContainer, options: { useHistory: withHistory } } );
|
|
28
34
|
|
|
29
35
|
return newElementInstance;
|
|
30
36
|
};
|
|
31
37
|
|
|
32
38
|
function getNewElementContainer(
|
|
33
|
-
|
|
39
|
+
currentElementContainer: V1Element,
|
|
34
40
|
newElement: Omit< V1ElementModelProps, 'id' >
|
|
35
41
|
): ElementLocation {
|
|
36
|
-
const currentElementContainer = getContainer( currentElement.id );
|
|
37
|
-
|
|
38
|
-
if ( ! currentElementContainer ) {
|
|
39
|
-
throw new ElementNotFoundError( { context: { elementId: currentElement.id } } );
|
|
40
|
-
}
|
|
41
|
-
|
|
42
42
|
const { parent } = currentElementContainer;
|
|
43
43
|
|
|
44
44
|
if ( ! parent ) {
|
|
45
|
-
throw new ElementParentNotFoundError( { context: { elementId:
|
|
45
|
+
throw new ElementParentNotFoundError( { context: { elementId: currentElementContainer.id } } );
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
const elementIndex = currentElementContainer.view?._index ?? 0;
|
|
49
49
|
|
|
50
50
|
if ( elementIndex === -1 ) {
|
|
51
|
-
throw new ElementIndexNotFoundError( { context: { elementId:
|
|
51
|
+
throw new ElementIndexNotFoundError( { context: { elementId: currentElementContainer.id } } );
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
-
let
|
|
54
|
+
let location: ElementLocation = { container: parent, index: elementIndex };
|
|
55
55
|
|
|
56
|
-
// If the element is at document top level and is a widget, wrap it with an empty container
|
|
57
56
|
if ( parent.id === 'document' && newElement.elType === 'widget' ) {
|
|
58
|
-
|
|
57
|
+
location = createWrapperForWidget( parent, elementIndex );
|
|
59
58
|
}
|
|
60
59
|
|
|
61
|
-
return
|
|
60
|
+
return location;
|
|
62
61
|
}
|
|
63
62
|
|
|
64
63
|
const DEFAULT_CONTAINER_TYPE = 'e-flexbox';
|
|
65
64
|
|
|
66
|
-
function createWrapperForWidget(
|
|
65
|
+
function createWrapperForWidget( parent: V1Element, elementIndex: number ): ElementLocation {
|
|
67
66
|
const container = createElement( {
|
|
68
|
-
|
|
67
|
+
container: parent,
|
|
69
68
|
model: { elType: DEFAULT_CONTAINER_TYPE },
|
|
70
69
|
options: { at: elementIndex, useHistory: false },
|
|
71
70
|
} );
|
|
72
71
|
|
|
73
|
-
return {
|
|
72
|
+
return { container, index: 0 };
|
|
74
73
|
}
|