@elementor/editor-controls 4.1.0-800 → 4.1.0-802

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-800",
4
+ "version": "4.1.0-802",
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-800",
44
- "@elementor/editor-elements": "4.1.0-800",
45
- "@elementor/editor-props": "4.1.0-800",
46
- "@elementor/editor-responsive": "4.1.0-800",
47
- "@elementor/editor-ui": "4.1.0-800",
48
- "@elementor/editor-v1-adapters": "4.1.0-800",
49
- "@elementor/env": "4.1.0-800",
50
- "@elementor/events": "4.1.0-800",
51
- "@elementor/http-client": "4.1.0-800",
43
+ "@elementor/editor-current-user": "4.1.0-802",
44
+ "@elementor/editor-elements": "4.1.0-802",
45
+ "@elementor/editor-props": "4.1.0-802",
46
+ "@elementor/editor-responsive": "4.1.0-802",
47
+ "@elementor/editor-ui": "4.1.0-802",
48
+ "@elementor/editor-v1-adapters": "4.1.0-802",
49
+ "@elementor/env": "4.1.0-802",
50
+ "@elementor/events": "4.1.0-802",
51
+ "@elementor/http-client": "4.1.0-802",
52
52
  "@elementor/icons": "^1.68.0",
53
- "@elementor/locations": "4.1.0-800",
54
- "@elementor/query": "4.1.0-800",
55
- "@elementor/session": "4.1.0-800",
53
+ "@elementor/locations": "4.1.0-802",
54
+ "@elementor/query": "4.1.0-802",
55
+ "@elementor/session": "4.1.0-802",
56
56
  "@elementor/ui": "1.37.5",
57
- "@elementor/utils": "4.1.0-800",
58
- "@elementor/wp-media": "4.1.0-800",
57
+ "@elementor/utils": "4.1.0-802",
58
+ "@elementor/wp-media": "4.1.0-802",
59
59
  "@monaco-editor/react": "^4.7.0",
60
60
  "@tiptap/extension-bold": "^3.11.1",
61
61
  "@tiptap/extension-document": "^3.11.1",
@@ -4,6 +4,7 @@ import { type PropTypeUtil } from '@elementor/editor-props';
4
4
  import { type PopupState, usePopupState } from '@elementor/ui';
5
5
 
6
6
  import { useBoundProp } from '../../../bound-prop-context/use-bound-prop';
7
+ import { usePopoverDismiss } from '../../../hooks/use-repeater-popover-dismiss';
7
8
  import { useSyncExternalState } from '../../../hooks/use-sync-external-state';
8
9
  import { eventBus } from '../../../services/event-bus';
9
10
  import { type Item, type RepeatablePropValue } from '../types';
@@ -144,6 +145,18 @@ export const RepeaterContextProvider = < T extends RepeatablePropValue = Repeata
144
145
  setItems( newItems );
145
146
  };
146
147
 
