@reactuses/core 1.1.5 → 2.0.1

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.cjs CHANGED
@@ -131,7 +131,7 @@ function useStorage(key, defaults, getStorage, options = {}) {
131
131
  }
132
132
  const type = guessSerializerType(defaults);
133
133
  const serializer = (_a = options.serializer) != null ? _a : StorageSerializers[type];
134
- const getStoredValue = () => {
134
+ const getStoredValue = useEvent(() => {
135
135
  try {
136
136
  const raw = storage == null ? void 0 : storage.getItem(key);
137
137
  if (raw !== void 0 && raw !== null) {
@@ -143,11 +143,11 @@ function useStorage(key, defaults, getStorage, options = {}) {
143
143
  } catch (e) {
144
144
  onError(e);
145
145
  }
146
- };
147
- const [state, setState] = React.useState(() => getStoredValue());
148
- useUpdateEffect(() => {
146
+ });
147
+ const [state, setState] = React.useState(defaults);
148
+ React.useEffect(() => {
149
149
  setState(getStoredValue());
150
- }, [key]);
150
+ }, [getStoredValue, key]);
151
151
  const updateState = useEvent(
152
152
  (valOrFunc) => {
153
153
  const currentState = isFunction(valOrFunc) ? valOrFunc(state) : valOrFunc;
@@ -205,12 +205,12 @@ function useInterval(callback, delay, options) {
205
205
  }
206
206
 
207
207
  const getInitialState = (query, defaultState) => {
208
- if (isBrowser) {
209
- return window.matchMedia(query).matches;
210
- }
211
208
  if (defaultState !== void 0) {
212
209
  return defaultState;
213
210
  }
211
+ if (isBrowser) {
212
+ return window.matchMedia(query).matches;
213
+ }
214
214
  if (process.env.NODE_ENV !== "production") {
215
215
  console.warn(
216
216
  "`useMediaQuery` When server side rendering, defaultState should be defined to prevent a hydration mismatches."
@@ -262,21 +262,24 @@ function useDarkMode(options = {}) {
262
262
  const prefersDarkMode = usePreferredDark(false);
263
263
  const value = initialValue ? initialValue : prefersDarkMode ? "dark" : "light";
264
264
  const [dark, setDark] = useStorage(storageKey, value, storage);
265
- React.useEffect(() => {
266
- const element = window == null ? void 0 : window.document.querySelector(selector);
267
- if (!element) {
268
- return;
269
- }
270
- if (attribute === "class") {
271
- dark && element.classList.add(dark);
272
- } else {
273
- dark && element.setAttribute(attribute, dark);
274
- }
275
- return () => {
276
- dark && (element == null ? void 0 : element.classList.remove(dark));
277
- };
278
- }, [attribute, dark, selector]);
279
- return [dark, setDark];
265
+ const wrappedSetDark = React.useCallback(
266
+ (latestDark) => {
267
+ const element = window == null ? void 0 : window.document.querySelector(selector);
268
+ if (!element) {
269
+ return;
270
+ }
271
+ if (attribute === "class") {
272
+ latestDark && element.classList.add(latestDark);
273
+ dark && element.classList.remove(dark);
274
+ } else {
275
+ latestDark && element.setAttribute(attribute, latestDark);
276
+ dark && element.removeAttribute(attribute);
277
+ }
278
+ setDark(latestDark);
279
+ },
280
+ [attribute, dark, selector, setDark]
281
+ );
282
+ return [dark, wrappedSetDark];
280
283
  }
281
284
 
282
285
  function useMount(fn) {
@@ -544,8 +547,8 @@ function useDeepCompareEffect(effect, deps) {
544
547
 
545
548
  function useEventListener(eventName, handler, element, options) {
546
549
  const savedHandler = useLatest(handler);
550
+ const targetElement = getTargetElement(element, window);
547
551
  useDeepCompareEffect(() => {
548
- const targetElement = getTargetElement(element, window);
549
552
  if (!(targetElement && targetElement.addEventListener)) {
550
553
  return;
551
554
  }
@@ -554,7 +557,7 @@ function useEventListener(eventName, handler, element, options) {
554
557
  return () => {
555
558
  off(targetElement, eventName, eventListener);
556
559
  };
557
- }, [eventName, element, options, savedHandler]);
560
+ }, [eventName, targetElement, options, savedHandler]);
558
561
  }
559
562
 
560
563
  function useCounter(initialValue = 0, max = null, min = null) {
@@ -698,20 +701,20 @@ function useFavicon(href, baseUrl = "", rel = "icon") {
698
701
  function useMutationObserver(callback, target, options = {}) {
699
702
  const callbackRef = useLatest(callback);
700
703
  const observerRef = React.useRef();
704
+ const element = getTargetElement(target);
701
705
  const stop = React.useCallback(() => {
702
706
  if (observerRef.current) {
703
707
  observerRef.current.disconnect();
704
708
  }
705
709
  }, []);
706
710
  useDeepCompareEffect(() => {
707
- const element = getTargetElement(target);
708
711
  if (!element) {
709
712
  return;
710
713
  }
711
714
  observerRef.current = new MutationObserver(callbackRef.current);
712
715
  observerRef.current.observe(element, options);
713
716
  return stop;
714
- }, [options]);
717
+ }, [options, element]);
715
718
  return stop;
716
719
  }
717
720
 
@@ -1496,13 +1499,13 @@ function useOrientation(initialState = defaultState) {
1496
1499
  function useIntersectionObserver(target, callback, options = {}) {
1497
1500
  const savedCallback = useLatest(callback);
1498
1501
  const observerRef = React.useRef();
1502
+ const element = getTargetElement(target);
1499
1503
  const stop = React.useCallback(() => {
1500
1504
  if (observerRef.current) {
1501
1505
  observerRef.current.disconnect();
1502
1506
  }
1503
1507
  }, []);
1504
1508
  useDeepCompareEffect(() => {
1505
- const element = getTargetElement(target);
1506
1509
  if (!element) {
1507
1510
  return;
1508
1511
  }
@@ -1512,7 +1515,7 @@ function useIntersectionObserver(target, callback, options = {}) {
1512
1515
  );
1513
1516
  observerRef.current.observe(element);
1514
1517
  return stop;
1515
- }, [options]);
1518
+ }, [options, element]);
1516
1519
  return stop;
1517
1520
  }
1518
1521
 
@@ -1552,20 +1555,20 @@ function useDocumentVisibility() {
1552
1555
  function useResizeObserver(target, callback, options = {}) {
1553
1556
  const savedCallback = useLatest(callback);
1554
1557
  const observerRef = React.useRef();
1558
+ const element = getTargetElement(target);
1555
1559
  const stop = React.useCallback(() => {
1556
1560
  if (observerRef.current) {
1557
1561
  observerRef.current.disconnect();
1558
1562
  }
1559
1563
  }, []);
1560
1564
  useDeepCompareEffect(() => {
1561
- const element = getTargetElement(target);
1562
1565
  if (!element) {
1563
1566
  return;
1564
1567
  }
1565
1568
  observerRef.current = new ResizeObserver(savedCallback.current);
1566
1569
  observerRef.current.observe(element, options);
1567
1570
  return stop;
1568
- }, [options]);
1571
+ }, [options, element]);
1569
1572
  return stop;
1570
1573
  }
1571
1574
 
@@ -1790,11 +1793,11 @@ function useInfiniteScroll(target, onLoadMore, options = {}) {
1790
1793
  [direction]: (_b = options.distance) != null ? _b : 0
1791
1794
  }, options.offset)
1792
1795
  }));
1796
+ const element = getTargetElement(target);
1793
1797
  const di = state[3][direction];
1794
1798
  useUpdateEffect(() => {
1795
1799
  const fn = () => __async$1(this, null, function* () {
1796
1800
  var _a2, _b2;
1797
- const element = getTargetElement(target);
1798
1801
  const previous = {
1799
1802
  height: (_a2 = element == null ? void 0 : element.scrollHeight) != null ? _a2 : 0,
1800
1803
  width: (_b2 = element == null ? void 0 : element.scrollWidth) != null ? _b2 : 0
@@ -1808,7 +1811,7 @@ function useInfiniteScroll(target, onLoadMore, options = {}) {
1808
1811
  }
1809
1812
  });
1810
1813
  fn();
1811
- }, [di, options.preserveScrollPosition]);
1814
+ }, [di, options.preserveScrollPosition, element]);
1812
1815
  }
