@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
|
@@ -10,154 +10,217 @@ import { TextFieldPopover } from '../components/text-field-popover';
|
|
|
10
10
|
import { createControl } from '../create-control';
|
|
11
11
|
import { useSizeExtendedOptions } from '../hooks/use-size-extended-options';
|
|
12
12
|
import { useSyncExternalState } from '../hooks/use-sync-external-state';
|
|
13
|
-
import {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
import {
|
|
14
|
+
type AngleUnit,
|
|
15
|
+
angleUnits,
|
|
16
|
+
DEFAULT_SIZE,
|
|
17
|
+
DEFAULT_UNIT,
|
|
18
|
+
type ExtendedOption,
|
|
19
|
+
isUnitExtendedOption,
|
|
20
|
+
type LengthUnit,
|
|
21
|
+
lengthUnits,
|
|
22
|
+
type TimeUnit,
|
|
23
|
+
timeUnits,
|
|
24
|
+
type Unit,
|
|
25
|
+
} from '../utils/size-control';
|
|
17
26
|
|
|
18
27
|
type SizeValue = SizePropValue[ 'value' ];
|
|
19
28
|
|
|
20
|
-
type
|
|
29
|
+
type SizeVariant = 'length' | 'angle' | 'time';
|
|
30
|
+
|
|
31
|
+
type UnitProps< T extends readonly Unit[] > = {
|
|
32
|
+
units?: T;
|
|
33
|
+
defaultUnit?: T[ number ];
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
type BaseSizeControlProps = {
|
|
21
37
|
placeholder?: string;
|
|
22
38
|
startIcon?: React.ReactNode;
|
|
23
|
-
units?: Unit[];
|
|
24
39
|
extendedOptions?: ExtendedOption[];
|
|
25
40
|
disableCustom?: boolean;
|
|
26
41
|
anchorRef?: RefObject< HTMLDivElement | null >;
|
|
27
|
-
defaultUnit?: Unit;
|
|
28
42
|
};
|
|
29
43
|
|
|
44
|
+
type LengthSizeControlProps = BaseSizeControlProps &
|
|
45
|
+
UnitProps< LengthUnit[] > & {
|
|
46
|
+
variant: 'length';
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
type AngleSizeControlProps = BaseSizeControlProps &
|
|
50
|
+
UnitProps< AngleUnit[] > & {
|
|
51
|
+
variant: 'angle';
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
type TimeSizeControlProps = BaseSizeControlProps &
|
|
55
|
+
UnitProps< TimeUnit[] > & {
|
|
56
|
+
variant: 'time';
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
export type SizeControlProps = LengthSizeControlProps | AngleSizeControlProps | TimeSizeControlProps;
|
|
60
|
+
|
|
30
61
|
type State = {
|
|
31
62
|
numeric: number;
|
|
32
63
|
custom: string;
|
|
33
64
|
unit: Unit | ExtendedOption;
|
|
34
65
|
};
|
|
35
66
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
67
|
+
const defaultSelectedUnit: Record< SizeControlProps[ 'variant' ], Unit > = {
|
|
68
|
+
length: 'px',
|
|
69
|
+
angle: 'deg',
|
|
70
|
+
time: 'ms',
|
|
71
|
+
} as const;
|
|
72
|
+
|
|
73
|
+
const defaultUnits: Record< SizeControlProps[ 'variant' ], Unit[] > = {
|
|
74
|
+
length: [ ...lengthUnits ] as LengthUnit[],
|
|
75
|
+
angle: [ ...angleUnits ] as AngleUnit[],
|
|
76
|
+
time: [ ...timeUnits ] as TimeUnit[],
|
|
77
|
+
} as const;
|
|
78
|
+
|
|
79
|
+
export const SizeControl = createControl(
|
|
80
|
+
( {
|
|
81
|
+
variant = 'length' as SizeControlProps[ 'variant' ],
|
|
82
|
+
defaultUnit,
|
|
83
|
+
units,
|
|
84
|
+
placeholder,
|
|
85
|
+
startIcon,
|
|
86
|
+
anchorRef,
|
|
87
|
+
extendedOptions,
|
|
88
|
+
disableCustom,
|
|
89
|
+
}: Omit< SizeControlProps, 'variant' > & { variant?: SizeVariant } ) => {
|
|
90
|
+
const {
|
|
91
|
+
value: sizeValue,
|
|
92
|
+
setValue: setSizeValue,
|
|
93
|
+
disabled,
|
|
94
|
+
restoreValue,
|
|
95
|
+
placeholder: externalPlaceholder,
|
|
96
|
+
} = useBoundProp( sizePropTypeUtil );
|
|
97
|
+
const actualDefaultUnit = defaultUnit ?? externalPlaceholder?.unit ?? defaultSelectedUnit[ variant ];
|
|
98
|
+
const actualUnits = units ?? [ ...defaultUnits[ variant ] ];
|
|
99
|
+
const [ internalState, setInternalState ] = useState( createStateFromSizeProp( sizeValue, actualDefaultUnit ) );
|
|
100
|
+
const activeBreakpoint = useActiveBreakpoint();
|
|
101
|
+
|
|
102
|
+
const actualExtendedOptions = useSizeExtendedOptions( extendedOptions || [], disableCustom ?? false );
|
|
103
|
+
const popupState = usePopupState( { variant: 'popover' } );
|
|
104
|
+
|
|
105
|
+
const [ state, setState ] = useSyncExternalState( {
|
|
106
|
+
external: internalState,
|
|
107
|
+
setExternal: ( newState: State | null ) => setSizeValue( extractValueFromState( newState ) ),
|
|
108
|
+
persistWhen: ( newState ) => {
|
|
109
|
+
if ( ! newState?.unit ) {
|
|
110
|
+
return false;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if ( isUnitExtendedOption( newState.unit ) ) {
|
|
114
|
+
return newState.unit === 'auto' ? true : !! newState.custom;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return !! newState?.numeric || newState?.numeric === 0;
|
|
118
|
+
},
|
|
119
|
+
fallback: ( newState ) => ( {
|
|
120
|
+
unit: newState?.unit ?? actualDefaultUnit,
|
|
121
|
+
numeric: newState?.numeric ?? DEFAULT_SIZE,
|
|
122
|
+
custom: newState?.custom ?? '',
|
|
123
|
+
} ),
|
|
124
|
+
} );
|
|
125
|
+
|
|
126
|
+
const { size: controlSize = DEFAULT_SIZE, unit: controlUnit = actualDefaultUnit } =
|
|
127
|
+
extractValueFromState( state ) || {};
|
|
128
|
+
|
|
129
|
+
const handleUnitChange = ( newUnit: Unit | ExtendedOption ) => {
|
|
130
|
+
if ( newUnit === 'custom' ) {
|
|
131
|
+
popupState.open( anchorRef?.current );
|
|
56
132
|
}
|
|
57
133
|
|
|
58
|
-
|
|
59
|
-
}
|
|
60
|
-
fallback: ( newState ) => ( {
|
|
61
|
-
unit: newState?.unit ?? props.defaultUnit ?? DEFAULT_UNIT,
|
|
62
|
-
numeric: newState?.numeric ?? DEFAULT_SIZE,
|
|
63
|
-
custom: newState?.custom ?? '',
|
|
64
|
-
} ),
|
|
65
|
-
} );
|
|
66
|
-
|
|
67
|
-
const { size: controlSize = DEFAULT_SIZE, unit: controlUnit = DEFAULT_UNIT } = extractValueFromState( state ) || {};
|
|
134
|
+
setState( ( prev ) => ( { ...prev, unit: newUnit } ) );
|
|
135
|
+
};
|
|
68
136
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
popupState.open( anchorRef?.current );
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
setState( ( prev ) => ( { ...prev, unit: newUnit } ) );
|
|
75
|
-
};
|
|
137
|
+
const handleSizeChange = ( event: React.ChangeEvent< HTMLInputElement > ) => {
|
|
138
|
+
const { value: size } = event.target;
|
|
76
139
|
|
|
77
|
-
|
|
78
|
-
|
|
140
|
+
if ( controlUnit === 'auto' ) {
|
|
141
|
+
setState( ( prev ) => ( { ...prev, unit: controlUnit } ) );
|
|
79
142
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
return;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
setState( ( prev ) => ( {
|
|
87
|
-
...prev,
|
|
88
|
-
[ controlUnit === 'custom' ? 'custom' : 'numeric' ]: formatSize( size, controlUnit ),
|
|
89
|
-
unit: controlUnit,
|
|
90
|
-
} ) );
|
|
91
|
-
};
|
|
92
|
-
|
|
93
|
-
const onInputFocus = ( event: React.FocusEvent< HTMLInputElement > ) => {
|
|
94
|
-
if ( isUnitExtendedOption( state.unit ) ) {
|
|
95
|
-
( event.target as HTMLElement )?.blur();
|
|
96
|
-
}
|
|
97
|
-
};
|
|
98
|
-
|
|
99
|
-
const onInputClick = ( event: React.MouseEvent ) => {
|
|
100
|
-
if ( ( event.target as HTMLElement ).closest( 'input' ) && 'custom' === state.unit ) {
|
|
101
|
-
popupState.open( anchorRef?.current );
|
|
102
|
-
}
|
|
103
|
-
};
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
104
145
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
146
|
+
setState( ( prev ) => ( {
|
|
147
|
+
...prev,
|
|
148
|
+
[ controlUnit === 'custom' ? 'custom' : 'numeric' ]: formatSize( size, controlUnit ),
|
|
149
|
+
unit: controlUnit,
|
|
150
|
+
} ) );
|
|
151
|
+
};
|
|
109
152
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
153
|
+
const onInputClick = ( event: React.MouseEvent ) => {
|
|
154
|
+
if ( ( event.target as HTMLElement ).closest( 'input' ) && 'custom' === state.unit ) {
|
|
155
|
+
popupState.open( anchorRef?.current );
|
|
156
|
+
}
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
useEffect( () => {
|
|
160
|
+
const newState = createStateFromSizeProp(
|
|
161
|
+
sizeValue,
|
|
162
|
+
state.unit === 'custom' ? state.unit : actualDefaultUnit,
|
|
163
|
+
'',
|
|
164
|
+
state.custom
|
|
165
|
+
);
|
|
166
|
+
const currentUnitType = isUnitExtendedOption( state.unit ) ? 'custom' : 'numeric';
|
|
167
|
+
const mergedStates = {
|
|
168
|
+
...state,
|
|
169
|
+
unit: newState.unit ?? state.unit,
|
|
170
|
+
[ currentUnitType ]: newState[ currentUnitType ],
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
if ( mergedStates.unit !== 'auto' && areStatesEqual( state, mergedStates ) ) {
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
113
176
|
|
|
114
|
-
|
|
115
|
-
|
|
177
|
+
if ( state.unit === newState.unit ) {
|
|
178
|
+
setInternalState( mergedStates );
|
|
116
179
|
|
|
117
|
-
|
|
118
|
-
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
119
182
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
183
|
+
setState( newState );
|
|
184
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
185
|
+
}, [ sizeValue ] );
|
|
123
186
|
|
|
124
|
-
|
|
125
|
-
|
|
187
|
+
useEffect( () => {
|
|
188
|
+
const newState = createStateFromSizeProp( sizeValue, actualDefaultUnit, '', state.custom );
|
|
126
189
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
onClick={ onInputClick }
|
|
147
|
-
popupState={ popupState }
|
|
148
|
-
/>
|
|
149
|
-
{ anchorRef?.current && (
|
|
150
|
-
<TextFieldPopover
|
|
190
|
+
if ( activeBreakpoint && ! areStatesEqual( newState, state ) ) {
|
|
191
|
+
setState( newState );
|
|
192
|
+
}
|
|
193
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
194
|
+
}, [ activeBreakpoint ] );
|
|
195
|
+
|
|
196
|
+
return (
|
|
197
|
+
<>
|
|
198
|
+
<SizeInput
|
|
199
|
+
disabled={ disabled }
|
|
200
|
+
size={ controlSize }
|
|
201
|
+
unit={ controlUnit }
|
|
202
|
+
units={ [ ...actualUnits, ...( actualExtendedOptions || [] ) ] }
|
|
203
|
+
placeholder={ placeholder }
|
|
204
|
+
startIcon={ startIcon }
|
|
205
|
+
handleSizeChange={ handleSizeChange }
|
|
206
|
+
handleUnitChange={ handleUnitChange }
|
|
207
|
+
onBlur={ restoreValue }
|
|
208
|
+
onClick={ onInputClick }
|
|
151
209
|
popupState={ popupState }
|
|
152
|
-
anchorRef={ anchorRef }
|
|
153
|
-
restoreValue={ restoreValue }
|
|
154
|
-
value={ controlSize as string }
|
|
155
|
-
onChange={ handleSizeChange }
|
|
156
210
|
/>
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
}
|
|
211
|
+
{ anchorRef?.current && (
|
|
212
|
+
<TextFieldPopover
|
|
213
|
+
popupState={ popupState }
|
|
214
|
+
anchorRef={ anchorRef }
|
|
215
|
+
restoreValue={ restoreValue }
|
|
216
|
+
value={ controlSize as string }
|
|
217
|
+
onChange={ handleSizeChange }
|
|
218
|
+
/>
|
|
219
|
+
) }
|
|
220
|
+
</>
|
|
221
|
+
);
|
|
222
|
+
}
|
|
223
|
+
);
|
|
161
224
|
|
|
162
225
|
function formatSize< TSize extends string | number >( size: TSize, unit: Unit | ExtendedOption ): TSize {
|
|
163
226
|
if ( isUnitExtendedOption( unit ) ) {
|
|
@@ -167,16 +230,21 @@ function formatSize< TSize extends string | number >( size: TSize, unit: Unit |
|
|
|
167
230
|
return size || size === 0 ? ( Number( size ) as TSize ) : ( NaN as TSize );
|
|
168
231
|
}
|
|
169
232
|
|
|
170
|
-
function createStateFromSizeProp(
|
|
233
|
+
function createStateFromSizeProp(
|
|
234
|
+
sizeValue: SizeValue | null,
|
|
235
|
+
defaultUnit: Unit | ExtendedOption,
|
|
236
|
+
defaultSize: string | number = '',
|
|
237
|
+
customState: string = ''
|
|
238
|
+
): State {
|
|
171
239
|
const unit = sizeValue?.unit ?? defaultUnit;
|
|
172
|
-
const size = sizeValue?.size ??
|
|
240
|
+
const size = sizeValue?.size ?? defaultSize;
|
|
173
241
|
|
|
174
242
|
return {
|
|
175
243
|
numeric:
|
|
176
244
|
! isUnitExtendedOption( unit ) && ! isNaN( Number( size ) ) && ( size || size === 0 )
|
|
177
245
|
? Number( size )
|
|
178
246
|
: DEFAULT_SIZE,
|
|
179
|
-
custom: unit === 'custom' ? String( size ) :
|
|
247
|
+
custom: unit === 'custom' ? String( size ) : customState,
|
|
180
248
|
unit,
|
|
181
249
|
};
|
|
182
250
|
}
|
|
@@ -8,7 +8,7 @@ import { PropKeyProvider, PropProvider, useBoundProp } from '../bound-prop-conte
|
|
|
8
8
|
import { ControlFormLabel } from '../components/control-form-label';
|
|
9
9
|
import { SectionContent } from '../components/section-content';
|
|
10
10
|
import { createControl } from '../create-control';
|
|
11
|
-
import { type
|
|
11
|
+
import { type LengthUnit } from '../utils/size-control';
|
|
12
12
|
import { ColorControl } from './color-control';
|
|
13
13
|
import { SizeControl } from './size-control';
|
|
14
14
|
|
|
@@ -18,7 +18,7 @@ type StrokeProps = {
|
|
|
18
18
|
children: React.ReactNode;
|
|
19
19
|
};
|
|
20
20
|
|
|
21
|
-
const units:
|
|
21
|
+
const units: LengthUnit[] = [ 'px', 'em', 'rem' ];
|
|
22
22
|
|
|
23
23
|
export const StrokeControl = createControl( () => {
|
|
24
24
|
const propContext = useBoundProp( strokePropTypeUtil );
|
|
@@ -1,26 +1,41 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { stringPropTypeUtil } from '@elementor/editor-props';
|
|
3
|
-
import { TextField } from '@elementor/ui';
|
|
3
|
+
import { type SxProps, TextField } from '@elementor/ui';
|
|
4
4
|
|
|
5
5
|
import { useBoundProp } from '../bound-prop-context';
|
|
6
6
|
import ControlActions from '../control-actions/control-actions';
|
|
7
7
|
import { createControl } from '../create-control';
|
|
8
8
|
|
|
9
|
-
export const TextControl = createControl(
|
|
10
|
-
|
|
9
|
+
export const TextControl = createControl(
|
|
10
|
+
( {
|
|
11
|
+
placeholder,
|
|
12
|
+
error,
|
|
13
|
+
inputValue,
|
|
14
|
+
inputDisabled,
|
|
15
|
+
sx,
|
|
16
|
+
}: {
|
|
17
|
+
placeholder?: string;
|
|
18
|
+
error?: boolean;
|
|
19
|
+
inputValue?: string;
|
|
20
|
+
inputDisabled?: boolean;
|
|
21
|
+
sx?: SxProps;
|
|
22
|
+
} ) => {
|
|
23
|
+
const { value, setValue, disabled } = useBoundProp( stringPropTypeUtil );
|
|
24
|
+
const handleChange = ( event: React.ChangeEvent< HTMLInputElement > ) => setValue( event.target.value );
|
|
11
25
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
}
|
|
26
|
+
return (
|
|
27
|
+
<ControlActions>
|
|
28
|
+
<TextField
|
|
29
|
+
size="tiny"
|
|
30
|
+
fullWidth
|
|
31
|
+
disabled={ inputDisabled ?? disabled }
|
|
32
|
+
value={ inputValue ?? value ?? '' }
|
|
33
|
+
onChange={ handleChange }
|
|
34
|
+
placeholder={ placeholder }
|
|
35
|
+
error={ error }
|
|
36
|
+
sx={ sx }
|
|
37
|
+
/>
|
|
38
|
+
</ControlActions>
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
);
|
|
@@ -42,12 +42,13 @@ export const ToggleControl = createControl(
|
|
|
42
42
|
maxItems,
|
|
43
43
|
fullWidth,
|
|
44
44
|
size,
|
|
45
|
+
placeholder,
|
|
45
46
|
};
|
|
46
47
|
|
|
47
48
|
return exclusive ? (
|
|
48
49
|
<ControlToggleButtonGroup
|
|
49
50
|
{ ...toggleButtonGroupProps }
|
|
50
|
-
value={ value ??
|
|
51
|
+
value={ value ?? null }
|
|
51
52
|
onChange={ setValue }
|
|
52
53
|
disabled={ disabled }
|
|
53
54
|
exclusive={ true }
|
|
@@ -55,7 +56,7 @@ export const ToggleControl = createControl(
|
|
|
55
56
|
) : (
|
|
56
57
|
<ControlToggleButtonGroup
|
|
57
58
|
{ ...toggleButtonGroupProps }
|
|
58
|
-
value={
|
|
59
|
+
value={ value?.split( ' ' ) ?? [] }
|
|
59
60
|
onChange={ handleNonExclusiveToggle }
|
|
60
61
|
disabled={ disabled }
|
|
61
62
|
exclusive={ false }
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type RefObject } from 'react';
|
|
2
2
|
import * as React from 'react';
|
|
3
|
+
import { type AngleUnit } from '@elementor/editor-controls';
|
|
3
4
|
import { Grid } from '@elementor/ui';
|
|
4
5
|
|
|
5
6
|
import { PropKeyProvider } from '../../../bound-prop-context';
|
|
@@ -12,9 +13,10 @@ type TransformAxisRowProps = {
|
|
|
12
13
|
bindValue: 'x' | 'y' | 'z';
|
|
13
14
|
startIcon: React.ReactNode;
|
|
14
15
|
anchorRef?: RefObject< HTMLDivElement | null >;
|
|
16
|
+
units?: AngleUnit[];
|
|
15
17
|
};
|
|
16
18
|
|
|
17
|
-
export const AxisRow = ( { label, bindValue, startIcon, anchorRef }: TransformAxisRowProps ) => {
|
|
19
|
+
export const AxisRow = ( { label, bindValue, startIcon, anchorRef, units }: TransformAxisRowProps ) => {
|
|
18
20
|
return (
|
|
19
21
|
<Grid item xs={ 12 }>
|
|
20
22
|
<PopoverGridContainer ref={ anchorRef }>
|
|
@@ -23,7 +25,7 @@ export const AxisRow = ( { label, bindValue, startIcon, anchorRef }: TransformAx
|
|
|
23
25
|
</Grid>
|
|
24
26
|
<Grid item xs={ 6 }>
|
|
25
27
|
<PropKeyProvider bind={ bindValue }>
|
|
26
|
-
<SizeControl anchorRef={ anchorRef } startIcon={ startIcon } />
|
|
28
|
+
<SizeControl anchorRef={ anchorRef } startIcon={ startIcon } units={ units } variant="angle" />
|
|
27
29
|
</PropKeyProvider>
|
|
28
30
|
</Grid>
|
|
29
31
|
</PopoverGridContainer>
|
|
@@ -6,6 +6,7 @@ import { Grid } from '@elementor/ui';
|
|
|
6
6
|
import { __ } from '@wordpress/i18n';
|
|
7
7
|
|
|
8
8
|
import { PropKeyProvider, PropProvider, useBoundProp } from '../../../bound-prop-context';
|
|
9
|
+
import { TransformFunctionKeys } from '../types';
|
|
9
10
|
import { AxisRow } from './axis-row';
|
|
10
11
|
|
|
11
12
|
const moveAxisControls: { label: string; bindValue: 'x' | 'y' | 'z'; startIcon: React.ReactNode }[] = [
|
|
@@ -33,7 +34,7 @@ export const Move = () => {
|
|
|
33
34
|
return (
|
|
34
35
|
<Grid container spacing={ 1.5 }>
|
|
35
36
|
<PropProvider { ...context }>
|
|
36
|
-
<PropKeyProvider bind={
|
|
37
|
+
<PropKeyProvider bind={ TransformFunctionKeys.move }>
|
|
37
38
|
{ moveAxisControls.map( ( control ) => (
|
|
38
39
|
<AxisRow key={ control.bindValue } { ...control } anchorRef={ rowRef } />
|
|
39
40
|
) ) }
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { useRef } from 'react';
|
|
3
|
+
import { rotateTransformPropTypeUtil } from '@elementor/editor-props';
|
|
4
|
+
import { Arrow360Icon, RotateClockwiseIcon } from '@elementor/icons';
|
|
5
|
+
import { Grid } from '@elementor/ui';
|
|
6
|
+
import { __ } from '@wordpress/i18n';
|
|
7
|
+
|
|
8
|
+
import { PropKeyProvider, PropProvider, useBoundProp } from '../../../bound-prop-context';
|
|
9
|
+
import { type AngleUnit } from '../../../utils/size-control';
|
|
10
|
+
import { TransformFunctionKeys } from '../types';
|
|
11
|
+
import { AxisRow } from './axis-row';
|
|
12
|
+
|
|
13
|
+
const rotateAxisControls: { label: string; bindValue: 'x' | 'y' | 'z'; startIcon: React.ReactNode }[] = [
|
|
14
|
+
{
|
|
15
|
+
label: __( 'Rotate X', 'elementor' ),
|
|
16
|
+
bindValue: 'x',
|
|
17
|
+
startIcon: <Arrow360Icon fontSize={ 'tiny' } />,
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
label: __( 'Rotate Y', 'elementor' ),
|
|
21
|
+
bindValue: 'y',
|
|
22
|
+
startIcon: <Arrow360Icon fontSize="tiny" style={ { transform: 'scaleX(-1) rotate(-90deg)' } } />,
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
label: __( 'Rotate Z', 'elementor' ),
|
|
26
|
+
bindValue: 'z',
|
|
27
|
+
startIcon: <RotateClockwiseIcon fontSize={ 'tiny' } />,
|
|
28
|
+
},
|
|
29
|
+
];
|
|
30
|
+
|
|
31
|
+
const rotateUnits: AngleUnit[] = [ 'deg', 'rad', 'grad', 'turn' ];
|
|
32
|
+
|
|
33
|
+
export const Rotate = () => {
|
|
34
|
+
const context = useBoundProp( rotateTransformPropTypeUtil );
|
|
35
|
+
const rowRef = useRef< HTMLDivElement >( null );
|
|
36
|
+
|
|
37
|
+
return (
|
|
38
|
+
<Grid container spacing={ 1.5 }>
|
|
39
|
+
<PropProvider { ...context }>
|
|
40
|
+
<PropKeyProvider bind={ TransformFunctionKeys.rotate }>
|
|
41
|
+
{ rotateAxisControls.map( ( control ) => (
|
|
42
|
+
<AxisRow key={ control.bindValue } { ...control } anchorRef={ rowRef } units={ rotateUnits } />
|
|
43
|
+
) ) }
|
|
44
|
+
</PropKeyProvider>
|
|
45
|
+
</PropProvider>
|
|
46
|
+
</Grid>
|
|
47
|
+
);
|
|
48
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { type RefObject } from 'react';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { Grid } from '@elementor/ui';
|
|
4
|
+
|
|
5
|
+
import { PropKeyProvider } from '../../../bound-prop-context';
|
|
6
|
+
import { ControlLabel } from '../../../components/control-label';
|
|
7
|
+
import { PopoverGridContainer } from '../../../components/popover-grid-container';
|
|
8
|
+
import { NumberControl } from '../../number-control';
|
|
9
|
+
|
|
10
|
+
type ScaleAxisRowProps = {
|
|
11
|
+
label: string;
|
|
12
|
+
bindValue: 'x' | 'y' | 'z';
|
|
13
|
+
startIcon: React.ReactNode;
|
|
14
|
+
anchorRef?: RefObject< HTMLDivElement | null >;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export const ScaleAxisRow = ( { label, bindValue, startIcon, anchorRef }: ScaleAxisRowProps ) => {
|
|
18
|
+
return (
|
|
19
|
+
<Grid item xs={ 12 }>
|
|
20
|
+
<PopoverGridContainer ref={ anchorRef }>
|
|
21
|
+
<Grid item xs={ 6 }>
|
|
22
|
+
<ControlLabel>{ label }</ControlLabel>
|
|
23
|
+
</Grid>
|
|
24
|
+
<Grid item xs={ 6 }>
|
|
25
|
+
<PropKeyProvider bind={ bindValue }>
|
|
26
|
+
<NumberControl step={ 0.1 } placeholder="1" startIcon={ startIcon } />
|
|
27
|
+
</PropKeyProvider>
|
|
28
|
+
</Grid>
|
|
29
|
+
</PopoverGridContainer>
|
|
30
|
+
</Grid>
|
|
31
|
+
);
|
|
32
|
+
};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { useRef } from 'react';
|
|
3
|
+
import { scaleTransformPropTypeUtil } from '@elementor/editor-props';
|
|
4
|
+
import { ArrowDownLeftIcon, ArrowDownSmallIcon, ArrowRightIcon } from '@elementor/icons';
|
|
5
|
+
import { Grid } from '@elementor/ui';
|
|
6
|
+
import { __ } from '@wordpress/i18n';
|
|
7
|
+
|
|
8
|
+
import { PropKeyProvider, PropProvider, useBoundProp } from '../../../bound-prop-context';
|
|
9
|
+
import { TransformFunctionKeys } from '../types';
|
|
10
|
+
import { ScaleAxisRow } from './scale-axis-row';
|
|
11
|
+
|
|
12
|
+
const scaleAxisControls: { label: string; bindValue: 'x' | 'y' | 'z'; startIcon: React.ReactNode }[] = [
|
|
13
|
+
{
|
|
14
|
+
label: __( 'Scale X', 'elementor' ),
|
|
15
|
+
bindValue: 'x',
|
|
16
|
+
startIcon: <ArrowRightIcon fontSize={ 'tiny' } />,
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
label: __( 'Scale Y', 'elementor' ),
|
|
20
|
+
bindValue: 'y',
|
|
21
|
+
startIcon: <ArrowDownSmallIcon fontSize={ 'tiny' } />,
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
label: __( 'Scale Z', 'elementor' ),
|
|
25
|
+
bindValue: 'z',
|
|
26
|
+
startIcon: <ArrowDownLeftIcon fontSize={ 'tiny' } />,
|
|
27
|
+
},
|
|
28
|
+
];
|
|
29
|
+
|
|
30
|
+
export const Scale = () => {
|
|
31
|
+
const context = useBoundProp( scaleTransformPropTypeUtil );
|
|
32
|
+
const rowRef = useRef< HTMLDivElement >( null );
|
|
33
|
+
|
|
34
|
+
return (
|
|
35
|
+
<Grid container spacing={ 1.5 }>
|
|
36
|
+
<PropProvider { ...context }>
|
|
37
|
+
<PropKeyProvider bind={ TransformFunctionKeys.scale }>
|
|
38
|
+
{ scaleAxisControls.map( ( control ) => (
|
|
39
|
+
<ScaleAxisRow key={ control.bindValue } { ...control } anchorRef={ rowRef } />
|
|
40
|
+
) ) }
|
|
41
|
+
</PropKeyProvider>
|
|
42
|
+
</PropProvider>
|
|
43
|
+
</Grid>
|
|
44
|
+
);
|
|
45
|
+
};
|