@elementor/editor-controls 3.33.0-99 → 3.34.3

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.
Files changed (94) hide show
  1. package/dist/index.d.mts +264 -74
  2. package/dist/index.d.ts +264 -74
  3. package/dist/index.js +2541 -1861
  4. package/dist/index.js.map +1 -1
  5. package/dist/index.mjs +2344 -1660
  6. package/dist/index.mjs.map +1 -1
  7. package/package.json +31 -17
  8. package/src/bound-prop-context/prop-context.tsx +8 -1
  9. package/src/bound-prop-context/use-bound-prop.ts +19 -5
  10. package/src/components/autocomplete.tsx +34 -3
  11. package/src/components/conditional-control-infotip.tsx +64 -0
  12. package/src/components/{unstable-repeater → control-repeater}/actions/disable-item-action.tsx +2 -2
  13. package/src/components/{unstable-repeater → control-repeater}/actions/duplicate-item-action.tsx +10 -4
  14. package/src/components/{unstable-repeater → control-repeater}/actions/remove-item-action.tsx +2 -2
  15. package/src/components/control-repeater/context/item-context.tsx +8 -0
  16. package/src/components/{unstable-repeater → control-repeater}/context/repeater-context.tsx +24 -15
  17. package/src/components/control-repeater/control-repeater.tsx +29 -0
  18. package/src/components/{unstable-repeater → control-repeater}/index.ts +1 -2
  19. package/src/components/{unstable-repeater → control-repeater}/items/edit-item-popover.tsx +6 -20
  20. package/src/components/control-repeater/items/item.tsx +75 -0
  21. package/src/components/{unstable-repeater → control-repeater}/items/items-container.tsx +8 -13
  22. package/src/components/{unstable-repeater → control-repeater}/locations.ts +0 -4
  23. package/src/components/{unstable-repeater → control-repeater}/types.ts +1 -2
  24. package/src/components/control-toggle-button-group.tsx +79 -69
  25. package/src/components/enable-unfiltered-modal.tsx +1 -26
  26. package/src/components/icon-buttons/clear-icon-button.tsx +23 -0
  27. package/src/components/inline-editor-toolbar.tsx +137 -0
  28. package/src/components/inline-editor.tsx +111 -0
  29. package/src/components/item-selector.tsx +10 -4
  30. package/src/components/{unstable-repeater/header/header.tsx → repeater/repeater-header.tsx} +4 -12
  31. package/src/components/repeater/repeater-popover.tsx +19 -0
  32. package/src/components/repeater/repeater-tag.tsx +16 -0
  33. package/src/components/repeater/repeater.tsx +405 -0
  34. package/src/components/{sortable.tsx → repeater/sortable.tsx} +1 -1
  35. package/src/components/size-control/size-input.tsx +20 -14
  36. package/src/components/size-control/text-field-inner-selection.tsx +15 -2
  37. package/src/control-adornments/control-adornments-context.tsx +5 -4
  38. package/src/control-replacements.tsx +3 -43
  39. package/src/controls/background-control/background-control.tsx +43 -12
  40. package/src/controls/background-control/background-gradient-color-control.tsx +5 -8
  41. package/src/controls/background-control/background-overlay/background-image-overlay/background-image-overlay-position.tsx +18 -13
  42. package/src/controls/background-control/background-overlay/background-overlay-repeater-control.tsx +25 -16
  43. package/src/controls/box-shadow-repeater-control.tsx +38 -21
  44. package/src/controls/color-control.tsx +3 -1
  45. package/src/controls/date-time-control.tsx +108 -0
  46. package/src/controls/filter-control/drop-shadow/drop-shadow-item-content.tsx +1 -0
  47. package/src/controls/filter-control/drop-shadow/drop-shadow-item-label.tsx +10 -6
  48. package/src/controls/filter-control/filter-content.tsx +1 -1
  49. package/src/controls/filter-control/filter-repeater-control.tsx +24 -21
  50. package/src/controls/filter-control/single-size/single-size-item-content.tsx +1 -1
  51. package/src/controls/filter-control/single-size/single-size-item-label.tsx +2 -1
  52. package/src/controls/font-family-control/font-family-control.tsx +66 -55
  53. package/src/controls/html-tag-control.tsx +90 -0
  54. package/src/controls/image-media-control.tsx +2 -2
  55. package/src/controls/inline-editing-control.tsx +18 -0
  56. package/src/controls/key-value-control.tsx +8 -2
  57. package/src/controls/link-control.tsx +23 -123
  58. package/src/controls/linked-dimensions-control.tsx +71 -33
  59. package/src/controls/query-control.tsx +168 -0
  60. package/src/controls/repeatable-control.tsx +62 -27
  61. package/src/controls/select-control-wrapper.tsx +57 -0
  62. package/src/controls/select-control.tsx +9 -5
  63. package/src/controls/selection-size-control.tsx +13 -2
  64. package/src/controls/size-control.tsx +32 -59
  65. package/src/controls/svg-media-control.tsx +33 -10
  66. package/src/controls/text-area-control.tsx +5 -1
  67. package/src/controls/text-control.tsx +5 -0
  68. package/src/controls/toggle-control.tsx +11 -2
  69. package/src/controls/transform-control/functions/axis-row.tsx +1 -0
  70. package/src/controls/transform-control/transform-icon.tsx +2 -2
  71. package/src/controls/transform-control/transform-label.tsx +15 -32
  72. package/src/controls/transform-control/transform-repeater-control.tsx +42 -36
  73. package/src/controls/transform-control/{transform-base-control.tsx → transform-settings-control.tsx} +2 -2
  74. package/src/controls/transform-control/use-transform-tabs-history.tsx +1 -1
  75. package/src/controls/transition-control/data.ts +16 -1
  76. package/src/controls/transition-control/trainsition-events.ts +2 -2
  77. package/src/controls/transition-control/transition-repeater-control.tsx +137 -13
  78. package/src/controls/transition-control/transition-selector.tsx +37 -14
  79. package/src/controls/url-control.tsx +21 -16
  80. package/src/hooks/use-filtered-items-list.ts +3 -2
  81. package/src/hooks/use-repeatable-control-context.ts +3 -0
  82. package/src/hooks/use-sync-external-state.tsx +0 -1
  83. package/src/index.ts +21 -5
  84. package/src/utils/convert-toggle-options-to-atomic.tsx +33 -0
  85. package/src/utils/escape-html-attr.ts +11 -0
  86. package/src/components/css-code-editor/css-editor.styles.ts +0 -52
  87. package/src/components/css-code-editor/css-editor.tsx +0 -142
  88. package/src/components/css-code-editor/css-validation.ts +0 -75
  89. package/src/components/css-code-editor/resize-handle.tsx +0 -55
  90. package/src/components/css-code-editor/visual-content-change-protection.ts +0 -69
  91. package/src/components/repeater.tsx +0 -343
  92. package/src/components/unstable-repeater/items/item.tsx +0 -77
  93. package/src/components/unstable-repeater/unstable-repeater.tsx +0 -26
  94. /package/src/components/{unstable-repeater → control-repeater}/actions/tooltip-add-item-action.tsx +0 -0
