@elementor/editor-editing-panel 1.14.0 → 1.16.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/CHANGELOG.md +33 -0
- package/dist/index.js +30 -16
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +31 -16
- package/dist/index.mjs.map +1 -1
- package/package.json +11 -11
- package/src/components/css-classes/css-class-menu.tsx +1 -1
- package/src/components/css-classes/css-class-selector.tsx +1 -1
- package/src/components/style-sections/layout-section/flex-size-field.tsx +1 -1
- package/src/components/style-sections/position-section/dimensions-field.tsx +1 -1
- package/src/components/style-sections/position-section/z-index-field.tsx +1 -1
- package/src/components/style-sections/size-section/size-section.tsx +18 -9
- package/src/components/style-sections/spacing-section/spacing-section.tsx +1 -1
- package/src/components/style-sections/typography-section/font-weight-field.tsx +3 -3
- package/src/dynamics/components/dynamic-selection-control.tsx +12 -3
- package/src/dynamics/components/dynamic-selection.tsx +1 -1
- package/src/dynamics/hooks/use-prop-dynamic-action.tsx +1 -1
- package/src/styles-inheritance/create-snapshots-manager.ts +179 -0
- package/src/styles-inheritance/create-styles-inheritance.ts +50 -0
- package/src/styles-inheritance/types.ts +42 -0
- package/src/styles-inheritance/utils.ts +10 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@elementor/editor-editing-panel",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.16.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"author": "Elementor Team",
|
|
6
6
|
"homepage": "https://elementor.com/",
|
|
@@ -39,23 +39,23 @@
|
|
|
39
39
|
"dev": "tsup --config=../../tsup.dev.ts"
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@elementor/editor": "0.18.
|
|
43
|
-
"@elementor/editor-controls": "0.
|
|
44
|
-
"@elementor/editor-elements": "0.
|
|
45
|
-
"@elementor/editor-panels": "0.12.
|
|
46
|
-
"@elementor/editor-props": "0.9.
|
|
47
|
-
"@elementor/editor-responsive": "0.13.
|
|
48
|
-
"@elementor/editor-styles": "0.
|
|
49
|
-
"@elementor/editor-styles-repository": "0.7.
|
|
42
|
+
"@elementor/editor": "0.18.1",
|
|
43
|
+
"@elementor/editor-controls": "0.14.0",
|
|
44
|
+
"@elementor/editor-elements": "0.6.0",
|
|
45
|
+
"@elementor/editor-panels": "0.12.1",
|
|
46
|
+
"@elementor/editor-props": "0.9.3",
|
|
47
|
+
"@elementor/editor-responsive": "0.13.1",
|
|
48
|
+
"@elementor/editor-styles": "0.6.0",
|
|
49
|
+
"@elementor/editor-styles-repository": "0.7.3",
|
|
50
50
|
"@elementor/editor-ui": "0.4.0",
|
|
51
|
-
"@elementor/editor-v1-adapters": "0.10.
|
|
51
|
+
"@elementor/editor-v1-adapters": "0.10.1",
|
|
52
52
|
"@elementor/icons": "1.31.0",
|
|
53
53
|
"@elementor/locations": "0.7.6",
|
|
54
54
|
"@elementor/menus": "0.1.3",
|
|
55
55
|
"@elementor/schema": "0.1.2",
|
|
56
56
|
"@elementor/session": "0.1.0",
|
|
57
57
|
"@elementor/ui": "1.26.0",
|
|
58
|
-
"@elementor/utils": "0.
|
|
58
|
+
"@elementor/utils": "0.4.0",
|
|
59
59
|
"@wordpress/i18n": "^5.13.0"
|
|
60
60
|
},
|
|
61
61
|
"peerDependencies": {
|
|
@@ -40,7 +40,7 @@ export function CssClassMenu( { styleId, provider, popupState, handleRename, anc
|
|
|
40
40
|
{ /* It has to be an array since MUI menu doesn't accept a Fragment as a child, and wrapping the items with an HTML element disrupts keyboard navigation */ }
|
|
41
41
|
{ getMenuItemsByProvider( { provider, styleId, handleRename, closeMenu: popupState.close } ) }
|
|
42
42
|
<ListSubheader sx={ { typography: 'caption', color: 'text.secondary', pb: 0.5, pt: 1 } }>
|
|
43
|
-
{ __( 'Pseudo
|
|
43
|
+
{ __( 'Pseudo classes', 'elementor' ) }
|
|
44
44
|
</ListSubheader>
|
|
45
45
|
{ STATES.map( ( state ) => {
|
|
46
46
|
return <StateMenuItem key={ state } state={ state } styleId={ styleId } />;
|
|
@@ -60,7 +60,7 @@ export function CssClassSelector() {
|
|
|
60
60
|
<Stack gap={ 1 } p={ 2 }>
|
|
61
61
|
<Stack direction="row" gap={ 1 } alignItems="center" justifyContent="space-between">
|
|
62
62
|
<Typography component="label" variant="caption" htmlFor={ ID }>
|
|
63
|
-
{ __( 'CSS
|
|
63
|
+
{ __( 'CSS classes', 'elementor' ) }
|
|
64
64
|
</Typography>
|
|
65
65
|
<Stack direction="row" gap={ 1 }>
|
|
66
66
|
<ClassSelectorActionsSlot />
|
|
@@ -130,7 +130,7 @@ const FlexCustomField = () => (
|
|
|
130
130
|
<ControlLabel>{ __( 'Basis', 'elementor' ) }</ControlLabel>
|
|
131
131
|
</Grid>
|
|
132
132
|
<Grid item xs={ 6 } sx={ { display: 'flex', justifyContent: 'end' } }>
|
|
133
|
-
<SizeControl />
|
|
133
|
+
<SizeControl extendedValues={ [ 'auto' ] } />
|
|
134
134
|
</Grid>
|
|
135
135
|
</Grid>
|
|
136
136
|
</StylesField>
|
|
@@ -38,7 +38,7 @@ const DimensionField = ( { side, label }: { side: Side; label: string } ) => {
|
|
|
38
38
|
</Grid>
|
|
39
39
|
<Grid item xs={ 12 }>
|
|
40
40
|
<StylesField bind={ side }>
|
|
41
|
-
<SizeControl startIcon={ sideIcons[ side ] } />
|
|
41
|
+
<SizeControl startIcon={ sideIcons[ side ] } extendedValues={ [ 'auto' ] } />
|
|
42
42
|
</StylesField>
|
|
43
43
|
</Grid>
|
|
44
44
|
</Grid>
|
|
@@ -10,7 +10,7 @@ export const ZIndexField = () => {
|
|
|
10
10
|
<StylesField bind="z-index">
|
|
11
11
|
<Grid container gap={ 2 } alignItems="center" flexWrap="nowrap">
|
|
12
12
|
<Grid item xs={ 6 }>
|
|
13
|
-
<ControlLabel>{ __( 'Z-
|
|
13
|
+
<ControlLabel>{ __( 'Z-index', 'elementor' ) }</ControlLabel>
|
|
14
14
|
</Grid>
|
|
15
15
|
<Grid item xs={ 6 }>
|
|
16
16
|
<NumberControl />
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import { ControlLabel, SizeControl } from '@elementor/editor-controls';
|
|
2
|
+
import { ControlLabel, type ExtendedValue, SizeControl } from '@elementor/editor-controls';
|
|
3
3
|
import { Grid, Stack } from '@elementor/ui';
|
|
4
4
|
import { __ } from '@wordpress/i18n';
|
|
5
5
|
|
|
@@ -13,26 +13,34 @@ export const SizeSection = () => {
|
|
|
13
13
|
<SectionContent>
|
|
14
14
|
<Grid container gap={ 2 } flexWrap="nowrap">
|
|
15
15
|
<Grid item xs={ 6 }>
|
|
16
|
-
<SizeField bind="width" label={ __( 'Width', 'elementor' ) } />
|
|
16
|
+
<SizeField bind="width" label={ __( 'Width', 'elementor' ) } extendedValues={ [ 'auto' ] } />
|
|
17
17
|
</Grid>
|
|
18
18
|
<Grid item xs={ 6 }>
|
|
19
|
-
<SizeField bind="height" label={ __( 'Height', 'elementor' ) } />
|
|
19
|
+
<SizeField bind="height" label={ __( 'Height', 'elementor' ) } extendedValues={ [ 'auto' ] } />
|
|
20
20
|
</Grid>
|
|
21
21
|
</Grid>
|
|
22
22
|
<Grid container gap={ 2 } flexWrap="nowrap">
|
|
23
23
|
<Grid item xs={ 6 }>
|
|
24
|
-
<SizeField
|
|
24
|
+
<SizeField
|
|
25
|
+
bind="min-width"
|
|
26
|
+
label={ __( 'Min width', 'elementor' ) }
|
|
27
|
+
extendedValues={ [ 'auto' ] }
|
|
28
|
+
/>
|
|
25
29
|
</Grid>
|
|
26
30
|
<Grid item xs={ 6 }>
|
|
27
|
-
<SizeField
|
|
31
|
+
<SizeField
|
|
32
|
+
bind="min-height"
|
|
33
|
+
label={ __( 'Min height', 'elementor' ) }
|
|
34
|
+
extendedValues={ [ 'auto' ] }
|
|
35
|
+
/>
|
|
28
36
|
</Grid>
|
|
29
37
|
</Grid>
|
|
30
38
|
<Grid container gap={ 2 } flexWrap="nowrap">
|
|
31
39
|
<Grid item xs={ 6 }>
|
|
32
|
-
<SizeField bind="max-width" label={ __( 'Max
|
|
40
|
+
<SizeField bind="max-width" label={ __( 'Max width', 'elementor' ) } />
|
|
33
41
|
</Grid>
|
|
34
42
|
<Grid item xs={ 6 }>
|
|
35
|
-
<SizeField bind="max-height" label={ __( 'Max
|
|
43
|
+
<SizeField bind="max-height" label={ __( 'Max height', 'elementor' ) } />
|
|
36
44
|
</Grid>
|
|
37
45
|
</Grid>
|
|
38
46
|
<PanelDivider />
|
|
@@ -46,9 +54,10 @@ export const SizeSection = () => {
|
|
|
46
54
|
type ControlProps = {
|
|
47
55
|
bind: StylesFieldProps[ 'bind' ];
|
|
48
56
|
label: string;
|
|
57
|
+
extendedValues?: ExtendedValue[];
|
|
49
58
|
};
|
|
50
59
|
|
|
51
|
-
const SizeField = ( { label, bind }: ControlProps ) => {
|
|
60
|
+
const SizeField = ( { label, bind, extendedValues }: ControlProps ) => {
|
|
52
61
|
return (
|
|
53
62
|
<StylesField bind={ bind }>
|
|
54
63
|
<Grid container gap={ 1 } alignItems="center">
|
|
@@ -56,7 +65,7 @@ const SizeField = ( { label, bind }: ControlProps ) => {
|
|
|
56
65
|
<ControlLabel>{ label }</ControlLabel>
|
|
57
66
|
</Grid>
|
|
58
67
|
<Grid item xs={ 12 }>
|
|
59
|
-
<SizeControl />
|
|
68
|
+
<SizeControl extendedValues={ extendedValues } />
|
|
60
69
|
</Grid>
|
|
61
70
|
</Grid>
|
|
62
71
|
</StylesField>
|
|
@@ -14,7 +14,7 @@ export const SpacingSection = () => {
|
|
|
14
14
|
</StylesField>
|
|
15
15
|
<PanelDivider />
|
|
16
16
|
<StylesField bind={ 'margin' }>
|
|
17
|
-
<LinkedDimensionsControl label={ __( 'Margin', 'elementor' ) } />
|
|
17
|
+
<LinkedDimensionsControl label={ __( 'Margin', 'elementor' ) } extendedValues={ [ 'auto' ] } />
|
|
18
18
|
</StylesField>
|
|
19
19
|
</SectionContent>
|
|
20
20
|
);
|
|
@@ -7,13 +7,13 @@ import { StylesField } from '../../../controls-registry/styles-field';
|
|
|
7
7
|
|
|
8
8
|
const fontWeightOptions = [
|
|
9
9
|
{ value: '100', label: __( '100 - Thin', 'elementor' ) },
|
|
10
|
-
{ value: '200', label: __( '200 - Extra
|
|
10
|
+
{ value: '200', label: __( '200 - Extra light', 'elementor' ) },
|
|
11
11
|
{ value: '300', label: __( '300 - Light', 'elementor' ) },
|
|
12
12
|
{ value: '400', label: __( '400 - Normal', 'elementor' ) },
|
|
13
13
|
{ value: '500', label: __( '500 - Medium', 'elementor' ) },
|
|
14
|
-
{ value: '600', label: __( '600 - Semi
|
|
14
|
+
{ value: '600', label: __( '600 - Semi bold', 'elementor' ) },
|
|
15
15
|
{ value: '700', label: __( '700 - Bold', 'elementor' ) },
|
|
16
|
-
{ value: '800', label: __( '800 - Extra
|
|
16
|
+
{ value: '800', label: __( '800 - Extra bold', 'elementor' ) },
|
|
17
17
|
{ value: '900', label: __( '900 - Black', 'elementor' ) },
|
|
18
18
|
];
|
|
19
19
|
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
bindTrigger,
|
|
9
9
|
Box,
|
|
10
10
|
Divider,
|
|
11
|
+
Grid,
|
|
11
12
|
IconButton,
|
|
12
13
|
Paper,
|
|
13
14
|
Popover,
|
|
@@ -83,7 +84,7 @@ export const DynamicSelectionControl = () => {
|
|
|
83
84
|
<Stack>
|
|
84
85
|
<Stack direction="row" alignItems="center" pl={ 1.5 } pr={ 0.5 } py={ 1.5 }>
|
|
85
86
|
<DatabaseIcon fontSize={ SIZE } sx={ { mr: 0.5 } } />
|
|
86
|
-
<Typography variant="subtitle2">{ __( 'Dynamic
|
|
87
|
+
<Typography variant="subtitle2">{ __( 'Dynamic tags', 'elementor' ) }</Typography>
|
|
87
88
|
<IconButton size={ SIZE } sx={ { ml: 'auto' } } onClick={ selectionPopoverState.close }>
|
|
88
89
|
<XIcon fontSize={ SIZE } />
|
|
89
90
|
</IconButton>
|
|
@@ -177,8 +178,16 @@ const Control = ( { control }: { control: Control[ 'value' ] } ) => {
|
|
|
177
178
|
|
|
178
179
|
return (
|
|
179
180
|
<DynamicControl bind={ control.bind }>
|
|
180
|
-
|
|
181
|
-
|
|
181
|
+
<Grid container gap={ 1 }>
|
|
182
|
+
{ control.label ? (
|
|
183
|
+
<Grid item xs={ 12 }>
|
|
184
|
+
<ControlLabel>{ control.label }</ControlLabel>
|
|
185
|
+
</Grid>
|
|
186
|
+
) : null }
|
|
187
|
+
<Grid item xs={ 12 }>
|
|
188
|
+
<BaseControl type={ control.type as ControlType } props={ control.props } />
|
|
189
|
+
</Grid>
|
|
190
|
+
</Grid>
|
|
182
191
|
</DynamicControl>
|
|
183
192
|
);
|
|
184
193
|
};
|
|
@@ -70,7 +70,7 @@ export const DynamicSelection = ( { onSelect }: DynamicSelectionProps ) => {
|
|
|
70
70
|
size={ SIZE }
|
|
71
71
|
value={ searchValue }
|
|
72
72
|
onChange={ handleSearch }
|
|
73
|
-
placeholder={ __( 'Search dynamic
|
|
73
|
+
placeholder={ __( 'Search dynamic tags…', 'elementor' ) }
|
|
74
74
|
InputProps={ {
|
|
75
75
|
startAdornment: (
|
|
76
76
|
<InputAdornment position="start">
|
|
@@ -15,7 +15,7 @@ export const usePropDynamicAction = (): PopoverActionProps => {
|
|
|
15
15
|
return {
|
|
16
16
|
visible,
|
|
17
17
|
icon: DatabaseIcon,
|
|
18
|
-
title: __( 'Dynamic
|
|
18
|
+
title: __( 'Dynamic tags', 'elementor' ),
|
|
19
19
|
popoverContent: ( { closePopover } ) => <DynamicSelection onSelect={ closePopover } />,
|
|
20
20
|
};
|
|
21
21
|
};
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import { type BreakpointId, type BreakpointNode } from '@elementor/editor-responsive';
|
|
2
|
+
import { type StyleDefinitionState } from '@elementor/editor-styles';
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
type BreakpointsInheritancePath,
|
|
6
|
+
type BreakpointsStatesSnapshotsMapping,
|
|
7
|
+
type BreakpointStatesSlotsMapping,
|
|
8
|
+
type SnapshotPropValue,
|
|
9
|
+
type StyleInheritanceMetaProps,
|
|
10
|
+
type StylesInheritanceSnapshot,
|
|
11
|
+
type StylesInheritanceSnapshotGetter,
|
|
12
|
+
type StylesInheritanceSnapshotsSlot,
|
|
13
|
+
type StyleVariantWithId,
|
|
14
|
+
} from './types';
|
|
15
|
+
import { DEFAULT_STATE, getBreakpointKey, getStateKey } from './utils';
|
|
16
|
+
|
|
17
|
+
export function createSnapshotsManager(
|
|
18
|
+
getStylesByMeta: ( meta: StyleInheritanceMetaProps ) => StyleVariantWithId[],
|
|
19
|
+
breakpointsRoot: BreakpointNode
|
|
20
|
+
): StylesInheritanceSnapshotGetter {
|
|
21
|
+
const breakpointsInheritancePaths = makeBreakpointsInheritancePaths( breakpointsRoot );
|
|
22
|
+
const allBreakpointStatesSnapshots: BreakpointsStatesSnapshotsMapping = {};
|
|
23
|
+
|
|
24
|
+
const buildMissingSnapshotsForBreakpoint = (
|
|
25
|
+
currentBreakpointId: BreakpointId | null,
|
|
26
|
+
parentBreakpoint: BreakpointStatesSlotsMapping | undefined,
|
|
27
|
+
state: StyleDefinitionState
|
|
28
|
+
) => {
|
|
29
|
+
const currentBreakpointKey = getBreakpointKey( currentBreakpointId );
|
|
30
|
+
const stateKey = getStateKey( state );
|
|
31
|
+
|
|
32
|
+
if ( ! allBreakpointStatesSnapshots[ currentBreakpointKey ] ) {
|
|
33
|
+
allBreakpointStatesSnapshots[ currentBreakpointKey ] = {
|
|
34
|
+
[ DEFAULT_STATE ]: buildStateSnapshotSlot(
|
|
35
|
+
getStylesByMeta( { breakpoint: currentBreakpointId, state: null } ),
|
|
36
|
+
parentBreakpoint,
|
|
37
|
+
{},
|
|
38
|
+
null
|
|
39
|
+
),
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if ( state && ! allBreakpointStatesSnapshots[ currentBreakpointKey ][ stateKey ] ) {
|
|
44
|
+
allBreakpointStatesSnapshots[ currentBreakpointKey ][ stateKey ] = buildStateSnapshotSlot(
|
|
45
|
+
getStylesByMeta( { breakpoint: currentBreakpointId, state } ),
|
|
46
|
+
parentBreakpoint,
|
|
47
|
+
allBreakpointStatesSnapshots[ currentBreakpointKey ],
|
|
48
|
+
state
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
return ( meta: StyleInheritanceMetaProps ) => {
|
|
54
|
+
const { breakpoint, state } = meta;
|
|
55
|
+
|
|
56
|
+
const stateKey = getStateKey( state );
|
|
57
|
+
const breakpointKey = getBreakpointKey( breakpoint );
|
|
58
|
+
|
|
59
|
+
if ( allBreakpointStatesSnapshots[ breakpointKey ]?.[ stateKey ] ) {
|
|
60
|
+
// snapshot was already made for this breakpoint+state
|
|
61
|
+
return allBreakpointStatesSnapshots[ breakpointKey ][ stateKey ].snapshot;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const breakpointsChain = [ ...breakpointsInheritancePaths[ breakpointKey ], breakpoint ];
|
|
65
|
+
|
|
66
|
+
breakpointsChain.forEach( ( breakpointId, index ) => {
|
|
67
|
+
const parentBreakpointId = index > 0 ? breakpointsChain[ index - 1 ] : null;
|
|
68
|
+
|
|
69
|
+
buildMissingSnapshotsForBreakpoint(
|
|
70
|
+
breakpointId,
|
|
71
|
+
parentBreakpointId ? allBreakpointStatesSnapshots[ parentBreakpointId ] : undefined,
|
|
72
|
+
state
|
|
73
|
+
);
|
|
74
|
+
} );
|
|
75
|
+
|
|
76
|
+
return allBreakpointStatesSnapshots[ breakpointKey ]?.[ stateKey ]?.snapshot;
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* builds a mapping of each breakpoint to its inheritance chain, e.g. -
|
|
82
|
+
* desktop: [],
|
|
83
|
+
* tablet: [ 'desktop' ],
|
|
84
|
+
* mobile: [ 'desktop', 'tablet' ]
|
|
85
|
+
* @param root
|
|
86
|
+
*/
|
|
87
|
+
function makeBreakpointsInheritancePaths( root: BreakpointNode ): BreakpointsInheritancePath {
|
|
88
|
+
const breakpoints: Partial< BreakpointsInheritancePath > = {};
|
|
89
|
+
|
|
90
|
+
const traverse = ( node: BreakpointNode, parent?: BreakpointId[] ) => {
|
|
91
|
+
const { id, children } = node;
|
|
92
|
+
|
|
93
|
+
breakpoints[ id ] = parent ? [ ...parent ] : [];
|
|
94
|
+
|
|
95
|
+
children?.forEach( ( child ) => {
|
|
96
|
+
traverse( child, [ ...( breakpoints[ id ] ?? [] ), id ] );
|
|
97
|
+
} );
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
traverse( root );
|
|
101
|
+
|
|
102
|
+
return breakpoints as BreakpointsInheritancePath;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// creates a snapshot slot for a specific breakpoint and state
|
|
106
|
+
function buildStateSnapshotSlot(
|
|
107
|
+
styles: StyleVariantWithId[],
|
|
108
|
+
parentBreakpoint: BreakpointStatesSlotsMapping | undefined,
|
|
109
|
+
currentBreakpoint: BreakpointStatesSlotsMapping,
|
|
110
|
+
state: StyleDefinitionState
|
|
111
|
+
): StylesInheritanceSnapshotsSlot {
|
|
112
|
+
const initialSlot = buildInitialSnapshotFromStyles( styles );
|
|
113
|
+
|
|
114
|
+
if ( ! state ) {
|
|
115
|
+
return {
|
|
116
|
+
snapshot: mergeSnapshots( [ initialSlot.snapshot, parentBreakpoint?.[ DEFAULT_STATE ]?.snapshot ] ),
|
|
117
|
+
stateSpecificSnapshot: undefined,
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return {
|
|
122
|
+
snapshot: mergeSnapshots( [
|
|
123
|
+
initialSlot.snapshot,
|
|
124
|
+
parentBreakpoint?.[ state ]?.stateSpecificSnapshot,
|
|
125
|
+
currentBreakpoint[ DEFAULT_STATE ]?.snapshot,
|
|
126
|
+
] ),
|
|
127
|
+
stateSpecificSnapshot: mergeSnapshots( [
|
|
128
|
+
initialSlot.stateSpecificSnapshot,
|
|
129
|
+
parentBreakpoint?.[ state ]?.stateSpecificSnapshot,
|
|
130
|
+
] ),
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// creates an initial snapshot based on the passed style variants only
|
|
135
|
+
function buildInitialSnapshotFromStyles( styles: StyleVariantWithId[] ): StylesInheritanceSnapshotsSlot {
|
|
136
|
+
const snapshot: StylesInheritanceSnapshot = {};
|
|
137
|
+
|
|
138
|
+
styles.forEach( ( styleVariantWithId ) => {
|
|
139
|
+
const {
|
|
140
|
+
styleVariant: { props },
|
|
141
|
+
} = styleVariantWithId;
|
|
142
|
+
|
|
143
|
+
Object.entries( props ).forEach( ( [ key, value ] ) => {
|
|
144
|
+
if ( ! snapshot[ key ] ) {
|
|
145
|
+
snapshot[ key ] = [];
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
const snapshotPropValue: SnapshotPropValue = {
|
|
149
|
+
...styleVariantWithId,
|
|
150
|
+
value,
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
snapshot[ key ].push( snapshotPropValue );
|
|
154
|
+
} );
|
|
155
|
+
} );
|
|
156
|
+
|
|
157
|
+
return {
|
|
158
|
+
snapshot,
|
|
159
|
+
stateSpecificSnapshot: snapshot,
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// merge previous snapshot into the current one - first value of each prop is the strongest
|
|
164
|
+
function mergeSnapshots( snapshots: ( StylesInheritanceSnapshot | undefined )[] ) {
|
|
165
|
+
const snapshot: StylesInheritanceSnapshot = {};
|
|
166
|
+
|
|
167
|
+
snapshots.filter( Boolean ).forEach( ( currentSnapshot ) =>
|
|
168
|
+
Object.entries( currentSnapshot as StylesInheritanceSnapshot ).forEach( ( [ key, values ] ) => {
|
|
169
|
+
if ( ! snapshot[ key ] ) {
|
|
170
|
+
snapshot[ key ] = [];
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// concatenate the previous snapshot's prop values to the current ones
|
|
174
|
+
snapshot[ key ] = snapshot[ key ].concat( values );
|
|
175
|
+
} )
|
|
176
|
+
);
|
|
177
|
+
|
|
178
|
+
return snapshot;
|
|
179
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { type BreakpointNode } from '@elementor/editor-responsive';
|
|
2
|
+
import { type StyleDefinition } from '@elementor/editor-styles';
|
|
3
|
+
|
|
4
|
+
import { createSnapshotsManager } from './create-snapshots-manager';
|
|
5
|
+
import { type BreakpointsStatesStyles, type StyleInheritanceMetaProps, type StylesInheritanceSnapshot } from './types';
|
|
6
|
+
import { getBreakpointKey, getStateKey } from './utils';
|
|
7
|
+
|
|
8
|
+
export function createStylesInheritance(
|
|
9
|
+
styleDefs: StyleDefinition[],
|
|
10
|
+
breakpointsRoot: BreakpointNode
|
|
11
|
+
): ( meta: StyleInheritanceMetaProps ) => StylesInheritanceSnapshot | undefined {
|
|
12
|
+
const styleVariantsByMeta = buildStyleVariantsByMetaMapping( styleDefs );
|
|
13
|
+
|
|
14
|
+
const getStyles = ( { breakpoint, state }: StyleInheritanceMetaProps ) =>
|
|
15
|
+
styleVariantsByMeta?.[ getBreakpointKey( breakpoint ) ]?.[ getStateKey( state ) ] ?? [];
|
|
16
|
+
|
|
17
|
+
return createSnapshotsManager( getStyles, breakpointsRoot );
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function buildStyleVariantsByMetaMapping( styleDefs: StyleDefinition[] ): BreakpointsStatesStyles {
|
|
21
|
+
const breakpointStateSlots: BreakpointsStatesStyles = {};
|
|
22
|
+
|
|
23
|
+
styleDefs.forEach( ( styleDef ) => {
|
|
24
|
+
// iterate over each style definition's variants and place them in the corresponding breakpoint's base or state styles
|
|
25
|
+
styleDef.variants.forEach( ( styleVariant ) => {
|
|
26
|
+
const { meta } = styleVariant;
|
|
27
|
+
const { state, breakpoint } = meta;
|
|
28
|
+
|
|
29
|
+
const breakpointKey = getBreakpointKey( breakpoint );
|
|
30
|
+
const stateKey = getStateKey( state );
|
|
31
|
+
|
|
32
|
+
if ( ! breakpointStateSlots[ breakpointKey ] ) {
|
|
33
|
+
breakpointStateSlots[ breakpointKey ] = {};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const breakpointNode = breakpointStateSlots[ breakpointKey ];
|
|
37
|
+
|
|
38
|
+
if ( ! breakpointNode[ stateKey ] ) {
|
|
39
|
+
breakpointNode[ stateKey ] = [];
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
breakpointNode[ stateKey ].push( {
|
|
43
|
+
styleId: styleDef.id,
|
|
44
|
+
styleVariant,
|
|
45
|
+
} );
|
|
46
|
+
} );
|
|
47
|
+
} );
|
|
48
|
+
|
|
49
|
+
return breakpointStateSlots;
|
|
50
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { type PropValue } from '@elementor/editor-props';
|
|
2
|
+
import { type BreakpointId } from '@elementor/editor-responsive';
|
|
3
|
+
import { type StyleDefinitionState, type StyleDefinitionVariant } from '@elementor/editor-styles';
|
|
4
|
+
|
|
5
|
+
export type StyleDefinitionStateWithNormal = NonNullable< StyleDefinitionState > | 'normal';
|
|
6
|
+
|
|
7
|
+
type StatesMapping< T > = Partial< Record< StyleDefinitionStateWithNormal, T > >;
|
|
8
|
+
|
|
9
|
+
export type StyleVariantWithId = {
|
|
10
|
+
styleId: string;
|
|
11
|
+
styleVariant: StyleDefinitionVariant;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export type SnapshotPropValue = StyleVariantWithId & {
|
|
15
|
+
value: PropValue;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export type StylesInheritanceSnapshot = Record< string, SnapshotPropValue[] >;
|
|
19
|
+
|
|
20
|
+
export type StylesInheritanceSnapshotsSlot = {
|
|
21
|
+
snapshot?: StylesInheritanceSnapshot;
|
|
22
|
+
stateSpecificSnapshot?: StylesInheritanceSnapshot; // with only prop values of the current state, used for inheritance - e.g. mobile-hover inherits first from tablet-hover specific snapshot
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export type BreakpointStatesSlotsMapping = StatesMapping< StylesInheritanceSnapshotsSlot >;
|
|
26
|
+
|
|
27
|
+
export type BreakpointsStatesSnapshotsMapping = Partial< Record< BreakpointId, BreakpointStatesSlotsMapping > >;
|
|
28
|
+
|
|
29
|
+
type BreakpointStatesStyles = StatesMapping< StyleVariantWithId[] >;
|
|
30
|
+
|
|
31
|
+
export type BreakpointsStatesStyles = Partial< Record< BreakpointId, Partial< BreakpointStatesStyles > > >;
|
|
32
|
+
|
|
33
|
+
export type BreakpointsInheritancePath = Record< BreakpointId, BreakpointId[] >;
|
|
34
|
+
|
|
35
|
+
export type StyleInheritanceMetaProps = {
|
|
36
|
+
breakpoint: BreakpointId | null;
|
|
37
|
+
state: StyleDefinitionState;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export type StylesInheritanceSnapshotGetter = (
|
|
41
|
+
meta: StyleInheritanceMetaProps
|
|
42
|
+
) => StylesInheritanceSnapshot | undefined;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type BreakpointId } from '@elementor/editor-responsive';
|
|
2
|
+
import { type StyleDefinitionState } from '@elementor/editor-styles';
|
|
3
|
+
|
|
4
|
+
export const DEFAULT_STATE = 'normal';
|
|
5
|
+
|
|
6
|
+
const DEFAULT_BREAKPOINT = 'desktop';
|
|
7
|
+
|
|
8
|
+
export const getStateKey = ( state: StyleDefinitionState ) => state ?? DEFAULT_STATE;
|
|
9
|
+
|
|
10
|
+
export const getBreakpointKey = ( breakpoint: BreakpointId | null ): BreakpointId => breakpoint ?? DEFAULT_BREAKPOINT;
|