Latest repo

This commit is contained in:
Marc
2025-06-02 16:42:16 +00:00
parent 53ddf1a329
commit cde5fae175
27907 changed files with 3875388 additions and 1 deletions

68
node_modules/@restart/hooks/esm/globals.d.ts generated vendored Normal file
View File

@@ -0,0 +1,68 @@
interface Window {
ResizeObserver: ResizeObserver
}
/**
* The ResizeObserver interface is used to observe changes to Element's content
* rect.
*
* It is modeled after MutationObserver and IntersectionObserver.
*/
interface ResizeObserver {
new (callback: ResizeObserverCallback)
/**
* Adds target to the list of observed elements.
*/
observe: (target: Element) => void
/**
* Removes target from the list of observed elements.
*/
unobserve: (target: Element) => void
/**
* Clears both the observationTargets and activeTargets lists.
*/
disconnect: () => void
}
/**
* This callback delivers ResizeObserver's notifications. It is invoked by a
* broadcast active observations algorithm.
*/
interface ResizeObserverCallback {
(entries: ResizeObserverEntry[], observer: ResizeObserver): void
}
interface ResizeObserverEntry {
/**
* @param target The Element whose size has changed.
*/
new (target: Element)
/**
* The Element whose size has changed.
*/
readonly target: Element
/**
* Element's content rect when ResizeObserverCallback is invoked.
*/
readonly contentRect: DOMRectReadOnly
}
interface DOMRectReadOnly {
fromRect(other: DOMRectInit | undefined): DOMRectReadOnly
readonly x: number
readonly y: number
readonly width: number
readonly height: number
readonly top: number
readonly right: number
readonly bottom: number
readonly left: number
toJSON: () => any
}

14
node_modules/@restart/hooks/esm/index.d.ts generated vendored Normal file
View File

@@ -0,0 +1,14 @@
import useCallbackRef from './useCallbackRef';
import useCommittedRef from './useCommittedRef';
import useEventCallback from './useEventCallback';
import useEventListener from './useEventListener';
import useGlobalListener from './useGlobalListener';
import useInterval from './useInterval';
import useRafInterval from './useRafInterval';
import useMergeState from './useMergeState';
import useMergeStateFromProps from './useMergeStateFromProps';
import useMounted from './useMounted';
import usePrevious from './usePrevious';
import useImage from './useImage';
import useResizeObserver from './useResizeObserver';
export { useCallbackRef, useCommittedRef, useEventCallback, useEventListener, useGlobalListener, useInterval, useRafInterval, useMergeState, useMergeStateFromProps, useMounted, usePrevious, useImage, useResizeObserver, };

14
node_modules/@restart/hooks/esm/index.js generated vendored Normal file
View File

@@ -0,0 +1,14 @@
import useCallbackRef from './useCallbackRef';
import useCommittedRef from './useCommittedRef';
import useEventCallback from './useEventCallback';
import useEventListener from './useEventListener';
import useGlobalListener from './useGlobalListener';
import useInterval from './useInterval';
import useRafInterval from './useRafInterval';
import useMergeState from './useMergeState';
import useMergeStateFromProps from './useMergeStateFromProps';
import useMounted from './useMounted';
import usePrevious from './usePrevious';
import useImage from './useImage';
import useResizeObserver from './useResizeObserver';
export { useCallbackRef, useCommittedRef, useEventCallback, useEventListener, useGlobalListener, useInterval, useRafInterval, useMergeState, useMergeStateFromProps, useMounted, usePrevious, useImage, useResizeObserver };

39
node_modules/@restart/hooks/esm/useAnimationFrame.d.ts generated vendored Normal file
View File

@@ -0,0 +1,39 @@
export interface UseAnimationFrameReturn {
cancel(): void;
/**
* Request for the provided callback to be called on the next animation frame.
* Previously registered callbacks will be cancelled
*/
request(callback: FrameRequestCallback): void;
/**
* Request for the provided callback to be called on the next animation frame.
* Previously registered callbacks can be cancelled by providing `cancelPrevious`
*/
request(cancelPrevious: boolean, callback: FrameRequestCallback): void;
}
/**
* Returns a controller object for requesting and cancelling an animation freame that is properly cleaned up
* once the component unmounts. New requests cancel and replace existing ones.
*
* ```ts
* const [style, setStyle] = useState({});
* const animationFrame = useAnimationFrame();
*
* const handleMouseMove = (e) => {
* animationFrame.request(() => {
* setStyle({ top: e.clientY, left: e.clientY })
* })
* }
*
* const handleMouseUp = () => {
* animationFrame.cancel()
* }
*
* return (
* <div onMouseUp={handleMouseUp} onMouseMove={handleMouseMove}>
* <Ball style={style} />
* </div>
* )
* ```
*/
export default function useAnimationFrame(): UseAnimationFrameReturn;

47
node_modules/@restart/hooks/esm/useAnimationFrame.js generated vendored Normal file
View File

@@ -0,0 +1,47 @@
import { useRef } from 'react';
import useMounted from './useMounted';
import useStableMemo from './useStableMemo';
import useWillUnmount from './useWillUnmount';
/**
* Returns a controller object for requesting and cancelling an animation freame that is properly cleaned up
* once the component unmounts. New requests cancel and replace existing ones.
*
* ```ts
* const [style, setStyle] = useState({});
* const animationFrame = useAnimationFrame();
*
* const handleMouseMove = (e) => {
* animationFrame.request(() => {
* setStyle({ top: e.clientY, left: e.clientY })
* })
* }
*
* const handleMouseUp = () => {
* animationFrame.cancel()
* }
*
* return (
* <div onMouseUp={handleMouseUp} onMouseMove={handleMouseMove}>
* <Ball style={style} />
* </div>
* )
* ```
*/
export default function useAnimationFrame() {
const isMounted = useMounted();
const handle = useRef();
const cancel = () => {
if (handle.current != null) {
cancelAnimationFrame(handle.current);
}
};
useWillUnmount(cancel);
return useStableMemo(() => ({
request(cancelPrevious, fn) {
if (!isMounted()) return;
if (cancelPrevious) cancel();
handle.current = requestAnimationFrame(fn || cancelPrevious);
},
cancel
}), []);
}

35
node_modules/@restart/hooks/esm/useBreakpoint.d.ts generated vendored Normal file
View File

@@ -0,0 +1,35 @@
export type BreakpointDirection = 'up' | 'down' | true;
export type BreakpointMap<TKey extends string> = Partial<Record<TKey, BreakpointDirection>>;
/**
* Create a responsive hook we a set of breakpoint names and widths.
* You can use any valid css units as well as a numbers (for pixels).
*
* **NOTE:** The object key order is important! it's assumed to be in order from smallest to largest
*
* ```ts
* const useBreakpoint = createBreakpointHook({
* xs: 0,
* sm: 576,
* md: 768,
* lg: 992,
* xl: 1200,
* })
* ```
*
* **Watch out!** using string values will sometimes construct media queries using css `calc()` which
* is NOT supported in media queries by all browsers at the moment. use numbers for
* the widest range of browser support.
*
* @param breakpointValues A object hash of names to breakpoint dimensions
*/
export declare function createBreakpointHook<TKey extends string>(breakpointValues: Record<TKey, string | number>): {
(breakpointMap: BreakpointMap<TKey>, window?: Window): boolean;
(breakpoint: TKey, direction?: BreakpointDirection, window?: Window): boolean;
};
export type DefaultBreakpoints = 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'xxl';
export type DefaultBreakpointMap = BreakpointMap<DefaultBreakpoints>;
declare const useBreakpoint: {
(breakpointMap: Partial<Record<DefaultBreakpoints, BreakpointDirection>>, window?: Window): boolean;
(breakpoint: DefaultBreakpoints, direction?: BreakpointDirection, window?: Window): boolean;
};
export default useBreakpoint;

116
node_modules/@restart/hooks/esm/useBreakpoint.js generated vendored Normal file
View File

@@ -0,0 +1,116 @@
import useMediaQuery from './useMediaQuery';
import { useMemo } from 'react';
/**
* Create a responsive hook we a set of breakpoint names and widths.
* You can use any valid css units as well as a numbers (for pixels).
*
* **NOTE:** The object key order is important! it's assumed to be in order from smallest to largest
*
* ```ts
* const useBreakpoint = createBreakpointHook({
* xs: 0,
* sm: 576,
* md: 768,
* lg: 992,
* xl: 1200,
* })
* ```
*
* **Watch out!** using string values will sometimes construct media queries using css `calc()` which
* is NOT supported in media queries by all browsers at the moment. use numbers for
* the widest range of browser support.
*
* @param breakpointValues A object hash of names to breakpoint dimensions
*/
export function createBreakpointHook(breakpointValues) {
const names = Object.keys(breakpointValues);
function and(query, next) {
if (query === next) {
return next;
}
return query ? `${query} and ${next}` : next;
}
function getNext(breakpoint) {
return names[Math.min(names.indexOf(breakpoint) + 1, names.length - 1)];
}
function getMaxQuery(breakpoint) {
const next = getNext(breakpoint);
let value = breakpointValues[next];
if (typeof value === 'number') value = `${value - 0.2}px`;else value = `calc(${value} - 0.2px)`;
return `(max-width: ${value})`;
}
function getMinQuery(breakpoint) {
let value = breakpointValues[breakpoint];
if (typeof value === 'number') {
value = `${value}px`;
}
return `(min-width: ${value})`;
}
/**
* Match a set of breakpoints
*
* ```tsx
* const MidSizeOnly = () => {
* const isMid = useBreakpoint({ lg: 'down', sm: 'up' });
*
* if (isMid) return <div>On a Reasonable sized Screen!</div>
* return null;
* }
* ```
* @param breakpointMap An object map of breakpoints and directions, queries are constructed using "and" to join
* breakpoints together
* @param window Optionally specify the target window to match against (useful when rendering into iframes)
*/
/**
* Match a single breakpoint exactly, up, or down.
*
* ```tsx
* const PhoneOnly = () => {
* const isSmall = useBreakpoint('sm', 'down');
*
* if (isSmall) return <div>On a Small Screen!</div>
* return null;
* }
* ```
*
* @param breakpoint The breakpoint key
* @param direction A direction 'up' for a max, 'down' for min, true to match only the breakpoint
* @param window Optionally specify the target window to match against (useful when rendering into iframes)
*/
function useBreakpoint(breakpointOrMap, direction, window) {
let breakpointMap;
if (typeof breakpointOrMap === 'object') {
breakpointMap = breakpointOrMap;
window = direction;
direction = true;
} else {
direction = direction || true;
breakpointMap = {
[breakpointOrMap]: direction
};
}
let query = useMemo(() => Object.entries(breakpointMap).reduce((query, [key, direction]) => {
if (direction === 'up' || direction === true) {
query = and(query, getMinQuery(key));
}
if (direction === 'down' || direction === true) {
query = and(query, getMaxQuery(key));
}
return query;
}, ''), [JSON.stringify(breakpointMap)]);
return useMediaQuery(query, window);
}
return useBreakpoint;
}
const useBreakpoint = createBreakpointHook({
xs: 0,
sm: 576,
md: 768,
lg: 992,
xl: 1200,
xxl: 1400
});
export default useBreakpoint;

28
node_modules/@restart/hooks/esm/useCallbackRef.d.ts generated vendored Normal file
View File