@@ -1,12 +1,14 @@
1
1
  import * as React from 'react';
2
2
  import { useState } from 'react';
3
+ import { useCurrentUserCapabilities } from '@elementor/editor-current-user';
3
4
  import { imageSrcPropTypeUtil } from '@elementor/editor-props';
4
5
  import { UploadIcon } from '@elementor/icons';
5
- import { Button, Card, CardMedia, CardOverlay, CircularProgress, Stack, styled } from '@elementor/ui';
6
+ import { Button, Card, CardMedia, CardOverlay, CircularProgress, Stack, styled, ThemeProvider } from '@elementor/ui';
6
7
  import { type OpenOptions, useWpMediaAttachment, useWpMediaFrame } from '@elementor/wp-media';
7
8
  import { __ } from '@wordpress/i18n';
8
9
 
9
10
  import { useBoundProp } from '../bound-prop-context';
11
+ import { ConditionalControlInfotip } from '../components/conditional-control-infotip';
10
12
  import { EnableUnfilteredModal } from '../components/enable-unfiltered-modal';
11
13
  import ControlActions from '../control-actions/control-actions';
12
14
  import { createControl } from '../create-control';
@@ -47,6 +49,8 @@ export const SvgMediaControl = createControl( () => {
47
49
  const src = attachment?.url ?? url?.value ?? null;
48
50
  const { data: allowSvgUpload } = useUnfilteredFilesUpload();
49
51
  const [ unfilteredModalOpenState, setUnfilteredModalOpenState ] = useState( false );
52
+ const { canUser } = useCurrentUserCapabilities();
53
+ const canManageOptions = canUser( 'manage_options' );
50
54
 
51
55
  const { open } = useWpMediaFrame( {
52
56
  mediaTypes: [ 'svg' ],
@@ -79,6 +83,18 @@ export const SvgMediaControl = createControl( () => {
79
83
  }
80
84
  };
81
85
 
86
+ const infotipProps = {
87
+ title: __( "Sorry, you can't upload that file yet.", 'elementor' ),
88
+ description: (
89
+ <>
90
+ { __( 'To upload them anyway, ask the site administrator to enable unfiltered', 'elementor' ) }
91
+ <br />
92
+ { __( 'file uploads.', 'elementor' ) }
93
+ </>
94
+ ),
95
+ isEnabled: ! canManageOptions,
96
+ };
97
+
82
98
  return (
83
99
  <Stack gap={ 1 }>
84
100
  <EnableUnfilteredModal open={ unfilteredModalOpenState } onClose={ onCloseUnfilteredModal } />
@@ -112,15 +128,22 @@ export const SvgMediaControl = createControl( () => {
112
128
  >
113
129
  { __( 'Select SVG', 'elementor' ) }
114
130
  </Button>
115
- <Button
116
- size="tiny"
117
- variant="text"
118
- color="inherit"
119
- startIcon={ <UploadIcon /> }
120
- onClick={ () => handleClick( MODE_UPLOAD ) }
121
- >
122
- { __( 'Upload', 'elementor' ) }
123
- </Button>
131
+ <ConditionalControlInfotip { ...infotipProps }>
132
+ <span>
133
+ <ThemeProvider colorScheme={ canManageOptions ? 'light' : 'dark' }>
134
+ <Button
135
+ size="tiny"
136
+ variant="text"
137
+ color="inherit"
138
+ startIcon={ <UploadIcon /> }
139
+ disabled={ canManageOptions ? false : true }
140
+ onClick={ () => canManageOptions && handleClick( MODE_UPLOAD ) }
141
+ >
142
+ { __( 'Upload', 'elementor' ) }
143
+ </Button>
144
+ </ThemeProvider>
145
+ </span>
146
+ </ConditionalControlInfotip>
124
147
  </Stack>
125
148
  </CardOverlay>
126
149
  </StyledCard>
@@ -8,9 +8,10 @@ import { createControl } from '../create-control';
8
8
 
9
9
  type Props = {
10
10
  placeholder?: string;
11
+ ariaLabel?: string;
11
12
  };
12
13
 
13
- export const TextAreaControl = createControl( ( { placeholder }: Props ) => {
14
+ export const TextAreaControl = createControl( ( { placeholder, ariaLabel }: Props ) => {
14
15
  const { value, setValue, disabled } = useBoundProp( stringPropTypeUtil );
15
16
 
16
17
  const handleChange = ( event: React.ChangeEvent< HTMLInputElement > ) => {
@@ -28,6 +29,9 @@ export const TextAreaControl = createControl( ( { placeholder }: Props ) => {
28
29
  value={ value ?? '' }
29
30
  onChange={ handleChange }
30
31
  placeholder={ placeholder }
32
+ inputProps={ {
33
+ ...( ariaLabel ? { 'aria-label': ariaLabel } : {} ),
34
+ } }
31
35
  />
32
36
  </ControlActions>
33
37
  );
@@ -14,6 +14,7 @@ export const TextControl = createControl(
14
14
  inputDisabled,
15
15
  helperText,
16
16
  sx,
17
+ ariaLabel,
17
18
  }: {
18
19
  placeholder?: string;
19
20
  error?: boolean;
@@ -21,6 +22,7 @@ export const TextControl = createControl(
21
22
  inputDisabled?: boolean;
22
23
  helperText?: string;
23
24
  sx?: SxProps;
25
+ ariaLabel?: string;
24
26
  } ) => {
25
27
  const { value, setValue, disabled } = useBoundProp( stringPropTypeUtil );
26
28
  const handleChange = ( event: React.ChangeEvent< HTMLInputElement > ) => setValue( event.target.value );
@@ -37,6 +39,9 @@ export const TextControl = createControl(
37
39
  error={ error }
38
40
  helperText={ helperText }
39
41
  sx={ sx }
42
+ inputProps={ {
43
+ ...( ariaLabel ? { 'aria-label': ariaLabel } : {} ),
44
+ } }
40
45
  />
41
46
  </ControlActions>
42
47
  );
@@ -5,6 +5,7 @@ import { type ToggleButtonProps } from '@elementor/ui';
5
5
  import { useBoundProp } from '../bound-prop-context';
6
6
  import { ControlToggleButtonGroup, type ToggleButtonGroupItem } from '../components/control-toggle-button-group';
7
7
  import { createControl } from '../create-control';
8
+ import { convertToggleOptionsToAtomic, type DynamicToggleOption } from '../utils/convert-toggle-options-to-atomic';
8
9
 
9
10
  export type ToggleControlProps< T extends PropValue > = {
10
11
  options: Array< ToggleButtonGroupItem< T > & { exclusive?: boolean } >;
@@ -12,6 +13,7 @@ export type ToggleControlProps< T extends PropValue > = {
12
13
  size?: ToggleButtonProps[ 'size' ];
13
14
  exclusive?: boolean;
14
15
  maxItems?: number;
16
+ convertOptions?: boolean;
15
17
  };
16
18
 
17
19
  export const ToggleControl = createControl(
@@ -21,10 +23,17 @@ export const ToggleControl = createControl(
21
23
  size = 'tiny',
22
24
  exclusive = true,
23
25
  maxItems,
26
+ convertOptions = false,
24
27
  }: ToggleControlProps< StringPropValue[ 'value' ] > ) => {
25
28
  const { value, setValue, placeholder, disabled } = useBoundProp( stringPropTypeUtil );
26
29
 
27
- const exclusiveValues = options.filter( ( option ) => option.exclusive ).map( ( option ) => option.value );
30
+ const processedOptions = convertOptions
31
+ ? convertToggleOptionsToAtomic( options as DynamicToggleOption[] )
32
+ : ( options as Array< ToggleButtonGroupItem< StringPropValue[ 'value' ] > & { exclusive?: boolean } > );
33
+
34
+ const exclusiveValues = processedOptions
35
+ .filter( ( option ) => option.exclusive )
36
+ .map( ( option ) => option.value );
28
37
 
29
38
  const handleNonExclusiveToggle = ( selectedValues: StringPropValue[ 'value' ][] ) => {
30
39
  const newSelectedValue = selectedValues[ selectedValues.length - 1 ];
@@ -38,7 +47,7 @@ export const ToggleControl = createControl(
38
47
  };
39
48
 
40
49
  const toggleButtonGroupProps = {
41
- items: options,
50
+ items: processedOptions,
42
51
  maxItems,
43
52
  fullWidth,
44
53
  size,
@@ -33,6 +33,7 @@ export const AxisRow = ( { label, bind, startIcon, anchorRef, units, variant = '
33
33
  units={ units }
34
34
  variant={ variant }
35
35
  min={ -Number.MAX_SAFE_INTEGER }
36
+ isRepeaterControl
36
37
  id={ safeId }
37
38
  />
38
39
  </PropKeyProvider>
@@ -1,6 +1,6 @@
1
1
  import * as React from 'react';
2
2
  import { type TransformFunctionsItemPropValue } from '@elementor/editor-props';
3
- import { ArrowsMaximizeIcon, ExpandIcon, RotateClockwise2Icon, SkewXIcon } from '@elementor/icons';
3
+ import { ArrowAutofitHeightIcon, ArrowsMaximizeIcon, RotateClockwise2Icon, SkewXIcon } from '@elementor/icons';
4
4
 
5
5
  import { TransformFunctionKeys } from './initial-values';
6
6
 
@@ -9,7 +9,7 @@ export const TransformIcon = ( { value }: { value: TransformFunctionsItemPropVal
9
9
  case TransformFunctionKeys.move:
10
10
  return <ArrowsMaximizeIcon fontSize="tiny" />;
11
11
  case TransformFunctionKeys.scale:
12
- return <ExpandIcon fontSize="tiny" />;
12
+ return <ArrowAutofitHeightIcon fontSize="tiny" />;
13
13
  case TransformFunctionKeys.rotate:
14
14
  return <RotateClockwise2Icon fontSize="tiny" />;
15
15
  case TransformFunctionKeys.skew:
@@ -3,53 +3,36 @@ import type { TransformFunctionsItemPropValue } from '@elementor/editor-props';
3
3
  import { Box } from '@elementor/ui';
4
4
  import { __ } from '@wordpress/i18n';
5
5
 
6
+ import { CUSTOM_SIZE_LABEL } from '../size-control';
6
7
  import { defaultValues, TransformFunctionKeys } from './initial-values';
7
8
 
8
- const transformMoveValue = ( value: TransformFunctionsItemPropValue[ 'value' ] ) =>
9
- Object.values( value )
9
+ const formatLabel = ( value: TransformFunctionsItemPropValue[ 'value' ], functionType: keyof typeof defaultValues ) => {
10
+ return Object.values( value )
10
11
  .map( ( axis ) => {
11
- const size = axis?.value?.size ?? defaultValues.move.size;
12
- const unit = axis?.value?.unit ?? defaultValues.move.unit;
12
+ if ( functionType === 'scale' ) {
13
+ return axis?.value || defaultValues[ functionType ];
14
+ }
13
15
 
14
- return `${ size }${ unit }`;
15
- } )
16
- .join( ', ' );
17
-
18
- const transformScaleValue = ( value: TransformFunctionsItemPropValue[ 'value' ] ) =>
19
- Object.values( value )
20
- .map( ( axis ) => axis?.value || defaultValues.scale )
21
- .join( ', ' );
22
-
23
- const transformRotateValue = ( value: TransformFunctionsItemPropValue[ 'value' ] ) =>
24
- Object.values( value )
25
- .map( ( axis ) => {
26
- const size = axis?.value?.size ?? defaultValues.rotate.size;
27
- const unit = axis?.value?.unit ?? defaultValues.rotate.unit;
16
+ const defaults = defaultValues[ functionType ];
17
+ const size = axis?.value?.size ?? defaults.size;
18
+ const unit = axis?.value?.unit ?? defaults.unit;
28
19
 
29
- return `${ size }${ unit }`;
30
- } )
31
- .join( ', ' );
32
- const transformSkewValue = ( value: TransformFunctionsItemPropValue[ 'value' ] ) =>
33
- Object.values( value )
34
- .map( ( axis ) => {
35
- const size = axis?.value?.size ?? defaultValues.skew.size;
36
- const unit = axis?.value?.unit ?? defaultValues.skew.unit;
37
-
38
- return `${ size }${ unit }`;
20
+ return unit === 'custom' ? size || CUSTOM_SIZE_LABEL : `${ size }${ unit }`;
39
21
  } )
40
22
  .join( ', ' );
23
+ };
41
24
 
42
25
  export const TransformLabel = ( props: { value: TransformFunctionsItemPropValue } ) => {
43
26
  const { $$type, value } = props.value;
44
27
  switch ( $$type ) {
45
28
  case TransformFunctionKeys.move:
46
- return <Label label={ __( 'Move', 'elementor' ) } value={ transformMoveValue( value ) } />;
29
+ return <Label label={ __( 'Move', 'elementor' ) } value={ formatLabel( value, 'move' ) } />;
47
30
  case TransformFunctionKeys.scale:
48
- return <Label label={ __( 'Scale', 'elementor' ) } value={ transformScaleValue( value ) } />;
31
+ return <Label label={ __( 'Scale', 'elementor' ) } value={ formatLabel( value, 'scale' ) } />;
49
32
  case TransformFunctionKeys.rotate:
50
- return <Label label={ __( 'Rotate', 'elementor' ) } value={ transformRotateValue( value ) } />;
33
+ return <Label label={ __( 'Rotate', 'elementor' ) } value={ formatLabel( value, 'rotate' ) } />;
51
34
  case TransformFunctionKeys.skew:
52
- return <Label label={ __( 'Skew', 'elementor' ) } value={ transformSkewValue( value ) } />;
35
+ return <Label label={ __( 'Skew', 'elementor' ) } value={ formatLabel( value, 'skew' ) } />;
53
36
  default:
54
37
  return '';
55
38
  }
@@ -2,28 +2,22 @@ import * as React from 'react';
2
2
  import { useRef } from 'react';
3
3
  import { type PropType, transformFunctionsPropTypeUtil, transformPropTypeUtil } from '@elementor/editor-props';
4
4
  import { AdjustmentsIcon, InfoCircleFilledIcon } from '@elementor/icons';
5
- import { bindTrigger, Box, IconButton, type PopupState, Typography, usePopupState } from '@elementor/ui';
5
+ import { bindTrigger, Box, IconButton, type PopupState, Tooltip, Typography, usePopupState } from '@elementor/ui';
6
6
  import { __ } from '@wordpress/i18n';
7
7
 
8
8
  import { PropKeyProvider, PropProvider, useBoundProp } from '../../bound-prop-context';
9
- import {
10
- Header,
11
- Item,
12
- ItemsContainer,
13
- TooltipAddItemAction,
14
- UnstableRepeater,
15
- } from '../../components/unstable-repeater';
16
- import { DisableItemAction } from '../../components/unstable-repeater/actions/disable-item-action';
17
- import { RemoveItemAction } from '../../components/unstable-repeater/actions/remove-item-action';
18
- import { EditItemPopover } from '../../components/unstable-repeater/items/edit-item-popover';
19
- import { injectIntoRepeaterHeaderActions } from '../../components/unstable-repeater/locations';
9
+ import { ControlRepeater, Item, ItemsContainer, TooltipAddItemAction } from '../../components/control-repeater';
10
+ import { DisableItemAction } from '../../components/control-repeater/actions/disable-item-action';
11
+ import { RemoveItemAction } from '../../components/control-repeater/actions/remove-item-action';
12
+ import { EditItemPopover } from '../../components/control-repeater/items/edit-item-popover';
13
+ import { RepeaterHeader } from '../../components/repeater/repeater-header';
20
14
  import { ControlAdornments } from '../../control-adornments/control-adornments';
21
15
  import { createControl } from '../../create-control';
22
16
  import { initialRotateValue, initialScaleValue, initialSkewValue, initialTransformValue } from './initial-values';
23
- import { TransformBaseControl } from './transform-base-control';
24
17
  import { TransformContent } from './transform-content';
25
18
  import { TransformIcon } from './transform-icon';
26
19
  import { TransformLabel } from './transform-label';
20
+ import { TransformSettingsControl } from './transform-settings-control';
27
21
 
28
22
  const SIZE = 'tiny';
29
23
 
@@ -32,19 +26,11 @@ export const TransformRepeaterControl = createControl( () => {
32
26
  const headerRef = useRef< HTMLDivElement >( null );
33
27
  const popupState = usePopupState( { variant: 'popover' } );
34
28
 
35
- const repeaterBindKey = 'transform-functions';
36
-
37
- injectIntoRepeaterHeaderActions( {
38
- id: 'transform-base-control',
39
- component: () => <TransformBasePopoverTrigger popupState={ popupState } repeaterBindKey={ repeaterBindKey } />,
40
- options: { overwrite: true },
41
- } );
42
-
43
29
  return (
44
30
  <PropProvider { ...context }>
45
- <TransformBaseControl popupState={ popupState } anchorRef={ headerRef } />
46
- <PropKeyProvider bind={ repeaterBindKey }>
47
- <Repeater headerRef={ headerRef } propType={ context.propType } />
31
+ <TransformSettingsControl popupState={ popupState } anchorRef={ headerRef } />
32
+ <PropKeyProvider bind={ 'transform-functions' }>
33
+ <Repeater headerRef={ headerRef } propType={ context.propType } popupState={ popupState } />
48
34
  </PropKeyProvider>
49
35
  </PropProvider>
50
36
  );
@@ -63,10 +49,18 @@ const ToolTip = (
63
49
  </Box>
64
50
  );
65
51
 
66
- const Repeater = ( { headerRef, propType }: { headerRef: React.RefObject< HTMLDivElement >; propType: PropType } ) => {
52
+ const Repeater = ( {
53
+ headerRef,
54
+ propType,
55
+ popupState,
56
+ }: {
57
+ headerRef: React.RefObject< HTMLDivElement >;
58
+ propType: PropType;
59
+ popupState: PopupState;
60
+ } ) => {
67
61
  const transformFunctionsContext = useBoundProp( transformFunctionsPropTypeUtil );
68
62
  const availableValues = [ initialTransformValue, initialScaleValue, initialRotateValue, initialSkewValue ];
69
- const { value: transformValues } = transformFunctionsContext;
63
+ const { value: transformValues, bind } = transformFunctionsContext;
70
64
 
71
65
  const getInitialValue = () => {
72
66
  return availableValues.find( ( value ) => ! transformValues?.some( ( item ) => item.$$type === value.$$type ) );
@@ -76,30 +70,39 @@ const Repeater = ( { headerRef, propType }: { headerRef: React.RefObject< HTMLDi
76
70
 
77
71
  return (
78
72
  <PropProvider { ...transformFunctionsContext }>
79
- <UnstableRepeater
73
+ <ControlRepeater
80
74
  initial={ getInitialValue() ?? initialTransformValue }
81
75
  propTypeUtil={ transformFunctionsPropTypeUtil }
82
76
  >
83
- <Header
77
+ <RepeaterHeader
84
78
  label={ __( 'Transform', 'elementor' ) }
85
79
  adornment={ () => <ControlAdornments customContext={ { path: [ 'transform' ], propType } } /> }
86
80
  ref={ headerRef }
87
81
  >
82
+ <TransformBasePopoverTrigger popupState={ popupState } repeaterBindKey={ bind } />
88
83
  <TooltipAddItemAction
89
84
  disabled={ shouldDisableAddItem }
90
85
  tooltipContent={ ToolTip }
91
86
  enableTooltip={ shouldDisableAddItem }
92
87
  ariaLabel={ 'transform' }
93
88
  />
94
- </Header>
95
- <ItemsContainer itemTemplate={ <Item Icon={ TransformIcon } Label={ TransformLabel } /> }>
96
- <DisableItemAction />
97
- <RemoveItemAction />
89
+ </RepeaterHeader>
90
+ <ItemsContainer>
91
+ <Item
92
+ Icon={ TransformIcon }
93
+ Label={ TransformLabel }
94
+ actions={
95
+ <>
96
+ <DisableItemAction />
97
+ <RemoveItemAction />
98
+ </>
99
+ }
100
+ />
98
101
  </ItemsContainer>
99
102
  <EditItemPopover>
100
103
  <TransformContent />
101
104
  </EditItemPopover>
102
- </UnstableRepeater>
105
+ </ControlRepeater>
103
106
  </PropProvider>
104
107
  );
105
108
  };
@@ -112,10 +115,13 @@ const TransformBasePopoverTrigger = ( {
112
115
  repeaterBindKey: string;
113
116
  } ) => {
114
117
  const { bind } = useBoundProp();
118
+ const titleLabel = __( 'Transform settings', 'elementor' );
115
119
 
116
120
  return bind !== repeaterBindKey ? null : (
117
- <IconButton size={ SIZE } aria-label={ __( 'Base Transform', 'elementor' ) } { ...bindTrigger( popupState ) }>
118
- <AdjustmentsIcon fontSize={ SIZE } />
119
- </IconButton>
121
+ <Tooltip title={ titleLabel } placement="top">
122
+ <IconButton size={ SIZE } aria-label={ titleLabel } { ...bindTrigger( popupState ) }>
123
+ <AdjustmentsIcon fontSize={ SIZE } />
124
+ </IconButton>
125
+ </Tooltip>
120
126
  );
121
127
  };
@@ -11,7 +11,7 @@ import { TransformOriginControl } from './transform-base-controls/transform-orig
11
11
 
12
12
  const SIZE = 'tiny';
13
13
 
14
- export const TransformBaseControl = ( {
14
+ export const TransformSettingsControl = ( {
15
15
  popupState,
16
16
  anchorRef,
17
17
  }: {
@@ -38,7 +38,7 @@ export const TransformBaseControl = ( {
38
38
  { ...popupProps }
39
39
  >
40
40
  <PopoverHeader
41
- title={ __( 'Base Transform', 'elementor' ) }
41
+ title={ __( 'Transform settings', 'elementor' ) }
42
42
  onClose={ popupState.close }
43
43
  icon={ <AdjustmentsIcon fontSize={ SIZE } /> }
44
44
  />
@@ -13,7 +13,7 @@ import {
13
13
  import { useTabs } from '@elementor/ui';
14
14
 
15
15
  import { useBoundProp } from '../../bound-prop-context';
16
- import { useRepeaterContext } from '../../components/unstable-repeater/context/repeater-context';
16
+ import { useRepeaterContext } from '../../components/control-repeater/context/repeater-context';
17
17
  import { type TransformFunction, TransformFunctionKeys } from './initial-values';
18
18
 
19
19
  type InitialTransformValues = {
@@ -1,9 +1,11 @@
1
+ import { type KeyValuePropValue, type SizePropValue } from '@elementor/editor-props';
1
2
  import { __ } from '@wordpress/i18n';
2
3
 
3
4
  export type TransitionProperty = {
4
5
  label: string;
5
6
  value: string;
6
7
  unavailable?: boolean;
8
+ isDisabled?: boolean;
7
9
  };
8
10
 
9
11
  export type TransitionCategory = {
@@ -12,7 +14,20 @@ export type TransitionCategory = {
12
14
  properties: TransitionProperty[];
13
15
  };
14
16
 
15
- export const initialTransitionValue = {
17
+ export type TransitionValue = {
18
+ selection: KeyValuePropValue;
19
+ size: SizePropValue;
20
+ };
21
+
22
+ export type TransitionItem = {
23
+ $$type: 'selection-size';
24
+ value: {
25
+ $$type: 'key-value';
26
+ value: TransitionValue;
27
+ };
28
+ };
29
+
30
+ export const initialTransitionValue: TransitionValue = {
16
31
  selection: {
17
32
  $$type: 'key-value',
18
33
  value: {
@@ -1,5 +1,5 @@
1
1
  import { getSelectedElements } from '@elementor/editor-elements';
2
- import { sendMixpanelEvent } from '@elementor/utils';
2
+ import { trackEvent } from '@elementor/mixpanel';
3
3
 
4
4
  import { eventBus } from '../../services/event-bus';
5
5
  import { type initialTransitionValue } from './data';
@@ -19,7 +19,7 @@ export function subscribeToTransitionEvent() {
19
19
  const value = payload?.itemValue?.selection?.value?.value?.value;
20
20
  const selectedElements = getSelectedElements();
21
21
  const widgetType = selectedElements[ 0 ]?.type ?? null;
22
- sendMixpanelEvent( {
22
+ trackEvent( {
23
23
  transition_type: value ?? 'unknown',
24
24
  ...transitionRepeaterMixpanelEvent,
25
25
  widget_type: widgetType,