@elementor/editor-canvas 3.35.0-359 → 3.35.0-360
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/dist/index.d.mts +12 -2
- package/dist/index.d.ts +12 -2
- package/dist/index.js +297 -294
- package/dist/index.mjs +266 -263
- package/package.json +18 -18
- package/src/components/__tests__/elements-overlays.test.tsx +0 -3
- package/src/init.tsx +3 -0
- package/src/legacy/create-templated-element-type.ts +4 -4
- package/src/legacy/init-legacy-views.ts +3 -10
- package/src/legacy/replacements/base.ts +35 -0
- package/src/legacy/replacements/inline-editing/inline-editing-elements.tsx +161 -0
- package/src/legacy/replacements/inline-editing/inline-editing-utils.ts +31 -0
- package/src/legacy/replacements/manager.ts +119 -0
- package/src/legacy/types.ts +14 -1
- package/src/legacy/create-inline-editing-element-type.tsx +0 -199
- package/src/utils/__tests__/inline-editing.test.ts +0 -553
- package/src/utils/inline-editing-utils.ts +0 -138
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@elementor/editor-canvas",
|
|
3
3
|
"description": "Elementor Editor Canvas",
|
|
4
|
-
"version": "3.35.0-
|
|
4
|
+
"version": "3.35.0-360",
|
|
5
5
|
"private": false,
|
|
6
6
|
"author": "Elementor Team",
|
|
7
7
|
"homepage": "https://elementor.com/",
|
|
@@ -37,24 +37,24 @@
|
|
|
37
37
|
"react-dom": "^18.3.1"
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@elementor/editor": "3.35.0-
|
|
41
|
-
"@elementor/editor-controls": "3.35.0-
|
|
42
|
-
"@elementor/editor-documents": "3.35.0-
|
|
43
|
-
"@elementor/editor-elements": "3.35.0-
|
|
44
|
-
"@elementor/editor-interactions": "3.35.0-
|
|
45
|
-
"@elementor/editor-mcp": "3.35.0-
|
|
46
|
-
"@elementor/editor-notifications": "3.35.0-
|
|
47
|
-
"@elementor/editor-props": "3.35.0-
|
|
48
|
-
"@elementor/editor-responsive": "3.35.0-
|
|
49
|
-
"@elementor/editor-styles": "3.35.0-
|
|
50
|
-
"@elementor/editor-styles-repository": "3.35.0-
|
|
51
|
-
"@elementor/editor-ui": "3.35.0-
|
|
52
|
-
"@elementor/editor-v1-adapters": "3.35.0-
|
|
53
|
-
"@elementor/schema": "3.35.0-
|
|
54
|
-
"@elementor/twing": "3.35.0-
|
|
40
|
+
"@elementor/editor": "3.35.0-360",
|
|
41
|
+
"@elementor/editor-controls": "3.35.0-360",
|
|
42
|
+
"@elementor/editor-documents": "3.35.0-360",
|
|
43
|
+
"@elementor/editor-elements": "3.35.0-360",
|
|
44
|
+
"@elementor/editor-interactions": "3.35.0-360",
|
|
45
|
+
"@elementor/editor-mcp": "3.35.0-360",
|
|
46
|
+
"@elementor/editor-notifications": "3.35.0-360",
|
|
47
|
+
"@elementor/editor-props": "3.35.0-360",
|
|
48
|
+
"@elementor/editor-responsive": "3.35.0-360",
|
|
49
|
+
"@elementor/editor-styles": "3.35.0-360",
|
|
50
|
+
"@elementor/editor-styles-repository": "3.35.0-360",
|
|
51
|
+
"@elementor/editor-ui": "3.35.0-360",
|
|
52
|
+
"@elementor/editor-v1-adapters": "3.35.0-360",
|
|
53
|
+
"@elementor/schema": "3.35.0-360",
|
|
54
|
+
"@elementor/twing": "3.35.0-360",
|
|
55
55
|
"@elementor/ui": "1.36.17",
|
|
56
|
-
"@elementor/utils": "3.35.0-
|
|
57
|
-
"@elementor/wp-media": "3.35.0-
|
|
56
|
+
"@elementor/utils": "3.35.0-360",
|
|
57
|
+
"@elementor/wp-media": "3.35.0-360",
|
|
58
58
|
"@floating-ui/react": "^0.27.5",
|
|
59
59
|
"@wordpress/i18n": "^5.13.0"
|
|
60
60
|
},
|
|
@@ -8,7 +8,6 @@ import {
|
|
|
8
8
|
} from '@elementor/editor-v1-adapters';
|
|
9
9
|
import { screen, waitFor } from '@testing-library/react';
|
|
10
10
|
|
|
11
|
-
import { hasInlineEditableProperty } from '../../utils/inline-editing-utils';
|
|
12
11
|
import { ElementsOverlays } from '../elements-overlays';
|
|
13
12
|
import { CANVAS_WRAPPER_ID } from '../outline-overlay';
|
|
14
13
|
|
|
@@ -19,7 +18,6 @@ jest.mock( '@elementor/editor-v1-adapters', () => ( {
|
|
|
19
18
|
__privateUseIsRouteActive: jest.fn(),
|
|
20
19
|
isExperimentActive: jest.fn(),
|
|
21
20
|
} ) );
|
|
22
|
-
jest.mock( '../../utils/inline-editing-utils' );
|
|
23
21
|
|
|
24
22
|
describe( '<ElementsOverlays />', () => {
|
|
25
23
|
beforeEach( () => {
|
|
@@ -30,7 +28,6 @@ describe( '<ElementsOverlays />', () => {
|
|
|
30
28
|
|
|
31
29
|
jest.mocked( useEditMode ).mockReturnValue( 'edit' );
|
|
32
30
|
jest.mocked( useIsRouteActive ).mockReturnValue( false );
|
|
33
|
-
jest.mocked( hasInlineEditableProperty ).mockReturnValue( false );
|
|
34
31
|
jest.mocked( isExperimentActive ).mockReturnValue( true );
|
|
35
32
|
|
|
36
33
|
jest.mocked( getElements ).mockReturnValue( [
|
package/src/init.tsx
CHANGED
|
@@ -9,6 +9,7 @@ import { StyleRenderer } from './components/style-renderer';
|
|
|
9
9
|
import { initSettingsTransformers } from './init-settings-transformers';
|
|
10
10
|
import { initStyleTransformers } from './init-style-transformers';
|
|
11
11
|
import { initLegacyViews } from './legacy/init-legacy-views';
|
|
12
|
+
import { initViewReplacements } from './legacy/replacements/manager';
|
|
12
13
|
import { initCanvasMcp } from './mcp/canvas-mcp';
|
|
13
14
|
import { mcpDescription } from './mcp/mcp-description';
|
|
14
15
|
import { initLinkInLinkPrevention } from './prevent-link-in-link-commands';
|
|
@@ -20,6 +21,8 @@ export function init() {
|
|
|
20
21
|
|
|
21
22
|
initLinkInLinkPrevention();
|
|
22
23
|
|
|
24
|
+
initViewReplacements();
|
|
25
|
+
|
|
23
26
|
initLegacyViews();
|
|
24
27
|
|
|
25
28
|
initSettingsTransformers();
|
|
@@ -86,11 +86,11 @@ export function createTemplatedElementView( {
|
|
|
86
86
|
this.#abortController = new AbortController();
|
|
87
87
|
|
|
88
88
|
const process = signalizedProcess( this.#abortController.signal )
|
|
89
|
-
.then( () => this
|
|
89
|
+
.then( () => this._beforeRender() )
|
|
90
90
|
.then( () => this._renderTemplate() )
|
|
91
91
|
.then( () => {
|
|
92
92
|
this._renderChildren();
|
|
93
|
-
this
|
|
93
|
+
this._afterRender();
|
|
94
94
|
} );
|
|
95
95
|
|
|
96
96
|
return process.execute();
|
|
@@ -136,7 +136,7 @@ export function createTemplatedElementView( {
|
|
|
136
136
|
return settings;
|
|
137
137
|
}
|
|
138
138
|
|
|
139
|
-
|
|
139
|
+
_beforeRender() {
|
|
140
140
|
this._ensureViewIsIntact();
|
|
141
141
|
|
|
142
142
|
this._isRendering = true;
|
|
@@ -146,7 +146,7 @@ export function createTemplatedElementView( {
|
|
|
146
146
|
this.triggerMethod( 'before:render', this );
|
|
147
147
|
}
|
|
148
148
|
|
|
149
|
-
|
|
149
|
+
_afterRender() {
|
|
150
150
|
this._isRendering = false;
|
|
151
151
|
this.isRendered = true;
|
|
152
152
|
|
|
@@ -2,14 +2,9 @@ import { getWidgetsCache } from '@elementor/editor-elements';
|
|
|
2
2
|
import { __privateListenTo, v1ReadyEvent } from '@elementor/editor-v1-adapters';
|
|
3
3
|
|
|
4
4
|
import { createDomRenderer } from '../renderers/create-dom-renderer';
|
|
5
|
-
import { shouldRenderInlineEditingView } from '../utils/inline-editing-utils';
|
|
6
5
|
import { createElementType } from './create-element-type';
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
canBeTemplated,
|
|
10
|
-
createTemplatedElementType,
|
|
11
|
-
type CreateTemplatedElementTypeOptions,
|
|
12
|
-
} from './create-templated-element-type';
|
|
6
|
+
import { canBeTemplated, type CreateTemplatedElementTypeOptions } from './create-templated-element-type';
|
|
7
|
+
import { createTemplatedElementTypeWithReplacements } from './replacements/manager';
|
|
13
8
|
import type { ElementType, LegacyWindow } from './types';
|
|
14
9
|
|
|
15
10
|
type ElementLegacyType = {
|
|
@@ -41,9 +36,7 @@ export function initLegacyViews() {
|
|
|
41
36
|
if ( !! elementsLegacyTypes[ type ] && canBeTemplated( element ) ) {
|
|
42
37
|
ElementType = elementsLegacyTypes[ type ]( { type, renderer, element } );
|
|
43
38
|
} else if ( canBeTemplated( element ) ) {
|
|
44
|
-
ElementType =
|
|
45
|
-
? createInlineEditingElementType( { type, renderer, element } )
|
|
46
|
-
: createTemplatedElementType( { type, renderer, element } );
|
|
39
|
+
ElementType = createTemplatedElementTypeWithReplacements( { type, renderer, element } );
|
|
47
40
|
} else {
|
|
48
41
|
ElementType = createElementType( type );
|
|
49
42
|
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { type ReplacementSettings } from '../types';
|
|
2
|
+
|
|
3
|
+
export default class ReplacementBase {
|
|
4
|
+
protected getSetting: ReplacementSettings[ 'getSetting' ];
|
|
5
|
+
protected setSetting: ReplacementSettings[ 'setSetting' ];
|
|
6
|
+
protected element: ReplacementSettings[ 'element' ];
|
|
7
|
+
protected type: ReplacementSettings[ 'type' ];
|
|
8
|
+
protected id: ReplacementSettings[ 'id' ];
|
|
9
|
+
protected refreshView: ReplacementSettings[ 'refreshView' ];
|
|
10
|
+
|
|
11
|
+
constructor( settings: ReplacementSettings ) {
|
|
12
|
+
this.getSetting = settings.getSetting;
|
|
13
|
+
this.setSetting = settings.setSetting;
|
|
14
|
+
this.element = settings.element;
|
|
15
|
+
this.type = settings.type;
|
|
16
|
+
this.id = settings.id;
|
|
17
|
+
this.refreshView = settings.refreshView;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
static getTypes(): string[] | null {
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
render(): void {}
|
|
25
|
+
|
|
26
|
+
onDestroy(): void {}
|
|
27
|
+
|
|
28
|
+
_beforeRender(): void {}
|
|
29
|
+
|
|
30
|
+
_afterRender(): void {}
|
|
31
|
+
|
|
32
|
+
shouldRenderReplacement(): boolean {
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { createRoot, type Root } from 'react-dom/client';
|
|
3
|
+
import { InlineEditor } from '@elementor/editor-controls';
|
|
4
|
+
import { getElementType } from '@elementor/editor-elements';
|
|
5
|
+
import {
|
|
6
|
+
htmlPropTypeUtil,
|
|
7
|
+
stringPropTypeUtil,
|
|
8
|
+
type StringPropValue,
|
|
9
|
+
type TransformablePropValue,
|
|
10
|
+
} from '@elementor/editor-props';
|
|
11
|
+
import { isExperimentActive } from '@elementor/editor-v1-adapters';
|
|
12
|
+
import { ThemeProvider } from '@elementor/ui';
|
|
13
|
+
|
|
14
|
+
import ReplacementBase from '../base';
|
|
15
|
+
import { getInitialPopoverPosition, INLINE_EDITING_PROPERTY_PER_TYPE } from './inline-editing-utils';
|
|
16
|
+
|
|
17
|
+
const EXPERIMENT_KEY = 'v4-inline-text-editing';
|
|
18
|
+
|
|
19
|
+
export default class InlineEditingReplacement extends ReplacementBase {
|
|
20
|
+
private inlineEditorRoot: Root | null = null;
|
|
21
|
+
private handlerAttached = false;
|
|
22
|
+
|
|
23
|
+
getReplacementKey() {
|
|
24
|
+
return 'inline-editing';
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
static getTypes() {
|
|
28
|
+
return Object.keys( INLINE_EDITING_PROPERTY_PER_TYPE );
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
isEditingModeActive() {
|
|
32
|
+
return !! this.inlineEditorRoot;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
shouldRenderReplacement() {
|
|
36
|
+
return isExperimentActive( EXPERIMENT_KEY ) && this.isEditingModeActive() && ! this.isValueDynamic();
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
handleRenderInlineEditor = ( event: Event ) => {
|
|
40
|
+
event.stopPropagation();
|
|
41
|
+
|
|
42
|
+
if ( ! this.isValueDynamic() ) {
|
|
43
|
+
this.renderInlineEditor();
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
handleUnmountInlineEditor = ( event: Event ) => {
|
|
48
|
+
event.stopPropagation();
|
|
49
|
+
this.unmountInlineEditor();
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
onDestroy() {
|
|
53
|
+
this.resetInlineEditorRoot();
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
_beforeRender(): void {
|
|
57
|
+
this.resetInlineEditorRoot();
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
_afterRender() {
|
|
61
|
+
if ( ! this.isValueDynamic() && ! this.handlerAttached ) {
|
|
62
|
+
this.element.addEventListener( 'dblclick', this.handleRenderInlineEditor );
|
|
63
|
+
this.handlerAttached = true;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
resetInlineEditorRoot() {
|
|
68
|
+
this.element.removeEventListener( 'dblclick', this.handleRenderInlineEditor );
|
|
69
|
+
this.handlerAttached = false;
|
|
70
|
+
this.inlineEditorRoot?.unmount?.();
|
|
71
|
+
this.inlineEditorRoot = null;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
unmountInlineEditor() {
|
|
75
|
+
this.resetInlineEditorRoot();
|
|
76
|
+
this.refreshView();
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
isValueDynamic() {
|
|
80
|
+
const settingKey = this.getInlineEditablePropertyName();
|
|
81
|
+
const propValue = this.getSetting( settingKey ) as TransformablePropValue< string >;
|
|
82
|
+
|
|
83
|
+
return propValue?.$$type === 'dynamic';
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
getInlineEditablePropertyName(): string {
|
|
87
|
+
return INLINE_EDITING_PROPERTY_PER_TYPE[ this.type ] ?? '';
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
getHtmlPropType() {
|
|
91
|
+
const propSchema = getElementType( this.type )?.propsSchema;
|
|
92
|
+
const propertyName = this.getInlineEditablePropertyName();
|
|
93
|
+
|
|
94
|
+
return propSchema?.[ propertyName ] ?? null;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
getContentValue() {
|
|
98
|
+
const prop = this.getHtmlPropType();
|
|
99
|
+
const defaultValue = ( prop?.default as StringPropValue | null )?.value ?? '';
|
|
100
|
+
const settingKey = this.getInlineEditablePropertyName();
|
|
101
|
+
|
|
102
|
+
return (
|
|
103
|
+
htmlPropTypeUtil.extract( this.getSetting( settingKey ) ?? null ) ??
|
|
104
|
+
htmlPropTypeUtil.extract( prop?.default ?? null ) ??
|
|
105
|
+
defaultValue ??
|
|
106
|
+
''
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
setContentValue( value: string | null ) {
|
|
111
|
+
const settingKey = this.getInlineEditablePropertyName();
|
|
112
|
+
const valueToSave = value ? htmlPropTypeUtil.create( value ) : null;
|
|
113
|
+
|
|
114
|
+
this.setSetting( settingKey, valueToSave );
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
getExpectedTag() {
|
|
118
|
+
const propsSchema = getElementType( this.type )?.propsSchema;
|
|
119
|
+
|
|
120
|
+
if ( ! propsSchema?.tag ) {
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const tagSettingKey = 'tag';
|
|
125
|
+
|
|
126
|
+
return (
|
|
127
|
+
stringPropTypeUtil.extract( this.getSetting( tagSettingKey ) ?? null ) ??
|
|
128
|
+
stringPropTypeUtil.extract( propsSchema.tag.default ?? null ) ??
|
|
129
|
+
null
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
renderInlineEditor() {
|
|
134
|
+
const propValue = this.getContentValue();
|
|
135
|
+
const classes = ( this.element.children?.[ 0 ]?.classList.toString() ?? '' ) + ' strip-styles';
|
|
136
|
+
const expectedTag = this.getExpectedTag();
|
|
137
|
+
|
|
138
|
+
this.element.innerHTML = '';
|
|
139
|
+
|
|
140
|
+
if ( this.inlineEditorRoot ) {
|
|
141
|
+
this.resetInlineEditorRoot();
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
this.inlineEditorRoot = createRoot( this.element );
|
|
145
|
+
|
|
146
|
+
this.inlineEditorRoot.render(
|
|
147
|
+
<ThemeProvider>
|
|
148
|
+
<InlineEditor
|
|
149
|
+
attributes={ { class: classes } }
|
|
150
|
+
value={ propValue }
|
|
151
|
+
setValue={ this.setContentValue.bind( this ) }
|
|
152
|
+
onBlur={ this.handleUnmountInlineEditor.bind( this ) }
|
|
153
|
+
autofocus
|
|
154
|
+
showToolbar
|
|
155
|
+
getInitialPopoverPosition={ getInitialPopoverPosition }
|
|
156
|
+
expectedTag={ expectedTag }
|
|
157
|
+
/>
|
|
158
|
+
</ThemeProvider>
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { type V1Element } from '@elementor/editor-elements';
|
|
2
|
+
|
|
3
|
+
import { type LegacyWindow } from '../../types';
|
|
4
|
+
|
|
5
|
+
export const INLINE_EDITING_PROPERTY_PER_TYPE: Record< string, string > = {
|
|
6
|
+
'e-heading': 'title',
|
|
7
|
+
'e-paragraph': 'paragraph',
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export const legacyWindow = window as unknown as LegacyWindow;
|
|
11
|
+
|
|
12
|
+
export const getWidgetType = ( container: V1Element | null ) => {
|
|
13
|
+
return container?.model?.get( 'widgetType' ) ?? container?.model?.get( 'elType' ) ?? null;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export const getInitialPopoverPosition = () => {
|
|
17
|
+
const positionFallback = { left: 0, top: 0 };
|
|
18
|
+
|
|
19
|
+
const iFrameElement = legacyWindow?.elementor?.$preview?.get( 0 );
|
|
20
|
+
const iFramePosition = iFrameElement?.getBoundingClientRect() ?? positionFallback;
|
|
21
|
+
|
|
22
|
+
const previewElement = legacyWindow?.elementor?.$previewWrapper?.get( 0 );
|
|
23
|
+
const previewPosition = previewElement
|
|
24
|
+
? { left: previewElement.scrollLeft, top: previewElement.scrollTop }
|
|
25
|
+
: positionFallback;
|
|
26
|
+
|
|
27
|
+
return {
|
|
28
|
+
left: iFramePosition.left + previewPosition.left,
|
|
29
|
+
top: iFramePosition.top + previewPosition.top,
|
|
30
|
+
};
|
|
31
|
+
};
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import type { CreateTemplatedElementTypeOptions } from '../create-templated-element-type';
|
|
2
|
+
import { createTemplatedElementView } from '../create-templated-element-type';
|
|
3
|
+
import type { ElementType, ElementView, LegacyWindow, ReplacementSettings } from '../types';
|
|
4
|
+
import type ReplacementBase from './base';
|
|
5
|
+
import InlineEditingReplacement from './inline-editing/inline-editing-elements';
|
|
6
|
+
|
|
7
|
+
type ReplacementConstructor = new ( settings: ReplacementSettings ) => ReplacementBase;
|
|
8
|
+
|
|
9
|
+
const replacements = new Map< string, ReplacementConstructor >();
|
|
10
|
+
|
|
11
|
+
export const initViewReplacements = () => {
|
|
12
|
+
registerReplacement( InlineEditingReplacement );
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export const registerReplacement = ( replacement: typeof ReplacementBase ) => {
|
|
16
|
+
const types = replacement.getTypes();
|
|
17
|
+
|
|
18
|
+
if ( ! types ) {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
types.forEach( ( type ) => {
|
|
23
|
+
replacements.set( type, replacement );
|
|
24
|
+
} );
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export const getReplacement = ( type: string ) => {
|
|
28
|
+
return replacements.get( type ) ?? null;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export const createViewWithReplacements = ( options: CreateTemplatedElementTypeOptions ): typeof ElementView => {
|
|
32
|
+
const TemplatedView = createTemplatedElementView( options );
|
|
33
|
+
|
|
34
|
+
return class extends TemplatedView {
|
|
35
|
+
#replacement: ReplacementBase | null = null;
|
|
36
|
+
#config: ReplacementSettings;
|
|
37
|
+
|
|
38
|
+
constructor( ...args: unknown[] ) {
|
|
39
|
+
super( ...args );
|
|
40
|
+
const settings = this.model.get( 'settings' );
|
|
41
|
+
|
|
42
|
+
this.#config = {
|
|
43
|
+
getSetting: settings.get.bind( settings ),
|
|
44
|
+
setSetting: settings.set.bind( settings ),
|
|
45
|
+
element: this.el,
|
|
46
|
+
type: this?.model?.get( 'widgetType' ) ?? this.container?.model?.get( 'elType' ) ?? null,
|
|
47
|
+
id: this?.model?.get( 'id' ) ?? null,
|
|
48
|
+
refreshView: this.render.bind( this ),
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
refreshView() {
|
|
53
|
+
this.render();
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
render() {
|
|
57
|
+
const config = this.#config;
|
|
58
|
+
const widgetType = config.type;
|
|
59
|
+
const ReplacementClass = widgetType ? getReplacement( widgetType ) : null;
|
|
60
|
+
|
|
61
|
+
if ( ReplacementClass && ! this.#replacement ) {
|
|
62
|
+
this.#replacement = new ReplacementClass( config );
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if ( ! this.#replacement?.shouldRenderReplacement() ) {
|
|
66
|
+
return TemplatedView.prototype.render.apply( this );
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
this.#replacement.render();
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
onDestroy() {
|
|
73
|
+
if ( this.#replacement ) {
|
|
74
|
+
this.#replacement.onDestroy();
|
|
75
|
+
this.#replacement = null;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
TemplatedView.prototype.onDestroy.apply( this );
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
_afterRender() {
|
|
82
|
+
if ( this.#replacement ) {
|
|
83
|
+
this.#replacement._afterRender();
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
TemplatedView.prototype._afterRender.apply( this );
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
_beforeRender(): void {
|
|
90
|
+
if ( this.#replacement ) {
|
|
91
|
+
this.#replacement._beforeRender();
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
TemplatedView.prototype._beforeRender.apply( this );
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
export const createTemplatedElementTypeWithReplacements = ( {
|
|
100
|
+
type,
|
|
101
|
+
renderer,
|
|
102
|
+
element,
|
|
103
|
+
}: CreateTemplatedElementTypeOptions ): typeof ElementType => {
|
|
104
|
+
const legacyWindow = window as unknown as LegacyWindow;
|
|
105
|
+
|
|
106
|
+
return class extends legacyWindow.elementor.modules.elements.types.Widget {
|
|
107
|
+
getType() {
|
|
108
|
+
return type;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
getView() {
|
|
112
|
+
return createViewWithReplacements( {
|
|
113
|
+
type,
|
|
114
|
+
renderer,
|
|
115
|
+
element,
|
|
116
|
+
} );
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
};
|
package/src/legacy/types.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type V1Element } from '@elementor/editor-elements';
|
|
2
|
-
import { type Props } from '@elementor/editor-props';
|
|
2
|
+
import { type Props, type PropValue } from '@elementor/editor-props';
|
|
3
3
|
|
|
4
4
|
export type LegacyWindow = Window & {
|
|
5
5
|
elementor: {
|
|
@@ -80,6 +80,10 @@ export declare class ElementView {
|
|
|
80
80
|
|
|
81
81
|
_renderChildren(): void;
|
|
82
82
|
|
|
83
|
+
_beforeRender(): void;
|
|
84
|
+
|
|
85
|
+
_afterRender(): void;
|
|
86
|
+
|
|
83
87
|
attachBuffer( collectionView: this, buffer: DocumentFragment ): void;
|
|
84
88
|
|
|
85
89
|
triggerMethod( method: string, ...args: unknown[] ): void;
|
|
@@ -140,3 +144,12 @@ type ContextMenuGroup = {
|
|
|
140
144
|
name: string;
|
|
141
145
|
actions: unknown[];
|
|
142
146
|
};
|
|
147
|
+
|
|
148
|
+
export type ReplacementSettings = {
|
|
149
|
+
getSetting: ( key: string ) => unknown;
|
|
150
|
+
setSetting: ( key: string, value: PropValue ) => void;
|
|
151
|
+
type: string;
|
|
152
|
+
id: string;
|
|
153
|
+
element: HTMLElement;
|
|
154
|
+
refreshView: () => void;
|
|
155
|
+
};
|