@@ -0,0 +1,28 @@
/**
* A convenience hook around `useState` designed to be paired with
* the component [callback ref](https://reactjs.org/docs/refs-and-the-dom.html#callback-refs) api.
* Callback refs are useful over `useRef()` when you need to respond to the ref being set
* instead of lazily accessing it in an effect.
*
* ```ts
* const [element, attachRef] = useCallbackRef<HTMLDivElement>()
*
* useEffect(() => {
* if (!element) return
*
* const calendar = new FullCalendar.Calendar(element)
*
* return () => {
* calendar.destroy()
* }
* }, [element])
*
* return <div ref={attachRef} />
* ```
*
* @category refs
*/
export default function useCallbackRef<TValue = unknown>(): [
TValue | null,
(ref: TValue | null) => void
];

29
node_modules/@restart/hooks/esm/useCallbackRef.js generated vendored Normal file
View File

@@ -0,0 +1,29 @@
import { useState } from 'react';
/**
* A convenience hook around `useState` designed to be paired with
* the component [callback ref](https://reactjs.org/docs/refs-and-the-dom.html#callback-refs) api.
* Callback refs are useful over `useRef()` when you need to respond to the ref being set
* instead of lazily accessing it in an effect.
*
* ```ts
* const [element, attachRef] = useCallbackRef<HTMLDivElement>()
*
* useEffect(() => {
* if (!element) return
*
* const calendar = new FullCalendar.Calendar(element)
*
* return () => {
* calendar.destroy()
* }
* }, [element])
*
* return <div ref={attachRef} />
* ```
*
* @category refs
*/
export default function useCallbackRef() {
return useState(null);
}

12
node_modules/@restart/hooks/esm/useCommittedRef.d.ts generated vendored Normal file
View File

@@ -0,0 +1,12 @@
/// <reference types="react" />
/**
* Creates a `Ref` whose value is updated in an effect, ensuring the most recent
* value is the one rendered with. Generally only required for Concurrent mode usage
* where previous work in `render()` may be discarded before being used.
*
* This is safe to access in an event handler.
*
* @param value The `Ref` value
*/
declare function useCommittedRef<TValue>(value: TValue): React.MutableRefObject<TValue>;
export default useCommittedRef;

19
node_modules/@restart/hooks/esm/useCommittedRef.js generated vendored Normal file
View File

@@ -0,0 +1,19 @@
import { useEffect, useRef } from 'react';
/**
* Creates a `Ref` whose value is updated in an effect, ensuring the most recent
* value is the one rendered with. Generally only required for Concurrent mode usage
* where previous work in `render()` may be discarded before being used.
*
* This is safe to access in an event handler.
*
* @param value The `Ref` value
*/
function useCommittedRef(value) {
const ref = useRef(value);
useEffect(() => {
ref.current = value;
}, [value]);
return ref;
}
export default useCommittedRef;

26
node_modules/@restart/hooks/esm/useCustomEffect.d.ts generated vendored Normal file
View File

@@ -0,0 +1,26 @@
import { DependencyList, EffectCallback } from 'react';
export type EffectHook = (effect: EffectCallback, deps?: DependencyList) => void;
export type IsEqual<TDeps extends DependencyList> = (nextDeps: TDeps, prevDeps: TDeps) => boolean;
export type CustomEffectOptions<TDeps extends DependencyList> = {
isEqual: IsEqual<TDeps>;
effectHook?: EffectHook;
};
/**
* a useEffect() hook with customized depedency comparision
*
* @param effect The effect callback
* @param dependencies A list of dependencies
* @param isEqual A function comparing the next and previous dependencyLists
*/
declare function useCustomEffect<TDeps extends DependencyList = DependencyList>(effect: EffectCallback, dependencies: TDeps, isEqual: IsEqual<TDeps>): void;
/**
* a useEffect() hook with customized depedency comparision
*
* @param effect The effect callback
* @param dependencies A list of dependencies
* @param options
* @param options.isEqual A function comparing the next and previous dependencyLists
* @param options.effectHook the underlying effect hook used, defaults to useEffect
*/
declare function useCustomEffect<TDeps extends DependencyList = DependencyList>(effect: EffectCallback, dependencies: TDeps, options: CustomEffectOptions<TDeps>): void;
export default useCustomEffect;

51
node_modules/@restart/hooks/esm/useCustomEffect.js generated vendored Normal file
View File

@@ -0,0 +1,51 @@
import { useRef, useEffect, useDebugValue } from 'react';
import useMounted from './useMounted';
/**
* a useEffect() hook with customized depedency comparision
*
* @param effect The effect callback
* @param dependencies A list of dependencies
* @param isEqual A function comparing the next and previous dependencyLists
*/
/**
* a useEffect() hook with customized depedency comparision
*
* @param effect The effect callback
* @param dependencies A list of dependencies
* @param options
* @param options.isEqual A function comparing the next and previous dependencyLists
* @param options.effectHook the underlying effect hook used, defaults to useEffect
*/
function useCustomEffect(effect, dependencies, isEqualOrOptions) {
const isMounted = useMounted();
const {
isEqual,
effectHook = useEffect
} = typeof isEqualOrOptions === 'function' ? {
isEqual: isEqualOrOptions
} : isEqualOrOptions;
const dependenciesRef = useRef();
dependenciesRef.current = dependencies;
const cleanupRef = useRef(null);
effectHook(() => {
// If the ref the is `null` it's either the first effect or the last effect
// ran and was cleared, meaning _this_ update should run, b/c the equality
// check failed on in the cleanup of the last effect.
if (cleanupRef.current === null) {
const cleanup = effect();
cleanupRef.current = () => {
if (isMounted() && isEqual(dependenciesRef.current, dependencies)) {
return;
}
cleanupRef.current = null;
if (cleanup) cleanup();
};
}
return cleanupRef.current;
});
useDebugValue(effect);
}
export default useCustomEffect;

View File

@@ -0,0 +1,32 @@
export interface UseDebouncedCallbackOptions {
wait: number;
leading?: boolean;
trailing?: boolean;
maxWait?: number;
}
export interface UseDebouncedCallbackOptionsLeading extends UseDebouncedCallbackOptions {
leading: true;
}
/**
* Creates a debounced function that will invoke the input function after the
* specified wait.
*
* > Heads up! debounced functions are not pure since they are called in a timeout
* > Don't call them inside render.
*
* @param fn a function that will be debounced
* @param waitOrOptions a wait in milliseconds or a debounce configuration
*/
declare function useDebouncedCallback<TCallback extends (...args: any[]) => any>(fn: TCallback, options: UseDebouncedCallbackOptionsLeading): (...args: Parameters<TCallback>) => ReturnType<TCallback>;
/**
* Creates a debounced function that will invoke the input function after the
* specified wait.
*
* > Heads up! debounced functions are not pure since they are called in a timeout
* > Don't call them inside render.
*
* @param fn a function that will be debounced
* @param waitOrOptions a wait in milliseconds or a debounce configuration
*/
declare function useDebouncedCallback<TCallback extends (...args: any[]) => any>(fn: TCallback, waitOrOptions: number | UseDebouncedCallbackOptions): (...args: Parameters<TCallback>) => ReturnType<TCallback> | undefined;
export default useDebouncedCallback;

131
node_modules/@restart/hooks/esm/useDebouncedCallback.js generated vendored Normal file
View File

@@ -0,0 +1,131 @@
import { useMemo, useRef } from 'react';
import useTimeout from './useTimeout';
import useEventCallback from './useEventCallback';
import useWillUnmount from './useWillUnmount';
/**
* Creates a debounced function that will invoke the input function after the
* specified wait.
*
* > Heads up! debounced functions are not pure since they are called in a timeout
* > Don't call them inside render.
*
* @param fn a function that will be debounced
* @param waitOrOptions a wait in milliseconds or a debounce configuration
*/
/**
* Creates a debounced function that will invoke the input function after the
* specified wait.
*
* > Heads up! debounced functions are not pure since they are called in a timeout
* > Don't call them inside render.
*
* @param fn a function that will be debounced
* @param waitOrOptions a wait in milliseconds or a debounce configuration
*/
function useDebouncedCallback(fn, waitOrOptions) {
const lastCallTimeRef = useRef(null);
const lastInvokeTimeRef = useRef(0);
const returnValueRef = useRef();
const isTimerSetRef = useRef(false);
const lastArgsRef = useRef(null);
// Use any to bypass type issue with setTimeout.
const timerRef = useRef(0);
const handleCallback = useEventCallback(fn);
const {
wait,
maxWait,
leading = false,
trailing = true
} = typeof waitOrOptions === 'number' ? {
wait: waitOrOptions
} : waitOrOptions;
const timeout = useTimeout();
useWillUnmount(() => {
clearTimeout(timerRef.current);
isTimerSetRef.current = false;
});
return useMemo(() => {
const hasMaxWait = !!maxWait;
function leadingEdge(time) {
// Reset any `maxWait` timer.
lastInvokeTimeRef.current = time;
// Start the timer for the trailing edge.
isTimerSetRef.current = true;
timeout.set(timerExpired, wait);
if (!leading) {
return returnValueRef.current;
}
return invokeFunc(time);
}
function trailingEdge(time) {
isTimerSetRef.current = false;
// Only invoke if we have `lastArgs` which means `func` has been
// debounced at least once.
if (trailing && lastArgsRef.current) {
return invokeFunc(time);
}
lastArgsRef.current = null;
return returnValueRef.current;
}
function timerExpired() {
var _lastCallTimeRef$curr;
var time = Date.now();
if (shouldInvoke(time)) {
return trailingEdge(time);
}
const timeSinceLastCall = time - ((_lastCallTimeRef$curr = lastCallTimeRef.current) != null ? _lastCallTimeRef$curr : 0);
const timeSinceLastInvoke = time - lastInvokeTimeRef.current;
const timeWaiting = wait - timeSinceLastCall;
// Restart the timer.
timeout.set(timerExpired, hasMaxWait ? Math.min(timeWaiting, maxWait - timeSinceLastInvoke) : timeWaiting);
}
function invokeFunc(time) {
var _lastArgsRef$current;
const args = (_lastArgsRef$current = lastArgsRef.current) != null ? _lastArgsRef$current : [];
lastArgsRef.current = null;
lastInvokeTimeRef.current = time;
const retValue = handleCallback(...args);
returnValueRef.current = retValue;
return retValue;
}
function shouldInvoke(time) {
var _lastCallTimeRef$curr2;
const timeSinceLastCall = time - ((_lastCallTimeRef$curr2 = lastCallTimeRef.current) != null ? _lastCallTimeRef$curr2 : 0);
const timeSinceLastInvoke = time - lastInvokeTimeRef.current;
// Either this is the first call, activity has stopped and we're at the
// trailing edge, the system time has gone backwards and we're treating
// it as the trailing edge, or we've hit the `maxWait` limit.
return lastCallTimeRef.current === null || timeSinceLastCall >= wait || timeSinceLastCall < 0 || hasMaxWait && timeSinceLastInvoke >= maxWait;
}
return (...args) => {
const time = Date.now();
const isInvoking = shouldInvoke(time);
lastArgsRef.current = args;
lastCallTimeRef.current = time;
if (isInvoking) {
if (!isTimerSetRef.current) {
return leadingEdge(lastCallTimeRef.current);
}
if (hasMaxWait) {
// Handle invocations in a tight loop.
isTimerSetRef.current = true;
timerRef.current = setTimeout(timerExpired, wait);
return invokeFunc(lastCallTimeRef.current);
}
}
if (!isTimerSetRef.current) {
isTimerSetRef.current = true;
timerRef.current = setTimeout(timerExpired, wait);
}
return returnValueRef.current;
};
}, [handleCallback, wait, maxWait, leading, trailing]);
}
export default useDebouncedCallback;

