@elementor/editor-editing-panel 1.40.0 → 1.42.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 (50) hide show
  1. package/CHANGELOG.md +46 -0
  2. package/dist/index.d.mts +9 -0
  3. package/dist/index.d.ts +9 -0
  4. package/dist/index.js +1227 -745
  5. package/dist/index.js.map +1 -1
  6. package/dist/index.mjs +1133 -628
  7. package/dist/index.mjs.map +1 -1
  8. package/package.json +7 -6
  9. package/src/action.tsx +26 -0
  10. package/src/components/add-or-remove-content.tsx +11 -3
  11. package/src/components/css-classes/css-class-item.tsx +3 -2
  12. package/src/components/css-classes/css-class-menu.tsx +15 -5
  13. package/src/components/css-classes/css-class-selector.tsx +1 -0
  14. package/src/components/css-classes/use-apply-and-unapply-class.ts +8 -4
  15. package/src/components/section-content.tsx +16 -6
  16. package/src/components/style-sections/background-section/background-section.tsx +6 -3
  17. package/src/components/style-sections/border-section/border-field.tsx +3 -0
  18. package/src/components/style-sections/layout-section/display-field.tsx +2 -1
  19. package/src/components/style-sections/layout-section/flex-order-field.tsx +5 -2
  20. package/src/components/style-sections/layout-section/flex-size-field.tsx +16 -12
  21. package/src/components/style-sections/size-section/object-fit-field.tsx +2 -6
  22. package/src/components/style-sections/size-section/object-position-field.tsx +2 -6
  23. package/src/components/style-sections/size-section/size-section.tsx +4 -10
  24. package/src/components/style-sections/typography-section/text-stroke-field.tsx +3 -0
  25. package/src/components/style-tab.tsx +1 -1
  26. package/src/contexts/style-context.tsx +11 -2
  27. package/src/contexts/styles-inheritance-context.tsx +9 -7
  28. package/src/controls-actions.ts +2 -0
  29. package/src/controls-registry/styles-field.tsx +3 -0
  30. package/src/init.ts +11 -1
  31. package/src/reset-style-props.tsx +31 -0
  32. package/src/styles-inheritance/components/action-icons.tsx +8 -0
  33. package/src/styles-inheritance/components/breakpoint-icon.tsx +47 -0
  34. package/src/styles-inheritance/components/index.ts +4 -0
  35. package/src/styles-inheritance/components/label-chip.tsx +48 -0
  36. package/src/styles-inheritance/components/value-component.tsx +25 -0
  37. package/src/styles-inheritance/consts.ts +17 -0
  38. package/src/styles-inheritance/create-styles-inheritance.ts +50 -12
  39. package/src/styles-inheritance/hooks/use-normalized-inheritance-chain-items.tsx +121 -0
  40. package/src/styles-inheritance/init-styles-inheritance-transformers.ts +38 -0
  41. package/src/styles-inheritance/init.ts +8 -0
  42. package/src/styles-inheritance/styles-inheritance-indicator.tsx +35 -32
  43. package/src/styles-inheritance/styles-inheritance-infotip.tsx +169 -20
  44. package/src/styles-inheritance/styles-inheritance-transformers-registry.tsx +3 -0
  45. package/src/styles-inheritance/transformers/background-color-overlay-transformer.tsx +27 -0
  46. package/src/styles-inheritance/transformers/background-gradient-overlay-transformer.tsx +50 -0
  47. package/src/styles-inheritance/transformers/background-image-overlay-transformer.tsx +79 -0
  48. package/src/styles-inheritance/transformers/background-overlay-transformer.tsx +20 -0
  49. package/src/styles-inheritance/types.ts +8 -2
  50. package/src/hooks/use-normalized-inheritance-chain-items.tsx +0 -75
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elementor/editor-editing-panel",
3
- "version": "1.40.0",
3
+ "version": "1.42.0",
4
4
  "private": false,
5
5
  "author": "Elementor Team",
6
6
  "homepage": "https://elementor.com/",
@@ -40,8 +40,8 @@
40
40
  },
