@elementor/editor-controls 4.1.0-758 → 4.1.0-760

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-758",
4
+ "version": "4.1.0-760",
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-758",
44
- "@elementor/editor-elements": "4.1.0-758",
45
- "@elementor/editor-props": "4.1.0-758",
46
- "@elementor/editor-responsive": "4.1.0-758",
47
- "@elementor/editor-ui": "4.1.0-758",
48
- "@elementor/editor-v1-adapters": "4.1.0-758",
49
- "@elementor/env": "4.1.0-758",
50
- "@elementor/http-client": "4.1.0-758",
43
+ "@elementor/editor-current-user": "4.1.0-760",
44
+ "@elementor/editor-elements": "4.1.0-760",
45
+ "@elementor/editor-props": "4.1.0-760",
46
+ "@elementor/editor-responsive": "4.1.0-760",
47
+ "@elementor/editor-ui": "4.1.0-760",
48
+ "@elementor/editor-v1-adapters": "4.1.0-760",
49
+ "@elementor/env": "4.1.0-760",
50
+ "@elementor/http-client": "4.1.0-760",
51
51
  "@elementor/icons": "^1.68.0",
52
- "@elementor/locations": "4.1.0-758",
53
- "@elementor/events": "4.1.0-758",
54
- "@elementor/query": "4.1.0-758",
55
- "@elementor/session": "4.1.0-758",
52
+ "@elementor/locations": "4.1.0-760",
53
+ "@elementor/events": "4.1.0-760",
54
+ "@elementor/query": "4.1.0-760",
55
+ "@elementor/session": "4.1.0-760",
56
56
  "@elementor/ui": "1.36.17",
57
- "@elementor/utils": "4.1.0-758",
58
- "@elementor/wp-media": "4.1.0-758",
57
+ "@elementor/utils": "4.1.0-760",
58
+ "@elementor/wp-media": "4.1.0-760",
59
59
  "@wordpress/i18n": "^5.13.0",
60
60
  "@monaco-editor/react": "^4.7.0",
61
61
  "dayjs": "^1.11.18",