18
node_modules/@restart/hooks/esm/useDebouncedState.d.ts generated vendored Normal file
View File

@@ -0,0 +1,18 @@
import { Dispatch, SetStateAction } from 'react';
import { UseDebouncedCallbackOptions } from './useDebouncedCallback';
/**
* Similar to `useState`, except the setter function is debounced by
* the specified delay. Unlike `useState`, the returned setter is not "pure" having
* the side effect of scheduling an update in a timeout, which makes it unsafe to call
* inside of the component render phase.
*
* ```ts
* const [value, setValue] = useDebouncedState('test', 500)
*
* setValue('test2')
* ```
*
* @param initialState initial state value
* @param delayOrOptions The milliseconds delay before a new value is set, or options object
*/
export default function useDebouncedState<T>(initialState: T | (() => T), delayOrOptions: number | UseDebouncedCallbackOptions): [T, Dispatch<SetStateAction<T>>];

23
node_modules/@restart/hooks/esm/useDebouncedState.js generated vendored Normal file
View File

@@ -0,0 +1,23 @@
import { useState } from 'react';
import useDebouncedCallback from './useDebouncedCallback';
/**
* Similar to `useState`, except the setter function is debounced by
* the specified delay. Unlike `useState`, the returned setter is not "pure" having
* the side effect of scheduling an update in a timeout, which makes it unsafe to call
* inside of the component render phase.
*
* ```ts
* const [value, setValue] = useDebouncedState('test', 500)
*
* setValue('test2')
* ```
*
* @param initialState initial state value
* @param delayOrOptions The milliseconds delay before a new value is set, or options object
*/
export default function useDebouncedState(initialState, delayOrOptions) {
const [state, setState] = useState(initialState);
const debouncedSetState = useDebouncedCallback(setState, delayOrOptions);
return [state, debouncedSetState];
}

15
node_modules/@restart/hooks/esm/useDebouncedValue.d.ts generated vendored Normal file
View File

@@ -0,0 +1,15 @@
import { UseDebouncedCallbackOptions } from './useDebouncedCallback';
export type UseDebouncedValueOptions = UseDebouncedCallbackOptions & {
isEqual?: (a: any, b: any) => boolean;
};
/**
* Debounce a value change by a specified number of milliseconds. Useful
* when you want need to trigger a change based on a value change, but want
* to defer changes until the changes reach some level of infrequency.
*
* @param value
* @param waitOrOptions
* @returns
*/
declare function useDebouncedValue<TValue>(value: TValue, waitOrOptions?: number | UseDebouncedValueOptions): TValue;
export default useDebouncedValue;

26
node_modules/@restart/hooks/esm/useDebouncedValue.js generated vendored Normal file
View File

@@ -0,0 +1,26 @@
import { useEffect, useDebugValue, useRef } from 'react';
import useDebouncedState from './useDebouncedState';
const defaultIsEqual = (a, b) => a === b;
/**
* Debounce a value change by a specified number of milliseconds. Useful
* when you want need to trigger a change based on a value change, but want
* to defer changes until the changes reach some level of infrequency.
*
* @param value
* @param waitOrOptions
* @returns
*/
function useDebouncedValue(value, waitOrOptions = 500) {
const previousValueRef = useRef(value);
const isEqual = typeof waitOrOptions === 'object' ? waitOrOptions.isEqual || defaultIsEqual : defaultIsEqual;
const [debouncedValue, setDebouncedValue] = useDebouncedState(value, waitOrOptions);
useDebugValue(debouncedValue);
useEffect(() => {
if (!isEqual || !isEqual(previousValueRef.current, value)) {
previousValueRef.current = value;
setDebouncedValue(value);
}
});
return debouncedValue;
}
export default useDebouncedValue;

View File

@@ -0,0 +1 @@
export default function useEventCallback<TCallback extends (...args: any[]) => any>(fn?: TCallback | null): TCallback;

8
node_modules/@restart/hooks/esm/useEventCallback.js generated vendored Normal file
View File

@@ -0,0 +1,8 @@
import { useCallback } from 'react';
import useCommittedRef from './useCommittedRef';
export default function useEventCallback(fn) {
const ref = useCommittedRef(fn);
return useCallback(function (...args) {
return ref.current && ref.current(...args);
}, [ref]);
}

12
node_modules/@restart/hooks/esm/useEventListener.d.ts generated vendored Normal file
View File

@@ -0,0 +1,12 @@
type EventHandler<T, K extends keyof DocumentEventMap> = (this: T, ev: DocumentEventMap[K]) => any;
/**
* Attaches an event handler outside directly to specified DOM element
* bypassing the react synthetic event system.
*
* @param element The target to listen for events on
* @param event The DOM event name
* @param handler An event handler
* @param capture Whether or not to listen during the capture event phase
*/
export default function useEventListener<T extends Element | Document | Window, K extends keyof DocumentEventMap>(eventTarget: T | (() => T), event: K, listener: EventHandler<T, K>, capture?: boolean | AddEventListenerOptions): void;
export {};

19
node_modules/@restart/hooks/esm/useEventListener.js generated vendored Normal file
View File

@@ -0,0 +1,19 @@
import { useEffect } from 'react';
import useEventCallback from './useEventCallback';
/**
* Attaches an event handler outside directly to specified DOM element
* bypassing the react synthetic event system.
*
* @param element The target to listen for events on
* @param event The DOM event name
* @param handler An event handler
* @param capture Whether or not to listen during the capture event phase
*/
export default function useEventListener(eventTarget, event, listener, capture = false) {
const handler = useEventCallback(listener);
useEffect(() => {
const target = typeof eventTarget === 'function' ? eventTarget() : eventTarget;
target.addEventListener(event, handler, capture);
return () => target.removeEventListener(event, handler, capture);
}, [eventTarget]);
}

50
node_modules/@restart/hooks/esm/useFocusManager.d.ts generated vendored Normal file
View File

@@ -0,0 +1,50 @@
/// <reference types="react" />
export interface FocusManagerOptions {
/**
* A callback fired when focus shifts. returning `false` will prevent
* handling the focus event
*/
willHandle?(focused: boolean, event: React.FocusEvent): boolean | void;
/**
* A callback fired after focus is handled but before onChange is called
*/
didHandle?(focused: boolean, event: React.FocusEvent): void;
/**
* A callback fired after focus has changed
*/
onChange?(focused: boolean, event: React.FocusEvent): void;
/**
* When true, the event handlers will not report focus changes
*/
isDisabled: () => boolean;
}
export interface FocusController {
onBlur: (event: any) => void;
onFocus: (event: any) => void;
}
/**
* useFocusManager provides a way to track and manage focus as it moves around
* a container element. An `onChange` is fired when focus enters or leaves the
* element, but not when it moves around inside the element, similar to
* `pointerenter` and `pointerleave` DOM events.
*
* ```tsx
* const [focused, setFocusState] = useState(false)
*
* const { onBlur, onFocus } = useFocusManager({
* onChange: nextFocused => setFocusState(nextFocused)
* })
*
* return (
* <div tabIndex="-1" onFocus={onFocus} onBlur={onBlur}>
* {String(focused)}
* <input />
* <input />
*
* <button>A button</button>
* </div>
* ```
*
* @returns a memoized FocusController containing event handlers
*/
export default function useFocusManager(opts: FocusManagerOptions): FocusController;

69
node_modules/@restart/hooks/esm/useFocusManager.js generated vendored Normal file
View File

@@ -0,0 +1,69 @@
import { useCallback, useMemo, useRef } from 'react';
import useEventCallback from './useEventCallback';
import useMounted from './useMounted';
/**
* useFocusManager provides a way to track and manage focus as it moves around
* a container element. An `onChange` is fired when focus enters or leaves the
* element, but not when it moves around inside the element, similar to
* `pointerenter` and `pointerleave` DOM events.
*
* ```tsx
* const [focused, setFocusState] = useState(false)
*
* const { onBlur, onFocus } = useFocusManager({
* onChange: nextFocused => setFocusState(nextFocused)
* })
*
* return (
* <div tabIndex="-1" onFocus={onFocus} onBlur={onBlur}>
* {String(focused)}
* <input />
* <input />
*
* <button>A button</button>
* </div>
* ```
*
* @returns a memoized FocusController containing event handlers
*/
export default function useFocusManager(opts) {
const isMounted = useMounted();
const lastFocused = useRef();
const handle = useRef();
const willHandle = useEventCallback(opts.willHandle);
const didHandle = useEventCallback(opts.didHandle);
const onChange = useEventCallback(opts.onChange);
const isDisabled = useEventCallback(opts.isDisabled);
const handleChange = useCallback((focused, event) => {
if (focused !== lastFocused.current) {
didHandle == null ? void 0 : didHandle(focused, event);
// only fire a change when unmounted if its a blur
if (isMounted() || !focused) {
lastFocused.current = focused;
onChange == null ? void 0 : onChange(focused, event);
}
}
}, [isMounted, didHandle, onChange, lastFocused]);
const handleFocusChange = useCallback((focused, event) => {
if (isDisabled()) return;
if (event && event.persist) event.persist();
if ((willHandle == null ? void 0 : willHandle(focused, event)) === false) {
return;
}
clearTimeout(handle.current);
if (focused) {
handleChange(focused, event);
} else {
handle.current = window.setTimeout(() => handleChange(focused, event));
}
}, [willHandle, handleChange]);
return useMemo(() => ({
onBlur: event => {
handleFocusChange(false, event);
},
onFocus: event => {
handleFocusChange(true, event);
}
}), [handleFocusChange]);
}

17
node_modules/@restart/hooks/esm/useForceUpdate.d.ts generated vendored Normal file
View File

@@ -0,0 +1,17 @@
/**
* Returns a function that triggers a component update. the hook equivalent to
* `this.forceUpdate()` in a class component. In most cases using a state value directly
* is preferable but may be required in some advanced usages of refs for interop or
* when direct DOM manipulation is required.
*
* ```ts
* const forceUpdate = useForceUpdate();
*
* const updateOnClick = useCallback(() => {
* forceUpdate()
* }, [forceUpdate])
*
* return <button type="button" onClick={updateOnClick}>Hi there</button>
* ```
*/
export default function useForceUpdate(): () => void;

24
node_modules/@restart/hooks/esm/useForceUpdate.js generated vendored Normal file
View File

@@ -0,0 +1,24 @@
import { useReducer } from 'react';
/**
* Returns a function that triggers a component update. the hook equivalent to
* `this.forceUpdate()` in a class component. In most cases using a state value directly
* is preferable but may be required in some advanced usages of refs for interop or
* when direct DOM manipulation is required.
*
* ```ts
* const forceUpdate = useForceUpdate();
*
* const updateOnClick = useCallback(() => {
* forceUpdate()
* }, [forceUpdate])
*
* return <button type="button" onClick={updateOnClick}>Hi there</button>
* ```
*/
export default function useForceUpdate() {
// The toggling state value is designed to defeat React optimizations for skipping
// updates when they are strictly equal to the last state value
const [, dispatch] = useReducer(state => !state, false);
return dispatch;
}

17
node_modules/@restart/hooks/esm/useGlobalListener.d.ts generated vendored Normal file
View File

