@elementor/editor-editing-panel 3.33.0-99 → 3.34.2
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 +419 -88
- package/dist/index.d.ts +419 -88
- package/dist/index.js +3361 -2421
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +3299 -2347
- package/dist/index.mjs.map +1 -1
- package/package.json +22 -21
- package/src/apply-unapply-actions.ts +30 -0
- package/src/components/collapsible-content.tsx +1 -0
- package/src/components/css-classes/css-class-item.tsx +14 -4
- package/src/components/css-classes/css-class-menu.tsx +83 -11
- package/src/components/css-classes/css-class-selector.tsx +22 -1
- package/src/components/css-classes/use-apply-and-unapply-class.ts +4 -13
- package/src/components/custom-css-indicator.tsx +68 -1
- package/src/components/editing-panel-tabs.tsx +13 -2
- package/src/components/interactions-tab.tsx +15 -0
- package/src/components/section-content.tsx +3 -2
- package/src/components/section.tsx +2 -1
- package/src/components/settings-control.tsx +79 -0
- package/src/components/settings-tab.tsx +16 -46
- package/src/components/style-sections/border-section/border-section.tsx +6 -4
- package/src/components/style-sections/effects-section/blend-mode-field.tsx +44 -0
- package/src/components/style-sections/effects-section/effects-section.tsx +4 -1
- package/src/components/style-sections/layout-section/flex-size-field.tsx +10 -8
- package/src/components/style-sections/typography-section/font-family-field.tsx +5 -1
- package/src/components/style-sections/typography-section/font-size-field.tsx +1 -1
- package/src/components/style-sections/typography-section/letter-spacing-field.tsx +1 -1
- package/src/components/style-sections/typography-section/text-color-field.tsx +1 -1
- package/src/components/style-sections/typography-section/word-spacing-field.tsx +1 -1
- package/src/components/style-tab-section.tsx +2 -2
- package/src/components/style-tab.tsx +12 -17
- package/src/components/styles-field-layout.tsx +8 -1
- package/src/contexts/interaction-context.tsx +0 -0
- package/src/controls-registry/conditional-field.tsx +1 -1
- package/src/controls-registry/control-type-container.tsx +17 -5
- package/src/controls-registry/controls-registry.tsx +18 -5
- package/src/controls-registry/element-controls/get-element-by-type.ts +21 -0
- package/src/controls-registry/element-controls/registry.ts +16 -0
- package/src/controls-registry/element-controls/tabs-control/tabs-control.tsx +229 -0
- package/src/controls-registry/element-controls/tabs-control/use-actions.ts +248 -0
- package/src/controls-registry/settings-field.tsx +54 -10
- package/src/controls-registry/styles-field.tsx +2 -9
- package/src/dynamics/components/dynamic-conditional-control.tsx +62 -0
- package/src/dynamics/components/dynamic-selection-control.tsx +81 -25
- package/src/dynamics/components/dynamic-selection.tsx +3 -3
- package/src/dynamics/dynamic-control.tsx +10 -1
- package/src/dynamics/hooks/use-prop-dynamic-tags.ts +24 -6
- package/src/field-indicators-registry.ts +37 -0
- package/src/hooks/use-computed-style.ts +1 -4
- package/src/index.ts +16 -3
- package/src/init.ts +7 -0
- package/src/reset-style-props.tsx +21 -4
- package/src/styles-inheritance/components/infotip/value-component.tsx +2 -0
- package/src/styles-inheritance/components/styles-inheritance-indicator.tsx +1 -13
- package/src/styles-inheritance/components/styles-inheritance-infotip.tsx +5 -1
- package/src/styles-inheritance/hooks/use-normalized-inheritance-chain-items.tsx +18 -2
- package/src/styles-inheritance/init-styles-inheritance-transformers.ts +25 -4
- package/src/styles-inheritance/init.ts +9 -0
- package/src/styles-inheritance/transformers/{background-overlay-transformer.tsx → array-transformer.tsx} +2 -2
- package/src/styles-inheritance/transformers/background-color-overlay-transformer.tsx +0 -6
- package/src/styles-inheritance/transformers/box-shadow-transformer.tsx +32 -0
- package/src/styles-inheritance/transformers/color-transformer.tsx +32 -0
- package/src/styles-inheritance/transformers/repeater-to-items-transformer.tsx +27 -0
- package/src/utils/is-equal.ts +53 -0
- package/src/utils/prop-dependency-utils.ts +107 -19
- package/src/utils/tracking/subscribe.ts +7 -0
- package/src/components/custom-css-field.tsx +0 -20
- package/src/components/custom-css.tsx +0 -36
- package/src/components/style-sections/border-section/border-field.tsx +0 -54
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@elementor/editor-editing-panel",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.34.2",
|
|
4
4
|
"private": false,
|
|
5
5
|
"author": "Elementor Team",
|
|
6
6
|
"homepage": "https://elementor.com/",
|
|
@@ -39,26 +39,27 @@
|
|
|
39
39
|
"dev": "tsup --config=../../tsup.dev.ts"
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@elementor/editor": "3.
|
|
43
|
-
"@elementor/editor-canvas": "3.
|
|
44
|
-
"@elementor/editor-controls": "3.
|
|
45
|
-
"@elementor/editor-documents": "3.
|
|
46
|
-
"@elementor/editor-elements": "3.
|
|
47
|
-
"@elementor/editor-
|
|
48
|
-
"@elementor/editor-
|
|
49
|
-
"@elementor/editor-
|
|
50
|
-
"@elementor/editor-
|
|
51
|
-
"@elementor/editor-styles
|
|
52
|
-
"@elementor/editor-
|
|
53
|
-
"@elementor/editor-
|
|
54
|
-
"@elementor/
|
|
55
|
-
"@elementor/
|
|
56
|
-
"@elementor/
|
|
57
|
-
"@elementor/
|
|
58
|
-
"@elementor/
|
|
59
|
-
"@elementor/
|
|
60
|
-
"@elementor/
|
|
61
|
-
"@elementor/
|
|
42
|
+
"@elementor/editor": "3.34.2",
|
|
43
|
+
"@elementor/editor-canvas": "3.34.2",
|
|
44
|
+
"@elementor/editor-controls": "3.34.2",
|
|
45
|
+
"@elementor/editor-documents": "3.34.2",
|
|
46
|
+
"@elementor/editor-elements": "3.34.2",
|
|
47
|
+
"@elementor/editor-interactions": "3.34.2",
|
|
48
|
+
"@elementor/editor-panels": "3.34.2",
|
|
49
|
+
"@elementor/editor-props": "3.34.2",
|
|
50
|
+
"@elementor/editor-responsive": "3.34.2",
|
|
51
|
+
"@elementor/editor-styles": "3.34.2",
|
|
52
|
+
"@elementor/editor-styles-repository": "3.34.2",
|
|
53
|
+
"@elementor/editor-ui": "3.34.2",
|
|
54
|
+
"@elementor/editor-v1-adapters": "3.34.2",
|
|
55
|
+
"@elementor/icons": "^1.61.0",
|
|
56
|
+
"@elementor/locations": "3.34.2",
|
|
57
|
+
"@elementor/menus": "3.34.2",
|
|
58
|
+
"@elementor/schema": "3.34.2",
|
|
59
|
+
"@elementor/session": "3.34.2",
|
|
60
|
+
"@elementor/ui": "1.36.17",
|
|
61
|
+
"@elementor/utils": "3.34.2",
|
|
62
|
+
"@elementor/wp-media": "3.34.2",
|
|
62
63
|
"@wordpress/i18n": "^5.13.0"
|
|
63
64
|
},
|
|
64
65
|
"peerDependencies": {
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { setDocumentModifiedStatus } from '@elementor/editor-documents';
|
|
2
|
+
import { getElementSetting, updateElementSettings } from '@elementor/editor-elements';
|
|
3
|
+
import { classesPropTypeUtil, type ClassesPropValue } from '@elementor/editor-props';
|
|
4
|
+
import { type StyleDefinitionID } from '@elementor/editor-styles';
|
|
5
|
+
|
|
6
|
+
// Externalized for use outside of Hooks
|
|
7
|
+
|
|
8
|
+
export function doGetAppliedClasses( elementId: string, classesPropType = 'classes' ) {
|
|
9
|
+
return getElementSetting< ClassesPropValue >( elementId, classesPropType )?.value || [];
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function doApplyClasses( elementId: string, classIds: StyleDefinitionID[], classesPropType = 'classes' ) {
|
|
13
|
+
updateElementSettings( {
|
|
14
|
+
id: elementId,
|
|
15
|
+
props: { [ classesPropType ]: classesPropTypeUtil.create( classIds ) },
|
|
16
|
+
withHistory: false,
|
|
17
|
+
} );
|
|
18
|
+
setDocumentModifiedStatus( true );
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function doUnapplyClass( elementId: string, classId: StyleDefinitionID, classesPropType = 'classes' ) {
|
|
22
|
+
const appliedClasses = getElementSetting< ClassesPropValue >( elementId, classesPropType )?.value || [];
|
|
23
|
+
if ( ! appliedClasses.includes( classId ) ) {
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const updatedClassIds = appliedClasses.filter( ( id ) => id !== classId );
|
|
28
|
+
doApplyClasses( elementId, updatedClassIds, classesPropType );
|
|
29
|
+
return true;
|
|
30
|
+
}
|
|
@@ -44,6 +44,7 @@ export const CollapsibleContent = ( { children, defaultOpen = false, titleEnd =
|
|
|
44
44
|
onClick={ handleToggle }
|
|
45
45
|
endIcon={ <CollapseIcon open={ open } /> }
|
|
46
46
|
sx={ { my: 0.5 } }
|
|
47
|
+
aria-label={ open ? 'Show less' : 'Show more' }
|
|
47
48
|
>
|
|
48
49
|
{ open ? __( 'Show less', 'elementor' ) : __( 'Show more', 'elementor' ) }
|
|
49
50
|
</Button>
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import { type ReactElement, useEffect, useState } from 'react';
|
|
2
|
+
import { type ReactElement, useEffect, useMemo, useState } from 'react';
|
|
3
|
+
import { isClassState } from '@elementor/editor-styles';
|
|
3
4
|
import { stylesRepository, useUserStylesCapability, validateStyleLabel } from '@elementor/editor-styles-repository';
|
|
4
5
|
import { EditableField, EllipsisWithTooltip, useEditable } from '@elementor/editor-ui';
|
|
5
6
|
import { DotsVerticalIcon } from '@elementor/icons';
|
|
@@ -20,7 +21,7 @@ import { __ } from '@wordpress/i18n';
|
|
|
20
21
|
|
|
21
22
|
import { useStyle } from '../../contexts/style-context';
|
|
22
23
|
import { CssClassProvider } from './css-class-context';
|
|
23
|
-
import { CssClassMenu } from './css-class-menu';
|
|
24
|
+
import { CssClassMenu, useElementStates } from './css-class-menu';
|
|
24
25
|
|
|
25
26
|
type CssClassItemProps = {
|
|
26
27
|
id: string | null;
|
|
@@ -43,6 +44,8 @@ export function CssClassItem( props: CssClassItemProps ) {
|
|
|
43
44
|
const { chipProps, icon, color: colorProp, fixed, ...classProps } = props;
|
|
44
45
|
const { id, provider, label, isActive, onClickActive, renameLabel, setError } = classProps;
|
|
45
46
|
|
|
47
|
+
const { elementStates } = useElementStates();
|
|
48
|
+
|
|
46
49
|
const { meta, setMetaState } = useStyle();
|
|
47
50
|
const popupState = usePopupState( { variant: 'popover' } );
|
|
48
51
|
const [ chipRef, setChipRef ] = useState< HTMLElement | null >( null );
|
|
@@ -75,12 +78,19 @@ export function CssClassItem( props: CssClassItemProps ) {
|
|
|
75
78
|
|
|
76
79
|
const isShowingState = isActive && meta.state;
|
|
77
80
|
|
|
81
|
+
const stateLabel = useMemo( () => {
|
|
82
|
+
if ( isClassState( meta.state ) ) {
|
|
83
|
+
return elementStates.find( ( state ) => state.value === meta.state )?.label;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return meta.state;
|
|
87
|
+
}, [ meta.state, elementStates ] );
|
|
88
|
+
|
|
78
89
|
useEffect( () => {
|
|
79
90
|
if ( convertedFromLocalId && id === convertedFromLocalId ) {
|
|
80
91
|
clearConvertedFromLocalId();
|
|
81
92
|
openEditMode();
|
|
82
93
|
}
|
|
83
|
-
// eslint-disable-next-line react-compiler/react-compiler
|
|
84
94
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
85
95
|
}, [ id, convertedFromLocalId ] );
|
|
86
96
|
|
|
@@ -138,7 +148,7 @@ export function CssClassItem( props: CssClassItemProps ) {
|
|
|
138
148
|
label={
|
|
139
149
|
isShowingState ? (
|
|
140
150
|
<Stack direction="row" gap={ 0.5 } alignItems="center">
|
|
141
|
-
<Typography variant="inherit">{
|
|
151
|
+
<Typography variant="inherit">{ stateLabel }</Typography>
|
|
142
152
|
<DotsVerticalIcon fontSize="tiny" />
|
|
143
153
|
</Stack>
|
|
144
154
|
) : undefined
|
|
@@ -9,9 +9,11 @@ import { MenuItemInfotip, MenuListItem } from '@elementor/editor-ui';
|
|
|
9
9
|
import { bindMenu, Divider, Menu, MenuSubheader, type PopupState, Stack } from '@elementor/ui';
|
|
10
10
|
import { __ } from '@wordpress/i18n';
|
|
11
11
|
|
|
12
|
+
import { useElement } from '../../contexts/element-context';
|
|
12
13
|
import { useStyle } from '../../contexts/style-context';
|
|
13
14
|
import { type StyleDefinitionStateWithNormal } from '../../styles-inheritance/types';
|
|
14
15
|
import { getTempStylesProviderThemeColor } from '../../utils/get-styles-provider-color';
|
|
16
|
+
import { trackStyles } from '../../utils/tracking/subscribe';
|
|
15
17
|
import { StyleIndicator } from '../style-indicator';
|
|
16
18
|
import { useCssClass } from './css-class-context';
|
|
17
19
|
import { LocalClassSubMenu } from './local-class-sub-menu';
|
|
@@ -20,13 +22,14 @@ import { useUnapplyClass } from './use-apply-and-unapply-class';
|
|
|
20
22
|
type State = {
|
|
21
23
|
key: StyleDefinitionStateWithNormal;
|
|
22
24
|
value: StyleDefinitionState | null;
|
|
25
|
+
label: string;
|
|
23
26
|
};
|
|
24
27
|
|
|
25
28
|
const STATES: State[] = [
|
|
26
|
-
{ key: 'normal', value: null },
|
|
27
|
-
{ key: 'hover', value: 'hover' },
|
|
28
|
-
{ key: 'focus', value: 'focus' },
|
|
29
|
-
{ key: 'active', value: 'active' },
|
|
29
|
+
{ key: 'normal', value: null, label: __( 'normal', 'elementor' ) },
|
|
30
|
+
{ key: 'hover', value: 'hover', label: __( 'hover', 'elementor' ) },
|
|
31
|
+
{ key: 'focus', value: 'focus', label: __( 'focus', 'elementor' ) },
|
|
32
|
+
{ key: 'active', value: 'active', label: __( 'active', 'elementor' ) },
|
|
30
33
|
];
|
|
31
34
|
|
|
32
35
|
type CssClassMenuProps = {
|
|
@@ -67,15 +70,75 @@ export function CssClassMenu( { popupState, anchorEl, fixed }: CssClassMenuProps
|
|
|
67
70
|
{ __( 'States', 'elementor' ) }
|
|
68
71
|
</MenuSubheader>
|
|
69
72
|
{ STATES.map( ( state ) => {
|
|
70
|
-
return
|
|
73
|
+
return (
|
|
74
|
+
<StateMenuItem
|
|
75
|
+
key={ state.key }
|
|
76
|
+
state={ state.value }
|
|
77
|
+
label={ state.label }
|
|
78
|
+
closeMenu={ popupState.close }
|
|
79
|
+
/>
|
|
80
|
+
);
|
|
71
81
|
} ) }
|
|
82
|
+
<ClassStatesMenu closeMenu={ popupState.close } />
|
|
72
83
|
</Menu>
|
|
73
84
|
);
|
|
74
85
|
}
|
|
75
86
|
|
|
87
|
+
function ClassStatesMenu( { closeMenu }: { closeMenu: () => void } ) {
|
|
88
|
+
const { elementStates, elementTitle } = useElementStates();
|
|
89
|
+
|
|
90
|
+
if ( ! elementStates.length ) {
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/* translators: %s: Element type title. */
|
|
95
|
+
const customTitle = __( '%s States', 'elementor' ).replace( '%s', elementTitle );
|
|
96
|
+
|
|
97
|
+
return (
|
|
98
|
+
<>
|
|
99
|
+
<Divider />
|
|
100
|
+
<MenuSubheader sx={ { typography: 'caption', color: 'text.secondary', pb: 0.5, pt: 1 } }>
|
|
101
|
+
{ customTitle }
|
|
102
|
+
</MenuSubheader>
|
|
103
|
+
{ elementStates.map( ( state ) => {
|
|
104
|
+
return (
|
|
105
|
+
<StateMenuItem
|
|
106
|
+
key={ state.key }
|
|
107
|
+
state={ state.value }
|
|
108
|
+
label={ state.label }
|
|
109
|
+
closeMenu={ closeMenu }
|
|
110
|
+
/>
|
|
111
|
+
);
|
|
112
|
+
} ) }
|
|
113
|
+
</>
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
const CLASS_STATES_MAP: Record< string, { label: string } > = {
|
|
118
|
+
selected: {
|
|
119
|
+
label: __( 'selected', 'elementor' ),
|
|
120
|
+
},
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
export function useElementStates() {
|
|
124
|
+
const { elementType } = useElement();
|
|
125
|
+
|
|
126
|
+
const { styleStates = [] } = elementType;
|
|
127
|
+
|
|
128
|
+
const elementStates = styleStates.map( ( { value, name } ) => ( {
|
|
129
|
+
key: value,
|
|
130
|
+
value,
|
|
131
|
+
label: CLASS_STATES_MAP[ value ]?.label ?? name,
|
|
132
|
+
} ) );
|
|
133
|
+
|
|
134
|
+
return {
|
|
135
|
+
elementStates,
|
|
136
|
+
elementTitle: elementType.title,
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
|
|
76
140
|
function useModifiedStates( styleId: string | null ): Partial< Record< StyleDefinitionStateWithNormal, true > > {
|
|
77
141
|
const { meta } = useStyle();
|
|
78
|
-
|
|
79
142
|
const styleDef = stylesRepository.all().find( ( style ) => style.id === styleId );
|
|
80
143
|
|
|
81
144
|
return Object.fromEntries(
|
|
@@ -126,10 +189,11 @@ function getMenuItemsByProvider( {
|
|
|
126
189
|
|
|
127
190
|
type StateMenuItemProps = {
|
|
128
191
|
state: StyleDefinitionState;
|
|
192
|
+
label: string;
|
|
129
193
|
closeMenu: () => void;
|
|
130
194
|
};
|
|
131
195
|
|
|
132
|
-
function StateMenuItem( { state, closeMenu, ...props }: StateMenuItemProps ) {
|
|
196
|
+
function StateMenuItem( { state, label, closeMenu, ...props }: StateMenuItemProps ) {
|
|
133
197
|
const { id: styleId, provider } = useCssClass();
|
|
134
198
|
const { id: activeId, setId: setActiveId, setMetaState: setActiveMetaState, meta } = useStyle();
|
|
135
199
|
const { state: activeState } = meta;
|
|
@@ -154,9 +218,12 @@ function StateMenuItem( { state, closeMenu, ...props }: StateMenuItemProps ) {
|
|
|
154
218
|
if ( ! isActive ) {
|
|
155
219
|
setActiveId( styleId );
|
|
156
220
|
}
|
|
157
|
-
|
|
221
|
+
trackStyles( provider ?? '', 'classStateClicked', {
|
|
222
|
+
classId: styleId,
|
|
223
|
+
type: label,
|
|
224
|
+
source: styleId ? 'global' : 'local',
|
|
225
|
+
} );
|
|
158
226
|
setActiveMetaState( state );
|
|
159
|
-
|
|
160
227
|
closeMenu();
|
|
161
228
|
} }
|
|
162
229
|
>
|
|
@@ -171,7 +238,7 @@ function StateMenuItem( { state, closeMenu, ...props }: StateMenuItemProps ) {
|
|
|
171
238
|
getColor={ getTempStylesProviderThemeColor( provider ?? '' ) }
|
|
172
239
|
/>
|
|
173
240
|
) }
|
|
174
|
-
{
|
|
241
|
+
{ label }
|
|
175
242
|
</Stack>
|
|
176
243
|
</MenuItemInfotip>
|
|
177
244
|
</MenuListItem>
|
|
@@ -179,7 +246,7 @@ function StateMenuItem( { state, closeMenu, ...props }: StateMenuItemProps ) {
|
|
|
179
246
|
}
|
|
180
247
|
|
|
181
248
|
function UnapplyClassMenuItem( { closeMenu, ...props }: { closeMenu: () => void } ) {
|
|
182
|
-
const { id: classId, label: classLabel } = useCssClass();
|
|
249
|
+
const { id: classId, label: classLabel, provider } = useCssClass();
|
|
183
250
|
const unapplyClass = useUnapplyClass();
|
|
184
251
|
|
|
185
252
|
return classId ? (
|
|
@@ -187,6 +254,11 @@ function UnapplyClassMenuItem( { closeMenu, ...props }: { closeMenu: () => void
|
|
|
187
254
|
{ ...props }
|
|
188
255
|
onClick={ () => {
|
|
189
256
|
unapplyClass( { classId, classLabel } );
|
|
257
|
+
trackStyles( provider ?? '', 'classRemoved', {
|
|
258
|
+
classId,
|
|
259
|
+
classTitle: classLabel,
|
|
260
|
+
source: 'style-tab',
|
|
261
|
+
} );
|
|
190
262
|
closeMenu();
|
|
191
263
|
} }
|
|
192
264
|
>
|
|
@@ -30,6 +30,7 @@ import { useClassesProp } from '../../contexts/classes-prop-context';
|
|
|
30
30
|
import { useElement } from '../../contexts/element-context';
|
|
31
31
|
import { useStyle } from '../../contexts/style-context';
|
|
32
32
|
import { getStylesProviderColorName } from '../../utils/get-styles-provider-color';
|
|
33
|
+
import { trackStyles } from '../../utils/tracking/subscribe';
|
|
33
34
|
import {
|
|
34
35
|
CreatableAutocomplete,
|
|
35
36
|
type CreatableAutocompleteProps,
|
|
@@ -127,6 +128,13 @@ export function CssClassSelector() {
|
|
|
127
128
|
if ( ! value.value ) {
|
|
128
129
|
throw new Error( `Cannot rename a class without style id` );
|
|
129
130
|
}
|
|
131
|
+
trackStyles( value.provider ?? '', 'classRenamed', {
|
|
132
|
+
classId: value.value,
|
|
133
|
+
newValue: newLabel,
|
|
134
|
+
oldValue: value.label,
|
|
135
|
+
source: 'style-tab',
|
|
136
|
+
} );
|
|
137
|
+
|
|
130
138
|
return updateClassByProvider( value.provider, { label: newLabel, id: value.value } );
|
|
131
139
|
};
|
|
132
140
|
|
|
@@ -244,7 +252,12 @@ function useCreateAction() {
|
|
|
244
252
|
}
|
|
245
253
|
|
|
246
254
|
const create = ( classLabel: string ) => {
|
|
247
|
-
createAction( { classLabel } );
|
|
255
|
+
const { createdId } = createAction( { classLabel } );
|
|
256
|
+
trackStyles( provider.getKey() ?? '', 'classCreated', {
|
|
257
|
+
source: 'created',
|
|
258
|
+
classTitle: classLabel,
|
|
259
|
+
classId: createdId,
|
|
260
|
+
} );
|
|
248
261
|
};
|
|
249
262
|
|
|
250
263
|
const validate = ( newClassLabel: string, event: ValidationEvent ): ValidationResult => {
|
|
@@ -302,10 +315,18 @@ function useHandleSelect() {
|
|
|
302
315
|
switch ( reason ) {
|
|
303
316
|
case 'selectOption':
|
|
304
317
|
apply( { classId: option.value, classLabel: option.label } );
|
|
318
|
+
trackStyles( option.provider ?? '', 'classApplied', {
|
|
319
|
+
classId: option.value,
|
|
320
|
+
source: 'style-tab',
|
|
321
|
+
} );
|
|
305
322
|
break;
|
|
306
323
|
|
|
307
324
|
case 'removeOption':
|
|
308
325
|
unapply( { classId: option.value, classLabel: option.label } );
|
|
326
|
+
trackStyles( option.provider ?? '', 'classRemoved', {
|
|
327
|
+
classId: option.value,
|
|
328
|
+
source: 'style-tab',
|
|
329
|
+
} );
|
|
309
330
|
break;
|
|
310
331
|
}
|
|
311
332
|
};
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import { useCallback, useMemo } from 'react';
|
|
2
|
-
import {
|
|
3
|
-
import { getElementLabel, getElementSetting, updateElementSettings } from '@elementor/editor-elements';
|
|
4
|
-
import { classesPropTypeUtil, type ClassesPropValue } from '@elementor/editor-props';
|
|
2
|
+
import { getElementLabel } from '@elementor/editor-elements';
|
|
5
3
|
import { type StyleDefinitionID } from '@elementor/editor-styles';
|
|
6
4
|
import { useGetStylesRepositoryCreateAction } from '@elementor/editor-styles-repository';
|
|
7
5
|
import { undoable } from '@elementor/editor-v1-adapters';
|
|
8
6
|
import { __ } from '@wordpress/i18n';
|
|
9
7
|
|
|
8
|
+
import { doApplyClasses, doGetAppliedClasses } from '../../apply-unapply-actions';
|
|
10
9
|
import { useClassesProp } from '../../contexts/classes-prop-context';
|
|
11
10
|
import { useElement } from '../../contexts/element-context';
|
|
12
11
|
import { useStyle } from '../../contexts/style-context';
|
|
@@ -112,7 +111,6 @@ export function useCreateAndApplyClass() {
|
|
|
112
111
|
|
|
113
112
|
const createdId = createAction( classLabel );
|
|
114
113
|
applyClass( createdId );
|
|
115
|
-
|
|
116
114
|
return { prevActiveId, createdId };
|
|
117
115
|
},
|
|
118
116
|
undo: ( _: CreateAndApplyClassPayload, { prevActiveId, createdId }: CreateAndApplyClassUndoData ) => {
|
|
@@ -194,17 +192,10 @@ function useClasses() {
|
|
|
194
192
|
|
|
195
193
|
return useMemo( () => {
|
|
196
194
|
const setClasses = ( ids: StyleDefinitionID[] ) => {
|
|
197
|
-
|
|
198
|
-
id: element.id,
|
|
199
|
-
props: { [ currentClassesProp ]: classesPropTypeUtil.create( ids ) },
|
|
200
|
-
withHistory: false,
|
|
201
|
-
} );
|
|
202
|
-
|
|
203
|
-
setDocumentModifiedStatus( true );
|
|
195
|
+
doApplyClasses( element.id, ids, currentClassesProp );
|
|
204
196
|
};
|
|
205
197
|
|
|
206
|
-
const getAppliedClasses = () =>
|
|
207
|
-
getElementSetting< ClassesPropValue >( element.id, currentClassesProp )?.value || [];
|
|
198
|
+
const getAppliedClasses = () => doGetAppliedClasses( element.id, currentClassesProp ) || [];
|
|
208
199
|
|
|
209
200
|
return { setClasses, getAppliedClasses };
|
|
210
201
|
}, [ currentClassesProp, element.id ] );
|
|
@@ -1,16 +1,83 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
+
import { type BreakpointId, type BreakpointNode, getBreakpointsTree } from '@elementor/editor-responsive';
|
|
3
|
+
import { getVariantByMeta, type StyleDefinition, type StyleDefinitionVariant } from '@elementor/editor-styles';
|
|
2
4
|
|
|
5
|
+
import { useElement } from '../contexts/element-context';
|
|
6
|
+
import { useStyle } from '../contexts/style-context';
|
|
3
7
|
import { useCustomCss } from '../hooks/use-custom-css';
|
|
8
|
+
import { getStylesProviderThemeColor } from '../utils/get-styles-provider-color';
|
|
4
9
|
import { StyleIndicator } from './style-indicator';
|
|
5
10
|
|
|
6
11
|
export const CustomCssIndicator = () => {
|
|
7
12
|
const { customCss } = useCustomCss();
|
|
13
|
+
const { id: styleId, provider, meta } = useStyle();
|
|
14
|
+
const {
|
|
15
|
+
element: { id: elementId },
|
|
16
|
+
} = useElement();
|
|
17
|
+
|
|
18
|
+
const style = React.useMemo(
|
|
19
|
+
() => ( styleId && provider ? provider.actions.get( styleId, { elementId } ) : null ),
|
|
20
|
+
[ styleId, provider, elementId ]
|
|
21
|
+
);
|
|
8
22
|
|
|
9
23
|
const hasContent = Boolean( customCss?.raw?.trim() );
|
|
10
24
|
|
|
25
|
+
const hasInheritedContent = React.useMemo( () => {
|
|
26
|
+
if ( hasContent ) {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return hasInheritedCustomCss( style, meta );
|
|
31
|
+
}, [ hasContent, style, meta ] );
|
|
32
|
+
|
|
11
33
|
if ( ! hasContent ) {
|
|
34
|
+
if ( hasInheritedContent ) {
|
|
35
|
+
return <StyleIndicator />;
|
|
36
|
+
}
|
|
12
37
|
return null;
|
|
13
38
|
}
|
|
14
39
|
|
|
15
|
-
return <StyleIndicator getColor={ (
|
|
40
|
+
return <StyleIndicator getColor={ provider ? getStylesProviderThemeColor( provider.getKey() ) : undefined } />;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const hasInheritedCustomCss = (
|
|
44
|
+
style: StyleDefinition | null,
|
|
45
|
+
meta: StyleDefinitionVariant[ 'meta' ] | null
|
|
46
|
+
): boolean => {
|
|
47
|
+
if ( ! style || ! meta ) {
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const target = ( meta.breakpoint ?? 'desktop' ) as BreakpointId;
|
|
52
|
+
const root = getBreakpointsTree();
|
|
53
|
+
const state = meta.state;
|
|
54
|
+
|
|
55
|
+
function search( node: BreakpointNode, ancestorHasCss: boolean ): boolean | undefined {
|
|
56
|
+
if ( ! style ) {
|
|
57
|
+
return undefined;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const hasHere = Boolean(
|
|
61
|
+
getVariantByMeta( style, {
|
|
62
|
+
breakpoint: node.id as BreakpointId,
|
|
63
|
+
state,
|
|
64
|
+
} )?.custom_css?.raw?.trim()
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
if ( node.id === target ) {
|
|
68
|
+
return ancestorHasCss;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
for ( const child of node.children ?? [] ) {
|
|
72
|
+
const res = search( child, ancestorHasCss || hasHere );
|
|
73
|
+
|
|
74
|
+
if ( res !== undefined ) {
|
|
75
|
+
return res;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return undefined;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return Boolean( search( root, false ) );
|
|
16
83
|
};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import * as React from 'react';
|
|
2
1
|
import { Fragment } from 'react';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { isExperimentActive } from '@elementor/editor-v1-adapters';
|
|
3
4
|
import { Divider, Stack, Tab, TabPanel, Tabs, useTabs } from '@elementor/ui';
|
|
4
5
|
import { __ } from '@wordpress/i18n';
|
|
5
6
|
|
|
@@ -7,10 +8,11 @@ import { useElement } from '../contexts/element-context';
|
|
|
7
8
|
import { ScrollProvider } from '../contexts/scroll-context';
|
|
8
9
|
import { useDefaultPanelSettings } from '../hooks/use-default-panel-settings';
|
|
9
10
|
import { useStateByElement } from '../hooks/use-state-by-element';
|
|
11
|
+
import { InteractionsTab } from './interactions-tab';
|
|
10
12
|
import { SettingsTab } from './settings-tab';
|
|
11
13
|
import { stickyHeaderStyles, StyleTab } from './style-tab';
|
|
12
14
|
|
|
13
|
-
type TabValue = 'settings' | 'style';
|
|
15
|
+
type TabValue = 'settings' | 'style' | 'interactions';
|
|
14
16
|
|
|
15
17
|
export const EditingPanelTabs = () => {
|
|
16
18
|
const { element } = useElement();
|
|
@@ -26,6 +28,7 @@ export const EditingPanelTabs = () => {
|
|
|
26
28
|
const PanelTabContent = () => {
|
|
27
29
|
const editorDefaults = useDefaultPanelSettings();
|
|
28
30
|
const defaultComponentTab = editorDefaults.defaultTab as TabValue;
|
|
31
|
+
const isInteractionsActive = isExperimentActive( 'e_interactions' );
|
|
29
32
|
|
|
30
33
|
const [ currentTab, setCurrentTab ] = useStateByElement< TabValue >( 'tab', defaultComponentTab );
|
|
31
34
|
const { getTabProps, getTabPanelProps, getTabsProps } = useTabs< TabValue >( currentTab );
|
|
@@ -45,6 +48,9 @@ const PanelTabContent = () => {
|
|
|
45
48
|
>
|
|
46
49
|
<Tab label={ __( 'General', 'elementor' ) } { ...getTabProps( 'settings' ) } />
|
|
47
50
|
<Tab label={ __( 'Style', 'elementor' ) } { ...getTabProps( 'style' ) } />
|
|
51
|
+
{ isInteractionsActive && (
|
|
52
|
+
<Tab label={ __( 'Interactions', 'elementor' ) } { ...getTabProps( 'interactions' ) } />
|
|
53
|
+
) }
|
|
48
54
|
</Tabs>
|
|
49
55
|
<Divider />
|
|
50
56
|
</Stack>
|
|
@@ -54,6 +60,11 @@ const PanelTabContent = () => {
|
|
|
54
60
|
<TabPanel { ...getTabPanelProps( 'style' ) } disablePadding>
|
|
55
61
|
<StyleTab />
|
|
56
62
|
</TabPanel>
|
|
63
|
+
{ isInteractionsActive && (
|
|
64
|
+
<TabPanel { ...getTabPanelProps( 'interactions' ) } disablePadding>
|
|
65
|
+
<InteractionsTab />
|
|
66
|
+
</TabPanel>
|
|
67
|
+
) }
|
|
57
68
|
</Stack>
|
|
58
69
|
</ScrollProvider>
|
|
59
70
|
);
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { InteractionsTab as InteractionsTabContent } from '@elementor/editor-interactions';
|
|
3
|
+
|
|
4
|
+
import { useElement } from '../contexts/element-context';
|
|
5
|
+
import { SectionsList } from './sections-list';
|
|
6
|
+
|
|
7
|
+
export const InteractionsTab = () => {
|
|
8
|
+
const { element } = useElement();
|
|
9
|
+
|
|
10
|
+
return (
|
|
11
|
+
<SectionsList>
|
|
12
|
+
<InteractionsTabContent elementId={ element.id } />
|
|
13
|
+
</SectionsList>
|
|
14
|
+
);
|
|
15
|
+
};
|
|
@@ -7,10 +7,11 @@ type SectionContentProps = PropsWithChildren< {
|
|
|
7
7
|
sx?: {
|
|
8
8
|
pt?: number;
|
|
9
9
|
};
|
|
10
|
+
'aria-label'?: string;
|
|
10
11
|
} >;
|
|
11
12
|
|
|
12
|
-
export const SectionContent: FC< SectionContentProps > = ( { gap = 2, sx, children } ) => (
|
|
13
|
-
<Stack gap={ gap } sx={ { ...sx } }>
|
|
13
|
+
export const SectionContent: FC< SectionContentProps > = ( { gap = 2, sx, children, 'aria-label': ariaLabel } ) => (
|
|
14
|
+
<Stack gap={ gap } sx={ { ...sx } } aria-label={ ariaLabel }>
|
|
14
15
|
{ children }
|
|
15
16
|
</Stack>
|
|
16
17
|
);
|
|
@@ -31,6 +31,7 @@ export function Section( { title, children, defaultExpanded = false, titleEnd, u
|
|
|
31
31
|
<ListItemButton
|
|
32
32
|
id={ labelId }
|
|
33
33
|
aria-controls={ contentId }
|
|
34
|
+
aria-label={ `${ title } section` }
|
|
34
35
|
onClick={ handleClick }
|
|
35
36
|
sx={ { '&:hover': { backgroundColor: 'transparent' } } }
|
|
36
37
|
>
|
|
@@ -52,7 +53,7 @@ export function Section( { title, children, defaultExpanded = false, titleEnd, u
|
|
|
52
53
|
unmountOnExit={ unmountOnExit }
|
|
53
54
|
>
|
|
54
55
|
<SectionRefContext.Provider value={ ref }>
|
|
55
|
-
<Stack ref={ ref } gap={ 2.5 } p={ 2 }>
|
|
56
|
+
<Stack ref={ ref } gap={ 2.5 } p={ 2 } aria-label={ `${ title } section content` }>
|
|
56
57
|
{ children }
|
|
57
58
|
</Stack>
|
|
58
59
|
</SectionRefContext.Provider>
|