@elementor/editor-canvas 0.12.0 → 0.13.0
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/.turbo/turbo-build.log +10 -10
- package/CHANGELOG.md +32 -0
- package/dist/index.d.mts +6 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.js +393 -45
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +406 -46
- package/dist/index.mjs.map +1 -1
- package/package.json +11 -10
- package/src/__tests__/__mocks__/styles-schema.ts +10 -1
- package/src/__tests__/init-styles-renderer.test.ts +19 -5
- package/src/__tests__/mock-attachment-data.ts +15 -0
- package/src/__tests__/prop-types.ts +65 -0
- package/src/__tests__/settings-props-resolver.test.ts +193 -0
- package/src/__tests__/styles-prop-resolver.test.ts +8 -16
- package/src/index.ts +1 -0
- package/src/init-settings-transformers.ts +19 -0
- package/src/init-style-transformers.ts +8 -9
- package/src/init-styles-renderer.ts +9 -3
- package/src/init.tsx +8 -0
- package/src/legacy/create-element-type.ts +84 -0
- package/src/legacy/init-legacy-views.ts +22 -0
- package/src/legacy/types.ts +60 -0
- package/src/settings-transformers-registry.ts +3 -0
- package/src/style-commands/__tests__/paste-style.test.ts +554 -0
- package/src/style-commands/__tests__/reset-style.test.ts +153 -0
- package/src/style-commands/init-style-commands.ts +7 -0
- package/src/style-commands/paste-style.ts +53 -0
- package/src/style-commands/reset-style.ts +34 -0
- package/src/style-commands/undoable-actions/paste-element-style.ts +107 -0
- package/src/style-commands/undoable-actions/reset-element-style.ts +60 -0
- package/src/style-commands/utils.ts +62 -0
- package/src/transformers/settings/array-transformer.ts +5 -0
- package/src/transformers/settings/link-transformer.ts +14 -0
- package/src/transformers/{styles → shared}/image-src-transformer.ts +2 -2
- package/src/transformers/shared/image-transformer.ts +41 -0
- package/src/transformers/shared/plain-transformer.ts +5 -0
- package/src/transformers/styles/background-color-overlay-transformer.ts +13 -3
- package/src/transformers/styles/background-image-overlay-transformer.ts +6 -2
- package/src/transformers/styles/image-attachment-transformer.ts +0 -15
- package/src/transformers/styles/image-transformer.ts +0 -34
- package/src/transformers/styles/primitive-transformer.ts +0 -3
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import {
|
|
2
|
+
booleanPropTypeUtil,
|
|
3
|
+
classesPropTypeUtil,
|
|
4
|
+
imageAttachmentIdPropType,
|
|
5
|
+
imagePropTypeUtil,
|
|
6
|
+
imageSrcPropTypeUtil,
|
|
7
|
+
linkPropTypeUtil,
|
|
8
|
+
numberPropTypeUtil,
|
|
9
|
+
type Props,
|
|
10
|
+
type PropsSchema,
|
|
11
|
+
stringPropTypeUtil,
|
|
12
|
+
urlPropTypeUtil,
|
|
13
|
+
} from '@elementor/editor-props';
|
|
14
|
+
import { getMediaAttachment } from '@elementor/wp-media';
|
|
15
|
+
|
|
16
|
+
import { initSettingsTransformers } from '../init-settings-transformers';
|
|
17
|
+
import { createPropsResolver } from '../renderers/create-props-resolver';
|
|
18
|
+
import { settingsTransformersRegistry } from '../settings-transformers-registry';
|
|
19
|
+
import { mockAttachmentData } from './mock-attachment-data';
|
|
20
|
+
import {
|
|
21
|
+
booleanPropType,
|
|
22
|
+
classesPropType,
|
|
23
|
+
imagePropType,
|
|
24
|
+
linkPropType,
|
|
25
|
+
numberPropType,
|
|
26
|
+
stringPropType,
|
|
27
|
+
urlPropType,
|
|
28
|
+
} from './prop-types';
|
|
29
|
+
|
|
30
|
+
jest.mock( '@elementor/wp-media' );
|
|
31
|
+
|
|
32
|
+
type Payload = {
|
|
33
|
+
name: string;
|
|
34
|
+
prepare?: () => void;
|
|
35
|
+
props: Props;
|
|
36
|
+
schema: PropsSchema;
|
|
37
|
+
expected: Record< string, unknown >;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
describe( 'settings props resolver', () => {
|
|
41
|
+
it.each< Payload >( [
|
|
42
|
+
{
|
|
43
|
+
name: 'plain props',
|
|
44
|
+
props: {
|
|
45
|
+
string: stringPropTypeUtil.create( 'test' ),
|
|
46
|
+
url: urlPropTypeUtil.create( 'url' ),
|
|
47
|
+
number: numberPropTypeUtil.create( 123 ),
|
|
48
|
+
boolean: booleanPropTypeUtil.create( true ),
|
|
49
|
+
},
|
|
50
|
+
schema: {
|
|
51
|
+
string: stringPropType(),
|
|
52
|
+
number: numberPropType(),
|
|
53
|
+
boolean: booleanPropType(),
|
|
54
|
+
url: urlPropType(),
|
|
55
|
+
},
|
|
56
|
+
expected: {
|
|
57
|
+
string: 'test',
|
|
58
|
+
url: 'url',
|
|
59
|
+
number: 123,
|
|
60
|
+
boolean: true,
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
name: 'classes',
|
|
65
|
+
props: {
|
|
66
|
+
classes: classesPropTypeUtil.create( [
|
|
67
|
+
'test-1',
|
|
68
|
+
'test-2',
|
|
69
|
+
'',
|
|
70
|
+
null as unknown as string,
|
|
71
|
+
undefined as unknown as string,
|
|
72
|
+
] ),
|
|
73
|
+
},
|
|
74
|
+
schema: {
|
|
75
|
+
classes: classesPropType(),
|
|
76
|
+
},
|
|
77
|
+
expected: {
|
|
78
|
+
classes: [ 'test-1', 'test-2' ],
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
name: 'link',
|
|
83
|
+
props: {
|
|
84
|
+
link1: linkPropTypeUtil.create( {
|
|
85
|
+
destination: 'https://elementor.com/blank',
|
|
86
|
+
isTargetBlank: true,
|
|
87
|
+
} ),
|
|
88
|
+
link2: linkPropTypeUtil.create( {
|
|
89
|
+
destination: 'https://elementor.com/self',
|
|
90
|
+
isTargetBlank: false,
|
|
91
|
+
} ),
|
|
92
|
+
},
|
|
93
|
+
schema: {
|
|
94
|
+
link1: linkPropType(),
|
|
95
|
+
link2: linkPropType(),
|
|
96
|
+
},
|
|
97
|
+
expected: {
|
|
98
|
+
link1: { href: 'https://elementor.com/blank', target: '_blank' },
|
|
99
|
+
link2: { href: 'https://elementor.com/self', target: '_self' },
|
|
100
|
+
},
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
name: 'image (url)',
|
|
104
|
+
props: {
|
|
105
|
+
image: imagePropTypeUtil.create( {
|
|
106
|
+
src: imageSrcPropTypeUtil.create( {
|
|
107
|
+
id: null,
|
|
108
|
+
url: urlPropTypeUtil.create( 'https://localhost.test/test-image.png' ),
|
|
109
|
+
} ),
|
|
110
|
+
size: stringPropTypeUtil.create( 'full' ),
|
|
111
|
+
} ),
|
|
112
|
+
},
|
|
113
|
+
schema: {
|
|
114
|
+
image: imagePropType(),
|
|
115
|
+
},
|
|
116
|
+
expected: {
|
|
117
|
+
image: {
|
|
118
|
+
src: 'https://localhost.test/test-image.png',
|
|
119
|
+
},
|
|
120
|
+
},
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
name: 'image (attachment with size)',
|
|
124
|
+
prepare: () => {
|
|
125
|
+
jest.mocked( getMediaAttachment ).mockImplementation(
|
|
126
|
+
( args ) => Promise.resolve( mockAttachmentData( args.id ) ) as never
|
|
127
|
+
);
|
|
128
|
+
},
|
|
129
|
+
props: {
|
|
130
|
+
image: imagePropTypeUtil.create( {
|
|
131
|
+
src: imageSrcPropTypeUtil.create( {
|
|
132
|
+
id: imageAttachmentIdPropType.create( 123 ),
|
|
133
|
+
url: null,
|
|
134
|
+
} ),
|
|
135
|
+
size: stringPropTypeUtil.create( 'large' ),
|
|
136
|
+
} ),
|
|
137
|
+
},
|
|
138
|
+
schema: {
|
|
139
|
+
image: imagePropType(),
|
|
140
|
+
},
|
|
141
|
+
expected: {
|
|
142
|
+
image: {
|
|
143
|
+
src: 'large-image-url-123',
|
|
144
|
+
height: 3,
|
|
145
|
+
width: 3,
|
|
146
|
+
},
|
|
147
|
+
},
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
name: 'image (attachment with non existing size)',
|
|
151
|
+
prepare: () => {
|
|
152
|
+
jest.mocked( getMediaAttachment ).mockImplementation(
|
|
153
|
+
( args ) => Promise.resolve( mockAttachmentData( args.id ) ) as never
|
|
154
|
+
);
|
|
155
|
+
},
|
|
156
|
+
props: {
|
|
157
|
+
image: imagePropTypeUtil.create( {
|
|
158
|
+
src: imageSrcPropTypeUtil.create( {
|
|
159
|
+
id: imageAttachmentIdPropType.create( 123 ),
|
|
160
|
+
url: null,
|
|
161
|
+
} ),
|
|
162
|
+
size: stringPropTypeUtil.create( 'non-existing-size' ),
|
|
163
|
+
} ),
|
|
164
|
+
},
|
|
165
|
+
schema: {
|
|
166
|
+
image: imagePropType(),
|
|
167
|
+
},
|
|
168
|
+
expected: {
|
|
169
|
+
image: {
|
|
170
|
+
src: 'original-image-url-123',
|
|
171
|
+
height: 0,
|
|
172
|
+
width: 0,
|
|
173
|
+
},
|
|
174
|
+
},
|
|
175
|
+
},
|
|
176
|
+
] )( 'it should resolve props for `$name`', async ( { prepare, props, expected, schema } ) => {
|
|
177
|
+
// Arrange.
|
|
178
|
+
prepare?.();
|
|
179
|
+
|
|
180
|
+
initSettingsTransformers();
|
|
181
|
+
|
|
182
|
+
const resolve = createPropsResolver( {
|
|
183
|
+
transformers: settingsTransformersRegistry.all(),
|
|
184
|
+
schema,
|
|
185
|
+
} );
|
|
186
|
+
|
|
187
|
+
// Act.
|
|
188
|
+
const result = await resolve( { props } );
|
|
189
|
+
|
|
190
|
+
// Assert.
|
|
191
|
+
expect( result ).toStrictEqual( expected );
|
|
192
|
+
} );
|
|
193
|
+
} );
|
|
@@ -30,8 +30,10 @@ import { getMediaAttachment } from '@elementor/wp-media';
|
|
|
30
30
|
import { initStyleTransformers } from '../init-style-transformers';
|
|
31
31
|
import { createPropsResolver } from '../renderers/create-props-resolver';
|
|
32
32
|
import { stylesSchemaMock } from './__mocks__/styles-schema';
|
|
33
|
+
import { mockAttachmentData } from './mock-attachment-data';
|
|
33
34
|
|
|
34
35
|
jest.mock( '@elementor/wp-media' );
|
|
36
|
+
jest.mock( '../style-commands/init-style-commands' );
|
|
35
37
|
|
|
36
38
|
type Payload = {
|
|
37
39
|
name: string;
|
|
@@ -200,8 +202,12 @@ describe( 'styles prop resolver', () => {
|
|
|
200
202
|
background: backgroundPropTypeUtil.create( {
|
|
201
203
|
color: colorPropTypeUtil.create( '#000' ),
|
|
202
204
|
'background-overlay': backgroundOverlayPropTypeUtil.create( [
|
|
203
|
-
backgroundColorOverlayPropTypeUtil.create(
|
|
204
|
-
|
|
205
|
+
backgroundColorOverlayPropTypeUtil.create( {
|
|
206
|
+
color: colorPropTypeUtil.create( 'blue' ),
|
|
207
|
+
} ),
|
|
208
|
+
backgroundColorOverlayPropTypeUtil.create( {
|
|
209
|
+
color: colorPropTypeUtil.create( 'yellow' ),
|
|
210
|
+
} ),
|
|
205
211
|
backgroundImageOverlayPropTypeUtil.create( {
|
|
206
212
|
image: imagePropTypeUtil.create( {
|
|
207
213
|
src: imageSrcPropTypeUtil.create( {
|
|
@@ -352,17 +358,3 @@ describe( 'styles prop resolver', () => {
|
|
|
352
358
|
expect( result ).toStrictEqual( expected );
|
|
353
359
|
} );
|
|
354
360
|
} );
|
|
355
|
-
|
|
356
|
-
const mockAttachmentData = ( id: number | null ) => {
|
|
357
|
-
const originalUrl = `original-image-url-${ id }`;
|
|
358
|
-
|
|
359
|
-
return {
|
|
360
|
-
url: originalUrl,
|
|
361
|
-
sizes: {
|
|
362
|
-
thumbnail: { url: `thumbnail-image-url-${ id }` },
|
|
363
|
-
medium_large: { url: `medium_large-image-url-${ id }` },
|
|
364
|
-
large: { url: `large-image-url-${ id }` },
|
|
365
|
-
full: { url: originalUrl },
|
|
366
|
-
},
|
|
367
|
-
};
|
|
368
|
-
};
|
package/src/index.ts
CHANGED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { settingsTransformersRegistry } from './settings-transformers-registry';
|
|
2
|
+
import { arrayTransformer } from './transformers/settings/array-transformer';
|
|
3
|
+
import { linkTransformer } from './transformers/settings/link-transformer';
|
|
4
|
+
import { imageSrcTransformer } from './transformers/shared/image-src-transformer';
|
|
5
|
+
import { imageTransformer } from './transformers/shared/image-transformer';
|
|
6
|
+
import { plainTransformer } from './transformers/shared/plain-transformer';
|
|
7
|
+
|
|
8
|
+
export function initSettingsTransformers() {
|
|
9
|
+
settingsTransformersRegistry
|
|
10
|
+
.register( 'string', plainTransformer )
|
|
11
|
+
.register( 'url', plainTransformer )
|
|
12
|
+
.register( 'number', plainTransformer )
|
|
13
|
+
.register( 'boolean', plainTransformer )
|
|
14
|
+
.register( 'classes', arrayTransformer )
|
|
15
|
+
.register( 'link', linkTransformer )
|
|
16
|
+
.register( 'image', imageTransformer )
|
|
17
|
+
.register( 'image-src', imageSrcTransformer )
|
|
18
|
+
.register( 'image-attachment-id', plainTransformer );
|
|
19
|
+
}
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import { styleTransformersRegistry } from './style-transformers-registry';
|
|
2
|
+
import { imageSrcTransformer } from './transformers/shared/image-src-transformer';
|
|
3
|
+
import { imageTransformer } from './transformers/shared/image-transformer';
|
|
4
|
+
import { plainTransformer } from './transformers/shared/plain-transformer';
|
|
2
5
|
import { backgroundColorOverlayTransformer } from './transformers/styles/background-color-overlay-transformer';
|
|
3
6
|
import { backgroundGradientOverlayTransformer } from './transformers/styles/background-gradient-overlay-transformer';
|
|
4
7
|
import { backgroundImageOverlayTransformer } from './transformers/styles/background-image-overlay-transformer';
|
|
@@ -8,10 +11,6 @@ import { backgroundTransformer } from './transformers/styles/background-transfor
|
|
|
8
11
|
import { colorStopTransformer } from './transformers/styles/color-stop-transformer';
|
|
9
12
|
import { createCombineArrayTransformer } from './transformers/styles/create-combine-array-transformer';
|
|
10
13
|
import { createMultiPropsTransformer } from './transformers/styles/create-multi-props-transformer';
|
|
11
|
-
import { imageAttachmentTransformer } from './transformers/styles/image-attachment-transformer';
|
|
12
|
-
import { imageSrcTransformer } from './transformers/styles/image-src-transformer';
|
|
13
|
-
import { imageTransformer } from './transformers/styles/image-transformer';
|
|
14
|
-
import { primitiveTransformer } from './transformers/styles/primitive-transformer';
|
|
15
14
|
import { shadowTransformer } from './transformers/styles/shadow-transformer';
|
|
16
15
|
import { sizeTransformer } from './transformers/styles/size-transformer';
|
|
17
16
|
import { strokeTransformer } from './transformers/styles/stroke-transformer';
|
|
@@ -28,10 +27,10 @@ export function initStyleTransformers() {
|
|
|
28
27
|
( { propKey, key } ) => `${ propKey }-${ key }`
|
|
29
28
|
)
|
|
30
29
|
)
|
|
31
|
-
.register( 'color',
|
|
32
|
-
.register( 'number',
|
|
33
|
-
.register( 'string',
|
|
34
|
-
.register( 'url',
|
|
30
|
+
.register( 'color', plainTransformer )
|
|
31
|
+
.register( 'number', plainTransformer )
|
|
32
|
+
.register( 'string', plainTransformer )
|
|
33
|
+
.register( 'url', plainTransformer )
|
|
35
34
|
.register( 'box-shadow', createCombineArrayTransformer( ',' ) )
|
|
36
35
|
.register( 'background', backgroundTransformer )
|
|
37
36
|
.register( 'background-overlay', createCombineArrayTransformer( ',' ) )
|
|
@@ -42,7 +41,7 @@ export function initStyleTransformers() {
|
|
|
42
41
|
.register( 'color-stop', colorStopTransformer )
|
|
43
42
|
.register( 'background-image-position-offset', backgroundImagePositionOffsetTransformer )
|
|
44
43
|
.register( 'background-image-size-scale', backgroundImageSizeScaleTransformer )
|
|
45
|
-
.register( 'image-attachment-id',
|
|
44
|
+
.register( 'image-attachment-id', plainTransformer )
|
|
46
45
|
.register( 'image-src', imageSrcTransformer )
|
|
47
46
|
.register( 'image', imageTransformer )
|
|
48
47
|
.register(
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { getBreakpointsMap } from '@elementor/editor-responsive';
|
|
2
2
|
import { getStylesSchema } from '@elementor/editor-styles';
|
|
3
3
|
import { stylesRepository } from '@elementor/editor-styles-repository';
|
|
4
|
-
import { __privateListenTo as listenTo, v1ReadyEvent } from '@elementor/editor-v1-adapters';
|
|
4
|
+
import { __privateListenTo as listenTo, registerDataHook, v1ReadyEvent } from '@elementor/editor-v1-adapters';
|
|
5
5
|
|
|
6
6
|
import { createPropsResolver } from './renderers/create-props-resolver';
|
|
7
7
|
import renderStyles from './renderers/render-styles';
|
|
@@ -22,7 +22,7 @@ export function initStylesRenderer() {
|
|
|
22
22
|
onPropResolve: enqueueUsedFonts,
|
|
23
23
|
} );
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
const injectStyleElements = async () => {
|
|
26
26
|
const styleContainer = getStylesContainer();
|
|
27
27
|
|
|
28
28
|
// Styles should be printed in a reversed order, so the high priority styles will be printed last.
|
|
@@ -42,7 +42,13 @@ export function initStylesRenderer() {
|
|
|
42
42
|
selectorPrefix: SELECTOR_PREFIX,
|
|
43
43
|
signal: abortController.signal,
|
|
44
44
|
} );
|
|
45
|
-
}
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
stylesRepository.subscribe( injectStyleElements );
|
|
48
|
+
|
|
49
|
+
// Add initial styles rendering as a hook to ensure the whole editor
|
|
50
|
+
// waits for styles to render before hiding the loaders.
|
|
51
|
+
registerDataHook( 'after', 'editor/documents/attach-preview', injectStyleElements );
|
|
46
52
|
} );
|
|
47
53
|
}
|
|
48
54
|
|
package/src/init.tsx
CHANGED
|
@@ -1,12 +1,20 @@
|
|
|
1
1
|
import { injectIntoTop } from '@elementor/editor';
|
|
2
2
|
|
|
3
3
|
import { ElementsOverlays } from './components/elements-overlays';
|
|
4
|
+
import { initSettingsTransformers } from './init-settings-transformers';
|
|
4
5
|
import { initStyleTransformers } from './init-style-transformers';
|
|
5
6
|
import { initStylesRenderer } from './init-styles-renderer';
|
|
7
|
+
import { initLegacyViews } from './legacy/init-legacy-views';
|
|
8
|
+
import { initStyleCommands } from './style-commands/init-style-commands';
|
|
6
9
|
|
|
7
10
|
export function init() {
|
|
8
11
|
initStyleTransformers();
|
|
9
12
|
initStylesRenderer();
|
|
13
|
+
initStyleCommands();
|
|
14
|
+
|
|
15
|
+
initLegacyViews();
|
|
16
|
+
|
|
17
|
+
initSettingsTransformers();
|
|
10
18
|
|
|
11
19
|
injectIntoTop( {
|
|
12
20
|
id: 'elements-overlays',
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { type ElementType, type ElementView, type LegacyWindow } from './types';
|
|
2
|
+
|
|
3
|
+
// Technically it shouldn't have a return type annotation, but for some
|
|
4
|
+
// reason TypeScript can't infer the types properly when emitting DTS.
|
|
5
|
+
//
|
|
6
|
+
// See: https://github.com/microsoft/TypeScript/issues/9944#issuecomment-244448079
|
|
7
|
+
export function createElementType( type: string ): typeof ElementType {
|
|
8
|
+
const legacyWindow = window as unknown as LegacyWindow;
|
|
9
|
+
|
|
10
|
+
return class extends legacyWindow.elementor.modules.elements.types.Widget {
|
|
11
|
+
getType() {
|
|
12
|
+
return type;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
getView() {
|
|
16
|
+
return createElementView();
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function createElementView(): typeof ElementView {
|
|
22
|
+
const legacyWindow = window as unknown as LegacyWindow;
|
|
23
|
+
|
|
24
|
+
return class extends legacyWindow.elementor.modules.elements.views.Widget {
|
|
25
|
+
// Dispatch `render` event so the overlay layer will be updated
|
|
26
|
+
onRender( ...args: unknown[] ) {
|
|
27
|
+
super.onRender( ...args );
|
|
28
|
+
|
|
29
|
+
this.#dispatchEvent( 'elementor/preview/atomic-widget/render' );
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Dispatch `destroy` event so the overlay layer will be updated
|
|
33
|
+
onDestroy( ...args: unknown[] ) {
|
|
34
|
+
super.onDestroy( ...args );
|
|
35
|
+
|
|
36
|
+
this.#dispatchEvent( 'elementor/preview/atomic-widget/destroy' );
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
attributes() {
|
|
40
|
+
return {
|
|
41
|
+
...super.attributes(),
|
|
42
|
+
|
|
43
|
+
// Mark the widget as atomic, so external APIs (such as the overlay layer) can reference it.
|
|
44
|
+
'data-atomic': '',
|
|
45
|
+
|
|
46
|
+
// Make the wrapper is non-existent in terms of CSS to mimic the frontend DOM tree.
|
|
47
|
+
style: 'display: contents !important;',
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Removes behaviors that are not needed for atomic widgets (that are implemented in the overlay layer).
|
|
52
|
+
behaviors() {
|
|
53
|
+
const disabledBehaviors = [ 'InlineEditing', 'Draggable', 'Resizable' ];
|
|
54
|
+
|
|
55
|
+
const behaviorsAsEntries = Object.entries( super.behaviors() ).filter(
|
|
56
|
+
( [ key ] ) => ! disabledBehaviors.includes( key )
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
return Object.fromEntries( behaviorsAsEntries );
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Change the drag handle because the $el is not the draggable element (`display: contents`).
|
|
63
|
+
getDomElement() {
|
|
64
|
+
return this.$el.find( ':first-child' );
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Remove the overlay, so we can use the new overlay layer.
|
|
68
|
+
getHandlesOverlay() {
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
#dispatchEvent( eventType: string ) {
|
|
73
|
+
window.top?.dispatchEvent(
|
|
74
|
+
new CustomEvent( eventType, {
|
|
75
|
+
detail: { id: this.model.get( 'id' ) },
|
|
76
|
+
} )
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
getContextMenuGroups() {
|
|
81
|
+
return super.getContextMenuGroups().filter( ( group ) => group.name !== 'save' );
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { getWidgetsCache } from '@elementor/editor-elements';
|
|
2
|
+
import { __privateListenTo, v1ReadyEvent } from '@elementor/editor-v1-adapters';
|
|
3
|
+
|
|
4
|
+
import { createElementType } from './create-element-type';
|
|
5
|
+
import type { LegacyWindow } from './types';
|
|
6
|
+
|
|
7
|
+
export function initLegacyViews() {
|
|
8
|
+
__privateListenTo( v1ReadyEvent(), () => {
|
|
9
|
+
const config = getWidgetsCache() ?? {};
|
|
10
|
+
const legacyWindow = window as unknown as LegacyWindow;
|
|
11
|
+
|
|
12
|
+
Object.entries( config ).forEach( ( [ type, element ] ) => {
|
|
13
|
+
if ( ! element.atomic ) {
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const ElementType = createElementType( type );
|
|
18
|
+
|
|
19
|
+
legacyWindow.elementor.elementsManager.registerElementType( new ElementType() );
|
|
20
|
+
} );
|
|
21
|
+
} );
|
|
22
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
export type LegacyWindow = Window & {
|
|
2
|
+
elementor: {
|
|
3
|
+
modules: {
|
|
4
|
+
elements: {
|
|
5
|
+
types: {
|
|
6
|
+
Widget: typeof ElementType;
|
|
7
|
+
};
|
|
8
|
+
views: {
|
|
9
|
+
Widget: typeof ElementView;
|
|
10
|
+
};
|
|
11
|
+
};
|
|
12
|
+
};
|
|
13
|
+
elementsManager: {
|
|
14
|
+
registerElementType: ( type: ElementType ) => void;
|
|
15
|
+
};
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export declare class ElementType {
|
|
20
|
+
getType(): string;
|
|
21
|
+
|
|
22
|
+
getView(): typeof ElementView;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export declare class ElementView {
|
|
26
|
+
$el: JQueryElement;
|
|
27
|
+
|
|
28
|
+
model: BackboneModel;
|
|
29
|
+
|
|
30
|
+
onRender( ...args: unknown[] ): void;
|
|
31
|
+
|
|
32
|
+
onDestroy( ...args: unknown[] ): void;
|
|
33
|
+
|
|
34
|
+
attributes(): Record< string, unknown >;
|
|
35
|
+
|
|
36
|
+
behaviors(): Record< string, unknown >;
|
|
37
|
+
|
|
38
|
+
getDomElement(): JQueryElement;
|
|
39
|
+
|
|
40
|
+
getHandlesOverlay(): JQueryElement | null;
|
|
41
|
+
|
|
42
|
+
getContextMenuGroups(): ContextMenuGroup[];
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
type JQueryElement = {
|
|
46
|
+
find: ( selector: string ) => JQueryElement;
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
type BackboneModel = {
|
|
50
|
+
get: < T extends keyof Model >( key: T ) => Model[ T ];
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
type Model = {
|
|
54
|
+
id: string;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
type ContextMenuGroup = {
|
|
58
|
+
name: string;
|
|
59
|
+
action: unknown[];
|
|
60
|
+
};
|