@elementor/editor-controls 4.2.0-885 → 4.2.0-887

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.2.0-885",
4
+ "version": "4.2.0-887",
5
5
  "private": false,
6
6
  "author": "Elementor Team",
7
7
  "homepage": "https://elementor.com/",
@@ -40,23 +40,23 @@
40
40
  "dev": "tsup --config=../../tsup.dev.ts"
41
41
  },
42
42
  "dependencies": {
43
- "@elementor/editor-current-user": "4.2.0-885",
44
- "@elementor/editor-elements": "4.2.0-885",
45
- "@elementor/editor-props": "4.2.0-885",
46
- "@elementor/editor-responsive": "4.2.0-885",
47
- "@elementor/editor-ui": "4.2.0-885",
48
- "@elementor/editor-v1-adapters": "4.2.0-885",
49
- "@elementor/env": "4.2.0-885",
50
- "@elementor/events": "4.2.0-885",
51
- "@elementor/http-client": "4.2.0-885",
43
+ "@elementor/editor-current-user": "4.2.0-887",
44
+ "@elementor/editor-elements": "4.2.0-887",
45
+ "@elementor/editor-props": "4.2.0-887",
46
+ "@elementor/editor-responsive": "4.2.0-887",
47
+ "@elementor/editor-ui": "4.2.0-887",
48
+ "@elementor/editor-v1-adapters": "4.2.0-887",
49
+ "@elementor/env": "4.2.0-887",
50
+ "@elementor/events": "4.2.0-887",
51
+ "@elementor/http-client": "4.2.0-887",
52
52
  "@elementor/icons": "~1.75.1",
53
- "@elementor/locations": "4.2.0-885",
54
- "@elementor/query": "4.2.0-885",
55
- "@elementor/schema": "4.2.0-885",
56
- "@elementor/session": "4.2.0-885",
53
+ "@elementor/locations": "4.2.0-887",
54
+ "@elementor/query": "4.2.0-887",
55
+ "@elementor/schema": "4.2.0-887",
56
+ "@elementor/session": "4.2.0-887",
57
57
  "@elementor/ui": "1.37.5",
58
- "@elementor/utils": "4.2.0-885",
59
- "@elementor/wp-media": "4.2.0-885",
58
+ "@elementor/utils": "4.2.0-887",
59
+ "@elementor/wp-media": "4.2.0-887",
60
60
  "@monaco-editor/react": "^4.7.0",
61
61
  "@tiptap/extension-bold": "^3.11.1",
62
62
  "@tiptap/extension-document": "^3.11.1",
@@ -1,6 +1,11 @@
1
1
  import * as React from 'react';
2
2
  import { type PropsWithChildren } from 'react';
3
- import { type LinkInLinkRestriction, selectElement } from '@elementor/editor-elements';
3
+ import {
4
+ getContainer,
5
+ getCurrentDocumentId,
6
+ type LinkInLinkRestriction,
7
+ selectElement,
8
+ } from '@elementor/editor-elements';
4
9
  import { InfoCircleFilledIcon } from '@elementor/icons';
5
10
  import { Alert, AlertAction, AlertTitle, Box, Infotip, Link } from '@elementor/ui';
6
11
  import { __ } from '@wordpress/i18n';
@@ -26,6 +31,23 @@ type RestrictedLinkInfotipProps = PropsWithChildren< {
26
31
  isVisible: boolean;
27
32
  } >;
28
33
 
34
+ function isTargetInCurrentDocument( elementId: string | null | undefined ): boolean {
35
+ if ( ! elementId ) {
36
+ return false;
37
+ }
38
+
39
+ const el = getContainer( elementId )?.view?.el;
40
+
41
+ if ( ! el ) {
42
+ return false;
43
+ }
44
+
45
+ const targetDocId = el.closest( '[data-elementor-id]' )?.getAttribute( 'data-elementor-id' );
46
+ const currentDocId = String( getCurrentDocumentId() ?? '' );
47
+
48
+ return !! ( targetDocId && currentDocId && targetDocId === currentDocId );
49
+ }
50
+
29
51
  export const RestrictedLinkInfotip: React.FC< RestrictedLinkInfotipProps > = ( {
30
52
  linkInLinkRestriction,
31
53
  isVisible,
@@ -33,6 +55,8 @@ export const RestrictedLinkInfotip: React.FC< RestrictedLinkInfotipProps > = ( {
33
55
  } ) => {
34
56
  const { shouldRestrict, reason, elementId } = linkInLinkRestriction;
35
57
 
58
+ const showTakeMeThereCta = !! ( elementId && isTargetInCurrentDocument( elementId ) );
59
+
36
60
  const handleTakeMeClick = () => {
37
61
  if ( elementId ) {
38
62
  selectElement( elementId );
@@ -45,14 +69,16 @@ export const RestrictedLinkInfotip: React.FC< RestrictedLinkInfotipProps > = ( {
45
69
  icon={ <InfoCircleFilledIcon /> }
46
70
  size="small"
47
71
  action={
48
- <AlertAction
49
- sx={ { width: 'fit-content' } }
50
- variant="contained"
51
- color="secondary"
52
- onClick={ handleTakeMeClick }
53
- >
54
- { __( 'Take me there', 'elementor' ) }
55
- </AlertAction>
72
+ showTakeMeThereCta ? (
73
+ <AlertAction
74
+ sx={ { width: 'fit-content' } }
75
+ variant="contained"
76
+ color="secondary"
77
+ onClick={ handleTakeMeClick }
78
+ >
79
+ { __( 'Take me there', 'elementor' ) }
80
+ </AlertAction>
81
+ ) : undefined
56
82
  }
57
83
  >
58
84
  <AlertTitle>{ __( 'Nested links', 'elementor' ) }</AlertTitle>
@@ -1,11 +1,12 @@
1
1
  import * as React from 'react';
2
- import { useEffect, useMemo, useState } from 'react';
3
- import { getLinkInLinkRestriction } from '@elementor/editor-elements';
2
+ import { useEffect, useState } from 'react';
3
+ import { getLinkInLinkRestriction, type LinkInLinkRestriction } from '@elementor/editor-elements';
4
4
  import { linkPropTypeUtil, type LinkPropValue } from '@elementor/editor-props';
5
+ import { __privateUseListenTo as useListenTo, commandEndEvent } from '@elementor/editor-v1-adapters';
5
6
  import { MinusIcon, PlusIcon } from '@elementor/icons';
6
7
  import { useSessionStorage } from '@elementor/session';
7
8
  import { Collapse, Grid, IconButton, Stack } from '@elementor/ui';
8
- import { debounce } from '@elementor/utils';
9
+ import { useDebouncedCallback } from '@elementor/utils';
9
10
  import { __ } from '@wordpress/i18n';
10
11
 
11
12
  import { PropKeyProvider, PropProvider, useBoundProp } from '../bound-prop-context';
@@ -62,36 +63,39 @@ export const LinkControl = createControl( ( props: Props ) => {
62
63
 
63
64
  const shouldDisableAddingLink = ! isActive && linkInLinkRestriction.shouldRestrict;
64
65
 
65
- const debouncedCheckRestriction = useMemo(
66
- () =>
67
- debounce( () => {
68
- const newRestriction = getLinkInLinkRestriction( elementId, value ?? linkPlaceholder );
66
+ const debouncedCheckRestriction = useDebouncedCallback( () => {
67
+ const newRestriction = getLinkInLinkRestriction( elementId, value ?? linkPlaceholder );
69
68
 
70
- if ( newRestriction.shouldRestrict && isActive && ! linkPlaceholder ) {
71
- setIsActive( false );
72
- }
69
+ if ( newRestriction.shouldRestrict && isActive && ! linkPlaceholder ) {
70
+ setIsActive( false );
73
71
 
74
- setLinkInLinkRestriction( newRestriction );
75
- }, 300 ),
76
- [ elementId, isActive, value, linkPlaceholder ]
72
+ if ( value !== null ) {
73
+ setValue( null );
74
+ }
75
+ }
76
+
77
+ setLinkInLinkRestriction( ( prev ) => ( isSameRestriction( prev, newRestriction ) ? prev : newRestriction ) );
78
+ }, 300 );
79
+
80
+ useListenTo(
81
+ commandEndEvent( 'document/elements/set-settings' ),
82
+ () => {
83
+ debouncedCheckRestriction();
84
+ },
85
+ [ debouncedCheckRestriction ]
77
86
  );
78
87
 
79
88
  useEffect( () => {
80
89
  debouncedCheckRestriction();
81
90
 
82
- const handleInlineLinkChanged = ( event: Event ) => {
83
- const customEvent = event as CustomEvent< { elementId: string } >;
84
-
85
- if ( customEvent.detail.elementId === elementId ) {
86
- debouncedCheckRestriction();
87
- }
91
+ const handleInlineLinkChanged = () => {
92
+ debouncedCheckRestriction();
88
93
  };
89
94
 
90
95
  window.addEventListener( 'elementor:inline-link-changed', handleInlineLinkChanged );
91
96
 
92
97
  return () => {
93
98
  window.removeEventListener( 'elementor:inline-link-changed', handleInlineLinkChanged );
94
- debouncedCheckRestriction.cancel();
95
99
  };
96
100
  }, [ elementId, debouncedCheckRestriction ] );
97
101
 
@@ -181,3 +185,7 @@ export const LinkControl = createControl( ( props: Props ) => {
181
185
  </PropProvider>
182
186
  );
183
187
  } );
188
+
189
+ function isSameRestriction( a: LinkInLinkRestriction, b: LinkInLinkRestriction ): boolean {
190
+ return a.shouldRestrict === b.shouldRestrict && a.reason === b.reason && a.elementId === b.elementId;
191
+ }