Skip to content

Commit d775398

Browse files
steven008thePunderWoman
authored andcommitted
refactor(migrations): update references for dom_trigger functions onInteract, onHover, onViewport to point to new location in core/primitives/defer (angular#61342)
Moves the onInteract, onHover, onViewport dom_trigger functions to /packages/core/primitives/defer to be used as a shared library PR Close angular#61342
1 parent 74cf9cb commit d775398

7 files changed

Lines changed: 60 additions & 127 deletions

File tree

packages/core/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ ng_project(
4242
],
4343
),
4444
interop_deps = [
45+
"//packages/core/primitives/defer:triggers",
4546
"//packages/core/primitives/di",
4647
"//packages/core/primitives/dom-navigation",
4748
"//packages/core/primitives/event-dispatch",
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
load("//tools:defaults.bzl", "ts_library")
2+
3+
package(default_visibility = [
4+
"//packages/core:__subpackages__",
5+
])
6+
7+
ts_library(
8+
name = "triggers",
9+
srcs = glob(
10+
[
11+
"**/*.ts",
12+
],
13+
),
14+
)
Lines changed: 35 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
/*!
2+
* @license
3+
* Copyright Google LLC All Rights Reserved.
4+
*
5+
* Use of this source code is governed by an MIT-style license that can be
6+
* found in the LICENSE file at https://angular.dev/license
7+
*/
18

29
/** Configuration object used to register passive and capturing events. */
310
const eventListenerOptions: AddEventListenerOptions = {
@@ -12,7 +19,7 @@ const hoverTriggers = new WeakMap<Element, DeferEventEntry>();
1219
const interactionTriggers = new WeakMap<Element, DeferEventEntry>();
1320

1421
/** Currently-registered `viewport` triggers. */
15-
const viewportTriggers = new WeakMap<Element, DeferEventEntry>();
22+
export const viewportTriggers = new WeakMap<Element, DeferEventEntry>();
1623

1724
/** Names of the events considered as interaction events. */
1825
export const interactionEventNames = ['click', 'keydown'] as const;
@@ -37,14 +44,12 @@ class DeferEventEntry {
3744
};
3845
}
3946

40-
export function getViewportTriggers() {
41-
return viewportTriggers;
42-
}
43-
4447
/**
4548
* Registers an interaction trigger.
4649
* @param trigger Element that is the trigger.
4750
* @param callback Callback to be invoked when the trigger is interacted with.
51+
* @return cleanup function which removes trigger Element from interactionTriggers map
52+
* and interaction event listeners from the trigger Element
4853
*/
4954
export function onInteraction(trigger: Element, callback: VoidFunction): VoidFunction {
5055
let entry = interactionTriggers.get(trigger);
@@ -86,11 +91,12 @@ export function onInteraction(trigger: Element, callback: VoidFunction): VoidFun
8691
};
8792
}
8893

89-
9094
/**
9195
* Registers a hover trigger.
9296
* @param trigger Element that is the trigger.
9397
* @param callback Callback to be invoked when the trigger is hovered over.
98+
* @return cleanup function which removes trigger element from hoverTriggers map
99+
* and removes hover interaction event listeners from the trigger element
94100
*/
95101
export function onHover(trigger: Element, callback: VoidFunction): VoidFunction {
96102
let entry = hoverTriggers.get(trigger);
@@ -120,125 +126,63 @@ export function onHover(trigger: Element, callback: VoidFunction): VoidFunction
120126
};
121127
}
122128