41
41
  "dependencies": {
42
42
  "@elementor/editor": "0.19.4",
43
- "@elementor/editor-canvas": "0.22.1",
44
- "@elementor/editor-controls": "0.33.0",
43
+ "@elementor/editor-canvas": "0.22.2",
44
+ "@elementor/editor-controls": "0.34.1",
45
45
  "@elementor/editor-current-user": "0.5.0",
46
46
  "@elementor/editor-documents": "0.13.6",
47
47
  "@elementor/editor-elements": "0.8.4",
@@ -49,16 +49,17 @@
49
49
  "@elementor/editor-props": "0.12.1",
50
50
  "@elementor/editor-responsive": "0.13.5",
51
51
  "@elementor/editor-styles": "0.6.8",
52
- "@elementor/editor-styles-repository": "0.10.0",
53
- "@elementor/editor-ui": "0.9.0",
52
+ "@elementor/editor-styles-repository": "0.10.1",
53
+ "@elementor/editor-ui": "0.10.0",
54
54
  "@elementor/editor-v1-adapters": "0.12.0",
55
- "@elementor/icons": "1.40.1",
55
+ "@elementor/icons": "1.44.0",
56
56
  "@elementor/locations": "0.8.0",
57
57
  "@elementor/menus": "0.1.5",
58
58
  "@elementor/schema": "0.1.2",
59
59
  "@elementor/session": "0.1.0",
60
60
  "@elementor/ui": "1.34.5",
61
61
  "@elementor/utils": "0.4.0",
62
+ "@elementor/wp-media": "0.6.0",
62
63
  "@wordpress/i18n": "^5.13.0"
63
64
  },
