@elementor/editor-controls 1.5.0 → 3.32.0-21
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 +0 -22
- package/dist/index.d.mts +95 -25
- package/dist/index.d.ts +95 -25
- package/dist/index.js +2045 -1041
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1962 -964
- 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/{font-family-selector.tsx → item-selector.tsx} +62 -50
- package/src/components/repeater.tsx +1 -1
- package/src/components/restricted-link-infotip.tsx +76 -0
- package/src/components/size-control/size-input.tsx +8 -7
- 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/equal-unequal-sizes-control.tsx +2 -9
- package/src/controls/filter-control/drop-shadow-item-content.tsx +4 -6
- package/src/controls/filter-control/drop-shadow-item-label.tsx +2 -2
- package/src/controls/filter-repeater-control.tsx +149 -110
- package/src/controls/font-family-control/font-family-control.tsx +22 -10
- package/src/controls/key-value-control.tsx +9 -6
- 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 +8 -5
- package/src/controls/select-control.tsx +7 -2
- package/src/controls/selection-size-control.tsx +74 -0
- package/src/controls/size-control.tsx +181 -126
- package/src/controls/stroke-control.tsx +2 -2
- 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 +12 -6
- package/src/hooks/use-filtered-font-families.ts +0 -24
|
@@ -1,127 +1,163 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { useRef } from 'react';
|
|
3
3
|
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
contrastFilterPropTypeUtil,
|
|
7
|
-
dropShadowFilterPropTypeUtil,
|
|
4
|
+
type CreateOptions,
|
|
5
|
+
cssFilterFunctionPropUtil,
|
|
8
6
|
type FilterItemPropValue,
|
|
9
7
|
filterPropTypeUtil,
|
|
10
|
-
grayscaleFilterPropTypeUtil,
|
|
11
|
-
hueRotateFilterPropTypeUtil,
|
|
12
|
-
invertFilterPropTypeUtil,
|
|
13
8
|
type PropKey,
|
|
14
|
-
type PropTypeUtil,
|
|
15
|
-
saturateFilterPropTypeUtil,
|
|
16
|
-
sepiaFilterPropTypeUtil,
|
|
17
9
|
type SizePropValue,
|
|
18
10
|
} from '@elementor/editor-props';
|
|
19
11
|
import { backdropFilterPropTypeUtil } from '@elementor/editor-props';
|
|
20
|
-
import {
|
|
21
|
-
import { Box, Grid, Select, type SelectChangeEvent } from '@elementor/ui';
|
|
12
|
+
import { Box, Grid } from '@elementor/ui';
|
|
22
13
|
import { __ } from '@wordpress/i18n';
|
|
23
14
|
|
|
24
15
|
import { PropKeyProvider, PropProvider, useBoundProp } from '../bound-prop-context';
|
|
25
|
-
import {
|
|
16
|
+
import { ControlFormLabel } from '../components/control-form-label';
|
|
26
17
|
import { PopoverContent } from '../components/popover-content';
|
|
27
18
|
import { PopoverGridContainer } from '../components/popover-grid-container';
|
|
28
19
|
import { type CollectionPropUtil, Repeater } from '../components/repeater';
|
|
29
20
|
import { createControl } from '../create-control';
|
|
30
|
-
import {
|
|
21
|
+
import { type LengthUnit, lengthUnits, type Unit } from '../utils/size-control';
|
|
31
22
|
import { DropShadowItemContent } from './filter-control/drop-shadow-item-content';
|
|
32
23
|
import { DropShadowItemLabel } from './filter-control/drop-shadow-item-label';
|
|
33
|
-
import {
|
|
24
|
+
import { SelectControl } from './select-control';
|
|
25
|
+
import { SizeControl, type SizeControlProps } from './size-control';
|
|
34
26
|
|
|
35
|
-
type FilterType = FilterItemPropValue[ '
|
|
36
|
-
type FilterValue = FilterItemPropValue[ 'value' ];
|
|
27
|
+
type FilterType = FilterItemPropValue[ 'value' ][ 'func' ];
|
|
37
28
|
|
|
38
|
-
const
|
|
29
|
+
const DEFAULT_FILTER = 'blur';
|
|
39
30
|
|
|
40
31
|
type FilterItemConfig = {
|
|
41
|
-
defaultValue:
|
|
32
|
+
defaultValue: FilterItemPropValue;
|
|
42
33
|
name: string;
|
|
43
34
|
valueName: string;
|
|
44
|
-
propType: PropTypeUtil< FilterValue, FilterValue >;
|
|
45
35
|
units?: Exclude< SizePropValue[ 'value' ][ 'unit' ], 'custom' | 'auto' >[];
|
|
36
|
+
sizeVariant?: SizeControlProps[ 'variant' ];
|
|
46
37
|
};
|
|
47
38
|
|
|
48
|
-
const filterConfig: Record<
|
|
39
|
+
const filterConfig: Record< string, FilterItemConfig > = {
|
|
49
40
|
blur: {
|
|
50
|
-
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
|
+
},
|
|
51
48
|
name: __( 'Blur', 'elementor' ),
|
|
52
49
|
valueName: __( 'Radius', 'elementor' ),
|
|
53
|
-
|
|
54
|
-
units: defaultUnits.filter( ( unit ) => unit !== '%' ),
|
|
50
|
+
units: lengthUnits.filter( ( unit ) => unit !== '%' ),
|
|
55
51
|
},
|
|
56
|
-
|
|
52
|
+
brightness: {
|
|
57
53
|
defaultValue: {
|
|
58
|
-
$$type: '
|
|
54
|
+
$$type: 'css-filter-func',
|
|
59
55
|
value: {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
blur: { $$type: 'size', value: { size: 10, unit: 'px' } },
|
|
63
|
-
color: { $$type: 'color', value: 'rgba(0, 0, 0, 1)' },
|
|
56
|
+
func: { $$type: 'string', value: 'brightness' },
|
|
57
|
+
args: { $$type: 'size', value: { size: 100, unit: '%' } },
|
|
64
58
|
},
|
|
65
59
|
},
|
|
66
|
-
name: __( 'Drop shadow', 'elementor' ),
|
|
67
|
-
valueName: __( 'Drop-shadow', 'elementor' ),
|
|
68
|
-
propType: dropShadowFilterPropTypeUtil,
|
|
69
|
-
units: defaultUnits.filter( ( unit ) => unit !== '%' ),
|
|
70
|
-
},
|
|
71
|
-
brightness: {
|
|
72
|
-
defaultValue: { $$type: 'amount', amount: { $$type: 'size', value: { size: 100, unit: '%' } } },
|
|
73
60
|
name: __( 'Brightness', 'elementor' ),
|
|
74
61
|
valueName: __( 'Amount', 'elementor' ),
|
|
75
|
-
propType: brightnessFilterPropTypeUtil,
|
|
76
62
|
units: [ '%' ],
|
|
77
63
|
},
|
|
78
64
|
contrast: {
|
|
79
|
-
defaultValue: {
|
|
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
|
+
},
|
|
80
72
|
name: __( 'Contrast', 'elementor' ),
|
|
81
73
|
valueName: __( 'Amount', 'elementor' ),
|
|
82
|
-
propType: contrastFilterPropTypeUtil,
|
|
83
74
|
units: [ '%' ],
|
|
84
75
|
},
|
|
85
76
|
'hue-rotate': {
|
|
86
|
-
defaultValue: {
|
|
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
|
+
},
|
|
87
84
|
name: __( 'Hue Rotate', 'elementor' ),
|
|
88
85
|
valueName: __( 'Angle', 'elementor' ),
|
|
89
|
-
propType: hueRotateFilterPropTypeUtil,
|
|
90
86
|
units: [ 'deg', 'rad', 'grad', 'turn' ],
|
|
91
87
|
},
|
|
92
88
|
saturate: {
|
|
93
|
-
defaultValue: {
|
|
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
|
+
},
|
|
94
96
|
name: __( 'Saturate', 'elementor' ),
|
|
95
97
|
valueName: __( 'Amount', 'elementor' ),
|
|
96
|
-
propType: saturateFilterPropTypeUtil,
|
|
97
98
|
units: [ '%' ],
|
|
98
99
|
},
|
|
99
100
|
grayscale: {
|
|
100
|
-
defaultValue: {
|
|
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
|
+
},
|
|
101
108
|
name: __( 'Grayscale', 'elementor' ),
|
|
102
109
|
valueName: __( 'Amount', 'elementor' ),
|
|
103
|
-
propType: grayscaleFilterPropTypeUtil,
|
|
104
110
|
units: [ '%' ],
|
|
105
111
|
},
|
|
106
112
|
invert: {
|
|
107
|
-
defaultValue: {
|
|
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
|
+
},
|
|
108
120
|
name: __( 'Invert', 'elementor' ),
|
|
109
121
|
valueName: __( 'Amount', 'elementor' ),
|
|
110
|
-
propType: invertFilterPropTypeUtil,
|
|
111
122
|
units: [ '%' ],
|
|
112
123
|
},
|
|
113
124
|
sepia: {
|
|
114
|
-
defaultValue: {
|
|
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
|
+
},
|
|
115
132
|
name: __( 'Sepia', 'elementor' ),
|
|
116
133
|
valueName: __( 'Amount', 'elementor' ),
|
|
117
|
-
propType: sepiaFilterPropTypeUtil,
|
|
118
134
|
units: [ '%' ],
|
|
119
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
|
+
},
|
|
120
156
|
};
|
|
121
157
|
|
|
122
|
-
const filterKeys = Object.keys( filterConfig )
|
|
158
|
+
const filterKeys = Object.keys( filterConfig );
|
|
123
159
|
|
|
124
|
-
const isSingleSize = ( key:
|
|
160
|
+
const isSingleSize = ( key: string ): boolean => {
|
|
125
161
|
return ! [ 'drop-shadow' ].includes( key );
|
|
126
162
|
};
|
|
127
163
|
|
|
@@ -145,10 +181,7 @@ export const FilterRepeaterControl = createControl( ( { filterPropName = 'filter
|
|
|
145
181
|
Icon: ItemIcon,
|
|
146
182
|
Label: ItemLabel,
|
|
147
183
|
Content: ItemContent,
|
|
148
|
-
initialValues:
|
|
149
|
-
$$type: DEFAULT_FILTER_KEY,
|
|
150
|
-
value: filterConfig[ DEFAULT_FILTER_KEY ].defaultValue,
|
|
151
|
-
} as FilterItemPropValue,
|
|
184
|
+
initialValues: filterConfig[ DEFAULT_FILTER ].defaultValue,
|
|
152
185
|
} }
|
|
153
186
|
/>
|
|
154
187
|
</PropProvider>
|
|
@@ -158,7 +191,7 @@ export const FilterRepeaterControl = createControl( ( { filterPropName = 'filter
|
|
|
158
191
|
const ItemIcon = () => <></>;
|
|
159
192
|
|
|
160
193
|
const ItemLabel = ( { value }: { value: FilterItemPropValue } ) => {
|
|
161
|
-
return isSingleSize( value
|
|
194
|
+
return isSingleSize( value.value.func.value ?? '' ) ? (
|
|
162
195
|
<SingleSizeItemLabel value={ value } />
|
|
163
196
|
) : (
|
|
164
197
|
<DropShadowItemLabel value={ value } />
|
|
@@ -166,14 +199,14 @@ const ItemLabel = ( { value }: { value: FilterItemPropValue } ) => {
|
|
|
166
199
|
};
|
|
167
200
|
|
|
168
201
|
const SingleSizeItemLabel = ( { value }: { value: FilterItemPropValue } ) => {
|
|
169
|
-
const {
|
|
170
|
-
const
|
|
171
|
-
|
|
172
|
-
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 };
|
|
173
206
|
|
|
174
207
|
const label = (
|
|
175
208
|
<Box component="span" style={ { textTransform: 'capitalize' } }>
|
|
176
|
-
{ value
|
|
209
|
+
{ func.value ?? '' }:
|
|
177
210
|
</Box>
|
|
178
211
|
);
|
|
179
212
|
|
|
@@ -194,80 +227,86 @@ const ItemContent = ( {
|
|
|
194
227
|
collectionPropUtil?: CollectionPropUtil< FilterItemPropValue >;
|
|
195
228
|
anchorEl?: HTMLElement | null;
|
|
196
229
|
} ) => {
|
|
197
|
-
const { value: filterValues
|
|
230
|
+
const { value: filterValues = [] } = useBoundProp( collectionPropUtil ?? filterPropTypeUtil );
|
|
198
231
|
const itemIndex = parseInt( bind, 10 );
|
|
199
232
|
const item = filterValues?.[ itemIndex ];
|
|
233
|
+
return item ? (
|
|
234
|
+
<PropKeyProvider bind={ bind }>
|
|
235
|
+
<PropContent item={ item } anchorEl={ anchorEl } />
|
|
236
|
+
</PropKeyProvider>
|
|
237
|
+
) : null;
|
|
238
|
+
};
|
|
200
239
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
const filterType = e.target.value as FilterType;
|
|
240
|
+
const PropContent = ( { item, anchorEl }: { item: FilterItemPropValue; anchorEl?: HTMLElement | null } ) => {
|
|
241
|
+
const propContext = useBoundProp( cssFilterFunctionPropUtil );
|
|
204
242
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
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
|
+
}
|
|
209
253
|
|
|
210
|
-
|
|
254
|
+
if ( ! newValue.args ) {
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
propContext.setValue( newValue );
|
|
211
258
|
};
|
|
212
259
|
|
|
213
260
|
return (
|
|
214
|
-
<
|
|
261
|
+
<PropProvider { ...propContext } setValue={ handleValueChange }>
|
|
215
262
|
<PopoverContent p={ 1.5 }>
|
|
216
263
|
<PopoverGridContainer>
|
|
217
264
|
<Grid item xs={ 6 }>
|
|
218
|
-
<
|
|
265
|
+
<ControlFormLabel>{ __( 'Filter', 'elementor' ) }</ControlFormLabel>
|
|
219
266
|
</Grid>
|
|
220
267
|
<Grid item xs={ 6 }>
|
|
221
|
-
<
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
<MenuListItem key={ filterKey } value={ filterKey }>
|
|
230
|
-
{ filterConfig[ filterKey ].name }
|
|
231
|
-
</MenuListItem>
|
|
232
|
-
) ) }
|
|
233
|
-
</Select>
|
|
268
|
+
<PropKeyProvider bind="func">
|
|
269
|
+
<SelectControl
|
|
270
|
+
options={ filterKeys.map( ( filterKey ) => ( {
|
|
271
|
+
label: filterConfig[ filterKey ].name,
|
|
272
|
+
value: filterKey,
|
|
273
|
+
} ) ) }
|
|
274
|
+
/>
|
|
275
|
+
</PropKeyProvider>
|
|
234
276
|
</Grid>
|
|
235
277
|
</PopoverGridContainer>
|
|
236
|
-
<
|
|
278
|
+
<PropKeyProvider bind="args">
|
|
279
|
+
<Content filterType={ item?.value.func } anchorEl={ anchorEl } />
|
|
280
|
+
</PropKeyProvider>
|
|
237
281
|
</PopoverContent>
|
|
238
|
-
</
|
|
282
|
+
</PropProvider>
|
|
239
283
|
);
|
|
240
284
|
};
|
|
241
285
|
|
|
242
286
|
const Content = ( { filterType, anchorEl }: { filterType: FilterType; anchorEl?: HTMLElement | null } ) => {
|
|
243
|
-
const
|
|
287
|
+
const filterName = filterType?.value || DEFAULT_FILTER;
|
|
288
|
+
const filterItemConfig = filterConfig[ filterName ];
|
|
289
|
+
const { units = [] } = filterItemConfig;
|
|
244
290
|
|
|
245
|
-
return isSingleSize(
|
|
246
|
-
<SingleSizeItemContent filterType={
|
|
291
|
+
return isSingleSize( filterName ) ? (
|
|
292
|
+
<SingleSizeItemContent filterType={ filterName } />
|
|
247
293
|
) : (
|
|
248
|
-
<DropShadowItemContent
|
|
294
|
+
<DropShadowItemContent units={ units as LengthUnit[] } anchorEl={ anchorEl } />
|
|
249
295
|
);
|
|
250
296
|
};
|
|
251
297
|
|
|
252
|
-
const SingleSizeItemContent = ( { filterType }: { filterType:
|
|
253
|
-
const {
|
|
254
|
-
const { $$type } = defaultValue;
|
|
255
|
-
const context = useBoundProp( propType );
|
|
298
|
+
const SingleSizeItemContent = ( { filterType }: { filterType: string } ) => {
|
|
299
|
+
const { valueName, defaultValue, units } = filterConfig[ filterType ];
|
|
256
300
|
const rowRef = useRef< HTMLDivElement >( null );
|
|
257
|
-
const defaultUnit = defaultValue
|
|
258
|
-
|
|
301
|
+
const defaultUnit = ( defaultValue.value.args as SizePropValue ).value.unit;
|
|
259
302
|
return (
|
|
260
|
-
<
|
|
261
|
-
<
|
|
262
|
-
<
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
</Grid>
|
|
269
|
-
</PopoverGridContainer>
|
|
270
|
-
</PropKeyProvider>
|
|
271
|
-
</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>
|
|
272
311
|
);
|
|
273
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
|
</>
|
|
@@ -105,21 +105,24 @@ export const KeyValueControl = createControl( ( props: KeyValueControlProps = {}
|
|
|
105
105
|
return (
|
|
106
106
|
<PropProvider { ...propContext } value={ value } setValue={ handleChange }>
|
|
107
107
|
<Grid container gap={ 1.5 }>
|
|
108
|
-
<Grid item xs={ 12 }>
|
|
109
|
-
<FormLabel size="tiny"
|
|
108
|
+
<Grid item xs={ 12 } display="flex" flexDirection="column">
|
|
109
|
+
<FormLabel size="tiny" sx={ { pb: 1 } }>
|
|
110
|
+
{ keyLabel }
|
|
111
|
+
</FormLabel>
|
|
110
112
|
<PropKeyProvider bind={ 'key' }>
|
|
111
|
-
<TextControl inputValue={ sessionState.key } error={ !! keyError }
|
|
113
|
+
<TextControl inputValue={ sessionState.key } error={ !! keyError } />
|
|
112
114
|
</PropKeyProvider>
|
|
113
115
|
{ !! keyError && <FormHelperText error>{ keyError }</FormHelperText> }
|
|
114
116
|
</Grid>
|
|
115
|
-
<Grid item xs={ 12 }>
|
|
116
|
-
<FormLabel size="tiny"
|
|
117
|
+
<Grid item xs={ 12 } display="flex" flexDirection="column">
|
|
118
|
+
<FormLabel size="tiny" sx={ { pb: 1 } }>
|
|
119
|
+
{ valueLabel }
|
|
120
|
+
</FormLabel>
|
|
117
121
|
<PropKeyProvider bind={ 'value' }>
|
|
118
122
|
<TextControl
|
|
119
123
|
inputValue={ sessionState.value }
|
|
120
124
|
error={ !! valueError }
|
|
121
125
|
inputDisabled={ !! keyError }
|
|
122
|
-
sx={ { pt: 1 } }
|
|
123
126
|
/>
|
|
124
127
|
</PropKeyProvider>
|
|
125
128
|
{ !! valueError && <FormHelperText error>{ valueError }</FormHelperText> }
|
|
@@ -1,20 +1,17 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import {
|
|
3
|
-
import { getLinkInLinkRestriction
|
|
2
|
+
import { useMemo, useState } from 'react';
|
|
3
|
+
import { getLinkInLinkRestriction } from '@elementor/editor-elements';
|
|
4
4
|
import {
|
|
5
|
-
booleanPropTypeUtil,
|
|
6
5
|
linkPropTypeUtil,
|
|
7
6
|
type LinkPropValue,
|
|
8
7
|
numberPropTypeUtil,
|
|
9
8
|
stringPropTypeUtil,
|
|
10
9
|
urlPropTypeUtil,
|
|
11
10
|
} from '@elementor/editor-props';
|
|
12
|
-
import { InfoTipCard } from '@elementor/editor-ui';
|
|
13
|
-
import { isExperimentActive } from '@elementor/editor-v1-adapters';
|
|
14
11
|
import { type HttpResponse, httpService } from '@elementor/http-client';
|
|
15
|
-
import {
|
|
12
|
+
import { MinusIcon, PlusIcon } from '@elementor/icons';
|
|
16
13
|
import { useSessionStorage } from '@elementor/session';
|
|
17
|
-
import {
|
|
14
|
+
import { Collapse, Grid, IconButton, Stack } from '@elementor/ui';
|
|
18
15
|
import { debounce } from '@elementor/utils';
|
|
19
16
|
import { __ } from '@wordpress/i18n';
|
|
20
17
|
|
|
@@ -27,6 +24,7 @@ import {
|
|
|
27
24
|
isCategorizedOptionPool,
|
|
28
25
|
} from '../components/autocomplete';
|
|
29
26
|
import { ControlFormLabel } from '../components/control-form-label';
|
|
27
|
+
import { RestrictedLinkInfotip } from '../components/restricted-link-infotip';
|
|
30
28
|
import ControlActions from '../control-actions/control-actions';
|
|
31
29
|
import { createControl } from '../create-control';
|
|
32
30
|
import { type ControlProps } from '../utils/types';
|
|
@@ -53,10 +51,6 @@ type LinkSessionValue = {
|
|
|
53
51
|
type Response = HttpResponse< { value: FlatOption[] | CategorizedOption[] } >;
|
|
54
52
|
|
|
55
53
|
const SIZE = 'tiny';
|
|
56
|
-
const learnMoreButton = {
|
|
57
|
-
label: __( 'Learn More', 'elementor' ),
|
|
58
|
-
href: 'https://go.elementor.com/element-link-inside-link-infotip',
|
|
59
|
-
};
|
|
60
54
|
|
|
61
55
|
export const LinkControl = createControl( ( props: Props ) => {
|
|
62
56
|
const { value, path, setValue, ...propContext } = useBoundProp( linkPropTypeUtil );
|
|
@@ -168,14 +162,14 @@ export const LinkControl = createControl( ( props: Props ) => {
|
|
|
168
162
|
} }
|
|
169
163
|
>
|
|
170
164
|
<ControlFormLabel>{ label }</ControlFormLabel>
|
|
171
|
-
<
|
|
165
|
+
<RestrictedLinkInfotip isVisible={ ! isActive } linkInLinkRestriction={ linkInLinkRestriction }>
|
|
172
166
|
<ToggleIconControl
|
|
173
167
|
disabled={ shouldDisableAddingLink }
|
|
174
168
|
active={ isActive }
|
|
175
169
|
onIconClick={ onEnabledChange }
|
|
176
170
|
label={ __( 'Toggle link', 'elementor' ) }
|
|
177
171
|
/>
|
|
178
|
-
</
|
|
172
|
+
</RestrictedLinkInfotip>
|
|
179
173
|
</Stack>
|
|
180
174
|
<Collapse in={ isActive } timeout="auto" unmountOnExit>
|
|
181
175
|
<Stack gap={ 1.5 }>
|
|
@@ -198,7 +192,7 @@ export const LinkControl = createControl( ( props: Props ) => {
|
|
|
198
192
|
<ControlFormLabel>{ __( 'Open in a new tab', 'elementor' ) }</ControlFormLabel>
|
|
199
193
|
</Grid>
|
|
200
194
|
<Grid item sx={ { marginInlineEnd: -1 } }>
|
|
201
|
-
<
|
|
195
|
+
<SwitchControl />
|
|
202
196
|
</Grid>
|
|
203
197
|
</Grid>
|
|
204
198
|
</PropKeyProvider>
|
|
@@ -224,30 +218,6 @@ const ToggleIconControl = ( { disabled, active, onIconClick, label }: ToggleIcon
|
|
|
224
218
|
);
|
|
225
219
|
};
|
|
226
220
|
|
|
227
|
-
const SwitchControlComponent = ( { disabled }: { disabled: boolean } ) => {
|
|
228
|
-
const { value, setValue } = useBoundProp( booleanPropTypeUtil );
|
|
229
|
-
const isVersion331Active = isExperimentActive( 'e_v_3_31' );
|
|
230
|
-
|
|
231
|
-
if ( isVersion331Active ) {
|
|
232
|
-
return <SwitchControl />;
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
const onClick = () => {
|
|
236
|
-
setValue( ! value );
|
|
237
|
-
};
|
|
238
|
-
|
|
239
|
-
return (
|
|
240
|
-
<Switch
|
|
241
|
-
checked={ value ?? false }
|
|
242
|
-
onClick={ onClick }
|
|
243
|
-
disabled={ disabled }
|
|
244
|
-
inputProps={ {
|
|
245
|
-
...( disabled ? { style: { opacity: 0 } } : {} ),
|
|
246
|
-
} }
|
|
247
|
-
/>
|
|
248
|
-
);
|
|
249
|
-
};
|
|
250
|
-
|
|
251
221
|
type FetchOptionsParams = Record< string, unknown > & { term: string };
|
|
252
222
|
|
|
253
223
|
async function fetchOptions( ajaxUrl: string, params: FetchOptionsParams ) {
|
|
@@ -286,56 +256,3 @@ function generateFirstLoadedOption( unionValue: LinkPropValue[ 'value' ] | null
|
|
|
286
256
|
]
|
|
287
257
|
: [];
|
|
288
258
|
}
|
|
289
|
-
|
|
290
|
-
interface ConditionalInfoTipType extends PropsWithChildren {
|
|
291
|
-
linkInLinkRestriction: LinkInLinkRestriction;
|
|
292
|
-
isVisible: boolean;
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
const ConditionalInfoTip: React.FC< ConditionalInfoTipType > = ( { linkInLinkRestriction, isVisible, children } ) => {
|
|
296
|
-
const { shouldRestrict, reason, elementId } = linkInLinkRestriction;
|
|
297
|
-
|
|
298
|
-
const handleTakeMeClick = () => {
|
|
299
|
-
if ( elementId ) {
|
|
300
|
-
selectElement( elementId );
|
|
301
|
-
}
|
|
302
|
-
};
|
|
303
|
-
|
|
304
|
-
return shouldRestrict && isVisible ? (
|
|
305
|
-
<Infotip
|
|
306
|
-
placement="right"
|
|
307
|
-
content={
|
|
308
|
-
<InfoTipCard
|
|
309
|
-
content={ INFOTIP_CONTENT[ reason ] }
|
|
310
|
-
svgIcon={ <AlertTriangleIcon /> }
|
|
311
|
-
learnMoreButton={ learnMoreButton }
|
|
312
|
-
ctaButton={ {
|
|
313
|
-
label: __( 'Take me there', 'elementor' ),
|
|
314
|
-
onClick: handleTakeMeClick,
|
|
315
|
-
} }
|
|
316
|
-
/>
|
|
317
|
-
}
|
|
318
|
-
>
|
|
319
|
-
<Box>{ children }</Box>
|
|
320
|
-
</Infotip>
|
|
321
|
-
) : (
|
|
322
|
-
<>{ children }</>
|
|
323
|
-
);
|
|
324
|
-
};
|
|
325
|
-
|
|
326
|
-
const INFOTIP_CONTENT = {
|
|
327
|
-
descendant: (
|
|
328
|
-
<>
|
|
329
|
-
{ __( 'To add a link to this container,', 'elementor' ) }
|
|
330
|
-
<br />
|
|
331
|
-
{ __( 'first remove the link from the elements inside of it.', 'elementor' ) }
|
|
332
|
-
</>
|
|
333
|
-
),
|
|
334
|
-
ancestor: (
|
|
335
|
-
<>
|
|
336
|
-
{ __( 'To add a link to this element,', 'elementor' ) }
|
|
337
|
-
<br />
|
|
338
|
-
{ __( 'first remove the link from its parent container.', 'elementor' ) }
|
|
339
|
-
</>
|
|
340
|
-
),
|
|
341
|
-
};
|