@elementor/editor-controls 1.3.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.
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.3.0",
4
+ "version": "1.5.0",
5
5
  "private": false,
6
6
  "author": "Elementor Team",
7
7
  "homepage": "https://elementor.com/",
@@ -40,11 +40,11 @@
40
40
  "dev": "tsup --config=../../tsup.dev.ts"
41
41
  },
42
42
  "dependencies": {
43
- "@elementor/editor-current-user": "0.6.0",
44
- "@elementor/editor-elements": "0.9.0",
45
- "@elementor/editor-props": "0.16.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.14.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",
@@ -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;
@@ -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
  />
@@ -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
+ };
@@ -3,12 +3,20 @@ import { useRef } from 'react';
3
3
  import {
4
4
  blurFilterPropTypeUtil,
5
5
  brightnessFilterPropTypeUtil,
6
+ contrastFilterPropTypeUtil,
7
+ dropShadowFilterPropTypeUtil,
6
8
  type FilterItemPropValue,
7
9
  filterPropTypeUtil,
10
+ grayscaleFilterPropTypeUtil,
11
+ hueRotateFilterPropTypeUtil,
12
+ invertFilterPropTypeUtil,
8
13
  type PropKey,
9
14
  type PropTypeUtil,
15
+ saturateFilterPropTypeUtil,
16
+ sepiaFilterPropTypeUtil,
10
17
  type SizePropValue,
11
18
  } from '@elementor/editor-props';
19
+ import { backdropFilterPropTypeUtil } from '@elementor/editor-props';
12
20
  import { MenuListItem } from '@elementor/editor-ui';
13
21
  import { Box, Grid, Select, type SelectChangeEvent } from '@elementor/ui';
14
22
  import { __ } from '@wordpress/i18n';
@@ -17,9 +25,11 @@ import { PropKeyProvider, PropProvider, useBoundProp } from '../bound-prop-conte
17
25
  import { ControlLabel } from '../components/control-label';
18
26
  import { PopoverContent } from '../components/popover-content';
19
27
  import { PopoverGridContainer } from '../components/popover-grid-container';
20
- import { Repeater } from '../components/repeater';
28
+ import { type CollectionPropUtil, Repeater } from '../components/repeater';
21
29
  import { createControl } from '../create-control';
22
- import { defaultUnits } from '../utils/size-control';
30
+ import { defaultUnits, type Unit } from '../utils/size-control';
31
+ import { DropShadowItemContent } from './filter-control/drop-shadow-item-content';
32
+ import { DropShadowItemLabel } from './filter-control/drop-shadow-item-label';
23
33
  import { SizeControl } from './size-control';
24
34
 
25
35
  type FilterType = FilterItemPropValue[ '$$type' ];
@@ -43,6 +53,21 @@ const filterConfig: Record< FilterType, FilterItemConfig > = {
43
53
  propType: blurFilterPropTypeUtil,
44
54
  units: defaultUnits.filter( ( unit ) => unit !== '%' ),
45
55
  },
