Removes the react-interactions project which is unused (#28799)
Removes the react-interactions project which is unused This project uses `unstable_createEventHandle` which is being removed from React in version 19
Josh Story committed
Apr 10, 2024 at 09:18 UTC
a8a83f7a5996b86f3901d5dc505b13506dd12caf
16 files changed
-1549
packages/react-interactions/README.md
deleted
-4
@@ -1,4 +0,0 @@
1
-# `react-interactions`
2
-
3
-This package is experimental. It is intended for use with the experimental React
4
-flags for internal testing.
\ No newline at end of file
packages/react-interactions/events/focus.js
deleted
-10
@@ -1,10 +0,0 @@
1
-/**
2
- * Copyright (c) Meta Platforms, Inc. and affiliates.
3
- *
4
- * This source code is licensed under the MIT license found in the
5
- * LICENSE file in the root directory of this source tree.
6
- *
7
- * @flow
8
- */
9
-
10
-export * from './src/dom/create-event-handle/Focus';
packages/react-interactions/events/src/dom/create-event-handle/Focus.js
deleted
-400
@@ -1,400 +0,0 @@
1
-/**
2
- * Copyright (c) Meta Platforms, Inc. and affiliates.
3
- *
4
- * This source code is licensed under the MIT license found in the
5
- * LICENSE file in the root directory of this source tree.
6
- *
7
- * @flow
8
- */
9
-
10
-import * as React from 'react';
11
-import useEvent from './useEvent';
12
-
13
-const {useCallback, useEffect, useLayoutEffect, useRef} = React;
14
-
15
-type FocusEvent = SyntheticEvent<EventTarget>;
16
-
17
-type UseFocusOptions = {
18
- disabled?: boolean,
19
- onBlur?: ?(FocusEvent) => void,
20
- onFocus?: ?(FocusEvent) => void,
21
- onFocusChange?: ?(boolean) => void,
22
- onFocusVisibleChange?: ?(boolean) => void,
23
-};
24
-
25
-type UseFocusWithinOptions = {
26
- disabled?: boolean,
27
- onAfterBlurWithin?: FocusEvent => void,
28
- onBeforeBlurWithin?: FocusEvent => void,
29
- onBlurWithin?: FocusEvent => void,
30
- onFocusWithin?: FocusEvent => void,
31
- onFocusWithinChange?: boolean => void,
32
- onFocusWithinVisibleChange?: boolean => void,
33
-};
34
-
35
-const isMac =
36
- typeof window !== 'undefined' && window.navigator != null
37
- ? /^Mac/.test(window.navigator.platform)
38
- : false;
39
-
40
-const hasPointerEvents =
41
- typeof window !== 'undefined' && window.PointerEvent != null;
42
-
43
-const globalFocusVisibleEvents = hasPointerEvents
44
- ? ['keydown', 'pointermove', 'pointerdown', 'pointerup']
45
- : [
46
- 'keydown',
47
- 'mousedown',
48
- 'mousemove',
49
- 'mouseup',
50
- 'touchmove',
51
- 'touchstart',
52
- 'touchend',
53
- ];
54
-
55
-// Global state for tracking focus visible and emulation of mouse
56
-let isGlobalFocusVisible = true;
57
-let hasTrackedGlobalFocusVisible = false;
58
-
59
-function trackGlobalFocusVisible() {
60
- globalFocusVisibleEvents.forEach(type => {
61
- window.addEventListener(type, handleGlobalFocusVisibleEvent, true);
62
- });
63
-}
64
-
65
-function isValidKey(nativeEvent: KeyboardEvent): boolean {
66
- const {metaKey, altKey, ctrlKey} = nativeEvent;
67
- return !(metaKey || (!isMac && altKey) || ctrlKey);
68
-}
69
-
70
-function isTextInput(nativeEvent: KeyboardEvent): boolean {
71
- const {key, target} = nativeEvent;
72
- if (key === 'Tab' || key === 'Escape') {
73
- return false;
74
- }
75
- const {isContentEditable, tagName} = (target: any);
76
- return tagName === 'INPUT' || tagName === 'TEXTAREA' || isContentEditable;
77
-}
78
-
79
-function handleGlobalFocusVisibleEvent(
80
- nativeEvent: MouseEvent | TouchEvent | KeyboardEvent,
81
-): void {
82
- if (nativeEvent.type === 'keydown') {
83
- if (isValidKey(((nativeEvent: any): KeyboardEvent))) {
84
- isGlobalFocusVisible = true;
85
- }
86
- } else {
87
- const nodeName = (nativeEvent.target: any).nodeName;
88
- // Safari calls mousemove/pointermove events when you tab out of the active
89
- // Safari frame.
90
- if (nodeName === 'HTML') {
91
- return;
92
- }
93
- // Handle all the other mouse/touch/pointer events
94
- isGlobalFocusVisible = false;
95
- }
96
-}
97
-
98
-function handleFocusVisibleTargetEvents(
99
- event: SyntheticEvent<EventTarget>,
100
- callback: boolean => void,
101
-): void {
102
- if (event.type === 'keydown') {
103
- const {nativeEvent} = (event: any);
104
- if (isValidKey(nativeEvent) && !isTextInput(nativeEvent)) {
105
- callback(true);
106
- }
107
- } else {
108
- callback(false);
109
- }
110
-}
111
-
112
-function isRelatedTargetWithin(
113
- focusWithinTarget: Object,
114
- relatedTarget: null | EventTarget,
115
-): boolean {
116
- if (relatedTarget == null) {
117
- return false;
118
- }
119
- // As the focusWithinTarget can be a Scope Instance (experimental API),
120
- // we need to use the containsNode() method. Otherwise, focusWithinTarget
121
- // must be a Node, which means we can use the contains() method.
122
- return typeof focusWithinTarget.containsNode === 'function'
123
- ? focusWithinTarget.containsNode(relatedTarget)
124
- : focusWithinTarget.contains(relatedTarget);
125
-}
126
-
127
-function setFocusVisibleListeners(
128
- // $FlowFixMe[missing-local-annot]
129
- focusVisibleHandles,
130
- focusTarget: EventTarget,
131
- callback: boolean => void,
132
-) {
133
- focusVisibleHandles.forEach(focusVisibleHandle => {
134
- focusVisibleHandle.setListener(focusTarget, event =>
135
- handleFocusVisibleTargetEvents(event, callback),
136
- );
137
- });
138
-}
139
-
140
-function useFocusVisibleInputHandles() {
141
- return [
142
- useEvent('mousedown'),
143
- useEvent(hasPointerEvents ? 'pointerdown' : 'touchstart'),
144
- useEvent('keydown'),
145
- ];
146
-}
147
-
148
-function useFocusLifecycles() {
149
- useEffect(() => {
150
- if (!hasTrackedGlobalFocusVisible) {
151
- hasTrackedGlobalFocusVisible = true;
152
- trackGlobalFocusVisible();
153
- }
154
- }, []);
155
-}
156
-
157
-export function useFocus(
158
- focusTargetRef: {current: null | Node},
159
- {
160
- disabled,
161
- onBlur,
162
- onFocus,
163
- onFocusChange,
164
- onFocusVisibleChange,
165
- }: UseFocusOptions,
166
-): void {
167
- // Setup controlled state for this useFocus hook
168
- const stateRef = useRef<null | {
169
- isFocused: boolean,
170
- isFocusVisible: boolean,
171
- }>({isFocused: false, isFocusVisible: false});
172
- const focusHandle = useEvent('focusin');
173
- const blurHandle = useEvent('focusout');
174
- const focusVisibleHandles = useFocusVisibleInputHandles();
175
-
176
- useLayoutEffect(() => {
177
- const focusTarget = focusTargetRef.current;
178
- const state = stateRef.current;
179
-
180
- if (focusTarget !== null && state !== null && focusTarget.nodeType === 1) {
181
- // Handle focus visible
182
- setFocusVisibleListeners(
183
- focusVisibleHandles,
184
- focusTarget,
185
- isFocusVisible => {
186
- if (state.isFocused && state.isFocusVisible !== isFocusVisible) {
187
- state.isFocusVisible = isFocusVisible;
188
- if (onFocusVisibleChange) {
189
- onFocusVisibleChange(isFocusVisible);
190
- }
191
- }
192
- },
193
- );
194
-
195
- // Handle focus
196
- focusHandle.setListener(focusTarget, (event: FocusEvent) => {
197
- if (disabled === true) {
198
- return;
199
- }
200
- if (!state.isFocused && focusTarget === event.target) {
201
- state.isFocused = true;
202
- state.isFocusVisible = isGlobalFocusVisible;
203
- if (onFocus) {
204
- onFocus(event);
205
- }
206
- if (onFocusChange) {
207
- onFocusChange(true);
208
- }
209
- if (state.isFocusVisible && onFocusVisibleChange) {
210
- onFocusVisibleChange(true);
211
- }
212
- }
213
- });
214
-
215
- // Handle blur
216
- blurHandle.setListener(focusTarget, (event: FocusEvent) => {
217
- if (disabled === true) {
218
- return;
219
- }
220
- if (state.isFocused) {
221
- state.isFocused = false;
222
- state.isFocusVisible = isGlobalFocusVisible;
223
- if (onBlur) {
224
- onBlur(event);
225
- }
226
- if (onFocusChange) {
227
- onFocusChange(false);
228
- }
229
- if (state.isFocusVisible && onFocusVisibleChange) {
230
- onFocusVisibleChange(false);
231
- }
232
- }
233
- });
234
- }
235
- }, [
236
- blurHandle,
237
- disabled,
238
- focusHandle,
239
- focusTargetRef,
240
- focusVisibleHandles,
241
- onBlur,
242
- onFocus,
243
- onFocusChange,
244
- onFocusVisibleChange,
245
- ]);
246
-
247
- // Mount/Unmount logic
248
- useFocusLifecycles();
249
-}
250
-
251
-export function useFocusWithin<T>(
252
- focusWithinTargetRef:
253
- | {current: null | T}
254
- | ((focusWithinTarget: null | T) => void),
255
- {
256
- disabled,
257
- onAfterBlurWithin,
258
- onBeforeBlurWithin,
259
- onBlurWithin,
260
- onFocusWithin,
261
- onFocusWithinChange,
262
- onFocusWithinVisibleChange,
263
- }: UseFocusWithinOptions,
264
-): (focusWithinTarget: null | T) => void {
265
- // Setup controlled state for this useFocus hook
266
- const stateRef = useRef<null | {
267
- isFocused: boolean,
268
- isFocusVisible: boolean,
269
- }>({isFocused: false, isFocusVisible: false});
270
- const focusHandle = useEvent('focusin');
271
- const blurHandle = useEvent('focusout');
272
- const afterBlurHandle = useEvent('afterblur');
273
- const beforeBlurHandle = useEvent('beforeblur');
274
- const focusVisibleHandles = useFocusVisibleInputHandles();
275
-
276
- const useFocusWithinRef = useCallback(
277
- (focusWithinTarget: null | T) => {
278
- // Handle the incoming focusTargetRef. It can be either a function ref
279
- // or an object ref.
280
- if (typeof focusWithinTargetRef === 'function') {
281
- focusWithinTargetRef(focusWithinTarget);
282
- } else {
283
- focusWithinTargetRef.current = focusWithinTarget;
284
- }
285
- const state = stateRef.current;
286
-
287
- if (focusWithinTarget !== null && state !== null) {
288
- // Handle focus visible
289
- setFocusVisibleListeners(
290
- focusVisibleHandles,
291
- // $FlowFixMe[incompatible-call] focusWithinTarget is not null here
292
- focusWithinTarget,
293
- isFocusVisible => {
294
- if (state.isFocused && state.isFocusVisible !== isFocusVisible) {
295
- state.isFocusVisible = isFocusVisible;
296
- if (onFocusWithinVisibleChange) {
297
- onFocusWithinVisibleChange(isFocusVisible);
298
- }
299
- }
300
- },
301
- );
302
-
303
- // Handle focus
304
- // $FlowFixMe[incompatible-call] focusWithinTarget is not null here
305
- focusHandle.setListener(focusWithinTarget, (event: FocusEvent) => {
306
- if (disabled) {
307
- return;
308
- }
309
- if (!state.isFocused) {
310
- state.isFocused = true;
311
- state.isFocusVisible = isGlobalFocusVisible;
312
- if (onFocusWithinChange) {
313
- onFocusWithinChange(true);
314
- }
315
- if (state.isFocusVisible && onFocusWithinVisibleChange) {
316
- onFocusWithinVisibleChange(true);
317
- }
318
- }
319
- if (!state.isFocusVisible && isGlobalFocusVisible) {
320
- state.isFocusVisible = isGlobalFocusVisible;
321
- if (onFocusWithinVisibleChange) {
322
- onFocusWithinVisibleChange(true);
323
- }
324
- }
325
- if (onFocusWithin) {
326
- onFocusWithin(event);
327
- }
328
- });
329
-
330
- // Handle blur
331
- // $FlowFixMe[incompatible-call] focusWithinTarget is not null here
332
- blurHandle.setListener(focusWithinTarget, (event: FocusEvent) => {
333
- if (disabled) {
334
- return;
335
- }
336
- const {relatedTarget} = (event.nativeEvent: any);
337
-
338
- if (
339
- state.isFocused &&
340
- !isRelatedTargetWithin(focusWithinTarget, relatedTarget)
341
- ) {
342
- state.isFocused = false;
343
- if (onFocusWithinChange) {
344
- onFocusWithinChange(false);
345
- }
346
- if (state.isFocusVisible && onFocusWithinVisibleChange) {
347
- onFocusWithinVisibleChange(false);
348
- }
349
- if (onBlurWithin) {
350
- onBlurWithin(event);
351
- }
352
- }
353
- });
354
-
355
- // Handle before blur. This is a special
356
- // React provided event.
357
- // $FlowFixMe[incompatible-call] focusWithinTarget is not null here
358
- beforeBlurHandle.setListener(focusWithinTarget, (event: FocusEvent) => {
359
- if (disabled) {
360
- return;
361
- }
362
- if (onBeforeBlurWithin) {
363
- onBeforeBlurWithin(event);
364
- // Add an "afterblur" listener on document. This is a special
365
- // React provided event.
366
- afterBlurHandle.setListener(
367
- document,
368
- (afterBlurEvent: FocusEvent) => {
369
- if (onAfterBlurWithin) {
370
- onAfterBlurWithin(afterBlurEvent);
371
- }
372
- // Clear listener on document
373
- afterBlurHandle.setListener(document, null);
374
- },
375
- );
376
- }
377
- });
378
- }
379
- },
380
- [
381
- afterBlurHandle,
382
- beforeBlurHandle,
383
- blurHandle,
384
- disabled,
385
- focusHandle,
386
- focusWithinTargetRef,
387
- onAfterBlurWithin,
388
- onBeforeBlurWithin,
389
- onBlurWithin,
390
- onFocusWithin,
391
- onFocusWithinChange,
392
- onFocusWithinVisibleChange,
393
- ],
394
- );
395
-
396
- // Mount/Unmount logic
397
- useFocusLifecycles();
398
-
399
- return useFocusWithinRef;
400
-}
packages/react-interactions/events/src/dom/create-event-handle/__tests__/useFocus-test.internal.js
deleted
-335
@@ -1,335 +0,0 @@
1
-/**
2
- * Copyright (c) Meta Platforms, Inc. and affiliates.
3
- *
4
- * This source code is licensed under the MIT license found in the
5
- * LICENSE file in the root directory of this source tree.
6
- *
7
- * @emails react-core
8
- */
9
-
10
-'use strict';
11
-
12
-import {createEventTarget, setPointerEvent} from 'dom-event-testing-library';
13
-
14
-let React;
15
-let ReactFeatureFlags;
16
-let ReactDOMClient;
17
-let useFocus;
18
-let act;
19
-
20
-function initializeModules(hasPointerEvents) {
21
- setPointerEvent(hasPointerEvents);
22
- jest.resetModules();
23
- ReactFeatureFlags = require('shared/ReactFeatureFlags');
24
- ReactFeatureFlags.enableCreateEventHandleAPI = true;
25
- React = require('react');
26
- ReactDOMClient = require('react-dom/client');
27
- act = require('internal-test-utils').act;
28
- // TODO: This import throws outside of experimental mode. Figure out better
29
- // strategy for gated imports.
30
- if (__EXPERIMENTAL__ || global.__WWW__) {
31
- useFocus = require('react-interactions/events/focus').useFocus;
32
- }
33
-}
34
-
35
-const forcePointerEvents = true;
36
-const table = [[forcePointerEvents], [!forcePointerEvents]];
37
-
38
-describe.each(table)(`useFocus hasPointerEvents=%s`, hasPointerEvents => {
39
- let container;
40
-
41
- beforeEach(() => {
42
- initializeModules(hasPointerEvents);
43
- container = document.createElement('div');
44
- document.body.appendChild(container);
45
- });
46
-
47
- afterEach(() => {
48
- document.body.removeChild(container);
49
- container = null;
50
- });
51
-
52
- describe('disabled', () => {
53
- let onBlur, onFocus, ref;
54
-
55
- const componentInit = async () => {
56
- onBlur = jest.fn();
57
- onFocus = jest.fn();
58
- ref = React.createRef();
59
- const Component = () => {
60
- useFocus(ref, {
61
- disabled: true,
62
- onBlur,
63
- onFocus,
64
- });
65
- return <div ref={ref} />;
66
- };
67
- const root = ReactDOMClient.createRoot(container);
68
- await act(() => {
69
- root.render(<Component />);
70
- });
71
- };
72
-
73
- // @gate www
74
- it('does not call callbacks', async () => {
75
- await componentInit();
76
- const target = createEventTarget(ref.current);
77
- target.focus();
78
- target.blur();
79
- expect(onFocus).not.toBeCalled();
80
- expect(onBlur).not.toBeCalled();
81
- });
82
- });
83
-
84
- describe('onBlur', () => {
85
- let onBlur, ref;
86
-
87
- const componentInit = async () => {
88
- onBlur = jest.fn();
89
- ref = React.createRef();
90
- const Component = () => {
91
- useFocus(ref, {
92
- onBlur,
93
- });
94
- return <div ref={ref} />;
95
- };
96
- const root = ReactDOMClient.createRoot(container);
97
- await act(() => {
98
- root.render(<Component />);
99
- });
100
- };
101
-
102
- // @gate www
103
- it('is called after "blur" event', async () => {
104
- await componentInit();
105
- const target = createEventTarget(ref.current);
106
- target.focus();
107
- target.blur();
108
- expect(onBlur).toHaveBeenCalledTimes(1);
109
- });
110
- });
111
-
112
- describe('onFocus', () => {
113
- let onFocus, ref, innerRef;
114
-
115
- const componentInit = async () => {
116
- onFocus = jest.fn();
117
- ref = React.createRef();
118
- innerRef = React.createRef();
119
- const Component = () => {
120
- useFocus(ref, {
121
- onFocus,
122
- });
123
- return (
124
- <div ref={ref}>
125
- <a ref={innerRef} />
126
- </div>
127
- );
128
- };
129
- const root = ReactDOMClient.createRoot(container);
130
- await act(() => {
131
- root.render(<Component />);
132
- });
133
- };
134
-
135
- // @gate www
136
- it('is called after "focus" event', async () => {
137
- await componentInit();
138
- const target = createEventTarget(ref.current);
139
- target.focus();
140
- expect(onFocus).toHaveBeenCalledTimes(1);
141
- });
142
-
143
- // @gate www
144
- it('is not called if descendants of target receive focus', async () => {
145
- await componentInit();
146
- const target = createEventTarget(innerRef.current);
147
- target.focus();
148
- expect(onFocus).not.toBeCalled();
149
- });
150
- });
151
-
152
- describe('onFocusChange', () => {
153
- let onFocusChange, ref, innerRef;
154
-
155
- const componentInit = async () => {
156
- onFocusChange = jest.fn();
157
- ref = React.createRef();
158
- innerRef = React.createRef();
159
- const Component = () => {
160
- useFocus(ref, {
161
- onFocusChange,
162
- });
163
- return (
164
- <div ref={ref}>
165
- <div ref={innerRef} />
166
- </div>
167
- );
168
- };
169
- const root = ReactDOMClient.createRoot(container);
170
- await act(() => {
171
- root.render(<Component />);
172
- });
173
- };
174
-
175
- // @gate www
176
- it('is called after "blur" and "focus" events', async () => {
177
- await componentInit();
178
- const target = createEventTarget(ref.current);
179
- target.focus();
180
- expect(onFocusChange).toHaveBeenCalledTimes(1);
181
- expect(onFocusChange).toHaveBeenCalledWith(true);
182
- target.blur();
183
- expect(onFocusChange).toHaveBeenCalledTimes(2);
184
- expect(onFocusChange).toHaveBeenCalledWith(false);
185
- });
186
-
187
- // @gate www
188
- it('is not called after "blur" and "focus" events on descendants', async () => {
189
- await componentInit();
190
- const target = createEventTarget(innerRef.current);
191
- target.focus();
192
- expect(onFocusChange).toHaveBeenCalledTimes(0);
193
- target.blur();
194
- expect(onFocusChange).toHaveBeenCalledTimes(0);
195
- });
196
- });
197
-
198
- describe('onFocusVisibleChange', () => {
199
- let onFocusVisibleChange, ref, innerRef;
200
-
201
- const componentInit = async () => {
202
- onFocusVisibleChange = jest.fn();
203
- ref = React.createRef();
204
- innerRef = React.createRef();
205
- const Component = () => {
206
- useFocus(ref, {
207
- onFocusVisibleChange,
208
- });
209
- return (
210
- <div ref={ref}>
211
- <div ref={innerRef} />
212
- </div>
213
- );
214
- };
215
- const root = ReactDOMClient.createRoot(container);
216
- await act(() => {
217
- root.render(<Component />);
218
- });
219
- };
220
-
221
- // @gate www
222
- it('is called after "focus" and "blur" if keyboard navigation is active', async () => {
223
- await componentInit();
224
- const target = createEventTarget(ref.current);
225
- const containerTarget = createEventTarget(container);
226
- // use keyboard first
227
- containerTarget.keydown({key: 'Tab'});
228
- target.focus();
229
- expect(onFocusVisibleChange).toHaveBeenCalledTimes(1);
230
- expect(onFocusVisibleChange).toHaveBeenCalledWith(true);
231
- target.blur({relatedTarget: container});
232
- expect(onFocusVisibleChange).toHaveBeenCalledTimes(2);
233
- expect(onFocusVisibleChange).toHaveBeenCalledWith(false);
234
- });
235
-
236
- // @gate www
237
- it('is called if non-keyboard event is dispatched on target previously focused with keyboard', async () => {
238
- await componentInit();
239
- const target = createEventTarget(ref.current);
240
- const containerTarget = createEventTarget(container);
241
- // use keyboard first
242
- containerTarget.keydown({key: 'Tab'});
243
- target.focus();
244
- expect(onFocusVisibleChange).toHaveBeenCalledTimes(1);
245
- expect(onFocusVisibleChange).toHaveBeenCalledWith(true);
246
- // then use pointer on the target, focus should no longer be visible
247
- target.pointerdown();
248
- expect(onFocusVisibleChange).toHaveBeenCalledTimes(2);
249
- expect(onFocusVisibleChange).toHaveBeenCalledWith(false);
250
- // onFocusVisibleChange should not be called again
251
- target.blur({relatedTarget: container});
252
- expect(onFocusVisibleChange).toHaveBeenCalledTimes(2);
253
- });
254
-
255
- // @gate www
256
- it('is not called after "focus" and "blur" events without keyboard', async () => {
257
- await componentInit();
258
- const target = createEventTarget(ref.current);
259
- const containerTarget = createEventTarget(container);
260
- target.pointerdown();
261
- target.pointerup();
262
- containerTarget.pointerdown();
263
- target.blur({relatedTarget: container});
264
- expect(onFocusVisibleChange).toHaveBeenCalledTimes(0);
265
- });
266
-
267
- // @gate www
268
- it('is not called after "blur" and "focus" events on descendants', async () => {
269
- await componentInit();
270
- const innerTarget = createEventTarget(innerRef.current);
271
- const containerTarget = createEventTarget(container);
272
- containerTarget.keydown({key: 'Tab'});
273
- innerTarget.focus();
274
- expect(onFocusVisibleChange).toHaveBeenCalledTimes(0);
275
- innerTarget.blur({relatedTarget: container});
276
- expect(onFocusVisibleChange).toHaveBeenCalledTimes(0);
277
- });
278
- });
279
-
280
- describe('nested Focus components', () => {
281
- // @gate www
282
- it('propagates events in the correct order', async () => {
283
- const events = [];
284
- const innerRef = React.createRef();
285
- const outerRef = React.createRef();
286
- const createEventHandler = msg => () => {
287
- events.push(msg);
288
- };
289
-
290
- const Inner = () => {
291
- useFocus(innerRef, {
292
- onBlur: createEventHandler('inner: onBlur'),
293
- onFocus: createEventHandler('inner: onFocus'),
294
- onFocusChange: createEventHandler('inner: onFocusChange'),
295
- });
296
- return <div ref={innerRef} />;
297
- };
298
-
299
- const Outer = () => {
300
- useFocus(outerRef, {
301
- onBlur: createEventHandler('outer: onBlur'),
302
- onFocus: createEventHandler('outer: onFocus'),
303
- onFocusChange: createEventHandler('outer: onFocusChange'),
304
- });
305
- return (
306
- <div ref={outerRef}>
307
- <Inner />
308
- </div>
309
- );
310
- };
311
-
312
- const root = ReactDOMClient.createRoot(container);
313
- await act(() => {
314
- root.render(<Outer />);
315
- });
316
- const innerTarget = createEventTarget(innerRef.current);
317
- const outerTarget = createEventTarget(outerRef.current);
318
-
319
- outerTarget.focus();
320
- outerTarget.blur();
321
- innerTarget.focus();
322
- innerTarget.blur();
323
- expect(events).toEqual([
324
- 'outer: onFocus',
325
- 'outer: onFocusChange',
326
- 'outer: onBlur',
327
- 'outer: onFocusChange',
328
- 'inner: onFocus',
329
- 'inner: onFocusChange',
330
- 'inner: onBlur',
331
- 'inner: onFocusChange',
332
- ]);
333
- });
334
- });
335
-});
packages/react-interactions/events/src/dom/create-event-handle/__tests__/useFocusWithin-test.internal.js
deleted
-626
@@ -1,626 +0,0 @@
1
-/**
2
- * Copyright (c) Meta Platforms, Inc. and affiliates.
3
- *
4
- * This source code is licensed under the MIT license found in the
5
- * LICENSE file in the root directory of this source tree.
6
- *
7
- * @emails react-core
8
- */
9
-
10
-'use strict';
11
-
12
-import {createEventTarget, setPointerEvent} from 'dom-event-testing-library';
13
-
14
-let React;
15
-let ReactFeatureFlags;
16
-let ReactDOMClient;
17
-let useFocusWithin;
18
-let act;
19
-
20
-function initializeModules(hasPointerEvents) {
21
- setPointerEvent(hasPointerEvents);
22
- jest.resetModules();
23
- ReactFeatureFlags = require('shared/ReactFeatureFlags');
24
- ReactFeatureFlags.enableScopeAPI = true;
25
- ReactFeatureFlags.enableCreateEventHandleAPI = true;
26
- React = require('react');
27
- ReactDOMClient = require('react-dom/client');
28
- act = require('internal-test-utils').act;
29
-
30
- // TODO: This import throws outside of experimental mode. Figure out better
31
- // strategy for gated imports.
32
- if (__EXPERIMENTAL__ || global.__WWW__) {
33
- useFocusWithin = require('react-interactions/events/focus').useFocusWithin;
34
- }
35
-}
36
-
37
-const forcePointerEvents = true;
38
-const table = [[forcePointerEvents], [!forcePointerEvents]];
39
-
40
-describe.each(table)(`useFocus`, hasPointerEvents => {
41
- let container;
42
- let container2;
43
- let root;
44
-
45
- beforeEach(() => {
46
- initializeModules(hasPointerEvents);
47
- container = document.createElement('div');
48
- document.body.appendChild(container);
49
- container2 = document.createElement('div');
50
- document.body.appendChild(container2);
51
- root = ReactDOMClient.createRoot(container);
52
- });
53
-
54
- afterEach(async () => {
55
- await act(() => {
56
- root.render(null);
57
- });
58
-
59
- document.body.removeChild(container);
60
- document.body.removeChild(container2);
61
- container = null;
62
- container2 = null;
63
- });
64
-
65
- describe('disabled', () => {
66
- let onFocusWithinChange, onFocusWithinVisibleChange, ref;
67
-
68
- const componentInit = async () => {
69
- onFocusWithinChange = jest.fn();
70
- onFocusWithinVisibleChange = jest.fn();
71
- ref = React.createRef();
72
- const Component = () => {
73
- const focusWithinRef = useFocusWithin(ref, {
74
- disabled: true,
75
- onFocusWithinChange,
76
- onFocusWithinVisibleChange,
77
- });
78
- return <div ref={focusWithinRef} />;
79
- };
80
- await act(() => {
81
- root.render(<Component />);
82
- });
83
- };
84
-
85
- // @gate www
86
- it('prevents custom events being dispatched', async () => {
87
- await componentInit();
88
- const target = createEventTarget(ref.current);
89
- target.focus();
90
- target.blur();
91
- expect(onFocusWithinChange).not.toBeCalled();
92
- expect(onFocusWithinVisibleChange).not.toBeCalled();
93
- });
94
- });
95
-
96
- describe('onFocusWithinChange', () => {
97
- let onFocusWithinChange, ref, innerRef, innerRef2;
98
-
99
- const Component = ({show}) => {
100
- const focusWithinRef = useFocusWithin(ref, {
101
- onFocusWithinChange,
102
- });
103
- return (
104
- <div ref={focusWithinRef}>
105
- {show && <input ref={innerRef} />}
106
- <div ref={innerRef2} />
107
- </div>
108
- );
109
- };
110
-
111
- const componentInit = async () => {
112
- onFocusWithinChange = jest.fn();
113
- ref = React.createRef();
114
- innerRef = React.createRef();
115
- innerRef2 = React.createRef();
116
- await act(() => {
117
- root.render(<Component show={true} />);
118
- });
119
- };
120
-
121
- // @gate www
122
- it('is called after "blur" and "focus" events on focus target', async () => {
123
- await componentInit();
124
- const target = createEventTarget(ref.current);
125
- target.focus();
126
- expect(onFocusWithinChange).toHaveBeenCalledTimes(1);
127
- expect(onFocusWithinChange).toHaveBeenCalledWith(true);
128
- target.blur({relatedTarget: container});
129
- expect(onFocusWithinChange).toHaveBeenCalledTimes(2);
130
- expect(onFocusWithinChange).toHaveBeenCalledWith(false);
131
- });
132
-
133
- // @gate www
134
- it('is called after "blur" and "focus" events on descendants', async () => {
135
- await componentInit();
136
- const target = createEventTarget(innerRef.current);
137
- target.focus();
138
- expect(onFocusWithinChange).toHaveBeenCalledTimes(1);
139
- expect(onFocusWithinChange).toHaveBeenCalledWith(true);
140
- target.blur({relatedTarget: container});
141
- expect(onFocusWithinChange).toHaveBeenCalledTimes(2);
142
- expect(onFocusWithinChange).toHaveBeenCalledWith(false);
143
- });
144
-
145
- // @gate www
146
- it('is only called once when focus moves within and outside the subtree', async () => {
147
- await componentInit();
148
- const node = ref.current;
149
- const innerNode1 = innerRef.current;
150
- const innerNode2 = innerRef.current;
151
- const target = createEventTarget(node);
152
- const innerTarget1 = createEventTarget(innerNode1);
153
- const innerTarget2 = createEventTarget(innerNode2);
154
-
155
- // focus shifts into subtree
156
- innerTarget1.focus();
157
- expect(onFocusWithinChange).toHaveBeenCalledTimes(1);
158
- expect(onFocusWithinChange).toHaveBeenCalledWith(true);
159
- // focus moves around subtree
160
- innerTarget1.blur({relatedTarget: innerNode2});
161
- innerTarget2.focus();
162
- innerTarget2.blur({relatedTarget: node});
163
- target.focus();
164
- target.blur({relatedTarget: innerNode1});
165
- expect(onFocusWithinChange).toHaveBeenCalledTimes(1);
166
- // focus shifts outside subtree
167
- innerTarget1.blur({relatedTarget: container});
168
- expect(onFocusWithinChange).toHaveBeenCalledTimes(2);
169
- expect(onFocusWithinChange).toHaveBeenCalledWith(false);
170
- });
171
- });
172
-
173
- describe('onFocusWithinVisibleChange', () => {
174
- let onFocusWithinVisibleChange, ref, innerRef, innerRef2;
175
-
176
- const Component = ({show}) => {
177
- const focusWithinRef = useFocusWithin(ref, {
178
- onFocusWithinVisibleChange,
179
- });
180
- return (
181
- <div ref={focusWithinRef}>
182
- {show && <input ref={innerRef} />}
183
- <div ref={innerRef2} />
184
- </div>
185
- );
186
- };
187
-
188
- const componentInit = async () => {
189
- onFocusWithinVisibleChange = jest.fn();
190
- ref = React.createRef();
191
- innerRef = React.createRef();
192
- innerRef2 = React.createRef();
193
- await act(() => {
194
- root.render(<Component show={true} />);
195
- });
196
- };
197
-
198
- // @gate www
199
- it('is called after "focus" and "blur" on focus target if keyboard was used', async () => {
200
- await componentInit();
201
- const target = createEventTarget(ref.current);
202
- const containerTarget = createEventTarget(container);
203
- // use keyboard first
204
- containerTarget.keydown({key: 'Tab'});
205
- target.focus();
206
- expect(onFocusWithinVisibleChange).toHaveBeenCalledTimes(1);
207
- expect(onFocusWithinVisibleChange).toHaveBeenCalledWith(true);
208
- target.blur({relatedTarget: container});
209
- expect(onFocusWithinVisibleChange).toHaveBeenCalledTimes(2);
210
- expect(onFocusWithinVisibleChange).toHaveBeenCalledWith(false);
211
- });
212
-
213
- // @gate www
214
- it('is called after "focus" and "blur" on descendants if keyboard was used', async () => {
215
- await componentInit();
216
- const innerTarget = createEventTarget(innerRef.current);
217
- const containerTarget = createEventTarget(container);
218
- // use keyboard first
219
- containerTarget.keydown({key: 'Tab'});
220
- innerTarget.focus();
221
- expect(onFocusWithinVisibleChange).toHaveBeenCalledTimes(1);
222
- expect(onFocusWithinVisibleChange).toHaveBeenCalledWith(true);
223
- innerTarget.blur({relatedTarget: container});
224
- expect(onFocusWithinVisibleChange).toHaveBeenCalledTimes(2);
225
- expect(onFocusWithinVisibleChange).toHaveBeenCalledWith(false);
226
- });
227
-
228
- // @gate www
229
- it('is called if non-keyboard event is dispatched on target previously focused with keyboard', async () => {
230
- await componentInit();
231
- const node = ref.current;
232
- const innerNode1 = innerRef.current;
233
- const innerNode2 = innerRef2.current;
234
-
235
- const target = createEventTarget(node);
236
- const innerTarget1 = createEventTarget(innerNode1);
237
- const innerTarget2 = createEventTarget(innerNode2);
238
- // use keyboard first
239
- target.focus();
240
- target.keydown({key: 'Tab'});
241
- target.blur({relatedTarget: innerNode1});
242
- innerTarget1.focus();
243
- expect(onFocusWithinVisibleChange).toHaveBeenCalledTimes(1);
244
- expect(onFocusWithinVisibleChange).toHaveBeenCalledWith(true);
245
- // then use pointer on the next target, focus should no longer be visible
246
- innerTarget2.pointerdown();
247
- innerTarget1.blur({relatedTarget: innerNode2});
248
- innerTarget2.focus();
249
- expect(onFocusWithinVisibleChange).toHaveBeenCalledTimes(2);
250
- expect(onFocusWithinVisibleChange).toHaveBeenCalledWith(false);
251
- // then use keyboard again
252
- innerTarget2.keydown({key: 'Tab', shiftKey: true});
253
- innerTarget2.blur({relatedTarget: innerNode1});
254
- innerTarget1.focus();
255
- expect(onFocusWithinVisibleChange).toHaveBeenCalledTimes(3);
256
- expect(onFocusWithinVisibleChange).toHaveBeenCalledWith(true);
257
- // then use pointer on the target, focus should no longer be visible
258
- innerTarget1.pointerdown();
259
- expect(onFocusWithinVisibleChange).toHaveBeenCalledTimes(4);
260
- expect(onFocusWithinVisibleChange).toHaveBeenCalledWith(false);
261
- // onFocusVisibleChange should not be called again
262
- innerTarget1.blur({relatedTarget: container});
263
- expect(onFocusWithinVisibleChange).toHaveBeenCalledTimes(4);
264
- });
265
-
266
- // @gate www
267
- it('is not called after "focus" and "blur" events without keyboard', async () => {
268
- await componentInit();
269
- const innerTarget = createEventTarget(innerRef.current);
270
- innerTarget.pointerdown();
271
- innerTarget.pointerup();
272
- innerTarget.blur({relatedTarget: container});
273
- expect(onFocusWithinVisibleChange).toHaveBeenCalledTimes(0);
274
- });
275
-
276
- // @gate www
277
- it('is only called once when focus moves within and outside the subtree', async () => {
278
- await componentInit();
279
- const node = ref.current;
280
- const innerNode1 = innerRef.current;
281
- const innerNode2 = innerRef2.current;
282
- const target = createEventTarget(node);
283
- const innerTarget1 = createEventTarget(innerNode1);
284
- const innerTarget2 = createEventTarget(innerNode2);
285
-
286
- // focus shifts into subtree
287
- innerTarget1.focus();
288
- expect(onFocusWithinVisibleChange).toHaveBeenCalledTimes(1);
289
- expect(onFocusWithinVisibleChange).toHaveBeenCalledWith(true);
290
- // focus moves around subtree
291
- innerTarget1.blur({relatedTarget: innerNode2});
292
- innerTarget2.focus();
293
- innerTarget2.blur({relatedTarget: node});
294
- target.focus();
295
- target.blur({relatedTarget: innerNode1});
296
- expect(onFocusWithinVisibleChange).toHaveBeenCalledTimes(1);
297
- // focus shifts outside subtree
298
- innerTarget1.blur({relatedTarget: container});
299
- expect(onFocusWithinVisibleChange).toHaveBeenCalledTimes(2);
300
- expect(onFocusWithinVisibleChange).toHaveBeenCalledWith(false);
301
- });
302
- });
303
-
304
- // @gate www
305
- it('should correctly handle focus visibility when typing into an input', async () => {
306
- const onFocusWithinVisibleChange = jest.fn();
307
- const ref = React.createRef();
308
- const inputRef = React.createRef();
309
- const Component = () => {
310
- const focusWithinRef = useFocusWithin(ref, {
311
- onFocusWithinVisibleChange,
312
- });
313
- return (
314
- <div ref={focusWithinRef}>
315
- <input ref={inputRef} type="text" />
316
- </div>
317
- );
318
- };
319
- await act(() => {
320
- root.render(<Component />);
321
- });
322
-
323
- const target = createEventTarget(inputRef.current);
324
- // focus the target
325
- target.pointerdown();
326
- target.focus();
327
- target.keydown({key: 'a'});
328
- expect(onFocusWithinVisibleChange).toHaveBeenCalledTimes(0);
329
- });
330
-
331
- describe('onBeforeBlurWithin', () => {
332
- let onBeforeBlurWithin, onAfterBlurWithin, ref, innerRef, innerRef2;
333
-
334
- beforeEach(() => {
335
- onBeforeBlurWithin = jest.fn();
336
- onAfterBlurWithin = jest.fn(e => {
337
- e.persist();
338
- });
339
- ref = React.createRef();
340
- innerRef = React.createRef();
341
- innerRef2 = React.createRef();
342
- });
343
-
344
- // @gate www
345
- it('is called after a focused element is unmounted', async () => {
346
- const Component = ({show}) => {
347
- const focusWithinRef = useFocusWithin(ref, {
348
- onBeforeBlurWithin,
349
- onAfterBlurWithin,
350
- });
351
- return (
352
- <div ref={focusWithinRef}>
353
- {show && <input ref={innerRef} />}
354
- <div ref={innerRef2} />
355
- </div>
356
- );
357
- };
358
-
359
- await act(() => {
360
- root.render(<Component show={true} />);
361
- });
362
-
363
- const inner = innerRef.current;
364
- const target = createEventTarget(inner);
365
- target.keydown({key: 'Tab'});
366
- target.focus();
367
- expect(onBeforeBlurWithin).toHaveBeenCalledTimes(0);
368
- expect(onAfterBlurWithin).toHaveBeenCalledTimes(0);
369
- await act(() => {
370
- root.render(<Component show={false} />);
371
- });
372
-
373
- expect(onBeforeBlurWithin).toHaveBeenCalledTimes(1);
374
- expect(onAfterBlurWithin).toHaveBeenCalledTimes(1);
375
- expect(onAfterBlurWithin).toHaveBeenCalledWith(
376
- expect.objectContaining({relatedTarget: inner}),
377
- );
378
- });
379
-
380
- // @gate www
381
- it('is called after a nested focused element is unmounted', async () => {
382
- const Component = ({show}) => {
383
- const focusWithinRef = useFocusWithin(ref, {
384
- onBeforeBlurWithin,
385
- onAfterBlurWithin,
386
- });
387
- return (
388
- <div ref={focusWithinRef}>
389
- {show && (
390
- <div>
391
- <input ref={innerRef} />
392
- </div>
393
- )}
394
- <div ref={innerRef2} />
395
- </div>
396
- );
397
- };
398
-
399
- await act(() => {
400
- root.render(<Component show={true} />);
401
- });
402
-
403
- const inner = innerRef.current;
404
- const target = createEventTarget(inner);
405
- target.keydown({key: 'Tab'});
406
- target.focus();
407
- expect(onBeforeBlurWithin).toHaveBeenCalledTimes(0);
408
- expect(onAfterBlurWithin).toHaveBeenCalledTimes(0);
409
-
410
- await act(() => {
411
- root.render(<Component show={false} />);
412
- });
413
-
414
- expect(onBeforeBlurWithin).toHaveBeenCalledTimes(1);
415
- expect(onAfterBlurWithin).toHaveBeenCalledTimes(1);
416
- expect(onAfterBlurWithin).toHaveBeenCalledWith(
417
- expect.objectContaining({relatedTarget: inner}),
418
- );
419
- });
420
-
421
- // @gate www
422
- it('is called after many elements are unmounted', async () => {
423
- const buttonRef = React.createRef();
424
- const inputRef = React.createRef();
425
-
426
- const Component = ({show}) => {
427
- const focusWithinRef = useFocusWithin(ref, {
428
- onBeforeBlurWithin,
429
- onAfterBlurWithin,
430
- });
431
- return (
432
- <div ref={focusWithinRef}>
433
- {show && <button>Press me!</button>}
434
- {show && <button>Press me!</button>}
435
- {show && <input ref={inputRef} />}
436
- {show && <button>Press me!</button>}
437
- {!show && <button ref={buttonRef}>Press me!</button>}
438
- {show && <button>Press me!</button>}
439
- <button>Press me!</button>
440
- <button>Press me!</button>
441
- </div>
442
- );
443
- };
444
-
445
- await act(() => {
446
- root.render(<Component show={true} />);
447
- });
448
-
449
- inputRef.current.focus();
450
- expect(onBeforeBlurWithin).toHaveBeenCalledTimes(0);
451
- expect(onAfterBlurWithin).toHaveBeenCalledTimes(0);
452
- await act(() => {
453
- root.render(<Component show={false} />);
454
- });
455
-
456
- expect(onBeforeBlurWithin).toHaveBeenCalledTimes(1);
457
- expect(onAfterBlurWithin).toHaveBeenCalledTimes(1);
458
- });
459
-
460
- // @gate www
461
- it('is called after a nested focused element is unmounted (with scope query)', async () => {
462
- const TestScope = React.unstable_Scope;
463
- const testScopeQuery = (type, props) => true;
464
- let targetNodes;
465
- let targetNode;
466
-
467
- const Component = ({show}) => {
468
- const scopeRef = React.useRef(null);
469
- const focusWithinRef = useFocusWithin(scopeRef, {
470
- onBeforeBlurWithin(event) {
471
- const scope = scopeRef.current;
472
- targetNode = innerRef.current;
473
- targetNodes = scope.DO_NOT_USE_queryAllNodes(testScopeQuery);
474
- },
475
- });
476
-
477
- return (
478
- <TestScope ref={focusWithinRef}>
479
- {show && <input ref={innerRef} />}
480
- </TestScope>
481
- );
482
- };
483
-
484
- await act(() => {
485
- root.render(<Component show={true} />);
486
- });
487
-
488
- const inner = innerRef.current;
489
- const target = createEventTarget(inner);
490
- target.keydown({key: 'Tab'});
491
- target.focus();
492
- await act(() => {
493
- root.render(<Component show={false} />);
494
- });
495
- expect(targetNodes).toEqual([targetNode]);
496
- });
497
-
498
- // @gate www
499
- it('is called after a focused suspended element is hidden', async () => {
500
- const Suspense = React.Suspense;
501
- let suspend = false;
502
- let resolve;
503
- const promise = new Promise(resolvePromise => (resolve = resolvePromise));
504
-
505
- function Child() {
506
- if (suspend) {
507
- throw promise;
508
- } else {
509
- return <input ref={innerRef} />;
510
- }
511
- }
512
-
513
- const Component = ({show}) => {
514
- const focusWithinRef = useFocusWithin(ref, {
515
- onBeforeBlurWithin,
516
- onAfterBlurWithin,
517
- });
518
-
519
- return (
520
- <div ref={focusWithinRef}>
521
- <Suspense fallback="Loading...">
522
- <Child />
523
- </Suspense>
524
- </div>
525
- );
526
- };
527
-
528
- const root2 = ReactDOMClient.createRoot(container2);
529
-
530
- await act(() => {
531
- root2.render(<Component />);
532
- });
533
- expect(container2.innerHTML).toBe('<div><input></div>');
534
-
535
- const inner = innerRef.current;
536
- const target = createEventTarget(inner);
537
- target.keydown({key: 'Tab'});
538
- target.focus();
539
- expect(onBeforeBlurWithin).toHaveBeenCalledTimes(0);
540
- expect(onAfterBlurWithin).toHaveBeenCalledTimes(0);
541
-
542
- suspend = true;
543
- await act(() => {
544
- root2.render(<Component />);
545
- });
546
- expect(container2.innerHTML).toBe(
547
- '<div><input style="display: none;">Loading...</div>',
548
- );
549
- expect(onBeforeBlurWithin).toHaveBeenCalledTimes(1);
550
- expect(onAfterBlurWithin).toHaveBeenCalledTimes(1);
551
- await act(() => {
552
- suspend = false;
553
- resolve();
554
- });
555
- expect(container2.innerHTML).toBe('<div><input style=""></div>');
556
- });
557
-
558
- // @gate www
559
- it('is called after a focused suspended element is hidden then shown', async () => {
560
- const Suspense = React.Suspense;
561
- let suspend = false;
562
- let resolve;
563
- const promise = new Promise(resolvePromise => (resolve = resolvePromise));
564
- const buttonRef = React.createRef();
565
-
566
- function Child() {
567
- if (suspend) {
568
- throw promise;
569
- } else {
570
- return <input ref={innerRef} />;
571
- }
572
- }
573
-
574
- const Component = ({show}) => {
575
- const focusWithinRef = useFocusWithin(ref, {
576
- onBeforeBlurWithin,
577
- onAfterBlurWithin,
578
- });
579
-
580
- return (
581
- <div ref={focusWithinRef}>
582
- <Suspense fallback={<button ref={buttonRef}>Loading...</button>}>
583
- <Child />
584
- </Suspense>
585
- </div>
586
- );
587
- };
588
-
589
- const root2 = ReactDOMClient.createRoot(container2);
590
-
591
- await act(() => {
592
- root2.render(<Component />);
593
- });
594
-
595
- expect(onBeforeBlurWithin).toHaveBeenCalledTimes(0);
596
- expect(onAfterBlurWithin).toHaveBeenCalledTimes(0);
597
-
598
- suspend = true;
599
- await act(() => {
600
- root2.render(<Component />);
601
- });
602
- expect(onBeforeBlurWithin).toHaveBeenCalledTimes(0);
603
- expect(onAfterBlurWithin).toHaveBeenCalledTimes(0);
604
-
605
- await act(() => {
606
- root2.render(<Component />);
607
- });
608
- expect(onBeforeBlurWithin).toHaveBeenCalledTimes(0);
609
- expect(onAfterBlurWithin).toHaveBeenCalledTimes(0);
610
-
611
- buttonRef.current.focus();
612
- suspend = false;
613
- await act(() => {
614
- root2.render(<Component />);
615
- });
616
- expect(onBeforeBlurWithin).toHaveBeenCalledTimes(1);
617
- expect(onAfterBlurWithin).toHaveBeenCalledTimes(1);
618
-
619
- await act(() => {
620
- suspend = false;
621
- resolve();
622
- });
623
- expect(container2.innerHTML).toBe('<div><input style=""></div>');
624
- });
625
- });
626
-});
packages/react-interactions/events/src/dom/create-event-handle/useEvent.js
deleted
-72
@@ -1,72 +0,0 @@
1
-/**
2
- * Copyright (c) Meta Platforms, Inc. and affiliates.
3
- *
4
- * This source code is licensed under the MIT license found in the
5
- * LICENSE file in the root directory of this source tree.
6
- *
7
- * @flow
8
- */
9
-
10
-import * as React from 'react';
11
-import * as ReactDOM from 'react-dom';
12
-
13
-const {useLayoutEffect, useRef} = React;
14
-const {unstable_createEventHandle} = ReactDOM;
15
-
16
-type UseEventHandle = {
17
- setListener: (
18
- target: EventTarget,
19
- null | ((SyntheticEvent<EventTarget>) => void),
20
- ) => void,
21
- clear: () => void,
22
-};
23
-
24
-export default function useEvent(
25
- event: string,
26
- options?: {
27
- capture?: boolean,
28
- },
29
-): UseEventHandle {
30
- const handleRef = useRef<UseEventHandle | null>(null);
31
- let useEventHandle = handleRef.current;
32
-
33
- if (useEventHandle === null) {
34
- const setEventHandle = unstable_createEventHandle(event, options);
35
- const clears = new Map<EventTarget, () => void>();
36
- useEventHandle = {
37
- setListener(
38
- target: EventTarget,
39
- callback: null | ((SyntheticEvent<EventTarget>) => void),
40
- ): void {
41
- let clear = clears.get(target);
42
- if (clear !== undefined) {
43
- clear();
44
- }
45
- if (callback === null) {
46
- clears.delete(target);
47
- return;
48
- }
49
- clear = setEventHandle(target, callback);
50
- clears.set(target, clear);
51
- },
52
- clear(): void {
53
- clears.forEach(c => {
54
- c();
55
- });
56
- clears.clear();
57
- },
58
- };
59
- handleRef.current = useEventHandle;
60
- }
61
-
62
- useLayoutEffect(() => {
63
- return () => {
64
- if (useEventHandle !== null) {
65
- useEventHandle.clear();
66
- }
67
- handleRef.current = null;
68
- };
69
- }, [useEventHandle]);
70
-
71
- return useEventHandle;
72
-}
packages/react-interactions/npm/drag.js
deleted
-7
@@ -1,7 +0,0 @@
1
-'use strict';
2
-
3
-if (process.env.NODE_ENV === 'production') {
4
- module.exports = require('./cjs/react-interactions-events/drag.production.min.js');
5
-} else {
6
- module.exports = require('./cjs/react-interactions-events/drag.development.js');
7
-}
packages/react-interactions/npm/focus.js
deleted
-7
@@ -1,7 +0,0 @@
1
-'use strict';
2
-
3
-if (process.env.NODE_ENV === 'production') {
4
- module.exports = require('./cjs/react-interactions-events/focus.production.min.js');
5
-} else {
6
- module.exports = require('./cjs/react-interactions-events/focus.development.js');
7
-}
packages/react-interactions/npm/hover.js
deleted
-7
@@ -1,7 +0,0 @@
1
-'use strict';
2
-
3
-if (process.env.NODE_ENV === 'production') {
4
- module.exports = require('./cjs/react-interactions-events/hover.production.min.js');
5
-} else {
6
- module.exports = require('./cjs/react-interactions-events/hover.development.js');
7
-}
packages/react-interactions/npm/input.js
deleted
-7
@@ -1,7 +0,0 @@
1
-'use strict';
2
-
3
-if (process.env.NODE_ENV === 'production') {
4
- module.exports = require('./cjs/react-interactions-events/input.production.min.js');
5
-} else {
6
- module.exports = require('./cjs/react-interactions-events/input.development.js');
7
-}
packages/react-interactions/npm/press-legacy.js
deleted
-7
@@ -1,7 +0,0 @@
1
-'use strict';
2
-
3
-if (process.env.NODE_ENV === 'production') {
4
- module.exports = require('./cjs/react-interactions-events/press-legacy.production.min.js');
5
-} else {
6
- module.exports = require('./cjs/react-interactions-events/press-legacy.development.js');
7
-}
packages/react-interactions/npm/press.js
deleted
-7
@@ -1,7 +0,0 @@
1
-'use strict';
2
-
3
-if (process.env.NODE_ENV === 'production') {
4
- module.exports = require('./cjs/react-interactions-events/press.production.min.js');
5
-} else {
6
- module.exports = require('./cjs/react-interactions-events/press.development.js');
7
-}
packages/react-interactions/npm/scroll.js
deleted
-7
@@ -1,7 +0,0 @@
1
-'use strict';
2
-
3
-if (process.env.NODE_ENV === 'production') {
4
- module.exports = require('./cjs/react-interactions-events/scroll.production.min.js');
5
-} else {
6
- module.exports = require('./cjs/react-interactions-events/scroll.development.js');
7
-}
packages/react-interactions/npm/swipe.js
deleted
-7
@@ -1,7 +0,0 @@
1
-'use strict';
2
-
3
-if (process.env.NODE_ENV === 'production') {
4
- module.exports = require('./cjs/react-interactions-events/swipe.production.min.js');
5
-} else {
6
- module.exports = require('./cjs/react-interactions-events/swipe.development.js');
7
-}
packages/react-interactions/npm/tap.js
deleted
-7
@@ -1,7 +0,0 @@
1
-'use strict';
2
-
3
-if (process.env.NODE_ENV === 'production') {
4
- module.exports = require('./cjs/react-interactions-events/tap.production.min.js');
5
-} else {
6
- module.exports = require('./cjs/react-interactions-events/tap.development.js');
7
-}
packages/react-interactions/package.json
deleted
-39
@@ -1,39 +0,0 @@
1
-{
2
- "name": "react-interactions",
3
- "private": true,
4
- "description": "React is a JavaScript library for building user interfaces.",
5
- "keywords": [
6
- "react"
7
- ],
8
- "version": "0.1.0",
9
- "homepage": "https://react.dev/",
10
- "bugs": "https://github.com/facebook/react/issues",
11
- "license": "MIT",
12
- "files": [
13
- "LICENSE",
14
- "README.md",
15
- "events/README.md",
16
- "events/context-menu.js",
17
- "events/focus.js",
18
- "events/hover.js",
19
- "events/input.js",
20
- "events/keyboard.js",
21
- "events/press.js",
22
- "events/press-legacy.js",
23
- "events/tap.js",
24
- "cjs/",
25
- "umd/"
26
- ],
27
- "main": "index.js",
28
- "repository": {
29
- "type": "git",
30
- "url": "https://github.com/facebook/react.git",
31
- "directory": "packages/react"
32
- },
33
- "engines": {
34
- "node": ">=0.10.0"
35
- },
36
- "peerDependencies": {
37
- "react": "^17.0.0"
38
- }
39
-}