@elementor/editor-canvas 0.9.0 → 0.11.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 +36 -0
- package/dist/index.d.mts +17 -1
- package/dist/index.d.ts +17 -1
- package/dist/index.js +203 -225
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +192 -227
- package/dist/index.mjs.map +1 -1
- package/package.json +10 -10
- package/src/{renderers/__tests__ → __tests__}/__mocks__/styles-schema.ts +258 -131
- package/src/__tests__/init-styles-renderer.test.ts +8 -3
- package/src/{renderers/__tests__/create-props-resolver.transformers.test.ts → __tests__/styles-prop-resolver.test.ts} +19 -27
- package/src/index.ts +2 -0
- package/src/init-style-transformers.ts +58 -0
- package/src/init-styles-renderer.ts +8 -6
- package/src/init.tsx +2 -0
- package/src/renderers/__tests__/create-props-resolver.test.ts +44 -34
- package/src/renderers/__tests__/render-styles.test.ts +3 -15
- package/src/renderers/create-props-resolver.ts +32 -31
- package/src/renderers/render-styles.ts +4 -7
- package/src/style-transformers-registry.ts +3 -0
- package/src/transformers/create-transformer.ts +13 -0
- package/src/transformers/create-transformers-registry.ts +16 -0
- package/src/transformers/styles/background-color-overlay-transformer.ts +5 -0
- package/src/transformers/styles/background-image-overlay-transformer.ts +28 -0
- package/src/transformers/styles/background-image-position-offset-transformer.ts +10 -0
- package/src/transformers/styles/background-image-size-scale-transformer.ts +10 -0
- package/src/transformers/styles/background-transformer.ts +13 -0
- package/src/transformers/styles/create-combine-array-transformer.ts +5 -0
- package/src/transformers/styles/create-multi-props-transformer.ts +14 -0
- package/src/transformers/styles/image-attachment-transformer.ts +15 -0
- package/src/transformers/styles/image-src-transformer.ts +11 -0
- package/src/transformers/styles/image-transformer.ts +34 -0
- package/src/transformers/styles/primitive-transformer.ts +3 -0
- package/src/transformers/styles/shadow-transformer.ts +16 -0
- package/src/transformers/styles/size-transformer.ts +10 -0
- package/src/transformers/styles/stroke-transformer.ts +17 -0
- package/src/transformers/types.ts +20 -0
- package/src/renderers/style-transformers/background-color-overlay-transformer.ts +0 -9
- package/src/renderers/style-transformers/background-image-overlay-transformer.ts +0 -24
- package/src/renderers/style-transformers/background-image-position-offset-transformer.ts +0 -10
- package/src/renderers/style-transformers/background-image-size-scale-transformer.ts +0 -10
- package/src/renderers/style-transformers/background-transformer.ts +0 -12
- package/src/renderers/style-transformers/create-combine-array-transformer.ts +0 -9
- package/src/renderers/style-transformers/create-corner-sizes-transformer.ts +0 -31
- package/src/renderers/style-transformers/create-edge-sizes-transformer.ts +0 -31
- package/src/renderers/style-transformers/dimensions.ts +0 -20
- package/src/renderers/style-transformers/image-attachment.ts +0 -14
- package/src/renderers/style-transformers/image-src.ts +0 -8
- package/src/renderers/style-transformers/image.ts +0 -25
- package/src/renderers/style-transformers/index.ts +0 -48
- package/src/renderers/style-transformers/layout-direction-transformer.ts +0 -20
- package/src/renderers/style-transformers/primitive-transformer.ts +0 -7
- package/src/renderers/style-transformers/shadow-transformer.ts +0 -11
- package/src/renderers/style-transformers/size-transformer.ts +0 -9
- package/src/renderers/style-transformers/stroke-transformer.ts +0 -16
- package/src/renderers/types.ts +0 -12
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { styleTransformersRegistry } from '@elementor/editor-canvas';
|
|
1
2
|
import {
|
|
2
3
|
backgroundColorOverlayPropTypeUtil,
|
|
3
4
|
backgroundImageOverlayPropTypeUtil,
|
|
@@ -15,15 +16,15 @@ import {
|
|
|
15
16
|
imageSrcPropTypeUtil,
|
|
16
17
|
layoutDirectionPropTypeUtil,
|
|
17
18
|
type Props,
|
|
18
|
-
type PropsSchema,
|
|
19
19
|
shadowPropTypeUtil,
|
|
20
20
|
sizePropTypeUtil,
|
|
21
|
+
stringPropTypeUtil,
|
|
21
22
|
strokePropTypeUtil,
|
|
22
23
|
} from '@elementor/editor-props';
|
|
23
24
|
import { getMediaAttachment } from '@elementor/wp-media';
|
|
24
25
|
|
|
25
|
-
import {
|
|
26
|
-
import {
|
|
26
|
+
import { initStyleTransformers } from '../init-style-transformers';
|
|
27
|
+
import { createPropsResolver } from '../renderers/create-props-resolver';
|
|
27
28
|
import { stylesSchemaMock } from './__mocks__/styles-schema';
|
|
28
29
|
|
|
29
30
|
jest.mock( '@elementor/wp-media' );
|
|
@@ -32,11 +33,10 @@ type Payload = {
|
|
|
32
33
|
name: string;
|
|
33
34
|
prepare?: () => void;
|
|
34
35
|
props: Props;
|
|
35
|
-
schema: PropsSchema;
|
|
36
36
|
expected: Record< string, unknown >;
|
|
37
37
|
};
|
|
38
38
|
|
|
39
|
-
describe( '
|
|
39
|
+
describe( 'styles prop resolver', () => {
|
|
40
40
|
it.each< Payload >( [
|
|
41
41
|
{
|
|
42
42
|
name: 'text-stroke',
|
|
@@ -49,7 +49,6 @@ describe( 'createPropsResolver - transformers', () => {
|
|
|
49
49
|
color: colorPropTypeUtil.create( '#000000' ),
|
|
50
50
|
} ),
|
|
51
51
|
},
|
|
52
|
-
schema: stylesSchemaMock,
|
|
53
52
|
expected: {
|
|
54
53
|
'-webkit-text-stroke': '1px #000000',
|
|
55
54
|
stroke: '#000000',
|
|
@@ -77,7 +76,6 @@ describe( 'createPropsResolver - transformers', () => {
|
|
|
77
76
|
} ),
|
|
78
77
|
] ),
|
|
79
78
|
},
|
|
80
|
-
schema: stylesSchemaMock,
|
|
81
79
|
expected: {
|
|
82
80
|
'box-shadow': '1px 1px 1px 1px #000000,1px 1px 1px 1px #000000 inset',
|
|
83
81
|
},
|
|
@@ -85,7 +83,7 @@ describe( 'createPropsResolver - transformers', () => {
|
|
|
85
83
|
{
|
|
86
84
|
name: 'linked-dimensional',
|
|
87
85
|
props: {
|
|
88
|
-
|
|
86
|
+
margin: dimensionsPropTypeUtil.create( {
|
|
89
87
|
top: sizePropTypeUtil.create( {
|
|
90
88
|
size: 10,
|
|
91
89
|
unit: 'px',
|
|
@@ -98,18 +96,14 @@ describe( 'createPropsResolver - transformers', () => {
|
|
|
98
96
|
size: 30,
|
|
99
97
|
unit: 'px',
|
|
100
98
|
} ),
|
|
101
|
-
left:
|
|
102
|
-
size: 40,
|
|
103
|
-
unit: 'px',
|
|
104
|
-
} ),
|
|
99
|
+
left: stringPropTypeUtil.create( 'auto' ),
|
|
105
100
|
} ),
|
|
106
101
|
},
|
|
107
|
-
schema: stylesSchemaMock,
|
|
108
102
|
expected: {
|
|
109
|
-
'
|
|
110
|
-
'
|
|
111
|
-
'
|
|
112
|
-
'
|
|
103
|
+
'margin-top': '10px',
|
|
104
|
+
'margin-right': '20px',
|
|
105
|
+
'margin-bottom': '30px',
|
|
106
|
+
'margin-left': 'auto',
|
|
113
107
|
},
|
|
114
108
|
},
|
|
115
109
|
{
|
|
@@ -122,7 +116,6 @@ describe( 'createPropsResolver - transformers', () => {
|
|
|
122
116
|
left: sizePropTypeUtil.create( { size: 40, unit: 'px' } ),
|
|
123
117
|
} ),
|
|
124
118
|
},
|
|
125
|
-
schema: stylesSchemaMock,
|
|
126
119
|
expected: {
|
|
127
120
|
'border-top-width': '10px',
|
|
128
121
|
'border-right-width': '20px',
|
|
@@ -140,7 +133,6 @@ describe( 'createPropsResolver - transformers', () => {
|
|
|
140
133
|
'end-end': sizePropTypeUtil.create( { size: 40, unit: 'px' } ),
|
|
141
134
|
} ),
|
|
142
135
|
},
|
|
143
|
-
schema: stylesSchemaMock,
|
|
144
136
|
expected: {
|
|
145
137
|
'border-start-start-radius': '10px',
|
|
146
138
|
'border-start-end-radius': '20px',
|
|
@@ -156,7 +148,6 @@ describe( 'createPropsResolver - transformers', () => {
|
|
|
156
148
|
column: sizePropTypeUtil.create( { size: 20, unit: 'px' } ),
|
|
157
149
|
} ),
|
|
158
150
|
},
|
|
159
|
-
schema: stylesSchemaMock,
|
|
160
151
|
expected: {
|
|
161
152
|
'column-gap': '20px',
|
|
162
153
|
'row-gap': '10px',
|
|
@@ -169,7 +160,6 @@ describe( 'createPropsResolver - transformers', () => {
|
|
|
169
160
|
color: colorPropTypeUtil.create( '#ee00ff' ),
|
|
170
161
|
} ),
|
|
171
162
|
},
|
|
172
|
-
schema: stylesSchemaMock,
|
|
173
163
|
expected: {
|
|
174
164
|
background: '#ee00ff',
|
|
175
165
|
},
|
|
@@ -191,7 +181,6 @@ describe( 'createPropsResolver - transformers', () => {
|
|
|
191
181
|
] ),
|
|
192
182
|
} ),
|
|
193
183
|
},
|
|
194
|
-
schema: stylesSchemaMock,
|
|
195
184
|
expected: {
|
|
196
185
|
background: 'url(https://localhost.test/test-image.png)',
|
|
197
186
|
},
|
|
@@ -249,7 +238,6 @@ describe( 'createPropsResolver - transformers', () => {
|
|
|
249
238
|
] ),
|
|
250
239
|
} ),
|
|
251
240
|
},
|
|
252
|
-
schema: stylesSchemaMock,
|
|
253
241
|
expected: {
|
|
254
242
|
background:
|
|
255
243
|
'linear-gradient(blue, blue),linear-gradient(yellow, yellow),' +
|
|
@@ -291,19 +279,23 @@ describe( 'createPropsResolver - transformers', () => {
|
|
|
291
279
|
] ),
|
|
292
280
|
} ),
|
|
293
281
|
},
|
|
294
|
-
schema: stylesSchemaMock,
|
|
295
282
|
expected: {
|
|
296
283
|
background: 'url(medium_large-image-url-123) repeat-x,url(thumbnail-image-url-123) fixed',
|
|
297
284
|
},
|
|
298
285
|
},
|
|
299
|
-
] )( 'it should resolve props for `$name`', async ( { prepare, props,
|
|
286
|
+
] )( 'it should resolve props for `$name`', async ( { prepare, props, expected } ) => {
|
|
300
287
|
// Arrange.
|
|
301
288
|
prepare?.();
|
|
302
289
|
|
|
303
|
-
|
|
290
|
+
initStyleTransformers();
|
|
291
|
+
|
|
292
|
+
const resolve = createPropsResolver( {
|
|
293
|
+
transformers: styleTransformersRegistry.all(),
|
|
294
|
+
schema: stylesSchemaMock,
|
|
295
|
+
} );
|
|
304
296
|
|
|
305
297
|
// Act.
|
|
306
|
-
const result = await resolve( { props
|
|
298
|
+
const result = await resolve( { props } );
|
|
307
299
|
|
|
308
300
|
// Assert.
|
|
309
301
|
expect( result ).toStrictEqual( expected );
|
package/src/index.ts
CHANGED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { styleTransformersRegistry } from './style-transformers-registry';
|
|
2
|
+
import { backgroundColorOverlayTransformer } from './transformers/styles/background-color-overlay-transformer';
|
|
3
|
+
import { backgroundImageOverlayTransformer } from './transformers/styles/background-image-overlay-transformer';
|
|
4
|
+
import { backgroundImagePositionOffsetTransformer } from './transformers/styles/background-image-position-offset-transformer';
|
|
5
|
+
import { backgroundImageSizeScaleTransformer } from './transformers/styles/background-image-size-scale-transformer';
|
|
6
|
+
import { backgroundTransformer } from './transformers/styles/background-transformer';
|
|
7
|
+
import { createCombineArrayTransformer } from './transformers/styles/create-combine-array-transformer';
|
|
8
|
+
import { createMultiPropsTransformer } from './transformers/styles/create-multi-props-transformer';
|
|
9
|
+
import { imageAttachmentTransformer } from './transformers/styles/image-attachment-transformer';
|
|
10
|
+
import { imageSrcTransformer } from './transformers/styles/image-src-transformer';
|
|
11
|
+
import { imageTransformer } from './transformers/styles/image-transformer';
|
|
12
|
+
import { primitiveTransformer } from './transformers/styles/primitive-transformer';
|
|
13
|
+
import { shadowTransformer } from './transformers/styles/shadow-transformer';
|
|
14
|
+
import { sizeTransformer } from './transformers/styles/size-transformer';
|
|
15
|
+
import { strokeTransformer } from './transformers/styles/stroke-transformer';
|
|
16
|
+
|
|
17
|
+
export function initStyleTransformers() {
|
|
18
|
+
styleTransformersRegistry
|
|
19
|
+
.register( 'size', sizeTransformer )
|
|
20
|
+
.register( 'shadow', shadowTransformer )
|
|
21
|
+
.register( 'stroke', strokeTransformer )
|
|
22
|
+
.register(
|
|
23
|
+
'dimensions',
|
|
24
|
+
createMultiPropsTransformer(
|
|
25
|
+
[ 'top', 'right', 'bottom', 'left' ],
|
|
26
|
+
( { propKey, key } ) => `${ propKey }-${ key }`
|
|
27
|
+
)
|
|
28
|
+
)
|
|
29
|
+
.register( 'color', primitiveTransformer )
|
|
30
|
+
.register( 'number', primitiveTransformer )
|
|
31
|
+
.register( 'string', primitiveTransformer )
|
|
32
|
+
.register( 'url', primitiveTransformer )
|
|
33
|
+
.register( 'box-shadow', createCombineArrayTransformer( ',' ) )
|
|
34
|
+
.register( 'background', backgroundTransformer )
|
|
35
|
+
.register( 'background-overlay', createCombineArrayTransformer( ',' ) )
|
|
36
|
+
.register( 'background-color-overlay', backgroundColorOverlayTransformer )
|
|
37
|
+
.register( 'background-image-overlay', backgroundImageOverlayTransformer )
|
|
38
|
+
.register( 'background-image-position-offset', backgroundImagePositionOffsetTransformer )
|
|
39
|
+
.register( 'background-image-size-scale', backgroundImageSizeScaleTransformer )
|
|
40
|
+
.register( 'image-attachment-id', imageAttachmentTransformer )
|
|
41
|
+
.register( 'image-src', imageSrcTransformer )
|
|
42
|
+
.register( 'image', imageTransformer )
|
|
43
|
+
.register(
|
|
44
|
+
'layout-direction',
|
|
45
|
+
createMultiPropsTransformer( [ 'row', 'column' ], ( { propKey, key } ) => `${ key }-${ propKey }` )
|
|
46
|
+
)
|
|
47
|
+
.register(
|
|
48
|
+
'border-width',
|
|
49
|
+
createMultiPropsTransformer( [ 'top', 'right', 'bottom', 'left' ], ( { key } ) => `border-${ key }-width` )
|
|
50
|
+
)
|
|
51
|
+
.register(
|
|
52
|
+
'border-radius',
|
|
53
|
+
createMultiPropsTransformer(
|
|
54
|
+
[ 'start-start', 'start-end', 'end-start', 'end-end' ],
|
|
55
|
+
( { key } ) => `border-${ key }-radius`
|
|
56
|
+
)
|
|
57
|
+
);
|
|
58
|
+
}
|
|
@@ -5,7 +5,7 @@ import { __privateListenTo as listenTo, v1ReadyEvent } from '@elementor/editor-v
|
|
|
5
5
|
|
|
6
6
|
import { createPropsResolver } from './renderers/create-props-resolver';
|
|
7
7
|
import renderStyles from './renderers/render-styles';
|
|
8
|
-
import {
|
|
8
|
+
import { styleTransformersRegistry } from './style-transformers-registry';
|
|
9
9
|
import { enqueueFont } from './sync/enqueue-font';
|
|
10
10
|
import { getCanvasIframeBody } from './sync/get-canvas-iframe-body';
|
|
11
11
|
|
|
@@ -13,18 +13,21 @@ const WRAPPER_DATA_ATTR = 'data-styles-container';
|
|
|
13
13
|
const SELECTOR_PREFIX = '.elementor';
|
|
14
14
|
|
|
15
15
|
export function initStylesRenderer() {
|
|
16
|
-
|
|
16
|
+
listenTo( v1ReadyEvent(), () => {
|
|
17
|
+
let abortController: AbortController | null = null;
|
|
17
18
|
|
|
18
|
-
|
|
19
|
+
const resolve = createPropsResolver( {
|
|
20
|
+
transformers: styleTransformersRegistry.all(),
|
|
21
|
+
schema: getStylesSchema(),
|
|
22
|
+
onPropResolve: enqueueUsedFonts,
|
|
23
|
+
} );
|
|
19
24
|
|
|
20
|
-
listenTo( v1ReadyEvent(), () => {
|
|
21
25
|
stylesRepository.subscribe( async () => {
|
|
22
26
|
const styleContainer = getStylesContainer();
|
|
23
27
|
|
|
24
28
|
// Styles should be printed in a reversed order, so the high priority styles will be printed last.
|
|
25
29
|
const styles = stylesRepository.all().reverse();
|
|
26
30
|
const breakpoints = getBreakpointsMap();
|
|
27
|
-
const schema = getStylesSchema();
|
|
28
31
|
|
|
29
32
|
if ( abortController ) {
|
|
30
33
|
abortController.abort();
|
|
@@ -38,7 +41,6 @@ export function initStylesRenderer() {
|
|
|
38
41
|
breakpoints,
|
|
39
42
|
selectorPrefix: SELECTOR_PREFIX,
|
|
40
43
|
signal: abortController.signal,
|
|
41
|
-
schema,
|
|
42
44
|
} );
|
|
43
45
|
} );
|
|
44
46
|
} );
|
package/src/init.tsx
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { injectIntoTop } from '@elementor/editor';
|
|
2
2
|
|
|
3
3
|
import { ElementsOverlays } from './components/elements-overlays';
|
|
4
|
+
import { initStyleTransformers } from './init-style-transformers';
|
|
4
5
|
import { initStylesRenderer } from './init-styles-renderer';
|
|
5
6
|
|
|
6
7
|
export function init() {
|
|
8
|
+
initStyleTransformers();
|
|
7
9
|
initStylesRenderer();
|
|
8
10
|
|
|
9
11
|
injectIntoTop( {
|
|
@@ -1,20 +1,21 @@
|
|
|
1
1
|
import { createMockPropType } from 'test-utils';
|
|
2
2
|
|
|
3
|
+
import { createTransformer } from '../../transformers/create-transformer';
|
|
3
4
|
import { createPropsResolver } from '../create-props-resolver';
|
|
4
5
|
|
|
5
6
|
describe( 'createPropsResolver', () => {
|
|
6
7
|
it( 'should resolve simple props', async () => {
|
|
7
8
|
// Arrange.
|
|
8
|
-
const resolve = createPropsResolver( {
|
|
9
|
+
const resolve = createPropsResolver( {
|
|
10
|
+
transformers: { int: createTransformer( ( value: number ) => value + 1 ) },
|
|
11
|
+
schema: { int: createMockPropType( { kind: 'plain', key: 'int' } ) },
|
|
12
|
+
} );
|
|
9
13
|
|
|
10
14
|
// Act.
|
|
11
15
|
const result = await resolve( {
|
|
12
16
|
props: {
|
|
13
17
|
int: { $$type: 'int', value: 0 },
|
|
14
18
|
},
|
|
15
|
-
schema: {
|
|
16
|
-
int: createMockPropType( { kind: 'plain', key: 'int' } ),
|
|
17
|
-
},
|
|
18
19
|
} );
|
|
19
20
|
|
|
20
21
|
// Assert.
|
|
@@ -23,7 +24,10 @@ describe( 'createPropsResolver', () => {
|
|
|
23
24
|
|
|
24
25
|
it( 'should skip disabled props', async () => {
|
|
25
26
|
// Arrange.
|
|
26
|
-
const resolve = createPropsResolver( {
|
|
27
|
+
const resolve = createPropsResolver( {
|
|
28
|
+
transformers: { int: createTransformer( ( value: number ) => value + 1 ) },
|
|
29
|
+
schema: { int: createMockPropType( { kind: 'plain', key: 'int' } ) },
|
|
30
|
+
} );
|
|
27
31
|
|
|
28
32
|
// Act.
|
|
29
33
|
const result = await resolve( {
|
|
@@ -34,9 +38,6 @@ describe( 'createPropsResolver', () => {
|
|
|
34
38
|
disabled: true,
|
|
35
39
|
},
|
|
36
40
|
},
|
|
37
|
-
schema: {
|
|
38
|
-
int: createMockPropType( { kind: 'plain', key: 'int' } ),
|
|
39
|
-
},
|
|
40
41
|
} );
|
|
41
42
|
|
|
42
43
|
// Assert.
|
|
@@ -45,11 +46,8 @@ describe( 'createPropsResolver', () => {
|
|
|
45
46
|
|
|
46
47
|
it( 'should fallback to default value when there is no value', async () => {
|
|
47
48
|
// Arrange.
|
|
48
|
-
const resolve = createPropsResolver( {
|
|
49
|
-
|
|
50
|
-
// Act.
|
|
51
|
-
const result = await resolve( {
|
|
52
|
-
props: {},
|
|
49
|
+
const resolve = createPropsResolver( {
|
|
50
|
+
transformers: { int: createTransformer( ( value: number ) => value + 1 ) },
|
|
53
51
|
schema: {
|
|
54
52
|
int: createMockPropType( {
|
|
55
53
|
kind: 'plain',
|
|
@@ -59,13 +57,21 @@ describe( 'createPropsResolver', () => {
|
|
|
59
57
|
},
|
|
60
58
|
} );
|
|
61
59
|
|
|
60
|
+
// Act.
|
|
61
|
+
const result = await resolve( { props: {} } );
|
|
62
|
+
|
|
62
63
|
// Assert.
|
|
63
64
|
expect( result ).toEqual( { int: 4 } );
|
|
64
65
|
} );
|
|
65
66
|
|
|
66
67
|
it( 'should skip props that are not in the schema', async () => {
|
|
67
68
|
// Arrange.
|
|
68
|
-
const resolve = createPropsResolver( {
|
|
69
|
+
const resolve = createPropsResolver( {
|
|
70
|
+
transformers: { int: createTransformer( ( value: number ) => value + 1 ) },
|
|
71
|
+
schema: {
|
|
72
|
+
int: createMockPropType( { kind: 'plain', key: 'int' } ),
|
|
73
|
+
},
|
|
74
|
+
} );
|
|
69
75
|
|
|
70
76
|
// Act.
|
|
71
77
|
const result = await resolve( {
|
|
@@ -79,9 +85,6 @@ describe( 'createPropsResolver', () => {
|
|
|
79
85
|
value: 1,
|
|
80
86
|
},
|
|
81
87
|
},
|
|
82
|
-
schema: {
|
|
83
|
-
int: createMockPropType( { kind: 'plain', key: 'int' } ),
|
|
84
|
-
},
|
|
85
88
|
} );
|
|
86
89
|
|
|
87
90
|
// Assert.
|
|
@@ -90,7 +93,13 @@ describe( 'createPropsResolver', () => {
|
|
|
90
93
|
|
|
91
94
|
it( "should skip props that don't have a transformer", async () => {
|
|
92
95
|
// Arrange.
|
|
93
|
-
const resolve = createPropsResolver( {
|
|
96
|
+
const resolve = createPropsResolver( {
|
|
97
|
+
transformers: { int: createTransformer( ( value: number ) => value + 1 ) },
|
|
98
|
+
schema: {
|
|
99
|
+
int: createMockPropType( { kind: 'plain', key: 'int' } ),
|
|
100
|
+
invalid: createMockPropType( { kind: 'plain', key: 'invalid' } ),
|
|
101
|
+
},
|
|
102
|
+
} );
|
|
94
103
|
|
|
95
104
|
// Act.
|
|
96
105
|
const result = await resolve( {
|
|
@@ -104,10 +113,6 @@ describe( 'createPropsResolver', () => {
|
|
|
104
113
|
value: 1,
|
|
105
114
|
},
|
|
106
115
|
},
|
|
107
|
-
schema: {
|
|
108
|
-
int: createMockPropType( { kind: 'plain', key: 'int' } ),
|
|
109
|
-
invalid: createMockPropType( { kind: 'plain', key: 'invalid' } ),
|
|
110
|
-
},
|
|
111
116
|
} );
|
|
112
117
|
|
|
113
118
|
// Assert.
|
|
@@ -116,9 +121,15 @@ describe( 'createPropsResolver', () => {
|
|
|
116
121
|
|
|
117
122
|
it( 'should skip props when their transformer throws an error', async () => {
|
|
118
123
|
const resolve = createPropsResolver( {
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
124
|
+
transformers: {
|
|
125
|
+
int: createTransformer( ( value: number ) => value + 1 ),
|
|
126
|
+
throws: createTransformer< number >( () => {
|
|
127
|
+
throw new Error( 'Not Working!' );
|
|
128
|
+
} ),
|
|
129
|
+
},
|
|
130
|
+
schema: {
|
|
131
|
+
int: createMockPropType( { kind: 'plain', key: 'int' } ),
|
|
132
|
+
invalid: createMockPropType( { kind: 'plain', key: 'throws' } ),
|
|
122
133
|
},
|
|
123
134
|
} );
|
|
124
135
|
|
|
@@ -134,10 +145,6 @@ describe( 'createPropsResolver', () => {
|
|
|
134
145
|
value: 1,
|
|
135
146
|
},
|
|
136
147
|
},
|
|
137
|
-
schema: {
|
|
138
|
-
int: createMockPropType( { kind: 'plain', key: 'int' } ),
|
|
139
|
-
invalid: createMockPropType( { kind: 'plain', key: 'throws' } ),
|
|
140
|
-
},
|
|
141
148
|
} );
|
|
142
149
|
|
|
143
150
|
// Assert.
|
|
@@ -147,7 +154,14 @@ describe( 'createPropsResolver', () => {
|
|
|
147
154
|
it( 'should trigger onResolve when resolving a prop', async () => {
|
|
148
155
|
const onResolve = jest.fn();
|
|
149
156
|
|
|
150
|
-
const resolve = createPropsResolver( {
|
|
157
|
+
const resolve = createPropsResolver( {
|
|
158
|
+
transformers: { int: createTransformer( ( value: number ) => value + 1 ) },
|
|
159
|
+
schema: {
|
|
160
|
+
int: createMockPropType( { kind: 'plain', key: 'int' } ),
|
|
161
|
+
int2: createMockPropType( { kind: 'plain', key: 'int' } ),
|
|
162
|
+
},
|
|
163
|
+
onPropResolve: onResolve,
|
|
164
|
+
} );
|
|
151
165
|
|
|
152
166
|
// Act.
|
|
153
167
|
await resolve( {
|
|
@@ -161,10 +175,6 @@ describe( 'createPropsResolver', () => {
|
|
|
161
175
|
value: 3,
|
|
162
176
|
},
|
|
163
177
|
},
|
|
164
|
-
schema: {
|
|
165
|
-
int: createMockPropType( { kind: 'plain', key: 'int' } ),
|
|
166
|
-
int2: createMockPropType( { kind: 'plain', key: 'int' } ),
|
|
167
|
-
},
|
|
168
178
|
} );
|
|
169
179
|
|
|
170
180
|
// Assert.
|
|
@@ -1,18 +1,10 @@
|
|
|
1
1
|
/* eslint-disable testing-library/render-result-naming-convention */
|
|
2
|
-
import { createMockPropType } from 'test-utils';
|
|
3
2
|
import type { BreakpointsMap } from '@elementor/editor-responsive';
|
|
4
|
-
import {
|
|
3
|
+
import { type StyleDefinition } from '@elementor/editor-styles';
|
|
5
4
|
|
|
6
5
|
import renderStyles from '../render-styles';
|
|
7
|
-
import { stylesSchemaMock } from './__mocks__/styles-schema';
|
|
8
|
-
|
|
9
|
-
jest.mock( '@elementor/editor-styles' );
|
|
10
6
|
|
|
11
7
|
describe( 'renderStyles', () => {
|
|
12
|
-
beforeEach( () => {
|
|
13
|
-
jest.mocked( getStylesSchema ).mockReturnValue( stylesSchemaMock );
|
|
14
|
-
} );
|
|
15
|
-
|
|
16
8
|
it( 'should render media queries', async () => {
|
|
17
9
|
// Arrange.
|
|
18
10
|
const styleDef: StyleDefinition = {
|
|
@@ -32,14 +24,12 @@ describe( 'renderStyles', () => {
|
|
|
32
24
|
};
|
|
33
25
|
|
|
34
26
|
const resolve = jest.fn( ( { props } ) => props );
|
|
35
|
-
const schema = { 'font-size': createMockPropType( { kind: 'plain', key: 'string' } ) };
|
|
36
27
|
|
|
37
28
|
// Act.
|
|
38
29
|
const cssString = await renderStyles( {
|
|
39
30
|
styles: [ styleDef ],
|
|
40
31
|
resolve,
|
|
41
32
|
breakpoints: { tablet: { width: 992, type: 'max-width' } } as BreakpointsMap,
|
|
42
|
-
schema,
|
|
43
33
|
} );
|
|
44
34
|
|
|
45
35
|
// Assert.
|
|
@@ -49,8 +39,8 @@ describe( 'renderStyles', () => {
|
|
|
49
39
|
expect( cssString ).toBe( `<style data-style-id="test">${ defaultStyle }${ tabletStyle }</style>` );
|
|
50
40
|
|
|
51
41
|
expect( resolve ).toHaveBeenCalledTimes( 2 );
|
|
52
|
-
expect( resolve ).toHaveBeenNthCalledWith( 1, { props: { 'font-size': '24px' }
|
|
53
|
-
expect( resolve ).toHaveBeenNthCalledWith( 2, { props: { 'font-size': '18px' }
|
|
42
|
+
expect( resolve ).toHaveBeenNthCalledWith( 1, { props: { 'font-size': '24px' } } );
|
|
43
|
+
expect( resolve ).toHaveBeenNthCalledWith( 2, { props: { 'font-size': '18px' } } );
|
|
54
44
|
} );
|
|
55
45
|
|
|
56
46
|
it( 'should render pseudo classes', async () => {
|
|
@@ -82,7 +72,6 @@ describe( 'renderStyles', () => {
|
|
|
82
72
|
styles: [ styleDef ],
|
|
83
73
|
resolve,
|
|
84
74
|
breakpoints: { mobile: { width: 768, type: 'max-width' } } as BreakpointsMap,
|
|
85
|
-
schema: { 'font-size': createMockPropType( { kind: 'plain', key: 'string' } ) },
|
|
86
75
|
} );
|
|
87
76
|
|
|
88
77
|
// Assert.
|
|
@@ -115,7 +104,6 @@ describe( 'renderStyles', () => {
|
|
|
115
104
|
const result = await renderStyles( {
|
|
116
105
|
styles: [ styleDef ],
|
|
117
106
|
resolve,
|
|
118
|
-
schema: getStylesSchema(),
|
|
119
107
|
selectorPrefix: '.elementor-prefix',
|
|
120
108
|
breakpoints: {} as BreakpointsMap,
|
|
121
109
|
} );
|
|
@@ -7,16 +7,18 @@ import {
|
|
|
7
7
|
type PropValue,
|
|
8
8
|
} from '@elementor/editor-props';
|
|
9
9
|
|
|
10
|
+
import { type TransformersMap } from '../transformers/types';
|
|
10
11
|
import { getMultiPropsValue, isMultiProps } from './multi-props';
|
|
11
|
-
import { type TransformersMap } from './types';
|
|
12
12
|
|
|
13
|
-
type
|
|
13
|
+
type CreatePropResolverArgs = {
|
|
14
|
+
transformers: TransformersMap;
|
|
15
|
+
schema: PropsSchema;
|
|
14
16
|
onPropResolve?: ( args: { key: string; value: unknown } ) => void;
|
|
15
17
|
};
|
|
16
18
|
|
|
17
19
|
type ResolveArgs = {
|
|
18
20
|
props: Props;
|
|
19
|
-
schema
|
|
21
|
+
schema?: PropsSchema;
|
|
20
22
|
signal?: AbortSignal;
|
|
21
23
|
};
|
|
22
24
|
|
|
@@ -32,10 +34,33 @@ export type PropsResolver = ReturnType< typeof createPropsResolver >;
|
|
|
32
34
|
|
|
33
35
|
const TRANSFORM_DEPTH_LIMIT = 3;
|
|
34
36
|
|
|
35
|
-
export function createPropsResolver(
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
export function createPropsResolver( { transformers, schema: initialSchema, onPropResolve }: CreatePropResolverArgs ) {
|
|
38
|
+
async function resolve( { props, schema, signal }: ResolveArgs ) {
|
|
39
|
+
schema = schema ?? initialSchema;
|
|
40
|
+
|
|
41
|
+
const promises = Promise.all(
|
|
42
|
+
Object.entries( schema ).map( async ( [ key, type ] ) => {
|
|
43
|
+
const value = props[ key ] ?? type.default;
|
|
44
|
+
|
|
45
|
+
const transformed = await transform( { value, key, type, signal } );
|
|
46
|
+
|
|
47
|
+
if ( transformed === null ) {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
onPropResolve?.( { key, value: transformed } );
|
|
52
|
+
|
|
53
|
+
if ( isMultiProps( transformed ) ) {
|
|
54
|
+
return getMultiPropsValue( transformed );
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return { [ key ]: transformed };
|
|
58
|
+
} )
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
return Object.assign( {}, ...( await promises ).filter( Boolean ) );
|
|
62
|
+
}
|
|
63
|
+
|
|
39
64
|
async function transform( { value, key, type, signal, depth = 0 }: TransformArgs ) {
|
|
40
65
|
if ( value === null || value === undefined ) {
|
|
41
66
|
return null;
|
|
@@ -95,29 +120,5 @@ export function createPropsResolver(
|
|
|
95
120
|
}
|
|
96
121
|
}
|
|
97
122
|
|
|
98
|
-
async function resolve( { props, schema, signal }: ResolveArgs ) {
|
|
99
|
-
const promises = Promise.all(
|
|
100
|
-
Object.entries( schema ).map( async ( [ key, type ] ) => {
|
|
101
|
-
const value = props[ key ] ?? type.default;
|
|
102
|
-
|
|
103
|
-
const transformed = await transform( { value, key, type, signal } );
|
|
104
|
-
|
|
105
|
-
if ( transformed === null ) {
|
|
106
|
-
return;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
onPropResolve?.( { key, value: transformed } );
|
|
110
|
-
|
|
111
|
-
if ( isMultiProps( transformed ) ) {
|
|
112
|
-
return getMultiPropsValue( transformed );
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
return { [ key ]: transformed };
|
|
116
|
-
} )
|
|
117
|
-
);
|
|
118
|
-
|
|
119
|
-
return Object.assign( {}, ...( await promises ).filter( Boolean ) );
|
|
120
|
-
}
|
|
121
|
-
|
|
122
123
|
return resolve;
|
|
123
124
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type Props
|
|
1
|
+
import { type Props } from '@elementor/editor-props';
|
|
2
2
|
import { type Breakpoint, type BreakpointsMap } from '@elementor/editor-responsive';
|
|
3
3
|
import { type StyleDefinition, type StyleDefinitionState, type StyleDefinitionType } from '@elementor/editor-styles';
|
|
4
4
|
|
|
@@ -8,7 +8,6 @@ import { UnknownStyleTypeError } from './errors';
|
|
|
8
8
|
type RenderParams = {
|
|
9
9
|
resolve: PropsResolver;
|
|
10
10
|
styles: StyleDefinition[];
|
|
11
|
-
schema: PropsSchema;
|
|
12
11
|
breakpoints: BreakpointsMap;
|
|
13
12
|
selectorPrefix?: string;
|
|
14
13
|
signal?: AbortSignal;
|
|
@@ -16,7 +15,6 @@ type RenderParams = {
|
|
|
16
15
|
|
|
17
16
|
type PropsToCssArgs = {
|
|
18
17
|
props: Props;
|
|
19
|
-
schema: PropsSchema;
|
|
20
18
|
resolve: PropsResolver;
|
|
21
19
|
signal?: AbortSignal;
|
|
22
20
|
};
|
|
@@ -28,14 +26,13 @@ const SELECTORS_MAP: Record< StyleDefinitionType, string > = {
|
|
|
28
26
|
export default async function renderStyles( {
|
|
29
27
|
resolve,
|
|
30
28
|
styles,
|
|
31
|
-
schema,
|
|
32
29
|
breakpoints,
|
|
33
30
|
selectorPrefix = '',
|
|
34
31
|
signal,
|
|
35
32
|
}: RenderParams ) {
|
|
36
33
|
const stylesCssPromises = styles.map( async ( style ) => {
|
|
37
34
|
const variantCssPromises = Object.values( style.variants ).map( async ( variant ) => {
|
|
38
|
-
const css = await propsToCss( { props: variant.props,
|
|
35
|
+
const css = await propsToCss( { props: variant.props, resolve, signal } );
|
|
39
36
|
|
|
40
37
|
return createStyleWrapper()
|
|
41
38
|
.forStyle( style )
|
|
@@ -95,8 +92,8 @@ function createStyleWrapper( value: string = '', wrapper?: ( css: string ) => st
|
|
|
95
92
|
};
|
|
96
93
|
}
|
|
97
94
|
|
|
98
|
-
async function propsToCss( { props, resolve, signal
|
|
99
|
-
const transformed = await resolve( { props,
|
|
95
|
+
async function propsToCss( { props, resolve, signal }: PropsToCssArgs ) {
|
|
96
|
+
const transformed = await resolve( { props, signal } );
|
|
100
97
|
|
|
101
98
|
return Object.entries( transformed )
|
|
102
99
|
.reduce< string[] >( ( acc, [ propName, propValue ] ) => {
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type AnyTransformable } from '@elementor/editor-props';
|
|
2
|
+
|
|
3
|
+
import { type Transformer, type UnbrandedTransformer } from './types';
|
|
4
|
+
|
|
5
|
+
// Wrap transformer for better DX (types).
|
|
6
|
+
// Inspired by: https://tkdodo.eu/blog/the-query-options-api
|
|
7
|
+
export function createTransformer< TValue = never >(
|
|
8
|
+
cb: TValue extends AnyTransformable
|
|
9
|
+
? 'Transformable values are invalid, use the actual value instead.'
|
|
10
|
+
: UnbrandedTransformer< TValue >
|
|
11
|
+
): Transformer< NoInfer< TValue > > {
|
|
12
|
+
return cb as never;
|
|
13
|
+
}
|