@elementor/editor-controls 1.2.0 → 1.5.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 (41) hide show
  1. package/CHANGELOG.md +66 -0
  2. package/dist/index.d.mts +20 -8
  3. package/dist/index.d.ts +20 -8
  4. package/dist/index.js +1092 -714
  5. package/dist/index.js.map +1 -1
  6. package/dist/index.mjs +937 -549
  7. package/dist/index.mjs.map +1 -1
  8. package/package.json +7 -7
  9. package/src/bound-prop-context/prop-context.tsx +3 -3
  10. package/src/bound-prop-context/prop-key-context.tsx +1 -0
  11. package/src/bound-prop-context/use-bound-prop.ts +5 -1
  12. package/src/components/font-family-selector.tsx +54 -56
  13. package/src/components/repeater.tsx +22 -11
  14. package/src/components/size-control/size-input.tsx +4 -4
  15. package/src/components/text-field-popover.tsx +19 -18
  16. package/src/controls/background-control/background-overlay/background-overlay-repeater-control.tsx +3 -15
  17. package/src/controls/box-shadow-repeater-control.tsx +1 -1
  18. package/src/controls/color-control.tsx +12 -1
  19. package/src/controls/equal-unequal-sizes-control.tsx +1 -1
  20. package/src/controls/filter-control/drop-shadow-item-content.tsx +69 -0
  21. package/src/controls/filter-control/drop-shadow-item-label.tsx +20 -0
  22. package/src/controls/filter-repeater-control.tsx +108 -21
  23. package/src/controls/font-family-control/font-family-control.tsx +14 -2
  24. package/src/controls/image-control.tsx +45 -16
  25. package/src/controls/key-value-control.tsx +57 -46
  26. package/src/controls/link-control.tsx +25 -20
  27. package/src/controls/linked-dimensions-control.tsx +1 -1
  28. package/src/controls/repeatable-control.tsx +100 -21
  29. package/src/controls/select-control.tsx +22 -2
  30. package/src/controls/size-control.tsx +25 -12
  31. package/src/controls/switch-control.tsx +9 -1
  32. package/src/controls/text-control.tsx +33 -18
  33. package/src/controls/transform-control/functions/axis-row.tsx +32 -0
  34. package/src/controls/transform-control/functions/move.tsx +44 -0
  35. package/src/controls/transform-control/transform-content.tsx +36 -0
  36. package/src/controls/transform-control/transform-icon.tsx +12 -0
  37. package/src/controls/transform-control/transform-label.tsx +27 -0
  38. package/src/controls/transform-control/transform-repeater-control.tsx +42 -0
  39. package/src/hooks/use-repeatable-control-context.ts +6 -1
  40. package/src/index.ts +1 -0
  41. package/src/utils/size-control.ts +4 -2
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@elementor/editor-controls",
3
3
  "description": "This package contains the controls model and utils for the Elementor editor",
4
- "version": "1.2.0",
4
+ "version": "1.5.0",
5
5
  "private": false,
6
6
  "author": "Elementor Team",
7
7
  "homepage": "https://elementor.com/",
@@ -40,19 +40,19 @@
40
40
  "dev": "tsup --config=../../tsup.dev.ts"
41
41
  },