64
65
  "peerDependencies": {
package/src/action.tsx ADDED
@@ -0,0 +1,26 @@
1
+ import * as React from 'react';
2
+ import { type ElementType as ReactElementType } from 'react';
3
+ import { IconButton, Tooltip } from '@elementor/ui';
4
+
5
+ const SIZE = 'tiny';
6
+
7
+ type ActionProps = {
8
+ title: string;
9
+ visible?: boolean;
10
+ icon: ReactElementType;
11
+ onClick: () => void;
12
+ };
13
+
14
+ export default function Action( { title, visible = true, icon: Icon, onClick }: ActionProps ) {
15
+ if ( ! visible ) {
16
+ return null;
17
+ }
18
+
19
+ return (
20
+ <Tooltip placement="bottom" title={ title } arrow={ true }>
21
+ <IconButton aria-label={ title } size={ SIZE } onClick={ onClick }>
22
+ <Icon fontSize={ SIZE } />
23
+ </IconButton>
24
+ </Tooltip>
25
+ );
26
+ }
@@ -13,9 +13,17 @@ type Props = {
13
13
  isAdded: boolean;
14
14
  onAdd: () => void;
15
15
  onRemove: () => void;
16
+ disabled?: boolean;
16
17
  };
17
18
 
18
- export const AddOrRemoveContent = ( { isAdded, label, onAdd, onRemove, children }: PropsWithChildren< Props > ) => {
19
+ export const AddOrRemoveContent = ( {
20
+ isAdded,
21
+ label,
22
+ onAdd,
23
+ onRemove,
24
+ children,
25
+ disabled,
26
+ }: PropsWithChildren< Props > ) => {
19
27
  return (
20
28
  <SectionContent>
21
29
  <Stack
@@ -28,11 +36,11 @@ export const AddOrRemoveContent = ( { isAdded, label, onAdd, onRemove, children
28
36
  >
29
37
  <ControlLabel>{ label }</ControlLabel>
30
38
  { isAdded ? (
31
- <IconButton size={ SIZE } onClick={ onRemove } aria-label="Remove">
39
+ <IconButton size={ SIZE } onClick={ onRemove } aria-label="Remove" disabled={ disabled }>
32
40
  <MinusIcon fontSize={ SIZE } />
33
41
  </IconButton>
34
42
  ) : (
35
- <IconButton size={ SIZE } onClick={ onAdd } aria-label="Add">
43
+ <IconButton size={ SIZE } onClick={ onAdd } aria-label="Add" disabled={ disabled }>
36
44
  <PlusIcon fontSize={ SIZE } />
37
45
  </IconButton>
38
46
  ) }
@@ -24,6 +24,7 @@ type CssClassItemProps = {
24
24
  id: string | null;
25
25
  provider: string | null;
26
26
  label: string;
27
+ fixed?: boolean;
27
28
  isActive: boolean;
28
29
  color: ChipOwnProps[ 'color' ];
29
30
  icon: ReactElement | null;
@@ -37,7 +38,7 @@ type CssClassItemProps = {
37
38
  const CHIP_SIZE = 'tiny';
38
39
 
39
40
  export function CssClassItem( props: CssClassItemProps ) {
40
- const { chipProps, icon, color: colorProp, ...classProps } = props;
41
+ const { chipProps, icon, color: colorProp, fixed, ...classProps } = props;
41
42
  const { id, provider, label, isActive, onClickActive, renameLabel, setError } = classProps;
42
43
 
43
44
  const { meta, setMetaState } = useStyle();
@@ -139,7 +140,7 @@ export function CssClassItem( props: CssClassItemProps ) {
139
140
  ) }
140
141
  </UnstableChipGroup>
141
142
  <CssClassProvider { ...classProps } handleRename={ openEditMode }>
142
- <CssClassMenu popupState={ popupState } anchorEl={ chipRef } />
143
+ <CssClassMenu popupState={ popupState } anchorEl={ chipRef } fixed={ fixed } />
143
144
  </CssClassProvider>
144
145
  </>
145
146
  );
@@ -30,9 +30,10 @@ const STATES: State[] = [
30
30
  type CssClassMenuProps = {
31
31
  popupState: PopupState;
32
32
  anchorEl: HTMLElement | null;
33
+ fixed?: boolean;
33
34
  };
34
35
 
35
- export function CssClassMenu( { popupState, anchorEl }: CssClassMenuProps ) {
36
+ export function CssClassMenu( { popupState, anchorEl, fixed }: CssClassMenuProps ) {
36
37
  const { provider } = useCssClass();
37
38
 
38
39
  const handleKeyDown = ( e: React.KeyboardEvent< HTMLElement > ) => {
@@ -57,7 +58,7 @@ export function CssClassMenu( { popupState, anchorEl }: CssClassMenuProps ) {
57
58
  disableAutoFocusItem
58
59
  >
59
60
  { /* 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 */ }
60
- { getMenuItemsByProvider( { provider, closeMenu: popupState.close } ) }
61
+ { getMenuItemsByProvider( { provider, closeMenu: popupState.close, fixed } ) }
61
62
  <MenuSubheader sx={ { typography: 'caption', color: 'text.secondary', pb: 0.5, pt: 1 } }>
62
63
  { __( 'States', 'elementor' ) }
63
64
  </MenuSubheader>
@@ -80,7 +81,15 @@ function useModifiedStates( styleId: string | null ): Partial< Record< StyleDefi
80
81
  );
81
82
  }
82
83
 
83
- function getMenuItemsByProvider( { provider, closeMenu }: { provider: string | null; closeMenu: () => void } ) {
84
+ function getMenuItemsByProvider( {
85
+ provider,
86
+ closeMenu,
87
+ fixed,
88
+ }: {
89
+ provider: string | null;
90
+ closeMenu: () => void;
91
+ fixed?: boolean;
92
+ } ) {
84
93
  if ( ! provider ) {
85
94
  return [];
86
95
  }
@@ -88,11 +97,12 @@ function getMenuItemsByProvider( { provider, closeMenu }: { provider: string | n
88
97
  const providerInstance = stylesRepository.getProviderByKey( provider );
89
98
  const providerActions = providerInstance?.actions;
90
99
 
91
- const [ canUpdate, canDelete ] = [ providerActions?.update, providerActions?.delete ];
100
+ const canUpdate = providerActions?.update;
101
+ const canUnapply = ! fixed;
92
102
 
93
103
  const actions = [
94
104
  canUpdate && <RenameClassMenuItem key="rename-class" closeMenu={ closeMenu } />,
95
- canDelete && <UnapplyClassMenuItem key="unapply-class" closeMenu={ closeMenu } />,
105
+ canUnapply && <UnapplyClassMenuItem key="unapply-class" closeMenu={ closeMenu } />,
96
106
  ].filter( Boolean );
97
107
 
98
108
  if ( actions.length ) {
@@ -121,6 +121,7 @@ export function CssClassSelector() {
121
121
  return (
122
122
  <CssClassItem
123
123
  key={ chipProps.key }
124
+ fixed={ value.fixed }
124
125
  label={ value.label }
125
126
  provider={ value.provider }
126
127
  id={ value.value }
@@ -31,7 +31,6 @@ export function useApplyClass() {
31
31
  const prevActiveId = activeId;
32
32
 
33
33
  applyClass( classId );
34
- setDocumentModifiedStatus( true );
35
34
 
36
35
  return prevActiveId;
37
36
  },
@@ -76,7 +75,6 @@ export function useUnapplyClass() {
76
75
  const prevActiveId = activeId;
77
76
 
78
77
  unapplyClass( classId );
79
- setDocumentModifiedStatus( true );
80
78
 
81
79
  return prevActiveId;
82
80
  },
@@ -158,13 +156,19 @@ function useSetClasses() {
158
156
  const { element } = useElement();
159
157
  const currentClassesProp = useClassesProp();
160
158
 
159
+ const isVersion330Active = isExperimentActive( 'e_v_3_30' );
160
+
161
161
  return useMemo( () => {
162
162
  const setClasses = ( ids: StyleDefinitionID[] ) => {
163
163
  updateElementSettings( {
164
164
  id: element.id,
165
165
  props: { [ currentClassesProp ]: classesPropTypeUtil.create( ids ) },
166
- withHistory: false,
166
+ withHistory: isVersion330Active ? false : true,
167
167
  } );
168
+
169
+ if ( isVersion330Active ) {
170
+ setDocumentModifiedStatus( true );
171
+ }
168
172
  };
169
173
 
170
174
  const getAppliedClasses = () =>
@@ -174,5 +178,5 @@ function useSetClasses() {
174
178
  setClasses,
175
179
  getAppliedClasses,
176
180
  };
177
- }, [ currentClassesProp, element.id ] );
181
+ }, [ currentClassesProp, element.id, isVersion330Active ] );
178
182
  }
@@ -1,7 +1,11 @@
1
- import { type FC, type PropsWithChildren } from 'react';
1
+ import { createContext, type FC, type PropsWithChildren, useContext, useRef } from 'react';
2
2
  import * as React from 'react';
3
3
  import { Stack } from '@elementor/ui';
4
4
 
5
+ const SectionContentRefContext = createContext< React.RefObject< HTMLElement > | null >( null );
6
+
7
+ export const useSectionContentRef = () => useContext( SectionContentRefContext );
8
+
5
9
  type SectionContentProps = PropsWithChildren< {
6
10
  gap?: number;
7
11
  sx?: {
@@ -9,8 +13,14 @@ type SectionContentProps = PropsWithChildren< {
9
13
  };
10
14
  } >;
11
15
 
12
- export const SectionContent: FC< SectionContentProps > = ( { gap = 2, sx, children } ) => (
13
- <Stack gap={ gap } sx={ { ...sx } }>
14
- { children }
15
- </Stack>
16
- );
16
+ export const SectionContent: FC< SectionContentProps > = ( { gap = 2, sx, children } ) => {
17
+ const ref = useRef< HTMLElement >( null );
18
+
19
+ return (
20
+ <SectionContentRefContext.Provider value={ ref }>
21
+ <Stack gap={ gap } sx={ { ...sx } } ref={ ref }>
22
+ { children }
23
+ </Stack>
24
+ </SectionContentRefContext.Provider>
25
+ );
26
+ };
@@ -2,11 +2,14 @@ import * as React from 'react';
2
2
  import { BackgroundControl } from '@elementor/editor-controls';
3
3
 
4
4
  import { StylesField } from '../../../controls-registry/styles-field';
5
+ import { SectionContent } from '../../section-content';
5
6
 
6
7
  export const BackgroundSection = () => {
7
8
  return (
8
- <StylesField bind="background">
9
- <BackgroundControl />
10
- </StylesField>
9
+ <SectionContent>
10
+ <StylesField bind="background">
11
+ <BackgroundControl />
12
+ </StylesField>
13
+ </SectionContent>
11
14
  );
12
15
  };
@@ -1,6 +1,7 @@
1
1
  import * as React from 'react';
2
2
  import { __ } from '@wordpress/i18n';
3
3
 
4
+ import { useStyle } from '../../../contexts/style-context';
4
5
  import { useStylesFields } from '../../../hooks/use-styles-fields';
5
6
  import { AddOrRemoveContent } from '../../add-or-remove-content';
6
7
  import { BorderColorField } from './border-color-field';
@@ -14,6 +15,7 @@ const initialBorder = {
14
15
  };
15
16
 
16
17
  export const BorderField = () => {
18
+ const { canEdit } = useStyle();
17
19
  const [ border, setBorder ] = useStylesFields( Object.keys( initialBorder ) );
18
20
 
19
21
  const addBorder = () => {
@@ -36,6 +38,7 @@ export const BorderField = () => {
36
38
  isAdded={ hasBorder }
37
39
  onAdd={ addBorder }
38
40
  onRemove={ removeBorder }
41
+ disabled={ ! canEdit }
39
42
  >
40
43
  <BorderWidthField />
41
44
  <BorderColorField />
@@ -6,6 +6,7 @@ import { __ } from '@wordpress/i18n';
6
6
 
7
7
  import { useStylesInheritanceChain } from '../../../contexts/styles-inheritance-context';
8
8
  import { StylesField } from '../../../controls-registry/styles-field';
9
+ import { EXPERIMENTAL_FEATURES } from '../../../sync/experiments-flags';
9
10
  import { ControlLabel } from '../../control-label';
10
11
 
11
12
  type Displays = 'block' | 'flex' | 'inline-block' | 'inline-flex' | 'none';
@@ -32,7 +33,7 @@ const displayFieldItems: ToggleButtonGroupItem< Displays >[] = [
32
33
  ];
33
34
 
34
35
  export const DisplayField = () => {
35
- const isDisplayNoneFeatureActive = isExperimentActive( 'e_v_3_30' );
36
+ const isDisplayNoneFeatureActive = isExperimentActive( EXPERIMENTAL_FEATURES.V_3_30 );
36
37
  const items = [ ...displayFieldItems ];
37
38
 
38
39
  if ( isDisplayNoneFeatureActive ) {
@@ -6,6 +6,7 @@ import { ArrowDownSmallIcon, ArrowUpSmallIcon, PencilIcon } from '@elementor/ico
6
6
  import { DirectionProvider, Grid, ThemeProvider } from '@elementor/ui';
7
7
  import { __ } from '@wordpress/i18n';
8
8
 
9
+ import { useStyle } from '../../../contexts/style-context';
9
10
  import { StylesField } from '../../../controls-registry/styles-field';
10
11
  import { useDirection } from '../../../hooks/use-direction';
11
12
  import { useStylesField } from '../../../hooks/use-styles-field';
@@ -47,8 +48,9 @@ const items: ToggleButtonGroupItem< GroupControlItemOption >[] = [
47
48
  ];
48
49
 
49
50
  export const FlexOrderField = () => {
50
- const { isSiteRtl } = useDirection(),
51
- [ order, setOrder ] = useStylesField< NumberPropValue | null >( 'order' );
51
+ const { isSiteRtl } = useDirection();
52
+ const [ order, setOrder ] = useStylesField< NumberPropValue | null >( 'order' );
53
+ const { canEdit } = useStyle();
52
54
 
53
55
  const [ groupControlValue, setGroupControlValue ] = useState( getGroupControlValue( order?.value || null ) );
54
56
 
@@ -79,6 +81,7 @@ export const FlexOrderField = () => {
79
81
  value={ groupControlValue }
80
82
  onChange={ handleToggleButtonChange }
81
83
  exclusive={ true }
84
+ disabled={ ! canEdit }
82
85
  />
83
86
  </Grid>
84
87
  </Grid>
@@ -11,6 +11,7 @@ import { ExpandIcon, PencilIcon, ShrinkIcon } from '@elementor/icons';
11
11
  import { DirectionProvider, Grid, ThemeProvider } from '@elementor/ui';
12
12
  import { __ } from '@wordpress/i18n';
13
13
 
14
+ import { useStyle } from '../../../contexts/style-context';
14
15
  import { StylesField } from '../../../controls-registry/styles-field';
15
16
  import { useDirection } from '../../../hooks/use-direction';
16
17
  import { useStylesFields } from '../../../hooks/use-styles-fields';
@@ -44,6 +45,7 @@ const items: ToggleButtonGroupItem< GroupItem >[] = [
44
45
 
45
46
  export const FlexSizeField = () => {
46
47
  const { isSiteRtl } = useDirection();
48
+ const { canEdit } = useStyle();
47
49
 
48
50
  const [ fields, setFields ] = useStylesFields< {
49
51
  'flex-grow': NumberPropValue | null;
@@ -93,19 +95,21 @@ export const FlexSizeField = () => {
93
95
  <ThemeProvider>
94
96
  <SectionContent>
95
97
  <Grid container gap={ 2 } alignItems="center" flexWrap="nowrap">
96
- <Grid item xs={ 6 }>
97
- <StylesField bind={ activeGroup ?? '' }>
98
+ <StylesField bind={ activeGroup ?? '' }>
99
+ <Grid item xs={ 6 }>
98
100
  <ControlLabel>{ __( 'Size', 'elementor' ) }</ControlLabel>
99
- </StylesField>
100
- </Grid>
101
- <Grid item xs={ 6 } sx={ { display: 'flex', justifyContent: 'end' } }>
102
- <ControlToggleButtonGroup
103
- value={ activeGroup }
104
- onChange={ onChangeGroup }
105
- items={ items }
106
- exclusive={ true }
107
- />
108
- </Grid>
101
+ </Grid>
102
+
103
+ <Grid item xs={ 6 } sx={ { display: 'flex', justifyContent: 'end' } }>
104
+ <ControlToggleButtonGroup
105
+ value={ activeGroup }
106
+ onChange={ onChangeGroup }
107
+ disabled={ ! canEdit }
108
+ items={ items }
109
+ exclusive={ true }
110
+ />
111
+ </Grid>
112
+ </StylesField>
109
113
  </Grid>
110
114
  { 'custom' === activeGroup && <FlexCustomField /> }
111
115
  </SectionContent>
@@ -14,11 +14,7 @@ const positionOptions = [
14
14
  { label: __( 'Scale down', 'elementor' ), value: 'scale-down' },
15
15
  ];
16
16
 
17
- type Props = {
18
- onChange?: ( newValue: string | null, previousValue: string | null | undefined ) => void;
19
- };
20
-
21
- export const ObjectFitField = ( { onChange }: Props ) => {
17
+ export const ObjectFitField = () => {
22
18
  return (
23
19
  <StylesField bind="object-fit">
24
20
  <Grid container gap={ 2 } alignItems="center" flexWrap="nowrap">
@@ -26,7 +22,7 @@ export const ObjectFitField = ( { onChange }: Props ) => {
26
22
  <ControlLabel>{ __( 'Object fit', 'elementor' ) }</ControlLabel>
27
23
  </Grid>
28
24
  <Grid item xs={ 6 } sx={ { overflow: 'hidden' } }>
29
- <SelectControl options={ positionOptions } onChange={ onChange } />
25
+ <SelectControl options={ positionOptions } />
30
26
  </Grid>
31
27
  </Grid>
32
28
  </StylesField>
@@ -18,11 +18,7 @@ const positionOptions = [
18
18
  { label: __( 'Bottom right', 'elementor' ), value: 'bottom right' },
19
19
  ];
20
20
 
21
- type Props = {
22
- onChange?: ( newValue: string | null, previousValue: string | null | undefined ) => void;
23
- };
24
-
25
- export const ObjectPositionField = ( { onChange }: Props ) => {
21
+ export const ObjectPositionField = () => {
26
22
  return (
27
23
  <StylesField bind="object-position">
28
24
  <Grid container gap={ 2 } alignItems="center" flexWrap="nowrap">
@@ -30,7 +26,7 @@ export const ObjectPositionField = ( { onChange }: Props ) => {
30
26
  <ControlLabel>{ __( 'Object position', 'elementor' ) }</ControlLabel>
31
27
  </Grid>
32
28
  <Grid item xs={ 6 } sx={ { overflow: 'hidden' } }>
33
- <SelectControl options={ positionOptions } onChange={ onChange } />
29
+ <SelectControl options={ positionOptions } />
34
30
  </Grid>
35
31
  </Grid>
36
32
  </StylesField>
@@ -16,18 +16,12 @@ import { ObjectPositionField } from './object-position-field';
16
16
  import { OverflowField } from './overflow-field';
17
17
 
18
18
  export const SizeSection = () => {
19
- const [ fitValue, setFitValue ] = useStylesField< StringPropValue >( 'object-fit' );
19
+ const [ fitValue ] = useStylesField< StringPropValue >( 'object-fit' );
20
+
20
21
  const isNotFill = fitValue && fitValue?.value !== 'fill';
21
22
 
22
- const onFitChange = ( newFit: string | null, previousValue: string | null | undefined ) => {
23
- if ( newFit && newFit !== previousValue ) {
24
- setFitValue( {
25
- value: newFit,
26
- $$type: 'string',
27
- } );
28
- }
29
- };
30
23
  const isVersion330Active = isExperimentActive( 'e_v_3_30' );
24
+
31
25
  return (
32
26
  <SectionContent>
33
27
  <Grid container gap={ 2 } flexWrap="nowrap">
@@ -73,7 +67,7 @@ export const SizeSection = () => {
73
67
  <AspectRatioControl label={ __( 'Aspect Ratio', 'elementor' ) } />
74
68
  </StylesField>
75
69
  <PanelDivider />
76
- <ObjectFitField onChange={ onFitChange } />
70
+ <ObjectFitField />
77
71
  { isNotFill && (
78
72
  <Grid item xs={ 6 }>
79
73
  <ObjectPositionField />
@@ -2,6 +2,7 @@ import * as React from 'react';
2
2
  import { StrokeControl } from '@elementor/editor-controls';
3
3
  import { __ } from '@wordpress/i18n';
4
4
 
5
+ import { useStyle } from '../../../contexts/style-context';
5
6
  import { StylesField } from '../../../controls-registry/styles-field';
6
7
  import { useStylesField } from '../../../hooks/use-styles-field';
7
8
  import { AddOrRemoveContent } from '../../add-or-remove-content';
@@ -24,6 +25,7 @@ const initTextStroke = {
24
25
  };
25
26
 
26
27
  export const TextStrokeField = () => {
28
+ const { canEdit } = useStyle();
27
29
  const [ textStroke, setTextStroke ] = useStylesField( 'stroke' );
28
30
 
29
31
  const addTextStroke = () => {
@@ -43,6 +45,7 @@ export const TextStrokeField = () => {
43
45
  isAdded={ hasTextStroke }
44
46
  onAdd={ addTextStroke }
45
47
  onRemove={ removeTextStroke }
48
+ disabled={ ! canEdit }
46
49
  >
47
50
  <StrokeControl />
48
51
  </AddOrRemoveContent>
@@ -50,7 +50,7 @@ const PanelSection = ( { section }: { section: Section } ) => {
50
50
  const SectionComponent = component;
51
51
  const isExpanded = isExperimentActive( EXPERIMENTAL_FEATURES.V_3_30 )
52
52
  ? tabDefaults.defaultSectionsExpanded.style?.includes( name )
53
- : true;
53
+ : false;
54
54
 
55
55
  return (
56
56
  <Section title={ title } defaultExpanded={ isExpanded }>
@@ -6,7 +6,7 @@ import {
6
6
  type StyleDefinitionState,
7
7
  type StyleDefinitionVariant,
8
8
  } from '@elementor/editor-styles';
9
- import { type StylesProvider, stylesRepository } from '@elementor/editor-styles-repository';
9
+ import { type StylesProvider, stylesRepository, useUserStylesCapability } from '@elementor/editor-styles-repository';
10
10
 
11
11
  import { StylesProviderNotFoundError } from '../errors';
12
12
 
@@ -14,6 +14,7 @@ type ContextValue = {
14
14
  setId: Dispatch< StyleDefinition[ 'id' ] | null >;
15
15
  meta: StyleDefinitionVariant[ 'meta' ];
16
16
  setMetaState: Dispatch< StyleDefinitionState >;
17
+ canEdit?: boolean;
17
18
  } & ( ContextValueWithProvider | ContextValueWithoutProvider );
18
19
 
19
20
  type ContextValueWithProvider = {
@@ -33,11 +34,15 @@ type Props = PropsWithChildren< Omit< ContextValue, 'provider' > >;
33
34
  export function StyleProvider( { children, ...props }: Props ) {
34
35
  const provider = props.id === null ? null : getProviderByStyleId( props.id );
35
36
 
37
+ const { userCan } = useUserStylesCapability();
38
+
36
39
  if ( props.id && ! provider ) {
37
40
  throw new StylesProviderNotFoundError( { context: { styleId: props.id } } );
38
41
  }
39
42
 
40
- return <Context.Provider value={ { ...props, provider } as ContextValue }>{ children }</Context.Provider>;
43
+ const canEdit = userCan( provider?.getKey() ?? '' ).updateProps;
44
+
45
+ return <Context.Provider value={ { ...props, provider, canEdit } as ContextValue }>{ children }</Context.Provider>;
41
46
  }
42
47
 
43
48
  export function useStyle() {
@@ -57,3 +62,7 @@ export function getProviderByStyleId( styleId: StyleDefinitionID ) {
57
62
 
58
63
  return styleProvider ?? null;
59
64
  }
65
+
66
+ export function useIsStyle(): boolean {
67
+ return !! useContext( Context );
68
+ }
@@ -3,6 +3,7 @@ import { createContext, type PropsWithChildren, useContext } from 'react';
3
3
  import { getWidgetsCache, useElementSetting } from '@elementor/editor-elements';
4
4
  import { classesPropTypeUtil, type ClassesPropValue } from '@elementor/editor-props';
5
5
  import { getBreakpointsTree } from '@elementor/editor-responsive';
6
+ import { getStylesSchema } from '@elementor/editor-styles';
6
7
  import { stylesRepository } from '@elementor/editor-styles-repository';
7
8
 
8
9
  import { useStylesRerender } from '../hooks/use-styles-rerender';
@@ -50,13 +51,17 @@ export function useStylesInheritanceChain( path: string[] ): SnapshotPropValue[]
50
51
  throw new Error( 'useStylesInheritanceChain must be used within a StyleInheritanceProvider' );
51
52
  }
52
53
 
54
+ const schema = getStylesSchema();
55
+
56
+ const topLevelPropType = schema?.[ path[ 0 ] ];
57
+
53
58
  const snapshot = useStylesInheritanceSnapshot();
54
59
 
55
60
  if ( ! snapshot ) {
56
61
  return [];
57
62
  }
58
63
 
59
- return context.getInheritanceChain( snapshot, path );
64
+ return context.getInheritanceChain( snapshot, path, topLevelPropType );
60
65
  }
61
66
 
62
67
  const useAppliedStyles = () => {
@@ -68,12 +73,9 @@ const useAppliedStyles = () => {
68
73
 
69
74
  const classesProp = useElementSetting< ClassesPropValue >( element.id, currentClassesProp );
70
75
 
71
- const appliedStyles = classesPropTypeUtil.extract( classesProp );
76
+ const appliedStyles = classesPropTypeUtil.extract( classesProp ) ?? [];
72
77
 
73
- return stylesRepository
74
- .all()
75
- .filter( ( style ) => appliedStyles?.includes( style.id ) )
76
- .concat( baseStyles );
78
+ return stylesRepository.all().filter( ( style ) => [ ...baseStyles, ...appliedStyles ].includes( style.id ) );
77
79
  };
78
80
 
79
81
  const useBaseStyles = () => {
@@ -81,5 +83,5 @@ const useBaseStyles = () => {
81
83
  const widgetsCache = getWidgetsCache();
82
84
  const widgetCache = widgetsCache?.[ elementType.key ];
83
85
 
84
- return Object.values( widgetCache?.base_styles ?? {} );
86
+ return Object.keys( widgetCache?.base_styles ?? {} );
85
87
  };
@@ -1,9 +1,11 @@
1
1
  import { createMenu } from '@elementor/menus';
2
2
 
3
+ import Action from './action';
3
4
  import PopoverAction from './popover-action';
4
5
 
5
6
  export const controlActionsMenu = createMenu( {
6
7
  components: {
8
+ Action,
7
9
  PopoverAction,
8
10
  },
9
11
  } );
@@ -3,6 +3,7 @@ import { ControlAdornmentsProvider, PropKeyProvider, PropProvider } from '@eleme
3
3
  import { type PropKey, type PropValue } from '@elementor/editor-props';
4
4
  import { getStylesSchema } from '@elementor/editor-styles';
5
5
 
6
+ import { useStyle } from '../contexts/style-context';
6
7
  import { useStylesField } from '../hooks/use-styles-field';
7
8
  import { StylesInheritanceIndicator } from '../styles-inheritance/styles-inheritance-indicator';
8
9
  import { createTopLevelOjectType } from './create-top-level-object-type';
@@ -15,6 +16,7 @@ export type StylesFieldProps = {
15
16
 
16
17
  export const StylesField = ( { bind, placeholder, children }: StylesFieldProps ) => {
17
18
  const [ value, setValue ] = useStylesField( bind );
19
+ const { canEdit } = useStyle();
18
20
 
19
21
  const stylesSchema = getStylesSchema();
20
22
 
@@ -41,6 +43,7 @@ export const StylesField = ( { bind, placeholder, children }: StylesFieldProps )
41
43
  value={ values }
42
44
  setValue={ setValues }
43
45
  placeholder={ placeholderValues }
46
+ disabled={ ! canEdit }
44
47
  >
45
48
  <PropKeyProvider bind={ bind }>{ children }</PropKeyProvider>
46
49
  </PropProvider>