@elementor/editor-controls 4.1.0-772 → 4.1.0-774

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@elementor/editor-controls",
3
3
  "description": "This package contains the controls model and utils for the Elementor editor",
4
- "version": "4.1.0-772",
4
+ "version": "4.1.0-774",
5
5
  "private": false,
6
6
  "author": "Elementor Team",
7
7
  "homepage": "https://elementor.com/",
@@ -40,22 +40,22 @@
40
40
  "dev": "tsup --config=../../tsup.dev.ts"
41
41
  },
42
42
  "dependencies": {
43
- "@elementor/editor-current-user": "4.1.0-772",
44
- "@elementor/editor-elements": "4.1.0-772",
45
- "@elementor/editor-props": "4.1.0-772",
46
- "@elementor/editor-responsive": "4.1.0-772",
47
- "@elementor/editor-ui": "4.1.0-772",
48
- "@elementor/editor-v1-adapters": "4.1.0-772",
49
- "@elementor/env": "4.1.0-772",
50
- "@elementor/events": "4.1.0-772",
51
- "@elementor/http-client": "4.1.0-772",
43
+ "@elementor/editor-current-user": "4.1.0-774",
44
+ "@elementor/editor-elements": "4.1.0-774",
45
+ "@elementor/editor-props": "4.1.0-774",
46
+ "@elementor/editor-responsive": "4.1.0-774",
47
+ "@elementor/editor-ui": "4.1.0-774",
48
+ "@elementor/editor-v1-adapters": "4.1.0-774",
49
+ "@elementor/env": "4.1.0-774",
50
+ "@elementor/events": "4.1.0-774",
51
+ "@elementor/http-client": "4.1.0-774",
52
52
  "@elementor/icons": "^1.68.0",
53
- "@elementor/locations": "4.1.0-772",
54
- "@elementor/query": "4.1.0-772",
55
- "@elementor/session": "4.1.0-772",
53
+ "@elementor/locations": "4.1.0-774",
54
+ "@elementor/query": "4.1.0-774",
55
+ "@elementor/session": "4.1.0-774",
56
56
  "@elementor/ui": "1.37.5",
57
- "@elementor/utils": "4.1.0-772",
58
- "@elementor/wp-media": "4.1.0-772",
57
+ "@elementor/utils": "4.1.0-774",
58
+ "@elementor/wp-media": "4.1.0-774",
59
59
  "@monaco-editor/react": "^4.7.0",
60
60
  "@tiptap/extension-bold": "^3.11.1",
61
61
  "@tiptap/extension-document": "^3.11.1",
@@ -1,6 +1,13 @@
1
1
  import * as React from 'react';
2
2
  import { type RefObject, useLayoutEffect, useRef, useState } from 'react';
3
- import { dimensionsPropTypeUtil, type PropKey, sizePropTypeUtil } from '@elementor/editor-props';
3
+ import {
4
+ dimensionsPropTypeUtil,
5
+ type DimensionsPropValue,
6
+ type PropKey,
7
+ type PropValue,
8
+ sizePropTypeUtil,
9
+ type SizePropValue,
10
+ } from '@elementor/editor-props';
4
11
  import { useActiveBreakpoint } from '@elementor/editor-responsive';
5
12
  import { DetachIcon, LinkIcon, SideBottomIcon, SideLeftIcon, SideRightIcon, SideTopIcon } from '@elementor/icons';
6
13
  import { Grid, Stack, Tooltip } from '@elementor/ui';
@@ -11,7 +18,7 @@ import { ControlFormLabel } from '../components/control-form-label';
11
18
  import { ControlLabel } from '../components/control-label';
12
19
  import { StyledToggleButton } from '../components/control-toggle-button-group';
13
20
  import { type ExtendedOption } from '../utils/size-control';
14
- import { SizeControl } from './size-control';
21
+ import { UnstableSizeControl } from './size-control/unstable-size-control';
15
22
 
16
23
  type Props = {
17
24
  label: string;
@@ -20,7 +27,7 @@ type Props = {
20
27
  min?: number;
21
28
  };
22
29
 
23
- export const LinkedDimensionsControl = ( { label, isSiteRtl = false, extendedOptions, min }: Props ) => {
30
+ export const LinkedDimensionsControl = ( { label, isSiteRtl = false, min }: Props ) => {
24
31
  const gridRowRefs: RefObject< HTMLDivElement >[] = [ useRef( null ), useRef( null ) ];
25
32
 
26
33
  const { disabled: sizeDisabled } = useBoundProp( sizePropTypeUtil );
@@ -51,10 +58,12 @@ export const LinkedDimensionsControl = ( { label, isSiteRtl = false, extendedOpt
51
58
 
52
59
  const activeBreakpoint = useActiveBreakpoint();
53
60
 
61
+ const isCurrentlyDimensions = dimensionsPropTypeUtil.isValid( masterValue ?? masterPlaceholder );
62
+
54
63
  useLayoutEffect( () => {
55
64
  setIsLinked( inferIsLinked );
56
65
  // eslint-disable-next-line react-hooks/exhaustive-deps
57
- }, [ activeBreakpoint ] );
66
+ }, [ activeBreakpoint, isCurrentlyDimensions ] );
58
67
 
59
68
  const onLinkToggle = () => {
60
69
  setIsLinked( ( prev ) => ! prev );
@@ -79,12 +88,7 @@ export const LinkedDimensionsControl = ( { label, isSiteRtl = false, extendedOpt
79
88
  return;
80
89
  }
81
90
 
82
- const sizeValue =
83
- dimensionsValue?.[ 'block-start' ] ??
84
- dimensionsValue?.[ 'inline-end' ] ??
85
- dimensionsValue?.[ 'block-end' ] ??
86
- dimensionsValue?.[ 'inline-start' ] ??
87
- null;
91
+ const sizeValue = getFirstDefined( dimensionsValue ) ?? null;
88
92
 
89
93
  if ( ! sizeValue ) {
90
94
  setMasterValue( null );
@@ -119,12 +123,27 @@ export const LinkedDimensionsControl = ( { label, isSiteRtl = false, extendedOpt
119
123
  propType,
120
124
  value: dimensionsValue,
121
125
  placeholder: effectiveDimensionsPlaceholder,
122
- setValue: setDimensionsValue,
126
+ setValue: ( dimensions: PropValue ) => {
127
+ const entries = Object.entries( dimensions as DimensionsPropValue );
128
+ const filtered = entries.filter( ( [ , value ] ) => Boolean( value ) );
129
+
130
+ setDimensionsValue( filtered.length === 0 ? null : Object.fromEntries( filtered ) );
131
+ },
123
132
  isDisabled: () => dimensionsDisabled,
124
133
  };
125
134
 
126
135
  const hasPlaceholders = ! masterValue && ( dimensionsPlaceholder || masterPlaceholder );
127
136
 
137
+ const getEffectivePlaceholder = ( bind: string ) => {
138
+ if ( isLinked ) {
139
+ const linkedPlaceholder = getFirstDefined( dimensionsPlaceholder );
140
+
141
+ return sizePropTypeUtil.extract( linkedPlaceholder );
142
+ }
143
+
144
+ return sizePropTypeUtil.extract( dimensionsPlaceholder?.[ bind as keyof DimensionsPropValue[ 'value' ] ] );
145
+ };
146
+
128
147
  return (
129
148
  <PropProvider { ...propProviderProps }>
130
149
  <Stack direction="row" gap={ 2 } flexWrap="nowrap">
@@ -158,7 +177,7 @@ export const LinkedDimensionsControl = ( { label, isSiteRtl = false, extendedOpt
158
177
  ariaLabel={ props.ariaLabel }
159
178
  startIcon={ icon }
160
179
  isLinked={ isLinked }
161
- extendedOptions={ extendedOptions }
180
+ placeholder={ getEffectivePlaceholder( props.bind ) ?? undefined }
162
181
  anchorRef={ gridRowRefs[ index ] }
163
182
  min={ min }
164
183
  />
@@ -176,7 +195,7 @@ const Control = ( {
176
195
  ariaLabel,
177
196
  startIcon,
178
197
  isLinked,
179
- extendedOptions,
198
+ placeholder,
180
199
  anchorRef,
181
200
  min,
182
201
  }: {
@@ -184,17 +203,17 @@ const Control = ( {
184
203
  ariaLabel: string;
185
204
  startIcon: React.ReactNode;
186
205
  isLinked: boolean;
187
- extendedOptions?: ExtendedOption[];
206
+ placeholder?: SizePropValue[ 'value' ];
188
207
  anchorRef: RefObject< HTMLDivElement >;
189
208
  min?: number;
190
209
  } ) => {
191
210
  if ( isLinked ) {
192
211
  return (
193
- <SizeControl
212
+ <UnstableSizeControl
194
213
  ariaLabel={ ariaLabel }
195
214
  startIcon={ startIcon }
196
- extendedOptions={ extendedOptions }
197
215
  anchorRef={ anchorRef }
216
+ placeholder={ placeholder }
198
217
  min={ min }
199
218
  />
200
219
  );
@@ -202,12 +221,12 @@ const Control = ( {
202
221
 
203
222
  return (
204
223
  <PropKeyProvider bind={ bind }>
205
- <SizeControl
224
+ <UnstableSizeControl
206
225
  ariaLabel={ ariaLabel }
207
226
  startIcon={ startIcon }
208
- extendedOptions={ extendedOptions }
209
227
  anchorRef={ anchorRef }
210
228
  min={ min }
229
+ placeholder={ placeholder }
211
230
  />
212
231
  </PropKeyProvider>
213
232
  );
@@ -221,6 +240,15 @@ const Label = ( { label, bind }: { label: string; bind: PropKey } ) => {
221
240
  );
222
241
  };
223
242
 
243
+ const getFirstDefined = ( dimensions: DimensionsPropValue[ 'value' ] | null | undefined ) => {
244
+ return (
245
+ dimensions?.[ 'block-start' ] ??
246
+ dimensions?.[ 'inline-end' ] ??
247
+ dimensions?.[ 'block-end' ] ??
248
+ dimensions?.[ 'inline-start' ]
249
+ );
250
+ };
251
+
224
252
  function getCssDimensionProps( label: string, isSiteRtl: boolean ) {
225
253
  return [
226
254
  [
@@ -2,7 +2,7 @@ import { useMemo } from 'react';
2
2
  import { type SizePropValue } from '@elementor/editor-props';
3
3
 
4
4
  import { useSyncExternalState } from '../../../hooks/use-sync-external-state';
5
- import { type SetSizeValue, type SizeUnit } from '../types';
5
+ import { type SetSizeValue } from '../types';
6
6
  import { isExtendedUnit } from '../utils/is-extended-unit';
7
7
  import { createDefaultSizeValue, resolveSizeOnUnitChange, resolveSizeValue } from '../utils/resolve-size-value';
8
8
  import { useUnitSync } from './use-unit-sync';
@@ -16,7 +16,7 @@ type UseSizeValueProps< T, U > = {
16
16
  defaultUnit?: U;
17
17
  };
18
18
 
19
- export const useSizeValue = < T extends SizeValue, U extends SizeUnit >( {
19
+ export const useSizeValue = < T extends SizeValue, U extends SizeValue[ 'unit' ] >( {
20
20
  value,
21
21
  setValue,
22
22
  units,
@@ -40,7 +40,7 @@ export const useSizeValue = < T extends SizeValue, U extends SizeUnit >( {
40
40
  } );
41
41
 
42
42
  const [ unit, setUnit ] = useUnitSync( {
43
- unit: sizeValue?.unit,
43
+ sizeValue,
44
44
  setUnit: ( newUnit ) => {
45
45
  setSizeValue( {
46
46
  unit: newUnit,
@@ -48,7 +48,7 @@ export const useSizeValue = < T extends SizeValue, U extends SizeUnit >( {
48
48
  } as T );
49
49
  },
50
50
  persistWhen: () => {
51
- return Boolean( sizeValue.size ) || sizeValue.size !== '';
51
+ return Boolean( sizeValue.size ) || sizeValue.size !== '' || isExtendedUnit( sizeValue.unit );
52
52
  },
53
53
  } );
54
54
 
@@ -1,30 +1,27 @@
1
1
  import { useEffect, useState } from 'react';
2
+ import { type SizePropValue } from '@elementor/editor-props';
2
3
 
3
- import { EXTENDED_UNITS } from '../utils/resolve-size-value';
4
+ import { isExtendedUnit } from '../utils/is-extended-unit';
4
5
 
5
- type UseUnitSyncProps< U > = {
6
- unit: U;
7
- setUnit: ( unit: U ) => void;
6
+ type SizeValue = SizePropValue[ 'value' ];
7
+
8
+ type UseUnitSyncProps = {
9
+ sizeValue: SizeValue;
10
+ setUnit: ( unit: SizeValue[ 'unit' ] ) => void;
8
11
  persistWhen: () => boolean;
9
12
  };
10
13
 
11
- type ExtendedUnit = ( typeof EXTENDED_UNITS )[ keyof typeof EXTENDED_UNITS ];
12
-
13
- export const useUnitSync = < U >( { unit, setUnit, persistWhen }: UseUnitSyncProps< U > ) => {
14
- const [ state, setState ] = useState( unit );
14
+ export const useUnitSync = ( { sizeValue, setUnit, persistWhen }: UseUnitSyncProps ) => {
15
+ const [ state, setState ] = useState( sizeValue.unit );
15
16
 
16
17
  useEffect( () => {
17
- if ( unit !== state ) {
18
- setState( unit );
18
+ if ( sizeValue.unit !== state ) {
19
+ setState( sizeValue.unit );
19
20
  }
20
21
  // eslint-disable-next-line react-hooks/exhaustive-deps
21
- }, [ unit ] );
22
-
23
- const isExtendedUnit = ( value: U ): value is ExtendedUnit & U => {
24
- return Object.values( EXTENDED_UNITS ).includes( value as ExtendedUnit );
25
- };
22
+ }, [ sizeValue.unit, sizeValue.size ] );
26
23
 
27
- const setInternalValue = ( newUnit: U ) => {
24
+ const setInternalValue = ( newUnit: SizeValue[ 'unit' ] ) => {
28
25
  setState( newUnit );
29
26
 
30
27
  if ( isExtendedUnit( newUnit ) || persistWhen() ) {
@@ -1,4 +1,4 @@
1
- import { type SizeUnit } from '../types';
1
+ import { type ExtendedSizeOption, type SizeUnit } from '../types';
2
2
 
3
3
  export const getLengthUnits = () => {
4
4
  return ( window.elementor?.config?.size_units?.length ?? [] ) as SizeUnit[];
@@ -13,5 +13,5 @@ export const getTimeUnits = () => {
13
13
  };
14
14
 
15
15
  export const getExtendedUnits = () => {
16
- return ( window.elementor?.config?.size_units?.extended_units ?? [] ) as SizeUnit[];
16
+ return ( window.elementor?.config?.size_units?.extended_units ?? [] ) as ExtendedSizeOption[];
17
17
  };
@@ -6,10 +6,10 @@ type LengthUnit = 'px' | '%' | 'em' | 'rem' | 'vw' | 'vh' | 'ch';
6
6
  type AngleUnit = 'deg' | 'rad' | 'grad' | 'turn';
7
7
  type TimeUnit = 's' | 'ms';
8
8
 
9
- type ExtendedSizeOption = 'auto' | 'custom';
10
-
11
9
  type Unit = LengthUnit | AngleUnit | TimeUnit;
12
10
 
11
+ export type ExtendedSizeOption = 'auto' | 'custom';
12
+
13
13
  export type SizeUnit = Unit | ExtendedSizeOption;
14
14
 
15
15
  export type SizeVariant = 'length' | 'angle' | 'time';
@@ -1,5 +1,5 @@
1
1
  import * as React from 'react';
2
- import type { RefObject } from 'react';
2
+ import { type RefObject, useRef } from 'react';
3
3
  import { type CreateOptions, sizePropTypeUtil, type SizePropValue } from '@elementor/editor-props';
4
4
 
5
5
  import { type SetValueMeta, useBoundProp } from '../../bound-prop-context';
@@ -7,6 +7,7 @@ import ControlActions from '../../control-actions/control-actions';
7
7
  import { createControl } from '../../create-control';
8
8
  import { SizeComponent } from './size-component';
9
9
  import { type SizeVariant } from './types';
10
+ import { isExtendedUnit } from './utils/is-extended-unit';
10
11
  import { resolveBoundPropValue } from './utils/resolve-bound-prop-value';
11
12
  import { getDefaultUnit } from './utils/settings/get-default-unit';
12
13
  import { getSizeUnits } from './utils/settings/get-size-units';
@@ -31,8 +32,13 @@ export const UnstableSizeControl = createControl(
31
32
  placeholder: boundPropPlaceholder,
32
33
  restoreValue,
33
34
  } = useBoundProp( sizePropTypeUtil );
35
+ const lastNonAutoValue = useRef< SizePropValue[ 'value' ] | null >( null );
34
36
 
35
- const { sizeValue, placeholder } = resolveBoundPropValue( value, boundPropPlaceholder, propPlaceholder );
37
+ const { sizeValue, placeholder } = resolveBoundPropValue(
38
+ value ?? lastNonAutoValue.current,
39
+ boundPropPlaceholder,
40
+ propPlaceholder
41
+ );
36
42
 
37
43
  const units = getSizeUnits( propType, variant );
38
44
  const defaultUnit = getDefaultUnit( propType );
@@ -50,6 +56,13 @@ export const UnstableSizeControl = createControl(
50
56
  };
51
57
 
52
58
  const handleChange = ( newValue: SizePropValue[ 'value' ], options?: CreateOptions, meta?: SetValueMeta ) => {
59
+ if ( isTransitioningFromExtendedUnit( newValue, value ) ) {
60
+ lastNonAutoValue.current = newValue;
61
+
62
+ setValue( null );
63
+ return;
64
+ }
65
+
53
66
  setValue( newValue, options, {
54
67
  ...meta,
55
68
  validation: () => {
@@ -79,3 +92,10 @@ export const UnstableSizeControl = createControl(
79
92
  );
80
93
  }
81
94
  );
95
+
96
+ const isTransitioningFromExtendedUnit = (
97
+ nextValue: SizePropValue[ 'value' ],
98
+ previousValue: SizePropValue[ 'value' ]
99
+ ): boolean => {
100
+ return ! isExtendedUnit( nextValue.unit ) && isExtendedUnit( previousValue?.unit ) && nextValue.size === '';
101
+ };
@@ -1,8 +1,8 @@
1
- import { getExtendedUnits } from '../sync/get-units';
2
- import { type SizeUnit } from '../types';
1
+ import { type SizePropValue } from '@elementor/editor-props';
3
2
 
4
- export const isExtendedUnit = ( unit: SizeUnit ) => {
5
- const extendedUnits = getExtendedUnits();
3
+ import { getExtendedUnits } from '../sync/get-units';
4
+ import { type ExtendedSizeOption } from '../types';
6
5
 
7
- return extendedUnits.includes( unit );
6
+ export const isExtendedUnit = ( unit: SizePropValue[ 'value' ][ 'unit' ] ): unit is ExtendedSizeOption => {
7
+ return getExtendedUnits().includes( unit as ExtendedSizeOption );
8
8
  };
@@ -3,7 +3,7 @@ import { type PropType } from '@elementor/editor-props';
3
3
  import { type SizeUnit } from '../../types';
4
4
 
5
5
  type Settings = {
6
- units?: SizeUnit[];
6
+ available_units?: SizeUnit[];
7
7
  default_unit?: SizeUnit;
8
8
  };
9
9
 
@@ -15,7 +15,7 @@ const getVariantUnits = ( variant: SizeVariant ): SizeUnit[] => {
15
15
  };
16
16
 
17
17
  const getSettingsUnits = ( propType: PropType ) => {
18
- return getPropTypeSettings( propType )?.units;
18
+ return getPropTypeSettings( propType )?.available_units;
19
19
  };
20
20
 
21
21
  export const getSizeUnits = ( propType: PropType, variant: SizeVariant ): SizeUnit[] => {
@@ -5,6 +5,7 @@ import { EXTENDED_UNITS } from './resolve-size-value';
5
5
  type SizeValue = SizePropValue[ 'value' ] | null;
6
6
 
7
7
  const conditions: Array< ( value: SizeValue ) => boolean > = [
8
+ ( value ) => Boolean( value ),
8
9
  ( value ) => value?.size === null || value?.size === undefined || value?.size === '',
9
10
  ( value ) => value?.unit !== EXTENDED_UNITS.auto,
10
11
  ( value ) => value?.unit !== EXTENDED_UNITS.custom,