@elementor/editor-editing-panel 1.9.0 → 1.11.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 (44) hide show
  1. package/CHANGELOG.md +105 -0
  2. package/dist/index.d.mts +1 -35
  3. package/dist/index.d.ts +1 -35
  4. package/dist/index.js +996 -1059
  5. package/dist/index.js.map +1 -1
  6. package/dist/index.mjs +905 -970
  7. package/dist/index.mjs.map +1 -1
  8. package/package.json +18 -14
  9. package/src/components/css-classes/css-class-item.tsx +130 -0
  10. package/src/components/css-classes/css-class-menu.tsx +151 -0
  11. package/src/components/{css-class-selector.tsx → css-classes/css-class-selector.tsx} +34 -160
  12. package/src/components/style-sections/layout-section/display-field.tsx +9 -1
  13. package/src/components/style-sections/layout-section/flex-order-field.tsx +5 -5
  14. package/src/components/style-sections/layout-section/flex-size-field.tsx +1 -1
  15. package/src/components/style-sections/layout-section/gap-control-field.tsx +0 -2
  16. package/src/components/style-sections/position-section/dimensions-field.tsx +1 -1
  17. package/src/components/style-sections/position-section/position-section.tsx +1 -1
  18. package/src/components/style-sections/typography-section/font-weight-field.tsx +9 -5
  19. package/src/components/style-sections/typography-section/text-alignment-field.tsx +16 -8
  20. package/src/components/style-sections/typography-section/transform-field.tsx +12 -3
  21. package/src/components/style-tab.tsx +1 -1
  22. package/src/contexts/style-context.tsx +36 -5
  23. package/src/controls-registry/control.tsx +3 -12
  24. package/src/controls-registry/controls-registry.tsx +3 -1
  25. package/src/controls-registry/settings-field.tsx +8 -1
  26. package/src/dynamics/components/dynamic-selection.tsx +1 -1
  27. package/src/dynamics/dynamic-control.tsx +1 -1
  28. package/src/dynamics/types.ts +2 -2
  29. package/src/dynamics/utils.ts +2 -2
  30. package/src/errors.ts +22 -0
  31. package/src/hooks/use-persist-dynamic-value.ts +1 -1
  32. package/src/hooks/use-styles-fields.ts +151 -9
  33. package/src/hooks/use-unapply-class.ts +4 -0
  34. package/src/index.ts +1 -2
  35. package/src/init.ts +2 -4
  36. package/src/sync/types.ts +4 -3
  37. package/src/components/collapsible-field.tsx +0 -36
  38. package/src/components/conditional-tooltip-wrapper.tsx +0 -58
  39. package/src/components/css-class-menu.tsx +0 -125
  40. package/src/components/editable-field.tsx +0 -166
  41. package/src/contexts/css-class-item-context.tsx +0 -31
  42. package/src/css-classes.ts +0 -45
  43. package/src/hooks/use-session-storage.ts +0 -46
  44. package/src/sync/enqueue-font.ts +0 -7
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elementor/editor-editing-panel",
3
- "version": "1.9.0",
3
+ "version": "1.11.0",
4
4
  "private": false,
5
5
  "author": "Elementor Team",
6
6
  "homepage": "https://elementor.com/",
@@ -39,25 +39,29 @@
39
39
  "dev": "tsup --config=../../tsup.dev.ts"
40
40
  },