@@ -0,0 +1,17 @@
type DocumentEventHandler<K extends keyof DocumentEventMap> = (this: Document, ev: DocumentEventMap[K]) => any;
/**
* Attaches an event handler outside directly to the `document`,
* bypassing the react synthetic event system.
*
* ```ts
* useGlobalListener('keydown', (event) => {
* console.log(event.key)
* })
* ```
*
* @param event The DOM event name
* @param handler An event handler
* @param capture Whether or not to listen during the capture event phase
*/
export default function useGlobalListener<K extends keyof DocumentEventMap>(event: K, handler: DocumentEventHandler<K>, capture?: boolean | AddEventListenerOptions): void;
export {};

20
node_modules/@restart/hooks/esm/useGlobalListener.js generated vendored Normal file
View File

@@ -0,0 +1,20 @@
import useEventListener from './useEventListener';
import { useCallback } from 'react';
/**
* Attaches an event handler outside directly to the `document`,
* bypassing the react synthetic event system.
*
* ```ts
* useGlobalListener('keydown', (event) => {
* console.log(event.key)
* })
* ```
*
* @param event The DOM event name
* @param handler An event handler
* @param capture Whether or not to listen during the capture event phase
*/
export default function useGlobalListener(event, handler, capture = false) {
const documentTarget = useCallback(() => document, []);
return useEventListener(documentTarget, event, handler, capture);
}

31
node_modules/@restart/hooks/esm/useImage.d.ts generated vendored Normal file
View File

@@ -0,0 +1,31 @@
type State = {
image: HTMLImageElement | null;
error: unknown | null;
};
/**
* Fetch and load an image for programatic use such as in a `<canvas>` element.
*
* @param imageOrUrl The `HtmlImageElement` or image url to load
* @param crossOrigin The `crossorigin` attribute to set
*
* ```ts
* const { image, error } = useImage('/static/kittens.png')
* const ref = useRef<HTMLCanvasElement>()
*
* useEffect(() => {
* const ctx = ref.current.getContext('2d')
*
* if (image) {
* ctx.drawImage(image, 0, 0)
* }
* }, [ref, image])
*
* return (
* <>
* {error && "there was a problem loading the image"}
* <canvas ref={ref} />
* </>
* ```
*/
export default function useImage(imageOrUrl?: string | HTMLImageElement | null | undefined, crossOrigin?: 'anonymous' | 'use-credentials' | string): State;
export {};

69
node_modules/@restart/hooks/esm/useImage.js generated vendored Normal file
View File

@@ -0,0 +1,69 @@
import { useState, useEffect } from 'react';
/**
* Fetch and load an image for programatic use such as in a `<canvas>` element.
*
* @param imageOrUrl The `HtmlImageElement` or image url to load
* @param crossOrigin The `crossorigin` attribute to set
*
* ```ts
* const { image, error } = useImage('/static/kittens.png')
* const ref = useRef<HTMLCanvasElement>()
*
* useEffect(() => {
* const ctx = ref.current.getContext('2d')
*
* if (image) {
* ctx.drawImage(image, 0, 0)
* }
* }, [ref, image])
*
* return (
* <>
* {error && "there was a problem loading the image"}
* <canvas ref={ref} />
* </>
* ```
*/
export default function useImage(imageOrUrl, crossOrigin) {
const [state, setState] = useState({
image: null,
error: null
});
useEffect(() => {
if (!imageOrUrl) return undefined;
let image;
if (typeof imageOrUrl === 'string') {
image = new Image();
if (crossOrigin) image.crossOrigin = crossOrigin;
image.src = imageOrUrl;
} else {
image = imageOrUrl;
if (image.complete && image.naturalHeight > 0) {
setState({
image,
error: null
});
return;
}
}
function onLoad() {
setState({
image,
error: null
});
}
function onError(error) {
setState({
image,
error
});
}
image.addEventListener('load', onLoad);
image.addEventListener('error', onError);
return () => {
image.removeEventListener('load', onLoad);
image.removeEventListener('error', onError);
};
}, [imageOrUrl, crossOrigin]);
return state;
}

View File

@@ -0,0 +1,2 @@
import useUpdateImmediateEffect from './useUpdateImmediateEffect';
export default useUpdateImmediateEffect;

View File

@@ -0,0 +1,2 @@
import useUpdateImmediateEffect from './useUpdateImmediateEffect';
export default useUpdateImmediateEffect;

View File

@@ -0,0 +1,28 @@
/**
* Setup an [`IntersectionObserver`](https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver) on
* a DOM Element that returns it's entries as they arrive.
*
* @param element The DOM element to observe
* @param init IntersectionObserver options with a notable change,
* unlike a plain IntersectionObserver `root: null` means "not provided YET",
* and the hook will wait until it receives a non-null value to set up the observer.
* This change allows for easier syncing of element and root values in a React
* context.
*/
declare function useIntersectionObserver<TElement extends Element>(element: TElement | null | undefined, options?: IntersectionObserverInit): IntersectionObserverEntry[];
/**
* Setup an [`IntersectionObserver`](https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver) on
* a DOM Element. This overload does not trigger component updates when receiving new
* entries. This allows for finer grained performance optimizations by the consumer.
*
* @param element The DOM element to observe
* @param callback A listener for intersection updates.
* @param init IntersectionObserver options with a notable change,
* unlike a plain IntersectionObserver `root: null` means "not provided YET",
* and the hook will wait until it receives a non-null value to set up the observer.
* This change allows for easier syncing of element and root values in a React
* context.
*
*/
declare function useIntersectionObserver<TElement extends Element>(element: TElement | null | undefined, callback: IntersectionObserverCallback, options?: IntersectionObserverInit): void;
export default useIntersectionObserver;

View File

@@ -0,0 +1,65 @@
import { useState } from 'react';
import useStableMemo from './useStableMemo';
import useEffect from './useIsomorphicEffect';
import useEventCallback from './useEventCallback';
/**
* Setup an [`IntersectionObserver`](https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver) on
* a DOM Element that returns it's entries as they arrive.
*
* @param element The DOM element to observe
* @param init IntersectionObserver options with a notable change,
* unlike a plain IntersectionObserver `root: null` means "not provided YET",
* and the hook will wait until it receives a non-null value to set up the observer.
* This change allows for easier syncing of element and root values in a React
* context.
*/
/**
* Setup an [`IntersectionObserver`](https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver) on
* a DOM Element. This overload does not trigger component updates when receiving new
* entries. This allows for finer grained performance optimizations by the consumer.
*
* @param element The DOM element to observe
* @param callback A listener for intersection updates.
* @param init IntersectionObserver options with a notable change,
* unlike a plain IntersectionObserver `root: null` means "not provided YET",
* and the hook will wait until it receives a non-null value to set up the observer.
* This change allows for easier syncing of element and root values in a React
* context.
*
*/
function useIntersectionObserver(element, callbackOrOptions, maybeOptions) {
let callback;
let options;
if (typeof callbackOrOptions === 'function') {
callback = callbackOrOptions;
options = maybeOptions || {};
} else {
options = callbackOrOptions || {};
}
const {
threshold,
root,
rootMargin
} = options;
const [entries, setEntry] = useState(null);
const handler = useEventCallback(callback || setEntry);
// We wait for element to exist before constructing
const observer = useStableMemo(() => root !== null && typeof IntersectionObserver !== 'undefined' && new IntersectionObserver(handler, {
threshold,
root,
rootMargin
}), [handler, root, rootMargin, threshold && JSON.stringify(threshold)]);
useEffect(() => {
if (!element || !observer) return;
observer.observe(element);
return () => {
observer.unobserve(element);
};
}, [observer, element]);
return callback ? undefined : entries || [];
}
export default useIntersectionObserver;

61
node_modules/@restart/hooks/esm/useInterval.d.ts generated vendored Normal file
View File

@@ -0,0 +1,61 @@
/**
* Creates a `setInterval` that is properly cleaned up when a component unmounted
*
* ```tsx
* function Timer() {
* const [timer, setTimer] = useState(0)
* useInterval(() => setTimer(i => i + 1), 1000)
*
* return <span>{timer} seconds past</span>
* }
* ```
*
* @param fn an function run on each interval
* @param ms The milliseconds duration of the interval
*/
declare function useInterval(fn: () => void, ms: number): void;
/**
* Creates a pausable `setInterval` that is properly cleaned up when a component unmounted
*
* ```tsx
* const [paused, setPaused] = useState(false)
* const [timer, setTimer] = useState(0)
*
* useInterval(() => setTimer(i => i + 1), 1000, paused)
*
* return (
* <span>
* {timer} seconds past
*
* <button onClick={() => setPaused(p => !p)}>{paused ? 'Play' : 'Pause' }</button>
* </span>
* )
* ```
*
* @param fn an function run on each interval
* @param ms The milliseconds duration of the interval
* @param paused Whether or not the interval is currently running
*/
declare function useInterval(fn: () => void, ms: number, paused: boolean): void;
/**
* Creates a pausable `setInterval` that _fires_ immediately and is
* properly cleaned up when a component unmounted
*
* ```tsx
* const [timer, setTimer] = useState(-1)
* useInterval(() => setTimer(i => i + 1), 1000, false, true)
*
* // will update to 0 on the first effect
* return <span>{timer} seconds past</span>
* ```
*
* @param fn an function run on each interval
* @param ms The milliseconds duration of the interval
* @param paused Whether or not the interval is currently running
* @param runImmediately Whether to run the function immediately on mount or unpause
* rather than waiting for the first interval to elapse
*
*/
declare function useInterval(fn: () => void, ms: number, paused: boolean, runImmediately: boolean): void;
export default useInterval;

89
node_modules/@restart/hooks/esm/useInterval.js generated vendored Normal file
View File

@@ -0,0 +1,89 @@
import { useEffect } from 'react';
import useCommittedRef from './useCommittedRef';
/**
* Creates a `setInterval` that is properly cleaned up when a component unmounted
*
* ```tsx
* function Timer() {
* const [timer, setTimer] = useState(0)
* useInterval(() => setTimer(i => i + 1), 1000)
*
* return <span>{timer} seconds past</span>
* }
* ```
*
* @param fn an function run on each interval
* @param ms The milliseconds duration of the interval
*/
/**
* Creates a pausable `setInterval` that is properly cleaned up when a component unmounted
*
* ```tsx
* const [paused, setPaused] = useState(false)
* const [timer, setTimer] = useState(0)
*
* useInterval(() => setTimer(i => i + 1), 1000, paused)
*
* return (
* <span>
* {timer} seconds past
*
* <button onClick={() => setPaused(p => !p)}>{paused ? 'Play' : 'Pause' }</button>
* </span>
* )
* ```
*
* @param fn an function run on each interval
* @param ms The milliseconds duration of the interval
* @param paused Whether or not the interval is currently running
*/
/**
* Creates a pausable `setInterval` that _fires_ immediately and is
* properly cleaned up when a component unmounted
*
* ```tsx
* const [timer, setTimer] = useState(-1)
* useInterval(() => setTimer(i => i + 1), 1000, false, true)
*
* // will update to 0 on the first effect
* return <span>{timer} seconds past</span>
* ```
*
* @param fn an function run on each interval
* @param ms The milliseconds duration of the interval
* @param paused Whether or not the interval is currently running
* @param runImmediately Whether to run the function immediately on mount or unpause
* rather than waiting for the first interval to elapse
*
*/
function useInterval(fn, ms, paused = false, runImmediately = false) {
let handle;
const fnRef = useCommittedRef(fn);
// this ref is necessary b/c useEffect will sometimes miss a paused toggle
// orphaning a setTimeout chain in the aether, so relying on it's refresh logic is not reliable.
const pausedRef = useCommittedRef(paused);
const tick = () => {
if (pausedRef.current) return;
fnRef.current();
schedule(); // eslint-disable-line no-use-before-define
};
const schedule = () => {
clearTimeout(handle);
handle = setTimeout(tick, ms);
};
useEffect(() => {
if (runImmediately) {
tick();
} else {
schedule();
}
return () => clearTimeout(handle);
}, [paused, runImmediately]);
}
export default useInterval;

