@elementor/editor-controls 3.32.0-28 → 3.32.0-30

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 (33) hide show
  1. package/dist/index.d.mts +1 -3
  2. package/dist/index.d.ts +1 -3
  3. package/dist/index.js +274 -282
  4. package/dist/index.js.map +1 -1
  5. package/dist/index.mjs +235 -242
  6. package/dist/index.mjs.map +1 -1
  7. package/package.json +14 -14
  8. package/src/components/unstable-repeater/actions/disable-item-action.tsx +2 -2
  9. package/src/components/unstable-repeater/actions/duplicate-item-action.tsx +3 -3
  10. package/src/components/unstable-repeater/actions/tooltip-add-item-action.tsx +66 -0
  11. package/src/components/unstable-repeater/context/repeater-context.tsx +52 -67
  12. package/src/components/unstable-repeater/header/header.tsx +2 -2
  13. package/src/components/unstable-repeater/index.ts +1 -1
  14. package/src/components/unstable-repeater/items/edit-item-popover.tsx +28 -12
  15. package/src/components/unstable-repeater/items/item.tsx +15 -19
  16. package/src/components/unstable-repeater/items/items-container.tsx +17 -15
  17. package/src/components/unstable-repeater/types.ts +2 -12
  18. package/src/components/unstable-repeater/unstable-repeater.tsx +5 -3
  19. package/src/controls/background-control/background-overlay/background-overlay-repeater-control.tsx +25 -23
  20. package/src/controls/transform-control/functions/move.tsx +1 -1
  21. package/src/controls/transform-control/functions/rotate.tsx +1 -1
  22. package/src/controls/transform-control/functions/scale.tsx +1 -1
  23. package/src/controls/transform-control/functions/skew.tsx +1 -1
  24. package/src/controls/transform-control/transform-content.tsx +2 -12
  25. package/src/controls/transform-control/transform-icon.tsx +1 -1
  26. package/src/controls/transform-control/transform-label.tsx +1 -1
  27. package/src/controls/transform-control/transform-repeater-control.tsx +49 -17
  28. package/src/controls/transform-control/use-transform-tabs-history.tsx +12 -2
  29. package/src/index.ts +0 -1
  30. package/src/components/unstable-repeater/actions/add-item-action.tsx +0 -50
  31. package/src/components/unstable-repeater/items/use-popover.tsx +0 -26
  32. package/src/controls/unstable-transform-control/unstable-transform-repeater-control.tsx +0 -35
  33. /package/src/controls/transform-control/{types.ts → initial-values.ts} +0 -0
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": "3.32.0-28",
4
+ "version": "3.32.0-30",
5
5
  "private": false,
6
6
  "author": "Elementor Team",
7
7
  "homepage": "https://elementor.com/",
@@ -40,21 +40,21 @@
40
40
  "dev": "tsup --config=../../tsup.dev.ts"
41
41
  },
42
42
  "dependencies": {
43
- "@elementor/editor-current-user": "3.32.0-28",
44
- "@elementor/editor-elements": "3.32.0-28",
45
- "@elementor/editor-props": "3.32.0-28",
46
- "@elementor/editor-responsive": "3.32.0-28",
47
- "@elementor/editor-ui": "3.32.0-28",
48
- "@elementor/editor-v1-adapters": "3.32.0-28",
49
- "@elementor/env": "3.32.0-28",
50
- "@elementor/http-client": "3.32.0-28",
43
+ "@elementor/editor-current-user": "3.32.0-30",
44
+ "@elementor/editor-elements": "3.32.0-30",
45
+ "@elementor/editor-props": "3.32.0-30",
46
+ "@elementor/editor-responsive": "3.32.0-30",
47
+ "@elementor/editor-ui": "3.32.0-30",
48
+ "@elementor/editor-v1-adapters": "3.32.0-30",
49
+ "@elementor/env": "3.32.0-30",
50
+ "@elementor/http-client": "3.32.0-30",
51
51
  "@elementor/icons": "^1.51.1",
52
- "@elementor/locations": "3.32.0-28",
53
- "@elementor/query": "3.32.0-28",
54
- "@elementor/session": "3.32.0-28",
52
+ "@elementor/locations": "3.32.0-30",
53
+ "@elementor/query": "3.32.0-30",
54
+ "@elementor/session": "3.32.0-30",
55
55
  "@elementor/ui": "1.36.2",
56
- "@elementor/utils": "3.32.0-28",
57
- "@elementor/wp-media": "3.32.0-28",
56
+ "@elementor/utils": "3.32.0-30",
57
+ "@elementor/wp-media": "3.32.0-30",
58
58
  "@wordpress/i18n": "^5.13.0",
59
59
  "@monaco-editor/react": "^4.7.0"
60
60
  },