1813
1816
 
1814
1817
  const defaultEvents = [
@@ -1845,6 +1848,7 @@ function useMousePressed(target, options = {}) {
1845
1848
  const { touch = true, drag = true, initialValue = false } = options;
1846
1849
  const [pressed, setPressed] = React.useState(initialValue);
1847
1850
  const [sourceType, setSourceType] = React.useState(null);
1851
+ const element = getTargetElement(target);
1848
1852
  const onPressed = React.useCallback(
1849
1853
  (srcType) => () => {
1850
1854
  setPressed(true);
@@ -1859,8 +1863,7 @@ function useMousePressed(target, options = {}) {
1859
1863
  useEventListener("mousedown", onPressed("mouse"), target, { passive: true });
1860
1864
  useEventListener("mouseleave", onReleased, () => window, { passive: true });
1861
1865
  useEventListener("mouseup", onReleased, () => window, { passive: true });
1862
- useMount(() => {
1863
- const element = getTargetElement(target);
1866
+ React.useEffect(() => {
1864
1867
  if (drag) {
1865
1868
  element == null ? void 0 : element.addEventListener("dragstart", onPressed("mouse"), {
1866
1869
  passive: true
@@ -1895,7 +1898,7 @@ function useMousePressed(target, options = {}) {
1895
1898
  element == null ? void 0 : element.removeEventListener("touchcancel", onReleased);
1896
1899
  }
1897
1900
  };
1898
- });
1901
+ }, [drag, onPressed, onReleased, element, touch]);
1899
1902
  return [pressed, sourceType];
1900
1903
  }
1901
1904
 
@@ -1912,28 +1915,25 @@ function preventDefault(rawEvent) {
1912
1915
  function useScrollLock(target, initialState = false) {
1913
1916
  const [locked, setLocked] = React.useState(initialState);
1914
1917
  const initialOverflowRef = React.useRef("scroll");
1915
- useMount(() => {
1916
- const element = getTargetElement(target);
1918
+ const element = getTargetElement(target);
1919
+ React.useEffect(() => {
1917
1920
  if (element) {
1918
1921
  initialOverflowRef.current = element.style.overflow;
1919
1922
  if (locked) {
1920
1923
  element.style.overflow = "hidden";
1921
1924
  }
1922
1925
  }
1923
- });
1926
+ }, [locked, element]);
1924
1927
  const lock = useEvent(() => {
1925
- const element = getTargetElement(target);
1926
1928
  if (!element || locked) {
1927
1929
  return;
1928
1930
  }
1929
1931
  if (isIOS) {
1930
1932
  element.addEventListener("touchmove", preventDefault, { passive: false });
1931
1933
  }
1932
- element.style.overflow = "hidden";
1933
1934
  setLocked(true);
1934
1935
  });
1935
1936
  const unlock = useEvent(() => {
1936
- const element = getTargetElement(target);
1937
1937
  if (!element || !locked) {
1938
1938
  return;
1939
1939
  }
@@ -2480,6 +2480,239 @@ var useOnceEffect = createOnceEffect(React.useEffect);
2480
2480
 
2481
2481
  var useOnceLayoutEffect = createOnceEffect(React.useLayoutEffect);
2482
2482
 
2483
+ function useReducedMotion(defaultState) {
2484
+ return useMediaQuery("(prefers-reduced-motion: reduce)", defaultState);
2485
+ }
2486
+
2487
+ const setScrollParam = ({
2488
+ axis,
2489
+ parent,
2490
+ distance
2491
+ }) => {
2492
+ if (!parent && typeof document === "undefined") {
2493
+ return;
2494
+ }
2495
+ const method = axis === "y" ? "scrollTop" : "scrollLeft";
2496
+ if (parent) {
2497
+ parent[method] = distance;
2498
+ } else {
2499
+ const { body, documentElement } = document;
2500
+ body[method] = distance;
2501
+ documentElement[method] = distance;
2502
+ }
2503
+ };
2504
+ const isScrollElement = (axis, node) => {
2505
+ if (!node) {
2506
+ return false;
2507
+ }
2508
+ const AXIS = axis === "x" ? "X" : "Y";
2509
+ return getComputedStyle(node)[`overflow${AXIS}`] === "auto" || getComputedStyle(node)[`overflow${AXIS}`] === "scroll";
2510
+ };
2511
+ const cache = /* @__PURE__ */ new Map();
2512
+ const getScrollParent = (axis, node) => {
2513
+ if (!node || !node.parentElement) {
2514
+ return null;
2515
+ }
2516
+ if (cache.has(node)) {
2517
+ return cache.get(node) || null;
2518
+ }
2519
+ let parent = node.parentElement;
2520
+ while (parent && !isScrollElement(axis, parent)) {
2521
+ parent = parent.parentElement;
2522
+ }
2523
+ if (parent) {
2524
+ cache.set(node, parent);
2525
+ }
2526
+ return parent;
2527
+ };
2528
+ const getScrollStart = ({
2529
+ axis,
2530
+ parent
2531
+ }) => {
2532
+ if (!parent && typeof document === "undefined") {
2533
+ return 0;
2534
+ }
2535
+ const method = axis === "y" ? "scrollTop" : "scrollLeft";
2536
+ if (parent) {
2537
+ return parent[method];
2538
+ }
2539
+ const { body, documentElement } = document;
2540
+ return body[method] + documentElement[method];
2541
+ };
2542
+
2543
+ const easeInOutQuad = (t) => t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t;
2544
+
2545
+ const getRelativePosition = ({
2546
+ axis,
2547
+ target,
2548
+ parent,
2549
+ alignment,
2550
+ offset,
2551
+ isList
2552
+ }) => {
2553
+ if (!target || !parent && typeof document === "undefined") {
2554
+ return 0;
2555
+ }
2556
+ const isCustomParent = !!parent;
2557
+ const parentElement = parent || document.body;
2558
+ const parentPosition = parentElement.getBoundingClientRect();
2559
+ const targetPosition = target.getBoundingClientRect();
2560
+ const getDiff = (property) => targetPosition[property] - parentPosition[property];
2561
+ if (axis === "y") {
2562
+ const diff = getDiff("top");
2563
+ if (diff === 0) {
2564
+ return 0;
2565
+ }
2566
+ if (alignment === "start") {
2567
+ const distance = diff - offset;
2568
+ const shouldScroll = distance <= targetPosition.height * (isList ? 0 : 1) || !isList;
2569
+ return shouldScroll ? distance : 0;
2570
+ }
2571
+ const parentHeight = isCustomParent ? parentPosition.height : window.innerHeight;
2572
+ if (alignment === "end") {
2573
+ const distance = diff + offset - parentHeight + targetPosition.height;
2574
+ const shouldScroll = distance >= -targetPosition.height * (isList ? 0 : 1) || !isList;
2575
+ return shouldScroll ? distance : 0;
2576
+ }
2577
+ if (alignment === "center") {
2578
+ return diff - parentHeight / 2 + targetPosition.height / 2;
2579
+ }
2580
+ return 0;
2581
+ }
2582
+ if (axis === "x") {
2583
+ const diff = getDiff("left");
2584
+ if (diff === 0) {
2585
+ return 0;
2586
+ }
2587
+ if (alignment === "start") {
2588
+ const distance = diff - offset;
2589
+ const shouldScroll = distance <= targetPosition.width || !isList;
2590
+ return shouldScroll ? distance : 0;
2591
+ }
2592
+ const parentWidth = isCustomParent ? parentPosition.width : window.innerWidth;
2593
+ if (alignment === "end") {
2594
+ const distance = diff + offset - parentWidth + targetPosition.width;
2595
+ const shouldScroll = distance >= -targetPosition.width || !isList;
2596
+ return shouldScroll ? distance : 0;
2597
+ }
2598
+ if (alignment === "center") {
2599
+ return diff - parentWidth / 2 + targetPosition.width / 2;
2600
+ }
2601
+ return 0;
2602
+ }
2603
+ return 0;
2604
+ };
2605
+
2606
+ function useScrollIntoView({
2607
+ duration = 1250,
2608
+ axis = "y",
2609
+ onScrollFinish,
2610
+ easing = easeInOutQuad,
2611
+ offset = 0,
2612
+ cancelable = true,
2613
+ isList = false,
2614
+ targetElement,
2615
+ scrollElement
2616
+ }) {
2617
+ const frameID = React.useRef(0);
2618
+ const startTime = React.useRef(0);
2619
+ const shouldStop = React.useRef(false);
2620
+ const reducedMotion = useReducedMotion(false);
2621
+ const cancel = () => {
2622
+ if (frameID.current) {
2623
+ cancelAnimationFrame(frameID.current);
2624
+ }
2625
+ };
2626
+ const scrollIntoView = useEvent(
2627
+ ({ alignment = "start" } = {}) => {
2628
+ var _a;
2629
+ const element = getTargetElement(targetElement);
2630
+ const parent = getTargetElement(scrollElement) || getScrollParent(axis, element);
2631
+ shouldStop.current = false;
2632
+ if (frameID.current) {
2633
+ cancel();
2634
+ }
2635
+ const start = (_a = getScrollStart({ parent, axis })) != null ? _a : 0;
2636
+ const change = getRelativePosition({
2637
+ parent,
2638
+ target: element,
2639
+ axis,
2640
+ alignment,
2641
+ offset,
2642
+ isList
2643
+ }) - (parent ? 0 : start);
2644
+ const animateScroll = () => {
2645
+ if (startTime.current === 0) {
2646
+ startTime.current = performance.now();
2647
+ }
2648
+ const now = performance.now();
2649
+ const elapsed = now - startTime.current;
2650
+ const t = reducedMotion || duration === 0 ? 1 : elapsed / duration;
2651
+ const distance = start + change * easing(t);
2652
+ setScrollParam({
2653
+ parent,
2654
+ axis,
2655
+ distance
2656
+ });
2657
+ if (!shouldStop.current && t < 1) {
2658
+ frameID.current = requestAnimationFrame(animateScroll);
2659
+ } else {
2660
+ typeof onScrollFinish === "function" && onScrollFinish();
2661
+ startTime.current = 0;
2662
+ frameID.current = 0;
2663
+ cancel();
2664
+ }
2665
+ };
2666
+ animateScroll();
2667
+ }
2668
+ );
2669
+ const handleStop = () => {
2670
+ if (cancelable) {
2671
+ shouldStop.current = true;
2672
+ }
2673
+ };
2674
+ useEventListener("wheel", handleStop, null, { passive: true });
2675
+ useEventListener("touchmove", handleStop, null, { passive: true });
2676
+ React.useEffect(() => cancel, []);
2677
+ return {
2678
+ scrollIntoView,
2679
+ cancel
2680
+ };
2681
+ }
2682
+
2683
+ const useSticky = ({
2684
+ targetElement,
2685
+ scrollElement,
2686
+ axis = "y",
2687
+ nav = 0
2688
+ }) => {
2689
+ const [isSticky, setSticky] = React.useState(false);
2690
+ const element = getTargetElement(targetElement);
2691
+ const scrollParent = getTargetElement(scrollElement) || getScrollParent(axis, element);
2692
+ const { run: scrollHandler } = useThrottleFn(() => {
2693
+ if (!element) {
2694
+ return;
2695
+ }
2696
+ const rect = element.getBoundingClientRect();
2697
+ if (axis === "y") {
2698
+ setSticky((rect == null ? void 0 : rect.top) <= nav);
2699
+ } else {
2700
+ setSticky((rect == null ? void 0 : rect.left) <= nav);
2701
+ }
2702
+ }, 50);
2703
+ React.useEffect(() => {
2704
+ if (!element || !scrollParent) {
2705
+ return;
2706
+ }
2707
+ scrollParent.addEventListener("scroll", scrollHandler);
2708
+ scrollHandler();
2709
+ return () => {
2710
+ scrollParent.removeEventListener("scroll", scrollHandler);
2711
+ };
2712
+ }, [axis, element, scrollHandler, scrollParent]);
2713
+ return [isSticky, setSticky];
2714
+ };
2715
+
2483
2716
  exports.useActiveElement = useActiveElement;
2484
2717
  exports.useClickOutside = useClickOutSide;
2485
2718
  exports.useClipboard = useClipBorad;
@@ -2537,11 +2770,14 @@ exports.usePreferredDark = usePreferredDark;
2537
2770
  exports.usePrevious = usePrevious;
2538
2771
  exports.useRafFn = useRafFn;
2539
2772
  exports.useRafState = useRafState;
2773
+ exports.useReducedMotion = useReducedMotion;
2540
2774
  exports.useResizeObserver = useResizeObserver;
2541
2775
  exports.useScriptTag = useScriptTag;
2542
2776
  exports.useScroll = useScroll;
2777
+ exports.useScrollIntoView = useScrollIntoView;
2543
2778
  exports.useScrollLock = useScrollLock;
2544
2779
  exports.useSessionStorage = useSessionStorage;
2780
+ exports.useSticky = useSticky;
2545
2781
  exports.useTextDirection = useTextDirection;
2546
2782
  exports.useThrottle = useThrottle;
2547
2783
  exports.useThrottleFn = useThrottleFn;
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as react from 'react';
2
- import { MutableRefObject, useEffect, useLayoutEffect, Dispatch, SetStateAction, DependencyList, EffectCallback, RefObject, CSSProperties } from 'react';
2
+ import react__default, { MutableRefObject, useEffect, useLayoutEffect, Dispatch, SetStateAction, DependencyList, EffectCallback, RefObject, CSSProperties } from 'react';
3
3
  import * as lodash from 'lodash';
4
4
 
5
5
  declare function usePrevious<T>(state: T): T | undefined;
@@ -74,7 +74,8 @@ interface UseDarkOptions<T> {
74
74
  */
75
75
  attribute?: string;
76
76
  /**
77
- * The initial value write the target element
77
+ * The initial value write the target element, defaultValue follow system prefer color
78
+ * must be set in SSR
78
79
  * @default 'light | dark'
79
80
  */
80
81
  initialValue?: T;
@@ -91,7 +92,7 @@ interface UseDarkOptions<T> {
91
92
  */
92
93
  storage?: () => Storage;
93
94
  }
94
- declare function useDarkMode<T extends string | "light" | "dark">(options?: UseDarkOptions<T>): readonly [T | null, react.Dispatch<react.SetStateAction<T | null>>];
95
+ declare function useDarkMode<T extends string | "light" | "dark">(options?: UseDarkOptions<T>): readonly [T | null, (latestDark: T) => void];
95
96
 
96
97
  declare function useMediaQuery(query: string, defaultState?: boolean): boolean;
97
98
 
@@ -749,4 +750,46 @@ declare const _default$1: typeof useEffect | typeof react.useLayoutEffect;
749
750
 
750
751
  declare const _default: typeof react.useEffect | typeof useLayoutEffect;
751
752
 
752
- export { ColorScheme, Contrast, CursorState, GeneralPermissionDescriptor, IDisposable, IEvent, IEventOnce, IListener, INetworkInformation, IState, IUseNetworkState, KeyModifier, MousePressedOptions, MouseSourceType, OrientationState, RafLoopReturns, State, Status, Target, UseDarkOptions, UseDraggableOptions, UseElementBoundingOptions, UseEventEmitterReturn, UseFileDialogOptions, UseFpsOptions, UseFullScreenOptions, UseInfiniteScrollOptions, UseLongPressOptions, UseModifierOptions, UseScriptTagOptions, UseScrollOptions, UseTextDirectionOptions, UseTextDirectionValue, UseTimeoutFnOptions, UseVirtualListItem, UseVirtualListOptions, UseVirtualListReturn, WindowSize, useActiveElement, useClickOutSide as useClickOutside, useClipBorad as useClipboard, useControlled, useCounter, useCustomCompareEffect, useCycleList, useDarkMode, useDebounce, useDebounceFn, useDeepCompareEffect, useDocumentVisibility, useDraggable, useDropZone, useElementBounding, useElementSize, useElementVisibility, useEvent, useEventEmitter, useEventListener, useFavicon, useFileDialog, useFirstMountState, useFocus, _default$2 as useFps, useFullscreen, useGeolocation, useIdle, useInfiniteScroll, useIntersectionObserver, useInterval, useIsomorphicLayoutEffect, useKeyModifier, useLatest, useLocalStorage, useLongPress, _default$3 as useMediaDevices, useMediaQuery, useMount, useMountedState, useMouse, useMousePressed, useMutationObserver, useNetwork, useObjectUrl, _default$1 as useOnceEffect, _default as useOnceLayoutEffect, useOnline, useOrientation, usePageLeave, usePermission, usePreferredColorScheme, usePreferredContrast, usePreferredDark, usePrevious, useRafFn, useRafState, useResizeObserver, useScriptTag, useScroll, useScrollLock, useSessionStorage, useTextDirection, useThrottle, useThrottleFn, useTimeout, useTimeoutFn, useTitle, useToggle, useUnmount, useUpdate, _default$5 as useUpdateEffect, _default$4 as useUpdateLayoutEffect, useVirtualList, useWindowScroll, useWindowSize, useWindowsFocus };
753
+ declare function useReducedMotion(defaultState?: boolean): boolean;
754
+
755
+ interface ScrollIntoViewAnimation {
756
+ /** target element alignment relatively to parent based on current axis */
757
+ alignment?: "start" | "end" | "center";
758
+ }
759
+ interface ScrollIntoViewParams {
760
+ /** callback fired after scroll */
761
+ onScrollFinish?: () => void;
762
+ /** duration of scroll in milliseconds */
763
+ duration?: number;
764
+ /** axis of scroll */
765
+ axis?: "x" | "y";
766
+ /** custom mathematical easing function */
767
+ easing?: (t: number) => number;
768
+ /** additional distance between nearest edge and element */
769
+ offset?: number;
770
+ /** indicator if animation may be interrupted by user scrolling */
771
+ cancelable?: boolean;
772
+ /** prevents content jumping in scrolling lists with multiple targets */
773
+ isList?: boolean;
774
+ targetElement: BasicTarget<HTMLElement>;
775
+ scrollElement?: BasicTarget<HTMLElement>;
776
+ }
777
+ declare function useScrollIntoView({ duration, axis, onScrollFinish, easing, offset, cancelable, isList, targetElement, scrollElement, }: ScrollIntoViewParams): {
778
+ scrollIntoView: ({ alignment }?: ScrollIntoViewAnimation) => void;
779
+ cancel: () => void;
780
+ };
781
+
782
+ interface UseStickyParams {
783
+ targetElement: BasicTarget<HTMLElement>;
784
+ scrollElement?: BasicTarget<HTMLElement>;
785
+ /** axis of scroll */
786
+ axis?: "x" | "y";
787
+ /** cover height or width */
788
+ nav: number;
789
+ }
790
+ declare const useSticky: ({ targetElement, scrollElement, axis, nav, }: UseStickyParams) => [
791
+ boolean,
792
+ react__default.Dispatch<react__default.SetStateAction<boolean>>
793
+ ];
794
+
795
+ export { ColorScheme, Contrast, CursorState, GeneralPermissionDescriptor, IDisposable, IEvent, IEventOnce, IListener, INetworkInformation, IState, IUseNetworkState, KeyModifier, MousePressedOptions, MouseSourceType, OrientationState, RafLoopReturns, ScrollIntoViewAnimation, ScrollIntoViewParams, State, Status, Target, UseDarkOptions, UseDraggableOptions, UseElementBoundingOptions, UseEventEmitterReturn, UseFileDialogOptions, UseFpsOptions, UseFullScreenOptions, UseInfiniteScrollOptions, UseLongPressOptions, UseModifierOptions, UseScriptTagOptions, UseScrollOptions, UseStickyParams, UseTextDirectionOptions, UseTextDirectionValue, UseTimeoutFnOptions, UseVirtualListItem, UseVirtualListOptions, UseVirtualListReturn, WindowSize, useActiveElement, useClickOutSide as useClickOutside, useClipBorad as useClipboard, useControlled, useCounter, useCustomCompareEffect, useCycleList, useDarkMode, useDebounce, useDebounceFn, useDeepCompareEffect, useDocumentVisibility, useDraggable, useDropZone, useElementBounding, useElementSize, useElementVisibility, useEvent, useEventEmitter, useEventListener, useFavicon, useFileDialog, useFirstMountState, useFocus, _default$2 as useFps, useFullscreen, useGeolocation, useIdle, useInfiniteScroll, useIntersectionObserver, useInterval, useIsomorphicLayoutEffect, useKeyModifier, useLatest, useLocalStorage, useLongPress, _default$3 as useMediaDevices, useMediaQuery, useMount, useMountedState, useMouse, useMousePressed, useMutationObserver, useNetwork, useObjectUrl, _default$1 as useOnceEffect, _default as useOnceLayoutEffect, useOnline, useOrientation, usePageLeave, usePermission, usePreferredColorScheme, usePreferredContrast, usePreferredDark, usePrevious, useRafFn, useRafState, useReducedMotion, useResizeObserver, useScriptTag, useScroll, useScrollIntoView, useScrollLock, useSessionStorage, useSticky, useTextDirection, useThrottle, useThrottleFn, useTimeout, useTimeoutFn, useTitle, useToggle, useUnmount, useUpdate, _default$5 as useUpdateEffect, _default$4 as useUpdateLayoutEffect, useVirtualList, useWindowScroll, useWindowSize, useWindowsFocus };
package/dist/index.mjs CHANGED
@@ -123,7 +123,7 @@ function useStorage(key, defaults, getStorage, options = {}) {
123
123
  }
124
124
  const type = guessSerializerType(defaults);
125
125
  const serializer = (_a = options.serializer) != null ? _a : StorageSerializers[type];
126
- const getStoredValue = () => {
126
+ const getStoredValue = useEvent(() => {
127
127
  try {
128
128
  const raw = storage == null ? void 0 : storage.getItem(key);
129
129
  if (raw !== void 0 && raw !== null) {
@@ -135,11 +135,11 @@ function useStorage(key, defaults, getStorage, options = {}) {
135
135
  } catch (e) {
136
136
  onError(e);
137
137
  }
138
- };
139
- const [state, setState] = useState(() => getStoredValue());
140
- useUpdateEffect(() => {
138
+ });
139
+ const [state, setState] = useState(defaults);
140
+ useEffect(() => {
141
141
  setState(getStoredValue());
142
- }, [key]);
142
+ }, [getStoredValue, key]);
143
143
  const updateState = useEvent(
144
144
  (valOrFunc) => {
145
145
  const currentState = isFunction(valOrFunc) ? valOrFunc(state) : valOrFunc;
@@ -197,12 +197,12 @@ function useInterval(callback, delay, options) {
197
197
  }
198
198
 
199
199
  const getInitialState = (query, defaultState) => {
200
- if (isBrowser) {
201
- return window.matchMedia(query).matches;
202
- }
203
200
  if (defaultState !== void 0) {
204
201
  return defaultState;
205
202
  }
203
+ if (isBrowser) {
204
+ return window.matchMedia(query).matches;
205
+ }
206
206
  if (process.env.NODE_ENV !== "production") {
207
207
  console.warn(
208
208
  "`useMediaQuery` When server side rendering, defaultState should be defined to prevent a hydration mismatches."
@@ -254,21 +254,24 @@ function useDarkMode(options = {}) {
254
254
  const prefersDarkMode = usePreferredDark(false);
255
255
  const value = initialValue ? initialValue : prefersDarkMode ? "dark" : "light";
256
256
  const [dark, setDark] = useStorage(storageKey, value, storage);
257
- useEffect(() => {
258
- const element = window == null ? void 0 : window.document.querySelector(selector);
259
- if (!element) {
260
- return;
261
- }
262
- if (attribute === "class") {
263
- dark && element.classList.add(dark);
264
- } else {
265
- dark && element.setAttribute(attribute, dark);
266
- }
267
- return () => {
268
- dark && (element == null ? void 0 : element.classList.remove(dark));
269
- };
270
- }, [attribute, dark, selector]);
271
- return [dark, setDark];
257
+ const wrappedSetDark = useCallback(
258
+ (latestDark) => {
259
+ const element = window == null ? void 0 : window.document.querySelector(selector);
260
+ if (!element) {
261
+ return;
262
+ }
263
+ if (attribute === "class") {
264
+ latestDark && element.classList.add(latestDark);
265
+ dark && element.classList.remove(dark);
266
+ } else {
267
+ latestDark && element.setAttribute(attribute, latestDark);
268
+ dark && element.removeAttribute(attribute);
269
+ }
270
+ setDark(latestDark);
271
+ },
272
+ [attribute, dark, selector, setDark]
273
+ );
274
+ return [dark, wrappedSetDark];
272
275
  }
273
276
 
274
277
  function useMount(fn) {
@@ -536,8 +539,8 @@ function useDeepCompareEffect(effect, deps) {
536
539
 
537
540
  function useEventListener(eventName, handler, element, options) {
538
541
  const savedHandler = useLatest(handler);
542
+ const targetElement = getTargetElement(element, window);
539
543
  useDeepCompareEffect(() => {
540
- const targetElement = getTargetElement(element, window);
541
544
  if (!(targetElement && targetElement.addEventListener)) {
542
545
  return;
543
546
  }
@@ -546,7 +549,7 @@ function useEventListener(eventName, handler, element, options) {
546
549
  return () => {
547
550
  off(targetElement, eventName, eventListener);
548
551
  };
549
- }, [eventName, element, options, savedHandler]);
552
+ }, [eventName, targetElement, options, savedHandler]);
550
553
  }
551
554
 
552
555
  function useCounter(initialValue = 0, max = null, min = null) {
@@ -690,20 +693,20 @@ function useFavicon(href, baseUrl = "", rel = "icon") {
690
693
  function useMutationObserver(callback, target, options = {}) {
691
694
  const callbackRef = useLatest(callback);
692
695
  const observerRef = useRef();
696
+ const element = getTargetElement(target);
693
697
  const stop = useCallback(() => {
694
698
  if (observerRef.current) {
695
699
  observerRef.current.disconnect();
696
700
  }
697
701
  }, []);
698
702
  useDeepCompareEffect(() => {
699
- const element = getTargetElement(target);
700
703
  if (!element) {
701
704
  return;
702
705
  }
703
706
  observerRef.current = new MutationObserver(callbackRef.current);
704
707
  observerRef.current.observe(element, options);
705
708
  return stop;
706
- }, [options]);
709
+ }, [options, element]);
707
710
  return stop;
708
711
  }
709
712
 
@@ -1488,13 +1491,13 @@ function useOrientation(initialState = defaultState) {
1488
1491
  function useIntersectionObserver(target, callback, options = {}) {
1489
1492
  const savedCallback = useLatest(callback);
1490
1493
  const observerRef = useRef();
1494
+ const element = getTargetElement(target);
1491
1495
  const stop = useCallback(() => {
1492
1496
  if (observerRef.current) {
1493
1497
  observerRef.current.disconnect();
1494
1498
  }
1495
1499
  }, []);
1496
1500
  useDeepCompareEffect(() => {
1497
- const element = getTargetElement(target);
1498
1501
  if (!element) {
1499
1502
  return;
1500
1503
  }
@@ -1504,7 +1507,7 @@ function useIntersectionObserver(target, callback, options = {}) {
1504
1507
  );
1505
1508
  observerRef.current.observe(element);
1506
1509
  return stop;
1507
- }, [options]);
1510
+ }, [options, element]);
1508
1511
  return stop;
1509
1512
  }
1510
1513
 
@@ -1544,20 +1547,20 @@ function useDocumentVisibility() {
1544
1547
  function useResizeObserver(target, callback, options = {}) {
1545
1548
  const savedCallback = useLatest(callback);
1546
1549
  const observerRef = useRef();
1550
+ const element = getTargetElement(target);
1547
1551
  const stop = useCallback(() => {
1548
1552
  if (observerRef.current) {
1549
1553
  observerRef.current.disconnect();
1550
1554
  }
1551
1555
  }, []);
1552
1556
  useDeepCompareEffect(() => {
1553
- const element = getTargetElement(target);
1554
1557
  if (!element) {
1555
1558
  return;
1556
1559
  }
1557
1560
  observerRef.current = new ResizeObserver(savedCallback.current);
1558
1561
  observerRef.current.observe(element, options);
1559
1562
  return stop;
1560
- }, [options]);
1563
+ }, [options, element]);
1561
1564
  return stop;
1562
1565
  }
1563
1566
 
@@ -1782,11 +1785,11 @@ function useInfiniteScroll(target, onLoadMore, options = {}) {
1782
1785
  [direction]: (_b = options.distance) != null ? _b : 0
1783
1786
  }, options.offset)
1784
1787
  }));
1788
+ const element = getTargetElement(target);
1785
1789
  const di = state[3][direction];
1786
1790
  useUpdateEffect(() => {
1787
1791
  const fn = () => __async$1(this, null, function* () {
1788
1792
  var _a2, _b2;
1789
- const element = getTargetElement(target);
1790
1793
  const previous = {
1791
1794
  height: (_a2 = element == null ? void 0 : element.scrollHeight) != null ? _a2 : 0,
1792
1795
  width: (_b2 = element == null ? void 0 : element.scrollWidth) != null ? _b2 : 0
@@ -1800,7 +1803,7 @@ function useInfiniteScroll(target, onLoadMore, options = {}) {
1800
1803
  }
1801
1804
  });
1802
1805
  fn();
1803
- }, [di, options.preserveScrollPosition]);
1806
+ }, [di, options.preserveScrollPosition, element]);
1804
1807
  }
1805
1808
 
1806
1809
  const defaultEvents = [
@@ -1837,6 +1840,7 @@ function useMousePressed(target, options = {}) {
1837
1840
  const { touch = true, drag = true, initialValue = false } = options;
1838
1841
  const [pressed, setPressed] = useState(initialValue);
1839
1842
  const [sourceType, setSourceType] = useState(null);
1843
+ const element = getTargetElement(target);
1840
1844
  const onPressed = useCallback(
1841
1845
  (srcType) => () => {
1842
1846
  setPressed(true);
@@ -1851,8 +1855,7 @@ function useMousePressed(target, options = {}) {
1851
1855
  useEventListener("mousedown", onPressed("mouse"), target, { passive: true });
1852
1856
  useEventListener("mouseleave", onReleased, () => window, { passive: true });
1853
1857
  useEventListener("mouseup", onReleased, () => window, { passive: true });
1854
- useMount(() => {
1855
- const element = getTargetElement(target);
1858
+ useEffect(() => {
1856
1859
  if (drag) {
1857
1860
  element == null ? void 0 : element.addEventListener("dragstart", onPressed("mouse"), {
1858
1861
  passive: true
@@ -1887,7 +1890,7 @@ function useMousePressed(target, options = {}) {
1887
1890
  element == null ? void 0 : element.removeEventListener("touchcancel", onReleased);
1888
1891
  }
1889
1892
  };
1890
- });
1893
+ }, [drag, onPressed, onReleased, element, touch]);
1891
1894
  return [pressed, sourceType];
1892
1895
  }
1893
1896
 
@@ -1904,28 +1907,25 @@ function preventDefault(rawEvent) {
1904
1907
  function useScrollLock(target, initialState = false) {
1905
1908
  const [locked, setLocked] = useState(initialState);
1906
1909
  const initialOverflowRef = useRef("scroll");
1907
- useMount(() => {
1908
- const element = getTargetElement(target);
1910
+ const element = getTargetElement(target);
1911
+ useEffect(() => {
1909
1912
  if (element) {
1910
1913
  initialOverflowRef.current = element.style.overflow;
1911
1914
  if (locked) {
1912
1915
  element.style.overflow = "hidden";
1913
1916
  }
1914
1917
  }
1915
- });
1918
+ }, [locked, element]);
1916
1919
  const lock = useEvent(() => {
1917
- const element = getTargetElement(target);
1918
1920
  if (!element || locked) {
1919
1921
  return;
1920
1922
  }
1921
1923
  if (isIOS) {
1922
1924
  element.addEventListener("touchmove", preventDefault, { passive: false });
1923
1925
  }
1924
- element.style.overflow = "hidden";
1925
1926
  setLocked(true);
1926
1927
  });
1927
1928
  const unlock = useEvent(() => {
1928
- const element = getTargetElement(target);
1929
1929
  if (!element || !locked) {
1930
1930
  return;
1931
1931
  }
@@ -2472,4 +2472,237 @@ var useOnceEffect = createOnceEffect(useEffect);
2472
2472
 
2473
2473
  var useOnceLayoutEffect = createOnceEffect(useLayoutEffect);
2474
2474
 
2475
- export { useActiveElement, useClickOutSide as useClickOutside, useClipBorad as useClipboard, useControlled, useCounter, useCustomCompareEffect, useCycleList, useDarkMode, useDebounce, useDebounceFn, useDeepCompareEffect, useDocumentVisibility, useDraggable, useDropZone, useElementBounding, useElementSize, useElementVisibility, useEvent, useEventEmitter, useEventListener, useFavicon, useFileDialog, useFirstMountState, useFocus, useFps$1 as useFps, useFullscreen, useGeolocation, useIdle, useInfiniteScroll, useIntersectionObserver, useInterval, useIsomorphicLayoutEffect, useKeyModifier, useLatest, useLocalStorage, useLongPress, useMediaDevices$1 as useMediaDevices, useMediaQuery, useMount, useMountedState, useMouse, useMousePressed, useMutationObserver, useNetwork, useObjectUrl, useOnceEffect, useOnceLayoutEffect, useOnline, useOrientation, usePageLeave, usePermission, usePreferredColorScheme, usePreferredContrast, usePreferredDark, usePrevious, useRafFn, useRafState, useResizeObserver, useScriptTag, useScroll, useScrollLock, useSessionStorage, useTextDirection, useThrottle, useThrottleFn, useTimeout, useTimeoutFn, useTitle, useToggle, useUnmount, useUpdate, useUpdateEffect, useUpdateLayoutEffect, useVirtualList, useWindowScroll, useWindowSize, useWindowsFocus };
2475
+ function useReducedMotion(defaultState) {
2476
+ return useMediaQuery("(prefers-reduced-motion: reduce)", defaultState);
2477
+ }
2478
+
2479
+ const setScrollParam = ({
2480
+ axis,
2481
+ parent,
2482
+ distance
2483
+ }) => {
2484
+ if (!parent && typeof document === "undefined") {
2485
+ return;
2486
+ }
2487
+ const method = axis === "y" ? "scrollTop" : "scrollLeft";
2488
+ if (parent) {
2489
+ parent[method] = distance;
2490
+ } else {
2491
+ const { body, documentElement } = document;
2492
+ body[method] = distance;
2493
+ documentElement[method] = distance;
2494
+ }
2495
+ };
2496
+ const isScrollElement = (axis, node) => {
2497
+ if (!node) {
2498
+ return false;
2499
+ }
2500
+ const AXIS = axis === "x" ? "X" : "Y";
2501
+ return getComputedStyle(node)[`overflow${AXIS}`] === "auto" || getComputedStyle(node)[`overflow${AXIS}`] === "scroll";
2502
+ };
2503
+ const cache = /* @__PURE__ */ new Map();
2504
+ const getScrollParent = (axis, node) => {
2505
+ if (!node || !node.parentElement) {
2506
+ return null;
2507
+ }
2508
+ if (cache.has(node)) {
2509
+ return cache.get(node) || null;
2510
+ }
2511
+ let parent = node.parentElement;
2512
+ while (parent && !isScrollElement(axis, parent)) {
2513
+ parent = parent.parentElement;
2514
+ }
2515
+ if (parent) {
2516
+ cache.set(node, parent);
2517
+ }
2518
+ return parent;
2519
+ };
2520
+ const getScrollStart = ({
2521
+ axis,
2522
+ parent
2523
+ }) => {
2524
+ if (!parent && typeof document === "undefined") {
2525
+ return 0;
2526
+ }
2527
+ const method = axis === "y" ? "scrollTop" : "scrollLeft";
2528
+ if (parent) {
2529
+ return parent[method];
2530
+ }
2531
+ const { body, documentElement } = document;
2532
+ return body[method] + documentElement[method];
2533
+ };
2534
+
2535
+ const easeInOutQuad = (t) => t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t;
2536
+
2537
+ const getRelativePosition = ({
2538
+ axis,
2539
+ target,
2540
+ parent,
2541
+ alignment,
2542
+ offset,
2543
+ isList
2544
+ }) => {
2545
+ if (!target || !parent && typeof document === "undefined") {
2546
+ return 0;
2547
+ }
2548
+ const isCustomParent = !!parent;
2549
+ const parentElement = parent || document.body;
2550
+ const parentPosition = parentElement.getBoundingClientRect();
2551
+ const targetPosition = target.getBoundingClientRect();
2552
+ const getDiff = (property) => targetPosition[property] - parentPosition[property];
2553
+ if (axis === "y") {
2554
+ const diff = getDiff("top");
2555
+ if (diff === 0) {
2556
+ return 0;
2557
+ }
2558
+ if (alignment === "start") {
2559
+ const distance = diff - offset;
2560
+ const shouldScroll = distance <= targetPosition.height * (isList ? 0 : 1) || !isList;
2561
+ return shouldScroll ? distance : 0;
2562
+ }
2563
+ const parentHeight = isCustomParent ? parentPosition.height : window.innerHeight;
2564
+ if (alignment === "end") {
2565
+ const distance = diff + offset - parentHeight + targetPosition.height;
2566
+ const shouldScroll = distance >= -targetPosition.height * (isList ? 0 : 1) || !isList;
2567
+ return shouldScroll ? distance : 0;
2568
+ }
2569
+ if (alignment === "center") {
2570
+ return diff - parentHeight / 2 + targetPosition.height / 2;
2571
+ }
2572
+ return 0;
2573
+ }
2574
+ if (axis === "x") {
2575
+ const diff = getDiff("left");
2576
+ if (diff === 0) {
2577
+ return 0;
2578
+ }
2579
+ if (alignment === "start") {
2580
+ const distance = diff - offset;
2581
+ const shouldScroll = distance <= targetPosition.width || !isList;
2582
+ return shouldScroll ? distance : 0;
2583
+ }
2584
+ const parentWidth = isCustomParent ? parentPosition.width : window.innerWidth;
2585
+ if (alignment === "end") {
2586
+ const distance = diff + offset - parentWidth + targetPosition.width;
2587
+ const shouldScroll = distance >= -targetPosition.width || !isList;
2588
+ return shouldScroll ? distance : 0;
2589
+ }
2590
+ if (alignment === "center") {
2591
+ return diff - parentWidth / 2 + targetPosition.width / 2;
2592
+ }
2593
+ return 0;
2594
+ }
2595
+ return 0;
2596
+ };
2597
+
2598
+ function useScrollIntoView({
2599
+ duration = 1250,
2600
+ axis = "y",
2601
+ onScrollFinish,
2602
+ easing = easeInOutQuad,
2603
+ offset = 0,
2604
+ cancelable = true,
2605
+ isList = false,
2606
+ targetElement,
2607
+ scrollElement
2608
+ }) {
2609
+ const frameID = useRef(0);
2610
+ const startTime = useRef(0);
2611
+ const shouldStop = useRef(false);
2612
+ const reducedMotion = useReducedMotion(false);
2613
+ const cancel = () => {
2614
+ if (frameID.current) {
2615
+ cancelAnimationFrame(frameID.current);
2616
+ }
2617
+ };
2618
+ const scrollIntoView = useEvent(
2619
+ ({ alignment = "start" } = {}) => {
2620
+ var _a;
2621
+ const element = getTargetElement(targetElement);
2622
+ const parent = getTargetElement(scrollElement) || getScrollParent(axis, element);
2623
+ shouldStop.current = false;
2624
+ if (frameID.current) {
2625
+ cancel();
2626
+ }
2627
+ const start = (_a = getScrollStart({ parent, axis })) != null ? _a : 0;
2628
+ const change = getRelativePosition({
2629
+ parent,
2630
+ target: element,
2631
+ axis,
2632
+ alignment,
2633
+ offset,
2634
+ isList
2635
+ }) - (parent ? 0 : start);
2636
+ const animateScroll = () => {
2637
+ if (startTime.current === 0) {
2638
+ startTime.current = performance.now();
2639
+ }
2640
+ const now = performance.now();
2641
+ const elapsed = now - startTime.current;
2642
+ const t = reducedMotion || duration === 0 ? 1 : elapsed / duration;
2643
+ const distance = start + change * easing(t);
2644
+ setScrollParam({
2645
+ parent,
2646
+ axis,
2647
+ distance
2648
+ });
2649
+ if (!shouldStop.current && t < 1) {
2650
+ frameID.current = requestAnimationFrame(animateScroll);
2651
+ } else {
2652
+ typeof onScrollFinish === "function" && onScrollFinish();
2653
+ startTime.current = 0;
2654
+ frameID.current = 0;
2655
+ cancel();
2656
+ }
2657
+ };
2658
+ animateScroll();
2659
+ }
2660
+ );
2661
+ const handleStop = () => {
2662
+ if (cancelable) {
2663
+ shouldStop.current = true;
2664
+ }
2665
+ };
2666
+ useEventListener("wheel", handleStop, null, { passive: true });
2667
+ useEventListener("touchmove", handleStop, null, { passive: true });
2668
+ useEffect(() => cancel, []);
2669
+ return {
2670
+ scrollIntoView,
2671
+ cancel
2672
+ };
2673
+ }
2674
+
2675
+ const useSticky = ({
2676
+ targetElement,
2677
+ scrollElement,
2678
+ axis = "y",
2679
+ nav = 0
2680
+ }) => {
2681
+ const [isSticky, setSticky] = useState(false);
2682
+ const element = getTargetElement(targetElement);
2683
+ const scrollParent = getTargetElement(scrollElement) || getScrollParent(axis, element);
2684
+ const { run: scrollHandler } = useThrottleFn(() => {
2685
+ if (!element) {
2686
+ return;
2687
+ }
2688
+ const rect = element.getBoundingClientRect();
2689
+ if (axis === "y") {
2690
+ setSticky((rect == null ? void 0 : rect.top) <= nav);
2691
+ } else {
2692
+ setSticky((rect == null ? void 0 : rect.left) <= nav);
2693
+ }
2694
+ }, 50);
2695
+ useEffect(() => {
2696
+ if (!element || !scrollParent) {
2697
+ return;
2698
+ }
2699
+ scrollParent.addEventListener("scroll", scrollHandler);
2700
+ scrollHandler();
2701
+ return () => {
2702
+ scrollParent.removeEventListener("scroll", scrollHandler);
2703
+ };
2704
+ }, [axis, element, scrollHandler, scrollParent]);
2705
+ return [isSticky, setSticky];
2706
+ };
2707
+
2708
+ export { useActiveElement, useClickOutSide as useClickOutside, useClipBorad as useClipboard, useControlled, useCounter, useCustomCompareEffect, useCycleList, useDarkMode, useDebounce, useDebounceFn, useDeepCompareEffect, useDocumentVisibility, useDraggable, useDropZone, useElementBounding, useElementSize, useElementVisibility, useEvent, useEventEmitter, useEventListener, useFavicon, useFileDialog, useFirstMountState, useFocus, useFps$1 as useFps, useFullscreen, useGeolocation, useIdle, useInfiniteScroll, useIntersectionObserver, useInterval, useIsomorphicLayoutEffect, useKeyModifier, useLatest, useLocalStorage, useLongPress, useMediaDevices$1 as useMediaDevices, useMediaQuery, useMount, useMountedState, useMouse, useMousePressed, useMutationObserver, useNetwork, useObjectUrl, useOnceEffect, useOnceLayoutEffect, useOnline, useOrientation, usePageLeave, usePermission, usePreferredColorScheme, usePreferredContrast, usePreferredDark, usePrevious, useRafFn, useRafState, useReducedMotion, useResizeObserver, useScriptTag, useScroll, useScrollIntoView, useScrollLock, useSessionStorage, useSticky, useTextDirection, useThrottle, useThrottleFn, useTimeout, useTimeoutFn, useTitle, useToggle, useUnmount, useUpdate, useUpdateEffect, useUpdateLayoutEffect, useVirtualList, useWindowScroll, useWindowSize, useWindowsFocus };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reactuses/core",
3
- "version": "1.1.5",
3
+ "version": "2.0.1",
4
4
  "main": "./dist/index.cjs",
5
5
  "module": "./dist/index.mjs",
6
6
  "types": "./dist/index.d.ts",