@elementor/editor-editing-panel 1.46.0 → 1.48.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 (77) hide show
  1. package/CHANGELOG.md +85 -0
  2. package/dist/index.d.mts +12 -1
  3. package/dist/index.d.ts +12 -1
  4. package/dist/index.js +1094 -889
  5. package/dist/index.js.map +1 -1
  6. package/dist/index.mjs +979 -780
  7. package/dist/index.mjs.map +1 -1
  8. package/package.json +17 -18
  9. package/src/components/popover-scrollable-content.tsx +12 -0
  10. package/src/components/section-content.tsx +6 -16
  11. package/src/components/section.tsx +8 -4
  12. package/src/components/settings-tab.tsx +5 -2
  13. package/src/components/style-sections/background-section/background-section.tsx +4 -1
  14. package/src/components/style-sections/border-section/border-color-field.tsx +10 -16
  15. package/src/components/style-sections/border-section/border-field.tsx +14 -7
  16. package/src/components/style-sections/border-section/border-radius-field.tsx +4 -2
  17. package/src/components/style-sections/border-section/border-style-field.tsx +11 -16
  18. package/src/components/style-sections/border-section/border-width-field.tsx +4 -2
  19. package/src/components/style-sections/effects-section/effects-section.tsx +29 -6
  20. package/src/components/style-sections/layout-section/align-content-field.tsx +11 -12
  21. package/src/components/style-sections/layout-section/align-items-field.tsx +8 -11
  22. package/src/components/style-sections/layout-section/align-self-child-field.tsx +11 -16
  23. package/src/components/style-sections/layout-section/display-field.tsx +6 -6
  24. package/src/components/style-sections/layout-section/flex-direction-field.tsx +11 -14
  25. package/src/components/style-sections/layout-section/flex-order-field.tsx +23 -20
  26. package/src/components/style-sections/layout-section/flex-size-field.tsx +42 -64
  27. package/src/components/style-sections/layout-section/gap-control-field.tsx +5 -6
  28. package/src/components/style-sections/layout-section/justify-content-field.tsx +11 -12
  29. package/src/components/style-sections/layout-section/layout-section.tsx +9 -2
  30. package/src/components/style-sections/layout-section/opacity-control-field.tsx +9 -13
  31. package/src/components/style-sections/layout-section/utils/rotated-icon.tsx +6 -1
  32. package/src/components/style-sections/layout-section/wrap-field.tsx +10 -14
  33. package/src/components/style-sections/position-section/dimensions-field.tsx +4 -4
  34. package/src/components/style-sections/position-section/offset-field.tsx +12 -14
  35. package/src/components/style-sections/position-section/position-field.tsx +7 -11
  36. package/src/components/style-sections/position-section/position-section.tsx +19 -8
  37. package/src/components/style-sections/position-section/z-index-field.tsx +7 -11
  38. package/src/components/style-sections/size-section/object-fit-field.tsx +7 -11
  39. package/src/components/style-sections/size-section/object-position-field.tsx +4 -1
  40. package/src/components/style-sections/size-section/overflow-field.tsx +7 -11
  41. package/src/components/style-sections/size-section/size-section.tsx +13 -8
  42. package/src/components/style-sections/spacing-section/spacing-section.tsx +7 -4
  43. package/src/components/style-sections/typography-section/column-count-field.tsx +7 -11
  44. package/src/components/style-sections/typography-section/column-gap-field.tsx +9 -13
  45. package/src/components/style-sections/typography-section/font-family-field.tsx +9 -11
  46. package/src/components/style-sections/typography-section/font-size-field.tsx +9 -13
  47. package/src/components/style-sections/typography-section/font-style-field.tsx +13 -13
  48. package/src/components/style-sections/typography-section/font-weight-field.tsx +7 -11
  49. package/src/components/style-sections/typography-section/letter-spacing-field.tsx +9 -13
  50. package/src/components/style-sections/typography-section/line-height-field.tsx +9 -13
  51. package/src/components/style-sections/typography-section/text-alignment-field.tsx +11 -14
  52. package/src/components/style-sections/typography-section/text-color-field.tsx +7 -11
  53. package/src/components/style-sections/typography-section/text-decoration-field.tsx +7 -11
  54. package/src/components/style-sections/typography-section/text-direction-field.tsx +7 -11
  55. package/src/components/style-sections/typography-section/text-stroke-field.tsx +7 -3
  56. package/src/components/style-sections/typography-section/transform-field.tsx +7 -11
  57. package/src/components/style-sections/typography-section/typography-section.tsx +6 -1
  58. package/src/components/style-sections/typography-section/word-spacing-field.tsx +9 -13
  59. package/src/components/style-tab.tsx +1 -1
  60. package/src/components/styles-field-layout.tsx +50 -0
  61. package/src/contexts/section-context.tsx +14 -0
  62. package/src/controls-registry/control-type-container.tsx +6 -2
  63. package/src/controls-registry/controls-registry.tsx +1 -1
  64. package/src/controls-registry/settings-field.tsx +85 -10
  65. package/src/controls-registry/styles-field.tsx +15 -5
  66. package/src/dynamics/components/dynamic-selection-control.tsx +10 -4
  67. package/src/dynamics/components/dynamic-selection.tsx +18 -14
  68. package/src/hooks/use-default-panel-settings.ts +4 -0
  69. package/src/hooks/use-styles-field.ts +3 -4
  70. package/src/hooks/use-styles-fields.ts +141 -73
  71. package/src/index.ts +4 -0
  72. package/src/init.ts +0 -6
  73. package/src/popover-action.tsx +8 -1
  74. package/src/styles-inheritance/components/styles-inheritance-indicator.tsx +4 -1
  75. package/src/styles-inheritance/components/styles-inheritance-infotip.tsx +9 -19
  76. package/src/sync/experiments-flags.ts +1 -0
  77. package/src/components/popover-content.tsx +0 -15