41
41
  "dependencies": {
42
- "@elementor/editor": "0.17.4",
43
- "@elementor/editor-controls": "0.7.0",
44
- "@elementor/editor-elements": "0.5.0",
45
- "@elementor/menus": "0.1.3",
46
- "@elementor/editor-props": "0.8.0",
47
- "@elementor/editor-panels": "0.10.4",
48
- "@elementor/editor-responsive": "0.12.5",
49
- "@elementor/editor-styles": "0.5.3",
50
- "@elementor/editor-styles-repository": "0.5.0",
51
- "@elementor/editor-v1-adapters": "0.9.0",
52
- "@elementor/icons": "1.24.0",
42
+ "@elementor/editor": "0.18.0",
43
+ "@elementor/editor-controls": "0.9.0",
44
+ "@elementor/editor-elements": "0.5.2",
45
+ "@elementor/editor-panels": "0.11.0",
46
+ "@elementor/editor-props": "0.9.0",
47
+ "@elementor/editor-responsive": "0.13.0",
48
+ "@elementor/editor-styles": "0.5.5",
49
+ "@elementor/editor-styles-repository": "0.7.0",
50
+ "@elementor/editor-ui": "0.2.0",
51
+ "@elementor/editor-v1-adapters": "0.10.0",
52
+ "@elementor/icons": "1.31.0",
53
53
  "@elementor/locations": "0.7.6",
54
+ "@elementor/menus": "0.1.3",
54
55
  "@elementor/schema": "0.1.2",
55
56
  "@elementor/session": "0.1.0",
56
- "@elementor/ui": "1.23.3",
57
- "@elementor/utils": "0.3.0",
57
+ "@elementor/ui": "1.26.0",
58
+ "@elementor/utils": "0.3.1",
58
59
  "@wordpress/i18n": "^5.13.0"
59
60
  },
60
61
  "peerDependencies": {
61
62
  "react": "^18.3.1"
63
+ },
64
+ "devDependencies": {
65
+ "tsup": "^8.3.5"
62
66
  }
63
67
  }
