@elementor/editor-editing-panel 1.24.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.
Files changed (36) hide show
  1. package/CHANGELOG.md +102 -0
  2. package/dist/index.d.mts +3 -1
  3. package/dist/index.d.ts +3 -1
  4. package/dist/index.js +448 -309
  5. package/dist/index.js.map +1 -1
  6. package/dist/index.mjs +426 -287
  7. package/dist/index.mjs.map +1 -1
  8. package/package.json +11 -10
  9. package/src/components/css-classes/css-class-item.tsx +8 -10
  10. package/src/components/css-classes/css-class-menu.tsx +60 -12
  11. package/src/components/css-classes/css-class-selector.tsx +28 -27
  12. package/src/components/editing-panel-tabs.tsx +1 -8
  13. package/src/components/multi-combobox.tsx +3 -0
  14. package/src/components/style-indicator.tsx +23 -0
  15. package/src/components/style-sections/border-section/border-radius-field.tsx +4 -5
  16. package/src/components/style-sections/border-section/border-width-field.tsx +2 -3
  17. package/src/components/style-sections/layout-section/display-field.tsx +34 -28
  18. package/src/components/style-sections/layout-section/flex-size-field.tsx +28 -18
  19. package/src/components/style-sections/layout-section/layout-section.tsx +14 -2
  20. package/src/components/style-sections/typography-section/text-alignment-field.tsx +5 -6
  21. package/src/components/style-tab.tsx +2 -19
  22. package/src/contexts/style-context.tsx +2 -2
  23. package/src/controls-registry/control-type-container.tsx +2 -2
  24. package/src/controls-registry/styles-field.tsx +9 -2
  25. package/src/dynamics/dynamic-transformer.ts +61 -0
  26. package/src/dynamics/errors.ts +6 -0
  27. package/src/dynamics/init.ts +6 -0
  28. package/src/dynamics/types.ts +17 -0
  29. package/src/hooks/use-active-style-def-id.ts +36 -0
  30. package/src/hooks/use-styles-fields.ts +7 -7
  31. package/src/index.ts +1 -3
  32. package/src/init.ts +1 -1
  33. package/src/styles-inheritance/create-snapshots-manager.ts +16 -9
  34. package/src/styles-inheritance/create-styles-inheritance.ts +8 -4
  35. package/src/styles-inheritance/styles-inheritance-indicator.tsx +13 -31
  36. package/src/styles-inheritance/types.ts +7 -6
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elementor/editor-editing-panel",
3
- "version": "1.24.0",
3
+ "version": "1.28.0",
4
4
  "private": false,
5
5
  "author": "Elementor Team",
6
6
  "homepage": "https://elementor.com/",
@@ -39,16 +39,17 @@
39
39
  "dev": "tsup --config=../../tsup.dev.ts"
40
40
  },
