Skip to content

Commit 56562e6

Browse files
committed
main 🧊 add target method
1 parent 2abacd5 commit 56562e6

File tree

68 files changed

+1218
-934
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

68 files changed

+1218
-934
lines changed

‎packages/core/src/bundle/hooks/useClickOutside/useClickOutside.js

+1-2
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,7 @@ import { useRefState } from '../useRefState/useRefState';
77
* @category Sensors
88
*
99
* @overload
10-
* @template Target The target element(s)
11-
* @param {Target} target The target element(s) to detect outside clicks for
10+
* @param {HookTarget} target The target element(s) to detect outside clicks for
1211
* @param {(event: Event) => void} callback The callback to execute when a click outside the target is detected
1312
* @returns {void}
1413
*

‎packages/core/src/bundle/hooks/useCssVar/useCssVar.js

+9-11
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { useEffect, useState } from 'react';
2-
import { getElement } from '@/utils/helpers';
2+
import { getElement, isTarget } from '@/utils/helpers';
33
import { useRefState } from '../useRefState/useRefState';
44
/**
55
* @name useCssVar
@@ -9,23 +9,22 @@ import { useRefState } from '../useRefState/useRefState';
99
* @overload
1010
* @param {string} key The CSS variable key
1111
* @param {string} initialValue The initial value of the CSS variable
12-
* @returns {UseCssVarReturn} The object containing the value of the CSS variable
12+
* @returns {UseCssVarReturn & { ref: StateRef<Element> }} The object containing the value of the CSS variable and ref
1313
*
1414
* @example
15-
* const { ref, value, set } = useCssVar('color', 'red');
15+
* const { ref, value, set } = useCssVar('--color', 'red');
1616
*
1717
* @overload
18-
* @template Target The target element
19-
* @param {Target} target The target element
18+
* @param {HookTarget} target The target element
2019
* @param {string} key The CSS variable key
2120
* @param {string} initialValue The initial value of the CSS variable
2221
* @returns {UseCssVarReturn} The object containing the value of the CSS variable
2322
*
2423
* @example
25-
* const { value, set } = useCssVar(ref, 'color', 'red');
24+
* const { value, set } = useCssVar(ref, '--color', 'red');
2625
*/
2726
export const useCssVar = ((...params) => {
28-
const target = (typeof params[0] === 'object' ? params[0] : undefined);
27+
const target = (isTarget(params[0]) ? params[0] : undefined);
2928
const key = (target ? params[1] : params[0]);
3029
const initialValue = (target ? params[2] : params[1]);
3130
const [value, setValue] = useState(initialValue ?? '');
@@ -67,8 +66,7 @@ export const useCssVar = ((...params) => {
6766
observer.disconnect();
6867
};
6968
}, [target, internalRef.state]);
70-
return {
71-
value,
72-
set
73-
};
69+
if (target)
70+
return { value, set };
71+
return { ref: internalRef, value, set };
7472
});

‎packages/core/src/bundle/hooks/useDisplayMedia/useDisplayMedia.js