View File

@@ -0,0 +1,8 @@
/// <reference types="react" />
/**
* Returns ref that is `true` on the initial render and `false` on subsequent renders. It
* is StrictMode safe, so will reset correctly if the component is unmounted and remounted.
*
* This hook *must* be used before any effects that read it's value to be accurate.
*/
export default function useIsInitialRenderRef(): import("react").MutableRefObject<boolean>;

View File

@@ -0,0 +1,25 @@
import { useEffect, useLayoutEffect, useRef } from 'react';
/**
* Returns ref that is `true` on the initial render and `false` on subsequent renders. It
* is StrictMode safe, so will reset correctly if the component is unmounted and remounted.
*
* This hook *must* be used before any effects that read it's value to be accurate.
*/
export default function useIsInitialRenderRef() {
const effectCount = useRef(0);
const isInitialRenderRef = useRef(true);
useLayoutEffect(() => {
effectCount.current += 1;
if (effectCount.current >= 2) {
isInitialRenderRef.current = false;
}
});
// Strict mode handling in React 18
useEffect(() => () => {
effectCount.current = 0;
isInitialRenderRef.current = true;
}, []);
return isInitialRenderRef;
}

View File

@@ -0,0 +1,11 @@
import { useEffect } from 'react';
/**
* Is `useLayoutEffect` in a DOM or React Native environment, otherwise resolves to useEffect
* Only useful to avoid the console warning.
*
* PREFER `useEffect` UNLESS YOU KNOW WHAT YOU ARE DOING.
*
* @category effects
*/
declare const _default: typeof useEffect;
export default _default;

17
node_modules/@restart/hooks/esm/useIsomorphicEffect.js generated vendored Normal file
View File

@@ -0,0 +1,17 @@
import { useEffect, useLayoutEffect } from 'react';
const isReactNative = typeof global !== 'undefined' &&
// @ts-ignore
global.navigator &&
// @ts-ignore
global.navigator.product === 'ReactNative';
const isDOM = typeof document !== 'undefined';
/**
* Is `useLayoutEffect` in a DOM or React Native environment, otherwise resolves to useEffect
* Only useful to avoid the console warning.
*
* PREFER `useEffect` UNLESS YOU KNOW WHAT YOU ARE DOING.
*
* @category effects
*/
export default isDOM || isReactNative ? useLayoutEffect : useEffect;

31
node_modules/@restart/hooks/esm/useMap.d.ts generated vendored Normal file
View File

@@ -0,0 +1,31 @@
export declare class ObservableMap<K, V> extends Map<K, V> {
private readonly listener;
constructor(listener: (map: ObservableMap<K, V>) => void, init?: Iterable<Readonly<[K, V]>>);
set(key: K, value: V): this;
delete(key: K): boolean;
clear(): void;
}
/**
* Create and return a [Map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map) that triggers rerenders when it's updated.
*
* ```tsx
* const customerAges = useMap<number>([
* ['john', 24],
* ['betsy', 25]
* ]);
*
* return (
* <>
* {Array.from(ids, ([name, age]) => (
* <div>
* {name}: {age}. <button onClick={() => ids.delete(name)}>X</button>
* </div>
* )}
* </>
* )
* ```
*
* @param init initial Map entries
*/
declare function useMap<K, V>(init?: Iterable<Readonly<[K, V]>>): ObservableMap<K, V>;
export default useMap;

52
node_modules/@restart/hooks/esm/useMap.js generated vendored Normal file
View File

@@ -0,0 +1,52 @@
import useForceUpdate from './useForceUpdate';
import useStableMemo from './useStableMemo';
export class ObservableMap extends Map {
constructor(listener, init) {
super(init);
this.listener = listener;
}
set(key, value) {
super.set(key, value);
// When initializing the Map, the base Map calls this.set() before the
// listener is assigned so it will be undefined
if (this.listener) this.listener(this);
return this;
}
delete(key) {
let result = super.delete(key);
this.listener(this);
return result;
}
clear() {
super.clear();
this.listener(this);
}
}
/**
* Create and return a [Map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map) that triggers rerenders when it's updated.
*
* ```tsx
* const customerAges = useMap<number>([
* ['john', 24],
* ['betsy', 25]
* ]);
*
* return (
* <>
* {Array.from(ids, ([name, age]) => (
* <div>
* {name}: {age}. <button onClick={() => ids.delete(name)}>X</button>
* </div>
* )}
* </>
* )
* ```
*
* @param init initial Map entries
*/
function useMap(init) {
const forceUpdate = useForceUpdate();
return useStableMemo(() => new ObservableMap(forceUpdate, init), []);
}
export default useMap;

20
node_modules/@restart/hooks/esm/useMediaQuery.d.ts generated vendored Normal file
View File

@@ -0,0 +1,20 @@
/**
* Match a media query and get updates as the match changes. The media string is
* passed directly to `window.matchMedia` and run as a Layout Effect, so initial
* matches are returned before the browser has a chance to paint.
*
* ```tsx
* function Page() {
* const isWide = useMediaQuery('min-width: 1000px')
*
* return isWide ? "very wide" : 'not so wide'
* }
* ```
*
* Media query lists are also reused globally, hook calls for the same query
* will only create a matcher once under the hood.
*
* @param query A media query
* @param targetWindow The window to match against, uses the globally available one as a default.
*/
export default function useMediaQuery(query: string | null, targetWindow?: Window | undefined): boolean;

60
node_modules/@restart/hooks/esm/useMediaQuery.js generated vendored Normal file
View File

@@ -0,0 +1,60 @@
import useEffect from './useIsomorphicEffect';
import { useState } from 'react';
const matchersByWindow = new WeakMap();
const getMatcher = (query, targetWindow) => {
if (!query || !targetWindow) return undefined;
const matchers = matchersByWindow.get(targetWindow) || new Map();
matchersByWindow.set(targetWindow, matchers);
let mql = matchers.get(query);
if (!mql) {
mql = targetWindow.matchMedia(query);
mql.refCount = 0;
matchers.set(mql.media, mql);
}
return mql;
};
/**
* Match a media query and get updates as the match changes. The media string is
* passed directly to `window.matchMedia` and run as a Layout Effect, so initial
* matches are returned before the browser has a chance to paint.
*
* ```tsx
* function Page() {
* const isWide = useMediaQuery('min-width: 1000px')
*
* return isWide ? "very wide" : 'not so wide'
* }
* ```
*
* Media query lists are also reused globally, hook calls for the same query
* will only create a matcher once under the hood.
*
* @param query A media query
* @param targetWindow The window to match against, uses the globally available one as a default.
*/
export default function useMediaQuery(query, targetWindow = typeof window === 'undefined' ? undefined : window) {
const mql = getMatcher(query, targetWindow);
const [matches, setMatches] = useState(() => mql ? mql.matches : false);
useEffect(() => {
let mql = getMatcher(query, targetWindow);
if (!mql) {
return setMatches(false);
}
let matchers = matchersByWindow.get(targetWindow);
const handleChange = () => {
setMatches(mql.matches);
};
mql.refCount++;
mql.addListener(handleChange);
handleChange();
return () => {
mql.removeListener(handleChange);
mql.refCount--;
if (mql.refCount <= 0) {
matchers == null ? void 0 : matchers.delete(mql.media);
}
mql = undefined;
};
}, [query]);
return matches;
}

22
node_modules/@restart/hooks/esm/useMergeState.d.ts generated vendored Normal file
View File

@@ -0,0 +1,22 @@
type Updater<TState> = (state: TState) => Partial<TState> | null;
/**
* Updates state, partial updates are merged into existing state values
*/
export type MergeStateSetter<TState> = (update: Updater<TState> | Partial<TState> | null) => void;
/**
* Mimics a React class component's state model, of having a single unified
* `state` object and an updater that merges updates into the existing state, as
* opposed to replacing it.
*
* ```js
* const [state, setState] = useMergeState({ name: 'Betsy', age: 24 })
*
* setState({ name: 'Johan' }) // { name: 'Johan', age: 24 }
*
* setState(state => ({ age: state.age + 10 })) // { name: 'Johan', age: 34 }
* ```
*
* @param initialState The initial state object
*/
export default function useMergeState<TState extends {}>(initialState: TState | (() => TState)): [TState, MergeStateSetter<TState>];
export {};

36
node_modules/@restart/hooks/esm/useMergeState.js generated vendored Normal file
View File

@@ -0,0 +1,36 @@
import { useCallback, useState } from 'react';
/**
* Updates state, partial updates are merged into existing state values
*/
/**
* Mimics a React class component's state model, of having a single unified
* `state` object and an updater that merges updates into the existing state, as
* opposed to replacing it.
*
* ```js
* const [state, setState] = useMergeState({ name: 'Betsy', age: 24 })
*
* setState({ name: 'Johan' }) // { name: 'Johan', age: 24 }
*
* setState(state => ({ age: state.age + 10 })) // { name: 'Johan', age: 34 }
* ```
*
* @param initialState The initial state object
*/
export default function useMergeState(initialState) {
const [state, setState] = useState(initialState);
const updater = useCallback(update => {
if (update === null) return;
if (typeof update === 'function') {
setState(state => {
const nextState = update(state);
return nextState == null ? state : Object.assign({}, state, nextState);
});
} else {
setState(state => Object.assign({}, state, update));
}
}, [setState]);
return [state, updater];
}

View File

@@ -0,0 +1,4 @@
import { MergeStateSetter } from './useMergeState';
type Mapper<TProps, TState> = (props: TProps, state: TState) => null | Partial<TState>;
export default function useMergeStateFromProps<TProps, TState extends {}>(props: TProps, gDSFP: Mapper<TProps, TState>, initialState: TState): [TState, MergeStateSetter<TState>];
export {};

View File

@@ -0,0 +1,7 @@
import useMergeState from './useMergeState';
export default function useMergeStateFromProps(props, gDSFP, initialState) {
const [state, setState] = useMergeState(initialState);
const nextState = gDSFP(props, state);
if (nextState !== null) setState(nextState);
return [state, setState];
}

22
node_modules/@restart/hooks/esm/useMergedRefs.d.ts generated vendored Normal file
View File

@@ -0,0 +1,22 @@
/// <reference types="react" />
type CallbackRef<T> = (ref: T | null) => void;
type Ref<T> = React.MutableRefObject<T> | CallbackRef<T>;
export declare function mergeRefs<T>(refA?: Ref<T> | null, refB?: Ref<T> | null): (value: T | null) => void;
/**
* Create and returns a single callback ref composed from two other Refs.
*
* ```tsx
* const Button = React.forwardRef((props, ref) => {
* const [element, attachRef] = useCallbackRef<HTMLButtonElement>();
* const mergedRef = useMergedRefs(ref, attachRef);
*
* return <button ref={mergedRef} {...props}/>
* })
* ```
*
* @param refA A Callback or mutable Ref
* @param refB A Callback or mutable Ref
* @category refs
*/
declare function useMergedRefs<T>(refA?: Ref<T> | null, refB?: Ref<T> | null): (value: T | null) => void;
export default useMergedRefs;

33
node_modules/@restart/hooks/esm/useMergedRefs.js generated vendored Normal file
View File