@@ -0,0 +1,130 @@
1
+ import * as React from 'react';
2
+ import { useState } from 'react';
3
+ import { stylesRepository } from '@elementor/editor-styles-repository';
4
+ import { EditableField, EllipsisWithTooltip, useEditable } from '@elementor/editor-ui';
5
+ import { DotsVerticalIcon } from '@elementor/icons';
6
+ import {
7
+ type AutocompleteRenderGetTagProps,
8
+ bindTrigger,
9
+ Chip,
10
+ type ChipOwnProps,
11
+ Stack,
12
+ Typography,
13
+ UnstableChipGroup,
14
+ usePopupState,
15
+ } from '@elementor/ui';
16
+ import { __ } from '@wordpress/i18n';
17
+
18
+ import { useStyle } from '../../contexts/style-context';
19
+ import { CssClassMenu } from './css-class-menu';
20
+
21
+ type CssClassItemProps = {
22
+ id: string;
23
+ label: string;
24
+ provider: string;
25
+ isActive: boolean;
26
+ color: ChipOwnProps[ 'color' ];
27
+ chipProps: ReturnType< AutocompleteRenderGetTagProps >;
28
+ onClickActive: ( id: string ) => void;
29
+ renameLabel: ( newLabel: string ) => void;
30
+ validateLabel?: ( newLabel: string ) => string | undefined | null;
31
+ };
32
+
33
+ const CHIP_SIZE = 'tiny';
34
+
35
+ export function CssClassItem( {
36
+ id,
37
+ label,
38
+ provider,
39
+ isActive,
40
+ color: colorProp,
41
+ chipProps,
42
+ onClickActive,
43
+ renameLabel,
44
+ }: CssClassItemProps ) {
45
+ const { meta } = useStyle();
46
+ const popupState = usePopupState( { variant: 'popover' } );
47
+ const [ chipRef, setChipRef ] = useState< HTMLElement | null >( null );
48
+ const { onDelete, ...chipGroupProps } = chipProps;
49
+
50
+ const {
51
+ ref,
52
+ isEditing,
53
+ openEditMode,
54
+ error,
55
+ getProps: getEditableProps,
56
+ } = useEditable( {
57
+ value: label,
58
+ onSubmit: renameLabel,
59
+ validation: validateLabel,
60
+ } );
61
+
62
+ const color = error ? 'error' : colorProp;
63
+
64
+ const providerActions = stylesRepository.getProviderByKey( provider )?.actions;
65
+ const allowRename = Boolean( providerActions?.update );
66
+
67
+ return (
68
+ <>
69
+ <UnstableChipGroup ref={ setChipRef } { ...chipGroupProps } aria-label={ `Edit ${ label }` } role="group">
70
+ <Chip
71
+ size={ CHIP_SIZE }
72
+ label={
73
+ isEditing ? (
74
+ <EditableField ref={ ref } error={ error } { ...getEditableProps() } />
75
+ ) : (
76
+ <EllipsisWithTooltip maxWidth="10ch" title={ label } as="div" />
77
+ )
78
+ }
79
+ variant={ isActive && ! meta.state ? 'filled' : 'standard' }
80
+ color={ color }
81
+ onClick={ () => {
82
+ if ( isActive && allowRename ) {
83
+ openEditMode();
84
+ }
85
+
86
+ onClickActive( id );
87
+ } }
88
+ aria-pressed={ isActive }
89
+ sx={ {
90
+ '&.Mui-focusVisible': {
91
+ boxShadow: 'none !important',
92
+ },
93
+ } }
94
+ />
95
+ { ! isEditing && (
96
+ <Chip
97
+ size={ CHIP_SIZE }
98
+ label={
99
+ <Stack direction="row" gap={ 0.5 } alignItems="center">
100
+ { isActive && meta.state && <Typography variant="inherit">{ meta.state }</Typography> }
101
+ <DotsVerticalIcon fontSize="inherit" />
102
+ </Stack>
103
+ }
104
+ variant="filled"
105
+ color={ color }
106
+ { ...bindTrigger( popupState ) }
107
+ aria-label={ __( 'Open CSS Class Menu', 'elementor' ) }
108
+ />
109
+ ) }
110
+ </UnstableChipGroup>
111
+ <CssClassMenu
112
+ styleId={ id }
113
+ popupState={ popupState }
114
+ provider={ provider }
115
+ handleRename={ openEditMode }
116
+ anchorEl={ chipRef }
117
+ />
118
+ </>
119
+ );
120
+ }
121
+
122
+ const validateLabel = ( newLabel: string ) => {
123
+ if ( ! stylesRepository.isLabelValid( newLabel ) ) {
124
+ return __( 'Format is not valid', 'elementor' );
125
+ }
126
+
127
+ if ( stylesRepository.isLabelExist( newLabel ) ) {
128
+ return __( 'Existing name', 'elementor' );
129
+ }
130
+ };
@@ -0,0 +1,151 @@
1
+ import * as React from 'react';
2
+ import { type StyleDefinitionState } from '@elementor/editor-styles';
3
+ import { stylesRepository } from '@elementor/editor-styles-repository';
4
+ import { bindMenu, Divider, ListSubheader, Menu, MenuItem, type PopupState } from '@elementor/ui';
5
+ import { __ } from '@wordpress/i18n';
6
+
7
+ import { useStyle } from '../../contexts/style-context';
8
+ import { useUnapplyClass } from '../../hooks/use-unapply-class';
9
+
10
+ const STATES: NonNullable< StyleDefinitionState >[] = [ 'hover', 'focus', 'active' ];
11
+
12
+ type CssClassMenuProps = {
13
+ styleId: string;
14
+ provider: string;
15
+ popupState: PopupState;
16
+ handleRename: () => void;
17
+ anchorEl: HTMLElement | null;
18
+ };
19
+
20
+ export function CssClassMenu( { styleId, provider, popupState, handleRename, anchorEl }: CssClassMenuProps ) {
21
+ const handleKeyDown = ( e: React.KeyboardEvent< HTMLElement > ) => {
22
+ e.stopPropagation();
23
+ };
24
+
25
+ return (
26
+ <Menu
27
+ MenuListProps={ { dense: true } }
28
+ { ...bindMenu( popupState ) }
29
+ anchorEl={ anchorEl }
30
+ anchorOrigin={ {
31
+ vertical: 'bottom',
32
+ horizontal: 'left',
33
+ } }
34
+ transformOrigin={ {
35
+ horizontal: 'left',
36
+ vertical: -4,
37
+ } }
38
+ onKeyDown={ handleKeyDown }
39
+ >
40
+ { /* It has to be an array since MUI menu doesn't accept a Fragment as a child, and wrapping the items with an HTML element disrupts keyboard navigation */ }
41
+ { getMenuItemsByProvider( { provider, styleId, handleRename, closeMenu: popupState.close } ) }
42
+ <ListSubheader sx={ { typography: 'caption', color: 'text.secondary', pb: 0.5, pt: 1 } }>
43
+ { __( 'Pseudo selector', 'elementor' ) }
44
+ </ListSubheader>
45
+ { STATES.map( ( state ) => {
46
+ return <StateMenuItem key={ state } state={ state } styleId={ styleId } />;
47
+ } ) }
48
+ </Menu>
49
+ );
50
+ }
51
+
52
+ function getMenuItemsByProvider( {
53
+ provider,
54
+ styleId,
55
+ handleRename,
56
+ closeMenu,
57
+ }: {
58
+ provider: string;
59
+ styleId: string;
60
+ handleRename: () => void;
61
+ closeMenu: () => void;
62
+ } ) {
63
+ const providerInstance = stylesRepository.getProviderByKey( provider );
64
+ const providerActions = providerInstance?.actions;
65
+
66
+ const [ canUpdate, canDelete ] = [ providerActions?.update, providerActions?.delete ];
67
+
68
+ const actions = [
69
+ canUpdate && <RenameClassMenuItem key="rename-class" handleRename={ handleRename } closeMenu={ closeMenu } />,
70
+ canDelete && <UnapplyClassMenuItem key="unapply-class" styleId={ styleId } />,
71
+ ].filter( Boolean );
72
+
73
+ if ( actions.length ) {
74
+ actions.unshift(
75
+ <ListSubheader
76
+ key="provider-label"
77
+ sx={ { typography: 'caption', color: 'text.secondary', pb: 0.5, pt: 1 } }
78
+ >
79
+ { providerInstance?.labels?.singular }
80
+ </ListSubheader>
81
+ );
82
+ actions.push( <Divider key="provider-actions-divider" /> );
83
+ }
84
+
85
+ return actions;
86
+ }
87
+
88
+ type StateMenuItemProps = {
89
+ state: StyleDefinitionState;
90
+ styleId: string;
91
+ };
92
+
93
+ function StateMenuItem( { state, styleId, ...props }: StateMenuItemProps ) {
94
+ const { id: activeId, setId: setActiveId, setMetaState: setActiveMetaState, meta } = useStyle();
95
+ const { state: activeState } = meta;
96
+
97
+ const isActive = styleId === activeId;
98
+ const isSelected = state === activeState && isActive;
99
+
100
+ return (
101
+ <StyledMenuItem
102
+ { ...props }
103
+ selected={ isSelected }
104
+ sx={ { textTransform: 'capitalize' } }
105
+ onClick={ () => {
106
+ if ( ! isActive ) {
107
+ setActiveId( styleId );
108
+ }
109
+
110
+ setActiveMetaState( state );
111
+ } }
112
+ >
113
+ { state }
114
+ </StyledMenuItem>
115
+ );
116
+ }
117
+
118
+ function UnapplyClassMenuItem( { styleId, ...props }: { styleId: string } ) {
119
+ const unapplyClass = useUnapplyClass( styleId );
120
+
121
+ return (
122
+ <StyledMenuItem { ...props } onClick={ unapplyClass }>
123
+ { __( 'Remove', 'elementor' ) }
124
+ </StyledMenuItem>
125
+ );
126
+ }
127
+
128
+ function RenameClassMenuItem( {
129
+ handleRename,
130
+ closeMenu,
131
+ ...props
132
+ }: {
133
+ handleRename: () => void;
134
+ closeMenu: () => void;
135
+ } ) {
136
+ return (
137
+ <StyledMenuItem
138
+ { ...props }
139
+ onClick={ () => {
140
+ closeMenu();
141
+ handleRename();
142
+ } }
143
+ >
144
+ { __( 'Rename', 'elementor' ) }
145
+ </StyledMenuItem>
146
+ );
147
+ }
148
+
149
+ const StyledMenuItem = ( { ...props } ) => (
150
+ <MenuItem { ...props } sx={ { ...( props.sx ?? {} ), typography: 'caption', color: 'text.primary' } } />
151
+ );
@@ -1,37 +1,24 @@
1
1
  import * as React from 'react';