@@ -6,6 +6,7 @@ import {
6
6
  bindPopover,
7
7
  bindTrigger,
8
8
  Box,
9
+ ClickAwayListener,
9
10
  IconButton,
10
11
  Infotip,
11
12
  Tooltip,
@@ -340,10 +341,14 @@ const RepeaterItem = < T, >( {
340
341
  actions,
341
342
  value,
342
343
  }: RepeaterItemProps< T > ) => {
343
- const { popoverState, popoverProps, ref, setRef } = usePopover( openOnMount, () => {
344
- onOpen();
345
- onPopoverOpen?.( value );
346
- } );
344
+ const { popoverState, popoverProps, ref, setRef } = usePopover(
345
+ openOnMount,
346
+ () => {
347
+ onOpen();
348
+ onPopoverOpen?.( value );
349
+ },
350
+ onPopoverClose
351
+ );
347
352
  const triggerProps = bindTrigger( popoverState );
348
353
 
349
354
  const duplicateLabel = __( 'Duplicate', 'elementor' );
@@ -392,22 +397,20 @@ const RepeaterItem = < T, >( {
392
397
  </>
393
398
  }
394
399
  />
395
- <RepeaterPopover
396
- width={ ref?.getBoundingClientRect().width }
397
- { ...popoverProps }
398
- onClose={ () => {
399
- popoverProps.onClose?.();
400
- onPopoverClose?.();
401
- } }
402
- anchorEl={ ref }
403
- >
404
- <Box>{ children( { anchorEl: ref } ) }</Box>
400
+ <RepeaterPopover width={ ref?.getBoundingClientRect().width } { ...popoverProps } anchorEl={ ref }>
401
+ <ClickAwayListener
402
+ mouseEvent="onMouseDown"
403
+ touchEvent="onTouchStart"
404
+ onClickAway={ popoverProps.onClose }
405
+ >
406
+ <Box>{ children( { anchorEl: ref } ) }</Box>
407
+ </ClickAwayListener>
405
408
  </RepeaterPopover>
406
409
  </>
407
410
  );
408
411
  };
409
412
 
410
- const usePopover = ( openOnMount: boolean, onOpen: () => void ) => {
413
+ const usePopover = ( openOnMount: boolean, onOpen: () => void, onPopoverClose?: () => void ) => {
411
414
  const [ ref, setRef ] = useState< HTMLElement | null >( null );
412
415
 
413
416
  const popoverState = usePopupState( { variant: 'popover' } );
@@ -422,10 +425,15 @@ const usePopover = ( openOnMount: boolean, onOpen: () => void ) => {
422
425
  // eslint-disable-next-line react-hooks/exhaustive-deps
423
426
  }, [ ref ] );
424
427
 
428
+ const onClose = () => {
429
+ popoverProps.onClose?.();
430
+ onPopoverClose?.();
431
+ };
432
+
425
433
  return {
426
434
  popoverState,
427
435
  ref,
428
436
  setRef,
429
- popoverProps,
437
+ popoverProps: { ...popoverProps, onClose },
430
438
  };
431
439
  };
@@ -5,6 +5,7 @@ import { useSyncExternalState } from '../../../hooks/use-sync-external-state';
5
5
  import { type SetSizeValue, type SizeUnit } from '../types';
6
6
  import { isExtendedUnit } from '../utils/is-extended-unit';
7
7
  import { createDefaultSizeValue, resolveSizeOnUnitChange, resolveSizeValue } from '../utils/resolve-size-value';
8
+ import { useUnitSync } from './use-unit-sync';
8
9
 
9
10
  type SizeValue = SizePropValue[ 'value' ];
10
11
 
@@ -38,8 +39,21 @@ export const useSizeValue = < T extends SizeValue, U extends SizeUnit >( {
38
39
  fallback: () => createDefaultSizeValue( units, defaultUnit ),
39
40
  } );
40
41
 
42
+ const [ unit, setUnit ] = useUnitSync( {
43
+ unit: sizeValue?.unit,
44
+ setUnit: ( newUnit ) => {
45
+ setSizeValue( {
46
+ unit: newUnit,
47
+ size: resolveSizeOnUnitChange( sizeValue.size, newUnit ),
48
+ } as T );
49
+ },
50
+ persistWhen: () => {
51
+ return Boolean( sizeValue.size ) || sizeValue.size !== '';
52
+ },
53
+ } );
54
+
41
55
  const setSize = ( newSize: string, isInputValid = true ) => {
42
- if ( isExtendedUnit( sizeValue.unit ) ) {
56
+ if ( isExtendedUnit( unit ) ) {
43
57
  return;
44
58
  }
45
59
 
@@ -47,21 +61,17 @@ export const useSizeValue = < T extends SizeValue, U extends SizeUnit >( {
47
61
  const parsed = Number( trimmed );
48
62
 
49
63
  const newState = {
50
- ...sizeValue,
64
+ unit,
51
65
  size: trimmed && ! isNaN( parsed ) ? parsed : '',
52
- };
66
+ } as T;
53
67
 
54
68
  setSizeValue( newState, undefined, { validation: () => isInputValid } );
55
69
  };
56
70
 
57
- const setUnit = ( unit: SizeValue[ 'unit' ] ) => {
58
- setSizeValue( { unit, size: resolveSizeOnUnitChange( sizeValue.size, unit ) } as T );
59
- };
60
-
61
71
  return {
62
72
  size: sizeValue.size,
63
- unit: sizeValue.unit,
64
73
  setSize,
74
+ unit,
65
75
  setUnit,
66
76
  };
67
77
  };
@@ -0,0 +1,28 @@
1
+ import { useEffect, useState } from 'react';
2
+
3
+ type UseUnitSyncProps< U > = {
4
+ unit: U;
5
+ setUnit: ( unit: U ) => void;
6
+ persistWhen: () => boolean;
7
+ };
8
+
9
+ export const useUnitSync = < U >( { unit, setUnit, persistWhen }: UseUnitSyncProps< U > ) => {
10
+ const [ state, setState ] = useState( unit );
11
+
12
+ useEffect( () => {
13
+ if ( unit !== state ) {
14
+ setState( unit );
15
+ }
16
+ // eslint-disable-next-line react-hooks/exhaustive-deps
17
+ }, [ unit ] );
18
+
19
+ const setInternalValue = ( newUnit: U ) => {
20
+ setState( newUnit );
21
+
22
+ if ( persistWhen() ) {
23
+ setUnit( newUnit );
24
+ }
25
+ };
26
+
27
+ return [ state, setInternalValue ] as const;
28
+ };
@@ -13,7 +13,7 @@ import { getSizeUnits } from './utils/settings/get-size-units';
13
13
  import { shouldNullifyValue } from './utils/should-nullify-value';
14
14
 
15
15
  type Props = {
16
- placeholder?: string;
16
+ placeholder?: string | SizePropValue[ 'value' ];
17
17
  variant?: SizeVariant;
18
18
  anchorRef?: RefObject< HTMLDivElement | null >;
19
19
  startIcon?: React.ReactNode;
@@ -1,55 +1,59 @@
1
- import { sizePropTypeUtil, type SizePropValue } from '@elementor/editor-props';
1
+ import { type PropValue, sizePropTypeUtil, type SizePropValue } from '@elementor/editor-props';
2
2
 
3
- type SizeValue = SizePropValue[ 'value' ] | null;
3
+ type SizeValue = SizePropValue[ 'value' ];
4
4
 
5
- export type ResolvedBoundProp = {
6
- sizeValue: SizeValue;
7
- placeholder: string | undefined;
5
+ type SizeValueResolver< T extends SizeValue > = {
6
+ candidate: PropValue;
7
+ resolve: ( v: T ) => T;
8
8
  };
9
9
 
10
10
  export const resolveBoundPropValue = < T extends SizeValue >(
11
11
  value?: T | null,
12
12
  boundPropPlaceholder?: T | null,
13
- propPlaceholder?: string
14
- ): ResolvedBoundProp => {
15
- let sizeValue: T | null = null;
16
-
17
- if ( validateSizeValue( value ) ) {
18
- sizeValue = value;
19
- } else if ( validateSizeValue( boundPropPlaceholder ) ) {
20
- sizeValue = { size: '', unit: boundPropPlaceholder?.unit } as T;
21
- }
13
+ propPlaceholder?: string | SizeValue
14
+ ) => {
15
+ const sizeValue = pickFirstValid< T >( [
16
+ { candidate: value, resolve: ( v ) => v },
17
+ { candidate: propPlaceholder, resolve: toUnitPlaceholder },
18
+ { candidate: boundPropPlaceholder, resolve: toUnitPlaceholder },
19
+ ] );
20
+
21
+ const placeholderSource = propPlaceholder ?? boundPropPlaceholder;
22
22
 
23
23
  return {
24
24
  sizeValue,
25
- placeholder: resolvePlaceholder( propPlaceholder, boundPropPlaceholder ),
25
+ placeholder: resolvePlaceholder( placeholderSource ),
26
26
  };
27
27
  };
28
28
 
29
- const validateSizeValue = ( value?: SizeValue | null ): value is SizeValue => {
30
- if ( ! value ) {
29
+ const toUnitPlaceholder = < T extends SizeValue >( v: T ): T => ( { ...v, size: '' } );
30
+
31
+ const pickFirstValid = < T extends SizeValue >( candidates: SizeValueResolver< T >[] ): T | null => {
32
+ const found = candidates.find( ( { candidate } ) => validateSizeValue( candidate ) );
33
+
34
+ return found ? found.resolve( found.candidate as T ) : null;
35
+ };
36
+
37
+ const validateSizeValue = ( value: PropValue ): value is SizeValue => {
38
+ if ( ! value || typeof value !== 'object' ) {
31
39
  return false;
32
40
  }
33
41
 
34
- const sizePropValue = sizePropTypeUtil.create( value );
42
+ const sizePropValue = sizePropTypeUtil.create( value as SizeValue );
35
43
 
36
44
  return sizePropTypeUtil.isValid( sizePropValue );
37
45
  };
38
46
 
39
- const resolvePlaceholder = ( propPlaceholder?: string, boundPropPlaceholder?: SizeValue ): string | undefined => {
40
- if ( propPlaceholder ) {
41
- return propPlaceholder;
47
+ const resolvePlaceholder = ( placeholder?: string | null | SizeValue ): string | undefined => {
48
+ if ( typeof placeholder === 'string' ) {
49
+ return placeholder;
42
50
  }
43
51
 
44
- const size = boundPropPlaceholder?.size;
52
+ const size = placeholder?.size;
45
53
 
46
54
  if ( size === undefined ) {
47
55
  return undefined;
48
56
  }
49
57
 
50
- if ( typeof size === 'number' ) {
51
- return size.toString();
52
- }
53
-
54
- return size;
58
+ return typeof size === 'number' ? size.toString() : size;
55
59
  };