@@ -24,8 +24,12 @@ const initTextStroke = {
24
24
  },
25
25
  };
26
26
 
27
+ const TEXT_STROKE_LABEL = __( 'Text stroke', 'elementor' );
28
+
27
29
  export const TextStrokeField = () => {
28
- const { value, setValue, canEdit } = useStylesField( 'stroke' );
30
+ const { value, setValue, canEdit } = useStylesField( 'stroke', {
31
+ history: { propDisplayName: TEXT_STROKE_LABEL },
32
+ } );
29
33
 
30
34
  const addTextStroke = () => {
31
35
  setValue( initTextStroke );
@@ -38,13 +42,13 @@ export const TextStrokeField = () => {
38
42
  const hasTextStroke = Boolean( value );
39
43
 
40
44
  return (
41
- <StylesField bind={ 'stroke' }>
45
+ <StylesField bind={ 'stroke' } propDisplayName={ TEXT_STROKE_LABEL }>
42
46
  <AddOrRemoveContent
43
47
  isAdded={ hasTextStroke }
44
48
  onAdd={ addTextStroke }
45
49
  onRemove={ removeTextStroke }
46
50
  disabled={ ! canEdit }
47
- renderLabel={ () => <ControlLabel>{ __( 'Text stroke', 'elementor' ) }</ControlLabel> }
51
+ renderLabel={ () => <ControlLabel>{ TEXT_STROKE_LABEL }</ControlLabel> }
48
52
  >
49
53
  <StrokeControl />
50
54
  </AddOrRemoveContent>
@@ -1,14 +1,15 @@
1
1
  import * as React from 'react';
2
2
  import { type ToggleButtonGroupItem, ToggleControl } from '@elementor/editor-controls';
3
3
  import { LetterCaseIcon, LetterCaseLowerIcon, LetterCaseUpperIcon, MinusIcon } from '@elementor/icons';
4
- import { Grid } from '@elementor/ui';
5
4
  import { __ } from '@wordpress/i18n';
6
5
 
7
6
  import { StylesField } from '../../../controls-registry/styles-field';
8
- import { ControlLabel } from '../../control-label';
7
+ import { StylesFieldLayout } from '../../styles-field-layout';
9
8
 
10
9
  type Transforms = 'none' | 'capitalize' | 'uppercase' | 'lowercase';
11
10
 
11
+ const TEXT_TRANSFORM_LABEL = __( 'Text transform', 'elementor' );
12
+
12
13
  const options: ToggleButtonGroupItem< Transforms >[] = [
13
14
  {
14
15
  value: 'none',
@@ -37,14 +38,9 @@ const options: ToggleButtonGroupItem< Transforms >[] = [
37
38
  ];
38
39
 
39
40
  export const TransformField = () => (
40
- <StylesField bind={ 'text-transform' }>
41
- <Grid container gap={ 2 } alignItems="center" flexWrap="nowrap">
42
- <Grid item xs={ 6 }>
43
- <ControlLabel>{ __( 'Text transform', 'elementor' ) }</ControlLabel>
44
- </Grid>
45
- <Grid item xs={ 6 } display="flex" justifyContent="end">
46
- <ToggleControl options={ options } />
47
- </Grid>
48
- </Grid>
41
+ <StylesField bind="text-transform" propDisplayName={ TEXT_TRANSFORM_LABEL }>
42
+ <StylesFieldLayout label={ TEXT_TRANSFORM_LABEL }>
43
+ <ToggleControl options={ options } />
44
+ </StylesFieldLayout>
49
45
  </StylesField>
50
46
  );
@@ -1,6 +1,7 @@
1
1
  import * as React from 'react';
2
2
  import type { NumberPropValue } from '@elementor/editor-props';
3
3
  import { isExperimentActive } from '@elementor/editor-v1-adapters';
4
+ import { __ } from '@wordpress/i18n';
4
5
 
5
6
  import { useStylesField } from '../../../hooks/use-styles-field';
6
7
  import { PanelDivider } from '../../panel-divider';
@@ -22,8 +23,12 @@ import { TextStrokeField } from './text-stroke-field';
22
23
  import { TransformField } from './transform-field';
23
24
  import { WordSpacingField } from './word-spacing-field';
24
25
 
26
+ const COLUMN_COUNT_LABEL = __( 'Column count', 'elementor' );
27
+
25
28
  export const TypographySection = () => {
26
- const { value: columnCount } = useStylesField< NumberPropValue >( 'column-count' );
29
+ const { value: columnCount } = useStylesField< NumberPropValue >( 'column-count', {
30
+ history: { propDisplayName: COLUMN_COUNT_LABEL },
31
+ } );
27
32
  const hasMultiColumns = !! ( columnCount?.value && columnCount?.value > 1 );
28
33
 
29
34
  const isVersion330Active = isExperimentActive( 'e_v_3_30' );
@@ -1,25 +1,21 @@
1
1
  import * as React from 'react';
2
- import { type MutableRefObject, useRef } from 'react';
2
+ import { useRef } from 'react';
3
3
  import { SizeControl } from '@elementor/editor-controls';
4
- import { Grid } from '@elementor/ui';
5
4
  import { __ } from '@wordpress/i18n';
6
5
 
7
6
  import { StylesField } from '../../../controls-registry/styles-field';
8
- import { ControlLabel } from '../../control-label';
7
+ import { StylesFieldLayout } from '../../styles-field-layout';
8
+
9
+ const WORD_SPACING_LABEL = __( 'Word spacing', 'elementor' );
9
10
 
10
11
  export const WordSpacingField = () => {
11
- const rowRef: MutableRefObject< HTMLElement | undefined > = useRef();
12
+ const rowRef = useRef< HTMLDivElement >( null );
12
13
 
13
14
  return (
14
- <StylesField bind="word-spacing">
15
- <Grid container gap={ 2 } alignItems="center" flexWrap="nowrap" ref={ rowRef }>
16
- <Grid item xs={ 6 }>
17
- <ControlLabel>{ __( 'Word spacing', 'elementor' ) }</ControlLabel>
18
- </Grid>
19
- <Grid item xs={ 6 }>
20
- <SizeControl anchorRef={ rowRef } />
21
- </Grid>
22
- </Grid>
15
+ <StylesField bind="word-spacing" propDisplayName={ WORD_SPACING_LABEL }>
16
+ <StylesFieldLayout label={ WORD_SPACING_LABEL } ref={ rowRef }>
17
+ <SizeControl anchorRef={ rowRef } />
18
+ </StylesFieldLayout>
23
19
  </StylesField>
24
20
  );
25
21
  };
@@ -29,7 +29,7 @@ const TABS_HEADER_HEIGHT = '37px';
29
29
 
30
30
  export const stickyHeaderStyles = {
31
31
  position: 'sticky',
32
- zIndex: 1,
32
+ zIndex: 1100,
33
33
  opacity: 1,
34
34
  backgroundColor: 'background.default',
35
35
  transition: 'top 300ms ease',
@@ -0,0 +1,50 @@
1
+ import * as React from 'react';
2
+ import { Grid, Stack, type Theme } from '@elementor/ui';
3
+
4
+ import { ControlLabel } from './control-label';
5
+
6
+ type StylesFieldLayoutProps = {
7
+ label: string;
8
+ children: React.ReactNode;
9
+ direction?: 'row' | 'column';
10
+ };
11
+
12
+ export const StylesFieldLayout = React.forwardRef< HTMLDivElement, StylesFieldLayoutProps >( ( props, ref ) => {
13
+ const { direction = 'row', children, label } = props;
14
+
15
+ const LayoutComponent = direction === 'row' ? Row : Column;
16
+
17
+ return <LayoutComponent label={ label } ref={ ref } children={ children } />;
18
+ } );
19
+
20
+ const Row = React.forwardRef< HTMLDivElement, { label: string; children: React.ReactNode } >(
21
+ ( { label, children }, ref ) => {
22
+ return (
23
+ <Grid container gap={ 2 } alignItems="center" flexWrap="nowrap" ref={ ref }>
24
+ <Grid item xs={ 6 }>
25
+ <ControlLabel>{ label }</ControlLabel>
26
+ </Grid>
27
+ <Grid
28
+ item
29
+ xs={ 6 }
30
+ sx={ ( theme: Theme ) => ( {
31
+ width: `calc(50% - ${ theme.spacing( 2 ) })`,
32
+ } ) }
33
+ >
34
+ { children }
35
+ </Grid>
36
+ </Grid>
37
+ );
38
+ }
39
+ );
40
+
41
+ const Column = React.forwardRef< HTMLDivElement, { label: string; children: React.ReactNode } >(
42
+ ( { label, children }, ref ) => {
43
+ return (
44
+ <Stack gap={ 0.75 } ref={ ref }>
45
+ <ControlLabel>{ label }</ControlLabel>
46
+ { children }
47
+ </Stack>
48
+ );
49
+ }
50
+ );
@@ -0,0 +1,14 @@
1
+ import { createContext, useContext } from 'react';
2
+ import type { RefObject } from 'react';
3
+
4
+ const FALLBACK_SECTION_WIDTH = 320;
5
+
6
+ export const SectionRefContext = createContext< RefObject< HTMLElement > | null >( null );
7
+
8
+ const useSectionRef = () => useContext( SectionRefContext );
9
+
10
+ export const useSectionWidth = (): number => {
11
+ const sectionRef = useSectionRef();
12
+
13
+ return sectionRef?.current?.offsetWidth ?? FALLBACK_SECTION_WIDTH;
14
+ };
@@ -3,6 +3,10 @@ import { type ControlLayout } from '@elementor/editor-elements';
3
3
  import { Box, type BoxProps, styled } from '@elementor/ui';
4
4
 
5
5
  export const ControlTypeContainer = ( { children, layout }: React.PropsWithChildren< { layout?: ControlLayout } > ) => {
6
+ if ( layout === 'custom' ) {
7
+ return children;
8
+ }
9
+
6
10
  return <StyledContainer layout={ layout }>{ children }</StyledContainer>;
7
11
  };
8
12
 
@@ -14,10 +18,10 @@ const StyledContainer = styled( Box, {
14
18
  ...getGridLayout( layout ),
15
19
  } ) );
16
20
 
17
- const getGridLayout = ( layout: ControlLayout ) => ( {
21
+ const getGridLayout = ( layout: Omit< ControlLayout, 'custom' > ) => ( {
18
22
  justifyContent: 'space-between',
19
23
  gridTemplateColumns: {
20
24
  full: 'minmax(0, 1fr)',
21
25
  'two-columns': 'repeat(2, minmax(0, 1fr))',
22
- }[ layout ],
26
+ }[ layout as string ],
23
27
  } );
@@ -37,7 +37,7 @@ const controlTypes = {
37
37
  textarea: { component: TextAreaControl, layout: 'full', propTypeUtil: stringPropTypeUtil },
38
38
  size: { component: SizeControl, layout: 'two-columns', propTypeUtil: sizePropTypeUtil },
39
39
  select: { component: SelectControl, layout: 'two-columns', propTypeUtil: stringPropTypeUtil },
40
- link: { component: LinkControl, layout: 'full', propTypeUtil: linkPropTypeUtil },
40
+ link: { component: LinkControl, layout: 'custom', propTypeUtil: linkPropTypeUtil },
41
41
  url: { component: UrlControl, layout: 'full', propTypeUtil: stringPropTypeUtil },
42
42
  switch: { component: SwitchControl, layout: 'two-columns', propTypeUtil: booleanPropTypeUtil },
43
43
  repeatable: { component: RepeatableControl, layout: 'full', propTypeUtil: undefined },
@@ -1,35 +1,110 @@
1
1
  import * as React from 'react';
2
+ import { useMemo } from 'react';
2
3
  import { PropKeyProvider, PropProvider } from '@elementor/editor-controls';
3
- import { updateElementSettings, useElementSetting } from '@elementor/editor-elements';
4
- import { type PropKey, type PropValue } from '@elementor/editor-props';
4
+ import { setDocumentModifiedStatus } from '@elementor/editor-documents';
5
+ import {
6
+ type ElementID,
7
+ getElementLabel,
8
+ getElementSetting,
9
+ updateElementSettings,
10
+ useElementSettings,
11
+ } from '@elementor/editor-elements';
12
+ import { type PropKey, type PropType, type PropValue, shouldApplyEffect } from '@elementor/editor-props';
13
+ import { isExperimentActive, undoable } from '@elementor/editor-v1-adapters';
14
+ import { __ } from '@wordpress/i18n';
5
15
 
6
16
  import { useElement } from '../contexts/element-context';
17
+ import { EXPERIMENTAL_FEATURES } from '../sync/experiments-flags';
7
18
  import { createTopLevelOjectType } from './create-top-level-object-type';
8
19
 
9
20
  type Props = {
10
21
  bind: PropKey;
22
+ propDisplayName: string;
11
23
  children: React.ReactNode;
12
24
  };
13
25
 
14
- export const SettingsField = ( { bind, children }: Props ) => {
26
+ export const SettingsField = ( { bind, children, propDisplayName }: Props ) => {
15
27
  const { element, elementType } = useElement();
16
28
 
17
- const settingsValue = useElementSetting< PropValue >( element.id, bind );
29
+ const elementSettingValues = useElementSettings< PropValue >( element.id, Object.keys( elementType.propsSchema ) );
18
30
 
19
- const value = { [ bind ]: settingsValue };
31
+ const value = { [ bind ]: elementSettingValues?.[ bind ] };
20
32
 
21
33
  const propType = createTopLevelOjectType( { schema: elementType.propsSchema } );
22
34
 
35
+ const undoableUpdateElementProp = useUndoableUpdateElementProp( {
36
+ propKey: bind,
37
+ elementId: element.id,
38
+ propDisplayName,
39
+ } );
40
+
23
41
  const setValue = ( newValue: Record< string, PropValue > ) => {
24
- updateElementSettings( {
25
- id: element.id,
26
- props: { ...newValue },
27
- } );
42
+ const isVersion331Active = isExperimentActive( EXPERIMENTAL_FEATURES.V_3_31 );
43
+
44
+ if ( isVersion331Active ) {
45
+ undoableUpdateElementProp( { newValue } );
46
+ } else {
47
+ updateElementSettings( { id: element.id, props: newValue } );
48
+ }
28
49
  };
29
50
 
51
+ const isDisabled = ( prop: PropType ) => getDisableState( prop, elementSettingValues );
52
+
30
53
  return (
31
- <PropProvider propType={ propType } value={ value } setValue={ setValue }>
54
+ <PropProvider propType={ propType } value={ value } setValue={ setValue } isDisabled={ isDisabled }>
32
55
  <PropKeyProvider bind={ bind }>{ children }</PropKeyProvider>
33
56
  </PropProvider>
34
57
  );
35
58
  };
59
+
60
+ function getDisableState( propType: PropType, elementValues: PropValue ): boolean | undefined {
61
+ const disablingDependencies = propType.dependencies?.filter( ( { effect } ) => effect === 'disable' ) || [];
62
+
63
+ if ( ! disablingDependencies.length ) {
64
+ return false;
65
+ }
66
+
67
+ if ( disablingDependencies.length > 1 ) {
68
+ throw new Error( 'Multiple disabling dependencies are not supported.' );
69
+ }
70
+
71
+ return shouldApplyEffect( disablingDependencies[ 0 ], elementValues );
72
+ }
73
+
74
+ type UndoableUpdateElementSettingsArgs = {
75
+ newValue: Record< string, PropValue >;
76
+ };
77
+
78
+ function useUndoableUpdateElementProp( {
79
+ propKey,
80
+ elementId,
81
+ propDisplayName,
82
+ }: {
83
+ propKey: PropKey;
84
+ elementId: ElementID;
85
+ propDisplayName: string;
86
+ } ) {
87
+ return useMemo( () => {
88
+ return undoable(
89
+ {
90
+ do: ( { newValue }: UndoableUpdateElementSettingsArgs ) => {
91
+ const prevPropValue = getElementSetting( elementId, propKey ) as PropValue;
92
+
93
+ updateElementSettings( { id: elementId, props: { ...newValue }, withHistory: false } );
94
+ setDocumentModifiedStatus( true );
95
+
96
+ return { [ propKey ]: prevPropValue };
97
+ },
98
+
99
+ undo: ( {}, prevProps ) => {
100
+ updateElementSettings( { id: elementId, props: prevProps, withHistory: false } );
101
+ },
102
+ },
103
+ {
104
+ title: getElementLabel( elementId ),
105
+ // translators: %s is the name of the property that was edited.
106
+ subtitle: __( '%s edited', 'elementor' ).replace( '%s', propDisplayName ),
107
+ }
108
+ );
109
+ }, [ propKey, elementId, propDisplayName ] );
110
+ }
@@ -2,7 +2,9 @@ import * as React from 'react';
2
2
  import { ControlAdornmentsProvider, PropKeyProvider, PropProvider } from '@elementor/editor-controls';
3
3
  import { type PropKey, type PropValue } from '@elementor/editor-props';
4
4
  import { getStylesSchema } from '@elementor/editor-styles';
5
+ import { isExperimentActive } from '@elementor/editor-v1-adapters';
5
6
 
7
+ import { useStylesInheritanceChain } from '../contexts/styles-inheritance-context';
6
8
  import { useStylesField } from '../hooks/use-styles-field';
7
9
  import { StylesInheritanceIndicator } from '../styles-inheritance/components/styles-inheritance-indicator';
8
10
  import { createTopLevelOjectType } from './create-top-level-object-type';
@@ -11,18 +13,26 @@ export type StylesFieldProps = {
11
13
  bind: PropKey;
12
14
  placeholder?: PropValue;
13
15
  children: React.ReactNode;
16
+ propDisplayName: string;
14
17
  };
15
18
 
16
- export const StylesField = ( { bind, placeholder, children }: StylesFieldProps ) => {
17
- const { value, setValue, canEdit } = useStylesField( bind );
19
+ export const StylesField = ( { bind, placeholder, propDisplayName, children }: StylesFieldProps ) => {
20
+ const { value, setValue, canEdit } = useStylesField( bind, {
21
+ history: { propDisplayName },
22
+ } );
23
+
24
+ const isVersion331Active = isExperimentActive( 'e_v_3_31' );
25
+ const stylesInheritanceChain = useStylesInheritanceChain( [ bind ] );
18
26
 
19
27
  const stylesSchema = getStylesSchema();
20
28
 
21
29
  const propType = createTopLevelOjectType( { schema: stylesSchema } );
22
30
 
23
31
  const values = { [ bind ]: value };
24
- const placeholderValues = { [ bind ]: placeholder };
25
-
32
+ const [ actualValue ] = stylesInheritanceChain;
33
+ const placeholderValues = {
34
+ [ bind ]: isVersion331Active ? actualValue?.value : placeholder,
35
+ };
26
36
  const setValues = ( newValue: Record< string, PropValue > ) => {
27
37
  setValue( newValue[ bind ] );
28
38
  };
@@ -41,7 +51,7 @@ export const StylesField = ( { bind, placeholder, children }: StylesFieldProps )
41
51
  value={ values }
42
52
  setValue={ setValues }
43
53
  placeholder={ placeholderValues }
44
- disabled={ ! canEdit }
54
+ isDisabled={ () => ! canEdit }
45
55
  >
46
56
  <PropKeyProvider bind={ bind }>{ children }</PropKeyProvider>
47
57
  </PropProvider>
@@ -21,7 +21,6 @@ import {
21
21
  } from '@elementor/ui';
22
22
  import { __ } from '@wordpress/i18n';
23
23
 
24
- import { PopoverContent } from '../../components/popover-content';
25
24
  import { Control as BaseControl } from '../../controls-registry/control';
26
25
  import { type ControlType, getControl } from '../../controls-registry/controls-registry';
27
26
  import { usePersistDynamicValue } from '../../hooks/use-persist-dynamic-value';
@@ -76,7 +75,11 @@ export const DynamicSelectionControl = () => {
76
75
  <Popover
77
76
  disablePortal
78
77
  disableScrollLock
79
- anchorOrigin={ { vertical: 'bottom', horizontal: 'left' } }
78
+ anchorOrigin={ { vertical: 'bottom', horizontal: 'right' } }
79
+ transformOrigin={ { vertical: 'top', horizontal: 'right' } }
80
+ PaperProps={ {
81
+ sx: { my: 1 },
82
+ } }
80
83
  { ...bindPopover( selectionPopoverState ) }
81
84
  >
82
85
  <Stack>
@@ -105,6 +108,9 @@ export const DynamicSettingsPopover = ( { dynamicTag }: { dynamicTag: DynamicTag
105
108
  disablePortal
106
109
  disableScrollLock
107
110
  anchorOrigin={ { vertical: 'bottom', horizontal: 'center' } }
111
+ PaperProps={ {
112
+ sx: { my: 0.5 },
113
+ } }
108
114
  { ...bindPopover( popupState ) }
109
115
  >
110
116
  <PopoverHeader
@@ -139,14 +145,14 @@ const DynamicSettings = ( { controls }: { controls: DynamicTag[ 'atomic_controls
139
145
  { tabs.map( ( { value }, index ) => {
140
146
  return (
141
147
  <TabPanel key={ index } sx={ { flexGrow: 1, py: 0 } } { ...getTabPanelProps( index ) }>
142
- <PopoverContent p={ 2 } gap={ 2 }>
148
+ <Stack p={ 2 } gap={ 2 }>
143
149
  { value.items.map( ( item ) => {
144
150
  if ( item.type === 'control' ) {
145
151
  return <Control key={ item.value.bind } control={ item.value } />;
146
152
  }
147
153
  return null;
148
154
  } ) }
149
- </PopoverContent>
155
+ </Stack>
150
156
  </TabPanel>
151
157
  );
152
158
  } ) }
@@ -6,6 +6,7 @@ import { DatabaseIcon } from '@elementor/icons';
6
6
  import { Box, Divider, Link, Stack, Typography, useTheme } from '@elementor/ui';
7
7
  import { __ } from '@wordpress/i18n';
8
8
 
9
+ import { PopoverScrollableContent } from '../../components/popover-scrollable-content';
9
10
  import { usePersistDynamicValue } from '../../hooks/use-persist-dynamic-value';
10
11
  import { usePropDynamicTags } from '../hooks/use-prop-dynamic-tags';
11
12
  import { getAtomicDynamicTags } from '../sync/get-atomic-dynamic-tags';
@@ -91,19 +92,23 @@ export const DynamicSelection = ( { close: closePopover }: DynamicSelectionProps
91
92
  onSearch={ handleSearch }
92
93
  placeholder={ __( 'Search dynamic tags…', 'elementor' ) }
93
94
  />
95
+
94
96
  <Divider />
95
- <PopoverMenuList
96
- items={ virtualizedItems }
97
- onSelect={ handleSetDynamicTag }
98
- onClose={ closePopover }
99
- selectedValue={ dynamicValue?.name }
100
- itemStyle={ ( item ) =>
101
- item.type === 'item' ? { paddingInlineStart: theme.spacing( 3.5 ) } : {}
102
- }
103
- noResultsComponent={
104
- <NoResults searchValue={ searchValue } onClear={ () => setSearchValue( '' ) } />
105
- }
106
- />
97
+
98
+ <PopoverScrollableContent>
99
+ <PopoverMenuList
100
+ items={ virtualizedItems }
101
+ onSelect={ handleSetDynamicTag }
102
+ onClose={ closePopover }
103
+ selectedValue={ dynamicValue?.name }
104
+ itemStyle={ ( item ) =>
105
+ item.type === 'item' ? { paddingInlineStart: theme.spacing( 3.5 ) } : {}
106
+ }
107
+ noResultsComponent={
108
+ <NoResults searchValue={ searchValue } onClear={ () => setSearchValue( '' ) } />
109
+ }
110
+ />
111
+ </PopoverScrollableContent>
107
112
  </Fragment>
108
113
  ) }
109
114
  </Stack>
@@ -127,9 +132,8 @@ const NoResults = ( { searchValue, onClear }: NoResultsProps ) => (
127
132
  <br />
128
133
  &ldquo;{ searchValue }&rdquo;.
129
134
  </Typography>
130
- <Typography align="center" variant="caption">
135
+ <Typography align="center" variant="caption" sx={ { display: 'flex', flexDirection: 'column' } }>
131
136
  { __( 'Try something else.', 'elementor' ) }
132
- &nbsp;
133
137
  <Link color="text.secondary" variant="caption" component="button" onClick={ onClear }>
134
138
  { __( 'Clear & try again', 'elementor' ) }
135
139
  </Link>
@@ -24,6 +24,10 @@ const defaultPanelSettingsContext = createContext< Record< string, Defaults | un
24
24
  defaultSectionsExpanded: fallbackEditorSettings.defaultSectionsExpanded,
25
25
  defaultTab: 'style',
26
26
  },
27
+ 'e-divider': {
28
+ defaultSectionsExpanded: fallbackEditorSettings.defaultSectionsExpanded,
29
+ defaultTab: 'style',
30
+ },
27
31
  } );
28
32
 
29
33
  export const useDefaultPanelSettings = () => {
@@ -3,7 +3,8 @@ import type { PropKey, PropValue } from '@elementor/editor-props';
3
3
  import { useStylesFields } from './use-styles-fields';
4
4
 
5
5
  export function useStylesField< T extends PropValue >(
6
- propName: PropKey
6
+ propName: PropKey,
7
+ meta: { history: { propDisplayName: string } }
7
8
  ): {
8
9
  value: T;
9
10
  setValue: ( newValue: T ) => void;
@@ -14,9 +15,7 @@ export function useStylesField< T extends PropValue >(
14
15
  const value = values?.[ propName ] ?? null;
15
16
 
16
17
  const setValue = ( newValue: T ) => {
17
- setValues( {
18
- [ propName ]: newValue,
19
- } );
18
+ setValues( { [ propName ]: newValue }, meta );
20
19
  };
21
20
 
22
21
  return { value: value as T, setValue, canEdit };