42
42
  "dependencies": {
43
- "@elementor/editor-current-user": "0.5.0",
44
- "@elementor/editor-elements": "0.8.7",
45
- "@elementor/editor-props": "0.15.0",
43
+ "@elementor/editor-current-user": "0.6.1",
44
+ "@elementor/editor-elements": "0.9.2",
45
+ "@elementor/editor-props": "0.18.0",
46
46
  "@elementor/editor-responsive": "0.13.6",
47
- "@elementor/editor-ui": "0.13.0",
47
+ "@elementor/editor-ui": "0.14.2",
48
48
  "@elementor/editor-v1-adapters": "0.12.1",
49
49
  "@elementor/env": "0.3.5",
50
50
  "@elementor/http-client": "0.3.0",
51
- "@elementor/icons": "1.44.0",
51
+ "@elementor/icons": "1.46.0",
52
52
  "@elementor/locations": "0.8.0",
53
53
  "@elementor/query": "0.2.4",
54
54
  "@elementor/session": "0.1.0",
55
- "@elementor/ui": "1.35.5",
55
+ "@elementor/ui": "1.36.0",
56
56
  "@elementor/utils": "0.5.0",
57
57
  "@elementor/wp-media": "0.6.1",
58
58
  "@wordpress/i18n": "^5.13.0"
@@ -15,7 +15,7 @@ type PropContext< T extends PropValue, P extends PropType > = {
15
15
  value: T | null;
16
16
  propType: P;
17
17
  placeholder?: T;
18
- disabled?: boolean;
18
+ isDisabled?: ( propType: PropType ) => boolean | undefined;
19
19
  };
20
20
 
21
21
  const PropContext = createContext< PropContext< PropValue, PropType > | null >( null );
@@ -30,7 +30,7 @@ export const PropProvider = < T extends PropValue, P extends PropType >( {
30
30
  setValue,
31
31
  propType,
32
32
  placeholder,
33
- disabled,
33
+ isDisabled,
34
34
  }: PropProviderProps< T, P > ) => {
35
35
  return (
36
36
  <PropContext.Provider
@@ -39,7 +39,7 @@ export const PropProvider = < T extends PropValue, P extends PropType >( {
39
39
  propType,
40
40
  setValue: setValue as SetValue< PropValue >,
41
41
  placeholder,
42
- disabled,
42
+ isDisabled,
43
43
  } }
44
44
  >
45
45
  { children }
@@ -21,6 +21,7 @@ export type PropKeyContextValue< T, P > = {
21
21
  propType: P;
22
22
  placeholder?: T;
23
23
  path: PropKey[];
24
+ isDisabled?: ( propType: PropType ) => boolean | undefined;
24
25
  disabled?: boolean;
25
26
  };
26
27
 
@@ -19,6 +19,7 @@ type UseBoundProp< TValue extends PropValue > = {
19
19
  placeholder?: TValue;
20
20
  path: PropKey[];
21
21
  restoreValue: () => void;
22
+ isDisabled?: ( propType: PropType ) => boolean | undefined;
22
23
  disabled?: boolean;
23
24
  };
24
25
 
@@ -38,9 +39,11 @@ export function useBoundProp< TKey extends string, TValue extends PropValue >(
38
39
 
39
40
  const { isValid, validate, restoreValue } = useValidation( propKeyContext.propType );
40
41
 
42
+ const disabled = propKeyContext.isDisabled?.( propKeyContext.propType );
43
+
41
44
  // allow using the hook without a propTypeUtil, with no modifications or validations.
42
45
  if ( ! propTypeUtil ) {
43
- return propKeyContext;
46
+ return { ...propKeyContext, disabled } as PropKeyContextValue< PropValue, PropType >;
44
47
  }
45
48
 
46
49
  function setValue( value: TValue | null, options: CreateOptions, meta: { bind?: PropKey } ) {
@@ -67,6 +70,7 @@ export function useBoundProp< TKey extends string, TValue extends PropValue >(
67
70
  value: isValid ? value : null,
68
71
  restoreValue,
69
72
  placeholder,
73
+ disabled,
70
74
  };
71
75
  }
72
76
 
@@ -1,6 +1,6 @@
1
1
  import * as React from 'react';
2
2
  import { useEffect, useState } from 'react';
3
- import { PopoverHeader, PopoverMenuList, PopoverScrollableContent, PopoverSearch } from '@elementor/editor-ui';
3
+ import { PopoverBody, PopoverHeader, PopoverMenuList, PopoverSearch } from '@elementor/editor-ui';
4
4
  import { TextIcon } from '@elementor/icons';
5
5
  import { Box, Divider, Link, Stack, Typography } from '@elementor/ui';
6
6
  import { debounce } from '@elementor/utils';
@@ -41,7 +41,7 @@ export const FontFamilySelector = ( {
41
41
  };
42
42
 
43
43
  return (
44
- <Stack>
44
+ <PopoverBody width={ sectionWidth }>
45
45
  <PopoverHeader
46
46
  title={ __( 'Font Family', 'elementor' ) }
47
47
  onClose={ handleClose }
@@ -56,64 +56,62 @@ export const FontFamilySelector = ( {
56
56
 
57
57
  <Divider />
58
58
 
59
- <PopoverScrollableContent width={ sectionWidth }>
60
- { filteredFontFamilies.length > 0 ? (
61
- <FontList
62
- fontListItems={ filteredFontFamilies }
63
- setFontFamily={ onFontFamilyChange }
64
- handleClose={ handleClose }
65
- fontFamily={ fontFamily }
66
- />
67
- ) : (
68
- <Stack
69
- alignItems="center"
70
- justifyContent="center"
71
- height="100%"
72
- p={ 2.5 }
73
- gap={ 1.5 }
74
- overflow={ 'hidden' }
75
- >
76
- <TextIcon fontSize="large" />
77
- <Box sx={ { maxWidth: 160, overflow: 'hidden' } }>
78
- <Typography align="center" variant="subtitle2" color="text.secondary">
79
- { __( 'Sorry, nothing matched', 'elementor' ) }
80
- </Typography>
81
- <Typography
82
- variant="subtitle2"
83
- color="text.secondary"
84
- sx={ {
85
- display: 'flex',
86
- width: '100%',
87
- justifyContent: 'center',
88
- } }
89
- >
90
- <span>&ldquo;</span>
91
- <span style={ { maxWidth: '80%', overflow: 'hidden', textOverflow: 'ellipsis' } }>
92
- { searchValue }
93
- </span>
94
- <span>&rdquo;.</span>
95
- </Typography>
96
- </Box>
59
+ { filteredFontFamilies.length > 0 ? (
60
+ <FontList
61
+ fontListItems={ filteredFontFamilies }
62
+ setFontFamily={ onFontFamilyChange }
63
+ handleClose={ handleClose }
64
+ fontFamily={ fontFamily }
65
+ />
66
+ ) : (
67
+ <Stack
68
+ alignItems="center"
69
+ justifyContent="center"
70
+ height="100%"
71
+ p={ 2.5 }
72
+ gap={ 1.5 }
73
+ overflow={ 'hidden' }
74
+ >
75
+ <TextIcon fontSize="large" />
76
+ <Box sx={ { maxWidth: 160, overflow: 'hidden' } }>
77
+ <Typography align="center" variant="subtitle2" color="text.secondary">
78
+ { __( 'Sorry, nothing matched', 'elementor' ) }
79
+ </Typography>
97
80
  <Typography
98
- align="center"
99
- variant="caption"
81
+ variant="subtitle2"
100
82
  color="text.secondary"
101
- sx={ { display: 'flex', flexDirection: 'column' } }
83
+ sx={ {
84
+ display: 'flex',
85
+ width: '100%',
86
+ justifyContent: 'center',
87
+ } }
102
88
  >
103
- { __( 'Try something else.', 'elementor' ) }
104
- <Link
105
- color="secondary"
106
- variant="caption"
107
- component="button"
108
- onClick={ () => setSearchValue( '' ) }
109
- >
110
- { __( 'Clear & try again', 'elementor' ) }
111
- </Link>
89
+ <span>&ldquo;</span>
90
+ <span style={ { maxWidth: '80%', overflow: 'hidden', textOverflow: 'ellipsis' } }>
91
+ { searchValue }
92
+ </span>
93
+ <span>&rdquo;.</span>
112
94
  </Typography>
113
- </Stack>
114
- ) }
115
- </PopoverScrollableContent>
116
- </Stack>
95
+ </Box>
96
+ <Typography
97
+ align="center"
98
+ variant="caption"
99
+ color="text.secondary"
100
+ sx={ { display: 'flex', flexDirection: 'column' } }
101
+ >
102
+ { __( 'Try something else.', 'elementor' ) }
103
+ <Link
104
+ color="secondary"
105
+ variant="caption"
106
+ component="button"
107
+ onClick={ () => setSearchValue( '' ) }
108
+ >
109
+ { __( 'Clear & try again', 'elementor' ) }
110
+ </Link>
111
+ </Typography>
112
+ </Stack>
113
+ ) }
114
+ </PopoverBody>
117
115
  );
118
116
  };
119
117
 
@@ -1,6 +1,6 @@
1
1
  import * as React from 'react';
2
2
  import { useEffect, useState } from 'react';
3
- import { type PropKey } from '@elementor/editor-props';
3
+ import { type PropKey, type PropTypeUtil } from '@elementor/editor-props';
4
4
  import { CopyIcon, EyeIcon, EyeOffIcon, PlusIcon, XIcon } from '@elementor/icons';
5
5
  import {
6
6
  bindPopover,
@@ -30,6 +30,16 @@ type AnchorEl = HTMLElement | null;
30
30
  type Item< T > = {
31
31
  disabled?: boolean;
32
32
  } & T;
33
+ export type CollectionPropUtil< T > = PropTypeUtil< PropKey, T[] >;
34
+
35
+ type RepeaterItemContentProps< T > = {
36
+ anchorEl: AnchorEl;
37
+ bind: PropKey;
38
+ value: T;
39
+ collectionPropUtil?: CollectionPropUtil< T >;
40
+ };
41
+
42
+ type RepeaterItemContent< T > = React.ComponentType< RepeaterItemContentProps< T > >;
33
43
 
34
44
  type RepeaterProps< T > = {
35
45
  label: string;
@@ -42,15 +52,12 @@ type RepeaterProps< T > = {
42
52
  initialValues: T;
43
53
  Label: React.ComponentType< { value: T } >;
44
54
  Icon: React.ComponentType< { value: T } >;
45
- Content: React.ComponentType< {
46
- anchorEl: AnchorEl;
47
- bind: PropKey;
48
- value: T;
49
- } >;
55
+ Content: RepeaterItemContent< T >;
50
56
  };
51
57
  showDuplicate?: boolean;
52
58
  showToggle?: boolean;
53
59
  isSortable?: boolean;
60
+ collectionPropUtil?: CollectionPropUtil< T >;
54
61
  };
55
62
 
56
63
  const EMPTY_OPEN_ITEM = -1;
@@ -66,6 +73,7 @@ export const Repeater = < T, >( {
66
73
  showDuplicate = true,
67
74
  showToggle = true,
68
75
  isSortable = true,
76
+ collectionPropUtil,
69
77
  }: RepeaterProps< Item< T > > ) => {
70
78
  const [ openItem, setOpenItem ] = useState( EMPTY_OPEN_ITEM );
71
79
 
@@ -203,6 +211,7 @@ export const Repeater = < T, >( {
203
211
  onOpen={ () => setOpenItem( EMPTY_OPEN_ITEM ) }
204
212
  showDuplicate={ showDuplicate }
205
213
  showToggle={ showToggle }
214
+ collectionPropUtil={ collectionPropUtil }
206
215
  >
207
216
  { ( props ) => (
208
217
  <itemSettings.Content { ...props } value={ value } bind={ String( index ) } />
@@ -217,22 +226,23 @@ export const Repeater = < T, >( {
217
226
  );
218
227
  };
219
228
 
220
- type RepeaterItemProps = {
229
+ type RepeaterItemProps< T > = {
221
230
  label: React.ReactNode;
222
231
  propDisabled?: boolean;
223
232
  startIcon: UnstableTagProps[ 'startIcon' ];
224
233
  removeItem: () => void;
225
234
  duplicateItem: () => void;
226
235
  toggleDisableItem: () => void;
227
- children: ( { anchorEl }: { anchorEl: AnchorEl } ) => React.ReactNode;
236
+ children: ( props: Pick< RepeaterItemContentProps< T >, 'anchorEl' | 'collectionPropUtil' > ) => React.ReactNode;
228
237
  openOnMount: boolean;
229
238
  onOpen: () => void;
230
239
  showDuplicate: boolean;
231
240
  showToggle: boolean;
232
241
  disabled?: boolean;
242
+ collectionPropUtil?: CollectionPropUtil< T >;
233
243
  };
234
244
 
235
- const RepeaterItem = ( {
245
+ const RepeaterItem = < T, >( {
236
246
  label,
237
247
  propDisabled,
238
248
  startIcon,
@@ -245,7 +255,8 @@ const RepeaterItem = ( {
245
255
  showDuplicate,
246
256
  showToggle,
247
257
  disabled,
248
- }: RepeaterItemProps ) => {
258
+ collectionPropUtil,
259
+ }: RepeaterItemProps< T > ) => {
249
260
  const [ anchorEl, setAnchorEl ] = useState< AnchorEl >( null );
250
261
  const { popoverState, popoverProps, ref, setRef } = usePopover( openOnMount, onOpen );
251
262
 
@@ -301,7 +312,7 @@ const RepeaterItem = ( {
301
312
  { ...popoverProps }
302
313
  anchorEl={ ref }
303
314
  >
304
- <Box>{ children( { anchorEl } ) }</Box>
315
+ <Box>{ children( { anchorEl, collectionPropUtil } ) }</Box>
305
316
  </Popover>
306
317
  </>
307
318
  );
@@ -4,19 +4,19 @@ import { PencilIcon } from '@elementor/icons';
4
4
  import { Box, InputAdornment, type PopupState } from '@elementor/ui';
5
5
 
6
6
  import ControlActions from '../../control-actions/control-actions';
7
- import { type ExtendedOption, isUnitExtendedOption, type Unit } from '../../utils/size-control';
7
+ import { type DegreeUnit, type ExtendedOption, isUnitExtendedOption, type Unit } from '../../utils/size-control';
8
8
  import { SelectionEndAdornment, TextFieldInnerSelection } from '../size-control/text-field-inner-selection';
9
9
 
10
10
  type SizeInputProps = {
11
- unit: Unit | ExtendedOption;
11
+ unit: Unit | DegreeUnit | ExtendedOption;
12
12
  size: number | string;
13
13
  placeholder?: string;
14
14
  startIcon?: React.ReactNode;
15
- units: ( Unit | ExtendedOption )[];
15
+ units: ( Unit | DegreeUnit | ExtendedOption )[];
16
16
  onBlur?: ( event: React.FocusEvent< HTMLInputElement > ) => void;
17
17
  onFocus?: ( event: React.FocusEvent< HTMLInputElement > ) => void;
18
18
  onClick?: ( event: React.MouseEvent< HTMLInputElement > ) => void;
19
- handleUnitChange: ( unit: Unit | ExtendedOption ) => void;
19
+ handleUnitChange: ( unit: Unit | DegreeUnit | ExtendedOption ) => void;
20
20
  handleSizeChange: ( event: React.ChangeEvent< HTMLInputElement > ) => void;
21
21
  popupState: PopupState;
22
22
  disabled?: boolean;
@@ -1,6 +1,6 @@
1
1
  import * as React from 'react';
2
2
  import { type RefObject } from 'react';
3
- import { bindPopover, Paper, Popover, type PopupState, TextField } from '@elementor/ui';
3
+ import { bindPopover, Popover, type PopupState, TextField } from '@elementor/ui';
4
4
 
5
5
  type Props = {
6
6
  popupState: PopupState;
@@ -16,6 +16,15 @@ export const TextFieldPopover = ( props: Props ) => {
16
16
  return (
17
17
  <Popover
18
18
  disablePortal
19
+ slotProps={ {
20
+ paper: {
21
+ sx: {
22
+ borderRadius: 2,
23
+ width: anchorRef.current?.offsetWidth + 'px',
24
+ p: 1.5,
25
+ },
26
+ },
27
+ } }
19
28
  { ...bindPopover( popupState ) }
20
29
  anchorOrigin={ { vertical: 'bottom', horizontal: 'center' } }
21
30
  transformOrigin={ { vertical: 'top', horizontal: 'center' } }
@@ -24,24 +33,16 @@ export const TextFieldPopover = ( props: Props ) => {
24
33
  popupState.close();
25
34
  } }
26
35
  >
27
- <Paper
28
- sx={ {
29
- width: anchorRef.current?.offsetWidth + 'px',
30
- borderRadius: 2,
31
- p: 1.5,
36
+ <TextField
37
+ value={ value }
38
+ onChange={ onChange }
39
+ size="tiny"
40
+ type="text"
41
+ fullWidth
42
+ inputProps={ {
43
+ autoFocus: true,
32
44
  } }
33
- >
34
- <TextField
35
- value={ value }
36
- onChange={ onChange }
37
- size="tiny"
38
- type="text"
39
- fullWidth
40
- inputProps={ {
41
- autoFocus: true,
42
- } }
43
- />
44
- </Paper>
45
+ />
45
46
  </Popover>
46
47
  );
47
48
  };
@@ -7,12 +7,11 @@ import {
7
7
  colorPropTypeUtil,
8
8
  type PropKey,
9
9
  } from '@elementor/editor-props';
10
- import { Box, CardMedia, Grid, styled, Tab, TabPanel, Tabs, type Theme, UnstableColorIndicator } from '@elementor/ui';
10
+ import { Box, CardMedia, styled, Tab, TabPanel, Tabs, type Theme, UnstableColorIndicator } from '@elementor/ui';
11
11
  import { useWpMediaAttachment } from '@elementor/wp-media';
12
12
  import { __ } from '@wordpress/i18n';
13
13
 
14
14
  import { PropKeyProvider, PropProvider, useBoundProp } from '../../../bound-prop-context';
15
- import { ControlFormLabel } from '../../../components/control-form-label';
16
15
  import { PopoverContent } from '../../../components/popover-content';
17
16
  import { Repeater } from '../../../components/repeater';
18
17
  import { createControl } from '../../../create-control';
@@ -75,7 +74,7 @@ export const BackgroundOverlayRepeaterControl = createControl( () => {
75
74
  const { propType, value: overlayValues, setValue, disabled } = useBoundProp( backgroundOverlayPropTypeUtil );
76
75
 
77
76
  return (
78
- <PropProvider propType={ propType } value={ overlayValues } setValue={ setValue } disabled={ disabled }>
77
+ <PropProvider propType={ propType } value={ overlayValues } setValue={ setValue } isDisabled={ () => disabled }>
79
78
  <Repeater
80
79
  openOnAdd
81
80
  disabled={ disabled }
@@ -236,18 +235,7 @@ const ImageOverlayContent = () => {
236
235
  return (
237
236
  <PropProvider { ...propContext }>
238
237
  <PropKeyProvider bind={ 'image' }>
239
- <Grid container spacing={ 1 } alignItems="center">
240
- <Grid item xs={ 12 }>
241
- <Grid container gap={ 2 } alignItems="center" flexWrap="nowrap">
242
- <Grid item xs={ 6 }>
243
- <ControlFormLabel>{ __( 'Resolution', 'elementor' ) }</ControlFormLabel>
244
- </Grid>
245
- <Grid item xs={ 6 } sx={ { overflow: 'hidden' } }>
246
- <ImageControl sizes={ backgroundResolutionOptions } />
247
- </Grid>
248
- </Grid>
249
- </Grid>
250
- </Grid>
238
+ <ImageControl sizes={ backgroundResolutionOptions } />
251
239
  </PropKeyProvider>
252
240
  <PropKeyProvider bind={ 'position' }>
253
241
  <BackgroundImageOverlayPosition />
@@ -17,7 +17,7 @@ export const BoxShadowRepeaterControl = createControl( () => {
17
17
  const { propType, value, setValue, disabled } = useBoundProp( boxShadowPropTypeUtil );
18
18
 
19
19
  return (
20
- <PropProvider propType={ propType } value={ value } setValue={ setValue } disabled={ disabled }>
20
+ <PropProvider propType={ propType } value={ value } setValue={ setValue } isDisabled={ () => disabled }>
21
21
  <Repeater
22
22
  openOnAdd
23
23
  disabled={ disabled }
@@ -13,7 +13,9 @@ type Props = Partial< Omit< UnstableColorFieldProps, 'value' | 'onChange' > > &
13
13
 
14
14
  export const ColorControl = createControl(
15
15
  ( { propTypeUtil = colorPropTypeUtil, anchorEl, slotProps = {}, ...props }: Props ) => {
16
- const { value, setValue, disabled } = useBoundProp( propTypeUtil );
16
+ const { value, setValue, placeholder: boundPropPlaceholder, disabled } = useBoundProp( propTypeUtil );
17
+
18
+ const placeholder = props.placeholder ?? boundPropPlaceholder;
17
19
 
18
20
  const handleChange = ( selectedColor: string ) => {
19
21
  setValue( selectedColor || null );
@@ -25,6 +27,7 @@ export const ColorControl = createControl(
25
27
  size="tiny"
26
28
  fullWidth
27
29
  value={ value ?? '' }
30
+ placeholder={ placeholder ?? '' }
28
31
  onChange={ handleChange }
29
32
  { ...props }
30
33
  disabled={ disabled }
@@ -40,6 +43,14 @@ export const ColorControl = createControl(
40
43
  vertical: 'top',
41
44
  horizontal: -10,
42
45
  },
46
+ slotProps: {
47
+ colorIndicator: {
48
+ value: value ?? placeholder ?? '',
49
+ },
50
+ colorBox: {
51
+ value: value ?? placeholder ?? '',
52
+ },
53
+ },
43
54
  },
44
55
  } }
45
56
  />
@@ -154,7 +154,7 @@ export function EqualUnequalSizesControl< TMultiPropType extends string, TPropVa
154
154
  propType={ multiSizePropType }
155
155
  value={ getMultiSizeValues() }
156
156
  setValue={ setNestedProp }
157
- disabled={ multiSizeDisabled }
157
+ isDisabled={ () => multiSizeDisabled }
158
158
  >
159
159
  <PopoverContent p={ 1.5 }>
160
160
  <PopoverGridContainer ref={ rowRefs[ 1 ] }>
@@ -0,0 +1,69 @@
1
+ import * as React from 'react';
2
+ import { useRef } from 'react';
3
+ import { type DropShadowFilterPropValue, type PropTypeUtil } from '@elementor/editor-props';
4
+ import { Grid } from '@elementor/ui';
5
+ import { __ } from '@wordpress/i18n';
6
+
7
+ import { PropKeyProvider, PropProvider, useBoundProp } from '../../bound-prop-context';
8
+ import { ControlFormLabel } from '../../components/control-form-label';
9
+ import { PopoverGridContainer } from '../../components/popover-grid-container';
10
+ import { type Unit } from '../../utils/size-control';
11
+ import { ColorControl } from '../color-control';
12
+ import { SizeControl } from '../size-control';
13
+
14
+ const items = [
15
+ {
16
+ bind: 'xAxis',
17
+ label: __( 'X-axis', 'elementor' ),
18
+ rowIndex: 0,
19
+ },
20
+ {
21
+ bind: 'yAxis',
22
+ label: __( 'Y-axis', 'elementor' ),
23
+ rowIndex: 0,
24
+ },
25
+ {
26
+ bind: 'blur',
27
+ label: __( 'Blur', 'elementor' ),
28
+ rowIndex: 1,
29
+ },
30
+ {
31
+ bind: 'color',
32
+ label: __( 'Color', 'elementor' ),
33
+ rowIndex: 1,
34
+ },
35
+ ];
36
+
37
+ export const DropShadowItemContent = ( {
38
+ propType,
39
+ units,
40
+ anchorEl,
41
+ }: {
42
+ propType: PropTypeUtil< 'drop-shadow', DropShadowFilterPropValue[ 'value' ] >;
43
+ units: Unit[];
44
+ anchorEl?: HTMLElement | null;
45
+ } ) => {
46
+ const context = useBoundProp( propType );
47
+ const rowRefs = [ useRef< HTMLDivElement >( null ), useRef< HTMLDivElement >( null ) ];
48
+
49
+ return (
50
+ <PropProvider { ...context }>
51
+ { items.map( ( item ) => (
52
+ <PopoverGridContainer key={ item.bind } ref={ rowRefs[ item.rowIndex ] ?? null }>
53
+ <PropKeyProvider bind={ item.bind }>
54
+ <Grid item xs={ 6 }>
55
+ <ControlFormLabel>{ item.label }</ControlFormLabel>
56
+ </Grid>
57
+ <Grid item xs={ 6 }>
58
+ { item.bind === 'color' ? (
59
+ <ColorControl anchorEl={ anchorEl } />
60
+ ) : (
61
+ <SizeControl anchorRef={ rowRefs[ item.rowIndex ] } units={ units } defaultUnit="px" />
62
+ ) }
63
+ </Grid>
64
+ </PropKeyProvider>
65
+ </PopoverGridContainer>
66
+ ) ) }
67
+ </PropProvider>
68
+ );
69
+ };
@@ -0,0 +1,20 @@
1
+ import * as React from 'react';
2
+ import { type FilterItemPropValue } from '@elementor/editor-props';
3
+ import { Box } from '@elementor/ui';
4
+
5
+ export const DropShadowItemLabel = ( { value }: { value: FilterItemPropValue } ) => {
6
+ const { xAxis, yAxis, blur } = value.value;
7
+
8
+ const xValue = `${ xAxis?.value?.size ?? 0 }${ xAxis?.value?.unit ?? 'px' }`;
9
+ const yValue = `${ yAxis?.value?.size ?? 0 }${ yAxis?.value?.unit ?? 'px' }`;
10
+ const blurValue = `${ blur?.value?.size ?? 10 }${ blur?.value?.unit ?? 'px' }`;
11
+
12
+ return (
13
+ <Box component="span">
14
+ <Box component="span" style={ { textTransform: 'capitalize' } }>
15
+ Drop shadow:
16
+ </Box>
17
+ { `${ xValue } ${ yValue } ${ blurValue }` }
18
+ </Box>
19
+ );
20
+ };