@elementor/editor-editing-panel 1.0.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 +70 -0
- package/dist/index.d.mts +10 -19
- package/dist/index.d.ts +10 -19
- package/dist/index.js +1539 -1754
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1534 -1723
- package/dist/index.mjs.map +1 -1
- package/package.json +13 -13
- package/src/components/add-or-remove-content.tsx +3 -3
- package/src/components/collapse-icon.tsx +12 -0
- package/src/components/collapsible-content.tsx +5 -14
- package/src/components/collapsible-field.tsx +5 -3
- package/src/components/css-class-selector.tsx +131 -0
- package/src/components/editing-panel-hooks.tsx +2 -0
- package/src/components/editing-panel-tabs.tsx +23 -13
- package/src/components/editing-panel.tsx +9 -6
- package/src/components/multi-combobox/index.ts +3 -0
- package/src/components/multi-combobox/multi-combobox.tsx +122 -0
- package/src/components/multi-combobox/types.ts +28 -0
- package/src/components/multi-combobox/use-combobox-actions.ts +62 -0
- package/src/components/section.tsx +37 -0
- package/src/components/sections-list.tsx +6 -0
- package/src/components/settings-tab.tsx +11 -11
- package/src/components/style-sections/background-section/background-color-field.tsx +4 -4
- package/src/components/style-sections/background-section/background-section.tsx +9 -7
- package/src/components/style-sections/border-section/border-color-field.tsx +4 -4
- package/src/components/style-sections/border-section/border-field.tsx +4 -3
- package/src/components/style-sections/border-section/border-radius-field.tsx +4 -3
- package/src/components/style-sections/border-section/border-section.tsx +7 -10
- package/src/components/style-sections/border-section/border-style-field.tsx +4 -4
- package/src/components/style-sections/border-section/border-width-field.tsx +4 -3
- package/src/components/style-sections/effects-section/effects-section.tsx +7 -10
- package/src/components/style-sections/layout-section/align-items-field.tsx +92 -0
- package/src/components/style-sections/layout-section/display-field.tsx +32 -0
- package/src/components/style-sections/layout-section/flex-direction-field.tsx +64 -0
- package/src/components/style-sections/layout-section/flex-order-field.tsx +114 -0
- package/src/components/style-sections/layout-section/justify-content-field.tsx +109 -0
- package/src/components/style-sections/layout-section/layout-section.tsx +36 -0
- package/src/components/style-sections/layout-section/wrap-field.tsx +52 -0
- package/src/components/style-sections/position-section/dimensions-field.tsx +6 -6
- package/src/components/style-sections/position-section/position-field.tsx +4 -4
- package/src/components/style-sections/position-section/position-section.tsx +45 -15
- package/src/components/style-sections/position-section/z-index-field.tsx +4 -4
- package/src/components/style-sections/size-section/overflow-field.tsx +8 -8
- package/src/components/style-sections/size-section/size-section.tsx +33 -26
- package/src/components/style-sections/spacing-section/spacing-section.tsx +11 -13
- package/src/components/style-sections/typography-section/font-family-field.tsx +40 -0
- package/src/components/style-sections/typography-section/font-size-field.tsx +4 -4
- package/src/components/style-sections/typography-section/font-weight-field.tsx +4 -4
- package/src/components/style-sections/typography-section/letter-spacing-field.tsx +4 -4
- package/src/components/style-sections/typography-section/text-alignment-field.tsx +9 -9
- package/src/components/style-sections/typography-section/text-color-field.tsx +4 -4
- package/src/components/style-sections/typography-section/text-direction-field.tsx +7 -7
- package/src/components/style-sections/typography-section/text-stroke-field.tsx +42 -7
- package/src/components/style-sections/typography-section/text-style-field.tsx +5 -4
- package/src/components/style-sections/typography-section/transform-field.tsx +23 -9
- package/src/components/style-sections/typography-section/typography-section.tsx +26 -27
- package/src/components/style-sections/typography-section/word-spacing-field.tsx +4 -4
- package/src/components/style-tab.tsx +67 -31
- package/src/contexts/classes-prop-context.tsx +1 -1
- package/src/contexts/element-context.tsx +2 -2
- package/src/contexts/style-context.tsx +6 -5
- package/src/control-replacement.tsx +1 -1
- package/src/controls-actions.ts +3 -2
- package/src/controls-registry/control-type-container.tsx +3 -2
- package/src/controls-registry/control.tsx +2 -1
- package/src/controls-registry/controls-registry.tsx +8 -1
- package/src/controls-registry/settings-field.tsx +5 -4
- package/src/controls-registry/styles-field.tsx +3 -2
- package/src/dynamics/components/dynamic-selection-control.tsx +15 -14
- package/src/dynamics/components/dynamic-selection.tsx +9 -8
- package/src/dynamics/dynamic-control.tsx +4 -4
- package/src/dynamics/hooks/use-dynamic-tag.ts +3 -2
- package/src/dynamics/hooks/use-prop-dynamic-action.tsx +6 -5
- package/src/dynamics/hooks/use-prop-dynamic-tags.ts +3 -2
- package/src/dynamics/init.ts +5 -3
- package/src/dynamics/sync/get-elementor-config.ts +1 -1
- package/src/dynamics/types.ts +2 -2
- package/src/dynamics/utils.ts +3 -2
- package/src/hooks/use-close-editor-panel.ts +23 -0
- package/src/hooks/use-direction.ts +13 -0
- package/src/hooks/use-open-editor-panel.ts +4 -3
- package/src/hooks/use-prop-value-history.ts +45 -0
- package/src/hooks/use-style-prop-history.ts +75 -0
- package/src/hooks/use-styles-field.ts +25 -4
- package/src/index.ts +1 -1
- package/src/init.ts +5 -4
- package/src/panel.ts +1 -0
- package/src/popover-action.tsx +1 -1
- package/src/sync/enqueue-font.ts +7 -0
- package/src/sync/get-elementor-config.ts +7 -0
- package/src/sync/{should-use-v2-panel.ts → is-atomic-widget-selected.ts} +1 -1
- package/src/sync/types.ts +20 -21
- package/src/components/accordion-section.tsx +0 -26
- package/src/components/control-label.tsx +0 -10
- package/src/controls/bound-prop-context.tsx +0 -30
- package/src/controls/components/control-toggle-button-group.tsx +0 -68
- package/src/controls/components/repeater.tsx +0 -197
- package/src/controls/components/text-field-inner-selection.tsx +0 -75
- package/src/controls/control-actions/control-actions-context.tsx +0 -27
- package/src/controls/control-actions/control-actions-menu.ts +0 -7
- package/src/controls/control-actions/control-actions.tsx +0 -31
- package/src/controls/controls/box-shadow-repeater-control.tsx +0 -210
- package/src/controls/controls/color-control.tsx +0 -25
- package/src/controls/controls/equal-unequal-sizes-control.tsx +0 -196
- package/src/controls/controls/image-control.tsx +0 -58
- package/src/controls/controls/image-media-control.tsx +0 -64
- package/src/controls/controls/linked-dimensions-control.tsx +0 -139
- package/src/controls/controls/number-control.tsx +0 -29
- package/src/controls/controls/select-control.tsx +0 -30
- package/src/controls/controls/size-control.tsx +0 -71
- package/src/controls/controls/stroke-control.tsx +0 -105
- package/src/controls/controls/text-area-control.tsx +0 -31
- package/src/controls/controls/text-control.tsx +0 -17
- package/src/controls/controls/toggle-control.tsx +0 -26
- package/src/controls/create-control-replacement.tsx +0 -53
- package/src/controls/create-control.tsx +0 -40
- package/src/controls/hooks/use-sync-external-state.tsx +0 -51
- package/src/controls/index.ts +0 -24
- package/src/dynamics/hooks/use-prop-value-history.ts +0 -26
|
@@ -1,196 +0,0 @@
|
|
|
1
|
-
import * as React from 'react';
|
|
2
|
-
import { ReactNode, useId, useRef } from 'react';
|
|
3
|
-
import { PropValue, TransformablePropValue } from '@elementor/editor-props';
|
|
4
|
-
import { bindPopover, bindToggle, Grid, Popover, Stack, ToggleButton, usePopupState } from '@elementor/ui';
|
|
5
|
-
import { __ } from '@wordpress/i18n';
|
|
6
|
-
import { ControlLabel } from '../../components/control-label';
|
|
7
|
-
import { BoundPropProvider, SizeControl, SizeControlValue, useBoundProp } from '../index';
|
|
8
|
-
|
|
9
|
-
type MultiSizePropValue< TMultiPropType extends string > = TransformablePropValue<
|
|
10
|
-
TMultiPropType,
|
|
11
|
-
Record< string, SizeControlValue >
|
|
12
|
-
>;
|
|
13
|
-
|
|
14
|
-
type Item< TMultiPropType extends string, TPropValue extends MultiSizePropValue< TMultiPropType > > = {
|
|
15
|
-
icon: ReactNode;
|
|
16
|
-
label: string;
|
|
17
|
-
bind: keyof TPropValue[ 'value' ];
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
export type EqualUnequalItems<
|
|
21
|
-
TMultiPropType extends string,
|
|
22
|
-
TPropValue extends MultiSizePropValue< TMultiPropType >,
|
|
23
|
-
> = [
|
|
24
|
-
Item< TMultiPropType, TPropValue >,
|
|
25
|
-
Item< TMultiPropType, TPropValue >,
|
|
26
|
-
Item< TMultiPropType, TPropValue >,
|
|
27
|
-
Item< TMultiPropType, TPropValue >,
|
|
28
|
-
];
|
|
29
|
-
|
|
30
|
-
type Props< TMultiPropType extends string, TPropValue extends MultiSizePropValue< TMultiPropType > > = {
|
|
31
|
-
label: string;
|
|
32
|
-
icon: ReactNode;
|
|
33
|
-
items: EqualUnequalItems< TMultiPropType, TPropValue >;
|
|
34
|
-
multiSizeType: TMultiPropType;
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
function hasMixedSizes( values: SizeControlValue[] ): boolean {
|
|
38
|
-
const [ firstValue, ...restValues ] = values;
|
|
39
|
-
|
|
40
|
-
return restValues.some(
|
|
41
|
-
( value ) => value?.value?.size !== firstValue?.value?.size || value?.value?.unit !== firstValue?.value?.unit
|
|
42
|
-
);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
export function EqualUnequalSizesControl<
|
|
46
|
-
TMultiPropType extends string,
|
|
47
|
-
TPropValue extends MultiSizePropValue< TMultiPropType >,
|
|
48
|
-
>( { label, icon, items, multiSizeType }: Props< TMultiPropType, TPropValue > ) {
|
|
49
|
-
const popupId = useId();
|
|
50
|
-
const controlRef = useRef< HTMLElement >( null );
|
|
51
|
-
const { value: controlValue, setValue: setControlValue } = useBoundProp< TPropValue >();
|
|
52
|
-
|
|
53
|
-
const actualValue: TPropValue[ 'value' ] = controlValue?.value ?? {};
|
|
54
|
-
const setActualValue = ( newValue: TPropValue[ 'value' ] ) => {
|
|
55
|
-
setControlValue( { $$type: multiSizeType, value: newValue } as TPropValue );
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
const setNestedProp = ( item: Item< TMultiPropType, TPropValue >, newValue: PropValue ) => {
|
|
59
|
-
const { bind } = item;
|
|
60
|
-
|
|
61
|
-
const newValues = {
|
|
62
|
-
...actualValue,
|
|
63
|
-
[ bind ]: newValue,
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
setActualValue( newValues );
|
|
67
|
-
};
|
|
68
|
-
|
|
69
|
-
const setEqualValues = ( newValue: PropValue ) => {
|
|
70
|
-
const equalValues = items.reduce( ( values: TPropValue[ 'value' ], item ) => {
|
|
71
|
-
return {
|
|
72
|
-
...values,
|
|
73
|
-
[ item.bind ]: newValue,
|
|
74
|
-
};
|
|
75
|
-
}, {} );
|
|
76
|
-
|
|
77
|
-
setActualValue( equalValues );
|
|
78
|
-
};
|
|
79
|
-
|
|
80
|
-
const popupState = usePopupState( {
|
|
81
|
-
variant: 'popover',
|
|
82
|
-
popupId,
|
|
83
|
-
} );
|
|
84
|
-
|
|
85
|
-
return (
|
|
86
|
-
<>
|
|
87
|
-
<Grid container alignItems="center" ref={ controlRef }>
|
|
88
|
-
<Grid item xs={ 6 }>
|
|
89
|
-
<ControlLabel>{ label }</ControlLabel>
|
|
90
|
-
</Grid>
|
|
91
|
-
<Grid item xs={ 6 }>
|
|
92
|
-
<EqualValuesControl
|
|
93
|
-
value={ actualValue }
|
|
94
|
-
setValue={ setEqualValues }
|
|
95
|
-
iconButton={
|
|
96
|
-
<ToggleButton
|
|
97
|
-
size={ 'tiny' }
|
|
98
|
-
value={ 'check' }
|
|
99
|
-
sx={ { marginLeft: 'auto' } }
|
|
100
|
-
{ ...bindToggle( popupState ) }
|
|
101
|
-
selected={ popupState.isOpen }
|
|
102
|
-
>
|
|
103
|
-
{ icon }
|
|
104
|
-
</ToggleButton>
|
|
105
|
-
}
|
|
106
|
-
/>
|
|
107
|
-
</Grid>
|
|
108
|
-
</Grid>
|
|
109
|
-
<Popover
|
|
110
|
-
disablePortal
|
|
111
|
-
disableScrollLock
|
|
112
|
-
anchorOrigin={ {
|
|
113
|
-
vertical: 'bottom',
|
|
114
|
-
horizontal: 'right',
|
|
115
|
-
} }
|
|
116
|
-
transformOrigin={ {
|
|
117
|
-
vertical: 'top',
|
|
118
|
-
horizontal: 'right',
|
|
119
|
-
} }
|
|
120
|
-
{ ...bindPopover( popupState ) }
|
|
121
|
-
slotProps={ {
|
|
122
|
-
paper: { sx: { mt: 0.5, p: 2, pt: 1, width: controlRef.current?.getBoundingClientRect().width } },
|
|
123
|
-
} }
|
|
124
|
-
>
|
|
125
|
-
<Stack gap={ 1.5 }>
|
|
126
|
-
<Grid container spacing={ 2 } alignItems="center">
|
|
127
|
-
<NestedValueControl item={ items[ 0 ] } value={ actualValue } setNestedProp={ setNestedProp } />
|
|
128
|
-
<NestedValueControl item={ items[ 1 ] } value={ actualValue } setNestedProp={ setNestedProp } />
|
|
129
|
-
</Grid>
|
|
130
|
-
<Grid container spacing={ 2 } alignItems="center">
|
|
131
|
-
<NestedValueControl item={ items[ 3 ] } value={ actualValue } setNestedProp={ setNestedProp } />
|
|
132
|
-
<NestedValueControl item={ items[ 2 ] } value={ actualValue } setNestedProp={ setNestedProp } />
|
|
133
|
-
</Grid>
|
|
134
|
-
</Stack>
|
|
135
|
-
</Popover>
|
|
136
|
-
</>
|
|
137
|
-
);
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
const NestedValueControl = < TMultiPropType extends string, TPropValue extends MultiSizePropValue< TMultiPropType > >( {
|
|
141
|
-
item,
|
|
142
|
-
value,
|
|
143
|
-
setNestedProp,
|
|
144
|
-
}: {
|
|
145
|
-
item: Item< TMultiPropType, TPropValue >;
|
|
146
|
-
value: TPropValue[ 'value' ] | undefined;
|
|
147
|
-
setNestedProp: ( item: Item< TMultiPropType, TPropValue >, newValue: PropValue ) => void;
|
|
148
|
-
} ) => {
|
|
149
|
-
const { bind } = item;
|
|
150
|
-
|
|
151
|
-
const nestedValue = value?.[ bind ] ? value[ bind ] : undefined;
|
|
152
|
-
|
|
153
|
-
return (
|
|
154
|
-
<BoundPropProvider bind={ '' } setValue={ ( val ) => setNestedProp( item, val ) } value={ nestedValue }>
|
|
155
|
-
<Grid item xs={ 6 }>
|
|
156
|
-
<Grid container spacing={ 1 } alignItems="center">
|
|
157
|
-
<Grid item xs={ 12 }>
|
|
158
|
-
<ControlLabel>{ item.label }</ControlLabel>
|
|
159
|
-
</Grid>
|
|
160
|
-
<Grid item xs={ 12 }>
|
|
161
|
-
<SizeControl startIcon={ item.icon } />
|
|
162
|
-
</Grid>
|
|
163
|
-
</Grid>
|
|
164
|
-
</Grid>
|
|
165
|
-
</BoundPropProvider>
|
|
166
|
-
);
|
|
167
|
-
};
|
|
168
|
-
|
|
169
|
-
const EqualValuesControl = <
|
|
170
|
-
TMultiPropType extends string,
|
|
171
|
-
TPropValue extends MultiSizePropValue< TMultiPropType >[ 'value' ],
|
|
172
|
-
>( {
|
|
173
|
-
value,
|
|
174
|
-
setValue,
|
|
175
|
-
iconButton,
|
|
176
|
-
}: {
|
|
177
|
-
value: TPropValue | undefined;
|
|
178
|
-
setValue: ( newValue: TPropValue ) => void;
|
|
179
|
-
iconButton: ReactNode;
|
|
180
|
-
} ) => {
|
|
181
|
-
const values = Object.values( value ?? {} ) as SizeControlValue[];
|
|
182
|
-
const isMixed = hasMixedSizes( values );
|
|
183
|
-
|
|
184
|
-
return (
|
|
185
|
-
<BoundPropProvider
|
|
186
|
-
bind={ '' }
|
|
187
|
-
setValue={ ( val ) => setValue( val as TPropValue ) }
|
|
188
|
-
value={ isMixed ? undefined : values[ 0 ] }
|
|
189
|
-
>
|
|
190
|
-
<Stack direction="row" alignItems="center" gap={ 1 }>
|
|
191
|
-
<SizeControl placeholder={ __( 'MIXED', 'elementor' ) } />
|
|
192
|
-
{ iconButton }
|
|
193
|
-
</Stack>
|
|
194
|
-
</BoundPropProvider>
|
|
195
|
-
);
|
|
196
|
-
};
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
import * as React from 'react';
|
|
2
|
-
import { __ } from '@wordpress/i18n';
|
|
3
|
-
import { BoundPropProvider, useBoundProp } from '../bound-prop-context';
|
|
4
|
-
import { Grid, Stack } from '@elementor/ui';
|
|
5
|
-
import { PropValue, ImagePropValue, SizePropValue, ImageSrcPropValue } from '@elementor/editor-props';
|
|
6
|
-
import { ImageMediaControl } from './image-media-control';
|
|
7
|
-
import { SelectControl } from './select-control';
|
|
8
|
-
import { createControl } from '../create-control';
|
|
9
|
-
import { ControlLabel } from '../../components/control-label';
|
|
10
|
-
|
|
11
|
-
type SetContextValue = ( v: PropValue ) => void;
|
|
12
|
-
|
|
13
|
-
export type ImageControlProps = {
|
|
14
|
-
sizes: { label: string; value: string }[];
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
export const ImageControl = createControl( ( props: ImageControlProps ) => {
|
|
18
|
-
const { value, setValue } = useBoundProp< ImagePropValue | undefined >();
|
|
19
|
-
const { src, size } = value?.value || {};
|
|
20
|
-
|
|
21
|
-
const setImageSrc = ( newValue: ImageSrcPropValue ) => {
|
|
22
|
-
setValue( {
|
|
23
|
-
$$type: 'image',
|
|
24
|
-
value: {
|
|
25
|
-
src: newValue,
|
|
26
|
-
size: size as SizePropValue,
|
|
27
|
-
},
|
|
28
|
-
} );
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
const setImageSize = ( newValue: SizePropValue ) => {
|
|
32
|
-
setValue( {
|
|
33
|
-
$$type: 'image',
|
|
34
|
-
value: {
|
|
35
|
-
src: src as ImageSrcPropValue,
|
|
36
|
-
size: newValue,
|
|
37
|
-
},
|
|
38
|
-
} );
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
return (
|
|
42
|
-
<Stack gap={ 2 }>
|
|
43
|
-
<BoundPropProvider value={ src } setValue={ setImageSrc as SetContextValue } bind={ 'src' }>
|
|
44
|
-
<ImageMediaControl />
|
|
45
|
-
</BoundPropProvider>
|
|
46
|
-
<BoundPropProvider value={ size } setValue={ setImageSize as SetContextValue } bind={ 'size' }>
|
|
47
|
-
<Grid container spacing={ 1 } alignItems="center">
|
|
48
|
-
<Grid item xs={ 6 }>
|
|
49
|
-
<ControlLabel> { __( 'Image Resolution', 'elementor' ) }</ControlLabel>
|
|
50
|
-
</Grid>
|
|
51
|
-
<Grid item xs={ 6 }>
|
|
52
|
-
<SelectControl options={ props.sizes } />
|
|
53
|
-
</Grid>
|
|
54
|
-
</Grid>
|
|
55
|
-
</BoundPropProvider>
|
|
56
|
-
</Stack>
|
|
57
|
-
);
|
|
58
|
-
} );
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
import * as React from 'react';
|
|
2
|
-
import { __ } from '@wordpress/i18n';
|
|
3
|
-
import { ImageSrcPropValue } from '@elementor/editor-props';
|
|
4
|
-
import { UploadIcon } from '@elementor/icons';
|
|
5
|
-
import { Button, Card, CardMedia, CardOverlay, Stack } from '@elementor/ui';
|
|
6
|
-
import { useWpMediaAttachment, useWpMediaFrame } from '@elementor/wp-media';
|
|
7
|
-
import { useBoundProp } from '../bound-prop-context';
|
|
8
|
-
import ControlActions from '../control-actions/control-actions';
|
|
9
|
-
import { createControl } from '../create-control';
|
|
10
|
-
|
|
11
|
-
export const ImageMediaControl = createControl( () => {
|
|
12
|
-
const { value, setValue } = useBoundProp< ImageSrcPropValue >();
|
|
13
|
-
const { id, url } = value?.value ?? {};
|
|
14
|
-
|
|
15
|
-
const { data: attachment } = useWpMediaAttachment( id?.value || null );
|
|
16
|
-
const src = attachment?.url ?? url;
|
|
17
|
-
|
|
18
|
-
const { open } = useWpMediaFrame( {
|
|
19
|
-
types: [ 'image' ],
|
|
20
|
-
multiple: false,
|
|
21
|
-
selected: id?.value || null,
|
|
22
|
-
onSelect: ( selectedAttachment ) => {
|
|
23
|
-
setValue( {
|
|
24
|
-
$$type: 'image-src',
|
|
25
|
-
value: {
|
|
26
|
-
id: {
|
|
27
|
-
$$type: 'image-attachment-id',
|
|
28
|
-
value: selectedAttachment.id,
|
|
29
|
-
},
|
|
30
|
-
url: null,
|
|
31
|
-
},
|
|
32
|
-
} );
|
|
33
|
-
},
|
|
34
|
-
} );
|
|
35
|
-
|
|
36
|
-
return (
|
|
37
|
-
<Card variant="outlined">
|
|
38
|
-
<CardMedia image={ src } sx={ { height: 150 } } />
|
|
39
|
-
<CardOverlay>
|
|
40
|
-
<ControlActions>
|
|
41
|
-
<Stack gap={ 0.5 }>
|
|
42
|
-
<Button
|
|
43
|
-
size="tiny"
|
|
44
|
-
color="inherit"
|
|
45
|
-
variant="outlined"
|
|
46
|
-
onClick={ () => open( { mode: 'browse' } ) }
|
|
47
|
-
>
|
|
48
|
-
{ __( 'Select Image', 'elementor' ) }
|
|
49
|
-
</Button>
|
|
50
|
-
<Button
|
|
51
|
-
size="tiny"
|
|
52
|
-
variant="text"
|
|
53
|
-
color="inherit"
|
|
54
|
-
startIcon={ <UploadIcon /> }
|
|
55
|
-
onClick={ () => open( { mode: 'upload' } ) }
|
|
56
|
-
>
|
|
57
|
-
{ __( 'Upload Image', 'elementor' ) }
|
|
58
|
-
</Button>
|
|
59
|
-
</Stack>
|
|
60
|
-
</ControlActions>
|
|
61
|
-
</CardOverlay>
|
|
62
|
-
</Card>
|
|
63
|
-
);
|
|
64
|
-
} );
|
|
@@ -1,139 +0,0 @@
|
|
|
1
|
-
import * as React from 'react';
|
|
2
|
-
import { __ } from '@wordpress/i18n';
|
|
3
|
-
import { Grid, Stack, ToggleButton } from '@elementor/ui';
|
|
4
|
-
import { PropValue, LinkedDimensionsPropValue } from '@elementor/editor-props';
|
|
5
|
-
import { DetachIcon, LinkIcon, SideBottomIcon, SideLeftIcon, SideRightIcon, SideTopIcon } from '@elementor/icons';
|
|
6
|
-
import { createControl } from '../create-control';
|
|
7
|
-
import { ControlLabel } from '../../components/control-label';
|
|
8
|
-
import { SizeControl } from './size-control';
|
|
9
|
-
import { BoundPropProvider, useBoundProp } from '../bound-prop-context';
|
|
10
|
-
|
|
11
|
-
export type Position = 'top' | 'right' | 'bottom' | 'left';
|
|
12
|
-
|
|
13
|
-
export const LinkedDimensionsControl = createControl( ( { label }: { label: string } ) => {
|
|
14
|
-
const { value, setValue } = useBoundProp< LinkedDimensionsPropValue >();
|
|
15
|
-
const { top, right, bottom, left, isLinked = true } = value?.value || {};
|
|
16
|
-
|
|
17
|
-
const setLinkedValue = ( position: Position, newValue: PropValue ) => {
|
|
18
|
-
const updatedValue = {
|
|
19
|
-
isLinked,
|
|
20
|
-
top: isLinked ? newValue : top,
|
|
21
|
-
right: isLinked ? newValue : right,
|
|
22
|
-
bottom: isLinked ? newValue : bottom,
|
|
23
|
-
left: isLinked ? newValue : left,
|
|
24
|
-
[ position ]: newValue,
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
setValue( {
|
|
28
|
-
$$type: 'linked-dimensions',
|
|
29
|
-
value: updatedValue,
|
|
30
|
-
} );
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
const toggleLinked = () => {
|
|
34
|
-
const updatedValue = {
|
|
35
|
-
isLinked: ! isLinked,
|
|
36
|
-
top,
|
|
37
|
-
right: ! isLinked ? top : right,
|
|
38
|
-
bottom: ! isLinked ? top : bottom,
|
|
39
|
-
left: ! isLinked ? top : left,
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
setValue( {
|
|
43
|
-
$$type: 'linked-dimensions',
|
|
44
|
-
value: updatedValue,
|
|
45
|
-
} );
|
|
46
|
-
};
|
|
47
|
-
|
|
48
|
-
const LinkedIcon = isLinked ? LinkIcon : DetachIcon;
|
|
49
|
-
|
|
50
|
-
return (
|
|
51
|
-
<>
|
|
52
|
-
<Stack direction="row" gap={ 2 }>
|
|
53
|
-
<ControlLabel>{ label }</ControlLabel>
|
|
54
|
-
<ToggleButton
|
|
55
|
-
aria-label={ __( 'Link Inputs', 'elementor' ) }
|
|
56
|
-
size={ 'tiny' }
|
|
57
|
-
value={ 'check' }
|
|
58
|
-
selected={ isLinked }
|
|
59
|
-
sx={ { marginLeft: 'auto' } }
|
|
60
|
-
onChange={ toggleLinked }
|
|
61
|
-
>
|
|
62
|
-
<LinkedIcon fontSize={ 'tiny' } />
|
|
63
|
-
</ToggleButton>
|
|
64
|
-
</Stack>
|
|
65
|
-
<Stack direction="row" gap={ 2 }>
|
|
66
|
-
<Grid container spacing={ 1 } alignItems="center">
|
|
67
|
-
<Grid item xs={ 12 }>
|
|
68
|
-
<ControlLabel>{ __( 'Top', 'elementor' ) }</ControlLabel>
|
|
69
|
-
</Grid>
|
|
70
|
-
<Grid item xs={ 12 }>
|
|
71
|
-
<Control
|
|
72
|
-
bind={ 'top' }
|
|
73
|
-
value={ top }
|
|
74
|
-
setValue={ setLinkedValue }
|
|
75
|
-
startIcon={ <SideTopIcon fontSize={ 'tiny' } /> }
|
|
76
|
-
/>
|
|
77
|
-
</Grid>
|
|
78
|
-
</Grid>
|
|
79
|
-
<Grid container spacing={ 1 } alignItems="center">
|
|
80
|
-
<Grid item xs={ 12 }>
|
|
81
|
-
<ControlLabel>{ __( 'Right', 'elementor' ) }</ControlLabel>
|
|
82
|
-
</Grid>
|
|
83
|
-
<Grid item xs={ 12 }>
|
|
84
|
-
<Control
|
|
85
|
-
bind={ 'right' }
|
|
86
|
-
value={ right }
|
|
87
|
-
setValue={ setLinkedValue }
|
|
88
|
-
startIcon={ <SideRightIcon fontSize={ 'tiny' } /> }
|
|
89
|
-
/>
|
|
90
|
-
</Grid>
|
|
91
|
-
</Grid>
|
|
92
|
-
</Stack>
|
|
93
|
-
<Stack direction="row" gap={ 2 }>
|
|
94
|
-
<Grid container spacing={ 1 } alignItems="center">
|
|
95
|
-
<Grid item xs={ 12 }>
|
|
96
|
-
<ControlLabel>{ __( 'Bottom', 'elementor' ) }</ControlLabel>
|
|
97
|
-
</Grid>
|
|
98
|
-
<Grid item xs={ 12 }>
|
|
99
|
-
<Control
|
|
100
|
-
bind={ 'bottom' }
|
|
101
|
-
value={ bottom }
|
|
102
|
-
setValue={ setLinkedValue }
|
|
103
|
-
startIcon={ <SideBottomIcon fontSize={ 'tiny' } /> }
|
|
104
|
-
/>
|
|
105
|
-
</Grid>
|
|
106
|
-
</Grid>
|
|
107
|
-
<Grid container spacing={ 1 } alignItems="center">
|
|
108
|
-
<Grid item xs={ 12 }>
|
|
109
|
-
<ControlLabel>{ __( 'Left', 'elementor' ) }</ControlLabel>
|
|
110
|
-
</Grid>
|
|
111
|
-
<Grid item xs={ 12 }>
|
|
112
|
-
<Control
|
|
113
|
-
bind={ 'left' }
|
|
114
|
-
value={ left }
|
|
115
|
-
setValue={ setLinkedValue }
|
|
116
|
-
startIcon={ <SideLeftIcon fontSize={ 'tiny' } /> }
|
|
117
|
-
/>
|
|
118
|
-
</Grid>
|
|
119
|
-
</Grid>
|
|
120
|
-
</Stack>
|
|
121
|
-
</>
|
|
122
|
-
);
|
|
123
|
-
} );
|
|
124
|
-
|
|
125
|
-
const Control = ( {
|
|
126
|
-
bind,
|
|
127
|
-
startIcon,
|
|
128
|
-
value,
|
|
129
|
-
setValue,
|
|
130
|
-
}: {
|
|
131
|
-
bind: Position;
|
|
132
|
-
value: PropValue;
|
|
133
|
-
startIcon: React.ReactNode;
|
|
134
|
-
setValue: ( bind: Position, newValue: PropValue ) => void;
|
|
135
|
-
} ) => (
|
|
136
|
-
<BoundPropProvider setValue={ ( newValue ) => setValue( bind, newValue ) } value={ value } bind={ bind }>
|
|
137
|
-
<SizeControl startIcon={ startIcon } />
|
|
138
|
-
</BoundPropProvider>
|
|
139
|
-
);
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import * as React from 'react';
|
|
2
|
-
import { TextField } from '@elementor/ui';
|
|
3
|
-
import { useBoundProp } from '../bound-prop-context';
|
|
4
|
-
import ControlActions from '../control-actions/control-actions';
|
|
5
|
-
import { createControl } from '../create-control';
|
|
6
|
-
|
|
7
|
-
const isEmptyOrNaN = ( value?: string | number ) =>
|
|
8
|
-
value === undefined || value === '' || Number.isNaN( Number( value ) );
|
|
9
|
-
|
|
10
|
-
export const NumberControl = createControl( ( { placeholder }: { placeholder?: string } ) => {
|
|
11
|
-
const { value, setValue } = useBoundProp< number | undefined >();
|
|
12
|
-
|
|
13
|
-
const handleChange = ( event: React.ChangeEvent< HTMLInputElement > ) => {
|
|
14
|
-
const eventValue: string = event.target.value;
|
|
15
|
-
setValue( isEmptyOrNaN( eventValue ) ? undefined : Number( eventValue ) );
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
return (
|
|
19
|
-
<ControlActions>
|
|
20
|
-
<TextField
|
|
21
|
-
size="tiny"
|
|
22
|
-
type="number"
|
|
23
|
-
value={ isEmptyOrNaN( value ) ? '' : value }
|
|
24
|
-
onChange={ handleChange }
|
|
25
|
-
placeholder={ placeholder }
|
|
26
|
-
/>
|
|
27
|
-
</ControlActions>
|
|
28
|
-
);
|
|
29
|
-
} );
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import * as React from 'react';
|
|
2
|
-
import { PropValue } from '@elementor/editor-props';
|
|
3
|
-
import { MenuItem, Select, SelectChangeEvent } from '@elementor/ui';
|
|
4
|
-
import { useBoundProp } from '../bound-prop-context';
|
|
5
|
-
import ControlActions from '../control-actions/control-actions';
|
|
6
|
-
import { createControl } from '../create-control';
|
|
7
|
-
|
|
8
|
-
type Props< T > = {
|
|
9
|
-
options: Array< { label: string; value: T; disabled?: boolean } >;
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
export const SelectControl = createControl( < T extends PropValue >( { options }: Props< T > ) => {
|
|
13
|
-
const { value, setValue } = useBoundProp< T >();
|
|
14
|
-
|
|
15
|
-
const handleChange = ( event: SelectChangeEvent< T > ) => {
|
|
16
|
-
setValue( event.target.value as T );
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
return (
|
|
20
|
-
<ControlActions>
|
|
21
|
-
<Select displayEmpty size="tiny" value={ value ?? '' } onChange={ handleChange } fullWidth>
|
|
22
|
-
{ options.map( ( { label, ...props } ) => (
|
|
23
|
-
<MenuItem key={ props.value } { ...props }>
|
|
24
|
-
{ label }
|
|
25
|
-
</MenuItem>
|
|
26
|
-
) ) }
|
|
27
|
-
</Select>
|
|
28
|
-
</ControlActions>
|
|
29
|
-
);
|
|
30
|
-
} );
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
import * as React from 'react';
|
|
2
|
-
import { SizePropValue, TransformablePropValue } from '@elementor/editor-props';
|
|
3
|
-
import { InputAdornment } from '@elementor/ui';
|
|
4
|
-
import { useBoundProp } from '../bound-prop-context';
|
|
5
|
-
import { useSyncExternalState } from '../hooks/use-sync-external-state';
|
|
6
|
-
import { SelectionEndAdornment, TextFieldInnerSelection } from '../components/text-field-inner-selection';
|
|
7
|
-
import ControlActions from '../control-actions/control-actions';
|
|
8
|
-
import { createControl } from '../create-control';
|
|
9
|
-
|
|
10
|
-
export type Unit = 'px' | '%' | 'em' | 'rem' | 'vw' | 'vh';
|
|
11
|
-
|
|
12
|
-
const defaultUnits: Unit[] = [ 'px', '%', 'em', 'rem', 'vw', 'vh' ];
|
|
13
|
-
|
|
14
|
-
export type SizeControlProps = {
|
|
15
|
-
placeholder?: string;
|
|
16
|
-
startIcon?: React.ReactNode;
|
|
17
|
-
units?: Unit[];
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
export type SizeControlValue = TransformablePropValue< 'size', { unit: Unit; size: number } >;
|
|
21
|
-
|
|
22
|
-
export const SizeControl = createControl( ( { units = defaultUnits, placeholder, startIcon }: SizeControlProps ) => {
|
|
23
|
-
const { value, setValue } = useBoundProp< SizePropValue | undefined >();
|
|
24
|
-
|
|
25
|
-
const [ state, setState ] = useSyncExternalState< SizePropValue >( {
|
|
26
|
-
external: value,
|
|
27
|
-
setExternal: setValue,
|
|
28
|
-
persistWhen: ( controlValue ) => !! controlValue?.value.size || controlValue?.value.size === 0,
|
|
29
|
-
fallback: ( controlValue ) => ( {
|
|
30
|
-
$$type: 'size',
|
|
31
|
-
value: { unit: controlValue?.value.unit || 'px', size: NaN },
|
|
32
|
-
} ),
|
|
33
|
-
} );
|
|
34
|
-
|
|
35
|
-
const handleUnitChange = ( unit: Unit ) => {
|
|
36
|
-
setState( ( prev ) => ( {
|
|
37
|
-
...prev,
|
|
38
|
-
value: {
|
|
39
|
-
...prev.value,
|
|
40
|
-
unit,
|
|
41
|
-
},
|
|
42
|
-
} ) );
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
const handleSizeChange = ( event: React.ChangeEvent< HTMLInputElement > ) => {
|
|
46
|
-
const { value: size } = event.target;
|
|
47
|
-
|
|
48
|
-
setState( ( prev ) => ( {
|
|
49
|
-
...prev,
|
|
50
|
-
value: {
|
|
51
|
-
...prev.value,
|
|
52
|
-
size: size || size === '0' ? parseFloat( size ) : NaN,
|
|
53
|
-
},
|
|
54
|
-
} ) );
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
return (
|
|
58
|
-
<ControlActions>
|
|
59
|
-
<TextFieldInnerSelection
|
|
60
|
-
endAdornment={
|
|
61
|
-
<SelectionEndAdornment options={ units } onClick={ handleUnitChange } value={ state.value.unit } />
|
|
62
|
-
}
|
|
63
|
-
placeholder={ placeholder }
|
|
64
|
-
startAdornment={ startIcon ?? <InputAdornment position="start">{ startIcon }</InputAdornment> }
|
|
65
|
-
type="number"
|
|
66
|
-
value={ Number.isNaN( state.value.size ) ? '' : state.value.size }
|
|
67
|
-
onChange={ handleSizeChange }
|
|
68
|
-
/>
|
|
69
|
-
</ControlActions>
|
|
70
|
-
);
|
|
71
|
-
} );
|
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
import * as React from 'react';
|
|
2
|
-
import { __ } from '@wordpress/i18n';
|
|
3
|
-
import { Grid, Stack } from '@elementor/ui';
|
|
4
|
-
import { createControl } from '../create-control';
|
|
5
|
-
import { SizeControl, Unit } from './size-control';
|
|
6
|
-
import { ControlLabel } from '../../components/control-label';
|
|
7
|
-
import { ColorControl } from './color-control';
|
|
8
|
-
import { PropValue, StrokePropValue, TransformablePropValue } from '@elementor/editor-props';
|
|
9
|
-
import { BoundPropProvider, useBoundProp } from '../bound-prop-context';
|
|
10
|
-
|
|
11
|
-
type SetContextValue = ( v: PropValue ) => void;
|
|
12
|
-
|
|
13
|
-
const defaultStrokeControlValue: StrokePropValue = {
|
|
14
|
-
$$type: 'stroke',
|
|
15
|
-
value: {
|
|
16
|
-
color: {
|
|
17
|
-
$$type: 'color',
|
|
18
|
-
value: '#000000',
|
|
19
|
-
},
|
|
20
|
-
width: {
|
|
21
|
-
$$type: 'size',
|
|
22
|
-
value: {
|
|
23
|
-
unit: 'px',
|
|
24
|
-
size: NaN,
|
|
25
|
-
},
|
|
26
|
-
},
|
|
27
|
-
},
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
const units: Unit[] = [ 'px', 'em', 'rem' ];
|
|
31
|
-
|
|
32
|
-
export const StrokeControl = createControl( () => {
|
|
33
|
-
const { value, setValue } = useBoundProp< StrokePropValue >( defaultStrokeControlValue );
|
|
34
|
-
|
|
35
|
-
const setStrokeWidth = ( newValue: TransformablePropValue< 'size', { unit: Unit; size: number } > ) => {
|
|
36
|
-
const updatedValue = {
|
|
37
|
-
...( value?.value ?? defaultStrokeControlValue.value ),
|
|
38
|
-
width: newValue,
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
setValue( {
|
|
42
|
-
$$type: 'stroke',
|
|
43
|
-
value: updatedValue,
|
|
44
|
-
} );
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
const setStrokeColor = ( newValue: TransformablePropValue< 'color', string > ) => {
|
|
48
|
-
const updatedValue = {
|
|
49
|
-
...( value?.value ?? defaultStrokeControlValue.value ),
|
|
50
|
-
color: newValue,
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
setValue( {
|
|
54
|
-
$$type: 'stroke',
|
|
55
|
-
value: updatedValue,
|
|
56
|
-
} );
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
return (
|
|
60
|
-
<Stack gap={ 1.5 }>
|
|
61
|
-
<Control
|
|
62
|
-
bind="width"
|
|
63
|
-
label={ __( 'Stroke Width', 'elementor' ) }
|
|
64
|
-
value={ value?.value.width ?? defaultStrokeControlValue.value.width }
|
|
65
|
-
setValue={ setStrokeWidth }
|
|
66
|
-
>
|
|
67
|
-
<SizeControl units={ units } />
|
|
68
|
-
</Control>
|
|
69
|
-
|
|
70
|
-
<Control
|
|
71
|
-
bind="color"
|
|
72
|
-
label={ __( 'Stroke Color', 'elementor' ) }
|
|
73
|
-
value={ value?.value.color ?? defaultStrokeControlValue.value.color }
|
|
74
|
-
setValue={ setStrokeColor }
|
|
75
|
-
>
|
|
76
|
-
<ColorControl />
|
|
77
|
-
</Control>
|
|
78
|
-
</Stack>
|
|
79
|
-
);
|
|
80
|
-
} );
|
|
81
|
-
|
|
82
|
-
const Control = < T extends PropValue >( {
|
|
83
|
-
bind,
|
|
84
|
-
value,
|
|
85
|
-
setValue,
|
|
86
|
-
label,
|
|
87
|
-
children,
|
|
88
|
-
}: {
|
|
89
|
-
bind: string;
|
|
90
|
-
value: T;
|
|
91
|
-
setValue: ( v: T ) => void;
|
|
92
|
-
label: string;
|
|
93
|
-
children: React.ReactNode;
|
|
94
|
-
} ) => (
|
|
95
|
-
<BoundPropProvider bind={ bind } value={ value } setValue={ setValue as SetContextValue }>
|
|
96
|
-
<Grid container spacing={ 1 } alignItems="center">
|
|
97
|
-
<Grid item xs={ 6 }>
|
|
98
|
-
<ControlLabel>{ label }</ControlLabel>
|
|
99
|
-
</Grid>
|
|
100
|
-
<Grid item xs={ 6 }>
|
|
101
|
-
{ children }
|
|
102
|
-
</Grid>
|
|
103
|
-
</Grid>
|
|
104
|
-
</BoundPropProvider>
|
|
105
|
-
);
|