@elementor/editor-controls 1.1.0 → 1.2.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 +31 -0
- package/dist/index.d.mts +20 -11
- package/dist/index.d.ts +20 -11
- package/dist/index.js +739 -565
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +548 -372
- package/dist/index.mjs.map +1 -1
- package/package.json +8 -8
- 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 +3 -3
- 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 +9 -4
- package/src/controls/box-shadow-repeater-control.tsx +2 -2
- package/src/controls/equal-unequal-sizes-control.tsx +3 -9
- package/src/controls/filter-repeater-control.tsx +186 -0
- package/src/controls/font-family-control/font-family-control.tsx +6 -2
- package/src/controls/gap-control.tsx +3 -3
- package/src/controls/image-control.tsx +22 -35
- package/src/controls/key-value-control.tsx +39 -19
- package/src/controls/link-control.tsx +3 -1
- package/src/controls/linked-dimensions-control.tsx +3 -3
- package/src/controls/number-control.tsx +3 -3
- package/src/controls/repeatable-control.tsx +38 -8
- 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/index.ts +3 -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.2.0",
|
|
5
5
|
"private": false,
|
|
6
6
|
"author": "Elementor Team",
|
|
7
7
|
"homepage": "https://elementor.com/",
|
|
@@ -41,11 +41,11 @@
|
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
43
|
"@elementor/editor-current-user": "0.5.0",
|
|
44
|
-
"@elementor/editor-elements": "0.8.
|
|
45
|
-
"@elementor/editor-props": "0.
|
|
46
|
-
"@elementor/editor-responsive": "0.13.
|
|
47
|
-
"@elementor/editor-ui": "0.
|
|
48
|
-
"@elementor/editor-v1-adapters": "0.12.
|
|
44
|
+
"@elementor/editor-elements": "0.8.7",
|
|
45
|
+
"@elementor/editor-props": "0.15.0",
|
|
46
|
+
"@elementor/editor-responsive": "0.13.6",
|
|
47
|
+
"@elementor/editor-ui": "0.13.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
51
|
"@elementor/icons": "1.44.0",
|
|
@@ -53,8 +53,8 @@
|
|
|
53
53
|
"@elementor/query": "0.2.4",
|
|
54
54
|
"@elementor/session": "0.1.0",
|
|
55
55
|
"@elementor/ui": "1.35.5",
|
|
56
|
-
"@elementor/utils": "0.
|
|
57
|
-
"@elementor/wp-media": "0.6.
|
|
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": {
|
|
@@ -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
|
|
2
|
+
import { type RefObject } from 'react';
|
|
3
3
|
import { bindPopover, Paper, 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;
|
|
@@ -26,7 +26,7 @@ export const TextFieldPopover = ( props: Props ) => {
|
|
|
26
26
|
>
|
|
27
27
|
<Paper
|
|
28
28
|
sx={ {
|
|
29
|
-
width: anchorRef.current
|
|
29
|
+
width: anchorRef.current?.offsetWidth + 'px',
|
|
30
30
|
borderRadius: 2,
|
|
31
31
|
p: 1.5,
|
|
32
32
|
} }
|
|
@@ -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
|
@@ -12,6 +12,7 @@ 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';
|
|
15
16
|
import { PopoverContent } from '../../../components/popover-content';
|
|
16
17
|
import { Repeater } from '../../../components/repeater';
|
|
17
18
|
import { createControl } from '../../../create-control';
|
|
@@ -237,10 +238,14 @@ const ImageOverlayContent = () => {
|
|
|
237
238
|
<PropKeyProvider bind={ 'image' }>
|
|
238
239
|
<Grid container spacing={ 1 } alignItems="center">
|
|
239
240
|
<Grid item xs={ 12 }>
|
|
240
|
-
<
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
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>
|
|
244
249
|
</Grid>
|
|
245
250
|
</Grid>
|
|
246
251
|
</PropKeyProvider>
|
|
@@ -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';
|
|
@@ -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 ) {
|
|
@@ -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
|
+
};
|
|
@@ -15,11 +15,12 @@ export type FontCategory = {
|
|
|
15
15
|
|
|
16
16
|
type FontFamilyControlProps = {
|
|
17
17
|
fontFamilies: FontCategory[];
|
|
18
|
+
sectionWidth: number;
|
|
18
19
|
};
|
|
19
20
|
|
|
20
21
|
const SIZE = 'tiny';
|
|
21
22
|
|
|
22
|
-
export const FontFamilyControl = createControl( ( { fontFamilies }: FontFamilyControlProps ) => {
|
|
23
|
+
export const FontFamilyControl = createControl( ( { fontFamilies, sectionWidth }: FontFamilyControlProps ) => {
|
|
23
24
|
const { value: fontFamily, setValue: setFontFamily, disabled } = useBoundProp( stringPropTypeUtil );
|
|
24
25
|
|
|
25
26
|
const popoverState = usePopupState( { variant: 'popover' } );
|
|
@@ -39,7 +40,9 @@ export const FontFamilyControl = createControl( ( { fontFamilies }: FontFamilyCo
|
|
|
39
40
|
<Popover
|
|
40
41
|
disablePortal
|
|
41
42
|
disableScrollLock
|
|
42
|
-
anchorOrigin={ { vertical: 'bottom', horizontal: '
|
|
43
|
+
anchorOrigin={ { vertical: 'bottom', horizontal: 'right' } }
|
|
44
|
+
transformOrigin={ { vertical: 'top', horizontal: 'right' } }
|
|
45
|
+
sx={ { my: 1.5 } }
|
|
43
46
|
{ ...bindPopover( popoverState ) }
|
|
44
47
|
>
|
|
45
48
|
<FontFamilySelector
|
|
@@ -47,6 +50,7 @@ export const FontFamilyControl = createControl( ( { fontFamilies }: FontFamilyCo
|
|
|
47
50
|
fontFamily={ fontFamily }
|
|
48
51
|
onFontFamilyChange={ setFontFamily }
|
|
49
52
|
onClose={ popoverState.close }
|
|
53
|
+
sectionWidth={ sectionWidth }
|
|
50
54
|
/>
|
|
51
55
|
</Popover>
|
|
52
56
|
</>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import { type
|
|
2
|
+
import { type RefObject, useRef } from 'react';
|
|
3
3
|
import { layoutDirectionPropTypeUtil, type PropKey, sizePropTypeUtil } from '@elementor/editor-props';
|
|
4
4
|
import { DetachIcon, LinkIcon } from '@elementor/icons';
|
|
5
5
|
import { Grid, Stack, ToggleButton, Tooltip } from '@elementor/ui';
|
|
@@ -19,7 +19,7 @@ export const GapControl = createControl( ( { label }: { label: string } ) => {
|
|
|
19
19
|
disabled: directionDisabled,
|
|
20
20
|
} = useBoundProp( layoutDirectionPropTypeUtil );
|
|
21
21
|
|
|
22
|
-
const stackRef
|
|
22
|
+
const stackRef = useRef< HTMLDivElement >( null );
|
|
23
23
|
|
|
24
24
|
const { value: sizeValue, setValue: setSizeValue, disabled: sizeDisabled } = useBoundProp( sizePropTypeUtil );
|
|
25
25
|
|
|
@@ -96,7 +96,7 @@ const Control = ( {
|
|
|
96
96
|
}: {
|
|
97
97
|
bind: PropKey;
|
|
98
98
|
isLinked: boolean;
|
|
99
|
-
anchorRef:
|
|
99
|
+
anchorRef: RefObject< HTMLDivElement >;
|
|
100
100
|
} ) => {
|
|
101
101
|
if ( isLinked ) {
|
|
102
102
|
return <SizeControl anchorRef={ anchorRef } />;
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { imagePropTypeUtil } from '@elementor/editor-props';
|
|
3
|
-
import {
|
|
3
|
+
import { Stack } from '@elementor/ui';
|
|
4
4
|
import { type MediaType } from '@elementor/wp-media';
|
|
5
|
-
import { __ } from '@wordpress/i18n';
|
|
6
5
|
|
|
7
6
|
import { PropKeyProvider, PropProvider, useBoundProp } from '../bound-prop-context';
|
|
8
|
-
import { ControlFormLabel } from '../components/control-form-label';
|
|
9
7
|
import { createControl } from '../create-control';
|
|
10
8
|
import { useUnfilteredFilesUpload } from '../hooks/use-unfiltered-files-upload';
|
|
11
9
|
import { ImageMediaControl } from './image-media-control';
|
|
@@ -13,40 +11,29 @@ import { SelectControl } from './select-control';
|
|
|
13
11
|
|
|
14
12
|
type ImageControlProps = {
|
|
15
13
|
sizes: { label: string; value: string }[];
|
|
16
|
-
resolutionLabel?: string;
|
|
17
14
|
showMode?: 'all' | 'media' | 'sizes';
|
|
18
15
|
};
|
|
19
16
|
|
|
20
|
-
export const ImageControl = createControl(
|
|
21
|
-
|
|
22
|
-
const propContext = useBoundProp( imagePropTypeUtil );
|
|
17
|
+
export const ImageControl = createControl( ( { sizes, showMode = 'all' }: ImageControlProps ) => {
|
|
18
|
+
const propContext = useBoundProp( imagePropTypeUtil );
|
|
23
19
|
|
|
24
|
-
|
|
25
|
-
|
|
20
|
+
const { data: allowSvgUpload } = useUnfilteredFilesUpload();
|
|
21
|
+
const mediaTypes: MediaType[] = allowSvgUpload ? [ 'image', 'svg' ] : [ 'image' ];
|
|
26
22
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
{
|
|
37
|
-
<
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
</Grid>
|
|
45
|
-
</Grid>
|
|
46
|
-
</PropKeyProvider>
|
|
47
|
-
) : null }
|
|
48
|
-
</Stack>
|
|
49
|
-
</PropProvider>
|
|
50
|
-
);
|
|
51
|
-
}
|
|
52
|
-
);
|
|
23
|
+
return (
|
|
24
|
+
<PropProvider { ...propContext }>
|
|
25
|
+
<Stack gap={ 1.5 }>
|
|
26
|
+
{ [ 'all', 'media' ].includes( showMode ) ? (
|
|
27
|
+
<PropKeyProvider bind={ 'src' }>
|
|
28
|
+
<ImageMediaControl mediaTypes={ mediaTypes } />
|
|
29
|
+
</PropKeyProvider>
|
|
30
|
+
) : null }
|
|
31
|
+
{ [ 'all', 'sizes' ].includes( showMode ) ? (
|
|
32
|
+
<PropKeyProvider bind={ 'size' }>
|
|
33
|
+
<SelectControl options={ sizes } />
|
|
34
|
+
</PropKeyProvider>
|
|
35
|
+
) : null }
|
|
36
|
+
</Stack>
|
|
37
|
+
</PropProvider>
|
|
38
|
+
);
|
|
39
|
+
} );
|