123-
export interface Observer {
124-
observe: (target: Element) => void,
125-
unobserve: (target: Element) => void,
126-
disconnect: () => void;
129+
/**
130+
* Used to create an IntersectionObserver instance.
131+
* @return IntersectionObserver that is used by onViewport
132+
*/
133+
export function createIntersectionObserver() {
134+
return new IntersectionObserver((entries) => {
135+
for (const current of entries) {
136+
if (current.isIntersecting && viewportTriggers.has(current.target)) {
137+
viewportTriggers.get(current.target)!.listener();
138+
}
139+
}
140+
});
127141
}
128142

129143
/**
130144
* Registers a viewport trigger.
131145
* @param trigger Element that is the trigger.
132146
* @param callback Callback to be invoked when the trigger comes into the viewport.
133-
* @param observer Observer interface which provides a way to observe changes to target element
147+
* @param observerFactoryFn Factory function which returns an IntersectionObserver
148+
* @return cleanup function which removes trigger Element from viewportTriggers map
149+
* and tells the intersection observer to stop observing trigger Element and set
150+
* intersectionObserver to null if there are no more Elements to observe
134151
*/
135152
export function onViewport(
136153
trigger: Element,
137154
callback: VoidFunction,
138-
observer: Observer,
155+
observerFactoryFn: () => IntersectionObserver,
139156
): VoidFunction {
140157
let entry = viewportTriggers.get(trigger);
141158

159+
intersectionObserver = intersectionObserver || observerFactoryFn();
160+
142161
if (!entry) {
143162
entry = new DeferEventEntry();
144-
observer.observe(trigger);
163+
intersectionObserver!.observe(trigger);
145164
viewportTriggers.set(trigger, entry);
146165
observedViewportElements++;
147166
}
148167

149168
entry.callbacks.add(callback);
150169

151170
return () => {
152-
// It's possible that a different cleanup callback fully removed this element already.
153171
if (!viewportTriggers.has(trigger)) {
154172
return;
155173
}
156174

157175
entry!.callbacks.delete(callback);
158176

159177
if (entry!.callbacks.size === 0) {
160-
observer.unobserve(trigger);
178+
intersectionObserver?.unobserve(trigger);
161179
viewportTriggers.delete(trigger);
162180
observedViewportElements--;
163181
}
164182

165183
if (observedViewportElements === 0) {
166-
observer.disconnect();
184+
intersectionObserver?.disconnect();
185+
intersectionObserver = null;
167186
}
168187
};
169188
}
170-
171-
172-
// function createIntersectionObserver(ngZone: NgZone | undefined): IntersectionObserver {
173-
// return new IntersectionObserver((entries) => {
174-
// for (const current of entries) {
175-
// // Only invoke the callbacks if the specific element is intersecting.
176-
// if (current.isIntersecting && viewportTriggers.has(current.target)) {
177-
// if (ngZone) {
178-
// ngZone!.run(viewportTriggers.get(current.target)!.listener);
179-
// } else {
180-
// viewportTriggers.get(current.target)!.listener();
181-
// }
182-
// }
183-
// }
184-
// })
185-
// }
186-
187-
// /**
188-
// * Registers a viewport trigger.
189-
// * @param trigger Element that is the trigger.
190-
// * @param callback Callback to be invoked when the trigger comes into the viewport.
191-
// * @param injector Injector that can be used by the trigger to resolve DI tokens.
192-
// */
193-
// export function onViewport(
194-
// trigger: Element,
195-
// callback: VoidFunction,
196-
// injector?: Injector,
197-
// ): VoidFunction {
198-
// const ngZone = injector?.get(NgZone);
199-
// let entry = viewportTriggers.get(trigger);
200-
201-
// if (!intersectionObserver) {
202-
// if (injector) {
203-
// intersectionObserver = ngZone!.runOutsideAngular(() => {
204-
// return createIntersectionObserver(ngZone);
205-
// });
206-
// } else {
207-
// intersectionObserver = createIntersectionObserver(ngZone);
208-
// }
209-
// }
210-
211-
// if (!entry) {
212-
// entry = new DeferEventEntry();
213-
// if (ngZone) {
214-
// ngZone.runOutsideAngular(() => intersectionObserver!.observe(trigger));
215-
// } else {
216-
// intersectionObserver!.observe(trigger);
217-
// }
218-
// viewportTriggers.set(trigger, entry);
219-
// observedViewportElements++;
220-
// }
221-
222-
// entry.callbacks.add(callback);
223-
224-
// return () => {
225-
// // It's possible that a different cleanup callback fully removed this element already.
226-
// if (!viewportTriggers.has(trigger)) {
227-
// return;
228-
// }
229-
230-
// entry!.callbacks.delete(callback);
231-
232-
// if (entry!.callbacks.size === 0) {
233-
// intersectionObserver?.unobserve(trigger);
234-
// viewportTriggers.delete(trigger);
235-
// observedViewportElements--;
236-
// }
237-
238-
// if (observedViewportElements === 0) {
239-
// intersectionObserver?.disconnect();
240-
// intersectionObserver = null;
241-
// }
242-
// };
243-
// }
244-

packages/core/src/defer/dom_triggers.ts

Lines changed: 7 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import {
2323
import {assertElement, assertEqual} from '../util/assert';
2424
import {NgZone} from '../zone';
2525
import {storeTriggerCleanupFn} from './cleanup';
26-
import {Observer, getViewportTriggers, onViewport} from '../../primitives/defer/src/triggers';
26+
import {onViewport, createIntersectionObserver} from '../../primitives/defer/src/triggers';
2727
import {
2828
DEFER_BLOCK_STATE,
2929
DeferBlockInternalState,
@@ -40,37 +40,12 @@ import {getLDeferBlockDetails} from './utils';
4040
* @param injector Injector that can be used by the trigger to resolve DI tokens.
4141
*/
4242
export function onViewportWrapper(trigger: Element, callback: VoidFunction, injector: Injector) {
43-
const angularInjectorObserver = new AngularIntersectionObserver(injector);
44-
return onViewport(trigger, callback, angularInjectorObserver);
45-
}
46-
47-
class AngularIntersectionObserver implements Observer{
48-
private intersectionObserver: IntersectionObserver;
49-
private ngZone: NgZone;
50-
constructor(injector: Injector) {
51-
this.ngZone = injector.get(NgZone);
52-
this.intersectionObserver = this.ngZone.runOutsideAngular(() => {
53-
return new IntersectionObserver((entries) => {
54-
for (const current of entries) {
55-
if (current.isIntersecting && getViewportTriggers().has(current.target)) {
56-
this.ngZone.run(getViewportTriggers().get(current.target)!.listener)
57-
}
58-
}
59-
})
60-
})
61-
}
62-
63-
observe(target: Element) {
64-
this.ngZone.runOutsideAngular(() => this.intersectionObserver.observe(target));
65-
}
66-
67-
unobserve(target: Element) {
68-
this.intersectionObserver.unobserve(target);
69-
}
70-
71-
disconnect() {
72-
this.intersectionObserver.disconnect();
73-
}
43+
const ngZone = injector.get(NgZone);
44+
return onViewport(
45+
trigger,
46+
() => ngZone.run(callback),
47+
() => ngZone.runOutsideAngular(() => createIntersectionObserver()),
48+
);
7449
}
7550

7651
/**

packages/core/src/defer/instructions.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ import {
2727
import {removeLViewOnDestroy, storeLViewOnDestroy} from '../render3/util/view_utils';
2828
import {performanceMarkFeature} from '../util/performance';
2929
import {invokeAllTriggerCleanupFns, storeTriggerCleanupFn} from './cleanup';
30-
//import {onHover, onInteraction, onViewport, registerDomTrigger} from './dom_triggers';
3130
import {onViewportWrapper, registerDomTrigger} from './dom_triggers';
3231
import {onHover, onInteraction} from '../../primitives/defer/src/triggers';
3332
import {onIdle} from './idle_scheduler';

packages/core/src/defer/triggering.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ import {
3636
invokeTriggerCleanupFns,
3737
storeTriggerCleanupFn,
3838
} from './cleanup';
39-
import {onViewport} from './dom_triggers';
39+
import {onViewportWrapper} from './dom_triggers';
4040
import {onIdle} from './idle_scheduler';
4141
import {
4242
DEFER_BLOCK_STATE,
@@ -701,7 +701,7 @@ function setViewportTriggers(injector: Injector, elementTriggers: ElementTrigger
701701
if (elementTriggers.length > 0) {
702702
const registry = injector.get(DEHYDRATED_BLOCK_REGISTRY);
703703
for (let elementTrigger of elementTriggers) {
704-
const cleanupFn = onViewport(
704+
const cleanupFn = onViewportWrapper(
705705
elementTrigger.el,
706706
() => triggerHydrationFromBlockName(injector, elementTrigger.blockName),
707707
injector,

packages/core/src/hydration/utils.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ import {
3636
import {IS_INCREMENTAL_HYDRATION_ENABLED, JSACTION_BLOCK_ELEMENT_MAP} from './tokens';
3737
import {RuntimeError, RuntimeErrorCode} from '../errors';
3838
import {DeferBlockTrigger, HydrateTriggerDetails} from '../defer/interfaces';
39-
import {hoverEventNames, interactionEventNames} from '../defer/dom_triggers';
39+
import {hoverEventNames, interactionEventNames} from '../../primitives/defer/src/triggers';
4040
import {DEHYDRATED_BLOCK_REGISTRY} from '../defer/registry';
4141
import {sharedMapFunction} from '../event_delegation_utils';
4242
import {isDetachedByI18n} from '../i18n/utils';

0 commit comments

Comments
 (0)