@elementor/editor-controls 0.35.0 → 1.0.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 +24 -13
- package/dist/index.d.ts +24 -13
- package/dist/index.js +809 -558
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +748 -491
- package/dist/index.mjs.map +1 -1
- package/package.json +5 -4
- package/src/bound-prop-context/use-bound-prop.ts +4 -1
- package/src/components/control-form-label.tsx +3 -3
- package/src/components/control-label.tsx +1 -1
- package/src/components/font-family-selector.tsx +8 -10
- package/src/components/popover-grid-container.tsx +7 -10
- package/src/components/repeater.tsx +2 -4
- package/src/components/size-control/size-input.tsx +125 -0
- package/src/components/{text-field-inner-selection.tsx → size-control/text-field-inner-selection.tsx} +33 -16
- package/src/components/sortable.tsx +4 -2
- package/src/components/text-field-popover.tsx +47 -0
- package/src/controls/background-control/background-overlay/background-image-overlay/background-image-overlay-position.tsx +14 -5
- package/src/controls/background-control/background-overlay/background-image-overlay/background-image-overlay-size.tsx +9 -4
- package/src/controls/background-control/background-overlay/background-overlay-repeater-control.tsx +1 -1
- package/src/controls/box-shadow-repeater-control.tsx +11 -9
- package/src/controls/equal-unequal-sizes-control.tsx +38 -18
- package/src/controls/font-family-control/font-family-control.tsx +3 -1
- package/src/controls/gap-control.tsx +20 -7
- package/src/controls/image-control.tsx +2 -2
- package/src/controls/link-control.tsx +1 -1
- package/src/controls/linked-dimensions-control.tsx +71 -83
- package/src/controls/size-control.tsx +179 -149
- package/src/controls/stroke-control.tsx +9 -6
- package/src/hooks/use-size-extended-options.ts +21 -0
- package/src/index.ts +2 -1
- package/src/utils/size-control.ts +10 -0
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": "0.
|
|
4
|
+
"version": "1.0.0",
|
|
5
5
|
"private": false,
|
|
6
6
|
"author": "Elementor Team",
|
|
7
7
|
"homepage": "https://elementor.com/",
|
|
@@ -41,9 +41,10 @@
|
|
|
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-
|
|
44
|
+
"@elementor/editor-elements": "0.8.5",
|
|
45
|
+
"@elementor/editor-props": "0.13.0",
|
|
46
|
+
"@elementor/editor-responsive": "0.13.5",
|
|
47
|
+
"@elementor/editor-ui": "0.11.0",
|
|
47
48
|
"@elementor/editor-v1-adapters": "0.12.0",
|
|
48
49
|
"@elementor/env": "0.3.5",
|
|
49
50
|
"@elementor/http-client": "0.3.0",
|
|
@@ -22,7 +22,10 @@ type UseBoundProp< TValue extends PropValue > = {
|
|
|
22
22
|
disabled?: boolean;
|
|
23
23
|
};
|
|
24
24
|
|
|
25
|
-
export function useBoundProp< T extends PropValue = PropValue >(): PropKeyContextValue<
|
|
25
|
+
export function useBoundProp< T extends PropValue = PropValue, P extends PropType = PropType >(): PropKeyContextValue<
|
|
26
|
+
T,
|
|
27
|
+
P
|
|
28
|
+
>;
|
|
26
29
|
|
|
27
30
|
export function useBoundProp< TKey extends string, TValue extends PropValue >(
|
|
28
31
|
propTypeUtil: PropTypeUtil< TKey, TValue >
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import { FormLabel } from '@elementor/ui';
|
|
2
|
+
import { FormLabel, type FormLabelProps } from '@elementor/ui';
|
|
3
3
|
|
|
4
|
-
export const ControlFormLabel = (
|
|
5
|
-
return <FormLabel size="tiny"
|
|
4
|
+
export const ControlFormLabel = ( props: FormLabelProps ) => {
|
|
5
|
+
return <FormLabel size="tiny" { ...props } />;
|
|
6
6
|
};
|
|
@@ -7,7 +7,7 @@ import { ControlFormLabel } from './control-form-label';
|
|
|
7
7
|
|
|
8
8
|
export const ControlLabel = ( { children }: PropsWithChildren< object > ) => {
|
|
9
9
|
return (
|
|
10
|
-
<Stack direction="row" alignItems="center" justifyItems="start" gap={
|
|
10
|
+
<Stack direction="row" alignItems="center" justifyItems="start" gap={ 0.25 }>
|
|
11
11
|
<ControlFormLabel>{ children }</ControlFormLabel>
|
|
12
12
|
<ControlAdornments />
|
|
13
13
|
</Stack>
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import { useEffect, useRef, useState } from 'react';
|
|
2
2
|
import * as React from 'react';
|
|
3
|
-
import {
|
|
4
|
-
import { SearchIcon, TextIcon
|
|
3
|
+
import { PopoverHeader } from '@elementor/editor-ui';
|
|
4
|
+
import { SearchIcon, TextIcon } from '@elementor/icons';
|
|
5
5
|
import {
|
|
6
6
|
Box,
|
|
7
7
|
Divider,
|
|
8
|
-
IconButton,
|
|
9
8
|
InputAdornment,
|
|
10
9
|
Link,
|
|
11
10
|
MenuList,
|
|
@@ -20,6 +19,7 @@ import { useVirtualizer } from '@tanstack/react-virtual';
|
|
|
20
19
|
import { __ } from '@wordpress/i18n';
|
|
21
20
|
|
|
22
21
|
import { enqueueFont } from '../controls/font-family-control/enqueue-font';
|
|
22
|
+
import { type FontCategory } from '../controls/font-family-control/font-family-control';
|
|
23
23
|
import { type FontListItem, useFilteredFontFamilies } from '../hooks/use-filtered-font-families';
|
|
24
24
|
|
|
25
25
|
const SIZE = 'tiny';
|
|
@@ -52,13 +52,11 @@ export const FontFamilySelector = ( {
|
|
|
52
52
|
|
|
53
53
|
return (
|
|
54
54
|
<Stack>
|
|
55
|
-
<
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
</IconButton>
|
|
61
|
-
</Stack>
|
|
55
|
+
<PopoverHeader
|
|
56
|
+
title={ __( 'Font Family', 'elementor' ) }
|
|
57
|
+
onClose={ handleClose }
|
|
58
|
+
icon={ <TextIcon fontSize={ SIZE } /> }
|
|
59
|
+
/>
|
|
62
60
|
|
|
63
61
|
<Box px={ 1.5 } pb={ 1 }>
|
|
64
62
|
<TextField
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { forwardRef, type PropsWithChildren } from 'react';
|
|
2
2
|
import * as React from 'react';
|
|
3
3
|
import { Grid } from '@elementor/ui';
|
|
4
4
|
|
|
@@ -8,13 +8,10 @@ type PopoverGridContainerProps = PropsWithChildren< {
|
|
|
8
8
|
flexWrap?: React.ComponentProps< typeof Grid >[ 'flexWrap' ];
|
|
9
9
|
} >;
|
|
10
10
|
|
|
11
|
-
export const PopoverGridContainer
|
|
12
|
-
gap = 1.5,
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
<Grid container gap={ gap } alignItems={ alignItems } flexWrap={ flexWrap }>
|
|
18
|
-
{ children }
|
|
19
|
-
</Grid>
|
|
11
|
+
export const PopoverGridContainer = forwardRef(
|
|
12
|
+
( { gap = 1.5, alignItems = 'center', flexWrap = 'nowrap', children }: PopoverGridContainerProps, ref ) => (
|
|
13
|
+
<Grid container gap={ gap } alignItems={ alignItems } flexWrap={ flexWrap } ref={ ref }>
|
|
14
|
+
{ children }
|
|
15
|
+
</Grid>
|
|
16
|
+
)
|
|
20
17
|
);
|
|
@@ -143,8 +143,6 @@ export const Repeater = < T, >( {
|
|
|
143
143
|
} );
|
|
144
144
|
};
|
|
145
145
|
|
|
146
|
-
const ItemWrapper = disabled ? React.Fragment : SortableItem;
|
|
147
|
-
|
|
148
146
|
return (
|
|
149
147
|
<SectionContent>
|
|
150
148
|
<Stack
|
|
@@ -178,7 +176,7 @@ export const Repeater = < T, >( {
|
|
|
178
176
|
}
|
|
179
177
|
|
|
180
178
|
return (
|
|
181
|
-
<
|
|
179
|
+
<SortableItem id={ key } key={ `sortable-${ key }` } disabled={ disabled }>
|
|
182
180
|
<RepeaterItem
|
|
183
181
|
disabled={ disabled }
|
|
184
182
|
propDisabled={ value?.disabled }
|
|
@@ -202,7 +200,7 @@ export const Repeater = < T, >( {
|
|
|
202
200
|
<itemSettings.Content { ...props } value={ value } bind={ String( index ) } />
|
|
203
201
|
) }
|
|
204
202
|
</RepeaterItem>
|
|
205
|
-
</
|
|
203
|
+
</SortableItem>
|
|
206
204
|
);
|
|
207
205
|
} ) }
|
|
208
206
|
</SortableProvider>
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { useRef } from 'react';
|
|
3
|
+
import { PencilIcon } from '@elementor/icons';
|
|
4
|
+
import { Box, InputAdornment, type PopupState } from '@elementor/ui';
|
|
5
|
+
|
|
6
|
+
import ControlActions from '../../control-actions/control-actions';
|
|
7
|
+
import { type ExtendedOption, isUnitExtendedOption, type Unit } from '../../utils/size-control';
|
|
8
|
+
import { SelectionEndAdornment, TextFieldInnerSelection } from '../size-control/text-field-inner-selection';
|
|
9
|
+
|
|
10
|
+
type SizeInputProps = {
|
|
11
|
+
unit: Unit | ExtendedOption;
|
|
12
|
+
size: number | string;
|
|
13
|
+
placeholder?: string;
|
|
14
|
+
startIcon?: React.ReactNode;
|
|
15
|
+
units: ( Unit | ExtendedOption )[];
|
|
16
|
+
onBlur?: ( event: React.FocusEvent< HTMLInputElement > ) => void;
|
|
17
|
+
onFocus?: ( event: React.FocusEvent< HTMLInputElement > ) => void;
|
|
18
|
+
onClick?: ( event: React.MouseEvent< HTMLInputElement > ) => void;
|
|
19
|
+
handleUnitChange: ( unit: Unit | ExtendedOption ) => void;
|
|
20
|
+
handleSizeChange: ( event: React.ChangeEvent< HTMLInputElement > ) => void;
|
|
21
|
+
popupState: PopupState;
|
|
22
|
+
disabled?: boolean;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const RESTRICTED_INPUT_KEYS = [ 'e', 'E', '+', '-' ];
|
|
26
|
+
|
|
27
|
+
export const SizeInput = ( {
|
|
28
|
+
units,
|
|
29
|
+
handleUnitChange,
|
|
30
|
+
handleSizeChange,
|
|
31
|
+
placeholder,
|
|
32
|
+
startIcon,
|
|
33
|
+
onBlur,
|
|
34
|
+
onFocus,
|
|
35
|
+
onClick,
|
|
36
|
+
size,
|
|
37
|
+
unit,
|
|
38
|
+
popupState,
|
|
39
|
+
disabled,
|
|
40
|
+
}: SizeInputProps ) => {
|
|
41
|
+
const unitInputBufferRef = useRef( '' );
|
|
42
|
+
const inputType = isUnitExtendedOption( unit ) ? 'text' : 'number';
|
|
43
|
+
const inputValue = ! isUnitExtendedOption( unit ) && Number.isNaN( size ) ? '' : size ?? '';
|
|
44
|
+
|
|
45
|
+
const handleKeyUp = ( event: React.KeyboardEvent< HTMLInputElement > ) => {
|
|
46
|
+
const { key } = event;
|
|
47
|
+
|
|
48
|
+
if ( ! /^[a-zA-Z%]$/.test( key ) ) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
event.preventDefault();
|
|
53
|
+
|
|
54
|
+
const newChar = key.toLowerCase();
|
|
55
|
+
const updatedBuffer = ( unitInputBufferRef.current + newChar ).slice( -3 );
|
|
56
|
+
unitInputBufferRef.current = updatedBuffer;
|
|
57
|
+
|
|
58
|
+
const matchedUnit =
|
|
59
|
+
units.find( ( u ) => u.includes( updatedBuffer ) ) ||
|
|
60
|
+
units.find( ( u ) => u.startsWith( newChar ) ) ||
|
|
61
|
+
units.find( ( u ) => u.includes( newChar ) );
|
|
62
|
+
|
|
63
|
+
if ( matchedUnit ) {
|
|
64
|
+
handleUnitChange( matchedUnit );
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
const popupAttributes = {
|
|
69
|
+
'aria-controls': popupState.isOpen ? popupState.popupId : undefined,
|
|
70
|
+
'aria-haspopup': true,
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
const inputProps = {
|
|
74
|
+
...popupAttributes,
|
|
75
|
+
autoComplete: 'off',
|
|
76
|
+
onClick,
|
|
77
|
+
onFocus,
|
|
78
|
+
startAdornment: startIcon ? (
|
|
79
|
+
<InputAdornment position="start" disabled={ disabled }>
|
|
80
|
+
{ startIcon }
|
|
81
|
+
</InputAdornment>
|
|
82
|
+
) : undefined,
|
|
83
|
+
endAdornment: (
|
|
84
|
+
<SelectionEndAdornment
|
|
85
|
+
disabled={ disabled }
|
|
86
|
+
options={ units }
|
|
87
|
+
onClick={ handleUnitChange }
|
|
88
|
+
value={ unit }
|
|
89
|
+
alternativeOptionLabels={ {
|
|
90
|
+
custom: <PencilIcon fontSize="small" />,
|
|
91
|
+
} }
|
|
92
|
+
menuItemsAttributes={
|
|
93
|
+
units.includes( 'custom' )
|
|
94
|
+
? {
|
|
95
|
+
custom: popupAttributes,
|
|
96
|
+
}
|
|
97
|
+
: undefined
|
|
98
|
+
}
|
|
99
|
+
/>
|
|
100
|
+
),
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
return (
|
|
104
|
+
<ControlActions>
|
|
105
|
+
<Box>
|
|
106
|
+
<TextFieldInnerSelection
|
|
107
|
+
disabled={ disabled }
|
|
108
|
+
placeholder={ placeholder }
|
|
109
|
+
type={ inputType }
|
|
110
|
+
value={ inputValue }
|
|
111
|
+
onChange={ handleSizeChange }
|
|
112
|
+
onKeyDown={ ( event ) => {
|
|
113
|
+
if ( RESTRICTED_INPUT_KEYS.includes( event.key ) ) {
|
|
114
|
+
event.preventDefault();
|
|
115
|
+
}
|
|
116
|
+
} }
|
|
117
|
+
onKeyUp={ handleKeyUp }
|
|
118
|
+
onBlur={ onBlur }
|
|
119
|
+
shouldBlockInput={ isUnitExtendedOption( unit ) }
|
|
120
|
+
inputProps={ inputProps }
|
|
121
|
+
/>
|
|
122
|
+
</Box>
|
|
123
|
+
</ControlActions>
|
|
124
|
+
);
|
|
125
|
+
};
|
|
@@ -2,7 +2,16 @@ import * as React from 'react';
|
|
|
2
2
|
import { forwardRef, useId } from 'react';
|
|
3
3
|
import { type PropValue } from '@elementor/editor-props';
|
|
4
4
|
import { MenuListItem } from '@elementor/editor-ui';
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
bindMenu,
|
|
7
|
+
bindTrigger,
|
|
8
|
+
Button,
|
|
9
|
+
InputAdornment,
|
|
10
|
+
Menu,
|
|
11
|
+
TextField,
|
|
12
|
+
type TextFieldProps,
|
|
13
|
+
usePopupState,
|
|
14
|
+
} from '@elementor/ui';
|
|
6
15
|
|
|
7
16
|
type TextFieldInnerSelectionProps = {
|
|
8
17
|
placeholder?: string;
|
|
@@ -12,8 +21,10 @@ type TextFieldInnerSelectionProps = {
|
|
|
12
21
|
onBlur?: ( event: React.FocusEvent< HTMLInputElement > ) => void;
|
|
13
22
|
onKeyDown?: ( event: React.KeyboardEvent< HTMLInputElement > ) => void;
|
|
14
23
|
onKeyUp?: ( event: React.KeyboardEvent< HTMLInputElement > ) => void;
|
|
15
|
-
|
|
16
|
-
|
|
24
|
+
shouldBlockInput?: boolean;
|
|
25
|
+
inputProps: TextFieldProps[ 'InputProps' ] & {
|
|
26
|
+
endAdornment: React.JSX.Element;
|
|
27
|
+
};
|
|
17
28
|
disabled?: boolean;
|
|
18
29
|
};
|
|
19
30
|
|
|
@@ -27,8 +38,8 @@ export const TextFieldInnerSelection = forwardRef(
|
|
|
27
38
|
onBlur,
|
|
28
39
|
onKeyDown,
|
|
29
40
|
onKeyUp,
|
|
30
|
-
|
|
31
|
-
|
|
41
|
+
shouldBlockInput = false,
|
|
42
|
+
inputProps,
|
|
32
43
|
disabled,
|
|
33
44
|
}: TextFieldInnerSelectionProps,
|
|
34
45
|
ref
|
|
@@ -36,20 +47,18 @@ export const TextFieldInnerSelection = forwardRef(
|
|
|
36
47
|
return (
|
|
37
48
|
<TextField
|
|
38
49
|
ref={ ref }
|
|
50
|
+
sx={ { input: { cursor: shouldBlockInput ? 'default !important' : undefined } } }
|
|
39
51
|
size="tiny"
|
|
40
52
|
fullWidth
|
|
41
|
-
type={ type }
|
|
53
|
+
type={ shouldBlockInput ? undefined : type }
|
|
42
54
|
value={ value }
|
|
55
|
+
onChange={ shouldBlockInput ? undefined : onChange }
|
|
56
|
+
onKeyDown={ shouldBlockInput ? undefined : onKeyDown }
|
|
57
|
+
onKeyUp={ shouldBlockInput ? undefined : onKeyUp }
|
|
43
58
|
disabled={ disabled }
|
|
44
|
-
onChange={ onChange }
|
|
45
|
-
onKeyDown={ onKeyDown }
|
|
46
|
-
onKeyUp={ onKeyUp }
|
|
47
59
|
onBlur={ onBlur }
|
|
48
60
|
placeholder={ placeholder }
|
|
49
|
-
InputProps={
|
|
50
|
-
endAdornment,
|
|
51
|
-
startAdornment,
|
|
52
|
-
} }
|
|
61
|
+
InputProps={ inputProps }
|
|
53
62
|
/>
|
|
54
63
|
);
|
|
55
64
|
}
|
|
@@ -59,13 +68,17 @@ type SelectionEndAdornmentProps< T extends string > = {
|
|
|
59
68
|
options: T[];
|
|
60
69
|
onClick: ( value: T ) => void;
|
|
61
70
|
value: T;
|
|
71
|
+
alternativeOptionLabels?: { [ key in T ]?: React.ReactNode };
|
|
72
|
+
menuItemsAttributes?: { [ key in T ]?: Record< string, unknown > };
|
|
62
73
|
disabled?: boolean;
|
|
63
74
|
};
|
|
64
75
|
|
|
65
76
|
export const SelectionEndAdornment = < T extends string >( {
|
|
66
77
|
options,
|
|
78
|
+
alternativeOptionLabels = {} as Record< T, React.ReactNode >,
|
|
67
79
|
onClick,
|
|
68
80
|
value,
|
|
81
|
+
menuItemsAttributes = {},
|
|
69
82
|
disabled,
|
|
70
83
|
}: SelectionEndAdornmentProps< T > ) => {
|
|
71
84
|
const popupState = usePopupState( {
|
|
@@ -87,13 +100,17 @@ export const SelectionEndAdornment = < T extends string >( {
|
|
|
87
100
|
sx={ { font: 'inherit', minWidth: 'initial', textTransform: 'uppercase' } }
|
|
88
101
|
{ ...bindTrigger( popupState ) }
|
|
89
102
|
>
|
|
90
|
-
{ value }
|
|
103
|
+
{ alternativeOptionLabels[ value ] ?? value }
|
|
91
104
|
</Button>
|
|
92
105
|
|
|
93
106
|
<Menu MenuListProps={ { dense: true } } { ...bindMenu( popupState ) }>
|
|
94
107
|
{ options.map( ( option, index ) => (
|
|
95
|
-
<MenuListItem
|
|
96
|
-
{ option
|
|
108
|
+
<MenuListItem
|
|
109
|
+
key={ option }
|
|
110
|
+
onClick={ () => handleMenuItemClick( index ) }
|
|
111
|
+
{ ...menuItemsAttributes?.[ option ] }
|
|
112
|
+
>
|
|
113
|
+
{ alternativeOptionLabels[ option ] ?? option.toUpperCase() }
|
|
97
114
|
</MenuListItem>
|
|
98
115
|
) ) }
|
|
99
116
|
</Menu>
|
|
@@ -23,12 +23,14 @@ export const SortableProvider = < T extends number >( props: UnstableSortablePro
|
|
|
23
23
|
type SortableItemProps = {
|
|
24
24
|
id: UnstableSortableItemProps[ 'id' ];
|
|
25
25
|
children: React.ReactNode;
|
|
26
|
+
disabled?: boolean;
|
|
26
27
|
};
|
|
27
28
|
|
|
28
|
-
export const SortableItem = ( { id, children }: SortableItemProps ): React.ReactNode => {
|
|
29
|
+
export const SortableItem = ( { id, children, disabled }: SortableItemProps ): React.ReactNode => {
|
|
29
30
|
return (
|
|
30
31
|
<UnstableSortableItem
|
|
31
32
|
id={ id }
|
|
33
|
+
disabled={ disabled }
|
|
32
34
|
render={ ( {
|
|
33
35
|
itemProps,
|
|
34
36
|
triggerProps,
|
|
@@ -39,7 +41,7 @@ export const SortableItem = ( { id, children }: SortableItemProps ): React.React
|
|
|
39
41
|
}: UnstableSortableItemRenderProps ) => {
|
|
40
42
|
return (
|
|
41
43
|
<StyledListItem { ...itemProps } style={ itemStyle }>
|
|
42
|
-
<SortableTrigger { ...triggerProps } style={ triggerStyle } />
|
|
44
|
+
{ ! disabled && <SortableTrigger { ...triggerProps } style={ triggerStyle } /> }
|
|
43
45
|
{ children }
|
|
44
46
|
{ showDropIndication && <StyledDivider style={ dropIndicationStyle } /> }
|
|
45
47
|
</StyledListItem>
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { type MutableRefObject } from 'react';
|
|
3
|
+
import { bindPopover, Paper, Popover, type PopupState, TextField } from '@elementor/ui';
|
|
4
|
+
|
|
5
|
+
type Props = {
|
|
6
|
+
popupState: PopupState;
|
|
7
|
+
anchorRef: MutableRefObject< HTMLElement >;
|
|
8
|
+
restoreValue: () => void;
|
|
9
|
+
value: string;
|
|
10
|
+
onChange: ( event: React.ChangeEvent< HTMLInputElement > ) => void;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export const TextFieldPopover = ( props: Props ) => {
|
|
14
|
+
const { popupState, restoreValue, anchorRef, value, onChange } = props;
|
|
15
|
+
|
|
16
|
+
return (
|
|
17
|
+
<Popover
|
|
18
|
+
disablePortal
|
|
19
|
+
{ ...bindPopover( popupState ) }
|
|
20
|
+
anchorOrigin={ { vertical: 'bottom', horizontal: 'center' } }
|
|
21
|
+
transformOrigin={ { vertical: 'top', horizontal: 'center' } }
|
|
22
|
+
onClose={ () => {
|
|
23
|
+
restoreValue();
|
|
24
|
+
popupState.close();
|
|
25
|
+
} }
|
|
26
|
+
>
|
|
27
|
+
<Paper
|
|
28
|
+
sx={ {
|
|
29
|
+
width: anchorRef.current.offsetWidth + 'px',
|
|
30
|
+
borderRadius: 2,
|
|
31
|
+
p: 1.5,
|
|
32
|
+
} }
|
|
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
|
+
</Popover>
|
|
46
|
+
);
|
|
47
|
+
};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
+
import { type MutableRefObject, useRef } from 'react';
|
|
2
3
|
import { backgroundImagePositionOffsetPropTypeUtil, stringPropTypeUtil } from '@elementor/editor-props';
|
|
3
4
|
import { MenuListItem } from '@elementor/editor-ui';
|
|
4
5
|
import { LetterXIcon, LetterYIcon } from '@elementor/icons';
|
|
@@ -40,6 +41,7 @@ export const BackgroundImageOverlayPosition = () => {
|
|
|
40
41
|
const stringPropContext = useBoundProp( stringPropTypeUtil );
|
|
41
42
|
|
|
42
43
|
const isCustom = !! backgroundImageOffsetContext.value;
|
|
44
|
+
const rowRef: MutableRefObject< HTMLElement | undefined > = useRef();
|
|
43
45
|
|
|
44
46
|
const handlePositionChange = ( event: SelectChangeEvent< Positions > ) => {
|
|
45
47
|
const value = event.target.value || null;
|
|
@@ -60,10 +62,11 @@ export const BackgroundImageOverlayPosition = () => {
|
|
|
60
62
|
</Grid>
|
|
61
63
|
<Grid item xs={ 6 } sx={ { display: 'flex', justifyContent: 'flex-end', overflow: 'hidden' } }>
|
|
62
64
|
<Select
|
|
65
|
+
fullWidth
|
|
63
66
|
size="tiny"
|
|
64
|
-
value={ ( backgroundImageOffsetContext.value ? 'custom' : stringPropContext.value ) ?? '' }
|
|
65
67
|
onChange={ handlePositionChange }
|
|
66
|
-
|
|
68
|
+
disabled={ stringPropContext.disabled }
|
|
69
|
+
value={ ( backgroundImageOffsetContext.value ? 'custom' : stringPropContext.value ) ?? '' }
|
|
67
70
|
>
|
|
68
71
|
{ backgroundPositionOptions.map( ( { label, value } ) => (
|
|
69
72
|
<MenuListItem key={ value } value={ value ?? '' }>
|
|
@@ -77,15 +80,21 @@ export const BackgroundImageOverlayPosition = () => {
|
|
|
77
80
|
{ isCustom ? (
|
|
78
81
|
<PropProvider { ...backgroundImageOffsetContext }>
|
|
79
82
|
<Grid item xs={ 12 }>
|
|
80
|
-
<Grid container spacing={ 1.5 }>
|
|
83
|
+
<Grid container spacing={ 1.5 } ref={ rowRef }>
|
|
81
84
|
<Grid item xs={ 6 }>
|
|
82
85
|
<PropKeyProvider bind={ 'x' }>
|
|
83
|
-
<SizeControl
|
|
86
|
+
<SizeControl
|
|
87
|
+
startIcon={ <LetterXIcon fontSize={ 'tiny' } /> }
|
|
88
|
+
anchorRef={ rowRef }
|
|
89
|
+
/>
|
|
84
90
|
</PropKeyProvider>
|
|
85
91
|
</Grid>
|
|
86
92
|
<Grid item xs={ 6 }>
|
|
87
93
|
<PropKeyProvider bind={ 'y' }>
|
|
88
|
-
<SizeControl
|
|
94
|
+
<SizeControl
|
|
95
|
+
startIcon={ <LetterYIcon fontSize={ 'tiny' } /> }
|
|
96
|
+
anchorRef={ rowRef }
|
|
97
|
+
/>
|
|
89
98
|
</PropKeyProvider>
|
|
90
99
|
</Grid>
|
|
91
100
|
</Grid>
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
+
import { type MutableRefObject, useRef } from 'react';
|
|
2
3
|
import { backgroundImageSizeScalePropTypeUtil, stringPropTypeUtil } from '@elementor/editor-props';
|
|
3
4
|
import {
|
|
4
5
|
ArrowBarBothIcon,
|
|
@@ -54,6 +55,7 @@ export const BackgroundImageOverlaySize = () => {
|
|
|
54
55
|
const stringPropContext = useBoundProp( stringPropTypeUtil );
|
|
55
56
|
|
|
56
57
|
const isCustom = !! backgroundImageScaleContext.value;
|
|
58
|
+
const rowRef: MutableRefObject< HTMLElement | undefined > = useRef();
|
|
57
59
|
|
|
58
60
|
const handleSizeChange = ( size: Sizes | null ) => {
|
|
59
61
|
if ( size === 'custom' ) {
|
|
@@ -74,23 +76,25 @@ export const BackgroundImageOverlaySize = () => {
|
|
|
74
76
|
<ControlToggleButtonGroup
|
|
75
77
|
exclusive
|
|
76
78
|
items={ sizeControlOptions }
|
|
79
|
+
onChange={ handleSizeChange }
|
|
80
|
+
disabled={ stringPropContext.disabled }
|
|
77
81
|
value={
|
|
78
82
|
( backgroundImageScaleContext.value ? 'custom' : stringPropContext.value ) as Sizes
|
|
79
83
|
}
|
|
80
|
-
onChange={ handleSizeChange }
|
|
81
84
|
/>
|
|
82
85
|
</Grid>
|
|
83
86
|
</PopoverGridContainer>
|
|
84
87
|
</Grid>
|
|
85
88
|
{ isCustom ? (
|
|
86
89
|
<PropProvider { ...backgroundImageScaleContext }>
|
|
87
|
-
<Grid item xs={ 12 }>
|
|
90
|
+
<Grid item xs={ 12 } ref={ rowRef }>
|
|
88
91
|
<PopoverGridContainer>
|
|
89
92
|
<Grid item xs={ 6 }>
|
|
90
93
|
<PropKeyProvider bind={ 'width' }>
|
|
91
94
|
<SizeControl
|
|
92
95
|
startIcon={ <ArrowsMoveHorizontalIcon fontSize={ 'tiny' } /> }
|
|
93
|
-
|
|
96
|
+
extendedOptions={ [ 'auto' ] }
|
|
97
|
+
anchorRef={ rowRef }
|
|
94
98
|
/>
|
|
95
99
|
</PropKeyProvider>
|
|
96
100
|
</Grid>
|
|
@@ -98,7 +102,8 @@ export const BackgroundImageOverlaySize = () => {
|
|
|
98
102
|
<PropKeyProvider bind={ 'height' }>
|
|
99
103
|
<SizeControl
|
|
100
104
|
startIcon={ <ArrowsMoveVerticalIcon fontSize={ 'tiny' } /> }
|
|
101
|
-
|
|
105
|
+
extendedOptions={ [ 'auto' ] }
|
|
106
|
+
anchorRef={ rowRef }
|
|
102
107
|
/>
|
|
103
108
|
</PropKeyProvider>
|
|
104
109
|
</Grid>
|
package/src/controls/background-control/background-overlay/background-overlay-repeater-control.tsx
CHANGED
|
@@ -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 } disabled={ disabled }>
|
|
78
78
|
<Repeater
|
|
79
79
|
openOnAdd
|
|
80
80
|
disabled={ disabled }
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
+
import { type MutableRefObject, useRef } from 'react';
|
|
2
3
|
import { boxShadowPropTypeUtil, type PropKey, shadowPropTypeUtil, type ShadowPropValue } from '@elementor/editor-props';
|
|
3
4
|
import { FormLabel, Grid, type SxProps, type Theme, UnstableColorIndicator } from '@elementor/ui';
|
|
4
5
|
import { __ } from '@wordpress/i18n';
|
|
@@ -16,7 +17,7 @@ export const BoxShadowRepeaterControl = createControl( () => {
|
|
|
16
17
|
const { propType, value, setValue, disabled } = useBoundProp( boxShadowPropTypeUtil );
|
|
17
18
|
|
|
18
19
|
return (
|
|
19
|
-
<PropProvider propType={ propType } value={ value } setValue={ setValue }>
|
|
20
|
+
<PropProvider propType={ propType } value={ value } setValue={ setValue } disabled={ disabled }>
|
|
20
21
|
<Repeater
|
|
21
22
|
openOnAdd
|
|
22
23
|
disabled={ disabled }
|
|
@@ -47,10 +48,11 @@ const ItemContent = ( { anchorEl, bind }: { anchorEl: HTMLElement | null; bind:
|
|
|
47
48
|
};
|
|
48
49
|
|
|
49
50
|
const Content = ( { anchorEl }: { anchorEl: HTMLElement | null } ) => {
|
|
50
|
-
const
|
|
51
|
+
const context = useBoundProp( shadowPropTypeUtil );
|
|
52
|
+
const rowRef: MutableRefObject< HTMLElement | undefined >[] = [ useRef(), useRef() ];
|
|
51
53
|
|
|
52
54
|
return (
|
|
53
|
-
<PropProvider
|
|
55
|
+
<PropProvider { ...context }>
|
|
54
56
|
<PopoverContent p={ 1.5 }>
|
|
55
57
|
<PopoverGridContainer>
|
|
56
58
|
<Control bind="color" label={ __( 'Color', 'elementor' ) }>
|
|
@@ -65,20 +67,20 @@ const Content = ( { anchorEl }: { anchorEl: HTMLElement | null } ) => {
|
|
|
65
67
|
/>
|
|
66
68
|
</Control>
|
|
67
69
|
</PopoverGridContainer>
|
|
68
|
-
<PopoverGridContainer>
|
|
70
|
+
<PopoverGridContainer ref={ rowRef[ 0 ] }>
|
|
69
71
|
<Control bind="hOffset" label={ __( 'Horizontal', 'elementor' ) }>
|
|
70
|
-
<SizeControl />
|
|
72
|
+
<SizeControl anchorRef={ rowRef[ 0 ] } />
|
|
71
73
|
</Control>
|
|
72
74
|
<Control bind="vOffset" label={ __( 'Vertical', 'elementor' ) }>
|
|
73
|
-
<SizeControl />
|
|
75
|
+
<SizeControl anchorRef={ rowRef[ 0 ] } />
|
|
74
76
|
</Control>
|
|
75
77
|
</PopoverGridContainer>
|
|
76
|
-
<PopoverGridContainer>
|
|
78
|
+
<PopoverGridContainer ref={ rowRef[ 1 ] }>
|
|
77
79
|
<Control bind="blur" label={ __( 'Blur', 'elementor' ) }>
|
|
78
|
-
<SizeControl />
|
|
80
|
+
<SizeControl anchorRef={ rowRef[ 1 ] } />
|
|
79
81
|
</Control>
|
|
80
82
|
<Control bind="spread" label={ __( 'Spread', 'elementor' ) }>
|
|
81
|
-
<SizeControl />
|
|
83
|
+
<SizeControl anchorRef={ rowRef[ 1 ] } />
|
|
82
84
|
</Control>
|
|
83
85
|
</PopoverGridContainer>
|
|
84
86
|
</PopoverContent>
|