@elementor/editor-controls 0.1.0 → 0.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 +22 -0
- package/dist/index.d.mts +61 -32
- package/dist/index.d.ts +61 -32
- package/dist/index.js +299 -225
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +304 -226
- package/dist/index.mjs.map +1 -1
- package/package.json +6 -6
- package/src/bound-prop-context.tsx +47 -10
- package/src/components/control-toggle-button-group.tsx +14 -3
- package/src/controls/background-overlay-repeater-control.tsx +3 -7
- package/src/controls/box-shadow-repeater-control.tsx +9 -9
- package/src/controls/color-control.tsx +4 -13
- package/src/controls/equal-unequal-sizes-control.tsx +100 -100
- package/src/controls/font-family-control.tsx +2 -1
- package/src/controls/image-control.tsx +7 -18
- package/src/controls/image-media-control.tsx +7 -10
- package/src/controls/link-control.tsx +90 -0
- package/src/controls/linked-dimensions-control.tsx +5 -11
- package/src/controls/number-control.tsx +48 -23
- package/src/controls/select-control.tsx +7 -7
- package/src/controls/size-control.tsx +10 -19
- package/src/controls/stroke-control.tsx +17 -45
- package/src/controls/text-area-control.tsx +2 -1
- package/src/controls/text-control.tsx +2 -1
- package/src/controls/toggle-control.tsx +5 -5
- package/src/controls/url-control.tsx +29 -0
- package/src/hooks/use-sync-external-state.tsx +8 -8
- package/src/index.ts +3 -0
|
@@ -1,30 +1,67 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { createContext, useContext } from 'react';
|
|
3
|
-
import { type PropKey, type PropValue } from '@elementor/editor-props';
|
|
3
|
+
import { type CreateOptions, type PropKey, type PropTypeUtil, type PropValue } from '@elementor/editor-props';
|
|
4
4
|
|
|
5
|
+
// Context
|
|
5
6
|
export type BoundPropContext< T extends PropValue > = {
|
|
6
7
|
bind: PropKey;
|
|
7
|
-
setValue: ( value: T |
|
|
8
|
-
value: T
|
|
8
|
+
setValue: ( value: T | null ) => void;
|
|
9
|
+
value: T;
|
|
9
10
|
};
|
|
10
11
|
|
|
12
|
+
const BoundPropContext = createContext< BoundPropContext< PropValue > | null >( null );
|
|
13
|
+
|
|
14
|
+
// Provider
|
|
11
15
|
export type BoundPropProviderProps< T extends PropValue > = BoundPropContext< T > & {
|
|
12
16
|
children: React.ReactNode;
|
|
17
|
+
setValue: ( value: T | null ) => void;
|
|
13
18
|
};
|
|
14
19
|
|
|
15
|
-
const BoundPropContext = createContext< BoundPropContext< PropValue > | null >( null );
|
|
16
20
|
export const BoundPropProvider = ( { children, value, setValue, bind }: BoundPropProviderProps< PropValue > ) => {
|
|
17
21
|
return <BoundPropContext.Provider value={ { value, setValue, bind } }>{ children }</BoundPropContext.Provider>;
|
|
18
22
|
};
|
|
19
23
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
+
// Hook
|
|
25
|
+
type SetValue< T > = ( value: T | null, options?: CreateOptions ) => void;
|
|
26
|
+
|
|
27
|
+
type UseBoundProp< TValue > = {
|
|
28
|
+
bind: PropKey;
|
|
29
|
+
setValue: SetValue< TValue >;
|
|
30
|
+
value: TValue;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export function useBoundProp< TValue extends PropValue >(): BoundPropContext< TValue >;
|
|
34
|
+
|
|
35
|
+
export function useBoundProp< TKey extends string, TValue extends PropValue >(
|
|
36
|
+
propTypeUtil: PropTypeUtil< TKey, TValue >
|
|
37
|
+
): UseBoundProp< TValue >;
|
|
38
|
+
|
|
39
|
+
export function useBoundProp< TKey extends string, TValue extends PropValue >(
|
|
40
|
+
propTypeUtil?: PropTypeUtil< TKey, TValue >
|
|
41
|
+
) {
|
|
42
|
+
const boundPropContext = useContext< BoundPropContext< TValue > >( BoundPropContext as never );
|
|
24
43
|
|
|
25
44
|
if ( ! boundPropContext ) {
|
|
26
|
-
throw new Error( 'useBoundProp must be used within a
|
|
45
|
+
throw new Error( 'useBoundProp must be used within a BoundPropProvider' );
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if ( ! propTypeUtil ) {
|
|
49
|
+
return boundPropContext;
|
|
27
50
|
}
|
|
28
51
|
|
|
29
|
-
|
|
52
|
+
function setValue( value: TValue | null, options?: CreateOptions ) {
|
|
53
|
+
if ( value === null ) {
|
|
54
|
+
return boundPropContext.setValue( null );
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return boundPropContext.setValue( propTypeUtil?.create( value, options ) as TValue );
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const value = propTypeUtil.extract( boundPropContext.value );
|
|
61
|
+
|
|
62
|
+
return {
|
|
63
|
+
...boundPropContext,
|
|
64
|
+
setValue,
|
|
65
|
+
value,
|
|
66
|
+
};
|
|
30
67
|
}
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
ToggleButtonGroup,
|
|
7
7
|
type ToggleButtonProps,
|
|
8
8
|
Tooltip,
|
|
9
|
+
useTheme,
|
|
9
10
|
} from '@elementor/ui';
|
|
10
11
|
|
|
11
12
|
type RenderContentProps = { size: ToggleButtonProps[ 'size' ] };
|
|
@@ -21,13 +22,13 @@ const StyledToggleButtonGroup = styled( ToggleButtonGroup )`
|
|
|
21
22
|
${ ( { justify } ) => `justify-content: ${ justify };` }
|
|
22
23
|
`;
|
|
23
24
|
|
|
24
|
-
type ExclusiveValue< TValue > = TValue
|
|
25
|
+
type ExclusiveValue< TValue > = TValue;
|
|
25
26
|
type NonExclusiveValue< TValue > = TValue[];
|
|
26
27
|
|
|
27
28
|
type Props< TValue > = {
|
|
28
29
|
justify?: StackProps[ 'justifyContent' ];
|
|
29
30
|
size?: ToggleButtonProps[ 'size' ];
|
|
30
|
-
items: ToggleButtonGroupItem< TValue >[];
|
|
31
|
+
items: ToggleButtonGroupItem< TValue | null >[];
|
|
31
32
|
fullWidth?: boolean;
|
|
32
33
|
} & (
|
|
33
34
|
| {
|
|
@@ -51,6 +52,8 @@ export const ControlToggleButtonGroup = < TValue, >( {
|
|
|
51
52
|
exclusive = false,
|
|
52
53
|
fullWidth = false,
|
|
53
54
|
}: Props< TValue > ) => {
|
|
55
|
+
const isRtl = 'rtl' === useTheme().direction;
|
|
56
|
+
|
|
54
57
|
const handleChange = (
|
|
55
58
|
_: React.MouseEvent< HTMLElement >,
|
|
56
59
|
newValue: typeof exclusive extends true ? ExclusiveValue< TValue > : NonExclusiveValue< TValue >
|
|
@@ -59,7 +62,15 @@ export const ControlToggleButtonGroup = < TValue, >( {
|
|
|
59
62
|
};
|
|
60
63
|
|
|
61
64
|
return (
|
|
62
|
-
<StyledToggleButtonGroup
|
|
65
|
+
<StyledToggleButtonGroup
|
|
66
|
+
justify={ justify }
|
|
67
|
+
value={ value }
|
|
68
|
+
onChange={ handleChange }
|
|
69
|
+
exclusive={ exclusive }
|
|
70
|
+
sx={ {
|
|
71
|
+
direction: isRtl ? 'rtl /* @noflip */' : 'ltr /* @noflip */',
|
|
72
|
+
} }
|
|
73
|
+
>
|
|
63
74
|
{ items.map( ( { label, value: buttonValue, renderContent: Content, showTooltip } ) =>
|
|
64
75
|
showTooltip ? (
|
|
65
76
|
<Tooltip key={ buttonValue } title={ label } disableFocusListener={ true } placement="top">
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import {
|
|
3
|
+
backgroundImagePropTypeUtil,
|
|
3
4
|
type backgroundImageTypePropValue,
|
|
4
5
|
type ColorGradientPropValue,
|
|
5
6
|
type PropValue,
|
|
@@ -15,15 +16,10 @@ import { ColorControl } from './color-control';
|
|
|
15
16
|
type SetContextValue = ( v: PropValue ) => void;
|
|
16
17
|
|
|
17
18
|
export const BackgroundOverlayRepeaterControl = createControl( () => {
|
|
18
|
-
const { value, setValue } = useBoundProp
|
|
19
|
-
|
|
20
|
-
const colorOverlayValues = value?.value;
|
|
19
|
+
const { value: colorOverlayValues, setValue } = useBoundProp( backgroundImagePropTypeUtil );
|
|
21
20
|
|
|
22
21
|
const setColorOverlay = ( newValue: backgroundImageTypePropValue[ 'value' ] ) => {
|
|
23
|
-
setValue(
|
|
24
|
-
$$type: 'background-image',
|
|
25
|
-
value: newValue,
|
|
26
|
-
} );
|
|
22
|
+
setValue( newValue );
|
|
27
23
|
};
|
|
28
24
|
|
|
29
25
|
return (
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
boxShadowPropTypeUtil,
|
|
4
|
+
type BoxShadowPropValue,
|
|
5
|
+
type PropValue,
|
|
6
|
+
type ShadowPropValue,
|
|
7
|
+
} from '@elementor/editor-props';
|
|
3
8
|
import { Grid, Stack, Typography, UnstableColorIndicator } from '@elementor/ui';
|
|
4
9
|
import { __ } from '@wordpress/i18n';
|
|
5
10
|
|
|
@@ -13,20 +18,15 @@ import { SizeControl } from './size-control';
|
|
|
13
18
|
type SetContextValue = ( v: PropValue ) => void;
|
|
14
19
|
|
|
15
20
|
export const BoxShadowRepeaterControl = createControl( () => {
|
|
16
|
-
const { value, setValue } = useBoundProp
|
|
17
|
-
|
|
18
|
-
const boxShadowValues = value?.value;
|
|
21
|
+
const { value: boxShadowValues, setValue } = useBoundProp( boxShadowPropTypeUtil );
|
|
19
22
|
|
|
20
23
|
const setBoxShadow = ( newValue: BoxShadowPropValue[ 'value' ] ) => {
|
|
21
|
-
setValue(
|
|
22
|
-
$$type: 'box-shadow',
|
|
23
|
-
value: newValue,
|
|
24
|
-
} );
|
|
24
|
+
setValue( newValue );
|
|
25
25
|
};
|
|
26
26
|
|
|
27
27
|
return (
|
|
28
28
|
<Repeater
|
|
29
|
-
values={ boxShadowValues }
|
|
29
|
+
values={ boxShadowValues ?? [] }
|
|
30
30
|
setValues={ setBoxShadow }
|
|
31
31
|
label={ __( 'Box shadow', 'elementor' ) }
|
|
32
32
|
itemSettings={ {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import { colorPropTypeUtil } from '@elementor/editor-props';
|
|
3
3
|
import { UnstableColorField, type UnstableColorFieldProps } from '@elementor/ui';
|
|
4
4
|
|
|
5
5
|
import { useBoundProp } from '../bound-prop-context';
|
|
@@ -8,24 +8,15 @@ import { createControl } from '../create-control';
|
|
|
8
8
|
|
|
9
9
|
export const ColorControl = createControl(
|
|
10
10
|
( props: Partial< Omit< UnstableColorFieldProps, 'value' | 'onChange' > > ) => {
|
|
11
|
-
const { value, setValue } = useBoundProp
|
|
11
|
+
const { value, setValue } = useBoundProp( colorPropTypeUtil );
|
|
12
12
|
|
|
13
13
|
const handleChange = ( selectedColor: string ) => {
|
|
14
|
-
setValue(
|
|
15
|
-
$$type: 'color',
|
|
16
|
-
value: selectedColor,
|
|
17
|
-
} );
|
|
14
|
+
setValue( selectedColor );
|
|
18
15
|
};
|
|
19
16
|
|
|
20
17
|
return (
|
|
21
18
|
<ControlActions>
|
|
22
|
-
<UnstableColorField
|
|
23
|
-
size="tiny"
|
|
24
|
-
{ ...props }
|
|
25
|
-
value={ value?.value }
|
|
26
|
-
onChange={ handleChange }
|
|
27
|
-
fullWidth
|
|
28
|
-
/>
|
|
19
|
+
<UnstableColorField size="tiny" { ...props } value={ value } onChange={ handleChange } fullWidth />
|
|
29
20
|
</ControlActions>
|
|
30
21
|
);
|
|
31
22
|
}
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { type ReactNode, useId, useRef } from 'react';
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
type PropKey,
|
|
5
|
+
type PropTypeUtil,
|
|
6
|
+
type PropValue,
|
|
7
|
+
sizePropTypeUtil,
|
|
8
|
+
type SizePropValue,
|
|
9
|
+
} from '@elementor/editor-props';
|
|
4
10
|
import { bindPopover, bindToggle, Grid, Popover, Stack, ToggleButton, usePopupState } from '@elementor/ui';
|
|
5
11
|
import { __ } from '@wordpress/i18n';
|
|
6
12
|
|
|
@@ -8,95 +14,69 @@ import { BoundPropProvider, useBoundProp } from '../bound-prop-context';
|
|
|
8
14
|
import { ControlLabel } from '../components/control-label';
|
|
9
15
|
import { SizeControl } from './size-control';
|
|
10
16
|
|
|
11
|
-
type
|
|
12
|
-
TMultiPropType,
|
|
13
|
-
Record< string, SizePropValue >
|
|
14
|
-
>;
|
|
17
|
+
type SetContextValue = ( v: PropValue ) => void;
|
|
15
18
|
|
|
16
|
-
type
|
|
19
|
+
type MultiSizePropValue = Record< PropKey, SizePropValue >;
|
|
20
|
+
|
|
21
|
+
type Item = {
|
|
17
22
|
icon: ReactNode;
|
|
18
23
|
label: string;
|
|
19
|
-
bind:
|
|
24
|
+
bind: PropKey;
|
|
20
25
|
};
|
|
21
26
|
|
|
22
|
-
export type EqualUnequalItems
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
> = [
|
|
26
|
-
Item< TMultiPropType, TPropValue >,
|
|
27
|
-
Item< TMultiPropType, TPropValue >,
|
|
28
|
-
Item< TMultiPropType, TPropValue >,
|
|
29
|
-
Item< TMultiPropType, TPropValue >,
|
|
30
|
-
];
|
|
31
|
-
|
|
32
|
-
type Props< TMultiPropType extends string, TPropValue extends MultiSizePropValue< TMultiPropType > > = {
|
|
27
|
+
export type EqualUnequalItems = [ Item, Item, Item, Item ];
|
|
28
|
+
|
|
29
|
+
type Props< TMultiPropType extends string, TPropValue extends MultiSizePropValue > = {
|
|
33
30
|
label: string;
|
|
34
31
|
icon: ReactNode;
|
|
35
|
-
items: EqualUnequalItems
|
|
36
|
-
|
|
32
|
+
items: EqualUnequalItems;
|
|
33
|
+
multiSizePropTypeUtil: PropTypeUtil< TMultiPropType, TPropValue >;
|
|
37
34
|
};
|
|
38
35
|
|
|
39
|
-
|
|
36
|
+
const isEqualSizes = ( values: SizePropValue[], items: EqualUnequalItems ) => {
|
|
37
|
+
if ( values.length !== items.length ) {
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
|
|
40
41
|
const [ firstValue, ...restValues ] = values;
|
|
41
42
|
|
|
42
|
-
return restValues.
|
|
43
|
-
( value ) => value
|
|
43
|
+
return restValues.every(
|
|
44
|
+
( value ) => value.value?.size === firstValue.value?.size && value.value?.unit === firstValue.value?.unit
|
|
44
45
|
);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
function getMultiSizeProps< TMultiPropType extends string, TPropValue extends MultiSizePropValue< TMultiPropType > >(
|
|
48
|
-
controlValue: TPropValue | SizePropValue | undefined,
|
|
49
|
-
items: Item< TMultiPropType, TPropValue >[]
|
|
50
|
-
) {
|
|
51
|
-
return controlValue?.$$type === 'size'
|
|
52
|
-
? items.reduce( ( values: TPropValue[ 'value' ], item ) => {
|
|
53
|
-
const { bind } = item;
|
|
54
|
-
values[ bind ] = controlValue as TPropValue[ 'value' ][ keyof TPropValue[ 'value' ] ];
|
|
55
|
-
|
|
56
|
-
return values;
|
|
57
|
-
}, {} )
|
|
58
|
-
: ( ( controlValue?.value ?? {} ) as TPropValue[ 'value' ] );
|
|
59
|
-
}
|
|
46
|
+
};
|
|
60
47
|
|
|
61
|
-
export function EqualUnequalSizesControl<
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
48
|
+
export function EqualUnequalSizesControl< TMultiPropType extends string, TPropValue extends MultiSizePropValue >( {
|
|
49
|
+
label,
|
|
50
|
+
icon,
|
|
51
|
+
items,
|
|
52
|
+
multiSizePropTypeUtil,
|
|
53
|
+
}: Props< TMultiPropType, TPropValue > ) {
|
|
65
54
|
const popupId = useId();
|
|
66
55
|
const controlRef = useRef< HTMLElement >( null );
|
|
67
|
-
const {
|
|
68
|
-
|
|
69
|
-
const setMultiSizeValue = ( newValue: TPropValue[ 'value' ] ) => {
|
|
70
|
-
setControlValue( { $$type: multiSizeType, value: newValue } as TPropValue );
|
|
71
|
-
};
|
|
56
|
+
const popupState = usePopupState( { variant: 'popover', popupId } );
|
|
72
57
|
|
|
73
|
-
const
|
|
58
|
+
const { value: sizeValue, setValue: setSizeValue } = useBoundProp( sizePropTypeUtil );
|
|
59
|
+
const { value: multiSizeValue, setValue: setMultiSizeValue } = useBoundProp( multiSizePropTypeUtil );
|
|
74
60
|
|
|
75
|
-
const
|
|
76
|
-
|
|
61
|
+
const splitEqualValue = () => {
|
|
62
|
+
return items.reduce( ( acc, item ) => ( { ...acc, [ item.bind ]: sizePropTypeUtil.create( sizeValue ) } ), {} );
|
|
63
|
+
};
|
|
77
64
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
65
|
+
const setNestedProp = ( item: Item, newValue: SizePropValue ) => {
|
|
66
|
+
const newMappedValues = {
|
|
67
|
+
...( multiSizeValue ?? splitEqualValue() ),
|
|
68
|
+
[ item.bind ]: newValue,
|
|
81
69
|
};
|
|
82
70
|
|
|
83
|
-
const
|
|
84
|
-
const isMixed = hasMixedSizes( sizes );
|
|
85
|
-
|
|
86
|
-
if ( isMixed ) {
|
|
87
|
-
setMultiSizeValue( newMappedValues );
|
|
71
|
+
const isEqual = isEqualSizes( Object.values( newMappedValues ), items );
|
|
88
72
|
|
|
89
|
-
|
|
73
|
+
if ( isEqual ) {
|
|
74
|
+
return setSizeValue( newValue?.value );
|
|
90
75
|
}
|
|
91
76
|
|
|
92
|
-
|
|
77
|
+
setMultiSizeValue( newMappedValues );
|
|
93
78
|
};
|
|
94
79
|
|
|
95
|
-
const popupState = usePopupState( {
|
|
96
|
-
variant: 'popover',
|
|
97
|
-
popupId,
|
|
98
|
-
} );
|
|
99
|
-
|
|
100
80
|
return (
|
|
101
81
|
<>
|
|
102
82
|
<Grid container gap={ 2 } alignItems="center" flexWrap="nowrap" ref={ controlRef }>
|
|
@@ -104,9 +84,11 @@ export function EqualUnequalSizesControl<
|
|
|
104
84
|
<ControlLabel>{ label }</ControlLabel>
|
|
105
85
|
</Grid>
|
|
106
86
|
<Grid item xs={ 6 }>
|
|
107
|
-
<
|
|
108
|
-
|
|
109
|
-
|
|
87
|
+
<EqualSizeControl
|
|
88
|
+
items={ items }
|
|
89
|
+
value={ sizeValue }
|
|
90
|
+
multiSizeValue={ multiSizeValue }
|
|
91
|
+
setValue={ setSizeValue }
|
|
110
92
|
iconButton={
|
|
111
93
|
<ToggleButton
|
|
112
94
|
size={ 'tiny' }
|
|
@@ -139,27 +121,31 @@ export function EqualUnequalSizesControl<
|
|
|
139
121
|
>
|
|
140
122
|
<Stack gap={ 1.5 }>
|
|
141
123
|
<Grid container gap={ 2 } alignItems="center" flexWrap="nowrap">
|
|
142
|
-
<
|
|
124
|
+
<MultiSizeValueControl
|
|
143
125
|
item={ items[ 0 ] }
|
|
144
|
-
value={
|
|
126
|
+
value={ multiSizeValue }
|
|
145
127
|
setNestedProp={ setNestedProp }
|
|
128
|
+
splitEqualValue={ splitEqualValue }
|
|
146
129
|
/>
|
|
147
|
-
<
|
|
130
|
+
<MultiSizeValueControl
|
|
148
131
|
item={ items[ 1 ] }
|
|
149
|
-
value={
|
|
132
|
+
value={ multiSizeValue }
|
|
150
133
|
setNestedProp={ setNestedProp }
|
|
134
|
+
splitEqualValue={ splitEqualValue }
|
|
151
135
|
/>
|
|
152
136
|
</Grid>
|
|
153
137
|
<Grid container gap={ 2 } alignItems="center" flexWrap="nowrap">
|
|
154
|
-
<
|
|
138
|
+
<MultiSizeValueControl
|
|
155
139
|
item={ items[ 3 ] }
|
|
156
|
-
value={
|
|
140
|
+
value={ multiSizeValue }
|
|
157
141
|
setNestedProp={ setNestedProp }
|
|
142
|
+
splitEqualValue={ splitEqualValue }
|
|
158
143
|
/>
|
|
159
|
-
<
|
|
144
|
+
<MultiSizeValueControl
|
|
160
145
|
item={ items[ 2 ] }
|
|
161
|
-
value={
|
|
146
|
+
value={ multiSizeValue }
|
|
162
147
|
setNestedProp={ setNestedProp }
|
|
148
|
+
splitEqualValue={ splitEqualValue }
|
|
163
149
|
/>
|
|
164
150
|
</Grid>
|
|
165
151
|
</Stack>
|
|
@@ -168,25 +154,29 @@ export function EqualUnequalSizesControl<
|
|
|
168
154
|
);
|
|
169
155
|
}
|
|
170
156
|
|
|
171
|
-
const
|
|
157
|
+
const MultiSizeValueControl = < TPropValue extends MultiSizePropValue >( {
|
|
172
158
|
item,
|
|
173
159
|
value,
|
|
174
160
|
setNestedProp,
|
|
161
|
+
splitEqualValue,
|
|
175
162
|
}: {
|
|
176
|
-
item: Item
|
|
177
|
-
value: TPropValue
|
|
178
|
-
setNestedProp: ( item: Item
|
|
163
|
+
item: Item;
|
|
164
|
+
value: TPropValue | undefined;
|
|
165
|
+
setNestedProp: ( item: Item, newValue: SizePropValue ) => void;
|
|
166
|
+
splitEqualValue: () => TPropValue;
|
|
179
167
|
} ) => {
|
|
180
|
-
const
|
|
168
|
+
const handleChange = ( val: SizePropValue ) => setNestedProp( item, val );
|
|
169
|
+
|
|
170
|
+
const getMultiSizeValues = () => {
|
|
171
|
+
if ( value ) {
|
|
172
|
+
return value?.[ item.bind ] ?? null;
|
|
173
|
+
}
|
|
181
174
|
|
|
182
|
-
|
|
175
|
+
return splitEqualValue()?.[ item.bind ] ?? null;
|
|
176
|
+
};
|
|
183
177
|
|
|
184
178
|
return (
|
|
185
|
-
<BoundPropProvider
|
|
186
|
-
bind={ '' }
|
|
187
|
-
setValue={ ( val ) => setNestedProp( item, val as SizePropValue ) }
|
|
188
|
-
value={ nestedValue }
|
|
189
|
-
>
|
|
179
|
+
<BoundPropProvider bind={ '' } setValue={ handleChange as SetContextValue } value={ getMultiSizeValues() }>
|
|
190
180
|
<Grid item xs={ 6 }>
|
|
191
181
|
<Grid container gap={ 1 } alignItems="center">
|
|
192
182
|
<Grid item xs={ 12 }>
|
|
@@ -201,27 +191,37 @@ const NestedValueControl = < TMultiPropType extends string, TPropValue extends M
|
|
|
201
191
|
);
|
|
202
192
|
};
|
|
203
193
|
|
|
204
|
-
const
|
|
205
|
-
TMultiPropType extends string,
|
|
206
|
-
TPropValue extends MultiSizePropValue< TMultiPropType >[ 'value' ],
|
|
207
|
-
>( {
|
|
194
|
+
const EqualSizeControl = ( {
|
|
208
195
|
value,
|
|
196
|
+
items,
|
|
209
197
|
setValue,
|
|
210
198
|
iconButton,
|
|
199
|
+
multiSizeValue,
|
|
211
200
|
}: {
|
|
212
|
-
value:
|
|
213
|
-
|
|
201
|
+
value: SizePropValue[ 'value' ] | null;
|
|
202
|
+
items: EqualUnequalItems;
|
|
203
|
+
setValue: ( newValue: SizePropValue[ 'value' ] ) => void;
|
|
214
204
|
iconButton: ReactNode;
|
|
205
|
+
multiSizeValue: PropValue;
|
|
215
206
|
} ) => {
|
|
216
|
-
const
|
|
217
|
-
|
|
207
|
+
const handleChange = ( newValue: SizePropValue ) => {
|
|
208
|
+
setValue( newValue.value );
|
|
209
|
+
};
|
|
210
|
+
|
|
211
|
+
const getDisplayValue = () => {
|
|
212
|
+
if ( value ) {
|
|
213
|
+
return sizePropTypeUtil.create( value );
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
const multiValues = Object.values( multiSizeValue ?? {} ) as SizePropValue[];
|
|
217
|
+
|
|
218
|
+
if ( isEqualSizes( multiValues, items ) ) {
|
|
219
|
+
return sizePropTypeUtil.create( multiValues[ 0 ].value );
|
|
220
|
+
}
|
|
221
|
+
};
|
|
218
222
|
|
|
219
223
|
return (
|
|
220
|
-
<BoundPropProvider
|
|
221
|
-
bind={ '' }
|
|
222
|
-
setValue={ ( val ) => setValue( val as SizePropValue ) }
|
|
223
|
-
value={ isMixed ? undefined : values[ 0 ] }
|
|
224
|
-
>
|
|
224
|
+
<BoundPropProvider bind={ '' } setValue={ handleChange as SetContextValue } value={ getDisplayValue() ?? null }>
|
|
225
225
|
<Stack direction="row" alignItems="center" gap={ 1 }>
|
|
226
226
|
<SizeControl placeholder={ __( 'MIXED', 'elementor' ) } />
|
|
227
227
|
{ iconButton }
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Fragment, useId, useState } from 'react';
|
|
2
2
|
import * as React from 'react';
|
|
3
|
+
import { stringPropTypeUtil } from '@elementor/editor-props';
|
|
3
4
|
import { ChevronDownIcon, EditIcon, PhotoIcon, SearchIcon, XIcon } from '@elementor/icons';
|
|
4
5
|
import {
|
|
5
6
|
bindPopover,
|
|
@@ -28,8 +29,8 @@ import { useFilteredFontFamilies } from '../hooks/use-filtered-font-families';
|
|
|
28
29
|
const SIZE = 'tiny';
|
|
29
30
|
|
|
30
31
|
export const FontFamilyControl = createControl( ( { fontFamilies } ) => {
|
|
31
|
-
const { value: fontFamily, setValue: setFontFamily } = useBoundProp< string | null >();
|
|
32
32
|
const [ searchValue, setSearchValue ] = useState( '' );
|
|
33
|
+
const { value: fontFamily, setValue: setFontFamily } = useBoundProp( stringPropTypeUtil );
|
|
33
34
|
|
|
34
35
|
const popupId = useId();
|
|
35
36
|
const popoverState = usePopupState( { variant: 'popover', popupId } );
|
|
@@ -1,10 +1,5 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import {
|
|
3
|
-
type ImagePropValue,
|
|
4
|
-
type ImageSrcPropValue,
|
|
5
|
-
type PropValue,
|
|
6
|
-
type SizePropValue,
|
|
7
|
-
} from '@elementor/editor-props';
|
|
2
|
+
import { imagePropTypeUtil, type ImageSrcPropValue, type PropValue, type SizePropValue } from '@elementor/editor-props';
|
|
8
3
|
import { Grid, Stack } from '@elementor/ui';
|
|
9
4
|
import { __ } from '@wordpress/i18n';
|
|
10
5
|
|
|
@@ -21,26 +16,20 @@ export type ImageControlProps = {
|
|
|
21
16
|
};
|
|
22
17
|
|
|
23
18
|
export const ImageControl = createControl( ( props: ImageControlProps ) => {
|
|
24
|
-
const { value, setValue } = useBoundProp
|
|
25
|
-
const { src, size } = value
|
|
19
|
+
const { value, setValue } = useBoundProp( imagePropTypeUtil );
|
|
20
|
+
const { src, size } = value || {};
|
|
26
21
|
|
|
27
22
|
const setImageSrc = ( newValue: ImageSrcPropValue ) => {
|
|
28
23
|
setValue( {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
src: newValue,
|
|
32
|
-
size: size as SizePropValue,
|
|
33
|
-
},
|
|
24
|
+
src: newValue,
|
|
25
|
+
size: size as SizePropValue,
|
|
34
26
|
} );
|
|
35
27
|
};
|
|
36
28
|
|
|
37
29
|
const setImageSize = ( newValue: SizePropValue ) => {
|
|
38
30
|
setValue( {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
src: src as ImageSrcPropValue,
|
|
42
|
-
size: newValue,
|
|
43
|
-
},
|
|
31
|
+
src: src as ImageSrcPropValue,
|
|
32
|
+
size: newValue,
|
|
44
33
|
} );
|
|
45
34
|
};
|
|
46
35
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import { imageSrcPropTypeUtil } from '@elementor/editor-props';
|
|
3
3
|
import { UploadIcon } from '@elementor/icons';
|
|
4
4
|
import { Button, Card, CardMedia, CardOverlay, CircularProgress, Stack } from '@elementor/ui';
|
|
5
5
|
import { useWpMediaAttachment, useWpMediaFrame } from '@elementor/wp-media';
|
|
@@ -10,8 +10,8 @@ import ControlActions from '../control-actions/control-actions';
|
|
|
10
10
|
import { createControl } from '../create-control';
|
|
11
11
|
|
|
12
12
|
export const ImageMediaControl = createControl( () => {
|
|
13
|
-
const { value, setValue } = useBoundProp
|
|
14
|
-
const { id, url } = value
|
|
13
|
+
const { value, setValue } = useBoundProp( imageSrcPropTypeUtil );
|
|
14
|
+
const { id, url } = value ?? {};
|
|
15
15
|
|
|
16
16
|
const { data: attachment, isFetching } = useWpMediaAttachment( id?.value || null );
|
|
17
17
|
const src = attachment?.url ?? url;
|
|
@@ -22,14 +22,11 @@ export const ImageMediaControl = createControl( () => {
|
|
|
22
22
|
selected: id?.value || null,
|
|
23
23
|
onSelect: ( selectedAttachment ) => {
|
|
24
24
|
setValue( {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
$$type: 'image-attachment-id',
|
|
29
|
-
value: selectedAttachment.id,
|
|
30
|
-
},
|
|
31
|
-
url: null,
|
|
25
|
+
id: {
|
|
26
|
+
$$type: 'image-attachment-id',
|
|
27
|
+
value: selectedAttachment.id,
|
|
32
28
|
},
|
|
29
|
+
url: null,
|
|
33
30
|
} );
|
|
34
31
|
},
|
|
35
32
|
} );
|