41
41
  "dependencies": {
42
- "@elementor/editor": "0.18.5",
43
- "@elementor/editor-controls": "0.21.0",
42
+ "@elementor/editor": "0.18.6",
43
+ "@elementor/editor-canvas": "0.18.0",
44
+ "@elementor/editor-controls": "0.25.0",
44
45
  "@elementor/editor-current-user": "0.3.0",
45
- "@elementor/editor-elements": "0.7.0",
46
- "@elementor/editor-panels": "0.14.0",
47
- "@elementor/editor-props": "0.11.1",
48
- "@elementor/editor-responsive": "0.13.3",
49
- "@elementor/editor-styles": "0.6.4",
50
- "@elementor/editor-styles-repository": "0.8.1",
51
- "@elementor/editor-ui": "0.5.1",
46
+ "@elementor/editor-elements": "0.8.1",
47
+ "@elementor/editor-panels": "0.14.1",
48
+ "@elementor/editor-props": "0.12.0",
49
+ "@elementor/editor-responsive": "0.13.4",
50
+ "@elementor/editor-styles": "0.6.6",
51
+ "@elementor/editor-styles-repository": "0.8.4",
52
+ "@elementor/editor-ui": "0.7.1",
52
53
  "@elementor/editor-v1-adapters": "0.11.0",
53
54
  "@elementor/icons": "1.37.0",
54
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
- if ( ! stylesRepository.isLabelValid( newLabel ) ) {
157
- return __( 'Format is not valid', 'elementor' );
158
- }
156
+ const result = validateStyleLabel( newLabel );
159
157
 
160
- if ( stylesRepository.isLabelExist( newLabel ) ) {
161
- return __( 'Existing name', 'elementor' );
158
+ if ( result.isValid ) {
159
+ return null;
162
160
  }
163
161
 
164
- return null;
162
+ return result.error;
165
163
  };
@@ -1,31 +1,37 @@
1
1
  import * as React from 'react';
2
2
  import { type StyleDefinitionState } from '@elementor/editor-styles';
3
- import { stylesRepository } from '@elementor/editor-styles-repository';
3
+ import { isElementsStylesProvider, stylesRepository } from '@elementor/editor-styles-repository';
4
4
  import { MenuListItem } from '@elementor/editor-ui';
5
- import { bindMenu, Divider, Menu, MenuSubheader, type PopupState } from '@elementor/ui';
5
+ import { bindMenu, Divider, Menu, MenuSubheader, type PopupState, Stack } from '@elementor/ui';
6
6
  import { __ } from '@wordpress/i18n';
7
7
 
8
8
  import { useStyle } from '../../contexts/style-context';
9
9
  import { useUnapplyClass } from '../../hooks/use-unapply-class';
10
+ import { type StyleDefinitionStateWithNormal } from '../../styles-inheritance/types';
11
+ import { StyleIndicator, type StyleIndicatorVariant } from '../style-indicator';
10
12
 
11
13
  const STATES: NonNullable< StyleDefinitionState >[] = [ 'hover', 'focus', 'active' ];
12
14
 
13
15
  type CssClassMenuProps = {
14
16
  styleId: string | null;
15
- provider: string;
17
+ provider: string | null;
16
18
  popupState: PopupState;
17
19
  handleRename: () => void;
18
20
  anchorEl: HTMLElement | null;
19
21
  };
20
22
 
21
23
  export function CssClassMenu( { styleId, provider, popupState, handleRename, anchorEl }: CssClassMenuProps ) {
24
+ const styledStates = useStyledStates( styleId );
25
+
26
+ const indicatorVariant = ! provider || isElementsStylesProvider( provider ) ? 'local' : 'global';
27
+
22
28
  const handleKeyDown = ( e: React.KeyboardEvent< HTMLElement > ) => {
23
29
  e.stopPropagation();
24
30
  };
25
31
 
26
32
  return (
27
33
  <Menu
28
- MenuListProps={ { dense: true } }
34
+ MenuListProps={ { dense: true, sx: { minWidth: '160px' } } }
29
35
  { ...bindMenu( popupState ) }
30
36
  anchorEl={ anchorEl }
31
37
  anchorOrigin={ {
@@ -37,34 +43,62 @@ export function CssClassMenu( { styleId, provider, popupState, handleRename, anc
37
43
  vertical: -4,
38
44
  } }
39
45
  onKeyDown={ handleKeyDown }
46
+ // Workaround for focus-visible issue.
47
+ disableAutoFocusItem
40
48
  >
41
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 */ }
42
50
  { getMenuItemsByProvider( { provider, styleId, handleRename, closeMenu: popupState.close } ) }
43
51
  <MenuSubheader sx={ { typography: 'caption', color: 'text.secondary', pb: 0.5, pt: 1 } }>
44
- { __( 'Pseudo classes', 'elementor' ) }
52
+ { __( 'States', 'elementor' ) }
45
53
  </MenuSubheader>
46
- <StateMenuItem key="normal" state={ null } styleId={ styleId } closeMenu={ popupState.close } />
54
+ <StateMenuItem
55
+ key="normal"
56
+ state={ null }
57
+ styleId={ styleId }
58
+ closeMenu={ popupState.close }
59
+ isStyled={ styledStates.normal }
60
+ indicatorVariant={ indicatorVariant }
61
+ />
47
62
  { STATES.map( ( state ) => {
48
63
  return (
49
- <StateMenuItem key={ state } state={ state } styleId={ styleId } closeMenu={ popupState.close } />
64
+ <StateMenuItem
65
+ key={ state }
66
+ state={ state }
67
+ styleId={ styleId }
68
+ closeMenu={ popupState.close }
69
+ isStyled={ styledStates[ state ] }
70
+ indicatorVariant={ indicatorVariant }
71
+ />
50
72
  );
51
73
  } ) }
52
74
  </Menu>
53
75
  );
54
76
  }
55
77
 
78
+ function useStyledStates( styleId: string | null ): Partial< Record< StyleDefinitionStateWithNormal, true > > {
79
+ const { meta } = useStyle();
80
+
81
+ const styleDef = stylesRepository.all().find( ( style ) => style.id === styleId );
82
+
83
+ return Object.fromEntries(
84
+ styleDef?.variants
85
+ .filter( ( variant ) => meta.breakpoint === variant.meta.breakpoint )
86
+ .map( ( variant ) => [ variant.meta.state ?? 'normal', true ] ) ?? []
87
+ );
88
+ }
89
+
56
90
  function getMenuItemsByProvider( {
57
91
  provider,
58
92
  styleId,
59
93
  handleRename,
60
94
  closeMenu,
61
95
  }: {
62
- provider: string;
96
+ provider: string | null;
63
97
  styleId: string | null;
64
98
  handleRename: () => void;
65
99
  closeMenu: () => void;
66
100
  } ) {
67
- if ( ! styleId ) {
101
+ if ( ! styleId || ! provider ) {
68
102
  return [];
69
103
  }
70
104
 
@@ -82,7 +116,7 @@ function getMenuItemsByProvider( {
82
116
  actions.unshift(
83
117
  <MenuSubheader
84
118
  key="provider-label"
85
- sx={ { typography: 'caption', color: 'text.secondary', pb: 0.5, pt: 1 } }
119
+ sx={ { typography: 'caption', color: 'text.secondary', pb: 0.5, pt: 1, textTransform: 'capitalize' } }
86
120
  >
87
121
  { providerInstance?.labels?.singular }
88
122
  </MenuSubheader>
@@ -97,9 +131,18 @@ type StateMenuItemProps = {
97
131
  state: StyleDefinitionState;
98
132
  styleId: string | null;
99
133
  closeMenu: () => void;
134
+ isStyled?: boolean;
135
+ indicatorVariant: StyleIndicatorVariant;
100
136
  };
101
137
 
102
- function StateMenuItem( { state, styleId, closeMenu, ...props }: StateMenuItemProps ) {
138
+ function StateMenuItem( {
139
+ state,
140
+ styleId,
141
+ closeMenu,
142
+ isStyled = false,
143
+ indicatorVariant,
144
+ ...props
145
+ }: StateMenuItemProps ) {
103
146
  const { id: activeId, setId: setActiveId, setMetaState: setActiveMetaState, meta } = useStyle();
104
147
  const { state: activeState } = meta;
105
148
 
@@ -121,7 +164,12 @@ function StateMenuItem( { state, styleId, closeMenu, ...props }: StateMenuItemPr
121
164
  closeMenu();
122
165
  } }
123
166
  >
124
- { state ? state : 'Normal' }
167
+ <Stack gap={ 0.75 } direction="row" alignItems="center">
168
+ { isStyled && (
169
+ <StyleIndicator aria-label={ __( 'Has style', 'elementor' ) } variant={ indicatorVariant } />
170
+ ) }
171
+ { state ?? 'normal' }
172
+ </Stack>
125
173
  </MenuListItem>
126
174
  );
127
175
  }
@@ -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
- ELEMENTS_STYLES_PROVIDER_KEY,
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, Stack, Typography } from '@elementor/ui';
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: ELEMENTS_STYLES_PROVIDER_KEY,
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 gap={ 1 } p={ 2 }>
67
+ <Stack p={ 2 }>
65
68
  <Stack direction="row" gap={ 1 } alignItems="center" justifyContent="space-between">
66
- <Typography component="label" variant="caption" htmlFor={ ID }>
67
- { __( 'CSS classes', 'elementor' ) }
68
- </Typography>
69
+ <FormLabel htmlFor={ ID } size="small">
70
+ { __( 'Classes', 'elementor' ) }
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.key === ELEMENTS_STYLES_PROVIDER_KEY;
136
- const styleDefs = provider.actions.get( { elementId: element.id } );
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,8 +155,9 @@ function useOptions() {
147
155
  fixed: isElements,
148
156
  color: isElements ? 'accent' : 'global',
149
157
  icon: isElements ? <MapPinIcon /> : null,
150
- provider: provider.key,
151
- group: provider.labels?.plural,
158
+ provider: provider.getKey(),
159
+ // translators: %s is the plural label of the provider (e.g "Existing classes").
160
+ group: __( 'Existing %s', 'elementor' ).replace( '%s', provider.labels?.plural ?? '' ),
152
161
  };
153
162
  } );
154
163
  } );
@@ -164,10 +173,10 @@ function useCreateActions( {
164
173
  return useCreateActionsByProvider().map( ( [ provider, create ] ): Action< StyleDefOption > => {
165
174
  return {
166
175
  // translators: %s is the label of the new class.
167
- label: ( value ) => __( 'Create new "%s"', 'elementor' ).replace( '%s', value ),
168
- // translators: %s is the singular label of css class provider (e.g "Global CSS Class").
169
- group: __( 'Create New %s', 'elementor' ).replace( '%s', provider.labels?.singular ?? '' ),
170
- condition: ( _, inputValue ) => isLabelValid( inputValue ) && ! hasReachedLimit( provider ),
176
+ label: ( value ) => __( 'Create "%s"', 'elementor' ).replace( '%s', value ),
177
+ // translators: %s is the singular label of css class provider (e.g "CSS Class").
178
+ group: __( 'Create a new %s', 'elementor' ).replace( '%s', provider.labels?.singular ?? '' ),
179
+ condition: ( _, inputValue ) => validateStyleLabel( inputValue ).isValid && ! hasReachedLimit( provider ),
171
180
  apply: ( label ) => {
172
181
  const createdId = create( label );
173
182
 
@@ -183,22 +192,14 @@ function useCreateActions( {
183
192
  }
184
193
 
185
194
  function hasReachedLimit( provider: StylesProvider ) {
186
- if ( provider.limit === undefined ) {
187
- return false;
188
- }
189
-
190
- return provider.actions.get().length >= provider.limit;
191
- }
192
-
193
- function isLabelValid( newLabel: string ) {
194
- return stylesRepository.isLabelValid( newLabel ) && ! stylesRepository.isLabelExist( newLabel );
195
+ return provider.actions.all().length >= provider.limit;
195
196
  }
196
197
 
197
198
  function useAppliedOptions( options: StyleDefOption[], appliedIds: StyleDefinitionID[] ) {
198
199
  const applied = options.filter( ( option ) => option.value && appliedIds.includes( option.value ) );
199
200
 
200
201
  const hasElementsProviderStyleApplied = applied.some(
201
- ( option ) => option.provider === ELEMENTS_STYLES_PROVIDER_KEY
202
+ ( option ) => option.provider && isElementsStylesProvider( option.provider )
202
203
  );
203
204
 
204
205
  if ( ! hasElementsProviderStyleApplied ) {
@@ -19,14 +19,7 @@ export const EditingPanelTabs = () => {
19
19
  // Reference: https://react.dev/learn/preserving-and-resetting-state#resetting-a-form-with-a-key
20
20
  <Fragment key={ element.id }>
21
21
  <Stack direction="column" sx={ { width: '100%' } }>
22
- <Tabs
23
- variant="fullWidth"
24
- indicatorColor="secondary"
25
- textColor="inherit"
26
- size="small"
27
- sx={ { mt: 0.5 } }
28
- { ...getTabsProps() }
29
- >
22
+ <Tabs variant="fullWidth" size="small" sx={ { mt: 0.5 } } { ...getTabsProps() }>
30
23
  <Tab label={ __( 'General', 'elementor' ) } { ...getTabProps( 'settings' ) } />
31
24
  <Tab label={ __( 'Style', 'elementor' ) } { ...getTabProps( 'style' ) } />
32
25
  </Tabs>
@@ -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 ),
@@ -0,0 +1,23 @@
1
+ import { styled } from '@elementor/ui';
2
+
3
+ export type StyleIndicatorVariant = 'overridden' | 'local' | 'global';
4
+
5
+ export const StyleIndicator = styled( 'div', {
6
+ shouldForwardProp: ( prop ) => prop !== 'variant',
7
+ } )< { variant?: StyleIndicatorVariant } >`
8
+ width: 5px;
9
+ height: 5px;
10
+ border-radius: 50%;
11
+ background-color: ${ ( { theme, variant } ) => {
12
+ switch ( variant ) {
13
+ case 'overridden':
14
+ return theme.palette.warning.light;
15
+ case 'global':
16
+ return theme.palette.global.dark;
17
+ case 'local':
18
+ return theme.palette.accent.main;
19
+ default:
20
+ return theme.palette.text.disabled;
21
+ }
22
+ } };
23
+ `;
@@ -13,7 +13,6 @@ import { __ } from '@wordpress/i18n';
13
13
 
14
14
  import { StylesField } from '../../../controls-registry/styles-field';
15
15
  import { useDirection } from '../../../hooks/use-direction';
16
- import { RotatedIcon } from '../layout-section/utils/rotated-icon';
17
16
 
18
17
  const StartStartIcon = withDirection( RadiusTopLeftIcon );
19
18
  const StartEndIcon = withDirection( RadiusTopRightIcon );
@@ -32,22 +31,22 @@ const getEndEndLabel = ( isSiteRtl: boolean ) =>
32
31
  const getCorners = ( isSiteRtl: boolean ): EqualUnequalItems => [
33
32
  {
34
33
  label: getStartStartLabel( isSiteRtl ),
35
- icon: <RotatedIcon icon={ StartStartIcon } size="tiny" />,
34
+ icon: <StartStartIcon fontSize={ 'tiny' } />,
36
35
  bind: 'start-start',
37
36
  },
38
37
  {
39
38
  label: getStartEndLabel( isSiteRtl ),
40
- icon: <RotatedIcon icon={ StartEndIcon } size="tiny" />,
39
+ icon: <StartEndIcon fontSize={ 'tiny' } />,
41
40
  bind: 'start-end',
42
41
  },
43
42
  {
44
43
  label: getEndStartLabel( isSiteRtl ),
45
- icon: <RotatedIcon icon={ EndStartIcon } size="tiny" />,
44
+ icon: <EndStartIcon fontSize={ 'tiny' } />,
46
45
  bind: 'end-start',
47
46
  },
48
47
  {
49
48
  label: getEndEndLabel( isSiteRtl ),
50
- icon: <RotatedIcon icon={ EndEndIcon } size="tiny" />,
49
+ icon: <EndEndIcon fontSize={ 'tiny' } />,
51
50
  bind: 'end-end',
52
51
  },
53
52
  ];
@@ -7,7 +7,6 @@ import { __ } from '@wordpress/i18n';
7
7
 
8
8
  import { StylesField } from '../../../controls-registry/styles-field';
9
9
  import { useDirection } from '../../../hooks/use-direction';
10
- import { RotatedIcon } from '../layout-section/utils/rotated-icon';
11
10
 
12
11
  const InlineStartIcon = withDirection( SideRightIcon );
13
12
  const InlineEndIcon = withDirection( SideLeftIcon );
@@ -20,7 +19,7 @@ const getEdges = ( isSiteRtl: boolean ): EqualUnequalItems => [
20
19
  },
21
20
  {
22
21
  label: isSiteRtl ? __( 'Left', 'elementor' ) : __( 'Right', 'elementor' ),
23
- icon: <RotatedIcon icon={ InlineStartIcon } size="tiny" />,
22
+ icon: <InlineStartIcon fontSize={ 'tiny' } />,
24
23
  bind: 'inline-end',
25
24
  },
26
25
  {
@@ -30,7 +29,7 @@ const getEdges = ( isSiteRtl: boolean ): EqualUnequalItems => [
30
29
  },
31
30
  {
32
31
  label: isSiteRtl ? __( 'Right', 'elementor' ) : __( 'Left', 'elementor' ),
33
- icon: <RotatedIcon icon={ InlineEndIcon } size="tiny" />,
32
+ icon: <InlineEndIcon fontSize={ 'tiny' } />,
34
33
  bind: 'inline-start',
35
34
  },
36
35
  ];
@@ -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 options: 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
- ];
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={ options } fullWidth={ true } />
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;