@elementor/editor-controls 0.32.0 → 0.34.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 (33) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/dist/index.d.mts +6 -2
  3. package/dist/index.d.ts +6 -2
  4. package/dist/index.js +154 -84
  5. package/dist/index.js.map +1 -1
  6. package/dist/index.mjs +152 -82
  7. package/dist/index.mjs.map +1 -1
  8. package/package.json +3 -3
  9. package/src/bound-prop-context/prop-context.tsx +3 -0
  10. package/src/bound-prop-context/prop-key-context.tsx +1 -0
  11. package/src/bound-prop-context/use-bound-prop.ts +1 -0
  12. package/src/components/control-toggle-button-group.tsx +6 -2
  13. package/src/components/popover-content.tsx +4 -2
  14. package/src/components/repeater.tsx +19 -10
  15. package/src/components/text-field-inner-selection.tsx +6 -0
  16. package/src/control-actions/control-actions.tsx +10 -2
  17. package/src/controls/aspect-ratio-control.tsx +14 -6
  18. package/src/controls/background-control/background-control.tsx +16 -19
  19. package/src/controls/background-control/background-overlay/background-overlay-repeater-control.tsx +2 -1
  20. package/src/controls/box-shadow-repeater-control.tsx +2 -1
  21. package/src/controls/color-control.tsx +2 -1
  22. package/src/controls/equal-unequal-sizes-control.tsx +25 -14
  23. package/src/controls/font-family-control/font-family-control.tsx +2 -1
  24. package/src/controls/gap-control.tsx +4 -1
  25. package/src/controls/linked-dimensions-control.tsx +36 -10
  26. package/src/controls/number-control.tsx +2 -1
  27. package/src/controls/select-control.tsx +2 -1
  28. package/src/controls/size-control.tsx +35 -27
  29. package/src/controls/switch-control.tsx +2 -2
  30. package/src/controls/text-area-control.tsx +2 -1
  31. package/src/controls/text-control.tsx +2 -1
  32. package/src/controls/toggle-control.tsx +3 -1
  33. package/src/controls/url-control.tsx +2 -1
@@ -1,5 +1,6 @@
1
1
  import * as React from 'react';
2
2
  import { dimensionsPropTypeUtil, type PropKey, sizePropTypeUtil } from '@elementor/editor-props';
3
+ import { isExperimentActive } from '@elementor/editor-v1-adapters';
3
4
  import { DetachIcon, LinkIcon, SideBottomIcon, SideLeftIcon, SideRightIcon, SideTopIcon } from '@elementor/icons';
4
5
  import { Grid, Stack, ToggleButton, Tooltip } from '@elementor/ui';
5
6
  import { __ } from '@wordpress/i18n';