@@ -13,12 +13,12 @@ export const DisableItemAction = ( { index = -1 }: { index?: number } ) => {
13
13
  return null;
14
14
  }
15
15
 
16
- const propDisabled = items[ index ]?.disabled ?? false;
16
+ const propDisabled = items[ index ].item.disabled ?? false;
17
17
 
18
18
  const toggleLabel = propDisabled ? __( 'Show', 'elementor' ) : __( 'Hide', 'elementor' );
19
19
 
20
20
  const onClick = () => {
21
- const self = structuredClone( items[ index ] );
21
+ const self = structuredClone( items[ index ].item );
22
22
 
23
23
  self.disabled = ! self.disabled;
24
24
 
@@ -16,10 +16,10 @@ export const DuplicateItemAction = ( { index = -1 }: { index?: number } ) => {
16
16
 
17
17
  const duplicateLabel = __( 'Duplicate', 'elementor' );
18
18
 
19
- const onClick = () => {
20
- const newItem = structuredClone( items[ index ] );
19
+ const onClick = ( ev: React.MouseEvent ) => {
20
+ const newItem = structuredClone( items[ index ]?.item );
21
21
 
22
- addItem( { item: newItem, index: index + 1 } );
22
+ addItem( ev, { item: newItem, index: index + 1 } );
23
23
  };
24
24
 
25
25
  return (
@@ -0,0 +1,66 @@
1
+ import * as React from 'react';
2
+ import { PlusIcon } from '@elementor/icons';
3
+ import { Box, IconButton, Infotip } from '@elementor/ui';
4
+ import { __ } from '@wordpress/i18n';
5
+
6
+ import { useRepeaterContext } from '../context/repeater-context';
7
+
8
+ const SIZE = 'tiny';
9
+
10
+ export const TooltipAddItemAction = ( {
11
+ disabled = false,
12
+ enableTooltip = false,
13
+ tooltipContent = null,
14
+ newItemIndex,
15
+ }: {
16
+ disabled?: boolean;
17
+ enableTooltip?: boolean;
18
+ tooltipContent?: React.ReactNode;
19
+ newItemIndex?: number;
20
+ } ) => {
21
+ const { addItem } = useRepeaterContext();
22
+
23
+ const onClick = ( ev: React.MouseEvent ) => addItem( ev, { index: newItemIndex } );
24
+
25
+ return (
26
+ <ConditionalToolTip content={ tooltipContent } enable={ enableTooltip }>
27
+ <Box sx={ { ml: 'auto' } }>
28
+ <IconButton
29
+ size={ SIZE }
30
+ disabled={ disabled }
31
+ onClick={ onClick }
32
+ aria-label={ __( 'Add item', 'elementor' ) }
33
+ >
34
+ <PlusIcon fontSize={ SIZE } />
35
+ </IconButton>
36
+ </Box>
37
+ </ConditionalToolTip>
38
+ );
39
+ };
40
+
41
+ const ConditionalToolTip = ( {
42
+ children,
43
+ enable,
44
+ content,
45
+ }: React.PropsWithChildren< {
46
+ content?: React.ReactNode;
47
+ enable: boolean;
48
+ } > ) =>
49
+ enable && content ? (
50
+ <Infotip
51
+ placement="right"
52
+ content={
53
+ <Box
54
+ component="span"
55
+ aria-label={ undefined }
56
+ sx={ { display: 'flex', gap: 0.5, p: 2, width: 320, borderRadius: 1 } }
57
+ >
58
+ { content }
59
+ </Box>
60
+ }
61
+ >
62
+ { children }
63
+ </Infotip>
64
+ ) : (
65
+ children
66
+ );
@@ -1,35 +1,36 @@
1
1
  import * as React from 'react';
2
2
  import { createContext, useState } from 'react';
3
- import { type PropTypeUtil, type PropValue } from '@elementor/editor-props';
3
+ import { type PropTypeUtil } from '@elementor/editor-props';
4
+ import { type PopupState, usePopupState } from '@elementor/ui';
4
5
 
5
6
  import { useBoundProp } from '../../../bound-prop-context/use-bound-prop';
6
7
  import { useSyncExternalState } from '../../../hooks/use-sync-external-state';
7
- import { type Item } from '../types';
8
+ import { type Item, type RepeatablePropValue } from '../types';
8
9
 
9
- type SetterFn< T extends PropValue > = ( prevItems: T[] ) => T[];
10
+ type SetterFn< T > = ( prevItems: T ) => T;
10
11
 
11
12
  type AddItem< T > = { item?: T; index?: number };
12
13
 
13
- type RepeaterContextType< T extends PropValue > = {
14
+ type ItemWithKey< T > = { key: number; item: T };
15
+
16
+ type RepeaterContextType< T extends RepeatablePropValue > = {
14
17
  isOpen: boolean;
15
- openItem: number;
16
- setOpenItem: ( key: number ) => void;
17
- items: Item< T >[];
18
- setItems: ( items: T[] | SetterFn< T > ) => void;
18
+ openItemIndex: number;
19
+ setOpenItemIndex: ( key: number ) => void;
20
+ items: ItemWithKey< Item< T > >[];
21
+ setItems: ( items: ItemWithKey< T >[] ) => void;
22
+ popoverState: PopupState;
19
23
  initial: T;
20
- uniqueKeys: number[];
21
- setUniqueKeys: ( keys: number[] ) => void;
22
- isSortable: boolean;
23
- generateNextKey: ( source: number[] ) => number;
24
- addItem: ( config?: AddItem< T > ) => void;
24
+ addItem: ( ev: React.MouseEvent, config?: AddItem< T > ) => void;
25
25
  updateItem: ( item: T, index: number ) => void;
26
26
  removeItem: ( index: number ) => void;
27
- sortItemsByKeys: ( newKeysOrder: number[] ) => void;
27
+ rowRef: HTMLElement | null;
28
+ setRowRef: ( ref: HTMLElement | null | SetterFn< HTMLElement | null > ) => void;
28
29
  };
29
30
 
30
- const RepeaterContext = createContext< RepeaterContextType< PropValue > | null >( null );
31
+ const RepeaterContext = createContext< RepeaterContextType< RepeatablePropValue > | null >( null );
31
32
 
32
- const EMPTY_OPEN_ITEM = -1;
33
+ export const EMPTY_OPEN_ITEM = -1;
33
34
 
34
35
  export const useRepeaterContext = () => {
35
36
  const context = React.useContext( RepeaterContext );
@@ -38,29 +39,13 @@ export const useRepeaterContext = () => {
38
39
  throw new Error( 'useRepeaterContext must be used within a RepeaterContextProvider' );
39
40
  }
40
41
 
41
- return {
42
- isOpen: context.isOpen,
43
- openItem: context.openItem,
44
- setOpenItem: context.setOpenItem,
45
- items: context.items,
46
- setItems: context.setItems,
47
- uniqueKeys: context.uniqueKeys,
48
- setUniqueKeys: context.setUniqueKeys,
49
- initial: context.initial,
50
- isSortable: context.isSortable,
51
- generateNextKey: context.generateNextKey,
52
- sortItemsByKeys: context.sortItemsByKeys,
53
- addItem: context.addItem,
54
- updateItem: context.updateItem,
55
- removeItem: context.removeItem,
56
- };
42
+ return context;
57
43
  };
58
44
 
59
- export const RepeaterContextProvider = < T extends PropValue = PropValue >( {
45
+ export const RepeaterContextProvider = < T extends RepeatablePropValue = RepeatablePropValue >( {
60
46
  children,
61
47
  initial,
62
48
  propTypeUtil,
63
- isSortable = true,
64
49
  }: React.PropsWithChildren< { initial: T; propTypeUtil: PropTypeUtil< string, T[] >; isSortable?: boolean } > ) => {
65
50
  const { value: repeaterValues, setValue: setRepeaterValues } = useBoundProp( propTypeUtil );
66
51
 
@@ -71,60 +56,60 @@ export const RepeaterContextProvider = < T extends PropValue = PropValue >( {
71
56
  persistWhen: () => true,
72
57
  } );
73
58
 
74
- const [ openItem, setOpenItem ] = useState( EMPTY_OPEN_ITEM );
75
- const [ uniqueKeys, setUniqueKeys ] = useState( items?.map( ( _, index ) => index ) ?? [] );
59
+ const itemWithKeysState = useState< ItemWithKey< T >[] >(
60
+ items?.map( ( item, index ) => ( { key: index, item } ) ) ?? []
61
+ );
76
62
 
77
- const isOpen = openItem !== EMPTY_OPEN_ITEM;
63
+ const itemsWithKeys = itemWithKeysState[ 0 ];
64
+ const setItemsWithKeys = ( newItems: ItemWithKey< T >[] ) => {
65
+ itemWithKeysState[ 1 ]( newItems as ItemWithKey< T >[] );
66
+ setItems( newItems.map( ( { item } ) => item as T ) );
67
+ };
78
68
 
79
- const sortItemsByKeys = ( keysOrder: number[] ) => {
80
- setUniqueKeys( keysOrder );
81
- setItems( ( prevItems ) =>
82
- keysOrder.map( ( key ) => {
83
- const index = uniqueKeys.indexOf( key );
69
+ const [ openItemIndex, setOpenItemIndex ] = useState( EMPTY_OPEN_ITEM );
70
+ const [ rowRef, setRowRef ] = useState< HTMLElement | null >( null );
84
71
 
85
- return prevItems[ index ];
86
- } )
87
- );
88
- };
72
+ const isOpen = openItemIndex !== EMPTY_OPEN_ITEM;
73
+ const popoverState = usePopupState( { variant: 'popover' } );
89
74
 
90
- const addItem = ( config?: AddItem< T > ) => {
75
+ const addItem = ( ev: React.MouseEvent, config?: AddItem< T > ) => {
91
76
  const item = config?.item ?? initial;
92
- const index = config?.index ?? items.length;
93
- const newItems = [ ...items ];
77
+ const newIndex = config?.index ?? items.length;
78
+ const newKey = generateNextKey( itemsWithKeys.map( ( { key } ) => key ) );
79
+ const newItemsWithKeys = [ ...itemsWithKeys ];
94
80
 
95
- newItems.splice( index, 0, item );
96
- setItems( newItems );
97
- setUniqueKeys( newItems.map( ( _, i ) => i ) );
81
+ newItemsWithKeys.splice( newIndex, 0, { item, key: newKey } );
82
+ setItemsWithKeys( newItemsWithKeys );
98
83
 
99
- setOpenItem( index );
84
+ setOpenItemIndex( newIndex );
85
+ popoverState.open( rowRef ?? ev );
100
86
  };
101
87
 
102
88
  const removeItem = ( index: number ) => {
103
- setItems( ( prevItems ) => prevItems.filter( ( _, pos ) => pos !== index ) );
104
- setUniqueKeys( ( prevKeys ) => prevKeys.slice( 0, -1 ) );
89
+ setItemsWithKeys( itemsWithKeys.filter( ( _, pos ) => pos !== index ) );
105
90
  };
106
91
 
107
92
  const updateItem = ( updatedItem: T, index: number ) => {
108
- setItems( ( prevItems ) => prevItems.map( ( item, pos ) => ( pos === index ? updatedItem : item ) ) );
93
+ const item = itemsWithKeys[ index ];
94
+
95
+ setItemsWithKeys( itemsWithKeys.toSpliced( index, 1, { ...item, item: updatedItem } ) );
109
96
  };
110
97
 
111
98
  return (
112
99
  <RepeaterContext.Provider
113
100
  value={ {
114
101
  isOpen,
115
- openItem,
116
- setOpenItem,
117
- items: ( items ?? [] ) as Item< T >[],
118
- setItems: setItems as ( items: PropValue[] | SetterFn< PropValue > ) => void,
102
+ openItemIndex,
103
+ setOpenItemIndex,
104
+ items: ( itemsWithKeys ?? [] ) as RepeaterContextType< T >[ 'items' ],
105
+ setItems: setItemsWithKeys as RepeaterContextType< RepeatablePropValue >[ 'setItems' ],
106
+ popoverState,
119
107
  initial,
120
- uniqueKeys,
121
- setUniqueKeys,
122
- isSortable,
123
- generateNextKey,
124
- sortItemsByKeys,
125
- addItem: addItem as ( config?: AddItem< PropValue > ) => void,
126
- updateItem: updateItem as ( item: PropValue, index: number ) => void,
108
+ updateItem: updateItem as RepeaterContextType< RepeatablePropValue >[ 'updateItem' ],
109
+ addItem: addItem as RepeaterContextType< RepeatablePropValue >[ 'addItem' ],
127
110
  removeItem,
111
+ rowRef,
112
+ setRowRef,
128
113
  } }
129
114
  >
130
115
  { children }
@@ -4,7 +4,7 @@ import { Stack, Typography } from '@elementor/ui';
4
4
  import { useBoundProp } from '../../../bound-prop-context/use-bound-prop';
5
5
  import { ControlAdornments } from '../../../control-adornments/control-adornments';
6
6
  import { SlotChildren } from '../../../control-replacements';
7
- import { AddItemAction } from '../actions/add-item-action';
7
+ import { TooltipAddItemAction } from '../actions/tooltip-add-item-action';
8
8
  import { RepeaterHeaderActionsSlot } from '../locations';
9
9
 
10
10
  export const Header = ( { label, children }: React.PropsWithChildren< { label: string } > ) => {
@@ -16,7 +16,7 @@ export const Header = ( { label, children }: React.PropsWithChildren< { label: s
16
16
  { label }
17
17
  </Typography>
18
18
  <RepeaterHeaderActionsSlot value={ value } />
19
- <SlotChildren whitelist={ [ AddItemAction ] as React.FC[] }>{ children }</SlotChildren>
19
+ <SlotChildren whitelist={ [ TooltipAddItemAction ] as React.FC[] }>{ children }</SlotChildren>
20
20
  <ControlAdornments />
21
21
  </Stack>
22
22
  );
@@ -1,4 +1,4 @@
1
- export { AddItemAction } from './actions/add-item-action';
1
+ export { TooltipAddItemAction } from './actions/tooltip-add-item-action';
2
2
  export { Header } from './header/header';
3
3
  export { ItemsContainer } from './items/items-container';
4
4
  export { Item } from './items/item';
@@ -1,28 +1,44 @@
1
1
  import * as React from 'react';
2
- import { Box, Popover, type PopoverProps } from '@elementor/ui';
2
+ import { bindPopover, Box, Popover } from '@elementor/ui';
3
3
 
4
- type AddItemPopoverProps = {
5
- anchorRef: HTMLElement | null;
6
- setAnchorEl: ( el: HTMLElement | null ) => void;
7
- popoverProps: Partial< PopoverProps >;
8
- children?: React.ReactNode;
9
- };
4
+ import { PropKeyProvider } from '../../../bound-prop-context';
5
+ import { EMPTY_OPEN_ITEM, useRepeaterContext } from '../context/repeater-context';
6
+
7
+ export const EditItemPopover = ( { children }: { children: React.ReactNode } ) => {
8
+ const { popoverState, openItemIndex, isOpen, rowRef, setOpenItemIndex, setRowRef, items } = useRepeaterContext();
9
+ const popoverProps = bindPopover( popoverState );
10
+
11
+ if ( ! isOpen || ! rowRef ) {
12
+ return null;
13
+ }
14
+
15
+ const bind = items[ openItemIndex ].item.$$type;
16
+
17
+ const onClose = () => {
18
+ popoverProps.onClose?.();
19
+ setRowRef( null );
20
+ setOpenItemIndex( EMPTY_OPEN_ITEM );
21
+ };
10
22
 
11
- export const EditItemPopover = ( { children, anchorRef, setAnchorEl, popoverProps }: AddItemPopoverProps ) => {
12
23
  return (
13
24
  <Popover
14
25
  disablePortal
15
26
  slotProps={ {
16
27
  paper: {
17
- ref: setAnchorEl,
18
- sx: { mt: 0.5, width: anchorRef?.offsetWidth },
28
+ sx: { mt: 0.5, width: rowRef.offsetWidth },
19
29
  },
20
30
  } }
21
31
  anchorOrigin={ { vertical: 'bottom', horizontal: 'left' } }
22
- anchorEl={ anchorRef }
23
32
  { ...popoverProps }
33
+ anchorEl={ rowRef }
34
+ onClose={ onClose }
24
35
  >
25
- <Box>{ children }</Box>
36
+ <PropKeyProvider bind={ String( openItemIndex ) }>
37
+ <Box>
38
+ { React.isValidElement< { bind: string; index: number } >( children ) &&
39
+ React.cloneElement( children, { bind, index: openItemIndex } ) }
40
+ </Box>
41
+ </PropKeyProvider>
26
42
  </Popover>
27
43
  );
28
44
  };
@@ -1,6 +1,4 @@
1
1
  import * as React from 'react';
2
- import { useState } from 'react';
3
- import { type PropValue } from '@elementor/editor-props';
4
2
  import { bindTrigger, UnstableTag } from '@elementor/ui';
5
3
  import { __ } from '@wordpress/i18n';
6
4
 
@@ -8,25 +6,25 @@ import { SlotChildren } from '../../../control-replacements';
8
6
  import { DisableItemAction } from '../actions/disable-item-action';
9
7
  import { DuplicateItemAction } from '../actions/duplicate-item-action';
10
8
  import { RemoveItemAction } from '../actions/remove-item-action';
9
+ import { useRepeaterContext } from '../context/repeater-context';
11
10
  import { RepeaterItemActionsSlot, RepeaterItemIconSlot, RepeaterItemLabelSlot } from '../locations';
12
- import { type ItemProps } from '../types';
13
- import { EditItemPopover } from './edit-item-popover';
14
- import { usePopover } from './use-popover';
11
+ import { type ItemProps, type RepeatablePropValue } from '../types';
15
12
 
16
- type AnchorEl = HTMLElement | null;
17
-
18
- export const Item = < T extends PropValue >( {
13
+ export const Item = < T extends RepeatablePropValue >( {
19
14
  Label,
20
15
  Icon,
21
- Content,
22
- key,
23
16
  value,
24
- index,
25
- openOnMount,
17
+ index = -1,
26
18
  children,
27
19
  }: React.PropsWithChildren< ItemProps< T > > ) => {
28
- const [ anchorEl, setAnchorEl ] = useState< AnchorEl >( null );
29
- const { popoverState, popoverProps, ref, setRef } = usePopover( openOnMount as boolean, () => {} );
20
+ const { items, popoverState, setRowRef, openItemIndex, setOpenItemIndex } = useRepeaterContext();
21
+ const triggerProps = bindTrigger( popoverState );
22
+ const key = items[ index ].key ?? -1;
23
+
24
+ const onClick = ( ev: React.MouseEvent ) => {
25
+ triggerProps.onClick( ev );
26
+ setOpenItemIndex( index );
27
+ };
30
28
 
31
29
  return (
32
30
  <>
@@ -40,10 +38,11 @@ export const Item = < T extends PropValue >( {
40
38
  }
41
39
  showActionsOnHover
42
40
  fullWidth
43
- ref={ setRef }
41
+ ref={ ( ref ) => ref && openItemIndex === index && setRowRef( ref ) }
44
42
  variant="outlined"
45
43
  aria-label={ __( 'Open item', 'elementor' ) }
46
- { ...bindTrigger( popoverState ) }
44
+ { ...triggerProps }
45
+ onClick={ onClick }
47
46
  startIcon={
48
47
  <RepeaterItemIconSlot value={ value }>
49
48
  <Icon value={ value as T } />
@@ -63,9 +62,6 @@ export const Item = < T extends PropValue >( {
63
62
  </>
64
63
  }
65
64
  />
66
- <EditItemPopover anchorRef={ ref } setAnchorEl={ setAnchorEl } popoverProps={ popoverProps }>
67
- <Content anchorEl={ anchorEl } bind={ String( index ) } value={ value as T } />
68
- </EditItemPopover>
69
65
  </>
70
66
  );
71
67
  };
@@ -1,33 +1,36 @@
1
1
  import * as React from 'react';
2
- import { type PropValue } from '@elementor/editor-props';
3
2
 
4
3
  import { SortableItem, SortableProvider } from '../../sortable';
5
4
  import { useRepeaterContext } from '../context/repeater-context';
6
- import { type ItemProps } from '../types';
5
+ import { type Item, type ItemProps, type RepeatablePropValue } from '../types';
7
6
 
8
- export const ItemsContainer = < T extends PropValue >( {
7
+ export const ItemsContainer = < T extends RepeatablePropValue >( {
9
8
  itemTemplate,
9
+ isSortable = true,
10
10
  children,
11
- }: React.PropsWithChildren< { itemTemplate: React.ReactNode } > ) => {
12
- const { items, uniqueKeys, openItem, isSortable, sortItemsByKeys } = useRepeaterContext();
11
+ }: React.PropsWithChildren< { itemTemplate: React.ReactNode; isSortable?: boolean } > ) => {
12
+ const { items, setItems } = useRepeaterContext();
13
+ const keys = items.map( ( { key } ) => key );
13
14
 
14
15
  if ( ! itemTemplate ) {
15
16
  return null;
16
17
  }
17
18
 
18
- const onChangeOrder = ( newOrder: number[] ) => {
19
- sortItemsByKeys( newOrder );
19
+ const onChangeOrder = ( newKeys: number[] ) => {
20
+ setItems(
21
+ newKeys.map( ( key ) => {
22
+ const index = items.findIndex( ( item ) => item.key === key );
23
+
24
+ return items[ index ];
25
+ } )
26
+ );
20
27
  };
21
28
 
22
29
  return (
23
30
  <>
24
- <SortableProvider value={ uniqueKeys } onChange={ onChangeOrder }>
25
- { uniqueKeys?.map( ( key: number, index: number ) => {
26
- const value = items?.[ index ] as T;
27
-
28
- if ( ! value ) {
29
- return null;
30
- }
31
+ <SortableProvider value={ keys } onChange={ onChangeOrder }>
32
+ { keys.map( ( key: number, index: number ) => {
33
+ const value = items[ index ].item as Item< T >;
31
34
 
32
35
  return (
33
36
  <SortableItem id={ key } key={ `sortable-${ key }` } disabled={ ! isSortable }>
@@ -36,7 +39,6 @@ export const ItemsContainer = < T extends PropValue >( {
36
39
  key,
37
40
  value,
38
41
  index,
39
- openOnMount: key === openItem,
40
42
  children,
41
43
  } )
42
44
  : null }
@@ -1,4 +1,4 @@
1
- import { type PropKey, type PropTypeUtil } from '@elementor/editor-props';
1
+ import { type PropKey, type PropTypeUtil, type PropValue, type TransformablePropValue } from '@elementor/editor-props';
2
2
 
3
3
  export type CollectionPropUtil< T > = PropTypeUtil< PropKey, T[] >;
4
4
 
@@ -6,21 +6,11 @@ export type Item< T > = {
6
6
  disabled?: boolean;
7
7
  } & T;
8
8
 
9
- type RepeaterItemContentProps< T > = {
10
- anchorEl: HTMLElement | null;
11
- bind: PropKey;
12
- value: T;
13
- collectionPropUtil?: CollectionPropUtil< T >;
14
- };
15
-
16
- type RepeaterItemContent< T > = React.ComponentType< RepeaterItemContentProps< T > >;
9
+ export type RepeatablePropValue = TransformablePropValue< PropKey, PropValue >;
17
10
 
18
11
  export type ItemProps< T > = {
19
12
  Label: React.ComponentType< { value: T } >;
20
13
  Icon: React.ComponentType< { value: T } >;
21
- Content: RepeaterItemContent< T >;
22
14
  value?: Item< T >;
23
- key?: string | number;
24
15
  index?: number;
25
- openOnMount?: boolean;
26
16
  };
@@ -1,13 +1,15 @@
1
1
  import * as React from 'react';
2
- import { type PropTypeUtil, type PropValue } from '@elementor/editor-props';
2
+ import { type PropTypeUtil } from '@elementor/editor-props';
3
3
 
4
4
  import { SlotChildren } from '../../control-replacements';
5
5
  import { SectionContent } from '../section-content';
6
6
  import { RepeaterContextProvider } from './context/repeater-context';
7
7
  import { Header } from './header/header';
8
+ import { EditItemPopover } from './items/edit-item-popover';
8
9
  import { ItemsContainer } from './items/items-container';
10
+ import { type RepeatablePropValue } from './types';
9
11
 
10
- export const UnstableRepeater = < T extends PropValue >( {
12
+ export const UnstableRepeater = < T extends RepeatablePropValue >( {
11
13
  children,
12
14
  initial,
13
15
  propTypeUtil,
@@ -15,7 +17,7 @@ export const UnstableRepeater = < T extends PropValue >( {
15
17
  return (
16
18
  <SectionContent>
17
19
  <RepeaterContextProvider initial={ initial } propTypeUtil={ propTypeUtil }>
18
- <SlotChildren whitelist={ [ Header, ItemsContainer ] as React.FC[] } sorted>
20
+ <SlotChildren whitelist={ [ Header, ItemsContainer, EditItemPopover ] as React.FC[] } sorted>
19
21
  { children }
20
22
  </SlotChildren>
21
23
  </RepeaterContextProvider>