56
+ 'drop-shadow': {
57
+ defaultValue: {
58
+ $$type: 'drop-shadow',
59
+ value: {
60
+ xAxis: { $$type: 'size', value: { size: 0, unit: 'px' } },
61
+ yAxis: { $$type: 'size', value: { size: 0, unit: 'px' } },
62
+ blur: { $$type: 'size', value: { size: 10, unit: 'px' } },
63
+ color: { $$type: 'color', value: 'rgba(0, 0, 0, 1)' },
64
+ },
65
+ },
66
+ name: __( 'Drop shadow', 'elementor' ),
67
+ valueName: __( 'Drop-shadow', 'elementor' ),
68
+ propType: dropShadowFilterPropTypeUtil,
69
+ units: defaultUnits.filter( ( unit ) => unit !== '%' ),
70
+ },
46
71
  brightness: {
47
72
  defaultValue: { $$type: 'amount', amount: { $$type: 'size', value: { size: 100, unit: '%' } } },
48
73
  name: __( 'Brightness', 'elementor' ),
@@ -50,18 +75,62 @@ const filterConfig: Record< FilterType, FilterItemConfig > = {
50
75
  propType: brightnessFilterPropTypeUtil,
51
76
  units: [ '%' ],
52
77
  },
78
+ contrast: {
79
+ defaultValue: { $$type: 'contrast', contrast: { $$type: 'size', value: { size: 100, unit: '%' } } },
80
+ name: __( 'Contrast', 'elementor' ),
81
+ valueName: __( 'Amount', 'elementor' ),
82
+ propType: contrastFilterPropTypeUtil,
83
+ units: [ '%' ],
84
+ },
85
+ 'hue-rotate': {
86
+ defaultValue: { $$type: 'hue-rotate', 'hue-rotate': { $$type: 'size', value: { size: 0, unit: 'deg' } } },
87
+ name: __( 'Hue Rotate', 'elementor' ),
88
+ valueName: __( 'Angle', 'elementor' ),
89
+ propType: hueRotateFilterPropTypeUtil,
90
+ units: [ 'deg', 'rad', 'grad', 'turn' ],
91
+ },
92
+ saturate: {
93
+ defaultValue: { $$type: 'saturate', saturate: { $$type: 'size', value: { size: 100, unit: '%' } } },
94
+ name: __( 'Saturate', 'elementor' ),
95
+ valueName: __( 'Amount', 'elementor' ),
96
+ propType: saturateFilterPropTypeUtil,
97
+ units: [ '%' ],
98
+ },
99
+ grayscale: {
100
+ defaultValue: { $$type: 'grayscale', grayscale: { $$type: 'size', value: { size: 0, unit: '%' } } },
101
+ name: __( 'Grayscale', 'elementor' ),
102
+ valueName: __( 'Amount', 'elementor' ),
103
+ propType: grayscaleFilterPropTypeUtil,
104
+ units: [ '%' ],
105
+ },
106
+ invert: {
107
+ defaultValue: { $$type: 'invert', invert: { $$type: 'size', value: { size: 0, unit: '%' } } },
108
+ name: __( 'Invert', 'elementor' ),
109
+ valueName: __( 'Amount', 'elementor' ),
110
+ propType: invertFilterPropTypeUtil,
111
+ units: [ '%' ],
112
+ },
113
+ sepia: {
114
+ defaultValue: { $$type: 'sepia', sepia: { $$type: 'size', value: { size: 0, unit: '%' } } },
115
+ name: __( 'Sepia', 'elementor' ),
116
+ valueName: __( 'Amount', 'elementor' ),
117
+ propType: sepiaFilterPropTypeUtil,
118
+ units: [ '%' ],
119
+ },
53
120
  };
54
121
 
55
122
  const filterKeys = Object.keys( filterConfig ) as FilterType[];
56
123
 
57
- const singleSizeFilterNames = filterKeys.filter( ( name ) => {
58
- const filter = filterConfig[ name as FilterType ].defaultValue;
59
-
60
- return filter[ filter.$$type ].$$type === 'size';
61
- } ) as FilterType[];
124
+ const isSingleSize = ( key: FilterType ): boolean => {
125
+ return ! [ 'drop-shadow' ].includes( key );
126
+ };
62
127
 