@@ -20,15 +21,19 @@ export const LinkedDimensionsControl = createControl(
20
21
  isSiteRtl?: boolean;
21
22
  extendedValues?: ExtendedValue[];
22
23
  } ) => {
24
+ const { value: sizeValue, setValue: setSizeValue, disabled: sizeDisabled } = useBoundProp( sizePropTypeUtil );
25
+
23
26
  const {
24
27
  value: dimensionsValue,
25
28
  setValue: setDimensionsValue,
26
29
  propType,
30
+ disabled: dimensionsDisabled,
27
31
  } = useBoundProp( dimensionsPropTypeUtil );
28
- const { value: sizeValue, setValue: setSizeValue } = useBoundProp( sizePropTypeUtil );
29
32
 
30
33
  const isLinked = ! dimensionsValue && ! sizeValue ? true : !! sizeValue;
31
34
 
35
+ const isUsingNestedProps = isExperimentActive( 'e_v_3_30' );
36
+
32
37
  const onLinkToggle = () => {
33
38
  if ( ! isLinked ) {
34
39
  setSizeValue( dimensionsValue[ 'block-start' ]?.value ?? null );
@@ -56,7 +61,11 @@ export const LinkedDimensionsControl = createControl(
56
61
  return (
57
62
  <PropProvider propType={ propType } value={ dimensionsValue } setValue={ setDimensionsValue }>
58
63
  <Stack direction="row" gap={ 2 } flexWrap="nowrap">
59
- <ControlLabel>{ label }</ControlLabel>
64
+ { isUsingNestedProps ? (
65
+ <ControlFormLabel>{ label }</ControlFormLabel>
66
+ ) : (
67
+ <ControlLabel>{ label }</ControlLabel>
68
+ ) }
60
69
  <Tooltip title={ isLinked ? unlinkedLabel : linkedLabel } placement="top">
61
70
  <ToggleButton
62
71
  aria-label={ isLinked ? unlinkedLabel : linkedLabel }
@@ -65,6 +74,7 @@ export const LinkedDimensionsControl = createControl(
65
74
  selected={ isLinked }
66
75
  sx={ { marginLeft: 'auto' } }
67
76
  onChange={ onLinkToggle }
77
+ disabled={ sizeDisabled || dimensionsDisabled }
68
78
  >
69
79
  <LinkedIcon fontSize={ 'tiny' } />
70
80
  </ToggleButton>
@@ -73,7 +83,7 @@ export const LinkedDimensionsControl = createControl(
73
83
  <Stack direction="row" gap={ 2 } flexWrap="nowrap">
74
84
  <Grid container gap={ 0.75 } alignItems="center">
75
85
  <Grid item xs={ 12 }>
76
- <ControlFormLabel>{ __( 'Top', 'elementor' ) }</ControlFormLabel>
86
+ <Label bind="block-start" label={ __( 'Top', 'elementor' ) } />
77
87
  </Grid>
78
88
  <Grid item xs={ 12 }>
79
89
  <Control
@@ -86,9 +96,10 @@ export const LinkedDimensionsControl = createControl(
86
96
  </Grid>
87
97
  <Grid container gap={ 0.75 } alignItems="center">
88
98
  <Grid item xs={ 12 }>
89
- <ControlFormLabel>
90
- { isSiteRtl ? __( 'Left', 'elementor' ) : __( 'Right', 'elementor' ) }
91
- </ControlFormLabel>
99
+ <Label
100
+ bind="inline-end"
101
+ label={ isSiteRtl ? __( 'Left', 'elementor' ) : __( 'Right', 'elementor' ) }
102
+ />
92
103
  </Grid>
93
104
  <Grid item xs={ 12 }>
94
105
  <Control
@@ -109,7 +120,7 @@ export const LinkedDimensionsControl = createControl(
109
120
  <Stack direction="row" gap={ 2 } flexWrap="nowrap">
110
121
  <Grid container gap={ 0.75 } alignItems="center">
111
122
  <Grid item xs={ 12 }>
112
- <ControlFormLabel>{ __( 'Bottom', 'elementor' ) }</ControlFormLabel>
123
+ <Label bind="block-end" label={ __( 'Bottom', 'elementor' ) } />
113
124
  </Grid>
114
125
  <Grid item xs={ 12 }>
115
126
  <Control
@@ -122,9 +133,10 @@ export const LinkedDimensionsControl = createControl(
122
133
  </Grid>
123
134
  <Grid container gap={ 0.75 } alignItems="center">
124
135
  <Grid item xs={ 12 }>
125
- <ControlFormLabel>
126
- { isSiteRtl ? __( 'Right', 'elementor' ) : __( 'Left', 'elementor' ) }
127
- </ControlFormLabel>
136
+ <Label
137
+ bind="inline-start"
138
+ label={ isSiteRtl ? __( 'Right', 'elementor' ) : __( 'Left', 'elementor' ) }
139
+ />
128
140
  </Grid>
129
141
  <Grid item xs={ 12 }>
130
142
  <Control
@@ -168,3 +180,17 @@ const Control = ( {
168
180
  </PropKeyProvider>
169
181
  );
170
182
  };
183
+
184
+ const Label = ( { label, bind }: { label: string; bind: PropKey } ) => {
185
+ const isUsingNestedProps = isExperimentActive( 'e_v_3_30' );
186
+
187
+ if ( ! isUsingNestedProps ) {
188
+ return <ControlFormLabel>{ label }</ControlFormLabel>;
189
+ }
190
+
191
+ return (
192
+ <PropKeyProvider bind={ bind }>
193
+ <ControlLabel>{ label }</ControlLabel>
194
+ </PropKeyProvider>
195
+ );
196
+ };
@@ -25,7 +25,7 @@ export const NumberControl = createControl(
25
25
  step?: number;
26
26
  shouldForceInt?: boolean;
27
27
  } ) => {
28
- const { value, setValue } = useBoundProp( numberPropTypeUtil );
28
+ const { value, setValue, disabled } = useBoundProp( numberPropTypeUtil );
29
29
 
30
30
  const handleChange = ( event: React.ChangeEvent< HTMLInputElement > ) => {
31
31
  const eventValue: string = event.target.value;
@@ -47,6 +47,7 @@ export const NumberControl = createControl(
47
47
  size="tiny"
48
48
  type="number"
49
49
  fullWidth
50
+ disabled={ disabled }
50
51
  value={ isEmptyOrNaN( value ) ? '' : value }
51
52
  onChange={ handleChange }
52
53
  placeholder={ placeholder }
@@ -13,7 +13,7 @@ type Props = {
13
13
  };
14
14
 
15
15
  export const SelectControl = createControl( ( { options, onChange }: Props ) => {
16
- const { value, setValue } = useBoundProp( stringPropTypeUtil );
16
+ const { value, setValue, disabled } = useBoundProp( stringPropTypeUtil );
17
17
 
18
18
  const handleChange = ( event: SelectChangeEvent< StringPropValue[ 'value' ] > ) => {
19
19
  const newValue = event.target.value || null;
@@ -30,6 +30,7 @@ export const SelectControl = createControl( ( { options, onChange }: Props ) =>
30
30
  size="tiny"
31
31
  value={ value ?? '' }
32
32
  onChange={ handleChange }
33
+ disabled={ disabled }
33
34
  fullWidth
34
35
  >
35
36
  { options.map( ( { label, ...props } ) => (
@@ -1,7 +1,7 @@
1
1
  import * as React from 'react';
2
2
  import { useRef } from 'react';
3
3
  import { sizePropTypeUtil, stringPropTypeUtil } from '@elementor/editor-props';
4
- import { InputAdornment } from '@elementor/ui';
4
+ import { Box, InputAdornment } from '@elementor/ui';
5
5
 
6
6
  import { useBoundProp } from '../bound-prop-context';
7
7
  import { SelectionEndAdornment, TextFieldInnerSelection } from '../components/text-field-inner-selection';
@@ -26,7 +26,7 @@ type SizeControlProps = {
26
26
 
27
27
  export const SizeControl = createControl(
28
28
  ( { units = defaultUnits, extendedValues = [], placeholder, startIcon }: SizeControlProps ) => {
29
- const { value: sizeValue, setValue: setSizeValue, restoreValue } = useBoundProp( sizePropTypeUtil );
29
+ const { value: sizeValue, setValue: setSizeValue, restoreValue, disabled } = useBoundProp( sizePropTypeUtil );
30
30
 
31
31
  const [ state, setState ] = useSyncExternalState( {
32
32
  external: sizeValue,
@@ -55,6 +55,7 @@ export const SizeControl = createControl(
55
55
 
56
56
  return (
57
57
  <Input
58
+ disabled={ disabled }
58
59
  size={ state.size }
59
60
  unit={ state.unit }
60
61
  placeholder={ placeholder }
@@ -103,6 +104,7 @@ type SizeInputProps = {
103
104
  onBlur?: ( event: React.FocusEvent< HTMLInputElement > ) => void;
104
105
  handleUnitChange: ( unit: Unit ) => void;
105
106
  handleSizeChange: ( event: React.ChangeEvent< HTMLInputElement > ) => void;
107
+ disabled?: boolean;
106
108
  };
107
109
 
108
110
  const RESTRICTED_INPUT_KEYS = [ 'e', 'E', '+', '-' ];
@@ -116,6 +118,7 @@ const SizeInput = ( {
116
118
  onBlur,
117
119
  size,
118
120
  unit,
121
+ disabled,
119
122
  }: SizeInputProps ) => {
120
123
  const unitInputBufferRef = useRef( '' );
121
124
 
@@ -144,32 +147,37 @@ const SizeInput = ( {
144
147
 
145
148
  return (
146
149
  <ControlActions>
147
- <TextFieldInnerSelection
148
- endAdornment={
149
- <SelectionEndAdornment
150
- options={ units }
151
- onClick={ handleUnitChange }
152
- value={ unit ?? defaultUnit }
153
- />
154
- }
155
- placeholder={ placeholder }
156
- startAdornment={
157
- startIcon ? <InputAdornment position="start">{ startIcon }</InputAdornment> : undefined
158
- }
159
- type="number"
160
- value={ Number.isNaN( size ) ? '' : size }
161
- onChange={ handleSizeChange }
162
- onBlur={ ( event ) => {
163
- unitInputBufferRef.current = '';
164
- onBlur?.( event );
165
- } }
166
- onKeyDown={ ( event ) => {
167
- if ( RESTRICTED_INPUT_KEYS.includes( event.key ) ) {
168
- event.preventDefault();
150
+ <Box>
151
+ <TextFieldInnerSelection
152
+ disabled={ disabled }
153
+ endAdornment={
154
+ <SelectionEndAdornment
155
+ disabled={ disabled }
156
+ options={ units }
157
+ onClick={ handleUnitChange }
158
+ value={ unit ?? defaultUnit }
159
+ />
169
160
  }
170
- } }
171
- onKeyUp={ handleKeyUp }
172
- />
161
+ placeholder={ placeholder }
162
+ startAdornment={
163
+ startIcon ? (
164
+ <InputAdornment position="start" disabled={ disabled }>
165
+ { startIcon }
166
+ </InputAdornment>
167
+ ) : undefined
168
+ }
169
+ type="number"
170
+ value={ Number.isNaN( size ) ? '' : size }
171
+ onChange={ handleSizeChange }
172
+ onBlur={ onBlur }
173
+ onKeyDown={ ( event ) => {
174
+ if ( RESTRICTED_INPUT_KEYS.includes( event.key ) ) {
175
+ event.preventDefault();
176
+ }
177
+ } }
178
+ onKeyUp={ handleKeyUp }
179
+ />
180
+ </Box>
173
181
  </ControlActions>
174
182
  );
175
183
  };
@@ -6,7 +6,7 @@ import { useBoundProp } from '../bound-prop-context/use-bound-prop';
6
6
  import { createControl } from '../create-control';
7
7
 
8
8
  export const SwitchControl = createControl( () => {
9
- const { value, setValue } = useBoundProp( booleanPropTypeUtil );
9
+ const { value, setValue, disabled } = useBoundProp( booleanPropTypeUtil );
10
10
 
11
11
  const handleChange = ( event: React.ChangeEvent< HTMLInputElement > ) => {
12
12
  setValue( event.target.checked );
@@ -14,7 +14,7 @@ export const SwitchControl = createControl( () => {
14
14
 
15
15
  return (
16
16
  <div style={ { display: 'flex', justifyContent: 'flex-end' } }>
17
- <Switch checked={ !! value } onChange={ handleChange } size="small" />
17
+ <Switch checked={ !! value } onChange={ handleChange } size="small" disabled={ disabled } />
18
18
  </div>
19
19
  );
20
20
  } );
@@ -11,7 +11,7 @@ type Props = {
11
11
  };
12
12
 
13
13
  export const TextAreaControl = createControl( ( { placeholder }: Props ) => {
14
- const { value, setValue } = useBoundProp( stringPropTypeUtil );
14
+ const { value, setValue, disabled } = useBoundProp( stringPropTypeUtil );
15
15
 
16
16
  const handleChange = ( event: React.ChangeEvent< HTMLInputElement > ) => {
17
17
  setValue( event.target.value );
@@ -24,6 +24,7 @@ export const TextAreaControl = createControl( ( { placeholder }: Props ) => {
24
24
  multiline
25
25
  fullWidth
26
26
  minRows={ 5 }
27
+ disabled={ disabled }
27
28
  value={ value ?? '' }
28
29
  onChange={ handleChange }
29
30
  placeholder={ placeholder }
@@ -7,7 +7,7 @@ import ControlActions from '../control-actions/control-actions';
7
7
  import { createControl } from '../create-control';
8
8
 
9
9
  export const TextControl = createControl( ( { placeholder }: { placeholder?: string } ) => {
10
- const { value, setValue } = useBoundProp( stringPropTypeUtil );
10
+ const { value, setValue, disabled } = useBoundProp( stringPropTypeUtil );
11
11
 
12
12
  const handleChange = ( event: React.ChangeEvent< HTMLInputElement > ) => setValue( event.target.value );
13
13
 
@@ -16,6 +16,7 @@ export const TextControl = createControl( ( { placeholder }: { placeholder?: str
16
16
  <TextField
17
17
  size="tiny"
18
18
  fullWidth
19
+ disabled={ disabled }
19
20
  value={ value ?? '' }
20
21
  onChange={ handleChange }
21
22
  placeholder={ placeholder }
@@ -22,7 +22,7 @@ export const ToggleControl = createControl(
22
22
  exclusive = true,
23
23
  maxItems,
24
24
  }: ToggleControlProps< StringPropValue[ 'value' ] > ) => {
25
- const { value, setValue, placeholder } = useBoundProp( stringPropTypeUtil );
25
+ const { value, setValue, placeholder, disabled } = useBoundProp( stringPropTypeUtil );
26
26
 
27
27
  const exclusiveValues = options.filter( ( option ) => option.exclusive ).map( ( option ) => option.value );
28
28
 
@@ -49,6 +49,7 @@ export const ToggleControl = createControl(
49
49
  { ...toggleButtonGroupProps }
50
50
  value={ value ?? placeholder ?? null }
51
51
  onChange={ setValue }
52
+ disabled={ disabled }
52
53
  exclusive={ true }
53
54
  />
54
55
  ) : (
@@ -56,6 +57,7 @@ export const ToggleControl = createControl(
56
57
  { ...toggleButtonGroupProps }
57
58
  value={ ( value ?? placeholder )?.split( ' ' ) ?? [] }
58
59
  onChange={ handleNonExclusiveToggle }
60
+ disabled={ disabled }
59
61
  exclusive={ false }
60
62
  />
61
63
  );
@@ -7,7 +7,7 @@ import ControlActions from '../control-actions/control-actions';
7
7
  import { createControl } from '../create-control';
8
8
 
9
9
  export const UrlControl = createControl( ( { placeholder }: { placeholder?: string } ) => {
10
- const { value, setValue } = useBoundProp( urlPropTypeUtil );
10
+ const { value, setValue, disabled } = useBoundProp( urlPropTypeUtil );
11
11
  const handleChange = ( event: React.ChangeEvent< HTMLInputElement > ) => setValue( event.target.value );
12
12
 
13
13
  return (
@@ -16,6 +16,7 @@ export const UrlControl = createControl( ( { placeholder }: { placeholder?: stri
16
16
  size="tiny"
17
17
  fullWidth
18
18
  value={ value ?? '' }
19
+ disabled={ disabled }
19
20
  onChange={ handleChange }
20
21
  placeholder={ placeholder }
21
22
  />