@elementor/frontend-handlers 3.35.0-425 → 3.35.0-427

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.js CHANGED
@@ -69,12 +69,12 @@ var unregisterBySelector = ({ selector, id }) => {
69
69
  return;
70
70
  }
71
71
  if (id) {
72
- elementTypeHandlers.get(selector)?.delete(id);
73
- if (elementTypeHandlers.get(selector)?.size === 0) {
74
- elementTypeHandlers.delete(selector);
72
+ elementSelectorHandlers.get(selector)?.delete(id);
73
+ if (elementSelectorHandlers.get(selector)?.size === 0) {
74
+ elementSelectorHandlers.delete(selector);
75
75
  }
76
76
  } else {
77
- elementTypeHandlers.delete(selector);
77
+ elementSelectorHandlers.delete(selector);
78
78
  }
79
79
  };
80
80
 
@@ -90,6 +90,7 @@ var onElementRender = ({
90
90
  const controller = new AbortController();
91
91
  const manualUnmount = [];
92
92
  const dispatchRenderedEvent = () => {
93
+ onElementSelectorRender({ element, elementId, controller });
93
94
  element.dispatchEvent(
94
95
  new CustomEvent(ELEMENT_RENDERED_EVENT_NAME, {
95
96
  bubbles: true,
@@ -167,8 +168,11 @@ var onElementSelectorRender = ({
167
168
  manualUnmount.push(unmount);
168
169
  }
169
170
  });
170
- if (!unmountElementSelectorCallbacks.has(elementId)) {
171
- unmountElementTypeCallbacks.set(elementId, /* @__PURE__ */ new Map());
171
+ if (!manualUnmount.length) {
172
+ return;
173
+ }
174
+ if (!unmountElementSelectorCallbacks.get(elementId)) {
175
+ unmountElementSelectorCallbacks.set(elementId, /* @__PURE__ */ new Map());
172
176
  }
173
177
  unmountElementSelectorCallbacks.get(elementId)?.set(selector, () => {
174
178
  controller.abort();
@@ -178,14 +182,23 @@ var onElementSelectorRender = ({
178
182
  };
179
183
  var onElementDestroy = ({ elementType, elementId }) => {
180
184
  const unmount = unmountElementTypeCallbacks.get(elementType)?.get(elementId);
181
- if (!unmount) {
182
- return;
185
+ const unmountSelector = unmountElementSelectorCallbacks.get(elementId);
186
+ if (unmount) {
187
+ unmount();
188
+ }
189
+ if (unmountSelector?.size) {
190
+ Array.from(unmountSelector.values()).forEach((selectorUnmount) => {
191
+ selectorUnmount();
192
+ });
183
193
  }
184
- unmount();
185
194
  unmountElementTypeCallbacks.get(elementType)?.delete(elementId);
195
+ unmountElementSelectorCallbacks.delete(elementId);
186
196
  if (unmountElementTypeCallbacks.get(elementType)?.size === 0) {
187
197
  unmountElementTypeCallbacks.delete(elementType);
188
198
  }
199
+ if (unmountElementSelectorCallbacks.size === 0) {
200
+ unmountElementSelectorCallbacks.delete(elementId);
201
+ }
189
202
  };
190
203
 
191
204
  // src/init.ts
@@ -202,7 +215,6 @@ function init() {
202
215
  onElementDestroy({ elementType: type, elementId: id });
203
216
  });
204
217
  document.addEventListener("DOMContentLoaded", () => {
205
- const controller = new AbortController();
206
218
  document.querySelectorAll("[data-e-type]").forEach((element) => {
207
219
  const el = element;
208
220
  const { eType, id } = el.dataset;
@@ -219,17 +231,6 @@ function init() {
219
231
  })
220
232
  );
221
233
  });
222
- Array.from(elementSelectorHandlers.keys()).forEach((selector) => {
223
- Array.from(document.querySelectorAll(selector)).forEach((element) => {
224
- const el = element;
225
- const elementId = el?.closest("[data-id]")?.getAttribute("data-id") ?? "";
226
- onElementSelectorRender({
227
- element,
228
- controller,
229
- elementId
230
- });
231
- });
232
- });
233
234
  });
234
235
  }
235
236
  // Annotate the CommonJS export names for ESM import in node:
package/dist/index.mjs CHANGED
@@ -39,12 +39,12 @@ var unregisterBySelector = ({ selector, id }) => {
39
39
  return;
40
40
  }
41
41
  if (id) {
42
- elementTypeHandlers.get(selector)?.delete(id);
43
- if (elementTypeHandlers.get(selector)?.size === 0) {
44
- elementTypeHandlers.delete(selector);
42
+ elementSelectorHandlers.get(selector)?.delete(id);
43
+ if (elementSelectorHandlers.get(selector)?.size === 0) {
44
+ elementSelectorHandlers.delete(selector);
45
45
  }
46
46
  } else {
47
- elementTypeHandlers.delete(selector);
47
+ elementSelectorHandlers.delete(selector);
48
48
  }
49
49
  };
50
50
 
@@ -60,6 +60,7 @@ var onElementRender = ({
60
60
  const controller = new AbortController();
61
61
  const manualUnmount = [];
62
62
  const dispatchRenderedEvent = () => {
63
+ onElementSelectorRender({ element, elementId, controller });
63
64
  element.dispatchEvent(
64
65
  new CustomEvent(ELEMENT_RENDERED_EVENT_NAME, {
65
66
  bubbles: true,
@@ -137,8 +138,11 @@ var onElementSelectorRender = ({
137
138
  manualUnmount.push(unmount);
138
139
  }
139
140
  });
140
- if (!unmountElementSelectorCallbacks.has(elementId)) {
141
- unmountElementTypeCallbacks.set(elementId, /* @__PURE__ */ new Map());
141
+ if (!manualUnmount.length) {
142
+ return;
143
+ }
144
+ if (!unmountElementSelectorCallbacks.get(elementId)) {
145
+ unmountElementSelectorCallbacks.set(elementId, /* @__PURE__ */ new Map());
142
146
  }
143
147
  unmountElementSelectorCallbacks.get(elementId)?.set(selector, () => {
144
148
  controller.abort();
@@ -148,14 +152,23 @@ var onElementSelectorRender = ({
148
152
  };
149
153
  var onElementDestroy = ({ elementType, elementId }) => {
150
154
  const unmount = unmountElementTypeCallbacks.get(elementType)?.get(elementId);
151
- if (!unmount) {
152
- return;
155
+ const unmountSelector = unmountElementSelectorCallbacks.get(elementId);
156
+ if (unmount) {
157
+ unmount();
158
+ }
159
+ if (unmountSelector?.size) {
160
+ Array.from(unmountSelector.values()).forEach((selectorUnmount) => {
161
+ selectorUnmount();
162
+ });
153
163
  }
154
- unmount();
155
164
  unmountElementTypeCallbacks.get(elementType)?.delete(elementId);
165
+ unmountElementSelectorCallbacks.delete(elementId);
156
166
  if (unmountElementTypeCallbacks.get(elementType)?.size === 0) {
157
167
  unmountElementTypeCallbacks.delete(elementType);
158
168
  }
169
+ if (unmountElementSelectorCallbacks.size === 0) {
170
+ unmountElementSelectorCallbacks.delete(elementId);
171
+ }
159
172
  };
160
173
 
161
174
  // src/init.ts
@@ -172,7 +185,6 @@ function init() {
172
185
  onElementDestroy({ elementType: type, elementId: id });
173
186
  });
174
187
  document.addEventListener("DOMContentLoaded", () => {
175
- const controller = new AbortController();
176
188
  document.querySelectorAll("[data-e-type]").forEach((element) => {
177
189
  const el = element;
178
190
  const { eType, id } = el.dataset;
@@ -189,17 +201,6 @@ function init() {
189
201
  })
190
202
  );
191
203
  });
192
- Array.from(elementSelectorHandlers.keys()).forEach((selector) => {
193
- Array.from(document.querySelectorAll(selector)).forEach((element) => {
194
- const el = element;
195
- const elementId = el?.closest("[data-id]")?.getAttribute("data-id") ?? "";
196
- onElementSelectorRender({
197
- element,
198
- controller,
199
- elementId
200
- });
201
- });
202
- });
203
204
  });
204
205
  }
205
206
  export {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@elementor/frontend-handlers",
3
3
  "description": "Elementor Frontend Handlers",
4
- "version": "3.35.0-425",
4
+ "version": "3.35.0-427",
5
5
  "private": false,
6
6
  "author": "Elementor Team",
7
7
  "homepage": "https://elementor.com/",
@@ -1,20 +1,35 @@
1
- import { elementTypeHandlers } from '../handlers-registry';
2
- import { init, register, unregister } from '../index';
1
+ import { init, register, registerBySelector, unregister, unregisterBySelector } from '../index';
3
2
 
4
3
  describe( 'Frontend Handlers', () => {
5
4
  const PARENT_ELEMENT_TYPE = 'e-parent-element';
6
5
  const CHILD_ELEMENT_TYPE = 'e-child-element';
7
6
  const WIDGET_ELEMENT_TYPE = 'e-widget';
7
+ const ELEMENT_CLASS = 'selector-target';
8
+ const SELECTOR_TARGET = `.${ ELEMENT_CLASS }`;
9
+ const HANDLER_IDS = {
10
+ handler_1: 'handler-1',
11
+ handler_2: 'handler-2',
12
+ parent_handler: 'parent-handler',
13
+ };
8
14
 
9
15
  beforeAll( () => {
10
16
  init();
11
17
  } );
12
18
 
13
19
  beforeEach( () => {
14
- elementTypeHandlers.clear();
15
20
  document.body.innerHTML = '';
16
21
  } );
17
22
 
23
+ afterEach( () => {
24
+ [ WIDGET_ELEMENT_TYPE, PARENT_ELEMENT_TYPE, CHILD_ELEMENT_TYPE ].forEach( ( elementType ) => {
25
+ unregister( { elementType } );
26
+ } );
27
+
28
+ Object.values( HANDLER_IDS ).forEach( ( handler ) => {
29
+ unregisterBySelector( { selector: SELECTOR_TARGET, id: handler } );
30
+ } );
31
+ } );
32
+
18
33
  describe( 'Handler Registration', () => {
19
34
  it( 'should register and execute handler callback', () => {
20
35
  // Arrange
@@ -57,13 +72,13 @@ describe( 'Frontend Handlers', () => {
57
72
 
58
73
  register( {
59
74
  elementType: WIDGET_ELEMENT_TYPE,
60
- id: 'handler-1',
75
+ id: HANDLER_IDS.handler_1,
61
76
  callback: handler1,
62
77
  } );
63
78
 
64
79
  register( {
65
80
  elementType: WIDGET_ELEMENT_TYPE,
66
- id: 'handler-2',
81
+ id: HANDLER_IDS.handler_2,
67
82
  callback: handler2,
68
83
  } );
69
84
 
@@ -91,11 +106,11 @@ describe( 'Frontend Handlers', () => {
91
106
 
92
107
  register( {
93
108
  elementType: WIDGET_ELEMENT_TYPE,
94
- id: 'widget-handler',
109
+ id: HANDLER_IDS.handler_1,
95
110
  callback: handlerCallback,
96
111
  } );
97
112
 
98
- unregister( { elementType: WIDGET_ELEMENT_TYPE, id: 'widget-handler' } );
113
+ unregister( { elementType: WIDGET_ELEMENT_TYPE, id: HANDLER_IDS.handler_1 } );
99
114
 
100
115
  const element = document.createElement( 'div' );
101
116
  element.setAttribute( 'data-e-type', WIDGET_ELEMENT_TYPE );
@@ -123,7 +138,7 @@ describe( 'Frontend Handlers', () => {
123
138
 
124
139
  register( {
125
140
  elementType: WIDGET_ELEMENT_TYPE,
126
- id: 'widget-handler',
141
+ id: HANDLER_IDS.handler_1,
127
142
  callback: handlerCallback,
128
143
  } );
129
144
 
@@ -157,7 +172,7 @@ describe( 'Frontend Handlers', () => {
157
172
 
158
173
  register( {
159
174
  elementType: WIDGET_ELEMENT_TYPE,
160
- id: 'widget-handler',
175
+ id: HANDLER_IDS.handler_1,
161
176
  callback: ( { settings } ) => {
162
177
  settingsHistory.push( { ...settings } );
163
178
  return undefined;
@@ -193,6 +208,37 @@ describe( 'Frontend Handlers', () => {
193
208
  } );
194
209
 
195
210
  describe( 'Cleanup and Unmount', () => {
211
+ it( 'should call selector unmount callback when element is destroyed', () => {
212
+ const ELEMENT_ID = 'selector-1';
213
+ const unmountSelector = jest.fn();
214
+
215
+ registerBySelector( {
216
+ selector: SELECTOR_TARGET,
217
+ id: HANDLER_IDS.handler_1,
218
+ callback: () => unmountSelector,
219
+ } );
220
+
221
+ const element = document.createElement( 'div' );
222
+ element.classList.add( ELEMENT_CLASS );
223
+ element.setAttribute( 'data-e-type', WIDGET_ELEMENT_TYPE );
224
+ element.setAttribute( 'data-id', ELEMENT_ID );
225
+ document.body.appendChild( element );
226
+
227
+ window.dispatchEvent(
228
+ new CustomEvent( 'elementor/element/render', {
229
+ detail: { id: ELEMENT_ID, type: WIDGET_ELEMENT_TYPE, element },
230
+ } )
231
+ );
232
+
233
+ window.dispatchEvent(
234
+ new CustomEvent( 'elementor/element/destroy', {
235
+ detail: { id: ELEMENT_ID, type: WIDGET_ELEMENT_TYPE },
236
+ } )
237
+ );
238
+
239
+ expect( unmountSelector ).toHaveBeenCalledTimes( 1 );
240
+ } );
241
+
196
242
  it( 'should call unmount callback when element is destroyed', () => {
197
243
  // Arrange
198
244
  const ELEMENT_ID = 'element-1';
@@ -200,7 +246,7 @@ describe( 'Frontend Handlers', () => {
200
246
 
201
247
  register( {
202
248
  elementType: WIDGET_ELEMENT_TYPE,
203
- id: 'widget-handler',
249
+ id: HANDLER_IDS.handler_1,
204
250
  callback: () => unmountCallback,
205
251
  } );
206
252
 
@@ -233,7 +279,7 @@ describe( 'Frontend Handlers', () => {
233
279
 
234
280
  register( {
235
281
  elementType: WIDGET_ELEMENT_TYPE,
236
- id: 'widget-handler',
282
+ id: HANDLER_IDS.handler_1,
237
283
  callback: () => {
238
284
  lifecycleEvents.push( 'init' );
239
285
  return () => {
@@ -279,7 +325,7 @@ describe( 'Frontend Handlers', () => {
279
325
 
280
326
  register( {
281
327
  elementType: WIDGET_ELEMENT_TYPE,
282
- id: 'widget-handler',
328
+ id: HANDLER_IDS.handler_1,
283
329
  callback: ( { signal } ) => {
284
330
  receivedSignal = signal;
285
331
  return undefined;
@@ -310,7 +356,7 @@ describe( 'Frontend Handlers', () => {
310
356
 
311
357
  register( {
312
358
  elementType: WIDGET_ELEMENT_TYPE,
313
- id: 'widget-handler',
359
+ id: HANDLER_IDS.handler_1,
314
360
  callback: ( { signal } ) => {
315
361
  signal.addEventListener( 'abort', () => {
316
362
  signalAborted = true;
@@ -351,7 +397,7 @@ describe( 'Frontend Handlers', () => {
351
397
 
352
398
  register( {
353
399
  elementType: PARENT_ELEMENT_TYPE,
354
- id: 'parent-handler',
400
+ id: HANDLER_IDS.handler_1,
355
401
  callback: ( { listenToChildren } ) => {
356
402
  listenToChildren( [ CHILD_ELEMENT_TYPE ] ).render( childRenderCallback );
357
403
  return undefined;
@@ -394,7 +440,7 @@ describe( 'Frontend Handlers', () => {
394
440
 
395
441
  register( {
396
442
  elementType: PARENT_ELEMENT_TYPE,
397
- id: 'parent-handler',
443
+ id: HANDLER_IDS.parent_handler,
398
444
  callback: ( { listenToChildren } ) => {
399
445
  listenToChildren( [ CHILD_ELEMENT_TYPE ] ).render( childRenderCallback );
400
446
  return undefined;
@@ -436,7 +482,7 @@ describe( 'Frontend Handlers', () => {
436
482
 
437
483
  register( {
438
484
  elementType: PARENT_ELEMENT_TYPE,
439
- id: 'parent-handler',
485
+ id: HANDLER_IDS.parent_handler,
440
486
  callback: ( { listenToChildren } ) => {
441
487
  listenToChildren( [ CHILD_ELEMENT_TYPE ] ).render( childRenderCallback );
442
488
  return undefined;
@@ -490,7 +536,7 @@ describe( 'Frontend Handlers', () => {
490
536
 
491
537
  register( {
492
538
  elementType: PARENT_ELEMENT_TYPE,
493
- id: 'parent-handler',
539
+ id: HANDLER_IDS.parent_handler,
494
540
  callback: ( { element, listenToChildren } ) => {
495
541
  const parentId = element.getAttribute( 'data-id' ) || 'unknown';
496
542
  callbackCounts.set( parentId, 0 );
@@ -543,16 +589,70 @@ describe( 'Frontend Handlers', () => {
543
589
  } );
544
590
 
545
591
  describe( 'DOMContentLoaded Initialization', () => {
546
- it( 'should initialize all existing elements on page load', () => {
592
+ it( 'should skip selector initialization on page load when in editor', () => {
547
593
  // Arrange
548
- elementTypeHandlers.clear();
549
- document.body.innerHTML = '';
594
+ const ELEMENT_ID = 'element-1';
595
+ const selectorHandler = jest.fn();
596
+
597
+ registerBySelector( {
598
+ selector: SELECTOR_TARGET,
599
+ id: HANDLER_IDS.handler_1,
600
+ callback: selectorHandler,
601
+ } );
550
602
 
603
+ const element = document.createElement( 'div' );
604
+ element.classList.add( ELEMENT_CLASS );
605
+ element.setAttribute( 'data-id', ELEMENT_ID );
606
+ element.setAttribute( 'data-e-type', WIDGET_ELEMENT_TYPE );
607
+ document.body.appendChild( element );
608
+
609
+ const editorWindow = window as Window & { elementor?: unknown };
610
+
611
+ editorWindow.elementor = {};
612
+
613
+ document.dispatchEvent( new Event( 'DOMContentLoaded' ) );
614
+
615
+ expect( selectorHandler ).toHaveBeenCalledTimes( 1 );
616
+ } );
617
+
618
+ it( 'should initialize selector handlers on page load', () => {
619
+ // Arrange
620
+ const ELEMENT_ID = 'element-1';
621
+ const selectorHandler = jest.fn();
622
+
623
+ registerBySelector( {
624
+ selector: SELECTOR_TARGET,
625
+ id: HANDLER_IDS.handler_1,
626
+ callback: selectorHandler,
627
+ } );
628
+
629
+ const element = document.createElement( 'div' );
630
+ element.classList.add( ELEMENT_CLASS );
631
+ element.setAttribute( 'data-id', ELEMENT_ID );
632
+ element.setAttribute( 'data-e-type', WIDGET_ELEMENT_TYPE );
633
+ document.body.appendChild( element );
634
+
635
+ document.dispatchEvent( new Event( 'DOMContentLoaded' ) );
636
+
637
+ expect( selectorHandler ).toHaveBeenCalledTimes( 1 );
638
+ expect( selectorHandler ).toHaveBeenCalledWith(
639
+ expect.objectContaining( {
640
+ element,
641
+ settings: {},
642
+ signal: expect.any( AbortSignal ),
643
+ } )
644
+ );
645
+ } );
646
+
647
+ it( 'should initialize all existing elements on page load', () => {
648
+ // Arrange
649
+ const PARENT_ID = 'parent-1';
650
+ const WIDGET_ID = 'widget-1';
551
651
  const initializedElements: string[] = [];
552
652
 
553
653
  register( {
554
654
  elementType: PARENT_ELEMENT_TYPE,
555
- id: 'parent-handler',
655
+ id: HANDLER_IDS.parent_handler,
556
656
  callback: ( { element } ) => {
557
657
  const id = element.getAttribute( 'data-id' ) || 'unknown';
558
658
  initializedElements.push( id );
@@ -562,7 +662,7 @@ describe( 'Frontend Handlers', () => {
562
662
 
563
663
  register( {
564
664
  elementType: WIDGET_ELEMENT_TYPE,
565
- id: 'widget-handler',
665
+ id: HANDLER_IDS.handler_1,
566
666
  callback: ( { element } ) => {
567
667
  const id = element.getAttribute( 'data-id' ) || 'unknown';
568
668
  initializedElements.push( id );
@@ -572,12 +672,12 @@ describe( 'Frontend Handlers', () => {
572
672
 
573
673
  const parent = document.createElement( 'div' );
574
674
  parent.setAttribute( 'data-e-type', PARENT_ELEMENT_TYPE );
575
- parent.setAttribute( 'data-id', 'parent-1' );
675
+ parent.setAttribute( 'data-id', PARENT_ID );
576
676
  document.body.appendChild( parent );
577
677
 
578
678
  const widget = document.createElement( 'div' );
579
679
  widget.setAttribute( 'data-e-type', WIDGET_ELEMENT_TYPE );
580
- widget.setAttribute( 'data-id', 'widget-1' );
680
+ widget.setAttribute( 'data-id', WIDGET_ID );
581
681
  document.body.appendChild( widget );
582
682
 
583
683
  init();
@@ -586,8 +686,8 @@ describe( 'Frontend Handlers', () => {
586
686
  document.dispatchEvent( new Event( 'DOMContentLoaded' ) );
587
687
 
588
688
  // Assert
589
- expect( initializedElements ).toContain( 'parent-1' );
590
- expect( initializedElements ).toContain( 'widget-1' );
689
+ expect( initializedElements ).toContain( PARENT_ID );
690
+ expect( initializedElements ).toContain( WIDGET_ID );
591
691
  } );
592
692
  } );
593
693
  } );
@@ -77,12 +77,12 @@ export const unregisterBySelector = ( { selector, id }: { selector: string; id?:
77
77
  }
78
78
 
79
79
  if ( id ) {
80
- elementTypeHandlers.get( selector )?.delete( id );
80
+ elementSelectorHandlers.get( selector )?.delete( id );
81
81
 
82
- if ( elementTypeHandlers.get( selector )?.size === 0 ) {
83
- elementTypeHandlers.delete( selector );
82
+ if ( elementSelectorHandlers.get( selector )?.size === 0 ) {
83
+ elementSelectorHandlers.delete( selector );
84
84
  }
85
85
  } else {
86
- elementTypeHandlers.delete( selector );
86
+ elementSelectorHandlers.delete( selector );
87
87
  }
88
88
  };
package/src/init.ts CHANGED
@@ -1,5 +1,4 @@
1
- import { elementSelectorHandlers } from './handlers-registry';
2
- import { onElementDestroy, onElementRender, onElementSelectorRender } from './lifecycle-events';
1
+ import { onElementDestroy, onElementRender } from './lifecycle-events';
3
2
 
4
3
  export function init() {
5
4
  window.addEventListener( 'elementor/element/render', ( _event ) => {
@@ -19,12 +18,10 @@ export function init() {
19
18
  onElementDestroy( { elementType: type, elementId: id } );
20
19
  } );
21
20
 
21
+ // 'elementor/element/render' doesn't fire on the frontend
22
22
  document.addEventListener( 'DOMContentLoaded', () => {
23
- const controller = new AbortController();
24
-
25
23
  document.querySelectorAll( '[data-e-type]' ).forEach( ( element ) => {
26
24
  const el = element as HTMLElement;
27
-
28
25
  const { eType, id } = el.dataset;
29
26
 
30
27
  if ( ! eType || ! id ) {
@@ -41,18 +38,5 @@ export function init() {
41
38
  } )
42
39
  );
43
40
  } );
44
-
45
- Array.from( elementSelectorHandlers.keys() ).forEach( ( selector ) => {
46
- Array.from( document.querySelectorAll( selector ) ).forEach( ( element ) => {
47
- const el = element as HTMLElement;
48
- const elementId = el?.closest( '[data-id]' )?.getAttribute( 'data-id' ) ?? '';
49
-
50
- onElementSelectorRender( {
51
- element,
52
- controller,
53
- elementId,
54
- } );
55
- } );
56
- } );
57
41
  } );
58
42
  }
@@ -18,6 +18,8 @@ export const onElementRender = ( {
18
18
  const manualUnmount: ( () => void )[] = [];
19
19
 
20
20
  const dispatchRenderedEvent = () => {
21
+ onElementSelectorRender( { element, elementId, controller } );
22
+
21
23
  element.dispatchEvent(
22
24
  new CustomEvent( ELEMENT_RENDERED_EVENT_NAME, {
23
25
  bubbles: true,
@@ -30,7 +32,7 @@ export const onElementRender = ( {
30
32
  );
31
33
  };
32
34
 
33
- // When the rendered event is dispatched, the element is not yet connected to the DOM (marrionet view case)
35
+ // When the rendered event is dispatched, the element is not yet connected to the DOM (marionette view case)
34
36
  if ( ! element.isConnected ) {
35
37
  requestAnimationFrame( () => {
36
38
  dispatchRenderedEvent();
@@ -117,8 +119,12 @@ export const onElementSelectorRender = ( {
117
119
  }
118
120
  } );
119
121
 
120
- if ( ! unmountElementSelectorCallbacks.has( elementId ) ) {
121
- unmountElementTypeCallbacks.set( elementId, new Map() );
122
+ if ( ! manualUnmount.length ) {
123
+ return;
124
+ }
125
+
126
+ if ( ! unmountElementSelectorCallbacks.get( elementId ) ) {
127
+ unmountElementSelectorCallbacks.set( elementId, new Map() );
122
128
  }
123
129
 
124
130
  unmountElementSelectorCallbacks.get( elementId )?.set( selector, () => {
@@ -131,16 +137,26 @@ export const onElementSelectorRender = ( {
131
137
 
132
138
  export const onElementDestroy = ( { elementType, elementId }: { elementType: string; elementId: string } ) => {
133
139
  const unmount = unmountElementTypeCallbacks.get( elementType )?.get( elementId );
140
+ const unmountSelector = unmountElementSelectorCallbacks.get( elementId );
134
141
 
135
- if ( ! unmount ) {
136
- return;
142
+ if ( unmount ) {
143
+ unmount();
137
144
  }
138
145
 
139
- unmount();
146
+ if ( unmountSelector?.size ) {
147
+ Array.from( unmountSelector.values() ).forEach( ( selectorUnmount ) => {
148
+ selectorUnmount();
149
+ } );
150
+ }
140
151
 
141
152
  unmountElementTypeCallbacks.get( elementType )?.delete( elementId );
153
+ unmountElementSelectorCallbacks.delete( elementId );
142
154
 
143
155
  if ( unmountElementTypeCallbacks.get( elementType )?.size === 0 ) {
144
156
  unmountElementTypeCallbacks.delete( elementType );
145
157
  }
158
+
159
+ if ( unmountElementSelectorCallbacks.size === 0 ) {
160
+ unmountElementSelectorCallbacks.delete( elementId );
161
+ }
146
162
  };