@@ -0,0 +1,33 @@
import { useMemo } from 'react';
const toFnRef = ref => !ref || typeof ref === 'function' ? ref : value => {
ref.current = value;
};
export function mergeRefs(refA, refB) {
const a = toFnRef(refA);
const b = toFnRef(refB);
return value => {
if (a) a(value);
if (b) b(value);
};
}
/**
* Create and returns a single callback ref composed from two other Refs.
*
* ```tsx
* const Button = React.forwardRef((props, ref) => {
* const [element, attachRef] = useCallbackRef<HTMLButtonElement>();
* const mergedRef = useMergedRefs(ref, attachRef);
*
* return <button ref={mergedRef} {...props}/>
* })
* ```
*
* @param refA A Callback or mutable Ref
* @param refB A Callback or mutable Ref
* @category refs
*/
function useMergedRefs(refA, refB) {
return useMemo(() => mergeRefs(refA, refB), [refA, refB]);
}
export default useMergedRefs;

20
node_modules/@restart/hooks/esm/useMountEffect.d.ts generated vendored Normal file
View File

@@ -0,0 +1,20 @@
import { EffectCallback } from 'react';
/**
* Run's an effect on mount, and is cleaned up on unmount. Generally
* useful for interop with non-react plugins or components
*
* ```ts
* useMountEffect(() => {
* const plugin = $.myPlugin(ref.current)
*
* return () => {
* plugin.destroy()
* }
* })
* ```
* @param effect An effect to run on mount
*
* @category effects
*/
declare function useMountEffect(effect: EffectCallback): void;
export default useMountEffect;

23
node_modules/@restart/hooks/esm/useMountEffect.js generated vendored Normal file
View File

@@ -0,0 +1,23 @@
import { useEffect } from 'react';
/**
* Run's an effect on mount, and is cleaned up on unmount. Generally
* useful for interop with non-react plugins or components
*
* ```ts
* useMountEffect(() => {
* const plugin = $.myPlugin(ref.current)
*
* return () => {
* plugin.destroy()
* }
* })
* ```
* @param effect An effect to run on mount
*
* @category effects
*/
function useMountEffect(effect) {
return useEffect(effect, []);
}
export default useMountEffect;

21
node_modules/@restart/hooks/esm/useMounted.d.ts generated vendored Normal file
View File

@@ -0,0 +1,21 @@
/**
* Track whether a component is current mounted. Generally less preferable than
* properlly canceling effects so they don't run after a component is unmounted,
* but helpful in cases where that isn't feasible, such as a `Promise` resolution.
*
* @returns a function that returns the current isMounted state of the component
*
* ```ts
* const [data, setData] = useState(null)
* const isMounted = useMounted()
*
* useEffect(() => {
* fetchdata().then((newData) => {
* if (isMounted()) {
* setData(newData);
* }
* })
* })
* ```
*/
export default function useMounted(): () => boolean;

33
node_modules/@restart/hooks/esm/useMounted.js generated vendored Normal file
View File

@@ -0,0 +1,33 @@
import { useRef, useEffect } from 'react';
/**
* Track whether a component is current mounted. Generally less preferable than
* properlly canceling effects so they don't run after a component is unmounted,
* but helpful in cases where that isn't feasible, such as a `Promise` resolution.
*
* @returns a function that returns the current isMounted state of the component
*
* ```ts
* const [data, setData] = useState(null)
* const isMounted = useMounted()
*
* useEffect(() => {
* fetchdata().then((newData) => {
* if (isMounted()) {
* setData(newData);
* }
* })
* })
* ```
*/
export default function useMounted() {
const mounted = useRef(true);
const isMounted = useRef(() => mounted.current);
useEffect(() => {
mounted.current = true;
return () => {
mounted.current = false;
};
}, []);
return isMounted.current;
}

View File

@@ -0,0 +1,40 @@
/**
* Observe mutations on a DOM node or tree of DOM nodes.
* Depends on the `MutationObserver` api.
*
* ```tsx
* const [element, attachRef] = useCallbackRef(null);
*
* useMutationObserver(element, { subtree: true }, (records) => {
*
* });
*
* return (
* <div ref={attachRef} />
* )
* ```
*
* @param element The DOM element to observe
* @param config The observer configuration
* @param callback A callback fired when a mutation occurs
*/
declare function useMutationObserver(element: Element | null | undefined, config: MutationObserverInit, callback: MutationCallback): void;
/**
* Observe mutations on a DOM node or tree of DOM nodes.
* use a `MutationObserver` and return records as the are received.
*
* ```tsx
* const [element, attachRef] = useCallbackRef(null);
*
* const records = useMutationObserver(element, { subtree: true });
*
* return (
* <div ref={attachRef} />
* )
* ```
*
* @param element The DOM element to observe
* @param config The observer configuration
*/
declare function useMutationObserver(element: Element | null | undefined, config: MutationObserverInit): MutationRecord[];
export default useMutationObserver;

72
node_modules/@restart/hooks/esm/useMutationObserver.js generated vendored Normal file
View File

@@ -0,0 +1,72 @@
import useCustomEffect from './useCustomEffect';
import { dequal } from 'dequal';
import useImmediateUpdateEffect from './useImmediateUpdateEffect';
import useEventCallback from './useEventCallback';
import { useState } from 'react';
function isDepsEqual([nextElement, nextConfig], [prevElement, prevConfig]) {
return nextElement === prevElement && dequal(nextConfig, prevConfig);
}
/**
* Observe mutations on a DOM node or tree of DOM nodes.
* Depends on the `MutationObserver` api.
*
* ```tsx
* const [element, attachRef] = useCallbackRef(null);
*
* useMutationObserver(element, { subtree: true }, (records) => {
*
* });
*
* return (
* <div ref={attachRef} />
* )
* ```
*
* @param element The DOM element to observe
* @param config The observer configuration
* @param callback A callback fired when a mutation occurs
*/
/**
* Observe mutations on a DOM node or tree of DOM nodes.
* use a `MutationObserver` and return records as the are received.
*
* ```tsx
* const [element, attachRef] = useCallbackRef(null);
*
* const records = useMutationObserver(element, { subtree: true });
*
* return (
* <div ref={attachRef} />
* )
* ```
*
* @param element The DOM element to observe
* @param config The observer configuration
*/
function useMutationObserver(element, config, callback) {
const [records, setRecords] = useState(null);
const handler = useEventCallback(callback || setRecords);
useCustomEffect(() => {
if (!element) return;
// The behavior around reusing mutation observers is confusing
// observing again _should_ disable the last listener but doesn't
// seem to always be the case, maybe just in JSDOM? In any case the cost
// to redeclaring it is gonna be fairly low anyway, so make it simple
const observer = new MutationObserver(handler);
observer.observe(element, config);
return () => {
observer.disconnect();
};
}, [element, config], {
isEqual: isDepsEqual,
// Intentionally done in render, otherwise observer will miss any
// changes made to the DOM during this update
effectHook: useImmediateUpdateEffect
});
return callback ? void 0 : records || [];
}
export default useMutationObserver;

18
node_modules/@restart/hooks/esm/usePrevious.d.ts generated vendored Normal file
View File

@@ -0,0 +1,18 @@
/**
* Store the last of some value. Tracked via a `Ref` only updating it
* after the component renders.
*
* Helpful if you need to compare a prop value to it's previous value during render.
*
* ```ts
* function Component(props) {
* const lastProps = usePrevious(props)
*
* if (lastProps.foo !== props.foo)
* resetValueFromProps(props.foo)
* }
* ```
*
* @param value the value to track
*/
export default function usePrevious<T>(value: T): T | null;

26
node_modules/@restart/hooks/esm/usePrevious.js generated vendored Normal file
View File

@@ -0,0 +1,26 @@
import { useEffect, useRef } from 'react';
/**
* Store the last of some value. Tracked via a `Ref` only updating it
* after the component renders.
*
* Helpful if you need to compare a prop value to it's previous value during render.
*
* ```ts
* function Component(props) {
* const lastProps = usePrevious(props)
*
* if (lastProps.foo !== props.foo)
* resetValueFromProps(props.foo)
* }
* ```
*
* @param value the value to track
*/
export default function usePrevious(value) {
const ref = useRef(null);
useEffect(() => {
ref.current = value;
});
return ref.current;
}

2
node_modules/@restart/hooks/esm/useRafInterval.d.ts generated vendored Normal file
View File

@@ -0,0 +1,2 @@
declare function useRafInterval(fn: () => void, ms: number): void;
export default useRafInterval;

26
node_modules/@restart/hooks/esm/useRafInterval.js generated vendored Normal file
View File

@@ -0,0 +1,26 @@
import { useEffect } from 'react';
import useCommittedRef from './useCommittedRef';
function useRafInterval(fn, ms, paused = false) {
let handle;
let start = new Date().getTime();
const fnRef = useCommittedRef(fn);
// this ref is necessary b/c useEffect will sometimes miss a paused toggle
// orphaning a setTimeout chain in the aether, so relying on it's refresh logic is not reliable.
const pausedRef = useCommittedRef(paused);
function loop() {
const current = new Date().getTime();
const delta = current - start;
if (pausedRef.current) return;
if (delta >= ms && fnRef.current) {
fnRef.current();
start = new Date().getTime();
}
cancelAnimationFrame(handle);
handle = requestAnimationFrame(loop);
}
useEffect(() => {
handle = requestAnimationFrame(loop);
return () => cancelAnimationFrame(handle);
}, []);
}
export default useRafInterval;

View File

@@ -0,0 +1,14 @@
/// <reference types="react" />
/**
* Exactly the same as `useRef` except that the initial value is set via a
* factory function. Useful when the default is relatively costly to construct.
*
* ```ts
* const ref = useRefWithInitialValueFactory<ExpensiveValue>(() => constructExpensiveValue())
*
* ```
*
* @param initialValueFactory A factory function returning the ref's default value
* @category refs
*/
export default function useRefWithInitialValueFactory<T>(initialValueFactory: () => T): import("react").MutableRefObject<T>;

View File

@@ -0,0 +1,22 @@
import { useRef } from 'react';
const dft = Symbol('default value sigil');
/**
* Exactly the same as `useRef` except that the initial value is set via a
* factory function. Useful when the default is relatively costly to construct.
*
* ```ts
* const ref = useRefWithInitialValueFactory<ExpensiveValue>(() => constructExpensiveValue())
*
* ```
*
* @param initialValueFactory A factory function returning the ref's default value
* @category refs
*/
export default function useRefWithInitialValueFactory(initialValueFactory) {
const ref = useRef(dft);
if (ref.current === dft) {
ref.current = initialValueFactory();
}
return ref;
}

25
node_modules/@restart/hooks/esm/useResizeObserver.d.ts generated vendored Normal file
View File

@@ -0,0 +1,25 @@
export interface Rect {
width: number;
height: number;
x?: number;
y?: number;
}
/**
* Efficiently observe size changes on an element. Depends on the `ResizeObserver` api,
* and polyfills are needed in older browsers.
*
* ```ts
* const [ref, attachRef] = useCallbackRef(null);
*
* const rect = useResizeObserver(ref);
*
* return (
* <div ref={attachRef}>
* {JSON.stringify(rect)}
* </div>
* )
* ```
*
* @param element The DOM element to observe
*/
export default function useResizeObserver<TElement extends Element>(element: TElement | null | undefined): Rect | null;

47
node_modules/@restart/hooks/esm/useResizeObserver.js generated vendored Normal file
View File