148
+ const closePopover = () => {
149
+ if ( ! isOpen ) {
150
+ return;
151
+ }
152
+
153
+ setOpenItemIndex( EMPTY_OPEN_ITEM );
154
+ setRowRef( null );
155
+ popoverState.close();
156
+ };
157
+
158
+ usePopoverDismiss( { isOpen, onClose: closePopover } );
159
+
147
160
  return (
148
161
  <RepeaterContext.Provider
149
162
  value={ {
@@ -6,7 +6,6 @@ import {
6
6
  bindPopover,
7
7
  bindTrigger,
8
8
  Box,
9
- ClickAwayListener,
10
9
  IconButton,
11
10
  Infotip,
12
11
  Tooltip,
@@ -17,6 +16,7 @@ import { __ } from '@wordpress/i18n';
17
16
 
18
17
  import { type SetValueMeta } from '../../bound-prop-context';
19
18
  import { ControlAdornments } from '../../control-adornments/control-adornments';
19
+ import { usePopoverDismiss } from '../../hooks/use-repeater-popover-dismiss';
20
20
  import { RepeaterItemIconSlot, RepeaterItemLabelSlot } from '../control-repeater/locations';
21
21
  import { SectionContent } from '../section-content';
22
22
  import { RepeaterHeader } from './repeater-header';
@@ -352,12 +352,14 @@ const RepeaterItem = < T, >( {
352
352
  );
353
353
  const triggerProps = bindTrigger( popoverState );
354
354
 
355
+ usePopoverDismiss( { isOpen: popoverState.isOpen, onClose: popoverProps.onClose } );
356
+
355
357
  const duplicateLabel = __( 'Duplicate', 'elementor' );
356
358
  const toggleLabel = propDisabled ? __( 'Show', 'elementor' ) : __( 'Hide', 'elementor' );
357
359
  const removeLabel = __( 'Remove', 'elementor' );
358
360
 
359
361
  return (
360
- <>
362
+ <Box sx={ { display: 'contents' } }>
361
363
  <RepeaterTag
362
364
  disabled={ disabled }
363
365
  label={ label }
@@ -399,15 +401,9 @@ const RepeaterItem = < T, >( {
399
401
  }
400
402
  />
401
403
  <RepeaterPopover width={ ref?.getBoundingClientRect().width } { ...popoverProps } anchorEl={ ref }>
402
- <ClickAwayListener
403
- mouseEvent="onMouseDown"
404
- touchEvent="onTouchStart"
405
- onClickAway={ popoverProps.onClose }
406
- >
407
- <Box>{ children( { anchorEl: ref } ) }</Box>
408
- </ClickAwayListener>
404
+ <Box>{ children( { anchorEl: ref } ) }</Box>
409
405
  </RepeaterPopover>
410
- </>
406
+ </Box>
411
407
  );
412
408
  };
413
409
 
@@ -0,0 +1,53 @@
1
+ import { useEffect, useMemo, useRef } from 'react';
2
+ import { type Breakpoint, useActiveBreakpoint, useBreakpoints } from '@elementor/editor-responsive';
3
+
4
+ const serializeBreakpoints = ( breakpoints: Breakpoint[] ) =>
5
+ breakpoints.map( ( b ) => [ b.id, b.width ?? '', b.type ?? '' ].join( ':' ) ).join( '|' );
6
+
7
+ export const usePopoverDismiss = ( { isOpen, onClose }: { isOpen: boolean; onClose: () => void } ) => {
8
+ const onCloseRef = useRef( onClose );
9
+ onCloseRef.current = onClose;
10
+
11
+ const activeBreakpoint = useActiveBreakpoint();
12
+ const breakpoints = useBreakpoints();
13
+ const breakpointsSignature = useMemo( () => serializeBreakpoints( breakpoints ), [ breakpoints ] );
14
+
15
+ const prevActiveBreakpointRef = useRef< typeof activeBreakpoint >( undefined );
16
+ const prevBreakpointsSignatureRef = useRef< string | null >( null );
17
+
18
+ useEffect( () => {
19
+ if ( ! isOpen ) {
20
+ prevActiveBreakpointRef.current = activeBreakpoint;
21
+ prevBreakpointsSignatureRef.current = breakpointsSignature;
22
+ return;
23
+ }
24
+
25
+ const previousBreakpoint = prevActiveBreakpointRef.current;
26
+ const previousSignature = prevBreakpointsSignatureRef.current;
27
+
28
+ const breakpointChanged = previousBreakpoint !== undefined && previousBreakpoint !== activeBreakpoint;
29
+ const breakpointsChanged = previousSignature !== null && previousSignature !== breakpointsSignature;
30
+
31
+ if ( breakpointChanged || breakpointsChanged ) {
32
+ onCloseRef.current();
33
+ }
34
+
35
+ prevActiveBreakpointRef.current = activeBreakpoint;
36
+ prevBreakpointsSignatureRef.current = breakpointsSignature;
37
+ }, [ activeBreakpoint, breakpointsSignature, isOpen ] );
38
+
39
+ useEffect( () => {
40
+ if ( ! isOpen ) {
41
+ return;
42
+ }
43
+ const onKeyDown = ( event: KeyboardEvent ) => {
44
+ if ( event.key === 'Escape' && ! event.defaultPrevented ) {
45
+ onCloseRef.current();
46
+ }
47
+ };
48
+ document.addEventListener( 'keydown', onKeyDown );
49
+ return () => {
50
+ document.removeEventListener( 'keydown', onKeyDown );
51
+ };
52
+ }, [ isOpen ] );
53
+ };