@elementor/editor-controls 1.1.0 → 1.3.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/CHANGELOG.md +57 -0
- package/dist/index.d.mts +26 -13
- package/dist/index.d.ts +26 -13
- package/dist/index.js +979 -575
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +823 -418
- package/dist/index.mjs.map +1 -1
- package/package.json +11 -11
- package/src/bound-prop-context/prop-context.tsx +3 -3
- package/src/bound-prop-context/prop-key-context.tsx +1 -0
- package/src/bound-prop-context/use-bound-prop.ts +5 -1
- package/src/components/font-family-selector.tsx +30 -13
- package/src/components/popover-content.tsx +3 -11
- package/src/components/repeater.tsx +3 -1
- package/src/components/text-field-popover.tsx +21 -20
- package/src/controls/aspect-ratio-control.tsx +20 -2
- package/src/controls/background-control/background-overlay/background-image-overlay/background-image-overlay-position.tsx +2 -2
- package/src/controls/background-control/background-overlay/background-image-overlay/background-image-overlay-size.tsx +2 -2
- package/src/controls/background-control/background-overlay/background-overlay-repeater-control.tsx +3 -10
- package/src/controls/box-shadow-repeater-control.tsx +3 -3
- package/src/controls/equal-unequal-sizes-control.tsx +4 -10
- package/src/controls/filter-repeater-control.tsx +186 -0
- package/src/controls/font-family-control/font-family-control.tsx +20 -4
- package/src/controls/gap-control.tsx +3 -3
- package/src/controls/image-control.tsx +46 -30
- package/src/controls/key-value-control.tsx +39 -19
- package/src/controls/link-control.tsx +28 -21
- package/src/controls/linked-dimensions-control.tsx +4 -4
- package/src/controls/number-control.tsx +3 -3
- package/src/controls/repeatable-control.tsx +98 -8
- package/src/controls/select-control.tsx +22 -2
- package/src/controls/size-control.tsx +3 -3
- package/src/controls/stroke-control.tsx +2 -2
- package/src/controls/svg-media-control.tsx +0 -2
- package/src/controls/switch-control.tsx +9 -1
- package/src/controls/transform-control/functions/axis-row.tsx +32 -0
- package/src/controls/transform-control/functions/move.tsx +44 -0
- package/src/controls/transform-control/transform-content.tsx +36 -0
- package/src/controls/transform-control/transform-icon.tsx +12 -0
- package/src/controls/transform-control/transform-label.tsx +27 -0
- package/src/controls/transform-control/transform-repeater-control.tsx +42 -0
- package/src/hooks/use-repeatable-control-context.ts +6 -1
- package/src/index.ts +4 -1
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.
|
|
4
|
+
"version": "1.3.0",
|
|
5
5
|
"private": false,
|
|
6
6
|
"author": "Elementor Team",
|
|
7
7
|
"homepage": "https://elementor.com/",
|
|
@@ -40,21 +40,21 @@
|
|
|
40
40
|
"dev": "tsup --config=../../tsup.dev.ts"
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
|
-
"@elementor/editor-current-user": "0.
|
|
44
|
-
"@elementor/editor-elements": "0.
|
|
45
|
-
"@elementor/editor-props": "0.
|
|
46
|
-
"@elementor/editor-responsive": "0.13.
|
|
47
|
-
"@elementor/editor-ui": "0.
|
|
48
|
-
"@elementor/editor-v1-adapters": "0.12.
|
|
43
|
+
"@elementor/editor-current-user": "0.6.0",
|
|
44
|
+
"@elementor/editor-elements": "0.9.0",
|
|
45
|
+
"@elementor/editor-props": "0.16.0",
|
|
46
|
+
"@elementor/editor-responsive": "0.13.6",
|
|
47
|
+
"@elementor/editor-ui": "0.14.0",
|
|
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.
|
|
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.
|
|
56
|
-
"@elementor/utils": "0.
|
|
57
|
-
"@elementor/wp-media": "0.6.
|
|
55
|
+
"@elementor/ui": "1.36.0",
|
|
56
|
+
"@elementor/utils": "0.5.0",
|
|
57
|
+
"@elementor/wp-media": "0.6.1",
|
|
58
58
|
"@wordpress/i18n": "^5.13.0"
|
|
59
59
|
},
|
|
60
60
|
"devDependencies": {
|
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
42
|
+
isDisabled,
|
|
43
43
|
} }
|
|
44
44
|
>
|
|
45
45
|
{ children }
|
|
@@ -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
|
|
|
@@ -17,6 +17,7 @@ type FontFamilySelectorProps = {
|
|
|
17
17
|
fontFamily: string | null;
|
|
18
18
|
onFontFamilyChange: ( fontFamily: string ) => void;
|
|
19
19
|
onClose: () => void;
|
|
20
|
+
sectionWidth: number;
|
|
20
21
|
};
|
|
21
22
|
|
|
22
23
|
export const FontFamilySelector = ( {
|
|
@@ -24,6 +25,7 @@ export const FontFamilySelector = ( {
|
|
|
24
25
|
fontFamily,
|
|
25
26
|
onFontFamilyChange,
|
|
26
27
|
onClose,
|
|
28
|
+
sectionWidth,
|
|
27
29
|
}: FontFamilySelectorProps ) => {
|
|
28
30
|
const [ searchValue, setSearchValue ] = useState( '' );
|
|
29
31
|
|
|
@@ -45,22 +47,32 @@ export const FontFamilySelector = ( {
|
|
|
45
47
|
onClose={ handleClose }
|
|
46
48
|
icon={ <TextIcon fontSize={ SIZE } /> }
|
|
47
49
|
/>
|
|
50
|
+
|
|
48
51
|
<PopoverSearch
|
|
49
52
|
value={ searchValue }
|
|
50
53
|
onSearch={ handleSearch }
|
|
51
54
|
placeholder={ __( 'Search', 'elementor' ) }
|
|
52
55
|
/>
|
|
56
|
+
|
|
53
57
|
<Divider />
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
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
|
+
>
|
|
64
76
|
<TextIcon fontSize="large" />
|
|
65
77
|
<Box sx={ { maxWidth: 160, overflow: 'hidden' } }>
|
|
66
78
|
<Typography align="center" variant="subtitle2" color="text.secondary">
|
|
@@ -82,7 +94,12 @@ export const FontFamilySelector = ( {
|
|
|
82
94
|
<span>”.</span>
|
|
83
95
|
</Typography>
|
|
84
96
|
</Box>
|
|
85
|
-
<Typography
|
|
97
|
+
<Typography
|
|
98
|
+
align="center"
|
|
99
|
+
variant="caption"
|
|
100
|
+
color="text.secondary"
|
|
101
|
+
sx={ { display: 'flex', flexDirection: 'column' } }
|
|
102
|
+
>
|
|
86
103
|
{ __( 'Try something else.', 'elementor' ) }
|
|
87
104
|
<Link
|
|
88
105
|
color="secondary"
|
|
@@ -94,8 +111,8 @@ export const FontFamilySelector = ( {
|
|
|
94
111
|
</Link>
|
|
95
112
|
</Typography>
|
|
96
113
|
</Stack>
|
|
97
|
-
|
|
98
|
-
|
|
114
|
+
) }
|
|
115
|
+
</PopoverScrollableContent>
|
|
99
116
|
</Stack>
|
|
100
117
|
);
|
|
101
118
|
};
|
|
@@ -1,17 +1,9 @@
|
|
|
1
1
|
import { type FC, type PropsWithChildren } from 'react';
|
|
2
2
|
import * as React from 'react';
|
|
3
|
-
import { Stack } from '@elementor/ui';
|
|
3
|
+
import { Stack, type StackProps } from '@elementor/ui';
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
gap?: number;
|
|
8
|
-
p?: 1.5 | 2 | 2.5;
|
|
9
|
-
pt?: 2.5;
|
|
10
|
-
pb?: 3;
|
|
11
|
-
} >;
|
|
12
|
-
|
|
13
|
-
export const PopoverContent: FC< PopoverContentProps > = ( { alignItems, gap = 1.5, p, pt, pb, children } ) => (
|
|
14
|
-
<Stack alignItems={ alignItems } gap={ gap } p={ p } pt={ pt } pb={ pb }>
|
|
5
|
+
export const PopoverContent: FC< PropsWithChildren< StackProps > > = ( { gap = 1.5, children, ...props } ) => (
|
|
6
|
+
<Stack { ...props } gap={ gap }>
|
|
15
7
|
{ children }
|
|
16
8
|
</Stack>
|
|
17
9
|
);
|
|
@@ -50,6 +50,7 @@ type RepeaterProps< T > = {
|
|
|
50
50
|
};
|
|
51
51
|
showDuplicate?: boolean;
|
|
52
52
|
showToggle?: boolean;
|
|
53
|
+
isSortable?: boolean;
|
|
53
54
|
};
|
|
54
55
|
|
|
55
56
|
const EMPTY_OPEN_ITEM = -1;
|
|
@@ -64,6 +65,7 @@ export const Repeater = < T, >( {
|
|
|
64
65
|
setValues: setRepeaterValues,
|
|
65
66
|
showDuplicate = true,
|
|
66
67
|
showToggle = true,
|
|
68
|
+
isSortable = true,
|
|
67
69
|
}: RepeaterProps< Item< T > > ) => {
|
|
68
70
|
const [ openItem, setOpenItem ] = useState( EMPTY_OPEN_ITEM );
|
|
69
71
|
|
|
@@ -180,7 +182,7 @@ export const Repeater = < T, >( {
|
|
|
180
182
|
}
|
|
181
183
|
|
|
182
184
|
return (
|
|
183
|
-
<SortableItem id={ key } key={ `sortable-${ key }` } disabled={
|
|
185
|
+
<SortableItem id={ key } key={ `sortable-${ key }` } disabled={ ! isSortable }>
|
|
184
186
|
<RepeaterItem
|
|
185
187
|
disabled={ disabled }
|
|
186
188
|
propDisabled={ value?.disabled }
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import { type
|
|
3
|
-
import { bindPopover,
|
|
2
|
+
import { type RefObject } from 'react';
|
|
3
|
+
import { bindPopover, Popover, type PopupState, TextField } from '@elementor/ui';
|
|
4
4
|
|
|
5
5
|
type Props = {
|
|
6
6
|
popupState: PopupState;
|
|
7
|
-
anchorRef:
|
|
7
|
+
anchorRef: RefObject< HTMLDivElement | null >;
|
|
8
8
|
restoreValue: () => void;
|
|
9
9
|
value: string;
|
|
10
10
|
onChange: ( event: React.ChangeEvent< HTMLInputElement > ) => void;
|
|
@@ -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
|
-
<
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
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
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import { useState } from 'react';
|
|
2
|
+
import { useEffect, useState } from 'react';
|
|
3
3
|
import { stringPropTypeUtil } from '@elementor/editor-props';
|
|
4
4
|
import { MenuListItem } from '@elementor/editor-ui';
|
|
5
5
|
import { ArrowsMoveHorizontalIcon, ArrowsMoveVerticalIcon } from '@elementor/icons';
|
|
@@ -38,6 +38,24 @@ export const AspectRatioControl = createControl( ( { label }: { label: string }
|
|
|
38
38
|
isCustomSelected ? CUSTOM_RATIO : aspectRatioValue || ''
|
|
39
39
|
);
|
|
40
40
|
|
|
41
|
+
useEffect( () => {
|
|
42
|
+
const isCustomValue =
|
|
43
|
+
aspectRatioValue && ! RATIO_OPTIONS.some( ( option ) => option.value === aspectRatioValue );
|
|
44
|
+
|
|
45
|
+
if ( isCustomValue ) {
|
|
46
|
+
const [ width, height ] = aspectRatioValue.split( '/' );
|
|
47
|
+
setCustomWidth( width || '' );
|
|
48
|
+
setCustomHeight( height || '' );
|
|
49
|
+
setSelectedValue( CUSTOM_RATIO );
|
|
50
|
+
setIsCustom( true );
|
|
51
|
+
} else {
|
|
52
|
+
setSelectedValue( aspectRatioValue || '' );
|
|
53
|
+
setIsCustom( false );
|
|
54
|
+
setCustomWidth( '' );
|
|
55
|
+
setCustomHeight( '' );
|
|
56
|
+
}
|
|
57
|
+
}, [ aspectRatioValue ] );
|
|
58
|
+
|
|
41
59
|
const handleSelectChange = ( event: SelectChangeEvent< string > ) => {
|
|
42
60
|
const newValue = event.target.value;
|
|
43
61
|
const isCustomRatio = newValue === CUSTOM_RATIO;
|
|
@@ -71,7 +89,7 @@ export const AspectRatioControl = createControl( ( { label }: { label: string }
|
|
|
71
89
|
|
|
72
90
|
return (
|
|
73
91
|
<ControlActions>
|
|
74
|
-
<Stack direction="column"
|
|
92
|
+
<Stack direction="column" gap={ 2 }>
|
|
75
93
|
<Grid container gap={ 2 } alignItems="center" flexWrap="nowrap">
|
|
76
94
|
<Grid item xs={ 6 }>
|
|
77
95
|
<ControlLabel>{ label }</ControlLabel>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import { useRef } from 'react';
|
|
3
3
|
import { backgroundImagePositionOffsetPropTypeUtil, stringPropTypeUtil } from '@elementor/editor-props';
|
|
4
4
|
import { MenuListItem } from '@elementor/editor-ui';
|
|
5
5
|
import { LetterXIcon, LetterYIcon } from '@elementor/icons';
|
|
@@ -41,7 +41,7 @@ export const BackgroundImageOverlayPosition = () => {
|
|
|
41
41
|
const stringPropContext = useBoundProp( stringPropTypeUtil );
|
|
42
42
|
|
|
43
43
|
const isCustom = !! backgroundImageOffsetContext.value;
|
|
44
|
-
const rowRef
|
|
44
|
+
const rowRef = useRef< HTMLDivElement >( null );
|
|
45
45
|
|
|
46
46
|
const handlePositionChange = ( event: SelectChangeEvent< Positions > ) => {
|
|
47
47
|
const value = event.target.value || null;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import { useRef } from 'react';
|
|
3
3
|
import { backgroundImageSizeScalePropTypeUtil, stringPropTypeUtil } from '@elementor/editor-props';
|
|
4
4
|
import {
|
|
5
5
|
ArrowBarBothIcon,
|
|
@@ -55,7 +55,7 @@ export const BackgroundImageOverlaySize = () => {
|
|
|
55
55
|
const stringPropContext = useBoundProp( stringPropTypeUtil );
|
|
56
56
|
|
|
57
57
|
const isCustom = !! backgroundImageScaleContext.value;
|
|
58
|
-
const rowRef
|
|
58
|
+
const rowRef = useRef< HTMLDivElement >( null );
|
|
59
59
|
|
|
60
60
|
const handleSizeChange = ( size: Sizes | null ) => {
|
|
61
61
|
if ( size === 'custom' ) {
|
package/src/controls/background-control/background-overlay/background-overlay-repeater-control.tsx
CHANGED
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
colorPropTypeUtil,
|
|
8
8
|
type PropKey,
|
|
9
9
|
} from '@elementor/editor-props';
|
|
10
|
-
import { Box, CardMedia,
|
|
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
|
|
|
@@ -74,7 +74,7 @@ export const BackgroundOverlayRepeaterControl = createControl( () => {
|
|
|
74
74
|
const { propType, value: overlayValues, setValue, disabled } = useBoundProp( backgroundOverlayPropTypeUtil );
|
|
75
75
|
|
|
76
76
|
return (
|
|
77
|
-
<PropProvider propType={ propType } value={ overlayValues } setValue={ setValue }
|
|
77
|
+
<PropProvider propType={ propType } value={ overlayValues } setValue={ setValue } isDisabled={ () => disabled }>
|
|
78
78
|
<Repeater
|
|
79
79
|
openOnAdd
|
|
80
80
|
disabled={ disabled }
|
|
@@ -235,14 +235,7 @@ const ImageOverlayContent = () => {
|
|
|
235
235
|
return (
|
|
236
236
|
<PropProvider { ...propContext }>
|
|
237
237
|
<PropKeyProvider bind={ 'image' }>
|
|
238
|
-
<
|
|
239
|
-
<Grid item xs={ 12 }>
|
|
240
|
-
<ImageControl
|
|
241
|
-
resolutionLabel={ __( 'Resolution', 'elementor' ) }
|
|
242
|
-
sizes={ backgroundResolutionOptions }
|
|
243
|
-
/>
|
|
244
|
-
</Grid>
|
|
245
|
-
</Grid>
|
|
238
|
+
<ImageControl sizes={ backgroundResolutionOptions } />
|
|
246
239
|
</PropKeyProvider>
|
|
247
240
|
<PropKeyProvider bind={ 'position' }>
|
|
248
241
|
<BackgroundImageOverlayPosition />
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import { type
|
|
2
|
+
import { type RefObject, useRef } from 'react';
|
|
3
3
|
import { boxShadowPropTypeUtil, type PropKey, shadowPropTypeUtil, type ShadowPropValue } from '@elementor/editor-props';
|
|
4
4
|
import { FormLabel, Grid, type SxProps, type Theme, UnstableColorIndicator } from '@elementor/ui';
|
|
5
5
|
import { __ } from '@wordpress/i18n';
|
|
@@ -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 }
|
|
20
|
+
<PropProvider propType={ propType } value={ value } setValue={ setValue } isDisabled={ () => disabled }>
|
|
21
21
|
<Repeater
|
|
22
22
|
openOnAdd
|
|
23
23
|
disabled={ disabled }
|
|
@@ -49,7 +49,7 @@ const ItemContent = ( { anchorEl, bind }: { anchorEl: HTMLElement | null; bind:
|
|
|
49
49
|
|
|
50
50
|
const Content = ( { anchorEl }: { anchorEl: HTMLElement | null } ) => {
|
|
51
51
|
const context = useBoundProp( shadowPropTypeUtil );
|
|
52
|
-
const rowRef:
|
|
52
|
+
const rowRef: RefObject< HTMLDivElement >[] = [ useRef( null ), useRef( null ) ];
|
|
53
53
|
|
|
54
54
|
return (
|
|
55
55
|
<PropProvider { ...context }>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import { type
|
|
2
|
+
import { type ReactNode, type RefObject, useId, useRef } from 'react';
|
|
3
3
|
import { type PropKey, type PropTypeUtil, sizePropTypeUtil, type SizePropValue } from '@elementor/editor-props';
|
|
4
4
|
import { isExperimentActive } from '@elementor/editor-v1-adapters';
|
|
5
5
|
import { bindPopover, bindToggle, Grid, Popover, Stack, ToggleButton, Tooltip, usePopupState } from '@elementor/ui';
|
|
@@ -63,7 +63,7 @@ export function EqualUnequalSizesControl< TMultiPropType extends string, TPropVa
|
|
|
63
63
|
|
|
64
64
|
const { value: sizeValue, setValue: setSizeValue } = useBoundProp( sizePropTypeUtil );
|
|
65
65
|
|
|
66
|
-
const rowRefs:
|
|
66
|
+
const rowRefs: RefObject< HTMLDivElement >[] = [ useRef( null ), useRef( null ) ];
|
|
67
67
|
|
|
68
68
|
const splitEqualValue = () => {
|
|
69
69
|
if ( ! sizeValue ) {
|
|
@@ -154,7 +154,7 @@ export function EqualUnequalSizesControl< TMultiPropType extends string, TPropVa
|
|
|
154
154
|
propType={ multiSizePropType }
|
|
155
155
|
value={ getMultiSizeValues() }
|
|
156
156
|
setValue={ setNestedProp }
|
|
157
|
-
|
|
157
|
+
isDisabled={ () => multiSizeDisabled }
|
|
158
158
|
>
|
|
159
159
|
<PopoverContent p={ 1.5 }>
|
|
160
160
|
<PopoverGridContainer ref={ rowRefs[ 1 ] }>
|
|
@@ -172,13 +172,7 @@ export function EqualUnequalSizesControl< TMultiPropType extends string, TPropVa
|
|
|
172
172
|
);
|
|
173
173
|
}
|
|
174
174
|
|
|
175
|
-
const MultiSizeValueControl = ( {
|
|
176
|
-
item,
|
|
177
|
-
rowRef,
|
|
178
|
-
}: {
|
|
179
|
-
item: Item;
|
|
180
|
-
rowRef: MutableRefObject< HTMLElement | undefined >;
|
|
181
|
-
} ) => {
|
|
175
|
+
const MultiSizeValueControl = ( { item, rowRef }: { item: Item; rowRef: RefObject< HTMLDivElement > } ) => {
|
|
182
176
|
const isUsingNestedProps = isExperimentActive( 'e_v_3_30' );
|
|
183
177
|
|
|
184
178
|
return (
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { useRef } from 'react';
|
|
3
|
+
import {
|
|
4
|
+
blurFilterPropTypeUtil,
|
|
5
|
+
brightnessFilterPropTypeUtil,
|
|
6
|
+
type FilterItemPropValue,
|
|
7
|
+
filterPropTypeUtil,
|
|
8
|
+
type PropKey,
|
|
9
|
+
type PropTypeUtil,
|
|
10
|
+
type SizePropValue,
|
|
11
|
+
} from '@elementor/editor-props';
|
|
12
|
+
import { MenuListItem } from '@elementor/editor-ui';
|
|
13
|
+
import { Box, Grid, Select, type SelectChangeEvent } from '@elementor/ui';
|
|
14
|
+
import { __ } from '@wordpress/i18n';
|
|
15
|
+
|
|
16
|
+
import { PropKeyProvider, PropProvider, useBoundProp } from '../bound-prop-context';
|
|
17
|
+
import { ControlLabel } from '../components/control-label';
|
|
18
|
+
import { PopoverContent } from '../components/popover-content';
|
|
19
|
+
import { PopoverGridContainer } from '../components/popover-grid-container';
|
|
20
|
+
import { Repeater } from '../components/repeater';
|
|
21
|
+
import { createControl } from '../create-control';
|
|
22
|
+
import { defaultUnits } from '../utils/size-control';
|
|
23
|
+
import { SizeControl } from './size-control';
|
|
24
|
+
|
|
25
|
+
type FilterType = FilterItemPropValue[ '$$type' ];
|
|
26
|
+
type FilterValue = FilterItemPropValue[ 'value' ];
|
|
27
|
+
|
|
28
|
+
const DEFAULT_FILTER_KEY: FilterType = 'blur';
|
|
29
|
+
|
|
30
|
+
type FilterItemConfig = {
|
|
31
|
+
defaultValue: FilterValue;
|
|
32
|
+
name: string;
|
|
33
|
+
valueName: string;
|
|
34
|
+
propType: PropTypeUtil< FilterValue, FilterValue >;
|
|
35
|
+
units?: Exclude< SizePropValue[ 'value' ][ 'unit' ], 'custom' | 'auto' >[];
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const filterConfig: Record< FilterType, FilterItemConfig > = {
|
|
39
|
+
blur: {
|
|
40
|
+
defaultValue: { $$type: 'radius', radius: { $$type: 'size', value: { size: 0, unit: 'px' } } },
|
|
41
|
+
name: __( 'Blur', 'elementor' ),
|
|
42
|
+
valueName: __( 'Radius', 'elementor' ),
|
|
43
|
+
propType: blurFilterPropTypeUtil,
|
|
44
|
+
units: defaultUnits.filter( ( unit ) => unit !== '%' ),
|
|
45
|
+
},
|
|
46
|
+
brightness: {
|
|
47
|
+
defaultValue: { $$type: 'amount', amount: { $$type: 'size', value: { size: 100, unit: '%' } } },
|
|
48
|
+
name: __( 'Brightness', 'elementor' ),
|
|
49
|
+
valueName: __( 'Amount', 'elementor' ),
|
|
50
|
+
propType: brightnessFilterPropTypeUtil,
|
|
51
|
+
units: [ '%' ],
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
const filterKeys = Object.keys( filterConfig ) as FilterType[];
|
|
56
|
+
|
|
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[];
|
|
62
|
+
|
|
63
|
+
export const FilterRepeaterControl = createControl( () => {
|
|
64
|
+
const { propType, value: filterValues, setValue, disabled } = useBoundProp( filterPropTypeUtil );
|
|
65
|
+
|
|
66
|
+
return (
|
|
67
|
+
<PropProvider propType={ propType } value={ filterValues } setValue={ setValue }>
|
|
68
|
+
<Repeater
|
|
69
|
+
openOnAdd
|
|
70
|
+
disabled={ disabled }
|
|
71
|
+
values={ filterValues ?? [] }
|
|
72
|
+
setValues={ setValue }
|
|
73
|
+
label={ __( 'Filter', 'elementor' ) }
|
|
74
|
+
itemSettings={ {
|
|
75
|
+
Icon: ItemIcon,
|
|
76
|
+
Label: ItemLabel,
|
|
77
|
+
Content: ItemContent,
|
|
78
|
+
initialValues: {
|
|
79
|
+
$$type: DEFAULT_FILTER_KEY,
|
|
80
|
+
value: filterConfig[ DEFAULT_FILTER_KEY ].defaultValue,
|
|
81
|
+
} as FilterItemPropValue,
|
|
82
|
+
} }
|
|
83
|
+
/>
|
|
84
|
+
</PropProvider>
|
|
85
|
+
);
|
|
86
|
+
} );
|
|
87
|
+
|
|
88
|
+
const ItemIcon = () => <></>;
|
|
89
|
+
|
|
90
|
+
const ItemLabel = ( props: { value: FilterItemPropValue } ) => {
|
|
91
|
+
const { $$type } = props.value;
|
|
92
|
+
|
|
93
|
+
return singleSizeFilterNames.includes( $$type ) && <SingleSizeItemLabel value={ props.value } />;
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
const SingleSizeItemLabel = ( { value }: { value: FilterItemPropValue } ) => {
|
|
97
|
+
const { $$type, value: sizeValue } = value;
|
|
98
|
+
const { $$type: key } = filterConfig[ $$type ].defaultValue;
|
|
99
|
+
const defaultUnit = filterConfig[ $$type ].defaultValue[ key ].value.unit;
|
|
100
|
+
const { unit, size } = sizeValue[ key ]?.value ?? { unit: defaultUnit, size: 0 };
|
|
101
|
+
|
|
102
|
+
const label = (
|
|
103
|
+
<Box component="span" style={ { textTransform: 'capitalize' } }>
|
|
104
|
+
{ value.$$type }:
|
|
105
|
+
</Box>
|
|
106
|
+
);
|
|
107
|
+
|
|
108
|
+
return (
|
|
109
|
+
<Box component="span">
|
|
110
|
+
{ label }
|
|
111
|
+
{ unit !== 'custom' ? ` ${ size ?? 0 }${ unit ?? defaultUnit }` : size }
|
|
112
|
+
</Box>
|
|
113
|
+
);
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
const ItemContent = ( { bind }: { bind: PropKey } ) => {
|
|
117
|
+
const { value: filterValues, setValue } = useBoundProp( filterPropTypeUtil );
|
|
118
|
+
const itemIndex = parseInt( bind, 10 );
|
|
119
|
+
const item = filterValues?.[ itemIndex ];
|
|
120
|
+
|
|
121
|
+
const handleChange = ( e: SelectChangeEvent< string > ) => {
|
|
122
|
+
const newFilterValues = [ ...filterValues ];
|
|
123
|
+
const filterType = e.target.value as FilterType;
|
|
124
|
+
|
|
125
|
+
newFilterValues[ itemIndex ] = {
|
|
126
|
+
$$type: filterType,
|
|
127
|
+
value: filterConfig[ filterType ].defaultValue,
|
|
128
|
+
} as FilterItemPropValue;
|
|
129
|
+
|
|
130
|
+
setValue( newFilterValues );
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
return (
|
|
134
|
+
<PropKeyProvider bind={ bind }>
|
|
135
|
+
<PopoverContent p={ 1.5 }>
|
|
136
|
+
<PopoverGridContainer>
|
|
137
|
+
<Grid item xs={ 6 }>
|
|
138
|
+
<ControlLabel>{ __( 'Filter', 'elementor' ) }</ControlLabel>
|
|
139
|
+
</Grid>
|
|
140
|
+
<Grid item xs={ 6 }>
|
|
141
|
+
<Select
|
|
142
|
+
sx={ { overflow: 'hidden' } }
|
|
143
|
+
size="tiny"
|
|
144
|
+
value={ item?.$$type ?? DEFAULT_FILTER_KEY }
|
|
145
|
+
onChange={ handleChange }
|
|
146
|
+
fullWidth
|
|
147
|
+
>
|
|
148
|
+
{ filterKeys.map( ( filterKey ) => (
|
|
149
|
+
<MenuListItem key={ filterKey } value={ filterKey }>
|
|
150
|
+
{ filterConfig[ filterKey ].name }
|
|
151
|
+
</MenuListItem>
|
|
152
|
+
) ) }
|
|
153
|
+
</Select>
|
|
154
|
+
</Grid>
|
|
155
|
+
</PopoverGridContainer>
|
|
156
|
+
<Content filterType={ item?.$$type } />
|
|
157
|
+
</PopoverContent>
|
|
158
|
+
</PropKeyProvider>
|
|
159
|
+
);
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
const Content = ( { filterType }: { filterType: FilterType } ) => {
|
|
163
|
+
return singleSizeFilterNames.includes( filterType ) && <SingleSizeItemContent filterType={ filterType } />;
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
const SingleSizeItemContent = ( { filterType }: { filterType: FilterType } ) => {
|
|
167
|
+
const { propType, valueName, defaultValue, units } = filterConfig[ filterType ];
|
|
168
|
+
const { $$type } = defaultValue;
|
|
169
|
+
const context = useBoundProp( propType );
|
|
170
|
+
const rowRef = useRef< HTMLDivElement >( null );
|
|
171
|
+
|
|
172
|
+
return (
|
|
173
|
+
<PropProvider { ...context }>
|
|
174
|
+
<PropKeyProvider bind={ $$type }>
|
|
175
|
+
<PopoverGridContainer ref={ rowRef }>
|
|
176
|
+
<Grid item xs={ 6 }>
|
|
177
|
+
<ControlLabel>{ valueName }</ControlLabel>
|
|
178
|
+
</Grid>
|
|
179
|
+
<Grid item xs={ 6 }>
|
|
180
|
+
<SizeControl anchorRef={ rowRef } units={ units } />
|
|
181
|
+
</Grid>
|
|
182
|
+
</PopoverGridContainer>
|
|
183
|
+
</PropKeyProvider>
|
|
184
|
+
</PropProvider>
|
|
185
|
+
);
|
|
186
|
+
};
|