@@ -0,0 +1,47 @@
import { useState } from 'react';
import useEffect from './useIsomorphicEffect';
const targetMap = new WeakMap();
let resizeObserver;
function getResizeObserver() {
// eslint-disable-next-line no-return-assign
return resizeObserver = resizeObserver || new window.ResizeObserver(entries => {
entries.forEach(entry => {
const handler = targetMap.get(entry.target);
if (handler) handler(entry.contentRect);
});
});
}
/**
* Efficiently observe size changes on an element. Depends on the `ResizeObserver` api,
* and polyfills are needed in older browsers.
*
* ```ts
* const [ref, attachRef] = useCallbackRef(null);
*
* const rect = useResizeObserver(ref);
*
* return (
* <div ref={attachRef}>
* {JSON.stringify(rect)}
* </div>
* )
* ```
*
* @param element The DOM element to observe
*/
export default function useResizeObserver(element) {
const [rect, setRect] = useState(null);
useEffect(() => {
if (!element) return;
getResizeObserver().observe(element);
setRect(element.getBoundingClientRect());
targetMap.set(element, rect => {
setRect(rect);
});
return () => {
targetMap.delete(element);
};
}, [element]);
return rect;
}

17
node_modules/@restart/hooks/esm/useSafeState.d.ts generated vendored Normal file
View File

@@ -0,0 +1,17 @@
import { Dispatch, SetStateAction } from 'react';
import { AsyncSetState } from './useStateAsync';
type StateSetter<TState> = Dispatch<SetStateAction<TState>>;
/**
* `useSafeState` takes the return value of a `useState` hook and wraps the
* setter to prevent updates onces the component has unmounted. Can used
* with `useMergeState` and `useStateAsync` as well
*
* @param state The return value of a useStateHook
*
* ```ts
* const [show, setShow] = useSafeState(useState(true));
* ```
*/
declare function useSafeState<TState>(state: [TState, AsyncSetState<TState>]): [TState, (stateUpdate: React.SetStateAction<TState>) => Promise<void>];
declare function useSafeState<TState>(state: [TState, StateSetter<TState>]): [TState, StateSetter<TState>];
export default useSafeState;

23
node_modules/@restart/hooks/esm/useSafeState.js generated vendored Normal file
View File

@@ -0,0 +1,23 @@
import { useCallback } from 'react';
import useMounted from './useMounted';
/**
* `useSafeState` takes the return value of a `useState` hook and wraps the
* setter to prevent updates onces the component has unmounted. Can used
* with `useMergeState` and `useStateAsync` as well
*
* @param state The return value of a useStateHook
*
* ```ts
* const [show, setShow] = useSafeState(useState(true));
* ```
*/
function useSafeState(state) {
const isMounted = useMounted();
return [state[0], useCallback(nextState => {
if (!isMounted()) return;
return state[1](nextState);
}, [isMounted, state[1]])];
}
export default useSafeState;

28
node_modules/@restart/hooks/esm/useSet.d.ts generated vendored Normal file
View File

@@ -0,0 +1,28 @@
export declare class ObservableSet<V> extends Set<V> {
private readonly listener;
constructor(listener: (map: ObservableSet<V>) => void, init?: Iterable<V>);
add(value: V): this;
delete(value: V): boolean;
clear(): void;
}
/**
* Create and return a [Set](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set) that triggers rerenders when it's updated.
*
* ```ts
* const ids = useSet<number>([1,2,3,4]);
*
* return (
* <>
* {Array.from(ids, id => (
* <div>
* id: {id}. <button onClick={() => ids.delete(id)}>X</button>
* </div>
* )}
* </>
* )
* ```
*
* @param init initial Set values
*/
declare function useSet<V>(init?: Iterable<V>): ObservableSet<V>;
export default useSet;

49
node_modules/@restart/hooks/esm/useSet.js generated vendored Normal file
View File

@@ -0,0 +1,49 @@
import useForceUpdate from './useForceUpdate';
import useStableMemo from './useStableMemo';
export class ObservableSet extends Set {
constructor(listener, init) {
super(init);
this.listener = listener;
}
add(value) {
super.add(value);
// When initializing the Set, the base Set calls this.add() before the
// listener is assigned so it will be undefined
if (this.listener) this.listener(this);
return this;
}
delete(value) {
const result = super.delete(value);
this.listener(this);
return result;
}
clear() {
super.clear();
this.listener(this);
}
}
/**
* Create and return a [Set](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set) that triggers rerenders when it's updated.
*
* ```ts
* const ids = useSet<number>([1,2,3,4]);
*
* return (
* <>
* {Array.from(ids, id => (
* <div>
* id: {id}. <button onClick={() => ids.delete(id)}>X</button>
* </div>
* )}
* </>
* )
* ```
*
* @param init initial Set values
*/
function useSet(init) {
const forceUpdate = useForceUpdate();
return useStableMemo(() => new ObservableSet(forceUpdate, init), []);
}
export default useSet;

10
node_modules/@restart/hooks/esm/useStableMemo.d.ts generated vendored Normal file
View File

@@ -0,0 +1,10 @@
import { DependencyList } from 'react';
/**
* Identical to `useMemo` _except_ that it provides a semantic guarantee that
* values will not be invalidated unless the dependencies change. This is unlike
* the built in `useMemo` which may discard memoized values for performance reasons.
*
* @param factory A function that returns a value to be memoized
* @param deps A dependency array
*/
export default function useStableMemo<T>(factory: () => T, deps?: DependencyList): T;

39
node_modules/@restart/hooks/esm/useStableMemo.js generated vendored Normal file
View File

@@ -0,0 +1,39 @@
import { useRef } from 'react';
function isEqual(a, b) {
if (a.length !== b.length) return false;
for (let i = 0; i < a.length; i++) {
if (a[i] !== b[i]) {
return false;
}
}
return true;
}
/**
* Identical to `useMemo` _except_ that it provides a semantic guarantee that
* values will not be invalidated unless the dependencies change. This is unlike
* the built in `useMemo` which may discard memoized values for performance reasons.
*
* @param factory A function that returns a value to be memoized
* @param deps A dependency array
*/
export default function useStableMemo(factory, deps) {
let isValid = true;
const valueRef = useRef();
// initial hook call
if (!valueRef.current) {
valueRef.current = {
deps,
result: factory()
};
// subsequent calls
} else {
isValid = !!(deps && valueRef.current.deps && isEqual(deps, valueRef.current.deps));
}
const cache = isValid ? valueRef.current : {
deps,
result: factory()
};
// must update immediately so any sync renders here don't cause an infinite loop
valueRef.current = cache;
return cache.result;
}

20
node_modules/@restart/hooks/esm/useStateAsync.d.ts generated vendored Normal file
View File

@@ -0,0 +1,20 @@
import React from 'react';
export type AsyncSetState<TState> = (stateUpdate: React.SetStateAction<TState>) => Promise<TState>;
/**
* A hook that mirrors `useState` in function and API, expect that setState
* calls return a promise that resolves after the state has been set (in an effect).
*
* This is _similar_ to the second callback in classy setState calls, but fires later.
*
* ```ts
* const [counter, setState] = useStateAsync(1);
*
* const handleIncrement = async () => {
* await setState(2);
* doWorkRequiringCurrentState()
* }
* ```
*
* @param initialState initialize with some state value same as `useState`
*/
export default function useStateAsync<TState>(initialState: TState | (() => TState)): [TState, AsyncSetState<TState>];

55
node_modules/@restart/hooks/esm/useStateAsync.js generated vendored Normal file
View File

@@ -0,0 +1,55 @@
import { useCallback, useEffect, useRef, useState } from 'react';
/**
* A hook that mirrors `useState` in function and API, expect that setState
* calls return a promise that resolves after the state has been set (in an effect).
*
* This is _similar_ to the second callback in classy setState calls, but fires later.
*
* ```ts
* const [counter, setState] = useStateAsync(1);
*
* const handleIncrement = async () => {
* await setState(2);
* doWorkRequiringCurrentState()
* }
* ```
*
* @param initialState initialize with some state value same as `useState`
*/
export default function useStateAsync(initialState) {
const [state, setState] = useState(initialState);
const resolvers = useRef([]);
useEffect(() => {
resolvers.current.forEach(resolve => resolve(state));
resolvers.current.length = 0;
}, [state]);
const setStateAsync = useCallback(update => {
return new Promise((resolve, reject) => {
setState(prevState => {
try {
let nextState;
// ugly instanceof for typescript
if (update instanceof Function) {
nextState = update(prevState);
} else {
nextState = update;
}
// If state does not change, we must resolve the promise because
// react won't re-render and effect will not resolve. If there are already
// resolvers queued, then it should be safe to assume an update will happen
if (!resolvers.current.length && Object.is(nextState, prevState)) {
resolve(nextState);
} else {
resolvers.current.push(resolve);
}
return nextState;
} catch (e) {
reject(e);
throw e;
}
});
});
}, [setState]);
return [state, setStateAsync];
}

View File

@@ -0,0 +1,34 @@
import { SyntheticEvent } from 'react';
export type ThrottledHandler<TEvent> = ((event: TEvent) => void) & {
clear(): void;
};
/**
* Creates a event handler function throttled by `requestAnimationFrame` that
* returns the **most recent** event. Useful for noisy events that update react state.
*
* ```tsx
* function Component() {
* const [position, setPosition] = useState();
* const handleMove = useThrottledEventHandler<React.PointerEvent>(
* (event) => {
* setPosition({
* top: event.clientX,
* left: event.clientY,
* })
* }
* )
*
* return (
* <div onPointerMove={handleMove}>
* <div style={position} />
* </div>
* );
* }
* ```
*
* @param handler An event handler function
* @typeParam TEvent The event object passed to the handler function
* @returns The event handler with a `clear` method attached for clearing any in-flight handler calls
*
*/
export default function useThrottledEventHandler<TEvent extends object = SyntheticEvent>(handler: (event: TEvent) => void): ThrottledHandler<TEvent>;

View File

@@ -0,0 +1,74 @@
import { useRef } from 'react';
import useMounted from './useMounted';
import useEventCallback from './useEventCallback';
const isSyntheticEvent = event => typeof event.persist === 'function';
/**
* Creates a event handler function throttled by `requestAnimationFrame` that
* returns the **most recent** event. Useful for noisy events that update react state.
*
* ```tsx
* function Component() {
* const [position, setPosition] = useState();
* const handleMove = useThrottledEventHandler<React.PointerEvent>(
* (event) => {
* setPosition({
* top: event.clientX,
* left: event.clientY,
* })
* }
* )
*
* return (
* <div onPointerMove={handleMove}>
* <div style={position} />
* </div>
* );
* }
* ```
*
* @param handler An event handler function
* @typeParam TEvent The event object passed to the handler function
* @returns The event handler with a `clear` method attached for clearing any in-flight handler calls
*
*/
export default function useThrottledEventHandler(handler) {
const isMounted = useMounted();
const eventHandler = useEventCallback(handler);
const nextEventInfoRef = useRef({
event: null,
handle: null
});
const clear = () => {
cancelAnimationFrame(nextEventInfoRef.current.handle);
nextEventInfoRef.current.handle = null;
};
const handlePointerMoveAnimation = () => {
const {
current: next
} = nextEventInfoRef;
if (next.handle && next.event) {
if (isMounted()) {
next.handle = null;
eventHandler(next.event);
}
}
next.event = null;
};
const throttledHandler = event => {
if (!isMounted()) return;
if (isSyntheticEvent(event)) {
event.persist();
}
// Special handling for a React.Konva event which reuses the
// event object as it bubbles, setting target
else if ('evt' in event) {
event = Object.assign({}, event);
}
nextEventInfoRef.current.event = event;
if (!nextEventInfoRef.current.handle) {
nextEventInfoRef.current.handle = requestAnimationFrame(handlePointerMoveAnimation);
}
};
throttledHandler.clear = clear;
return throttledHandler;
}

