@elementor/editor-editing-panel 4.1.0 → 4.2.0-839
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +169 -1
- package/dist/index.d.ts +169 -1
- package/dist/index.js +1301 -857
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1145 -683
- package/dist/index.mjs.map +1 -1
- package/package.json +25 -22
- package/src/components/css-classes/use-apply-and-unapply-class.ts +10 -0
- package/src/components/design-system-import/components/conflict-options.tsx +67 -0
- package/src/components/design-system-import/components/trigger-button.tsx +33 -0
- package/src/components/design-system-import/hooks/use-dialog-state.ts +24 -0
- package/src/components/design-system-import/hooks/use-import-request.ts +38 -0
- package/src/components/design-system-import/import-design-system-dialog.tsx +89 -0
- package/src/components/design-system-import/import-notifications.tsx +57 -0
- package/src/components/design-system-import/types.ts +1 -0
- package/src/components/promotions/init.tsx +6 -7
- package/src/components/section-content.tsx +9 -2
- package/src/components/style-sections/layout-section/align-self-grid-child-field.tsx +74 -0
- package/src/components/style-sections/layout-section/display-field.tsx +21 -8
- package/src/components/style-sections/layout-section/grid-auto-flow-field.tsx +102 -0
- package/src/components/style-sections/layout-section/grid-justify-items-field.tsx +58 -0
- package/src/components/style-sections/layout-section/grid-size-field.tsx +96 -0
- package/src/components/style-sections/layout-section/grid-span-field.tsx +78 -0
- package/src/components/style-sections/layout-section/layout-section.tsx +50 -2
- package/src/components/style-sections/position-section/position-field.tsx +2 -6
- package/src/components/style-sections/position-section/position-section.tsx +82 -85
- package/src/components/style-sections/position-section/z-index-field.tsx +29 -3
- package/src/components/style-tab.tsx +3 -0
- package/src/contexts/styles-inheritance-context.tsx +16 -2
- package/src/controls-registry/conditional-field.tsx +84 -7
- package/src/controls-registry/controls-registry.tsx +16 -0
- package/src/hooks/use-styles-fields.ts +1 -1
- package/src/utils/prop-dependency-utils.ts +88 -12
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { NumberControl } from '@elementor/editor-controls';
|
|
3
|
+
import { InfoCircleFilledIcon } from '@elementor/icons';
|
|
4
|
+
import { Alert, AlertTitle, Box, Infotip } from '@elementor/ui';
|
|
3
5
|
import { __ } from '@wordpress/i18n';
|
|
4
6
|
|
|
5
7
|
import { StylesField } from '../../../controls-registry/styles-field';
|
|
@@ -7,12 +9,36 @@ import { StylesFieldLayout } from '../../styles-field-layout';
|
|
|
7
9
|
|
|
8
10
|
const Z_INDEX_LABEL = __( 'Z-index', 'elementor' );
|
|
9
11
|
|
|
10
|
-
export const ZIndexField = () => {
|
|
11
|
-
|
|
12
|
+
export const ZIndexField = ( { disabled }: { disabled?: boolean } ) => {
|
|
13
|
+
const StyleField = (
|
|
12
14
|
<StylesField bind="z-index" propDisplayName={ Z_INDEX_LABEL }>
|
|
13
15
|
<StylesFieldLayout label={ Z_INDEX_LABEL }>
|
|
14
|
-
<NumberControl />
|
|
16
|
+
<NumberControl disabled={ disabled } />
|
|
15
17
|
</StylesFieldLayout>
|
|
16
18
|
</StylesField>
|
|
17
19
|
);
|
|
20
|
+
|
|
21
|
+
const content = (
|
|
22
|
+
<Alert color="secondary" icon={ <InfoCircleFilledIcon /> } size="small">
|
|
23
|
+
<AlertTitle>{ __( 'Z-index', 'elementor' ) }</AlertTitle>
|
|
24
|
+
<Box component="span">
|
|
25
|
+
{ __(
|
|
26
|
+
'z-index only works on positioned elements. Change position to relative, absolute, or fixed to enable layering.',
|
|
27
|
+
'elementor'
|
|
28
|
+
) }
|
|
29
|
+
</Box>
|
|
30
|
+
</Alert>
|
|
31
|
+
);
|
|
32
|
+
return disabled ? (
|
|
33
|
+
<Infotip
|
|
34
|
+
placement="right"
|
|
35
|
+
content={ content }
|
|
36
|
+
color="secondary"
|
|
37
|
+
slotProps={ { popper: { sx: { width: 300 } } } }
|
|
38
|
+
>
|
|
39
|
+
<Box>{ StyleField }</Box>
|
|
40
|
+
</Infotip>
|
|
41
|
+
) : (
|
|
42
|
+
<>{ StyleField }</>
|
|
43
|
+
);
|
|
18
44
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import { createContext, type PropsWithChildren, useContext } from 'react';
|
|
2
|
+
import { createContext, type PropsWithChildren, useContext, useMemo } from 'react';
|
|
3
3
|
import { getWidgetsCache } from '@elementor/editor-elements';
|
|
4
|
-
import { classesPropTypeUtil, type ClassesPropValue } from '@elementor/editor-props';
|
|
4
|
+
import { classesPropTypeUtil, type ClassesPropValue, type PropValue } from '@elementor/editor-props';
|
|
5
5
|
import { getBreakpointsTree } from '@elementor/editor-responsive';
|
|
6
6
|
import { getStylesSchema } from '@elementor/editor-styles';
|
|
7
7
|
import { stylesRepository } from '@elementor/editor-styles-repository';
|
|
@@ -64,6 +64,20 @@ export function useStylesInheritanceChain( path: string[] ): SnapshotPropValue[]
|
|
|
64
64
|
return context.getInheritanceChain( snapshot, path, topLevelPropType );
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
+
const EMPTY_INHERITED_VALUES: Record< string, PropValue > = {};
|
|
68
|
+
|
|
69
|
+
export function useInheritedValues( propKeys: string[] ): Record< string, PropValue > {
|
|
70
|
+
const snapshot = useStylesInheritanceSnapshot();
|
|
71
|
+
|
|
72
|
+
return useMemo( () => {
|
|
73
|
+
if ( ! snapshot || propKeys.length === 0 ) {
|
|
74
|
+
return EMPTY_INHERITED_VALUES;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return Object.fromEntries( propKeys.map( ( key ) => [ key, snapshot[ key ]?.[ 0 ]?.value ?? null ] ) );
|
|
78
|
+
}, [ snapshot, propKeys ] );
|
|
79
|
+
}
|
|
80
|
+
|
|
67
81
|
const useAppliedStyles = () => {
|
|
68
82
|
const currentClassesProp = useClassesProp();
|
|
69
83
|
const baseStyles = useBaseStyles();
|
|
@@ -1,22 +1,99 @@
|
|
|
1
|
+
import { type FC, type ReactNode, useEffect, useRef } from 'react';
|
|
1
2
|
import { useBoundProp } from '@elementor/editor-controls';
|
|
2
|
-
import { isDependency, isDependencyMet, type PropKey, type PropType } from '@elementor/editor-props';
|
|
3
|
+
import { isDependency, isDependencyMet, type PropKey, type PropType, type PropValue } from '@elementor/editor-props';
|
|
3
4
|
|
|
5
|
+
import { useInheritedValues } from '../contexts/styles-inheritance-context';
|
|
4
6
|
import { useStylesFields } from '../hooks/use-styles-fields';
|
|
5
7
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
} > = ( { children } ) => {
|
|
9
|
-
const { propType } = useBoundProp();
|
|
8
|
+
type DepValues = Record< string, PropValue > | null;
|
|
9
|
+
|
|
10
|
+
export const ConditionalField: FC< { children: ReactNode } > = ( { children } ) => {
|
|
11
|
+
const { propType, value, resetValue } = useBoundProp();
|
|
10
12
|
|
|
11
13
|
const depList = getDependencies( propType );
|
|
12
14
|
|
|
13
|
-
const { values: depValues } = useStylesFields( depList );
|
|
15
|
+
const { values: depValues, setValues: setDepValues } = useStylesFields( depList );
|
|
16
|
+
const inheritedValues = useInheritedValues( depList );
|
|
17
|
+
|
|
18
|
+
const resolvedValues = resolveWithInherited( depValues, inheritedValues );
|
|
19
|
+
const isHidden = ! isDependencyMet( propType?.dependencies, resolvedValues ).isMet;
|
|
14
20
|
|
|
15
|
-
|
|
21
|
+
useSyncDepsWithInherited( { isHidden, depValues, value, inheritedValues, setDepValues, resetValue } );
|
|
16
22
|
|
|
17
23
|
return isHidden ? null : children;
|
|
18
24
|
};
|
|
19
25
|
|
|
26
|
+
function wasDepsCleared( prevDepValues: DepValues, depValues: DepValues ): boolean {
|
|
27
|
+
if ( ! prevDepValues ) {
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return Object.keys( prevDepValues ).some(
|
|
32
|
+
( key ) => prevDepValues[ key ] && ( ! depValues || ! depValues[ key ] )
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function useSyncDepsWithInherited( {
|
|
37
|
+
isHidden,
|
|
38
|
+
depValues,
|
|
39
|
+
value,
|
|
40
|
+
inheritedValues,
|
|
41
|
+
setDepValues,
|
|
42
|
+
resetValue,
|
|
43
|
+
}: {
|
|
44
|
+
isHidden: boolean;
|
|
45
|
+
depValues: DepValues;
|
|
46
|
+
value: PropValue;
|
|
47
|
+
inheritedValues: Record< string, PropValue >;
|
|
48
|
+
setDepValues: ( props: Record< string, PropValue >, options: { history: { propDisplayName: string } } ) => void;
|
|
49
|
+
resetValue: () => void;
|
|
50
|
+
} ) {
|
|
51
|
+
const syncRef = useRef( { hasSynced: false, prevDepValues: depValues } );
|
|
52
|
+
|
|
53
|
+
useEffect( () => {
|
|
54
|
+
const { hasSynced, prevDepValues } = syncRef.current;
|
|
55
|
+
|
|
56
|
+
if (
|
|
57
|
+
( hasSynced && value && wasDepsCleared( prevDepValues, depValues ) ) ||
|
|
58
|
+
( isHidden && depValues && value )
|
|
59
|
+
) {
|
|
60
|
+
resetValue();
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if ( isHidden || ! value || ! depValues ) {
|
|
64
|
+
syncRef.current = { hasSynced: false, prevDepValues: depValues };
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if ( hasSynced ) {
|
|
69
|
+
syncRef.current.prevDepValues = depValues;
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
syncRef.current = { hasSynced: true, prevDepValues: depValues };
|
|
74
|
+
|
|
75
|
+
Object.entries( depValues ).forEach( ( [ key, depValue ] ) => {
|
|
76
|
+
const inherited = inheritedValues[ key ];
|
|
77
|
+
|
|
78
|
+
if ( ! depValue && inherited ) {
|
|
79
|
+
setDepValues( { [ key ]: inherited }, { history: { propDisplayName: key } } );
|
|
80
|
+
}
|
|
81
|
+
} );
|
|
82
|
+
}, [ isHidden, depValues, value, inheritedValues, setDepValues, resetValue ] );
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function resolveWithInherited( localValues: DepValues, inheritedValues: Record< string, PropValue > ): DepValues {
|
|
86
|
+
if ( ! localValues ) {
|
|
87
|
+
const hasInherited = Object.keys( inheritedValues ).length > 0;
|
|
88
|
+
|
|
89
|
+
return hasInherited ? { ...inheritedValues } : null;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return Object.fromEntries(
|
|
93
|
+
Object.entries( localValues ).map( ( [ key, val ] ) => [ key, val ?? inheritedValues[ key ] ?? null ] )
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
|
|
20
97
|
export function getDependencies( propType?: PropType ): PropKey[] {
|
|
21
98
|
if ( ! propType?.dependencies?.terms.length ) {
|
|
22
99
|
return [];
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
|
+
AttachmentTypeControl,
|
|
2
3
|
ChipsControl,
|
|
3
4
|
type ControlComponent,
|
|
5
|
+
DateRangeControl,
|
|
4
6
|
DateTimeControl,
|
|
5
7
|
EmailFormActionControl,
|
|
6
8
|
HtmlTagControl,
|
|
@@ -17,6 +19,7 @@ import {
|
|
|
17
19
|
SwitchControl,
|
|
18
20
|
TextAreaControl,
|
|
19
21
|
TextControl,
|
|
22
|
+
TimeRangeControl,
|
|
20
23
|
ToggleControl,
|
|
21
24
|
UrlControl,
|
|
22
25
|
VideoMediaControl,
|
|
@@ -24,6 +27,7 @@ import {
|
|
|
24
27
|
import { type ControlLayout } from '@elementor/editor-elements';
|
|
25
28
|
import {
|
|
26
29
|
booleanPropTypeUtil,
|
|
30
|
+
dateRangePropTypeUtil,
|
|
27
31
|
DateTimePropTypeUtil,
|
|
28
32
|
emailPropTypeUtil,
|
|
29
33
|
htmlV3PropTypeUtil,
|
|
@@ -37,6 +41,7 @@ import {
|
|
|
37
41
|
stringArrayPropTypeUtil,
|
|
38
42
|
stringPropTypeUtil,
|
|
39
43
|
svgSrcPropTypeUtil,
|
|
44
|
+
timeRangePropTypeUtil,
|
|
40
45
|
videoSrcPropTypeUtil,
|
|
41
46
|
} from '@elementor/editor-props';
|
|
42
47
|
|
|
@@ -69,6 +74,17 @@ const controlTypes = {
|
|
|
69
74
|
video: { component: VideoMediaControl, layout: 'full', propTypeUtil: videoSrcPropTypeUtil },
|
|
70
75
|
'inline-editing': { component: InlineEditingControl, layout: 'full', propTypeUtil: htmlV3PropTypeUtil },
|
|
71
76
|
email: { component: EmailFormActionControl, layout: 'custom', propTypeUtil: emailPropTypeUtil },
|
|
77
|
+
'date-range': {
|
|
78
|
+
component: DateRangeControl,
|
|
79
|
+
layout: 'custom',
|
|
80
|
+
propTypeUtil: dateRangePropTypeUtil,
|
|
81
|
+
},
|
|
82
|
+
'time-range': {
|
|
83
|
+
component: TimeRangeControl,
|
|
84
|
+
layout: 'custom',
|
|
85
|
+
propTypeUtil: timeRangePropTypeUtil,
|
|
86
|
+
},
|
|
87
|
+
'attachment-type': { component: AttachmentTypeControl, layout: 'custom', propTypeUtil: stringPropTypeUtil },
|
|
72
88
|
} as const satisfies ControlRegistry;
|
|
73
89
|
|
|
74
90
|
export type ControlType = keyof typeof controlTypes;
|
|
@@ -174,7 +174,7 @@ function useUndoableActions( {
|
|
|
174
174
|
}
|
|
175
175
|
|
|
176
176
|
function undo( _: UndoableUpdateStylePayload, { styleId, provider, prevProps }: UpdateStyleReturn ) {
|
|
177
|
-
provider.actions.updateProps?.( { id: styleId, meta, props: prevProps }, { elementId } );
|
|
177
|
+
provider.actions.updateProps?.( { id: styleId, meta, props: prevProps, mode: 'replace' }, { elementId } );
|
|
178
178
|
}
|
|
179
179
|
}, [ elementId, breakpoint, state, classesProp ] );
|
|
180
180
|
}
|
|
@@ -4,9 +4,12 @@ import {
|
|
|
4
4
|
extractValue,
|
|
5
5
|
isDependency,
|
|
6
6
|
isDependencyMet,
|
|
7
|
+
isOverridable,
|
|
8
|
+
isTransformable,
|
|
7
9
|
type Props,
|
|
8
10
|
type PropsSchema,
|
|
9
11
|
type PropType,
|
|
12
|
+
rewrapOverridableValue,
|
|
10
13
|
type TransformablePropValue,
|
|
11
14
|
} from '@elementor/editor-props';
|
|
12
15
|
import { getSessionStorageItem, removeSessionStorageItem, setSessionStorageItem } from '@elementor/session';
|
|
@@ -94,12 +97,19 @@ export function getUpdatedValues(
|
|
|
94
97
|
|
|
95
98
|
if ( ! testDependencies.previousValues.isMet ) {
|
|
96
99
|
const savedValue = retrievePreviousValueFromStorage< Value >( { path: dependency, elementId } );
|
|
100
|
+
const currentValue = extractValue( path, combinedValues, [], {
|
|
101
|
+
unwrapOverridableLeaf: false,
|
|
102
|
+
} ) as Value;
|
|
97
103
|
|
|
98
104
|
removePreviousValueFromStorage( { path: dependency, elementId } );
|
|
99
105
|
|
|
106
|
+
const restored = isCompatibleSavedValue( savedValue, currentValue )
|
|
107
|
+
? savedValue
|
|
108
|
+
: ( propType.default as Value );
|
|
109
|
+
|
|
100
110
|
return {
|
|
101
111
|
...newValues,
|
|
102
|
-
...updateValue( path,
|
|
112
|
+
...updateValue( path, restored, combinedValues ),
|
|
103
113
|
};
|
|
104
114
|
}
|
|
105
115
|
|
|
@@ -165,23 +175,88 @@ function evaluatePropType( props: {
|
|
|
165
175
|
|
|
166
176
|
function updateValue( path: string[], value: Value, values: Values ) {
|
|
167
177
|
const topPropKey = path[ 0 ];
|
|
168
|
-
const
|
|
178
|
+
const root: Values = { ...values };
|
|
169
179
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
180
|
+
let carry: Values = root;
|
|
181
|
+
|
|
182
|
+
for ( let index = 0; index < path.length; index++ ) {
|
|
183
|
+
const key = path[ index ];
|
|
184
|
+
const isLeaf = index === path.length - 1;
|
|
185
|
+
|
|
186
|
+
if ( isLeaf ) {
|
|
187
|
+
carry[ key ] = mergeLeafValue( carry[ key ], value );
|
|
188
|
+
break;
|
|
173
189
|
}
|
|
174
190
|
|
|
175
|
-
|
|
176
|
-
carry[ key ] = value ?? null;
|
|
191
|
+
const next = cloneDescent( carry[ key ] );
|
|
177
192
|
|
|
178
|
-
|
|
193
|
+
if ( ! next ) {
|
|
194
|
+
break;
|
|
179
195
|
}
|
|
180
196
|
|
|
181
|
-
|
|
182
|
-
|
|
197
|
+
carry[ key ] = next.replacement;
|
|
198
|
+
carry = next.descended;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
return { [ topPropKey ]: root[ topPropKey ] ?? null };
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
function cloneDescent( child: Value ): { replacement: Value; descended: Values } | null {
|
|
205
|
+
if ( ! child ) {
|
|
206
|
+
return null;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
if ( isOverridable( child ) ) {
|
|
210
|
+
const origin = child.value.origin_value;
|
|
211
|
+
|
|
212
|
+
if ( ! origin || ! isTransformable( origin ) ) {
|
|
213
|
+
return null;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
const descended: Values = { ...( origin.value as Values ) };
|
|
217
|
+
const replacement: Value = {
|
|
218
|
+
...child,
|
|
219
|
+
value: {
|
|
220
|
+
...child.value,
|
|
221
|
+
origin_value: { ...origin, value: descended },
|
|
222
|
+
},
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
return { replacement, descended };
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
if ( isTransformable( child ) ) {
|
|
229
|
+
const descended: Values = { ...( child.value as Values ) };
|
|
230
|
+
const replacement: Value = { ...child, value: descended };
|
|
231
|
+
|
|
232
|
+
return { replacement, descended };
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
return null;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
function isCompatibleSavedValue( saved: Value | null, current: Value ): saved is Value {
|
|
239
|
+
if ( ! saved ) {
|
|
240
|
+
return false;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
return isOverridable( saved ) === isOverridable( current );
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
function mergeLeafValue( existing: Value, incoming: Value ) {
|
|
247
|
+
if ( incoming === null ) {
|
|
248
|
+
return null;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
if ( incoming && isOverridable( incoming ) ) {
|
|
252
|
+
return incoming;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
if ( existing && isOverridable( existing ) && incoming ) {
|
|
256
|
+
return rewrapOverridableValue( existing, incoming );
|
|
257
|
+
}
|
|
183
258
|
|
|
184
|
-
return
|
|
259
|
+
return incoming;
|
|
185
260
|
}
|
|
186
261
|
|
|
187
262
|
function handleUnmetCondition( props: {
|
|
@@ -196,7 +271,8 @@ function handleUnmetCondition( props: {
|
|
|
196
271
|
( term ): term is Dependency => 'newValue' in term && !! term.newValue
|
|
197
272
|
) as Dependency | undefined;
|
|
198
273
|
const newValue = termWithNewValue?.newValue ?? null;
|
|
199
|
-
const currentValue =
|
|
274
|
+
const currentValue =
|
|
275
|
+
extractValue( dependency.split( '.' ), elementValues, [], { unwrapOverridableLeaf: false } ) ?? defaultValue;
|
|
200
276
|
|
|
201
277
|
savePreviousValueToStorage( {
|
|
202
278
|
path: dependency,
|