63
- export const FilterRepeaterControl = createControl( () => {
64
- const { propType, value: filterValues, setValue, disabled } = useBoundProp( filterPropTypeUtil );
128
+ export const FilterRepeaterControl = createControl( ( { filterPropName = 'filter' }: { filterPropName?: string } ) => {
129
+ const [ propUtil, label ] =
130
+ filterPropName === 'backdrop-filter'
131
+ ? [ backdropFilterPropTypeUtil, __( 'Backdrop Filters', 'elementor' ) ]
132
+ : [ filterPropTypeUtil, __( 'Filters', 'elementor' ) ];
133
+ const { propType, value: filterValues, setValue, disabled } = useBoundProp( propUtil );
65
134
 
66
135
  return (
67
136
  <PropProvider propType={ propType } value={ filterValues } setValue={ setValue }>
@@ -70,7 +139,8 @@ export const FilterRepeaterControl = createControl( () => {
70
139
  disabled={ disabled }
71
140
  values={ filterValues ?? [] }
72
141
  setValues={ setValue }
73
- label={ __( 'Filter', 'elementor' ) }
142
+ label={ label }
143
+ collectionPropUtil={ propUtil }
74
144
  itemSettings={ {
75
145
  Icon: ItemIcon,
76
146
  Label: ItemLabel,
@@ -87,10 +157,12 @@ export const FilterRepeaterControl = createControl( () => {
87
157
 
88
158
  const ItemIcon = () => <></>;
89
159
 
90
- const ItemLabel = ( props: { value: FilterItemPropValue } ) => {
91
- const { $$type } = props.value;
92
-
93
- return singleSizeFilterNames.includes( $$type ) && <SingleSizeItemLabel value={ props.value } />;
160
+ const ItemLabel = ( { value }: { value: FilterItemPropValue } ) => {
161
+ return isSingleSize( value.$$type ) ? (
162
+ <SingleSizeItemLabel value={ value } />
163
+ ) : (
164
+ <DropShadowItemLabel value={ value } />
165
+ );
94
166
  };
95
167
 
96
168
  const SingleSizeItemLabel = ( { value }: { value: FilterItemPropValue } ) => {
@@ -113,8 +185,16 @@ const SingleSizeItemLabel = ( { value }: { value: FilterItemPropValue } ) => {
113
185
  );
114
186
  };
115
187
 
116
- const ItemContent = ( { bind }: { bind: PropKey } ) => {
117
- const { value: filterValues, setValue } = useBoundProp( filterPropTypeUtil );
188
+ const ItemContent = ( {
189
+ bind,
190
+ collectionPropUtil,
191
+ anchorEl,
192
+ }: {
193
+ bind: PropKey;
194
+ collectionPropUtil?: CollectionPropUtil< FilterItemPropValue >;
195
+ anchorEl?: HTMLElement | null;
196
+ } ) => {
197
+ const { value: filterValues, setValue } = useBoundProp( collectionPropUtil ?? filterPropTypeUtil );
118
198
  const itemIndex = parseInt( bind, 10 );
119
199
  const item = filterValues?.[ itemIndex ];
120
200
 
@@ -124,7 +204,7 @@ const ItemContent = ( { bind }: { bind: PropKey } ) => {
124
204
 
125
205
  newFilterValues[ itemIndex ] = {
126
206
  $$type: filterType,
127
- value: filterConfig[ filterType ].defaultValue,
207
+ value: { ...filterConfig[ filterType ].defaultValue },
128
208
  } as FilterItemPropValue;
129
209
 
130
210
  setValue( newFilterValues );
@@ -153,14 +233,20 @@ const ItemContent = ( { bind }: { bind: PropKey } ) => {
153
233
  </Select>
154
234
  </Grid>
155
235
  </PopoverGridContainer>
156
- <Content filterType={ item?.$$type } />
236
+ <Content filterType={ item?.$$type } anchorEl={ anchorEl } />
157
237
  </PopoverContent>
158
238
  </PropKeyProvider>
159
239
  );
160
240
  };
161
241
 
162
- const Content = ( { filterType }: { filterType: FilterType } ) => {
163
- return singleSizeFilterNames.includes( filterType ) && <SingleSizeItemContent filterType={ filterType } />;
242
+ const Content = ( { filterType, anchorEl }: { filterType: FilterType; anchorEl?: HTMLElement | null } ) => {
243
+ const { propType, units = [] } = filterConfig[ filterType ];
244
+
245
+ return isSingleSize( filterType ) ? (
246
+ <SingleSizeItemContent filterType={ filterType } />
247
+ ) : (
248
+ <DropShadowItemContent propType={ propType } units={ units as Unit[] } anchorEl={ anchorEl } />
249
+ );
164
250
  };
165
251
 
166
252
  const SingleSizeItemContent = ( { filterType }: { filterType: FilterType } ) => {
@@ -168,6 +254,7 @@ const SingleSizeItemContent = ( { filterType }: { filterType: FilterType } ) =>
168
254
  const { $$type } = defaultValue;
169
255
  const context = useBoundProp( propType );
170
256
  const rowRef = useRef< HTMLDivElement >( null );
257
+ const defaultUnit = defaultValue[ $$type ].value.unit;
171
258
 
172
259
  return (
173
260
  <PropProvider { ...context }>
@@ -177,7 +264,7 @@ const SingleSizeItemContent = ( { filterType }: { filterType: FilterType } ) =>
177
264
  <ControlLabel>{ valueName }</ControlLabel>
178
265
  </Grid>
179
266
  <Grid item xs={ 6 }>
180
- <SizeControl anchorRef={ rowRef } units={ units } />
267
+ <SizeControl anchorRef={ rowRef } units={ units } defaultUnit={ defaultUnit } />
181
268
  </Grid>
182
269
  </PopoverGridContainer>
183
270
  </PropKeyProvider>