@elementor/editor-controls 1.3.0 → 3.32.0-20
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 +18 -0
- package/dist/index.d.mts +104 -26
- package/dist/index.d.ts +104 -26
- package/dist/index.js +2271 -1119
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2147 -990
- package/dist/index.mjs.map +1 -1
- package/package.json +18 -18
- package/src/components/control-toggle-button-group.tsx +78 -14
- package/src/components/floating-bar.tsx +45 -0
- package/src/components/item-selector.tsx +168 -0
- package/src/components/repeater.tsx +23 -12
- package/src/components/restricted-link-infotip.tsx +76 -0
- package/src/components/size-control/size-input.tsx +4 -3
- package/src/components/size-control/text-field-inner-selection.tsx +60 -14
- package/src/components/text-field-popover.tsx +30 -7
- package/src/components/unstable-repeater/actions/add-item-action.tsx +50 -0
- package/src/components/unstable-repeater/actions/disable-item-action.tsx +39 -0
- package/src/components/unstable-repeater/actions/duplicate-item-action.tsx +32 -0
- package/src/components/unstable-repeater/actions/remove-item-action.tsx +27 -0
- package/src/components/unstable-repeater/context/repeater-context.tsx +137 -0
- package/src/components/unstable-repeater/header/header.tsx +23 -0
- package/src/components/unstable-repeater/index.ts +5 -0
- package/src/components/unstable-repeater/items/edit-item-popover.tsx +28 -0
- package/src/components/unstable-repeater/items/item.tsx +71 -0
- package/src/components/unstable-repeater/items/items-container.tsx +49 -0
- package/src/components/unstable-repeater/items/use-popover.tsx +26 -0
- package/src/{locations.ts → components/unstable-repeater/locations.ts} +9 -1
- package/src/components/unstable-repeater/types.ts +26 -0
- package/src/components/unstable-repeater/unstable-repeater.tsx +24 -0
- package/src/control-actions/control-actions.tsx +3 -20
- package/src/control-replacements.tsx +41 -0
- package/src/controls/background-control/background-control.tsx +1 -8
- package/src/controls/background-control/background-overlay/background-overlay-repeater-control.tsx +17 -16
- package/src/controls/color-control.tsx +12 -1
- package/src/controls/equal-unequal-sizes-control.tsx +2 -9
- package/src/controls/filter-control/drop-shadow-item-content.tsx +67 -0
- package/src/controls/filter-control/drop-shadow-item-label.tsx +20 -0
- package/src/controls/filter-repeater-control.tsx +214 -88
- package/src/controls/font-family-control/font-family-control.tsx +22 -10
- package/src/controls/key-value-control.tsx +64 -50
- package/src/controls/link-control.tsx +8 -91
- package/src/controls/linked-dimensions-control.tsx +3 -16
- package/src/controls/number-control.tsx +10 -1
- package/src/controls/position-control.tsx +4 -16
- package/src/controls/repeatable-control.tsx +56 -34
- package/src/controls/select-control.tsx +7 -2
- package/src/controls/selection-size-control.tsx +74 -0
- package/src/controls/size-control.tsx +189 -121
- package/src/controls/stroke-control.tsx +2 -2
- package/src/controls/text-control.tsx +33 -18
- package/src/controls/toggle-control.tsx +3 -2
- package/src/controls/transform-control/functions/axis-row.tsx +4 -2
- package/src/controls/transform-control/functions/move.tsx +2 -1
- package/src/controls/transform-control/functions/rotate.tsx +48 -0
- package/src/controls/transform-control/functions/scale-axis-row.tsx +32 -0
- package/src/controls/transform-control/functions/scale.tsx +45 -0
- package/src/controls/transform-control/functions/skew.tsx +43 -0
- package/src/controls/transform-control/transform-content.tsx +60 -23
- package/src/controls/transform-control/transform-icon.tsx +10 -2
- package/src/controls/transform-control/transform-label.tsx +39 -2
- package/src/controls/transform-control/transform-repeater-control.tsx +2 -10
- package/src/controls/transform-control/types.ts +58 -0
- package/src/controls/transform-control/use-transform-tabs-history.tsx +107 -0
- package/src/controls/transition-control/data.ts +34 -0
- package/src/controls/transition-control/transition-repeater-control.tsx +63 -0
- package/src/controls/transition-control/transition-selector.tsx +88 -0
- package/src/controls/unstable-transform-control/unstable-transform-repeater-control.tsx +35 -0
- package/src/hooks/use-filtered-items-list.ts +24 -0
- package/src/hooks/use-size-extended-options.ts +1 -6
- package/src/index.ts +13 -3
- package/src/utils/size-control.ts +10 -2
- package/src/components/font-family-selector.tsx +0 -158
- package/src/hooks/use-filtered-font-families.ts +0 -24
|
@@ -1,67 +1,172 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { useRef } from 'react';
|
|
3
3
|
import {
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
type CreateOptions,
|
|
5
|
+
cssFilterFunctionPropUtil,
|
|
6
6
|
type FilterItemPropValue,
|
|
7
7
|
filterPropTypeUtil,
|
|
8
8
|
type PropKey,
|
|
9
|
-
type PropTypeUtil,
|
|
10
9
|
type SizePropValue,
|
|
11
10
|
} from '@elementor/editor-props';
|
|
12
|
-
import {
|
|
13
|
-
import { Box, Grid
|
|
11
|
+
import { backdropFilterPropTypeUtil } from '@elementor/editor-props';
|
|
12
|
+
import { Box, Grid } from '@elementor/ui';
|
|
14
13
|
import { __ } from '@wordpress/i18n';
|
|
15
14
|
|
|
16
15
|
import { PropKeyProvider, PropProvider, useBoundProp } from '../bound-prop-context';
|
|
17
|
-
import {
|
|
16
|
+
import { ControlFormLabel } from '../components/control-form-label';
|
|
18
17
|
import { PopoverContent } from '../components/popover-content';
|
|
19
18
|
import { PopoverGridContainer } from '../components/popover-grid-container';
|
|
20
|
-
import { Repeater } from '../components/repeater';
|
|
19
|
+
import { type CollectionPropUtil, Repeater } from '../components/repeater';
|
|
21
20
|
import { createControl } from '../create-control';
|
|
22
|
-
import {
|
|
23
|
-
import {
|
|
21
|
+
import { type LengthUnit, lengthUnits, type Unit } from '../utils/size-control';
|
|
22
|
+
import { DropShadowItemContent } from './filter-control/drop-shadow-item-content';
|
|
23
|
+
import { DropShadowItemLabel } from './filter-control/drop-shadow-item-label';
|
|
24
|
+
import { SelectControl } from './select-control';
|
|
25
|
+
import { SizeControl, type SizeControlProps } from './size-control';
|
|
24
26
|
|
|
25
|
-
type FilterType = FilterItemPropValue[ '
|
|
26
|
-
type FilterValue = FilterItemPropValue[ 'value' ];
|
|
27
|
+
type FilterType = FilterItemPropValue[ 'value' ][ 'func' ];
|
|
27
28
|
|
|
28
|
-
const
|
|
29
|
+
const DEFAULT_FILTER = 'blur';
|
|
29
30
|
|
|
30
31
|
type FilterItemConfig = {
|
|
31
|
-
defaultValue:
|
|
32
|
+
defaultValue: FilterItemPropValue;
|
|
32
33
|
name: string;
|
|
33
34
|
valueName: string;
|
|
34
|
-
propType: PropTypeUtil< FilterValue, FilterValue >;
|
|
35
35
|
units?: Exclude< SizePropValue[ 'value' ][ 'unit' ], 'custom' | 'auto' >[];
|
|
36
|
+
sizeVariant?: SizeControlProps[ 'variant' ];
|
|
36
37
|
};
|
|
37
38
|
|
|
38
|
-
const filterConfig: Record<
|
|
39
|
+
const filterConfig: Record< string, FilterItemConfig > = {
|
|
39
40
|
blur: {
|
|
40
|
-
defaultValue: {
|
|
41
|
+
defaultValue: {
|
|
42
|
+
$$type: 'css-filter-func',
|
|
43
|
+
value: {
|
|
44
|
+
func: { $$type: 'string', value: 'blur' },
|
|
45
|
+
args: { $$type: 'size', value: { size: 0, unit: 'px' } },
|
|
46
|
+
},
|
|
47
|
+
},
|
|
41
48
|
name: __( 'Blur', 'elementor' ),
|
|
42
49
|
valueName: __( 'Radius', 'elementor' ),
|
|
43
|
-
|
|
44
|
-
units: defaultUnits.filter( ( unit ) => unit !== '%' ),
|
|
50
|
+
units: lengthUnits.filter( ( unit ) => unit !== '%' ),
|
|
45
51
|
},
|
|
46
52
|
brightness: {
|
|
47
|
-
defaultValue: {
|
|
53
|
+
defaultValue: {
|
|
54
|
+
$$type: 'css-filter-func',
|
|
55
|
+
value: {
|
|
56
|
+
func: { $$type: 'string', value: 'brightness' },
|
|
57
|
+
args: { $$type: 'size', value: { size: 100, unit: '%' } },
|
|
58
|
+
},
|
|
59
|
+
},
|
|
48
60
|
name: __( 'Brightness', 'elementor' ),
|
|
49
61
|
valueName: __( 'Amount', 'elementor' ),
|
|
50
|
-
propType: brightnessFilterPropTypeUtil,
|
|
51
62
|
units: [ '%' ],
|
|
52
63
|
},
|
|
64
|
+
contrast: {
|
|
65
|
+
defaultValue: {
|
|
66
|
+
$$type: 'css-filter-func',
|
|
67
|
+
value: {
|
|
68
|
+
func: { $$type: 'string', value: 'contrast' },
|
|
69
|
+
args: { $$type: 'size', value: { size: 100, unit: '%' } },
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
name: __( 'Contrast', 'elementor' ),
|
|
73
|
+
valueName: __( 'Amount', 'elementor' ),
|
|
74
|
+
units: [ '%' ],
|
|
75
|
+
},
|
|
76
|
+
'hue-rotate': {
|
|
77
|
+
defaultValue: {
|
|
78
|
+
$$type: 'css-filter-func',
|
|
79
|
+
value: {
|
|
80
|
+
func: { $$type: 'string', value: 'hue-rotate' },
|
|
81
|
+
args: { $$type: 'size', value: { size: 0, unit: 'deg' } },
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
name: __( 'Hue Rotate', 'elementor' ),
|
|
85
|
+
valueName: __( 'Angle', 'elementor' ),
|
|
86
|
+
units: [ 'deg', 'rad', 'grad', 'turn' ],
|
|
87
|
+
},
|
|
88
|
+
saturate: {
|
|
89
|
+
defaultValue: {
|
|
90
|
+
$$type: 'css-filter-func',
|
|
91
|
+
value: {
|
|
92
|
+
func: { $$type: 'string', value: 'saturate' },
|
|
93
|
+
args: { $$type: 'size', value: { size: 100, unit: '%' } },
|
|
94
|
+
},
|
|
95
|
+
},
|
|
96
|
+
name: __( 'Saturate', 'elementor' ),
|
|
97
|
+
valueName: __( 'Amount', 'elementor' ),
|
|
98
|
+
units: [ '%' ],
|
|
99
|
+
},
|
|
100
|
+
grayscale: {
|
|
101
|
+
defaultValue: {
|
|
102
|
+
$$type: 'css-filter-func',
|
|
103
|
+
value: {
|
|
104
|
+
func: { $$type: 'string', value: 'grayscale' },
|
|
105
|
+
args: { $$type: 'size', value: { size: 0, unit: '%' } },
|
|
106
|
+
},
|
|
107
|
+
},
|
|
108
|
+
name: __( 'Grayscale', 'elementor' ),
|
|
109
|
+
valueName: __( 'Amount', 'elementor' ),
|
|
110
|
+
units: [ '%' ],
|
|
111
|
+
},
|
|
112
|
+
invert: {
|
|
113
|
+
defaultValue: {
|
|
114
|
+
$$type: 'css-filter-func',
|
|
115
|
+
value: {
|
|
116
|
+
func: { $$type: 'string', value: 'invert' },
|
|
117
|
+
args: { $$type: 'size', value: { size: 0, unit: '%' } },
|
|
118
|
+
},
|
|
119
|
+
},
|
|
120
|
+
name: __( 'Invert', 'elementor' ),
|
|
121
|
+
valueName: __( 'Amount', 'elementor' ),
|
|
122
|
+
units: [ '%' ],
|
|
123
|
+
},
|
|
124
|
+
sepia: {
|
|
125
|
+
defaultValue: {
|
|
126
|
+
$$type: 'css-filter-func',
|
|
127
|
+
value: {
|
|
128
|
+
func: { $$type: 'string', value: 'sepia' },
|
|
129
|
+
args: { $$type: 'size', value: { size: 0, unit: '%' } },
|
|
130
|
+
},
|
|
131
|
+
},
|
|
132
|
+
name: __( 'Sepia', 'elementor' ),
|
|
133
|
+
valueName: __( 'Amount', 'elementor' ),
|
|
134
|
+
units: [ '%' ],
|
|
135
|
+
},
|
|
136
|
+
'drop-shadow': {
|
|
137
|
+
defaultValue: {
|
|
138
|
+
$$type: 'css-filter-func',
|
|
139
|
+
value: {
|
|
140
|
+
func: { $$type: 'string', value: 'drop-shadow' },
|
|
141
|
+
args: {
|
|
142
|
+
$$type: 'drop-shadow',
|
|
143
|
+
value: {
|
|
144
|
+
xAxis: { $$type: 'size', value: { size: 0, unit: 'px' } },
|
|
145
|
+
yAxis: { $$type: 'size', value: { size: 0, unit: 'px' } },
|
|
146
|
+
blur: { $$type: 'size', value: { size: 10, unit: 'px' } },
|
|
147
|
+
color: { $$type: 'color', value: 'rgba(0, 0, 0, 1)' },
|
|
148
|
+
},
|
|
149
|
+
},
|
|
150
|
+
},
|
|
151
|
+
},
|
|
152
|
+
name: __( 'Drop shadow', 'elementor' ),
|
|
153
|
+
valueName: __( 'Drop-shadow', 'elementor' ),
|
|
154
|
+
units: lengthUnits.filter( ( unit ) => unit !== '%' ),
|
|
155
|
+
},
|
|
53
156
|
};
|
|
54
157
|
|
|
55
|
-
const filterKeys = Object.keys( filterConfig )
|
|
56
|
-
|
|
57
|
-
const singleSizeFilterNames = filterKeys.filter( ( name ) => {
|
|
58
|
-
const filter = filterConfig[ name as FilterType ].defaultValue;
|
|
158
|
+
const filterKeys = Object.keys( filterConfig );
|
|
59
159
|
|
|
60
|
-
|
|
61
|
-
|
|
160
|
+
const isSingleSize = ( key: string ): boolean => {
|
|
161
|
+
return ! [ 'drop-shadow' ].includes( key );
|
|
162
|
+
};
|
|
62
163
|
|
|
63
|
-
export const FilterRepeaterControl = createControl( () => {
|
|
64
|
-
const
|
|
164
|
+
export const FilterRepeaterControl = createControl( ( { filterPropName = 'filter' }: { filterPropName?: string } ) => {
|
|
165
|
+
const [ propUtil, label ] =
|
|
166
|
+
filterPropName === 'backdrop-filter'
|
|
167
|
+
? [ backdropFilterPropTypeUtil, __( 'Backdrop Filters', 'elementor' ) ]
|
|
168
|
+
: [ filterPropTypeUtil, __( 'Filters', 'elementor' ) ];
|
|
169
|
+
const { propType, value: filterValues, setValue, disabled } = useBoundProp( propUtil );
|
|
65
170
|
|
|
66
171
|
return (
|
|
67
172
|
<PropProvider propType={ propType } value={ filterValues } setValue={ setValue }>
|
|
@@ -70,15 +175,13 @@ export const FilterRepeaterControl = createControl( () => {
|
|
|
70
175
|
disabled={ disabled }
|
|
71
176
|
values={ filterValues ?? [] }
|
|
72
177
|
setValues={ setValue }
|
|
73
|
-
label={
|
|
178
|
+
label={ label }
|
|
179
|
+
collectionPropUtil={ propUtil }
|
|
74
180
|
itemSettings={ {
|
|
75
181
|
Icon: ItemIcon,
|
|
76
182
|
Label: ItemLabel,
|
|
77
183
|
Content: ItemContent,
|
|
78
|
-
initialValues:
|
|
79
|
-
$$type: DEFAULT_FILTER_KEY,
|
|
80
|
-
value: filterConfig[ DEFAULT_FILTER_KEY ].defaultValue,
|
|
81
|
-
} as FilterItemPropValue,
|
|
184
|
+
initialValues: filterConfig[ DEFAULT_FILTER ].defaultValue,
|
|
82
185
|
} }
|
|
83
186
|
/>
|
|
84
187
|
</PropProvider>
|
|
@@ -87,21 +190,23 @@ export const FilterRepeaterControl = createControl( () => {
|
|
|
87
190
|
|
|
88
191
|
const ItemIcon = () => <></>;
|
|
89
192
|
|
|
90
|
-
const ItemLabel = (
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
193
|
+
const ItemLabel = ( { value }: { value: FilterItemPropValue } ) => {
|
|
194
|
+
return isSingleSize( value.value.func.value ?? '' ) ? (
|
|
195
|
+
<SingleSizeItemLabel value={ value } />
|
|
196
|
+
) : (
|
|
197
|
+
<DropShadowItemLabel value={ value } />
|
|
198
|
+
);
|
|
94
199
|
};
|
|
95
200
|
|
|
96
201
|
const SingleSizeItemLabel = ( { value }: { value: FilterItemPropValue } ) => {
|
|
97
|
-
const {
|
|
98
|
-
const
|
|
99
|
-
|
|
100
|
-
const { unit, size } =
|
|
202
|
+
const { func, args } = value.value;
|
|
203
|
+
const defaultUnit =
|
|
204
|
+
( filterConfig[ func.value ?? '' ].defaultValue.value.args as SizePropValue ).value.unit ?? lengthUnits[ 0 ];
|
|
205
|
+
const { unit, size } = ( args as SizePropValue ).value ?? { unit: defaultUnit, size: 0 };
|
|
101
206
|
|
|
102
207
|
const label = (
|
|
103
208
|
<Box component="span" style={ { textTransform: 'capitalize' } }>
|
|
104
|
-
{ value
|
|
209
|
+
{ func.value ?? '' }:
|
|
105
210
|
</Box>
|
|
106
211
|
);
|
|
107
212
|
|
|
@@ -113,74 +218,95 @@ const SingleSizeItemLabel = ( { value }: { value: FilterItemPropValue } ) => {
|
|
|
113
218
|
);
|
|
114
219
|
};
|
|
115
220
|
|
|
116
|
-
const ItemContent = ( {
|
|
117
|
-
|
|
221
|
+
const ItemContent = ( {
|
|
222
|
+
bind,
|
|
223
|
+
collectionPropUtil,
|
|
224
|
+
anchorEl,
|
|
225
|
+
}: {
|
|
226
|
+
bind: PropKey;
|
|
227
|
+
collectionPropUtil?: CollectionPropUtil< FilterItemPropValue >;
|
|
228
|
+
anchorEl?: HTMLElement | null;
|
|
229
|
+
} ) => {
|
|
230
|
+
const { value: filterValues = [] } = useBoundProp( collectionPropUtil ?? filterPropTypeUtil );
|
|
118
231
|
const itemIndex = parseInt( bind, 10 );
|
|
119
232
|
const item = filterValues?.[ itemIndex ];
|
|
233
|
+
return item ? (
|
|
234
|
+
<PropKeyProvider bind={ bind }>
|
|
235
|
+
<PropContent item={ item } anchorEl={ anchorEl } />
|
|
236
|
+
</PropKeyProvider>
|
|
237
|
+
) : null;
|
|
238
|
+
};
|
|
120
239
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
const filterType = e.target.value as FilterType;
|
|
240
|
+
const PropContent = ( { item, anchorEl }: { item: FilterItemPropValue; anchorEl?: HTMLElement | null } ) => {
|
|
241
|
+
const propContext = useBoundProp( cssFilterFunctionPropUtil );
|
|
124
242
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
243
|
+
const handleValueChange = (
|
|
244
|
+
changedValue: FilterItemPropValue[ 'value' ],
|
|
245
|
+
options?: CreateOptions,
|
|
246
|
+
meta?: { bind?: PropKey }
|
|
247
|
+
) => {
|
|
248
|
+
let newValue = structuredClone( changedValue );
|
|
249
|
+
const newFuncName = newValue?.func.value ?? '';
|
|
250
|
+
if ( meta?.bind === 'func' ) {
|
|
251
|
+
newValue = structuredClone( filterConfig[ newFuncName ].defaultValue.value );
|
|
252
|
+
}
|
|
129
253
|
|
|
130
|
-
|
|
254
|
+
if ( ! newValue.args ) {
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
propContext.setValue( newValue );
|
|
131
258
|
};
|
|
132
259
|
|
|
133
260
|
return (
|
|
134
|
-
<
|
|
261
|
+
<PropProvider { ...propContext } setValue={ handleValueChange }>
|
|
135
262
|
<PopoverContent p={ 1.5 }>
|
|
136
263
|
<PopoverGridContainer>
|
|
137
264
|
<Grid item xs={ 6 }>
|
|
138
|
-
<
|
|
265
|
+
<ControlFormLabel>{ __( 'Filter', 'elementor' ) }</ControlFormLabel>
|
|
139
266
|
</Grid>
|
|
140
267
|
<Grid item xs={ 6 }>
|
|
141
|
-
<
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
<MenuListItem key={ filterKey } value={ filterKey }>
|
|
150
|
-
{ filterConfig[ filterKey ].name }
|
|
151
|
-
</MenuListItem>
|
|
152
|
-
) ) }
|
|
153
|
-
</Select>
|
|
268
|
+
<PropKeyProvider bind="func">
|
|
269
|
+
<SelectControl
|
|
270
|
+
options={ filterKeys.map( ( filterKey ) => ( {
|
|
271
|
+
label: filterConfig[ filterKey ].name,
|
|
272
|
+
value: filterKey,
|
|
273
|
+
} ) ) }
|
|
274
|
+
/>
|
|
275
|
+
</PropKeyProvider>
|
|
154
276
|
</Grid>
|
|
155
277
|
</PopoverGridContainer>
|
|
156
|
-
<
|
|
278
|
+
<PropKeyProvider bind="args">
|
|
279
|
+
<Content filterType={ item?.value.func } anchorEl={ anchorEl } />
|
|
280
|
+
</PropKeyProvider>
|
|
157
281
|
</PopoverContent>
|
|
158
|
-
</
|
|
282
|
+
</PropProvider>
|
|
159
283
|
);
|
|
160
284
|
};
|
|
161
285
|
|
|
162
|
-
const Content = ( { filterType }: { filterType: FilterType } ) => {
|
|
163
|
-
|
|
286
|
+
const Content = ( { filterType, anchorEl }: { filterType: FilterType; anchorEl?: HTMLElement | null } ) => {
|
|
287
|
+
const filterName = filterType?.value || DEFAULT_FILTER;
|
|
288
|
+
const filterItemConfig = filterConfig[ filterName ];
|
|
289
|
+
const { units = [] } = filterItemConfig;
|
|
290
|
+
|
|
291
|
+
return isSingleSize( filterName ) ? (
|
|
292
|
+
<SingleSizeItemContent filterType={ filterName } />
|
|
293
|
+
) : (
|
|
294
|
+
<DropShadowItemContent units={ units as LengthUnit[] } anchorEl={ anchorEl } />
|
|
295
|
+
);
|
|
164
296
|
};
|
|
165
297
|
|
|
166
|
-
const SingleSizeItemContent = ( { filterType }: { filterType:
|
|
167
|
-
const {
|
|
168
|
-
const { $$type } = defaultValue;
|
|
169
|
-
const context = useBoundProp( propType );
|
|
298
|
+
const SingleSizeItemContent = ( { filterType }: { filterType: string } ) => {
|
|
299
|
+
const { valueName, defaultValue, units } = filterConfig[ filterType ];
|
|
170
300
|
const rowRef = useRef< HTMLDivElement >( null );
|
|
171
|
-
|
|
301
|
+
const defaultUnit = ( defaultValue.value.args as SizePropValue ).value.unit;
|
|
172
302
|
return (
|
|
173
|
-
<
|
|
174
|
-
<
|
|
175
|
-
<
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
</Grid>
|
|
182
|
-
</PopoverGridContainer>
|
|
183
|
-
</PropKeyProvider>
|
|
184
|
-
</PropProvider>
|
|
303
|
+
<PopoverGridContainer ref={ rowRef }>
|
|
304
|
+
<Grid item xs={ 6 }>
|
|
305
|
+
<ControlFormLabel>{ valueName }</ControlFormLabel>
|
|
306
|
+
</Grid>
|
|
307
|
+
<Grid item xs={ 6 }>
|
|
308
|
+
<SizeControl anchorRef={ rowRef } units={ units as LengthUnit[] } defaultUnit={ defaultUnit as Unit } />
|
|
309
|
+
</Grid>
|
|
310
|
+
</PopoverGridContainer>
|
|
185
311
|
);
|
|
186
312
|
};
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { stringPropTypeUtil } from '@elementor/editor-props';
|
|
3
|
-
import { ChevronDownIcon } from '@elementor/icons';
|
|
3
|
+
import { ChevronDownIcon, TextIcon } from '@elementor/icons';
|
|
4
4
|
import { bindPopover, bindTrigger, Popover, UnstableTag, usePopupState } from '@elementor/ui';
|
|
5
|
+
import { __ } from '@wordpress/i18n';
|
|
5
6
|
|
|
6
7
|
import { useBoundProp } from '../../bound-prop-context';
|
|
7
|
-
import {
|
|
8
|
+
import { ItemSelector } from '../../components/item-selector';
|
|
9
|
+
import { type Category } from '../../components/item-selector';
|
|
8
10
|
import ControlActions from '../../control-actions/control-actions';
|
|
9
11
|
import { createControl } from '../../create-control';
|
|
12
|
+
import { enqueueFont } from './enqueue-font';
|
|
10
13
|
|
|
11
14
|
export type FontCategory = {
|
|
12
15
|
label: string;
|
|
@@ -18,22 +21,26 @@ type FontFamilyControlProps = {
|
|
|
18
21
|
sectionWidth: number;
|
|
19
22
|
};
|
|
20
23
|
|
|
21
|
-
const SIZE = 'tiny';
|
|
22
|
-
|
|
23
24
|
export const FontFamilyControl = createControl( ( { fontFamilies, sectionWidth }: FontFamilyControlProps ) => {
|
|
24
25
|
const { value: fontFamily, setValue: setFontFamily, disabled, placeholder } = useBoundProp( stringPropTypeUtil );
|
|
25
26
|
|
|
26
27
|
const popoverState = usePopupState( { variant: 'popover' } );
|
|
27
|
-
|
|
28
28
|
const isShowingPlaceholder = ! fontFamily && placeholder;
|
|
29
29
|
|
|
30
|
+
const mapFontSubs = React.useMemo< Category[] >( () => {
|
|
31
|
+
return fontFamilies.map( ( { label, fonts } ) => ( {
|
|
32
|
+
label,
|
|
33
|
+
items: fonts,
|
|
34
|
+
} ) );
|
|
35
|
+
}, [ fontFamilies ] );
|
|
36
|
+
|
|
30
37
|
return (
|
|
31
38
|
<>
|
|
32
39
|
<ControlActions>
|
|
33
40
|
<UnstableTag
|
|
34
41
|
variant="outlined"
|
|
35
42
|
label={ fontFamily || placeholder }
|
|
36
|
-
endIcon={ <ChevronDownIcon fontSize=
|
|
43
|
+
endIcon={ <ChevronDownIcon fontSize="tiny" /> }
|
|
37
44
|
{ ...bindTrigger( popoverState ) }
|
|
38
45
|
fullWidth
|
|
39
46
|
disabled={ disabled }
|
|
@@ -49,6 +56,7 @@ export const FontFamilyControl = createControl( ( { fontFamilies, sectionWidth }
|
|
|
49
56
|
}
|
|
50
57
|
/>
|
|
51
58
|
</ControlActions>
|
|
59
|
+
|
|
52
60
|
<Popover
|
|
53
61
|
disablePortal
|
|
54
62
|
disableScrollLock
|
|
@@ -57,12 +65,16 @@ export const FontFamilyControl = createControl( ( { fontFamilies, sectionWidth }
|
|
|
57
65
|
sx={ { my: 1.5 } }
|
|
58
66
|
{ ...bindPopover( popoverState ) }
|
|
59
67
|
>
|
|
60
|
-
<
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
68
|
+
<ItemSelector
|
|
69
|
+
itemsList={ mapFontSubs }
|
|
70
|
+
selectedItem={ fontFamily }
|
|
71
|
+
onItemChange={ setFontFamily }
|
|
64
72
|
onClose={ popoverState.close }
|
|
65
73
|
sectionWidth={ sectionWidth }
|
|
74
|
+
title={ __( 'Font Family', 'elementor' ) }
|
|
75
|
+
itemStyle={ ( item ) => ( { fontFamily: item.value } ) }
|
|
76
|
+
onDebounce={ enqueueFont }
|
|
77
|
+
icon={ TextIcon as React.ElementType< { fontSize: string } > }
|
|
66
78
|
/>
|
|
67
79
|
</Popover>
|
|
68
80
|
</>
|
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
|
|
2
|
+
import { useMemo, useState } from 'react';
|
|
3
|
+
import {
|
|
4
|
+
type CreateOptions,
|
|
5
|
+
isTransformable,
|
|
6
|
+
keyValuePropTypeUtil,
|
|
7
|
+
type PropKey,
|
|
8
|
+
type Props,
|
|
9
|
+
stringPropTypeUtil,
|
|
10
|
+
} from '@elementor/editor-props';
|
|
11
|
+
import { FormHelperText, FormLabel, Grid } from '@elementor/ui';
|
|
5
12
|
import { __ } from '@wordpress/i18n';
|
|
6
13
|
|
|
7
|
-
import { useBoundProp } from '../bound-prop-context';
|
|
8
|
-
import ControlActions from '../control-actions/control-actions';
|
|
14
|
+
import { PropKeyProvider, PropProvider, useBoundProp } from '../bound-prop-context';
|
|
9
15
|
import { createControl } from '../create-control';
|
|
10
|
-
|
|
11
|
-
type FieldType = 'key' | 'value';
|
|
16
|
+
import { TextControl } from './text-control';
|
|
12
17
|
|
|
13
18
|
type KeyValueControlProps = {
|
|
14
19
|
keyName?: string;
|
|
@@ -19,9 +24,9 @@ type KeyValueControlProps = {
|
|
|
19
24
|
};
|
|
20
25
|
|
|
21
26
|
export const KeyValueControl = createControl( ( props: KeyValueControlProps = {} ) => {
|
|
22
|
-
const { value, setValue } = useBoundProp( keyValuePropTypeUtil );
|
|
23
|
-
const [ keyError, setKeyError ] = useState< string
|
|
24
|
-
const [ valueError, setValueError ] = useState< string
|
|
27
|
+
const { value, setValue, ...propContext } = useBoundProp( keyValuePropTypeUtil );
|
|
28
|
+
const [ keyError, setKeyError ] = useState< string >( '' );
|
|
29
|
+
const [ valueError, setValueError ] = useState< string >( '' );
|
|
25
30
|
|
|
26
31
|
const [ sessionState, setSessionState ] = useState( {
|
|
27
32
|
key: value?.key?.value || '',
|
|
@@ -43,31 +48,48 @@ export const KeyValueControl = createControl( ( props: KeyValueControlProps = {}
|
|
|
43
48
|
const validate = ( newValue: string, fieldType: string ): boolean => {
|
|
44
49
|
if ( fieldType === 'key' && keyRegex ) {
|
|
45
50
|
const isValid = keyRegex.test( newValue );
|
|
46
|
-
setKeyError( isValid ?
|
|
51
|
+
setKeyError( isValid ? '' : errMsg );
|
|
52
|
+
|
|
47
53
|
return isValid;
|
|
48
54
|
} else if ( fieldType === 'value' && valueRegex ) {
|
|
49
55
|
const isValid = valueRegex.test( newValue );
|
|
50
|
-
setValueError( isValid ?
|
|
56
|
+
setValueError( isValid ? '' : errMsg );
|
|
57
|
+
|
|
51
58
|
return isValid;
|
|
52
59
|
}
|
|
60
|
+
|
|
53
61
|
return true;
|
|
54
62
|
};
|
|
55
63
|
|
|
56
|
-
const handleChange = (
|
|
57
|
-
const
|
|
64
|
+
const handleChange = ( newValue: Props, options?: CreateOptions, meta?: { bind?: PropKey } ) => {
|
|
65
|
+
const fieldType = meta?.bind;
|
|
66
|
+
|
|
67
|
+
if ( ! fieldType ) {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const newChangedValue = newValue[ fieldType ];
|
|
72
|
+
|
|
73
|
+
if ( isTransformable( newChangedValue ) && newChangedValue.$$type === 'dynamic' ) {
|
|
74
|
+
setValue( {
|
|
75
|
+
...value,
|
|
76
|
+
[ fieldType ]: newChangedValue,
|
|
77
|
+
} );
|
|
78
|
+
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const extractedValue = stringPropTypeUtil.extract( newChangedValue );
|
|
58
83
|
|
|
59
84
|
setSessionState( ( prev ) => ( {
|
|
60
85
|
...prev,
|
|
61
|
-
[ fieldType ]:
|
|
86
|
+
[ fieldType ]: extractedValue,
|
|
62
87
|
} ) );
|
|
63
88
|
|
|
64
|
-
if ( validate(
|
|
89
|
+
if ( extractedValue && validate( extractedValue, fieldType ) ) {
|
|
65
90
|
setValue( {
|
|
66
91
|
...value,
|
|
67
|
-
[ fieldType ]:
|
|
68
|
-
value: newValue,
|
|
69
|
-
$$type: 'string',
|
|
70
|
-
},
|
|
92
|
+
[ fieldType ]: newChangedValue,
|
|
71
93
|
} );
|
|
72
94
|
} else {
|
|
73
95
|
setValue( {
|
|
@@ -80,40 +102,32 @@ export const KeyValueControl = createControl( ( props: KeyValueControlProps = {}
|
|
|
80
102
|
}
|
|
81
103
|
};
|
|
82
104
|
|
|
83
|
-
const isKeyInvalid = keyError !== null;
|
|
84
|
-
const isValueInvalid = valueError !== null;
|
|
85
|
-
|
|
86
105
|
return (
|
|
87
|
-
<
|
|
106
|
+
<PropProvider { ...propContext } value={ value } setValue={ handleChange }>
|
|
88
107
|
<Grid container gap={ 1.5 }>
|
|
89
|
-
<Grid item xs={ 12 }>
|
|
90
|
-
<FormLabel size="tiny"
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
value={ sessionState.key }
|
|
98
|
-
onChange={ ( e: ChangeEvent< HTMLInputElement > ) => handleChange( e, 'key' ) }
|
|
99
|
-
error={ isKeyInvalid }
|
|
100
|
-
/>
|
|
101
|
-
{ isKeyInvalid && <FormHelperText error>{ keyError }</FormHelperText> }
|
|
108
|
+
<Grid item xs={ 12 } display="flex" flexDirection="column">
|
|
109
|
+
<FormLabel size="tiny" sx={ { pb: 1 } }>
|
|
110
|
+
{ keyLabel }
|
|
111
|
+
</FormLabel>
|
|
112
|
+
<PropKeyProvider bind={ 'key' }>
|
|
113
|
+
<TextControl inputValue={ sessionState.key } error={ !! keyError } />
|
|
114
|
+
</PropKeyProvider>
|
|
115
|
+
{ !! keyError && <FormHelperText error>{ keyError }</FormHelperText> }
|
|
102
116
|
</Grid>
|
|
103
|
-
<Grid item xs={ 12 }>
|
|
104
|
-
<FormLabel size="tiny"
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
{
|
|
117
|
+
<Grid item xs={ 12 } display="flex" flexDirection="column">
|
|
118
|
+
<FormLabel size="tiny" sx={ { pb: 1 } }>
|
|
119
|
+
{ valueLabel }
|
|
120
|
+
</FormLabel>
|
|
121
|
+
<PropKeyProvider bind={ 'value' }>
|
|
122
|
+
<TextControl
|
|
123
|
+
inputValue={ sessionState.value }
|
|
124
|
+
error={ !! valueError }
|
|
125
|
+
inputDisabled={ !! keyError }
|
|
126
|
+
/>
|
|
127
|
+
</PropKeyProvider>
|
|
128
|
+
{ !! valueError && <FormHelperText error>{ valueError }</FormHelperText> }
|
|
115
129
|
</Grid>
|
|
116
130
|
</Grid>
|
|
117
|
-
</
|
|
131
|
+
</PropProvider>
|
|
118
132
|
);
|
|
119
133
|
} );
|