2
- import { useId, useRef } from 'react';
3
2
  import { getElementSetting, updateElementSettings, useElementSetting } from '@elementor/editor-elements';
4
3
  import { classesPropTypeUtil, type ClassesPropValue } from '@elementor/editor-props';
5
4
  import { type StyleDefinitionID } from '@elementor/editor-styles';
6
5
  import {
7
6
  ELEMENTS_STYLES_PROVIDER_KEY,
7
+ type StylesProvider,
8
8
  stylesRepository,
9
9
  type UpdateActionPayload,
10
- useAllStylesByProvider,
11
10
  useCreateActionsByProvider,
11
+ useProviders,
12
12
  } from '@elementor/editor-styles-repository';
13
- import { DotsVerticalIcon } from '@elementor/icons';
14
13
  import { createLocation } from '@elementor/locations';
15
- import {
16
- type AutocompleteRenderGetTagProps,
17
- bindTrigger,
18
- Chip,
19
- type ChipOwnProps,
20
- Stack,
21
- Typography,
22
- UnstableChipGroup,
23
- usePopupState,
24
- } from '@elementor/ui';
14
+ import { Chip, Stack, Typography } from '@elementor/ui';
25
15
  import { __ } from '@wordpress/i18n';
26
16
 
27
- import { useClassesProp } from '../contexts/classes-prop-context';
28
- import { CssClassItemProvider } from '../contexts/css-class-item-context';
29
- import { useElement } from '../contexts/element-context';
30
- import { useStyle } from '../contexts/style-context';
31
- import { ConditionalTooltipWrapper } from './conditional-tooltip-wrapper';
32
- import { CssClassMenu } from './css-class-menu';
33
- import { EditableField, EditableFieldProvider, useEditableField } from './editable-field';
34
- import { type Action, MultiCombobox, type Option } from './multi-combobox';
17
+ import { useClassesProp } from '../../contexts/classes-prop-context';
18
+ import { useElement } from '../../contexts/element-context';
19
+ import { useStyle } from '../../contexts/style-context';
20
+ import { type Action, MultiCombobox, type Option } from '../multi-combobox';
21
+ import { CssClassItem } from './css-class-item';
35
22
 