+5-6
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,9 @@ import { useRefState } from '../useRefState/useRefState';
99
* @browserapi mediaDevices.getDisplayMedia https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getDisplayMedia
1010
*
1111
* @overload
12-
* @template Target The target video element
13-
* @param {Target} target The target video element to display the media stream
12+
* @param {HookTarget} target The target video element to display the media stream
1413
* @param {boolean | MediaTrackConstraints} [options.audio] Whether to enable audio sharing
15-
* @param {boolean} [options.enabled=false] Whether to start immediately
14+
* @param {boolean} [options.immediately=false] Whether to start immediately
1615
* @param {boolean | MediaTrackConstraints} [options.video] Whether to enable video sharing
1716
* @returns {UseDisplayMediaReturn} Object containing stream, sharing status and control methods
1817
*
@@ -22,7 +21,7 @@ import { useRefState } from '../useRefState/useRefState';
2221
* @overload
2322
* @template Target The target video element
2423
* @param {boolean | MediaTrackConstraints} [options.audio] Whether to enable audio sharing
25-
* @param {boolean} [options.enabled=false] Whether to start immediately
24+
* @param {boolean} [options.immediately=false] Whether to start immediately
2625
* @param {boolean | MediaTrackConstraints} [options.video] Whether to enable video sharing
2726
* @returns {UseDisplayMediaReturn & { ref: StateRef<HTMLVideoElement> }} Object containing stream, sharing status, control methods and ref
2827
*
@@ -36,7 +35,7 @@ export const useDisplayMedia = ((...params) => {
3635
'getDisplayMedia' in navigator.mediaDevices;
3736
const target = (isTarget(params[0]) ? params[0] : undefined);
3837
const options = (params[1] ? params[1] : params[0]);
39-
const enabled = options?.enabled ?? false;
38+
const immediately = options?.immediately ?? false;
4039
const [sharing, setSharing] = useState(false);
4140
const streamRef = useRef(null);
4241
const internalRef = useRefState();
@@ -68,7 +67,7 @@ export const useDisplayMedia = ((...params) => {
6867
return displayMedia;
6968
};
7069
useEffect(() => {
71-
if (!supported || !enabled)
70+
if (!supported || !immediately)
7271
return;
7372
if (!target && !internalRef.state)
7473
return;

‎packages/core/src/bundle/hooks/useElementSize/useElementSize.js

+3-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { useState } from 'react';
2-
import { getElement, isTarget } from '@/utils/helpers';
2+
import { getElement } from '@/utils/helpers';
33
import { useIsomorphicLayoutEffect } from '../useIsomorphicLayoutEffect/useIsomorphicLayoutEffect';
44
import { useRefState } from '../useRefState/useRefState';
55
/**
@@ -8,8 +8,7 @@ import { useRefState } from '../useRefState/useRefState';
88
* @category Elements
99
*
1010
* @overload
11-
* @template Target The target element type
12-
* @param {UseElementSizeTarget} target The target element to observe
11+
* @param {HookTarget} target The target element to observe
1312
* @returns {UseElementSizeReturn} An object containing the current width and height of the element
1413
*
1514
* @example
@@ -22,7 +21,7 @@ import { useRefState } from '../useRefState/useRefState';
2221
* const { ref, value } = useElementSize();
2322
*/
2423
export const useElementSize = ((...params) => {
25-
const target = (isTarget(params[0]) ? params[0] : undefined);
24+
const target = params[0];
2625
const [size, setSize] = useState({ width: 0, height: 0 });
2726
const internalRef = useRefState();
2827
useIsomorphicLayoutEffect(() => {

‎packages/core/src/bundle/hooks/useEventListener/useEventListener.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { useEffect } from 'react';
2-
import { getElement } from '@/utils/helpers';
2+
import { getElement, isTarget } from '@/utils/helpers';
33
import { useEvent } from '../useEvent/useEvent';
44
import { useRefState } from '../useRefState/useRefState';
55
/**
@@ -32,7 +32,7 @@ import { useRefState } from '../useRefState/useRefState';
3232
* @overload
3333
* @template Event Key of window event map
3434
* @template Target The target element
35-
* @param {Target} target The target element to attach the event listener to
35+
* @param {HookTarget} target The target element to attach the event listener to
3636
* @param {Event | Event[]} event An array of event types to listen for
3737
* @param {(this: Target, event: HTMLElementEventMap[Event]) => void} handler The event handler function
3838
* @param {UseEventListenerOptions} [options] Options for the event listener
@@ -53,7 +53,7 @@ import { useRefState } from '../useRefState/useRefState';
5353
* const ref = useEventListener('click', () => console.log('click'));
5454
*/
5555
export const useEventListener = ((...params) => {
56-
const target = (params[1] instanceof Function ? undefined : params[0]);
56+
const target = (isTarget(params[0]) ? params[0] : undefined);
5757
const event = (target ? params[1] : params[0]);
5858
const events = Array.isArray(event) ? event : [event];
5959
const listener = (target ? params[2] : params[1]);

‎packages/core/src/bundle/hooks/useFocus/useFocus.js

+16-6
Original file line numberDiff line numberDiff line change
@@ -7,27 +7,33 @@ import { useRefState } from '../useRefState/useRefState';
77
* @category Browser
88
*
99
* @overload
10-
* @template Target The target element
11-
* @param {Target} target The target element to focus
10+
* @param {HookTarget} target The target element to focus
1211
* @param {boolean} [options.initialValue=false] The initial focus state of the target
13-
* @returns {UseFocusReturn} An object with a `focus` boolean state value
12+
* @param {(event: FocusEvent) => void} [options.onFocus] The callback function to be invoked on focus
13+
* @param {(event: FocusEvent) => void} [options.onBlur] The callback function to be invoked on blur
14+
* @returns {UseFocusReturn} An object with focus state and methods
1415
*
1516
* @example
1617
* const { focus, blur, focused } = useFocus(ref);
1718
*
1819
* @overload
20+
* @template Target The target element
1921
* @param {boolean} [options.initialValue=false] The initial focus state of the target
20-
* @returns {UseFocusReturn} An object with a `focus` boolean state value
22+
* @param {(event: FocusEvent) => void} [options.onFocus] The callback function to be invoked on focus
23+
* @param {(event: FocusEvent) => void} [options.onBlur] The callback function to be invoked on blur
24+
* @returns {UseFocusReturn & { ref: StateRef<Target> }} An object with focus state, methods and ref
2125
*
2226
* @example
2327
* const { ref, focus, blur, focused } = useFocus();
2428
*/
2529
export const useFocus = ((...params) => {
26-
const target = isTarget(params[0]) ? params[0] : undefined;
30+
const target = (isTarget(params[0]) ? params[0] : undefined);
2731
const options = (target ? params[1] : params[0]) ?? {};
2832
const initialValue = options.initialValue ?? false;
2933
const [focused, setFocused] = useState(initialValue);
3034
const internalRef = useRefState();
35+
const internalOptionsRef = useRef(options);
36+
internalOptionsRef.current = options;
3137
const elementRef = useRef(null);
3238
const focus = () => elementRef.current?.focus();
3339
const blur = () => elementRef.current?.blur();
@@ -39,10 +45,14 @@ export const useFocus = ((...params) => {
3945
return;
4046
elementRef.current = element;
4147
const onFocus = (event) => {
48+
internalOptionsRef.current?.onFocus?.(event);
4249
if (!focus || event.target.matches?.(':focus-visible'))
4350
setFocused(true);
4451
};
45-
const onBlur = () => setFocused(false);
52+
const onBlur = (event) => {
53+
internalOptionsRef.current?.onBlur?.(event);
54+
setFocused(false);
55+
};
4656
if (initialValue)
4757
element.focus();
4858
element.addEventListener('focus', onFocus);

‎packages/core/src/bundle/hooks/useFullscreen/useFullscreen.js

+1-2
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@ import { useRefState } from '../useRefState/useRefState';
88
* @category Browser
99
*
1010
* @overload
11-
* @template Target The target element for fullscreen
12-
* @param {Target} target The target element for fullscreen
11+
* @param {HookTarget} target The target element for fullscreen
1312
* @param {boolean} [options.initialValue=false] initial value of fullscreen
1413
* @param {() => void} [options.onEnter] on enter fullscreen
1514
* @param {() => void} [options.onExit] on exit fullscreen

‎packages/core/src/bundle/hooks/useHotkeys/useHotkeys.js

+25-30
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { useEffect, useRef } from 'react';
2-
import { getElement } from '@/utils/helpers';
2+
import { getElement, isTarget } from '@/utils/helpers';
3+
import { useEvent } from '../useEvent/useEvent';
34
import { useRefState } from '../useRefState/useRefState';
45
export const isHotkeyMatch = (hotkey, keys) => hotkey
56
.toLowerCase()
@@ -14,8 +15,7 @@ export const isHotkeyMatch = (hotkey, keys) => hotkey
1415
* @category Sensors
1516
*
1617
* @overload
17-
* @template Target The target element
18-
* @param {Target} [target=window] The target element to attach the event listener to
18+
* @param {HookTarget} [target=window] The target element to attach the event listener to
1919
* @param {string} hotkeys The hotkey to listen for
2020
* @param {(event: KeyboardEvent) => void} callback The callback function to execute when hotkey is pressed
2121
* @param {Record<string, string>} [options.alias] Alias map for hotkeys
@@ -41,52 +41,47 @@ export const isHotkeyMatch = (hotkey, keys) => hotkey
4141
* const ref = useHotkeys('ctrl+a, ctrl+b', () => console.log('hotkey pressed'));
4242
*/
4343
export const useHotkeys = ((...params) => {
44-
const target = params[0] instanceof Element ||
45-
(params[0] && typeof params[0] === 'object' && 'current' in params[0])
46-
? params[0]
47-
: undefined;
44+
const target = (isTarget(params[0]) ? params[0] : undefined);
4845
const hotkeys = (target ? params[1] : params[0]);
4946
const callback = (target ? params[2] : params[1]);
5047
const options = (target ? params[3] : params[2]);
5148
const internalRef = useRefState(window);
5249
const keysRef = useRef([]);
53-
const callbackRef = useRef(callback);
54-
callbackRef.current = callback;
5550
const enabled = options?.enabled ?? true;
51+
const onKeyDown = useEvent((event) => {
52+
if (!enabled)
53+
return;
54+
if (keysRef.current.some(({ code }) => code === event.code))
55+
return;
56+
const alias = options?.alias?.[event.key] ?? event.code;
57+
const updatedKeys = [...keysRef.current, { key: event.key, code: event.code, alias }];
58+
keysRef.current = updatedKeys;
59+
const hotkeysList = hotkeys.split(',').map((h) => h.trim());
60+
const isMatch = hotkeysList.some((hotkey) => isHotkeyMatch(hotkey, updatedKeys));
61+
if (!isMatch)
62+
return;
63+
event.preventDefault();
64+
callback(event);
65+
});
66+
const onKeyUp = useEvent((event) => {
67+
if (!enabled)
68+
return;
69+
keysRef.current = keysRef.current.filter(({ code }) => code !== event.code);
70+
});
5671
useEffect(() => {
5772
keysRef.current = [];
5873
if (!target && !internalRef.state && !enabled)
5974
return;
6075
const element = (target ? getElement(target) : internalRef.current);
6176
if (!element)
6277
return;
63-
const onKeyDown = (event) => {
64-
if (!enabled)
65-
return;
66-
if (keysRef.current.some(({ code }) => code === event.code))
67-
return;
68-
const alias = options?.alias?.[event.key] ?? event.code;
69-
const updatedKeys = [...keysRef.current, { key: event.key, code: event.code, alias }];
70-
keysRef.current = updatedKeys;
71-
const hotkeysList = hotkeys.split(',').map((h) => h.trim());
72-
const isMatch = hotkeysList.some((hotkey) => isHotkeyMatch(hotkey, updatedKeys));
73-
if (!isMatch)
74-
return;
75-
event.preventDefault();
76-
callbackRef.current(event);
77-
};
78-
const onKeyUp = (event) => {
79-
if (!enabled)
80-
return;
81-
keysRef.current = keysRef.current.filter(({ code }) => code !== event.code);
82-
};
8378
element.addEventListener('keydown', onKeyDown);
8479
element.addEventListener('keyup', onKeyUp);
8580
return () => {
8681
element.removeEventListener('keydown', onKeyDown);
8782
element.removeEventListener('keyup', onKeyUp);
8883
};
89-
}, [target, internalRef.state, enabled, hotkeys]);
84+
}, [target, internalRef.state, enabled, hotkeys, onKeyDown, onKeyUp]);
9085
if (target)
9186
return;
9287
return internalRef;

‎packages/core/src/bundle/hooks/useHover/useHover.js

+2-4
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,15 @@ import { useRefState } from '../useRefState/useRefState';
77
* @category Sensors
88
*
99
* @overload
10-
* @template Target The target element
11-
* @param {Target} target The target element to be hovered
10+
* @param {HookTarget} target The target element to be hovered
1211
* @param {(event: Event) => void} [callback] The callback function to be invoked on mouse enter
1312
* @returns {boolean} The state of the hover
1413
*
1514
* @example
1615
* const hovering = useHover(ref, () => console.log('callback'));
1716
*
1817
* @overload
19-
* @template Target The target element
20-
* @param {Target} target The target element to be hovered
18+
* @param {HookTarget} target The target element to be hovered
2119
* @param {(event: Event) => void} [options.onEntry] The callback function to be invoked on mouse enter
2220
* @param {(event: Event) => void} [options.onLeave] The callback function to be invoked on mouse leave
2321
* @returns {boolean} The state of the hover

‎packages/core/src/bundle/hooks/useInfiniteScroll/useInfiniteScroll.js

+1-2
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,7 @@ import { useRefState } from '../useRefState/useRefState';
1818
* const { ref, loading } = useInfiniteScroll(() => console.log('infinite scroll'));
1919
*
2020
* @overload
21-
* @template Target The target element
22-
* @param {Target} target The target element to detect infinite scroll for
21+
* @param {HookTarget} target The target element to detect infinite scroll for
2322
* @param {(event: Event) => void} callback The callback to execute when a click outside the target is detected
2423
* @param {number} [options.distance=10] The distance in pixels to trigger the callback
2524
* @param {string} [options.direction='bottom'] The direction to trigger the callback

‎packages/core/src/bundle/hooks/useIntersectionObserver/useIntersectionObserver.js

+4-5
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,10 @@ import { useRefState } from '../useRefState/useRefState';
77
* @category Browser
88
*
99
* @overload
10-
* @template Target The target element
11-
* @param {Target} target The target element to detect intersection
10+
* @param {HookTarget} target The target element to detect intersection
1211
* @param {boolean} [options.enabled=true] The IntersectionObserver options
1312
* @param {((entries: IntersectionObserverEntry[], observer: IntersectionObserver) => void) | undefined} [options.onChange] The callback to execute when intersection is detected
14-
* @param {IntersectionObserverInit['root'] | RefObject<Element | null | undefined>} [options.root] The root element to observe
13+
* @param {HookTarget} [options.root] The root element to observe
1514
* @returns {UseIntersectionObserverReturn} An object containing the state and the supported status
1615
*
1716
* @example
@@ -21,7 +20,7 @@ import { useRefState } from '../useRefState/useRefState';
2120
* @template Target The target element
2221
* @param {boolean} [options.enabled=true] The IntersectionObserver options
2322
* @param {((entries: IntersectionObserverEntry[], observer: IntersectionObserver) => void) | undefined} [options.onChange] The callback to execute when intersection is detected
24-
* @param {IntersectionObserverInit['root'] | RefObject<Element | null | undefined>} [options.root] The root element to observe
23+
* @param {HookTarget} [options.root] The root element to observe
2524
* @returns {UseIntersectionObserverReturn & { ref: StateRef<Target> }} A React ref to attach to the target element
2625
*
2726
* @example
@@ -46,7 +45,7 @@ export const useIntersectionObserver = ((...params) => {
4645
internalOnChangeRef.current?.(entry);
4746
}, {
4847
...options,
49-
root: options?.root ? getElement(options?.root) : document
48+
root: options?.root ? getElement(options.root) : document
5049
});
5150
observer.observe(element);
5251
return () => {

0 commit comments

Comments
 (0)