@elementor/editor-editing-panel 1.27.0 → 1.28.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 +38 -0
- package/dist/index.d.mts +3 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +173 -134
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +146 -107
- package/dist/index.mjs.map +1 -1
- package/package.json +10 -10
- package/src/components/css-classes/css-class-item.tsx +8 -10
- package/src/components/css-classes/css-class-menu.tsx +7 -5
- package/src/components/css-classes/css-class-selector.tsx +22 -22
- package/src/components/multi-combobox.tsx +3 -0
- package/src/components/style-sections/layout-section/display-field.tsx +34 -28
- package/src/components/style-sections/layout-section/layout-section.tsx +14 -2
- package/src/components/style-tab.tsx +2 -19
- package/src/contexts/style-context.tsx +1 -1
- package/src/controls-registry/styles-field.tsx +9 -2
- package/src/hooks/use-active-style-def-id.ts +36 -0
- package/src/hooks/use-styles-fields.ts +7 -7
- package/src/index.ts +1 -3
- package/src/init.ts +1 -1
- package/src/styles-inheritance/create-snapshots-manager.ts +8 -1
- package/src/styles-inheritance/create-styles-inheritance.ts +1 -1
- package/src/styles-inheritance/styles-inheritance-indicator.tsx +2 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@elementor/editor-editing-panel",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.28.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"author": "Elementor Team",
|
|
6
6
|
"homepage": "https://elementor.com/",
|
|
@@ -39,17 +39,17 @@
|
|
|
39
39
|
"dev": "tsup --config=../../tsup.dev.ts"
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@elementor/editor": "0.18.
|
|
43
|
-
"@elementor/editor-canvas": "0.
|
|
44
|
-
"@elementor/editor-controls": "0.
|
|
42
|
+
"@elementor/editor": "0.18.6",
|
|
43
|
+
"@elementor/editor-canvas": "0.18.0",
|
|
44
|
+
"@elementor/editor-controls": "0.25.0",
|
|
45
45
|
"@elementor/editor-current-user": "0.3.0",
|
|
46
|
-
"@elementor/editor-elements": "0.8.
|
|
47
|
-
"@elementor/editor-panels": "0.14.
|
|
48
|
-
"@elementor/editor-props": "0.
|
|
46
|
+
"@elementor/editor-elements": "0.8.1",
|
|
47
|
+
"@elementor/editor-panels": "0.14.1",
|
|
48
|
+
"@elementor/editor-props": "0.12.0",
|
|
49
49
|
"@elementor/editor-responsive": "0.13.4",
|
|
50
|
-
"@elementor/editor-styles": "0.6.
|
|
51
|
-
"@elementor/editor-styles-repository": "0.8.
|
|
52
|
-
"@elementor/editor-ui": "0.7.
|
|
50
|
+
"@elementor/editor-styles": "0.6.6",
|
|
51
|
+
"@elementor/editor-styles-repository": "0.8.4",
|
|
52
|
+
"@elementor/editor-ui": "0.7.1",
|
|
53
53
|
"@elementor/editor-v1-adapters": "0.11.0",
|
|
54
54
|
"@elementor/icons": "1.37.0",
|
|
55
55
|
"@elementor/locations": "0.7.7",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { type ReactElement, useState } from 'react';
|
|
3
|
-
import { stylesRepository } from '@elementor/editor-styles-repository';
|
|
3
|
+
import { stylesRepository, validateStyleLabel } from '@elementor/editor-styles-repository';
|
|
4
4
|
import { EditableField, EllipsisWithTooltip, useEditable } from '@elementor/editor-ui';
|
|
5
5
|
import { DotsVerticalIcon } from '@elementor/icons';
|
|
6
6
|
import {
|
|
@@ -21,8 +21,8 @@ import { CssClassMenu } from './css-class-menu';
|
|
|
21
21
|
|
|
22
22
|
type CssClassItemProps = {
|
|
23
23
|
id: string | null;
|
|
24
|
+
provider: string | null;
|
|
24
25
|
label: string;
|
|
25
|
-
provider: string;
|
|
26
26
|
isActive: boolean;
|
|
27
27
|
color: ChipOwnProps[ 'color' ];
|
|
28
28
|
icon: ReactElement | null;
|
|
@@ -36,8 +36,8 @@ const CHIP_SIZE = 'tiny';
|
|
|
36
36
|
|
|
37
37
|
export function CssClassItem( {
|
|
38
38
|
id,
|
|
39
|
-
label,
|
|
40
39
|
provider,
|
|
40
|
+
label,
|
|
41
41
|
isActive,
|
|
42
42
|
color: colorProp,
|
|
43
43
|
icon,
|
|
@@ -64,7 +64,7 @@ export function CssClassItem( {
|
|
|
64
64
|
|
|
65
65
|
const color = error ? 'error' : colorProp;
|
|
66
66
|
|
|
67
|
-
const providerActions = stylesRepository.getProviderByKey( provider )?.actions;
|
|
67
|
+
const providerActions = provider ? stylesRepository.getProviderByKey( provider )?.actions : null;
|
|
68
68
|
const allowRename = Boolean( providerActions?.update );
|
|
69
69
|
|
|
70
70
|
const isShowingState = isActive && meta.state;
|
|
@@ -153,13 +153,11 @@ export function CssClassItem( {
|
|
|
153
153
|
}
|
|
154
154
|
|
|
155
155
|
const validateLabel = ( newLabel: string ) => {
|
|
156
|
-
|
|
157
|
-
return __( 'Invalid format', 'elementor' );
|
|
158
|
-
}
|
|
156
|
+
const result = validateStyleLabel( newLabel );
|
|
159
157
|
|
|
160
|
-
if (
|
|
161
|
-
return
|
|
158
|
+
if ( result.isValid ) {
|
|
159
|
+
return null;
|
|
162
160
|
}
|
|
163
161
|
|
|
164
|
-
return
|
|
162
|
+
return result.error;
|
|
165
163
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { type StyleDefinitionState } from '@elementor/editor-styles';
|
|
3
|
-
import {
|
|
3
|
+
import { isElementsStylesProvider, stylesRepository } from '@elementor/editor-styles-repository';
|
|
4
4
|
import { MenuListItem } from '@elementor/editor-ui';
|
|
5
5
|
import { bindMenu, Divider, Menu, MenuSubheader, type PopupState, Stack } from '@elementor/ui';
|
|
6
6
|
import { __ } from '@wordpress/i18n';
|
|
@@ -14,7 +14,7 @@ const STATES: NonNullable< StyleDefinitionState >[] = [ 'hover', 'focus', 'activ
|
|
|
14
14
|
|
|
15
15
|
type CssClassMenuProps = {
|
|
16
16
|
styleId: string | null;
|
|
17
|
-
provider: string;
|
|
17
|
+
provider: string | null;
|
|
18
18
|
popupState: PopupState;
|
|
19
19
|
handleRename: () => void;
|
|
20
20
|
anchorEl: HTMLElement | null;
|
|
@@ -23,7 +23,7 @@ type CssClassMenuProps = {
|
|
|
23
23
|
export function CssClassMenu( { styleId, provider, popupState, handleRename, anchorEl }: CssClassMenuProps ) {
|
|
24
24
|
const styledStates = useStyledStates( styleId );
|
|
25
25
|
|
|
26
|
-
const indicatorVariant = provider
|
|
26
|
+
const indicatorVariant = ! provider || isElementsStylesProvider( provider ) ? 'local' : 'global';
|
|
27
27
|
|
|
28
28
|
const handleKeyDown = ( e: React.KeyboardEvent< HTMLElement > ) => {
|
|
29
29
|
e.stopPropagation();
|
|
@@ -43,6 +43,8 @@ export function CssClassMenu( { styleId, provider, popupState, handleRename, anc
|
|
|
43
43
|
vertical: -4,
|
|
44
44
|
} }
|
|
45
45
|
onKeyDown={ handleKeyDown }
|
|
46
|
+
// Workaround for focus-visible issue.
|
|
47
|
+
disableAutoFocusItem
|
|
46
48
|
>
|
|
47
49
|
{ /* 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 */ }
|
|
48
50
|
{ getMenuItemsByProvider( { provider, styleId, handleRename, closeMenu: popupState.close } ) }
|
|
@@ -91,12 +93,12 @@ function getMenuItemsByProvider( {
|
|
|
91
93
|
handleRename,
|
|
92
94
|
closeMenu,
|
|
93
95
|
}: {
|
|
94
|
-
provider: string;
|
|
96
|
+
provider: string | null;
|
|
95
97
|
styleId: string | null;
|
|
96
98
|
handleRename: () => void;
|
|
97
99
|
closeMenu: () => void;
|
|
98
100
|
} ) {
|
|
99
|
-
if ( ! styleId ) {
|
|
101
|
+
if ( ! styleId || ! provider ) {
|
|
100
102
|
return [];
|
|
101
103
|
}
|
|
102
104
|
|
|
@@ -4,16 +4,17 @@ import { getElementSetting, updateElementSettings, useElementSetting } from '@el
|
|
|
4
4
|
import { classesPropTypeUtil, type ClassesPropValue } from '@elementor/editor-props';
|
|
5
5
|
import { type StyleDefinitionID } from '@elementor/editor-styles';
|
|
6
6
|
import {
|
|
7
|
-
|
|
7
|
+
isElementsStylesProvider,
|
|
8
8
|
type StylesProvider,
|
|
9
9
|
stylesRepository,
|
|
10
10
|
type UpdateActionPayload,
|
|
11
11
|
useCreateActionsByProvider,
|
|
12
12
|
useProviders,
|
|
13
|
+
validateStyleLabel,
|
|
13
14
|
} from '@elementor/editor-styles-repository';
|
|
14
15
|
import { MapPinIcon } from '@elementor/icons';
|
|
15
16
|
import { createLocation } from '@elementor/locations';
|
|
16
|
-
import { Chip,
|
|
17
|
+
import { Chip, FormLabel, Stack } from '@elementor/ui';
|
|
17
18
|
import { __ } from '@wordpress/i18n';
|
|
18
19
|
|
|
19
20
|
import { useClassesProp } from '../../contexts/classes-prop-context';
|
|
@@ -28,7 +29,7 @@ const TAGS_LIMIT = 50;
|
|
|
28
29
|
type StyleDefOption = Option & {
|
|
29
30
|
color: 'accent' | 'global';
|
|
30
31
|
icon: ReactElement | null;
|
|
31
|
-
provider: string;
|
|
32
|
+
provider: string | null;
|
|
32
33
|
};
|
|
33
34
|
|
|
34
35
|
const EMPTY_OPTION = {
|
|
@@ -37,7 +38,7 @@ const EMPTY_OPTION = {
|
|
|
37
38
|
fixed: true,
|
|
38
39
|
color: 'accent',
|
|
39
40
|
icon: <MapPinIcon />,
|
|
40
|
-
provider:
|
|
41
|
+
provider: null,
|
|
41
42
|
} satisfies StyleDefOption;
|
|
42
43
|
|
|
43
44
|
export const { Slot: ClassSelectorActionsSlot, inject: injectIntoClassSelectorActions } = createLocation();
|
|
@@ -60,12 +61,14 @@ export function CssClassSelector() {
|
|
|
60
61
|
const applied = useAppliedOptions( options, appliedIds );
|
|
61
62
|
const active = applied.find( ( option ) => option.value === activeId ) ?? EMPTY_OPTION;
|
|
62
63
|
|
|
64
|
+
const showPlaceholder = applied.every( ( { fixed } ) => fixed );
|
|
65
|
+
|
|
63
66
|
return (
|
|
64
|
-
<Stack
|
|
67
|
+
<Stack p={ 2 }>
|
|
65
68
|
<Stack direction="row" gap={ 1 } alignItems="center" justifyContent="space-between">
|
|
66
|
-
<
|
|
69
|
+
<FormLabel htmlFor={ ID } size="small">
|
|
67
70
|
{ __( 'Classes', 'elementor' ) }
|
|
68
|
-
</
|
|
71
|
+
</FormLabel>
|
|
69
72
|
<Stack direction="row" gap={ 1 }>
|
|
70
73
|
<ClassSelectorActionsSlot />
|
|
71
74
|
</Stack>
|
|
@@ -73,6 +76,7 @@ export function CssClassSelector() {
|
|
|
73
76
|
<MultiCombobox
|
|
74
77
|
id={ ID }
|
|
75
78
|
size="tiny"
|
|
79
|
+
placeholder={ showPlaceholder ? __( 'Type to search/add global classes', 'elementor' ) : undefined }
|
|
76
80
|
options={ options }
|
|
77
81
|
selected={ applied }
|
|
78
82
|
onSelect={ handleApply }
|
|
@@ -114,7 +118,11 @@ export function CssClassSelector() {
|
|
|
114
118
|
);
|
|
115
119
|
}
|
|
116
120
|
|
|
117
|
-
const updateClassByProvider = ( provider: string, data: UpdateActionPayload ) => {
|
|
121
|
+
const updateClassByProvider = ( provider: string | null, data: UpdateActionPayload ) => {
|
|
122
|
+
if ( ! provider ) {
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
|
|
118
126
|
const providerInstance = stylesRepository.getProviderByKey( provider );
|
|
119
127
|
|
|
120
128
|
if ( ! providerInstance ) {
|
|
@@ -132,8 +140,8 @@ function useOptions() {
|
|
|
132
140
|
return useProviders()
|
|
133
141
|
.filter( isProviderEditable )
|
|
134
142
|
.flatMap< StyleDefOption >( ( provider ) => {
|
|
135
|
-
const isElements = provider.
|
|
136
|
-
const styleDefs = provider.actions.
|
|
143
|
+
const isElements = isElementsStylesProvider( provider.getKey() );
|
|
144
|
+
const styleDefs = provider.actions.all( { elementId: element.id } );
|
|
137
145
|
|
|
138
146
|
// Add empty local option for elements, as fallback.
|
|
139
147
|
if ( isElements && styleDefs.length === 0 ) {
|
|
@@ -147,7 +155,7 @@ function useOptions() {
|
|
|
147
155
|
fixed: isElements,
|
|
148
156
|
color: isElements ? 'accent' : 'global',
|
|
149
157
|
icon: isElements ? <MapPinIcon /> : null,
|
|
150
|
-
provider: provider.
|
|
158
|
+
provider: provider.getKey(),
|
|
151
159
|
// translators: %s is the plural label of the provider (e.g "Existing classes").
|
|
152
160
|
group: __( 'Existing %s', 'elementor' ).replace( '%s', provider.labels?.plural ?? '' ),
|
|
153
161
|
};
|
|
@@ -168,7 +176,7 @@ function useCreateActions( {
|
|
|
168
176
|
label: ( value ) => __( 'Create "%s"', 'elementor' ).replace( '%s', value ),
|
|
169
177
|
// translators: %s is the singular label of css class provider (e.g "CSS Class").
|
|
170
178
|
group: __( 'Create a new %s', 'elementor' ).replace( '%s', provider.labels?.singular ?? '' ),
|
|
171
|
-
condition: ( _, inputValue ) =>
|
|
179
|
+
condition: ( _, inputValue ) => validateStyleLabel( inputValue ).isValid && ! hasReachedLimit( provider ),
|
|
172
180
|
apply: ( label ) => {
|
|
173
181
|
const createdId = create( label );
|
|
174
182
|
|
|
@@ -184,22 +192,14 @@ function useCreateActions( {
|
|
|
184
192
|
}
|
|
185
193
|
|
|
186
194
|
function hasReachedLimit( provider: StylesProvider ) {
|
|
187
|
-
|
|
188
|
-
return false;
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
return provider.actions.get().length >= provider.limit;
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
function isLabelValid( newLabel: string ) {
|
|
195
|
-
return stylesRepository.isLabelValid( newLabel ) && ! stylesRepository.isLabelExist( newLabel );
|
|
195
|
+
return provider.actions.all().length >= provider.limit;
|
|
196
196
|
}
|
|
197
197
|
|
|
198
198
|
function useAppliedOptions( options: StyleDefOption[], appliedIds: StyleDefinitionID[] ) {
|
|
199
199
|
const applied = options.filter( ( option ) => option.value && appliedIds.includes( option.value ) );
|
|
200
200
|
|
|
201
201
|
const hasElementsProviderStyleApplied = applied.some(
|
|
202
|
-
( option ) => option.provider
|
|
202
|
+
( option ) => option.provider && isElementsStylesProvider( option.provider )
|
|
203
203
|
);
|
|
204
204
|
|
|
205
205
|
if ( ! hasElementsProviderStyleApplied ) {
|
|
@@ -39,6 +39,7 @@ type Props< TOption extends Option > = Omit<
|
|
|
39
39
|
selected: TOption[];
|
|
40
40
|
options: TOption[];
|
|
41
41
|
onSelect?: ( value: TOption[] ) => void;
|
|
42
|
+
placeholder?: string;
|
|
42
43
|
};
|
|
43
44
|
|
|
44
45
|
export function MultiCombobox< TOption extends Option >( {
|
|
@@ -46,6 +47,7 @@ export function MultiCombobox< TOption extends Option >( {
|
|
|
46
47
|
selected,
|
|
47
48
|
options,
|
|
48
49
|
onSelect,
|
|
50
|
+
placeholder,
|
|
49
51
|
...props
|
|
50
52
|
}: Props< TOption > ) {
|
|
51
53
|
const filter = useFilterOptions< TOption >();
|
|
@@ -67,6 +69,7 @@ export function MultiCombobox< TOption extends Option >( {
|
|
|
67
69
|
renderInput={ ( params ) => (
|
|
68
70
|
<TextField
|
|
69
71
|
{ ...params }
|
|
72
|
+
placeholder={ placeholder }
|
|
70
73
|
sx={ ( theme: Theme ) => ( {
|
|
71
74
|
'.MuiAutocomplete-inputRoot.MuiInputBase-adornedStart': {
|
|
72
75
|
paddingLeft: theme.spacing( 0.25 ),
|
|
@@ -3,45 +3,51 @@ import { type ToggleButtonGroupItem, ToggleControl } from '@elementor/editor-con
|
|
|
3
3
|
import { Stack } from '@elementor/ui';
|
|
4
4
|
import { __ } from '@wordpress/i18n';
|
|
5
5
|
|
|
6
|
+
import { useStylesInheritanceField } from '../../../contexts/styles-inheritance-context';
|
|
6
7
|
import { StylesField } from '../../../controls-registry/styles-field';
|
|
7
8
|
import { ControlLabel } from '../../control-label';
|
|
8
9
|
|
|
9
10
|
type Displays = 'block' | 'flex' | 'inline-block' | 'inline-flex';
|
|
10
11
|
|
|
12
|
+
const displayFieldOptions: ToggleButtonGroupItem< Displays >[] = [
|
|
13
|
+
{
|
|
14
|
+
value: 'block',
|
|
15
|
+
renderContent: () => __( 'Block', 'elementor' ),
|
|
16
|
+
label: __( 'Block', 'elementor' ),
|
|
17
|
+
showTooltip: true,
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
value: 'flex',
|
|
21
|
+
renderContent: () => __( 'Flex', 'elementor' ),
|
|
22
|
+
label: __( 'Flex', 'elementor' ),
|
|
23
|
+
showTooltip: true,
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
value: 'inline-block',
|
|
27
|
+
renderContent: () => __( 'In-blk', 'elementor' ),
|
|
28
|
+
label: __( 'Inline-block', 'elementor' ),
|
|
29
|
+
showTooltip: true,
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
value: 'inline-flex',
|
|
33
|
+
renderContent: () => __( 'In-flx', 'elementor' ),
|
|
34
|
+
label: __( 'Inline-flex', 'elementor' ),
|
|
35
|
+
showTooltip: true,
|
|
36
|
+
},
|
|
37
|
+
];
|
|
38
|
+
|
|
11
39
|
export const DisplayField = () => {
|
|
12
|
-
const
|
|
13
|
-
{
|
|
14
|
-
value: 'block',
|
|
15
|
-
renderContent: () => __( 'Block', 'elementor' ),
|
|
16
|
-
label: __( 'Block', 'elementor' ),
|
|
17
|
-
showTooltip: true,
|
|
18
|
-
},
|
|
19
|
-
{
|
|
20
|
-
value: 'flex',
|
|
21
|
-
renderContent: () => __( 'Flex', 'elementor' ),
|
|
22
|
-
label: __( 'Flex', 'elementor' ),
|
|
23
|
-
showTooltip: true,
|
|
24
|
-
},
|
|
25
|
-
{
|
|
26
|
-
value: 'inline-block',
|
|
27
|
-
renderContent: () => __( 'In-blk', 'elementor' ),
|
|
28
|
-
label: __( 'Inline-block', 'elementor' ),
|
|
29
|
-
showTooltip: true,
|
|
30
|
-
},
|
|
31
|
-
{
|
|
32
|
-
value: 'inline-flex',
|
|
33
|
-
renderContent: () => __( 'In-flx', 'elementor' ),
|
|
34
|
-
label: __( 'Inline-flex', 'elementor' ),
|
|
35
|
-
showTooltip: true,
|
|
36
|
-
},
|
|
37
|
-
];
|
|
40
|
+
const placeholder = useDisplayPlaceholderValue();
|
|
38
41
|
|
|
39
42
|
return (
|
|
40
|
-
<StylesField bind="display">
|
|
43
|
+
<StylesField bind="display" placeholder={ placeholder }>
|
|
41
44
|
<Stack gap={ 0.75 }>
|
|
42
45
|
<ControlLabel>{ __( 'Display', 'elementor' ) }</ControlLabel>
|
|
43
|
-
<ToggleControl options={
|
|
46
|
+
<ToggleControl options={ displayFieldOptions } fullWidth={ true } />
|
|
44
47
|
</Stack>
|
|
45
48
|
</StylesField>
|
|
46
49
|
);
|
|
47
50
|
};
|
|
51
|
+
|
|
52
|
+
// TODO - placing this logic deliberately here, and will be removed once applied automatically to all style fields as part of ED-18491
|
|
53
|
+
export const useDisplayPlaceholderValue = () => useStylesInheritanceField( 'display' )[ 0 ]?.value ?? undefined;
|
|
@@ -12,7 +12,7 @@ import { SectionContent } from '../../section-content';
|
|
|
12
12
|
import { AlignContentField } from './align-content-field';
|
|
13
13
|
import { AlignItemsField } from './align-items-field';
|
|
14
14
|
import { AlignSelfChild } from './align-self-child-field';
|
|
15
|
-
import { DisplayField } from './display-field';
|
|
15
|
+
import { DisplayField, useDisplayPlaceholderValue } from './display-field';
|
|
16
16
|
import { FlexDirectionField } from './flex-direction-field';
|
|
17
17
|
import { FlexOrderField } from './flex-order-field';
|
|
18
18
|
import { FlexSizeField } from './flex-size-field';
|
|
@@ -22,6 +22,8 @@ import { WrapField } from './wrap-field';
|
|
|
22
22
|
|
|
23
23
|
export const LayoutSection = () => {
|
|
24
24
|
const [ display ] = useStylesField< StringPropValue >( 'display' );
|
|
25
|
+
const displayPlaceholder = useDisplayPlaceholderValue();
|
|
26
|
+
const isDisplayFlex = shouldDisplayFlexFields( display, displayPlaceholder as StringPropValue );
|
|
25
27
|
const { element } = useElement();
|
|
26
28
|
const parent = useParentElement( element.id );
|
|
27
29
|
const parentStyle = useComputedStyle( parent?.id || null );
|
|
@@ -29,7 +31,7 @@ export const LayoutSection = () => {
|
|
|
29
31
|
return (
|
|
30
32
|
<SectionContent>
|
|
31
33
|
<DisplayField />
|
|
32
|
-
{
|
|
34
|
+
{ isDisplayFlex && <FlexFields /> }
|
|
33
35
|
{ 'flex' === parentStyle?.display && <FlexChildFields /> }
|
|
34
36
|
</SectionContent>
|
|
35
37
|
);
|
|
@@ -60,3 +62,13 @@ const FlexChildFields = () => (
|
|
|
60
62
|
<FlexSizeField />
|
|
61
63
|
</>
|
|
62
64
|
);
|
|
65
|
+
|
|
66
|
+
const shouldDisplayFlexFields = ( display: StringPropValue | null, local: StringPropValue ) => {
|
|
67
|
+
const value = display?.value ?? local?.value;
|
|
68
|
+
|
|
69
|
+
if ( ! value ) {
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return 'flex' === value || 'inline-flex' === value;
|
|
74
|
+
};
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { useState } from 'react';
|
|
3
|
-
import {
|
|
4
|
-
import { CLASSES_PROP_KEY, type ClassesPropValue, type PropKey } from '@elementor/editor-props';
|
|
3
|
+
import { CLASSES_PROP_KEY } from '@elementor/editor-props';
|
|
5
4
|
import { useActiveBreakpoint } from '@elementor/editor-responsive';
|
|
6
5
|
import { type StyleDefinitionID, type StyleDefinitionState } from '@elementor/editor-styles';
|
|
7
6
|
import { SessionStorageProvider } from '@elementor/session';
|
|
@@ -12,6 +11,7 @@ import { ClassesPropProvider } from '../contexts/classes-prop-context';
|
|
|
12
11
|
import { useElement } from '../contexts/element-context';
|
|
13
12
|
import { StyleProvider } from '../contexts/style-context';
|
|
14
13
|
import { StyleInheritanceProvider } from '../contexts/styles-inheritance-context';
|
|
14
|
+
import { useActiveStyleDefId } from '../hooks/use-active-style-def-id';
|
|
15
15
|
import { CssClassSelector } from './css-classes/css-class-selector';
|
|
16
16
|
import { Section } from './section';
|
|
17
17
|
import { SectionsList } from './sections-list';
|
|
@@ -78,23 +78,6 @@ export const StyleTab = () => {
|
|
|
78
78
|
);
|
|
79
79
|
};
|
|
80
80
|
|
|
81
|
-
function useActiveStyleDefId( currentClassesProp: PropKey ) {
|
|
82
|
-
const [ activeStyledDefId, setActiveStyledDefId ] = useState< StyleDefinitionID | null >( null );
|
|
83
|
-
|
|
84
|
-
const fallback = useFirstElementStyleDef( currentClassesProp );
|
|
85
|
-
|
|
86
|
-
return [ activeStyledDefId || fallback?.id || null, setActiveStyledDefId ] as const;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
function useFirstElementStyleDef( currentClassesProp: PropKey ) {
|
|
90
|
-
const { element } = useElement();
|
|
91
|
-
|
|
92
|
-
const classesIds = useElementSetting< ClassesPropValue >( element.id, currentClassesProp )?.value || [];
|
|
93
|
-
const stylesDefs = getElementStyles( element.id ) ?? {};
|
|
94
|
-
|
|
95
|
-
return Object.values( stylesDefs ).find( ( styleDef ) => classesIds.includes( styleDef.id ) );
|
|
96
|
-
}
|
|
97
|
-
|
|
98
81
|
function useCurrentClassesProp(): string {
|
|
99
82
|
const { elementType } = useElement();
|
|
100
83
|
|
|
@@ -52,7 +52,7 @@ export function useStyle() {
|
|
|
52
52
|
|
|
53
53
|
export function getProviderByStyleId( styleId: StyleDefinitionID ) {
|
|
54
54
|
const styleProvider = stylesRepository.getProviders().find( ( provider ) => {
|
|
55
|
-
return provider.actions.
|
|
55
|
+
return provider.actions.all().find( ( style ) => style.id === styleId );
|
|
56
56
|
} );
|
|
57
57
|
|
|
58
58
|
return styleProvider ?? null;
|
|
@@ -9,10 +9,11 @@ import { createTopLevelOjectType } from './create-top-level-object-type';
|
|
|
9
9
|
|
|
10
10
|
export type StylesFieldProps = {
|
|
11
11
|
bind: PropKey;
|
|
12
|
+
placeholder?: PropValue;
|
|
12
13
|
children: React.ReactNode;
|
|
13
14
|
};
|
|
14
15
|
|
|
15
|
-
export const StylesField = ( { bind, children }: StylesFieldProps ) => {
|
|
16
|
+
export const StylesField = ( { bind, placeholder, children }: StylesFieldProps ) => {
|
|
16
17
|
const [ value, setValue ] = useStylesField( bind );
|
|
17
18
|
|
|
18
19
|
const stylesSchema = getStylesSchema();
|
|
@@ -20,6 +21,7 @@ export const StylesField = ( { bind, children }: StylesFieldProps ) => {
|
|
|
20
21
|
const propType = createTopLevelOjectType( { schema: stylesSchema } );
|
|
21
22
|
|
|
22
23
|
const values = { [ bind ]: value };
|
|
24
|
+
const placeholderValues = { [ bind ]: placeholder };
|
|
23
25
|
|
|
24
26
|
const setValues = ( newValue: Record< string, PropValue > ) => {
|
|
25
27
|
setValue( newValue[ bind ] );
|
|
@@ -34,7 +36,12 @@ export const StylesField = ( { bind, children }: StylesFieldProps ) => {
|
|
|
34
36
|
},
|
|
35
37
|
] }
|
|
36
38
|
>
|
|
37
|
-
<PropProvider
|
|
39
|
+
<PropProvider
|
|
40
|
+
propType={ propType }
|
|
41
|
+
value={ values }
|
|
42
|
+
setValue={ setValues }
|
|
43
|
+
placeholder={ placeholderValues }
|
|
44
|
+
>
|
|
38
45
|
<PropKeyProvider bind={ bind }>{ children }</PropKeyProvider>
|
|
39
46
|
</PropProvider>
|
|
40
47
|
</ControlAdornmentsProvider>
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { useState } from 'react';
|
|
2
|
+
import { getElementStyles, useElementSetting } from '@elementor/editor-elements';
|
|
3
|
+
import { type ClassesPropValue, type PropKey } from '@elementor/editor-props';
|
|
4
|
+
import { type StyleDefinitionID } from '@elementor/editor-styles';
|
|
5
|
+
|
|
6
|
+
import { useElement } from '../contexts/element-context';
|
|
7
|
+
|
|
8
|
+
export function useActiveStyleDefId( classProp: PropKey ) {
|
|
9
|
+
const [ activeStyledDefId, setActiveStyledDefId ] = useState< StyleDefinitionID | null >( null );
|
|
10
|
+
|
|
11
|
+
const appliedClassesIds = useAppliedClassesIds( classProp )?.value || [];
|
|
12
|
+
|
|
13
|
+
const fallback = useFirstAppliedClass( appliedClassesIds );
|
|
14
|
+
|
|
15
|
+
const activeAndAppliedClassId = useActiveAndAppliedClassId( activeStyledDefId, appliedClassesIds );
|
|
16
|
+
return [ activeAndAppliedClassId || fallback?.id || null, setActiveStyledDefId ] as const;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function useFirstAppliedClass( appliedClassesIds: string[] ) {
|
|
20
|
+
const { element } = useElement();
|
|
21
|
+
const stylesDefs = getElementStyles( element.id ) ?? {};
|
|
22
|
+
|
|
23
|
+
return Object.values( stylesDefs ).find( ( styleDef ) => appliedClassesIds.includes( styleDef.id ) );
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function useAppliedClassesIds( classProp: PropKey ) {
|
|
27
|
+
const { element } = useElement();
|
|
28
|
+
|
|
29
|
+
return useElementSetting< ClassesPropValue >( element.id, classProp );
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function useActiveAndAppliedClassId( id: StyleDefinitionID | null, appliedClassesIds: string[] ) {
|
|
33
|
+
const isClassApplied = !! id && appliedClassesIds.includes( id );
|
|
34
|
+
|
|
35
|
+
return isClassApplied ? id : null;
|
|
36
|
+
}
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
import type { Props } from '@elementor/editor-props';
|
|
10
10
|
import { getVariantByMeta, type StyleDefinition, type StyleDefinitionVariant } from '@elementor/editor-styles';
|
|
11
11
|
import { type StylesProvider } from '@elementor/editor-styles-repository';
|
|
12
|
-
import {
|
|
12
|
+
import { ELEMENTS_STYLES_RESERVED_LABEL } from '@elementor/editor-styles-repository';
|
|
13
13
|
import { undoable } from '@elementor/editor-v1-adapters';
|
|
14
14
|
import { __ } from '@wordpress/i18n';
|
|
15
15
|
|
|
@@ -78,10 +78,10 @@ function getProps< T extends Props >( { styleId, elementId, provider, meta, prop
|
|
|
78
78
|
return null;
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
-
const style = provider.actions.
|
|
81
|
+
const style = provider.actions.get( styleId, { elementId } );
|
|
82
82
|
|
|
83
83
|
if ( ! style ) {
|
|
84
|
-
throw new StyleNotFoundUnderProviderError( { context: { styleId, providerKey: provider.
|
|
84
|
+
throw new StyleNotFoundUnderProviderError( { context: { styleId, providerKey: provider.getKey() } } );
|
|
85
85
|
}
|
|
86
86
|
|
|
87
87
|
const variant = getVariantByMeta( style, meta );
|
|
@@ -100,7 +100,7 @@ function useUndoableCreateElementStyle() {
|
|
|
100
100
|
do: ( payload: UndoableCreateElementStyleArgs ) => {
|
|
101
101
|
return createElementStyle( {
|
|
102
102
|
...payload,
|
|
103
|
-
label:
|
|
103
|
+
label: ELEMENTS_STYLES_RESERVED_LABEL,
|
|
104
104
|
} );
|
|
105
105
|
},
|
|
106
106
|
|
|
@@ -112,7 +112,7 @@ function useUndoableCreateElementStyle() {
|
|
|
112
112
|
return createElementStyle( {
|
|
113
113
|
...payload,
|
|
114
114
|
styleId,
|
|
115
|
-
label:
|
|
115
|
+
label: ELEMENTS_STYLES_RESERVED_LABEL,
|
|
116
116
|
} );
|
|
117
117
|
},
|
|
118
118
|
},
|
|
@@ -139,11 +139,11 @@ function useUndoableUpdateStyle() {
|
|
|
139
139
|
do: ( { elementId, styleId, provider, meta, props }: UndoableUpdateStyleArgs ) => {
|
|
140
140
|
if ( ! provider.actions.updateProps ) {
|
|
141
141
|
throw new StylesProviderCannotUpdatePropsError( {
|
|
142
|
-
context: { providerKey: provider.
|
|
142
|
+
context: { providerKey: provider.getKey() },
|
|
143
143
|
} );
|
|
144
144
|
}
|
|
145
145
|
|
|
146
|
-
const style = provider.actions.
|
|
146
|
+
const style = provider.actions.get( styleId, { elementId } );
|
|
147
147
|
|
|
148
148
|
const prevProps = getCurrentProps( style, meta );
|
|
149
149
|
|
package/src/index.ts
CHANGED
|
@@ -4,6 +4,4 @@ export { replaceControl } from './control-replacement';
|
|
|
4
4
|
export { injectIntoClassSelectorActions } from './components/css-classes/css-class-selector';
|
|
5
5
|
export { usePanelActions, usePanelStatus } from './panel';
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
init();
|
|
7
|
+
export { init } from './init';
|
package/src/init.ts
CHANGED
|
@@ -8,7 +8,7 @@ import { init as initDynamics } from './dynamics/init';
|
|
|
8
8
|
import { panel } from './panel';
|
|
9
9
|
import { isAtomicWidgetSelected } from './sync/is-atomic-widget-selected';
|
|
10
10
|
|
|
11
|
-
export
|
|
11
|
+
export function init() {
|
|
12
12
|
registerPanel( panel );
|
|
13
13
|
blockV1Panel();
|
|
14
14
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { filterEmptyValues } from '@elementor/editor-props';
|
|
1
2
|
import { type BreakpointId, type BreakpointNode } from '@elementor/editor-responsive';
|
|
2
3
|
import { type StyleDefinitionState } from '@elementor/editor-styles';
|
|
3
4
|
|
|
@@ -141,13 +142,19 @@ function buildInitialSnapshotFromStyles( styles: StyleVariantDetails[] ): Styles
|
|
|
141
142
|
} = styleData;
|
|
142
143
|
|
|
143
144
|
Object.entries( props ).forEach( ( [ key, value ] ) => {
|
|
145
|
+
const filteredValue = filterEmptyValues( value );
|
|
146
|
+
|
|
147
|
+
if ( filteredValue === null ) {
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
|
|
144
151
|
if ( ! snapshot[ key ] ) {
|
|
145
152
|
snapshot[ key ] = [];
|
|
146
153
|
}
|
|
147
154
|
|
|
148
155
|
const snapshotPropValue: SnapshotPropValue = {
|
|
149
156
|
...styleData,
|
|
150
|
-
value,
|
|
157
|
+
value: filteredValue,
|
|
151
158
|
};
|
|
152
159
|
|
|
153
160
|
snapshot[ key ].push( snapshotPropValue );
|
|
@@ -22,7 +22,7 @@ function buildStyleVariantsByMetaMapping( styleDefs: StyleDefinition[] ): Breakp
|
|
|
22
22
|
const breakpointStateSlots: BreakpointsStatesStyles = {};
|
|
23
23
|
|
|
24
24
|
styleDefs.forEach( ( styleDef ) => {
|
|
25
|
-
const provider = getProviderByStyleId( styleDef.id )?.
|
|
25
|
+
const provider = getProviderByStyleId( styleDef.id )?.getKey() ?? null;
|
|
26
26
|
|
|
27
27
|
// iterate over each style definition's variants and place them in the corresponding breakpoint's base or state styles
|
|
28
28
|
styleDef.variants.forEach( ( variant ) => {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { useBoundProp } from '@elementor/editor-controls';
|
|
3
|
-
import { ELEMENTS_BASE_STYLES_PROVIDER_KEY,
|
|
3
|
+
import { ELEMENTS_BASE_STYLES_PROVIDER_KEY, isElementsStylesProvider } from '@elementor/editor-styles-repository';
|
|
4
4
|
import { __ } from '@wordpress/i18n';
|
|
5
5
|
|
|
6
6
|
import { StyleIndicator } from '../components/style-indicator';
|
|
@@ -35,7 +35,7 @@ export const StylesInheritanceIndicator = () => {
|
|
|
35
35
|
return (
|
|
36
36
|
<StyleIndicator
|
|
37
37
|
aria-label={ __( 'This is the final value', 'elementor' ) }
|
|
38
|
-
variant={ currentStyleProvider?.
|
|
38
|
+
variant={ isElementsStylesProvider( currentStyleProvider?.getKey() ) ? 'local' : 'global' }
|
|
39
39
|
/>
|
|
40
40
|
);
|
|
41
41
|
}
|