24
node_modules/@restart/hooks/esm/useTimeout.d.ts generated vendored Normal file
View File

@@ -0,0 +1,24 @@
import { MutableRefObject } from 'react';
/**
* Returns a controller object for setting a timeout that is properly cleaned up
* once the component unmounts. New timeouts cancel and replace existing ones.
*
*
*
* ```tsx
* const { set, clear } = useTimeout();
* const [hello, showHello] = useState(false);
* //Display hello after 5 seconds
* set(() => showHello(true), 5000);
* return (
* <div className="App">
* {hello ? <h3>Hello</h3> : null}
* </div>
* );
* ```
*/
export default function useTimeout(): {
set: (fn: () => void, delayMs?: number) => void;
clear: () => void;
handleRef: MutableRefObject<any>;
};

61
node_modules/@restart/hooks/esm/useTimeout.js generated vendored Normal file
View File

@@ -0,0 +1,61 @@
import { useMemo, useRef } from 'react';
import useMounted from './useMounted';
import useWillUnmount from './useWillUnmount';
/*
* Browsers including Internet Explorer, Chrome, Safari, and Firefox store the
* delay as a 32-bit signed integer internally. This causes an integer overflow
* when using delays larger than 2,147,483,647 ms (about 24.8 days),
* resulting in the timeout being executed immediately.
*
* via: https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout
*/
const MAX_DELAY_MS = 2 ** 31 - 1;
function setChainedTimeout(handleRef, fn, timeoutAtMs) {
const delayMs = timeoutAtMs - Date.now();
handleRef.current = delayMs <= MAX_DELAY_MS ? setTimeout(fn, delayMs) : setTimeout(() => setChainedTimeout(handleRef, fn, timeoutAtMs), MAX_DELAY_MS);
}
/**
* Returns a controller object for setting a timeout that is properly cleaned up
* once the component unmounts. New timeouts cancel and replace existing ones.
*
*
*
* ```tsx
* const { set, clear } = useTimeout();
* const [hello, showHello] = useState(false);
* //Display hello after 5 seconds
* set(() => showHello(true), 5000);
* return (
* <div className="App">
* {hello ? <h3>Hello</h3> : null}
* </div>
* );
* ```
*/
export default function useTimeout() {
const isMounted = useMounted();
// types are confused between node and web here IDK
const handleRef = useRef();
useWillUnmount(() => clearTimeout(handleRef.current));
return useMemo(() => {
const clear = () => clearTimeout(handleRef.current);
function set(fn, delayMs = 0) {
if (!isMounted()) return;
clear();
if (delayMs <= MAX_DELAY_MS) {
// For simplicity, if the timeout is short, just set a normal timeout.
handleRef.current = setTimeout(fn, delayMs);
} else {
setChainedTimeout(handleRef, fn, Date.now() + delayMs);
}
}
return {
set,
clear,
handleRef
};
}, []);
}

24
node_modules/@restart/hooks/esm/useToggleState.d.ts generated vendored Normal file
View File

@@ -0,0 +1,24 @@
/**
* Create a state setter pair for a boolean value that can be "switched".
* Unlike `useState(false)`, `useToggleState` will automatically flip the state
* value when its setter is called with no argument.
*
* @param initialState The initial boolean value
* @returns A tuple of the current state and a setter
*
* ```jsx
* const [show, toggleShow] = useToggleState(false)
*
* return (
* <>
* <button onClick={() => toggleShow()}>
* Toggle
* <button>
*
* {show && <strong>Now you can see me</strong>}
* </>
* )
*
* ```
*/
export default function useToggleState(initialState?: boolean): [boolean, (value?: boolean) => void];

28
node_modules/@restart/hooks/esm/useToggleState.js generated vendored Normal file
View File

@@ -0,0 +1,28 @@
import { useReducer } from 'react';
/**
* Create a state setter pair for a boolean value that can be "switched".
* Unlike `useState(false)`, `useToggleState` will automatically flip the state
* value when its setter is called with no argument.
*
* @param initialState The initial boolean value
* @returns A tuple of the current state and a setter
*
* ```jsx
* const [show, toggleShow] = useToggleState(false)
*
* return (
* <>
* <button onClick={() => toggleShow()}>
* Toggle
* <button>
*
* {show && <strong>Now you can see me</strong>}
* </>
* )
*
* ```
*/
export default function useToggleState(initialState = false) {
return useReducer((state, action) => action == null ? !state : action, initialState);
}

23
node_modules/@restart/hooks/esm/useUpdateEffect.d.ts generated vendored Normal file
View File

@@ -0,0 +1,23 @@
import { EffectCallback, DependencyList } from 'react';
/**
* Runs an effect only when the dependencies have changed, skipping the
* initial "on mount" run. Caution, if the dependency list never changes,
* the effect is **never run**
*
* ```ts
* const ref = useRef<HTMLInput>(null);
*
* // focuses an element only if the focus changes, and not on mount
* useUpdateEffect(() => {
* const element = ref.current?.children[focusedIdx] as HTMLElement
*
* element?.focus()
*
* }, [focusedIndex])
* ```
* @param effect An effect to run on mount
*
* @category effects
*/
declare function useUpdateEffect(fn: EffectCallback, deps: DependencyList): void;
export default useUpdateEffect;

33
node_modules/@restart/hooks/esm/useUpdateEffect.js generated vendored Normal file
View File

@@ -0,0 +1,33 @@
import { useEffect, useRef } from 'react';
/**
* Runs an effect only when the dependencies have changed, skipping the
* initial "on mount" run. Caution, if the dependency list never changes,
* the effect is **never run**
*
* ```ts
* const ref = useRef<HTMLInput>(null);
*
* // focuses an element only if the focus changes, and not on mount
* useUpdateEffect(() => {
* const element = ref.current?.children[focusedIdx] as HTMLElement
*
* element?.focus()
*
* }, [focusedIndex])
* ```
* @param effect An effect to run on mount
*
* @category effects
*/
function useUpdateEffect(fn, deps) {
const isFirst = useRef(true);
useEffect(() => {
if (isFirst.current) {
isFirst.current = false;
return;
}
return fn();
}, deps);
}
export default useUpdateEffect;

View File

@@ -0,0 +1,19 @@
import { DependencyList, EffectCallback } from 'react';
/**
* An _immediate_ effect that runs an effect callback when its dependency array
* changes. This is helpful for updates should must run during render, most
* commonly state derived from props; a more ergonomic version of https://reactjs.org/docs/hooks-faq.html#how-do-i-implement-getderivedstatefromprops
*
* ```ts
* function Example({ value }) {
* const [intermediaryValue, setValue] = useState(value);
*
* useUpdateImmediateEffect(() => {
* setValue(value)
* }, [value])
* ```
*
* @category effects
*/
declare function useUpdateImmediateEffect(effect: EffectCallback, deps: DependencyList): void;
export default useUpdateImmediateEffect;

View File

@@ -0,0 +1,36 @@
import { useRef } from 'react';
import useStableMemo from './useStableMemo';
import useWillUnmount from './useWillUnmount';
/**
* An _immediate_ effect that runs an effect callback when its dependency array
* changes. This is helpful for updates should must run during render, most
* commonly state derived from props; a more ergonomic version of https://reactjs.org/docs/hooks-faq.html#how-do-i-implement-getderivedstatefromprops
*
* ```ts
* function Example({ value }) {
* const [intermediaryValue, setValue] = useState(value);
*
* useUpdateImmediateEffect(() => {
* setValue(value)
* }, [value])
* ```
*
* @category effects
*/
function useUpdateImmediateEffect(effect, deps) {
const firstRef = useRef(true);
const tearDown = useRef();
useWillUnmount(() => {
if (tearDown.current) tearDown.current();
});
useStableMemo(() => {
if (firstRef.current) {
firstRef.current = false;
return;
}
if (tearDown.current) tearDown.current();
tearDown.current = effect();
}, deps);
}
export default useUpdateImmediateEffect;

View File

@@ -0,0 +1,23 @@
import { EffectCallback, DependencyList } from 'react';
/**
* Runs a layout effect only when the dependencies have changed, skipping the
* initial "on mount" run. Caution, if the dependency list never changes,
* the effect is **never run**
*
* ```ts
* const ref = useRef<HTMLInput>(null);
*
* // focuses an element only if the focus changes, and not on mount
* useUpdateLayoutEffect(() => {
* const element = ref.current?.children[focusedIdx] as HTMLElement
*
* element?.focus()
*
* }, [focusedIndex])
* ```
* @param effect An effect to run on mount
*
* @category effects
*/
declare function useUpdateLayoutEffect(fn: EffectCallback, deps: DependencyList): void;
export default useUpdateLayoutEffect;

View File

@@ -0,0 +1,33 @@
import { useLayoutEffect, useRef } from 'react';
/**
* Runs a layout effect only when the dependencies have changed, skipping the
* initial "on mount" run. Caution, if the dependency list never changes,
* the effect is **never run**
*
* ```ts
* const ref = useRef<HTMLInput>(null);
*
* // focuses an element only if the focus changes, and not on mount
* useUpdateLayoutEffect(() => {
* const element = ref.current?.children[focusedIdx] as HTMLElement
*
* element?.focus()
*
* }, [focusedIndex])
* ```
* @param effect An effect to run on mount
*
* @category effects
*/
function useUpdateLayoutEffect(fn, deps) {
const isFirst = useRef(true);
useLayoutEffect(() => {
if (isFirst.current) {
isFirst.current = false;
return;
}
return fn();
}, deps);
}
export default useUpdateLayoutEffect;

8
node_modules/@restart/hooks/esm/useUpdatedRef.d.ts generated vendored Normal file
View File

@@ -0,0 +1,8 @@
/// <reference types="react" />
/**
* Returns a ref that is immediately updated with the new value
*
* @param value The Ref value
* @category refs
*/
export default function useUpdatedRef<T>(value: T): import("react").MutableRefObject<T>;

13
node_modules/@restart/hooks/esm/useUpdatedRef.js generated vendored Normal file
View File

@@ -0,0 +1,13 @@
import { useRef } from 'react';
/**
* Returns a ref that is immediately updated with the new value
*
* @param value The Ref value
* @category refs
*/
export default function useUpdatedRef(value) {
const valueRef = useRef(value);
valueRef.current = value;
return valueRef;
}

7
node_modules/@restart/hooks/esm/useWillUnmount.d.ts generated vendored Normal file
View File

@@ -0,0 +1,7 @@
/**
* Attach a callback that fires when a component unmounts
*
* @param fn Handler to run when the component unmounts
* @category effects
*/
export default function useWillUnmount(fn: () => void): void;

13
node_modules/@restart/hooks/esm/useWillUnmount.js generated vendored Normal file
View File

@@ -0,0 +1,13 @@
import useUpdatedRef from './useUpdatedRef';
import { useEffect } from 'react';
/**
* Attach a callback that fires when a component unmounts
*
* @param fn Handler to run when the component unmounts
* @category effects
*/
export default function useWillUnmount(fn) {
const onUnmount = useUpdatedRef(fn);
useEffect(() => () => onUnmount.current(), []);
}