@elementor/editor-canvas 0.13.1 → 0.15.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 +33 -0
- package/dist/index.d.mts +9 -8
- package/dist/index.d.ts +9 -8
- package/dist/index.js +184 -31
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +192 -34
- package/dist/index.mjs.map +1 -1
- package/package.json +9 -8
- package/src/__tests__/__mocks__/styles-schema.ts +3 -3
- package/src/__tests__/settings-props-resolver.test.ts +1 -1
- package/src/__tests__/styles-prop-resolver.test.ts +7 -7
- package/src/components/__tests__/elements-overlays.test.tsx +40 -35
- package/src/components/element-overlay.tsx +3 -2
- package/src/components/elements-overlays.tsx +26 -9
- package/src/hooks/use-floating-on-element.ts +9 -6
- package/src/init-settings-transformers.ts +1 -5
- package/src/init-style-transformers.ts +2 -6
- package/src/init-styles-renderer.ts +1 -1
- package/src/legacy/__tests__/signalized-process.test.ts +80 -0
- package/src/legacy/create-element-type.ts +2 -2
- package/src/legacy/create-templated-element-type.ts +131 -0
- package/src/legacy/init-legacy-views.ts +7 -1
- package/src/legacy/signalized-process.ts +35 -0
- package/src/legacy/types.ts +27 -3
- package/src/renderers/__tests__/create-dom-renderer.test.ts +66 -0
- package/src/renderers/__tests__/create-props-resolver.test.ts +123 -15
- package/src/renderers/create-dom-renderer.ts +56 -0
- package/src/renderers/create-props-resolver.ts +10 -8
- package/src/renderers/render-styles.ts +4 -0
- package/src/transformers/create-transformers-registry.ts +16 -5
- package/src/transformers/styles/background-image-position-offset-transformer.ts +1 -1
- package/src/transformers/styles/background-image-size-scale-transformer.ts +1 -1
- package/src/transformers/types.ts +1 -5
|
@@ -1,13 +1,19 @@
|
|
|
1
1
|
import { createMockPropType } from 'test-utils';
|
|
2
2
|
|
|
3
3
|
import { createTransformer } from '../../transformers/create-transformer';
|
|
4
|
+
import { createTransformersRegistry } from '../../transformers/create-transformers-registry';
|
|
4
5
|
import { createPropsResolver } from '../create-props-resolver';
|
|
5
6
|
|
|
6
7
|
describe( 'createPropsResolver', () => {
|
|
7
8
|
it( 'should resolve simple props', async () => {
|
|
8
9
|
// Arrange.
|
|
10
|
+
const transformers = createTransformersRegistry().register(
|
|
11
|
+
'int',
|
|
12
|
+
createTransformer( ( value: number ) => value + 1 )
|
|
13
|
+
);
|
|
14
|
+
|
|
9
15
|
const resolve = createPropsResolver( {
|
|
10
|
-
transformers
|
|
16
|
+
transformers,
|
|
11
17
|
schema: { int: createMockPropType( { kind: 'plain', key: 'int' } ) },
|
|
12
18
|
} );
|
|
13
19
|
|
|
@@ -24,8 +30,13 @@ describe( 'createPropsResolver', () => {
|
|
|
24
30
|
|
|
25
31
|
it( 'should skip disabled props', async () => {
|
|
26
32
|
// Arrange.
|
|
33
|
+
const transformers = createTransformersRegistry().register(
|
|
34
|
+
'int',
|
|
35
|
+
createTransformer( ( value: number ) => value + 1 )
|
|
36
|
+
);
|
|
37
|
+
|
|
27
38
|
const resolve = createPropsResolver( {
|
|
28
|
-
transformers
|
|
39
|
+
transformers,
|
|
29
40
|
schema: { int: createMockPropType( { kind: 'plain', key: 'int' } ) },
|
|
30
41
|
} );
|
|
31
42
|
|
|
@@ -41,13 +52,18 @@ describe( 'createPropsResolver', () => {
|
|
|
41
52
|
} );
|
|
42
53
|
|
|
43
54
|
// Assert.
|
|
44
|
-
expect( result ).toEqual( {} );
|
|
55
|
+
expect( result ).toEqual( { int: null } );
|
|
45
56
|
} );
|
|
46
57
|
|
|
47
58
|
it( 'should fallback to default value when there is no value', async () => {
|
|
48
59
|
// Arrange.
|
|
60
|
+
const transformers = createTransformersRegistry().register(
|
|
61
|
+
'int',
|
|
62
|
+
createTransformer( ( value: number ) => value + 1 )
|
|
63
|
+
);
|
|
64
|
+
|
|
49
65
|
const resolve = createPropsResolver( {
|
|
50
|
-
transformers
|
|
66
|
+
transformers,
|
|
51
67
|
schema: {
|
|
52
68
|
int: createMockPropType( {
|
|
53
69
|
kind: 'plain',
|
|
@@ -66,8 +82,13 @@ describe( 'createPropsResolver', () => {
|
|
|
66
82
|
|
|
67
83
|
it( 'should skip props that are not in the schema', async () => {
|
|
68
84
|
// Arrange.
|
|
85
|
+
const transformers = createTransformersRegistry().register(
|
|
86
|
+
'int',
|
|
87
|
+
createTransformer( ( value: number ) => value + 1 )
|
|
88
|
+
);
|
|
89
|
+
|
|
69
90
|
const resolve = createPropsResolver( {
|
|
70
|
-
transformers
|
|
91
|
+
transformers,
|
|
71
92
|
schema: {
|
|
72
93
|
int: createMockPropType( { kind: 'plain', key: 'int' } ),
|
|
73
94
|
},
|
|
@@ -93,8 +114,13 @@ describe( 'createPropsResolver', () => {
|
|
|
93
114
|
|
|
94
115
|
it( "should skip props that don't have a transformer", async () => {
|
|
95
116
|
// Arrange.
|
|
117
|
+
const transformers = createTransformersRegistry().register(
|
|
118
|
+
'int',
|
|
119
|
+
createTransformer( ( value: number ) => value + 1 )
|
|
120
|
+
);
|
|
121
|
+
|
|
96
122
|
const resolve = createPropsResolver( {
|
|
97
|
-
transformers
|
|
123
|
+
transformers,
|
|
98
124
|
schema: {
|
|
99
125
|
int: createMockPropType( { kind: 'plain', key: 'int' } ),
|
|
100
126
|
invalid: createMockPropType( { kind: 'plain', key: 'invalid' } ),
|
|
@@ -116,17 +142,94 @@ describe( 'createPropsResolver', () => {
|
|
|
116
142
|
} );
|
|
117
143
|
|
|
118
144
|
// Assert.
|
|
119
|
-
expect( result ).toEqual( { int: 2 } );
|
|
145
|
+
expect( result ).toEqual( { int: 2, invalid: null } );
|
|
120
146
|
} );
|
|
121
147
|
|
|
122
|
-
it( 'should skip props
|
|
148
|
+
it( 'should not skip props if there is a fallback transformer', async () => {
|
|
149
|
+
// Arrange.
|
|
150
|
+
const transformers = createTransformersRegistry()
|
|
151
|
+
.register(
|
|
152
|
+
'int',
|
|
153
|
+
createTransformer( ( value: number ) => value + 1 )
|
|
154
|
+
)
|
|
155
|
+
.registerFallback( createTransformer( ( value: string ) => value + ' world' ) );
|
|
156
|
+
|
|
123
157
|
const resolve = createPropsResolver( {
|
|
124
|
-
transformers
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
158
|
+
transformers,
|
|
159
|
+
schema: {
|
|
160
|
+
int: createMockPropType( { kind: 'plain', key: 'int' } ),
|
|
161
|
+
greet: createMockPropType( { kind: 'plain', key: 'string' } ),
|
|
162
|
+
},
|
|
163
|
+
} );
|
|
164
|
+
|
|
165
|
+
// Act.
|
|
166
|
+
const result = await resolve( {
|
|
167
|
+
props: {
|
|
168
|
+
int: {
|
|
169
|
+
$$type: 'int',
|
|
170
|
+
value: 1,
|
|
171
|
+
},
|
|
172
|
+
greet: {
|
|
173
|
+
$$type: 'string',
|
|
174
|
+
value: 'hello',
|
|
175
|
+
},
|
|
176
|
+
},
|
|
177
|
+
} );
|
|
178
|
+
|
|
179
|
+
// Assert.
|
|
180
|
+
expect( result ).toEqual( { int: 2, greet: 'hello world' } );
|
|
181
|
+
} );
|
|
182
|
+
|
|
183
|
+
it( 'should return null if the prop is value is not match the prop type', async () => {
|
|
184
|
+
// Arrange.
|
|
185
|
+
const transformers = createTransformersRegistry()
|
|
186
|
+
.register(
|
|
187
|
+
'int',
|
|
188
|
+
createTransformer( ( value: number ) => value + 1 )
|
|
189
|
+
)
|
|
190
|
+
.registerFallback( createTransformer( ( value: string ) => value + ' world' ) );
|
|
191
|
+
|
|
192
|
+
const resolve = createPropsResolver( {
|
|
193
|
+
transformers,
|
|
194
|
+
schema: {
|
|
195
|
+
int: createMockPropType( { kind: 'plain', key: 'int' } ),
|
|
196
|
+
greet: createMockPropType( { kind: 'plain', key: 'string' } ),
|
|
129
197
|
},
|
|
198
|
+
} );
|
|
199
|
+
|
|
200
|
+
// Act.
|
|
201
|
+
const result = await resolve( {
|
|
202
|
+
props: {
|
|
203
|
+
int: {
|
|
204
|
+
$$type: 'int',
|
|
205
|
+
value: 1,
|
|
206
|
+
},
|
|
207
|
+
greet: {
|
|
208
|
+
$$type: 'int',
|
|
209
|
+
value: 2,
|
|
210
|
+
},
|
|
211
|
+
},
|
|
212
|
+
} );
|
|
213
|
+
|
|
214
|
+
// Assert.
|
|
215
|
+
expect( result ).toEqual( { int: 2, greet: null } );
|
|
216
|
+
} );
|
|
217
|
+
|
|
218
|
+
it( 'should skip props when their transformer throws an error', async () => {
|
|
219
|
+
const transformers = createTransformersRegistry()
|
|
220
|
+
.register(
|
|
221
|
+
'int',
|
|
222
|
+
createTransformer( ( value: number ) => value + 1 )
|
|
223
|
+
)
|
|
224
|
+
.register(
|
|
225
|
+
'throws',
|
|
226
|
+
createTransformer< number >( () => {
|
|
227
|
+
throw new Error( 'Not Working!' );
|
|
228
|
+
} )
|
|
229
|
+
);
|
|
230
|
+
|
|
231
|
+
const resolve = createPropsResolver( {
|
|
232
|
+
transformers,
|
|
130
233
|
schema: {
|
|
131
234
|
int: createMockPropType( { kind: 'plain', key: 'int' } ),
|
|
132
235
|
invalid: createMockPropType( { kind: 'plain', key: 'throws' } ),
|
|
@@ -148,14 +251,19 @@ describe( 'createPropsResolver', () => {
|
|
|
148
251
|
} );
|
|
149
252
|
|
|
150
253
|
// Assert.
|
|
151
|
-
expect( result ).toEqual( { int: 2 } );
|
|
254
|
+
expect( result ).toEqual( { int: 2, invalid: null } );
|
|
152
255
|
} );
|
|
153
256
|
|
|
154
257
|
it( 'should trigger onResolve when resolving a prop', async () => {
|
|
258
|
+
const transformers = createTransformersRegistry().register(
|
|
259
|
+
'int',
|
|
260
|
+
createTransformer( ( value: number ) => value + 1 )
|
|
261
|
+
);
|
|
262
|
+
|
|
155
263
|
const onResolve = jest.fn();
|
|
156
264
|
|
|
157
265
|
const resolve = createPropsResolver( {
|
|
158
|
-
transformers
|
|
266
|
+
transformers,
|
|
159
267
|
schema: {
|
|
160
268
|
int: createMockPropType( { kind: 'plain', key: 'int' } ),
|
|
161
269
|
int2: createMockPropType( { kind: 'plain', key: 'int' } ),
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { createArrayLoader, createEnvironment, type TwingArrayLoader, type TwingEnvironment } from '@elementor/twing';
|
|
2
|
+
|
|
3
|
+
export type DomRenderer = {
|
|
4
|
+
register: TwingArrayLoader[ 'setTemplate' ];
|
|
5
|
+
render: TwingEnvironment[ 'render' ];
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export function createDomRenderer(): DomRenderer {
|
|
9
|
+
const loader = createArrayLoader( {} );
|
|
10
|
+
const environment = createEnvironment( loader );
|
|
11
|
+
|
|
12
|
+
environment.registerEscapingStrategy( escapeHtmlTag, 'html_tag' );
|
|
13
|
+
environment.registerEscapingStrategy( escapeURL, 'full_url' );
|
|
14
|
+
|
|
15
|
+
return {
|
|
16
|
+
register: loader.setTemplate,
|
|
17
|
+
render: environment.render,
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function escapeHtmlTag( value: string ) {
|
|
22
|
+
const allowedTags = [
|
|
23
|
+
'a',
|
|
24
|
+
'article',
|
|
25
|
+
'aside',
|
|
26
|
+
'button',
|
|
27
|
+
'div',
|
|
28
|
+
'footer',
|
|
29
|
+
'h1',
|
|
30
|
+
'h2',
|
|
31
|
+
'h3',
|
|
32
|
+
'h4',
|
|
33
|
+
'h5',
|
|
34
|
+
'h6',
|
|
35
|
+
'header',
|
|
36
|
+
'main',
|
|
37
|
+
'nav',
|
|
38
|
+
'p',
|
|
39
|
+
'section',
|
|
40
|
+
'span',
|
|
41
|
+
];
|
|
42
|
+
|
|
43
|
+
return allowedTags.includes( value ) ? value : 'div';
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function escapeURL( value: string ) {
|
|
47
|
+
const allowedProtocols = [ 'http:', 'https:', 'mailto:', 'tel:' ];
|
|
48
|
+
|
|
49
|
+
try {
|
|
50
|
+
const parsed = new URL( value );
|
|
51
|
+
|
|
52
|
+
return allowedProtocols.includes( parsed.protocol ) ? value : '';
|
|
53
|
+
} catch {
|
|
54
|
+
return '';
|
|
55
|
+
}
|
|
56
|
+
}
|
|
@@ -7,11 +7,11 @@ import {
|
|
|
7
7
|
type PropValue,
|
|
8
8
|
} from '@elementor/editor-props';
|
|
9
9
|
|
|
10
|
-
import { type
|
|
10
|
+
import { type TransformersRegistry } from '../transformers/create-transformers-registry';
|
|
11
11
|
import { getMultiPropsValue, isMultiProps } from './multi-props';
|
|
12
12
|
|
|
13
13
|
type CreatePropResolverArgs = {
|
|
14
|
-
transformers:
|
|
14
|
+
transformers: TransformersRegistry;
|
|
15
15
|
schema: PropsSchema;
|
|
16
16
|
onPropResolve?: ( args: { key: string; value: unknown } ) => void;
|
|
17
17
|
};
|
|
@@ -30,12 +30,14 @@ type TransformArgs = {
|
|
|
30
30
|
depth?: number;
|
|
31
31
|
};
|
|
32
32
|
|
|
33
|
+
type ResolvedProps = Record< string, unknown >;
|
|
34
|
+
|
|
33
35
|
export type PropsResolver = ReturnType< typeof createPropsResolver >;
|
|
34
36
|
|
|
35
37
|
const TRANSFORM_DEPTH_LIMIT = 3;
|
|
36
38
|
|
|
37
39
|
export function createPropsResolver( { transformers, schema: initialSchema, onPropResolve }: CreatePropResolverArgs ) {
|
|
38
|
-
async function resolve( { props, schema, signal }: ResolveArgs ) {
|
|
40
|
+
async function resolve( { props, schema, signal }: ResolveArgs ): Promise< ResolvedProps > {
|
|
39
41
|
schema = schema ?? initialSchema;
|
|
40
42
|
|
|
41
43
|
const promises = Promise.all(
|
|
@@ -44,10 +46,6 @@ export function createPropsResolver( { transformers, schema: initialSchema, onPr
|
|
|
44
46
|
|
|
45
47
|
const transformed = await transform( { value, key, type, signal } );
|
|
46
48
|
|
|
47
|
-
if ( transformed === null ) {
|
|
48
|
-
return;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
49
|
onPropResolve?.( { key, value: transformed } );
|
|
52
50
|
|
|
53
51
|
if ( isMultiProps( transformed ) ) {
|
|
@@ -86,6 +84,10 @@ export function createPropsResolver( { transformers, schema: initialSchema, onPr
|
|
|
86
84
|
}
|
|
87
85
|
}
|
|
88
86
|
|
|
87
|
+
if ( value.$$type !== type.key ) {
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
|
|
89
91
|
// Warning: This variable is loosely-typed - use with caution.
|
|
90
92
|
let resolvedValue = value.value;
|
|
91
93
|
|
|
@@ -105,7 +107,7 @@ export function createPropsResolver( { transformers, schema: initialSchema, onPr
|
|
|
105
107
|
);
|
|
106
108
|
}
|
|
107
109
|
|
|
108
|
-
const transformer = transformers
|
|
110
|
+
const transformer = transformers.get( value.$$type );
|
|
109
111
|
|
|
110
112
|
if ( ! transformer ) {
|
|
111
113
|
return null;
|
|
@@ -97,6 +97,10 @@ async function propsToCss( { props, resolve, signal }: PropsToCssArgs ) {
|
|
|
97
97
|
|
|
98
98
|
return Object.entries( transformed )
|
|
99
99
|
.reduce< string[] >( ( acc, [ propName, propValue ] ) => {
|
|
100
|
+
if ( propValue === null ) {
|
|
101
|
+
return acc;
|
|
102
|
+
}
|
|
103
|
+
|
|
100
104
|
acc.push( propName + ':' + propValue + ';' );
|
|
101
105
|
|
|
102
106
|
return acc;
|
|
@@ -1,16 +1,27 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type PropTypeKey } from '@elementor/editor-props';
|
|
2
|
+
|
|
3
|
+
import { type AnyTransformer, type TransformersMap } from './types';
|
|
4
|
+
|
|
5
|
+
export type TransformersRegistry = ReturnType< typeof createTransformersRegistry >;
|
|
2
6
|
|
|
3
7
|
export function createTransformersRegistry() {
|
|
4
8
|
const transformers: TransformersMap = {};
|
|
5
9
|
|
|
10
|
+
let fallbackTransformer: AnyTransformer | null = null;
|
|
11
|
+
|
|
6
12
|
return {
|
|
7
|
-
register(
|
|
8
|
-
transformers[
|
|
13
|
+
register( type: PropTypeKey, transformer: AnyTransformer ) {
|
|
14
|
+
transformers[ type ] = transformer;
|
|
15
|
+
|
|
16
|
+
return this;
|
|
17
|
+
},
|
|
18
|
+
registerFallback( transformer: AnyTransformer ) {
|
|
19
|
+
fallbackTransformer = transformer;
|
|
9
20
|
|
|
10
21
|
return this;
|
|
11
22
|
},
|
|
12
|
-
|
|
13
|
-
return transformers;
|
|
23
|
+
get( type: PropTypeKey ): AnyTransformer | null {
|
|
24
|
+
return transformers[ type ] ?? fallbackTransformer;
|
|
14
25
|
},
|
|
15
26
|
};
|
|
16
27
|
}
|
|
@@ -6,5 +6,5 @@ type BackgroundImagePositionOffset = {
|
|
|
6
6
|
};
|
|
7
7
|
|
|
8
8
|
export const backgroundImagePositionOffsetTransformer = createTransformer(
|
|
9
|
-
( { x
|
|
9
|
+
( { x, y }: BackgroundImagePositionOffset ) => `${ x ?? '0px' } ${ y ?? '0px' }`
|
|
10
10
|
);
|
|
@@ -6,5 +6,5 @@ type BackgroundImageSizeScale = {
|
|
|
6
6
|
};
|
|
7
7
|
|
|
8
8
|
export const backgroundImageSizeScaleTransformer = createTransformer(
|
|
9
|
-
( { width
|
|
9
|
+
( { width, height }: BackgroundImageSizeScale ) => `${ width ?? 'auto' } ${ height ?? 'auto' }`
|
|
10
10
|
);
|
|
@@ -6,14 +6,10 @@ export type UnbrandedTransformer< TValue > = (
|
|
|
6
6
|
}
|
|
7
7
|
) => unknown;
|
|
8
8
|
|
|
9
|
-
const brand = Symbol( 'transformer-brand' );
|
|
10
|
-
|
|
11
9
|
export type Transformer< TValue > = UnbrandedTransformer< TValue > & {
|
|
12
|
-
|
|
10
|
+
__transformer: true;
|
|
13
11
|
};
|
|
14
12
|
|
|
15
|
-
export type TransformerName = string;
|
|
16
|
-
|
|
17
13
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
18
14
|
export type AnyTransformer = Transformer< any >;
|
|
19
15
|
|