36
23
  const ID = 'elementor-css-class-selector';
37
24
  const TAGS_LIMIT = 8;
@@ -65,14 +52,13 @@ export function CssClassSelector() {
65
52
  const actions = useCreateActions( { pushAppliedId, setActiveId } );
66
53
 
67
54
  const handleApply = useHandleApply( appliedIds, setAppliedIds );
68
- const handleActivate = ( { value }: Option ) => setActiveId( value );
69
55
 
70
56
  const applied = useAppliedOptions( options, appliedIds );
71
57
  const active = applied.find( ( option ) => option.value === activeId ) ?? EMPTY_OPTION;
72
58
 
73
59
  return (
74
60
  <Stack gap={ 1 } p={ 2 }>
75
- <Stack direction="row" gap={ 1 } alignItems="baseline" justifyContent="space-between">
61
+ <Stack direction="row" gap={ 1 } alignItems="center" justifyContent="space-between">
76
62
  <Typography component="label" variant="caption" htmlFor={ ID }>
77
63
  { __( 'CSS Classes', 'elementor' ) }
78
64
  </Typography>
@@ -95,34 +81,26 @@ export function CssClassSelector() {
95
81
  values.map( ( value, index ) => {
96
82
  const chipProps = getTagProps( { index } );
97
83
  const isActive = value.value === active?.value;
84
+ const isElementsProvider = value.provider === ELEMENTS_STYLES_PROVIDER_KEY;
98
85
 
99
86
  const renameLabel = ( newLabel: string ) => {
100
87
  return updateClassByProvider( value.provider, { label: newLabel, id: value.value } );
101
88
  };
102
89
 
103
90
  return (
104
- <EditableFieldProvider
91
+ <CssClassItem
105
92
  key={ chipProps.key }
106
- value={ value.label }
107
- onSubmit={ renameLabel }
108
- editable={ value.provider !== ELEMENTS_STYLES_PROVIDER_KEY }
109
- validation={ ( newLabel ) =>
110
- renameValidation(
111
- newLabel,
112
- options.filter( ( option ) => option.value !== value.value )
113
- )
114
- }
115
- >
116
- <CssClassItem
117
- label={ value.label }
118
- id={ value.value }
119
- isActive={ isActive }
120
- isGlobal={ value.color === 'global' }
121
- color={ isActive && value.color ? value.color : 'default' }
122
- chipProps={ chipProps }
123
- onClickActive={ () => handleActivate( value ) }
124
- />
125
- </EditableFieldProvider>
93
+ label={ value.label }
94
+ provider={ value.provider }
95
+ id={ value.value }
96
+ isActive={ isActive }
97
+ color={ isActive && value.color ? value.color : 'default' }
98
+ chipProps={ chipProps }
99
+ // There is only a single local style, which might not exist, so setting it to
100
+ // `null` will either return the actual style or the fallback one.
101
+ onClickActive={ () => setActiveId( isElementsProvider ? null : value.value ) }
102
+ renameLabel={ renameLabel }
103
+ />
126
104
  );
127
105
  } )
128
106
  }
@@ -131,91 +109,6 @@ export function CssClassSelector() {
131
109
  );
132
110
  }
133
111
 
134
- type CssClassItemProps = {
135
- id: string;
136
- label: string;
137
- isActive: boolean;
138
- isGlobal: boolean;
139
- color: ChipOwnProps[ 'color' ];
140
- chipProps: ReturnType< AutocompleteRenderGetTagProps >;
141
- onClickActive: ( id: string ) => void;
142
- };
143
-
144
- const CHIP_SIZE = 'tiny';
145
-
146
- export function CssClassItem( {
147
- id,
148
- label,
149
- isActive,
150
- isGlobal,
151
- color: colorProp,
152
- chipProps,
153
- onClickActive,
154
- }: CssClassItemProps ) {
155
- const { meta } = useStyle();
156
- // TODO - resolve the useId issue with invalid characters upon CSS selectors (EDS-1089)
157
- const popupId = useId().replace( /:/g, '_' );
158
- const popupState = usePopupState( { variant: 'popover', popupId } );
159
- const chipRef = useRef< Element >( null );
160
- const { onDelete, ...chipGroupProps } = chipProps;
161
- const { isEditing, openEditMode, error, submitting } = useEditableField();
162
-
163
- const color = error ? 'error' : colorProp;
164
-
165
- return (
166
- <CssClassItemProvider styleId={ id } isActive={ isActive } isGlobal={ isGlobal }>
167
- <UnstableChipGroup ref={ chipRef } { ...chipGroupProps } aria-label={ `Edit ${ label }` } role="group">
168
- <Chip
169
- disabled={ submitting }
170
- size={ CHIP_SIZE }
171
- label={
172
- <EditableField
173
- onDoubleClick={ () => {
174
- if ( ! isActive ) {
175
- openEditMode();
176
- }
177
- } }
178
- onClick={ () => {
179
- if ( isActive ) {
180
- openEditMode();
181
- }
182
- } }
183
- >
184
- <ConditionalTooltipWrapper maxWidth="10ch" title={ label } />
185
- </EditableField>
186
- }
187
- variant={ isActive && ! meta.state ? 'filled' : 'standard' }
188
- color={ color }
189
- onClick={ () => onClickActive( id ) }
190
- aria-pressed={ isActive }
191
- sx={ {
192
- '&.Mui-focusVisible': {
193
- boxShadow: 'none !important',
194
- },
195
- } }
196
- />
197
- { ! isEditing && (
198
- <Chip
199
- disabled={ submitting }
200
- size={ CHIP_SIZE }
201
- label={
202
- <Stack direction="row" gap={ 0.5 } alignItems="center">
203
- { isActive && meta.state && <Typography variant="inherit">{ meta.state }</Typography> }
204
- <DotsVerticalIcon fontSize="inherit" />
205
- </Stack>
206
- }
207
- variant="filled"
208
- color={ color }
209
- { ...bindTrigger( popupState ) }
210
- aria-label={ __( 'Open CSS Class Menu', 'elementor' ) }
211
- />
212
- ) }
213
- </UnstableChipGroup>
214
- <CssClassMenu popupState={ popupState } containerRef={ chipRef } />
215
- </CssClassItemProvider>
216
- );
217
- }
218
-
219
112
  const updateClassByProvider = ( provider: string, data: UpdateActionPayload ) => {
220
113
  const providerInstance = stylesRepository.getProviderByKey( provider );
221
114
 
@@ -226,34 +119,16 @@ const updateClassByProvider = ( provider: string, data: UpdateActionPayload ) =>
226
119
  return providerInstance.actions.update?.( data );
227
120
  };
228
121
 
229
- const VALID_SELECTOR_REGEX = /^[a-zA-Z0-9_-]+$/;
230
-
231
- const renameValidation = ( newLabel: string, options: Option[] ) => {
232
- if ( isNameExist( newLabel, options ) ) {
233
- return __( 'Existing name', 'elementor' );
234
- }
235
-
236
- if ( isCharactersNotSupported( newLabel ) ) {
237
- return __( 'Format is not valid', 'elementor' );
238
- }
239
- };
240
-
241
- const isNameExist = ( newLabel: string, options: Option[] ) => {
242
- if ( ! options?.length ) {
243
- return false;
244
- }
245
-
246
- return options.some( ( option ) => option.label.toLowerCase() === newLabel.toLowerCase() );
247
- };
248
-
249
- const isCharactersNotSupported = ( newLabel: string ) => ! VALID_SELECTOR_REGEX.test( newLabel );
250
-
251
122
  function useOptions() {
252
123
  const { element } = useElement();
253
124
 
254
- return useAllStylesByProvider( { elementId: element.id } ).flatMap< StyleDefOption >(
255
- ( [ provider, styleDefs ] ) => {
125
+ const isProviderEditable = ( provider: StylesProvider ) => !! provider.actions.updateProps;
126
+
127
+ return useProviders()
128
+ .filter( isProviderEditable )
129
+ .flatMap< StyleDefOption >( ( provider ) => {
256
130
  const isElements = provider.key === ELEMENTS_STYLES_PROVIDER_KEY;
131
+ const styleDefs = provider.actions.get( { elementId: element.id } );
257
132
 
258
133
  // Add empty local option for elements, as fallback.
259
134
  if ( isElements && styleDefs.length === 0 ) {
@@ -270,8 +145,7 @@ function useOptions() {
270
145
  group: provider.labels?.plural,
271
146
  };
272
147
  } );
273
- }
274
- );
148
+ } );
275
149
  }
