@elementor/editor-controls 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +20 -0
- package/dist/index.d.mts +35 -18
- package/dist/index.d.ts +35 -18
- package/dist/index.js +363 -575
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +347 -565
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -2
- package/src/bound-prop-context/errors.ts +16 -0
- package/src/bound-prop-context/index.ts +3 -0
- package/src/bound-prop-context/prop-context.tsx +48 -0
- package/src/bound-prop-context/prop-key-context.tsx +103 -0
- package/src/bound-prop-context/use-bound-prop.ts +69 -0
- package/src/components/repeater.tsx +3 -13
- package/src/controls/background-control/background-control.tsx +19 -42
- package/src/controls/background-control/background-overlay/background-overlay-repeater-control.tsx +32 -48
- package/src/controls/box-shadow-repeater-control.tsx +75 -139
- package/src/controls/color-control.tsx +16 -20
- package/src/controls/equal-unequal-sizes-control.tsx +65 -139
- package/src/controls/gap-control.tsx +20 -25
- package/src/controls/image-control.tsx +19 -34
- package/src/controls/image-media-control.tsx +1 -1
- package/src/controls/link-control.tsx +57 -58
- package/src/controls/linked-dimensions-control.tsx +25 -54
- package/src/controls/number-control.tsx +1 -1
- package/src/controls/stroke-control.tsx +18 -48
- package/src/controls/url-control.tsx +4 -14
- package/src/index.ts +3 -2
- package/src/bound-prop-context.tsx +0 -67
|
@@ -1,53 +1,38 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import { imagePropTypeUtil
|
|
2
|
+
import { imagePropTypeUtil } from '@elementor/editor-props';
|
|
3
3
|
import { Grid, Stack } from '@elementor/ui';
|
|
4
4
|
import { __ } from '@wordpress/i18n';
|
|
5
5
|
|
|
6
|
-
import {
|
|
6
|
+
import { PropKeyProvider, PropProvider, useBoundProp } from '../bound-prop-context';
|
|
7
7
|
import { ControlLabel } from '../components/control-label';
|
|
8
8
|
import { createControl } from '../create-control';
|
|
9
9
|
import { ImageMediaControl } from './image-media-control';
|
|
10
10
|
import { SelectControl } from './select-control';
|
|
11
11
|
|
|
12
|
-
type SetContextValue = ( v: PropValue ) => void;
|
|
13
|
-
|
|
14
12
|
export type ImageControlProps = {
|
|
15
13
|
sizes: { label: string; value: string }[];
|
|
16
14
|
};
|
|
17
15
|
|
|
18
16
|
export const ImageControl = createControl( ( props: ImageControlProps ) => {
|
|
19
|
-
const
|
|
20
|
-
const { src, size } = value || {};
|
|
21
|
-
|
|
22
|
-
const setImageSrc = ( newValue: ImageSrcPropValue ) => {
|
|
23
|
-
setValue( {
|
|
24
|
-
src: newValue,
|
|
25
|
-
size: size as SizePropValue,
|
|
26
|
-
} );
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
const setImageSize = ( newValue: SizePropValue ) => {
|
|
30
|
-
setValue( {
|
|
31
|
-
src: src as ImageSrcPropValue,
|
|
32
|
-
size: newValue,
|
|
33
|
-
} );
|
|
34
|
-
};
|
|
17
|
+
const propContext = useBoundProp( imagePropTypeUtil );
|
|
35
18
|
|
|
36
19
|
return (
|
|
37
|
-
<
|
|
38
|
-
<
|
|
39
|
-
<
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
<
|
|
43
|
-
<Grid
|
|
44
|
-
<
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
<
|
|
20
|
+
<PropProvider { ...propContext }>
|
|
21
|
+
<Stack gap={ 1.5 }>
|
|
22
|
+
<PropKeyProvider bind={ 'src' }>
|
|
23
|
+
<ImageMediaControl />
|
|
24
|
+
</PropKeyProvider>
|
|
25
|
+
<PropKeyProvider bind={ 'size' }>
|
|
26
|
+
<Grid container gap={ 2 } alignItems="center" flexWrap="nowrap">
|
|
27
|
+
<Grid item xs={ 6 }>
|
|
28
|
+
<ControlLabel> { __( 'Image Resolution', 'elementor' ) }</ControlLabel>
|
|
29
|
+
</Grid>
|
|
30
|
+
<Grid item xs={ 6 }>
|
|
31
|
+
<SelectControl options={ props.sizes } />
|
|
32
|
+
</Grid>
|
|
48
33
|
</Grid>
|
|
49
|
-
</
|
|
50
|
-
</
|
|
51
|
-
</
|
|
34
|
+
</PropKeyProvider>
|
|
35
|
+
</Stack>
|
|
36
|
+
</PropProvider>
|
|
52
37
|
);
|
|
53
38
|
} );
|
|
@@ -14,7 +14,7 @@ export const ImageMediaControl = createControl( () => {
|
|
|
14
14
|
const { id, url } = value ?? {};
|
|
15
15
|
|
|
16
16
|
const { data: attachment, isFetching } = useWpMediaAttachment( id?.value || null );
|
|
17
|
-
const src = attachment?.url ?? url;
|
|
17
|
+
const src = attachment?.url ?? url?.value ?? null;
|
|
18
18
|
|
|
19
19
|
const { open } = useWpMediaFrame( {
|
|
20
20
|
types: [ 'image' ],
|
|
@@ -1,89 +1,88 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import { linkPropTypeUtil, type LinkPropValue } from '@elementor/editor-props';
|
|
3
3
|
import { MinusIcon, PlusIcon } from '@elementor/icons';
|
|
4
4
|
import { Collapse, Divider, Grid, IconButton, Stack, Switch } from '@elementor/ui';
|
|
5
5
|
import { __ } from '@wordpress/i18n';
|
|
6
6
|
|
|
7
|
-
import {
|
|
7
|
+
import { PropKeyProvider, PropProvider, useBoundProp } from '../bound-prop-context';
|
|
8
8
|
import { ControlLabel } from '../components/control-label';
|
|
9
9
|
import { createControl } from '../create-control';
|
|
10
10
|
import { UrlControl } from './url-control';
|
|
11
11
|
|
|
12
12
|
const SIZE = 'tiny';
|
|
13
13
|
|
|
14
|
-
const DEFAULT_LINK_CONTROL_VALUE: LinkPropValue = {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
$$type: 'url',
|
|
20
|
-
value: '',
|
|
21
|
-
},
|
|
22
|
-
isTargetBlank: false,
|
|
14
|
+
const DEFAULT_LINK_CONTROL_VALUE: LinkPropValue[ 'value' ] = {
|
|
15
|
+
enabled: false,
|
|
16
|
+
href: {
|
|
17
|
+
$$type: 'url',
|
|
18
|
+
value: '',
|
|
23
19
|
},
|
|
20
|
+
isTargetBlank: false,
|
|
24
21
|
};
|
|
25
22
|
|
|
26
23
|
export const LinkControl = createControl( () => {
|
|
27
|
-
const { value = DEFAULT_LINK_CONTROL_VALUE,
|
|
28
|
-
const { enabled, href, isTargetBlank } = value?.value || {};
|
|
29
|
-
|
|
30
|
-
const handleOnChange = < T extends keyof LinkPropValue[ 'value' ] >(
|
|
31
|
-
key: T,
|
|
32
|
-
newValue: LinkPropValue[ 'value' ][ T ]
|
|
33
|
-
) => {
|
|
34
|
-
setValue( {
|
|
35
|
-
$$type: 'link',
|
|
36
|
-
value: {
|
|
37
|
-
...( value?.value ?? DEFAULT_LINK_CONTROL_VALUE.value ),
|
|
38
|
-
[ key ]: newValue,
|
|
39
|
-
},
|
|
40
|
-
} );
|
|
41
|
-
};
|
|
24
|
+
const { value = DEFAULT_LINK_CONTROL_VALUE, ...propContext } = useBoundProp( linkPropTypeUtil );
|
|
42
25
|
|
|
43
26
|
return (
|
|
44
|
-
<
|
|
45
|
-
<
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
<Collapse in={ enabled } timeout="auto" unmountOnExit>
|
|
59
|
-
<Stack gap={ 1.5 }>
|
|
60
|
-
<BoundPropProvider
|
|
61
|
-
value={ href }
|
|
62
|
-
setValue={ ( newHref ) => handleOnChange( 'href', newHref as UrlPropValue ) }
|
|
63
|
-
bind={ 'href' }
|
|
64
|
-
>
|
|
65
|
-
<UrlControl placeholder={ __( 'Paste URL or type', 'elementor' ) } />
|
|
66
|
-
</BoundPropProvider>
|
|
67
|
-
|
|
68
|
-
<SwitchControl
|
|
69
|
-
value={ isTargetBlank }
|
|
70
|
-
onSwitch={ () => handleOnChange( 'isTargetBlank', ! isTargetBlank ) }
|
|
71
|
-
/>
|
|
27
|
+
<PropProvider { ...propContext } value={ value }>
|
|
28
|
+
<Stack gap={ 1.5 }>
|
|
29
|
+
<Divider />
|
|
30
|
+
<Stack
|
|
31
|
+
direction="row"
|
|
32
|
+
sx={ {
|
|
33
|
+
justifyContent: 'space-between',
|
|
34
|
+
alignItems: 'center',
|
|
35
|
+
} }
|
|
36
|
+
>
|
|
37
|
+
<ControlLabel>{ __( 'Link', 'elementor' ) }</ControlLabel>
|
|
38
|
+
<PropKeyProvider bind={ 'enabled' }>
|
|
39
|
+
<ToggleIconControl />
|
|
40
|
+
</PropKeyProvider>
|
|
72
41
|
</Stack>
|
|
73
|
-
|
|
74
|
-
|
|
42
|
+
<Collapse in={ value?.enabled } timeout="auto" unmountOnExit>
|
|
43
|
+
<Stack gap={ 1.5 }>
|
|
44
|
+
<PropKeyProvider bind={ 'href' }>
|
|
45
|
+
<UrlControl placeholder={ __( 'Paste URL or type', 'elementor' ) } />
|
|
46
|
+
</PropKeyProvider>
|
|
47
|
+
|
|
48
|
+
<PropKeyProvider bind={ 'isTargetBlank' }>
|
|
49
|
+
<SwitchControl />
|
|
50
|
+
</PropKeyProvider>
|
|
51
|
+
</Stack>
|
|
52
|
+
</Collapse>
|
|
53
|
+
</Stack>
|
|
54
|
+
</PropProvider>
|
|
75
55
|
);
|
|
76
56
|
} );
|
|
77
57
|
|
|
58
|
+
// @TODO Should be refactored in EDS-1086
|
|
59
|
+
const ToggleIconControl = () => {
|
|
60
|
+
const { value = false, setValue } = useBoundProp();
|
|
61
|
+
|
|
62
|
+
const handleOnChange = () => setValue( ! value );
|
|
63
|
+
|
|
64
|
+
return (
|
|
65
|
+
<IconButton size={ SIZE } onClick={ handleOnChange }>
|
|
66
|
+
{ value ? <MinusIcon fontSize={ SIZE } /> : <PlusIcon fontSize={ SIZE } /> }
|
|
67
|
+
</IconButton>
|
|
68
|
+
);
|
|
69
|
+
};
|
|
70
|
+
|
|
78
71
|
// @TODO Should be refactored in ED-16323
|
|
79
|
-
const SwitchControl = (
|
|
72
|
+
const SwitchControl = () => {
|
|
73
|
+
const { value = false, setValue } = useBoundProp();
|
|
74
|
+
|
|
75
|
+
const onChange = () => {
|
|
76
|
+
setValue( ! value );
|
|
77
|
+
};
|
|
78
|
+
|
|
80
79
|
return (
|
|
81
80
|
<Grid container alignItems="center" flexWrap="nowrap" justifyContent="space-between">
|
|
82
81
|
<Grid item>
|
|
83
82
|
<ControlLabel>{ __( 'Open in new tab', 'elementor' ) }</ControlLabel>
|
|
84
83
|
</Grid>
|
|
85
84
|
<Grid item>
|
|
86
|
-
<Switch checked={ value } onChange={
|
|
85
|
+
<Switch checked={ value } onChange={ onChange } />
|
|
87
86
|
</Grid>
|
|
88
87
|
</Grid>
|
|
89
88
|
);
|
|
@@ -1,31 +1,32 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import { linkedDimensionsPropTypeUtil, type
|
|
2
|
+
import { linkedDimensionsPropTypeUtil, type LinkedDimensionsPropValue, type PropKey } from '@elementor/editor-props';
|
|
3
3
|
import { DetachIcon, LinkIcon, SideBottomIcon, SideLeftIcon, SideRightIcon, SideTopIcon } from '@elementor/icons';
|
|
4
4
|
import { Grid, Stack, ToggleButton } from '@elementor/ui';
|
|
5
5
|
import { __ } from '@wordpress/i18n';
|
|
6
6
|
|
|
7
|
-
import {
|
|
7
|
+
import { PropKeyProvider, PropProvider, type SetValue, useBoundProp } from '../bound-prop-context';
|
|
8
8
|
import { ControlLabel } from '../components/control-label';
|
|
9
9
|
import { createControl } from '../create-control';
|
|
10
10
|
import { SizeControl } from './size-control';
|
|
11
11
|
|
|
12
|
-
export type Position = 'top' | 'right' | 'bottom' | 'left';
|
|
13
|
-
|
|
14
12
|
export const LinkedDimensionsControl = createControl( ( { label }: { label: string } ) => {
|
|
15
|
-
const { value, setValue } = useBoundProp( linkedDimensionsPropTypeUtil );
|
|
13
|
+
const { value, setValue, propType } = useBoundProp( linkedDimensionsPropTypeUtil );
|
|
16
14
|
const { top, right, bottom, left, isLinked = true } = value || {};
|
|
17
15
|
|
|
18
|
-
const setLinkedValue = (
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
right: isLinked ? newValue : right,
|
|
23
|
-
bottom: isLinked ? newValue : bottom,
|
|
24
|
-
left: isLinked ? newValue : left,
|
|
25
|
-
[ position ]: newValue,
|
|
26
|
-
};
|
|
16
|
+
const setLinkedValue: SetValue< LinkedDimensionsPropValue[ 'value' ] > = ( newValue, _, meta ) => {
|
|
17
|
+
if ( ! isLinked ) {
|
|
18
|
+
return setValue( newValue );
|
|
19
|
+
}
|
|
27
20
|
|
|
28
|
-
|
|
21
|
+
const newDimension = newValue[ meta?.bind as keyof LinkedDimensionsPropValue[ 'value' ] ];
|
|
22
|
+
|
|
23
|
+
setValue( {
|
|
24
|
+
isLinked,
|
|
25
|
+
top: newDimension,
|
|
26
|
+
right: newDimension,
|
|
27
|
+
bottom: newDimension,
|
|
28
|
+
left: newDimension,
|
|
29
|
+
} );
|
|
29
30
|
};
|
|
30
31
|
|
|
31
32
|
const toggleLinked = () => {
|
|
@@ -43,7 +44,7 @@ export const LinkedDimensionsControl = createControl( ( { label }: { label: stri
|
|
|
43
44
|
const LinkedIcon = isLinked ? LinkIcon : DetachIcon;
|
|
44
45
|
|
|
45
46
|
return (
|
|
46
|
-
|
|
47
|
+
<PropProvider propType={ propType } value={ value } setValue={ setLinkedValue }>
|
|
47
48
|
<Stack direction="row" gap={ 2 } flexWrap="nowrap">
|
|
48
49
|
<ControlLabel>{ label }</ControlLabel>
|
|
49
50
|
<ToggleButton
|
|
@@ -63,12 +64,7 @@ export const LinkedDimensionsControl = createControl( ( { label }: { label: stri
|
|
|
63
64
|
<ControlLabel>{ __( 'Top', 'elementor' ) }</ControlLabel>
|
|
64
65
|
</Grid>
|
|
65
66
|
<Grid item xs={ 12 }>
|
|
66
|
-
<Control
|
|
67
|
-
bind={ 'top' }
|
|
68
|
-
value={ top }
|
|
69
|
-
setValue={ setLinkedValue }
|
|
70
|
-
startIcon={ <SideTopIcon fontSize={ 'tiny' } /> }
|
|
71
|
-
/>
|
|
67
|
+
<Control bind={ 'top' } startIcon={ <SideTopIcon fontSize={ 'tiny' } /> } />
|
|
72
68
|
</Grid>
|
|
73
69
|
</Grid>
|
|
74
70
|
<Grid container gap={ 1 } alignItems="center">
|
|
@@ -76,12 +72,7 @@ export const LinkedDimensionsControl = createControl( ( { label }: { label: stri
|
|
|
76
72
|
<ControlLabel>{ __( 'Right', 'elementor' ) }</ControlLabel>
|
|
77
73
|
</Grid>
|
|
78
74
|
<Grid item xs={ 12 }>
|
|
79
|
-
<Control
|
|
80
|
-
bind={ 'right' }
|
|
81
|
-
value={ right }
|
|
82
|
-
setValue={ setLinkedValue }
|
|
83
|
-
startIcon={ <SideRightIcon fontSize={ 'tiny' } /> }
|
|
84
|
-
/>
|
|
75
|
+
<Control bind={ 'right' } startIcon={ <SideRightIcon fontSize={ 'tiny' } /> } />
|
|
85
76
|
</Grid>
|
|
86
77
|
</Grid>
|
|
87
78
|
</Stack>
|
|
@@ -91,12 +82,7 @@ export const LinkedDimensionsControl = createControl( ( { label }: { label: stri
|
|
|
91
82
|
<ControlLabel>{ __( 'Bottom', 'elementor' ) }</ControlLabel>
|
|
92
83
|
</Grid>
|
|
93
84
|
<Grid item xs={ 12 }>
|
|
94
|
-
<Control
|
|
95
|
-
bind={ 'bottom' }
|
|
96
|
-
value={ bottom }
|
|
97
|
-
setValue={ setLinkedValue }
|
|
98
|
-
startIcon={ <SideBottomIcon fontSize={ 'tiny' } /> }
|
|
99
|
-
/>
|
|
85
|
+
<Control bind={ 'bottom' } startIcon={ <SideBottomIcon fontSize={ 'tiny' } /> } />
|
|
100
86
|
</Grid>
|
|
101
87
|
</Grid>
|
|
102
88
|
<Grid container gap={ 1 } alignItems="center">
|
|
@@ -104,31 +90,16 @@ export const LinkedDimensionsControl = createControl( ( { label }: { label: stri
|
|
|
104
90
|
<ControlLabel>{ __( 'Left', 'elementor' ) }</ControlLabel>
|
|
105
91
|
</Grid>
|
|
106
92
|
<Grid item xs={ 12 }>
|
|
107
|
-
<Control
|
|
108
|
-
bind={ 'left' }
|
|
109
|
-
value={ left }
|
|
110
|
-
setValue={ setLinkedValue }
|
|
111
|
-
startIcon={ <SideLeftIcon fontSize={ 'tiny' } /> }
|
|
112
|
-
/>
|
|
93
|
+
<Control bind={ 'left' } startIcon={ <SideLeftIcon fontSize={ 'tiny' } /> } />
|
|
113
94
|
</Grid>
|
|
114
95
|
</Grid>
|
|
115
96
|
</Stack>
|
|
116
|
-
|
|
97
|
+
</PropProvider>
|
|
117
98
|
);
|
|
118
99
|
} );
|
|
119
100
|
|
|
120
|
-
const Control = ( {
|
|
121
|
-
bind
|
|
122
|
-
startIcon,
|
|
123
|
-
value,
|
|
124
|
-
setValue,
|
|
125
|
-
}: {
|
|
126
|
-
bind: Position;
|
|
127
|
-
value: PropValue;
|
|
128
|
-
startIcon: React.ReactNode;
|
|
129
|
-
setValue: ( bind: Position, newValue: PropValue ) => void;
|
|
130
|
-
} ) => (
|
|
131
|
-
<BoundPropProvider setValue={ ( newValue ) => setValue( bind, newValue ) } value={ value } bind={ bind }>
|
|
101
|
+
const Control = ( { bind, startIcon }: { bind: PropKey; startIcon: React.ReactNode } ) => (
|
|
102
|
+
<PropKeyProvider bind={ bind }>
|
|
132
103
|
<SizeControl startIcon={ startIcon } />
|
|
133
|
-
</
|
|
104
|
+
</PropKeyProvider>
|
|
134
105
|
);
|
|
@@ -6,7 +6,7 @@ import { useBoundProp } from '../bound-prop-context';
|
|
|
6
6
|
import ControlActions from '../control-actions/control-actions';
|
|
7
7
|
import { createControl } from '../create-control';
|
|
8
8
|
|
|
9
|
-
const isEmptyOrNaN = ( value?: string | number ) =>
|
|
9
|
+
const isEmptyOrNaN = ( value?: string | number | null ) =>
|
|
10
10
|
value === null || value === undefined || value === '' || Number.isNaN( Number( value ) );
|
|
11
11
|
|
|
12
12
|
export const NumberControl = createControl(
|
|
@@ -1,71 +1,41 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import { strokePropTypeUtil } from '@elementor/editor-props';
|
|
3
3
|
import { Grid, Stack } from '@elementor/ui';
|
|
4
4
|
import { __ } from '@wordpress/i18n';
|
|
5
5
|
|
|
6
|
-
import {
|
|
6
|
+
import { PropKeyProvider, PropProvider, useBoundProp } from '../bound-prop-context';
|
|
7
7
|
import { ControlLabel } from '../components/control-label';
|
|
8
8
|
import { createControl } from '../create-control';
|
|
9
9
|
import { ColorControl } from './color-control';
|
|
10
10
|
import { SizeControl, type Unit } from './size-control';
|
|
11
11
|
|
|
12
|
-
type
|
|
13
|
-
|
|
14
|
-
export type StrokeProps< T > = {
|
|
12
|
+
export type StrokeProps = {
|
|
15
13
|
bind: string;
|
|
16
|
-
value: T;
|
|
17
|
-
setValue: ( v: T ) => void;
|
|
18
14
|
label: string;
|
|
19
15
|
children: React.ReactNode;
|
|
20
16
|
};
|
|
17
|
+
|
|
21
18
|
const units: Unit[] = [ 'px', 'em', 'rem' ];
|
|
22
19
|
|
|
23
20
|
export const StrokeControl = createControl( () => {
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
const setStrokeWidth = ( newValue: SizePropValue ) => {
|
|
27
|
-
const updatedValue = {
|
|
28
|
-
...value,
|
|
29
|
-
width: newValue,
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
setValue( updatedValue );
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
const setStrokeColor = ( newValue: ColorPropValue ) => {
|
|
36
|
-
const updatedValue = {
|
|
37
|
-
...value,
|
|
38
|
-
color: newValue,
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
setValue( updatedValue );
|
|
42
|
-
};
|
|
21
|
+
const propContext = useBoundProp( strokePropTypeUtil );
|
|
43
22
|
|
|
44
23
|
return (
|
|
45
|
-
<
|
|
46
|
-
<
|
|
47
|
-
bind="width"
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
</
|
|
54
|
-
|
|
55
|
-
<Control
|
|
56
|
-
bind="color"
|
|
57
|
-
label={ __( 'Stroke Color', 'elementor' ) }
|
|
58
|
-
value={ value?.color }
|
|
59
|
-
setValue={ setStrokeColor }
|
|
60
|
-
>
|
|
61
|
-
<ColorControl />
|
|
62
|
-
</Control>
|
|
63
|
-
</Stack>
|
|
24
|
+
<PropProvider { ...propContext }>
|
|
25
|
+
<Stack gap={ 1.5 }>
|
|
26
|
+
<Control bind="width" label={ __( 'Stroke Width', 'elementor' ) }>
|
|
27
|
+
<SizeControl units={ units } />
|
|
28
|
+
</Control>
|
|
29
|
+
<Control bind="color" label={ __( 'Stroke Color', 'elementor' ) }>
|
|
30
|
+
<ColorControl />
|
|
31
|
+
</Control>
|
|
32
|
+
</Stack>
|
|
33
|
+
</PropProvider>
|
|
64
34
|
);
|
|
65
35
|
} );
|
|
66
36
|
|
|
67
|
-
const Control =
|
|
68
|
-
<
|
|
37
|
+
const Control = ( { bind, label, children }: StrokeProps ) => (
|
|
38
|
+
<PropKeyProvider bind={ bind }>
|
|
69
39
|
<Grid container gap={ 2 } alignItems="center" flexWrap="nowrap">
|
|
70
40
|
<Grid item xs={ 6 }>
|
|
71
41
|
<ControlLabel>{ label }</ControlLabel>
|
|
@@ -74,5 +44,5 @@ const Control = < T extends PropValue >( { bind, value, setValue, label, childre
|
|
|
74
44
|
{ children }
|
|
75
45
|
</Grid>
|
|
76
46
|
</Grid>
|
|
77
|
-
</
|
|
47
|
+
</PropKeyProvider>
|
|
78
48
|
);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import { urlPropTypeUtil } from '@elementor/editor-props';
|
|
3
3
|
import { TextField } from '@elementor/ui';
|
|
4
4
|
|
|
5
5
|
import { useBoundProp } from '../bound-prop-context';
|
|
@@ -7,23 +7,13 @@ import ControlActions from '../control-actions/control-actions';
|
|
|
7
7
|
import { createControl } from '../create-control';
|
|
8
8
|
|
|
9
9
|
export const UrlControl = createControl( ( { placeholder }: { placeholder?: string } ) => {
|
|
10
|
-
const { value, setValue } = useBoundProp
|
|
10
|
+
const { value, setValue } = useBoundProp( urlPropTypeUtil );
|
|
11
11
|
|
|
12
|
-
const handleChange = ( event: React.ChangeEvent< HTMLInputElement > ) =>
|
|
13
|
-
setValue( {
|
|
14
|
-
$$type: 'url',
|
|
15
|
-
value: event.target.value,
|
|
16
|
-
} );
|
|
12
|
+
const handleChange = ( event: React.ChangeEvent< HTMLInputElement > ) => setValue( event.target.value );
|
|
17
13
|
|
|
18
14
|
return (
|
|
19
15
|
<ControlActions>
|
|
20
|
-
<TextField
|
|
21
|
-
size="tiny"
|
|
22
|
-
fullWidth
|
|
23
|
-
value={ value?.value }
|
|
24
|
-
onChange={ handleChange }
|
|
25
|
-
placeholder={ placeholder }
|
|
26
|
-
/>
|
|
16
|
+
<TextField size="tiny" fullWidth value={ value } onChange={ handleChange } placeholder={ placeholder } />
|
|
27
17
|
</ControlActions>
|
|
28
18
|
);
|
|
29
19
|
} );
|
package/src/index.ts
CHANGED
|
@@ -26,12 +26,13 @@ export type { ControlComponent } from './create-control';
|
|
|
26
26
|
export type { ToggleButtonGroupItem } from './components/control-toggle-button-group';
|
|
27
27
|
export type { EqualUnequalItems } from './controls/equal-unequal-sizes-control';
|
|
28
28
|
export type { ControlActionsItems } from './control-actions/control-actions-context';
|
|
29
|
-
export type {
|
|
29
|
+
export type { PropProviderProps } from './bound-prop-context';
|
|
30
|
+
export type { SetValue } from './bound-prop-context/prop-context';
|
|
30
31
|
|
|
31
32
|
// providers
|
|
32
33
|
export { createControlReplacement, ControlReplacementProvider } from './create-control-replacement';
|
|
33
|
-
export { useBoundProp, BoundPropProvider } from './bound-prop-context';
|
|
34
34
|
export { ControlActionsProvider, useControlActions } from './control-actions/control-actions-context';
|
|
35
|
+
export { useBoundProp, PropProvider, PropKeyProvider } from './bound-prop-context';
|
|
35
36
|
|
|
36
37
|
// hooks
|
|
37
38
|
export { useSyncExternalState } from './hooks/use-sync-external-state';
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
import * as React from 'react';
|
|
2
|
-
import { createContext, useContext } from 'react';
|
|
3
|
-
import { type CreateOptions, type PropKey, type PropTypeUtil, type PropValue } from '@elementor/editor-props';
|
|
4
|
-
|
|
5
|
-
// Context
|
|
6
|
-
export type BoundPropContext< T extends PropValue > = {
|
|
7
|
-
bind: PropKey;
|
|
8
|
-
setValue: ( value: T | null ) => void;
|
|
9
|
-
value: T;
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
const BoundPropContext = createContext< BoundPropContext< PropValue > | null >( null );
|
|
13
|
-
|
|
14
|
-
// Provider
|
|
15
|
-
export type BoundPropProviderProps< T extends PropValue > = BoundPropContext< T > & {
|
|
16
|
-
children: React.ReactNode;
|
|
17
|
-
setValue: ( value: T | null ) => void;
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
export const BoundPropProvider = ( { children, value, setValue, bind }: BoundPropProviderProps< PropValue > ) => {
|
|
21
|
-
return <BoundPropContext.Provider value={ { value, setValue, bind } }>{ children }</BoundPropContext.Provider>;
|
|
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 );
|
|
43
|
-
|
|
44
|
-
if ( ! boundPropContext ) {
|
|
45
|
-
throw new Error( 'useBoundProp must be used within a BoundPropProvider' );
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
if ( ! propTypeUtil ) {
|
|
49
|
-
return boundPropContext;
|
|
50
|
-
}
|
|
51
|
-
|
|
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
|
-
};
|
|
67
|
-
}
|