276
150
 
277
151
  function useCreateActions( {
@@ -285,15 +159,15 @@ function useCreateActions( {
285
159
  return {
286
160
  // translators: %s is the label of the new class.
287
161
  label: ( value ) => __( 'Create new "%s"', 'elementor' ).replace( '%s', value ),
288
- apply: async ( value ) => {
289
- const created = await create( { label: value } );
162
+ apply: ( label ) => {
163
+ const createdId = create( label );
290
164
 
291
- if ( ! created ) {
165
+ if ( ! createdId ) {
292
166
  return;
293
167
  }
294
168
 
295
- pushAppliedId( created.id );
296
- setActiveId( created.id );
169
+ pushAppliedId( createdId );
170
+ setActiveId( createdId );
297
171
  },
298
172
  condition: ( options, inputValue ) => {
299
173
  const isUniqueLabel = ! options.some(
@@ -5,7 +5,7 @@ import { __ } from '@wordpress/i18n';
5
5
 
6
6
  import { StylesField } from '../../../controls-registry/styles-field';
7
7
 
8
- type Displays = 'block' | 'flex';
8
+ type Displays = 'block' | 'flex' | 'inline-block';
9
9
 
10
10
  export const DisplayField = () => {
11
11
  const options: ToggleButtonGroupItem< Displays >[] = [
@@ -13,11 +13,19 @@ export const DisplayField = () => {
13
13
  value: 'block',
14
14
  renderContent: () => __( 'Block', 'elementor' ),
15
15
  label: __( 'Block', 'elementor' ),
16
+ showTooltip: true,
16
17
  },
17
18
  {
18
19
  value: 'flex',
19
20
  renderContent: () => __( 'Flex', 'elementor' ),
20
21
  label: __( 'Flex', 'elementor' ),
22
+ showTooltip: true,
23
+ },
24
+ {
25
+ value: 'inline-block',
26
+ renderContent: () => __( 'In-blk', 'elementor' ),
27
+ label: __( 'Inline-block', 'elementor' ),
28
+ showTooltip: true,
21
29
  },
22
30
  ];
23
31
 
@@ -17,11 +17,11 @@ import { useStylesField } from '../../../hooks/use-styles-field';
17
17
 
18
18
  type GroupControlItemOption = 'first' | 'last' | 'custom';
19
19
 
20
- export const FIRST_DEFAULT_VALUE = -99999,
21
- LAST_DEFAULT_VALUE = 99999,
22
- FIRST = 'first',
23
- LAST = 'last',
24
- CUSTOM = 'custom';
20
+ export const FIRST_DEFAULT_VALUE = -99999;
21
+ export const LAST_DEFAULT_VALUE = 99999;
22
+ const FIRST = 'first';
23
+ const LAST = 'last';
24
+ const CUSTOM = 'custom';
25
25
 
26
26
  const orderValueMap = {
27
27
  [ FIRST ]: FIRST_DEFAULT_VALUE,
@@ -18,7 +18,7 @@ import { useStylesField } from '../../../hooks/use-styles-field';
18
18
 
19
19
  type GroupItem = 'flex-grow' | 'flex-shrink' | 'custom';
20
20
 
21
- export const DEFAULT = 1;
21
+ const DEFAULT = 1;
22
22
 
23
23
  const items: ToggleButtonGroupItem< GroupItem >[] = [
24
24
  {
@@ -5,8 +5,6 @@ import { __ } from '@wordpress/i18n';
5
5
 
6
6
  import { StylesField } from '../../../controls-registry/styles-field';
7
7
 
8
- export type Gap = 'column' | 'row';
9
-
10
8
  export const GapControlField = () => {
11
9
  return (
12
10
  <Stack gap={ 1 }>
@@ -6,7 +6,7 @@ import { __ } from '@wordpress/i18n';
6
6
 
7
7
  import { StylesField } from '../../../controls-registry/styles-field';
8
8
 
9
- export type Side = 'left' | 'right' | 'top' | 'bottom';
9
+ type Side = 'left' | 'right' | 'top' | 'bottom';
10
10
 
11
11
  const sideIcons = {
12
12
  left: <SideLeftIcon fontSize={ 'tiny' } />,