@gmana/react-hooks
Version:
1,407 lines (1,389 loc) • 37.8 kB
TypeScript
import * as react0 from "react";
import React, { CSSProperties, DependencyList, Dispatch, EffectCallback, RefObject, SetStateAction, useEffect } from "react";
//#region src/lib/use-array.d.ts
/**
*
* @param defaultValue
* @returns
* @example
* ```tsx
* import { useArray } from '@gmana/hook';
*
* export default function ArrayComponent() {
* const { array, set, push, remove, filter, update, clear } = useArray([1, 2, 3, 4, 5, 6]);
*
* return (
* <div className="space-x-3 text-white divide-x-2 divide-gray-400">
* <div>{array.join(', ')}</div>
* <button onClick={() => push(7)}>Add 7</button>
* <button onClick={() => update(1, 9)}>Change Second Element To 9</button>
* <button onClick={() => remove(1)}>Remove Second Element</button>
* <button onClick={() => filter((n) => n < 4)}>Keep Numbers Less Than 4</button>
* <button onClick={() => set([1, 2])}>Set To 1, 2</button>
* <button onClick={clear}>Clear</button>
* </div>
* );
* }
* ```
*/
declare function useArray<T>(defaultValue: T[]): {
array: T[];
set: react0.Dispatch<react0.SetStateAction<T[]>>;
push: (element: T) => void;
filter: (callback: (n: T) => boolean) => void;
update: (index: number, newElement: T) => void;
remove: (index: number) => void;
clear: () => void;
};
//#endregion
//#region src/lib/use-boolean.d.ts
interface ReturnType$2 {
value: boolean;
setValue: Dispatch<SetStateAction<boolean>>;
setTrue: () => void;
setFalse: () => void;
toggle: () => void;
}
/**
*
* @param defaultValue
* @returns
* @example
* import React from 'react'
* import { useBoolean } from '@gmana/hook'
*
* export default function Component() {
* const { value, setValue, setTrue, setFalse, toggle } = useBoolean(false)
*
* // Just an example to use "setValue"
* const customToggle = () => setValue(x => !x)
*
* return (
* <>
* <p>
* Value is <code>{value.toString()}</code>
* </p>
* <button onClick={setTrue}>set true</button>
* <button onClick={setFalse}>set false</button>
* <button onClick={toggle}>toggle</button>
* <button onClick={customToggle}>custom toggle</button>
* </>
* )
* }
*/
declare function useBoolean(defaultValue?: boolean): ReturnType$2;
//#endregion
//#region src/lib/use-clipboard.d.ts
/**
* Hook to copy text to clipboard.
*/
declare function useClipboard(): {
isCopied: boolean;
copyToClipboard: (text: string) => Promise<void>;
};
//#endregion
//#region src/lib/use-cookies.d.ts
interface CookieOptions {
days?: number;
path?: string;
[key: string]: string | number | boolean | undefined;
}
interface EnhancedCookieOptions extends CookieOptions {
sameSite?: "strict" | "lax" | "none";
}
declare const setCookie: (name: string, value: string, options?: EnhancedCookieOptions) => void;
declare const getCookie: (name: string, initialValue?: string) => string;
declare const removeCookie: (name: string) => void;
//#endregion
//#region src/lib/use-copy-to-clipboard.d.ts
type CopiedValue = string | null;
type CopyFn = (text: string) => Promise<boolean>;
/**
*
* @returns
* @example
* import React from 'react'
* import { useCopyToClipboard } from '@gmana/hook'
*
* export default function Component() {
* const [value, copy] = useCopyToClipboard()
* return (
* <>
* <h1>Click to copy:</h1>
* <div style={{ display: 'flex' }}>
* <button onClick={() => copy('A')}>A</button>
* <button onClick={() => copy('B')}>B</button>
* <button onClick={() => copy('C')}>C</button>
* </div>
* <p>Copied value: {value ?? 'Nothing is copied yet!'}</p>
* </>
* )
* }
*/
declare function useCopyToClipboard(): [CopiedValue, CopyFn];
//#endregion
//#region src/lib/use-countdown.d.ts
declare function useCountdown(initialTime?: number): {
timeLeft: number;
isActive: boolean;
startTimer: () => void;
resetTimer: () => void;
canResend: boolean;
};
//#endregion
//#region src/lib/use-counter.d.ts
interface ReturnType$1 {
count: number;
increment: () => void;
decrement: () => void;
reset: () => void;
setCount: Dispatch<SetStateAction<number>>;
}
/**
*
* @param initialValue
* @returns
* @example
* import React from 'react'
* import { useCounter } from '@gmana/hook'
*
* export default function Component() {
* const { count, setCount, increment, decrement, reset } = useCounter(0)
*
* const multiplyBy2 = () => setCount(x => x * 2)
*
* return (
* <>
* <p>Count is {count}</p>
* <button onClick={increment}>Increment</button>
* <button onClick={decrement}>Decrement</button>
* <button onClick={reset}>Reset</button>
* <button onClick={multiplyBy2}>Multiply by 2</button>
* </>
* )
* }
*/
declare function useCounter(initialValue?: number): ReturnType$1;
//#endregion
//#region src/lib/use-dark-mode.d.ts
interface UseDarkModeOutput {
isDarkMode: boolean;
toggle: () => void;
enable: () => void;
disable: () => void;
}
/**
*
* @param defaultValue
* @returns
* @example
* import React from 'react'
* import { useDarkMode } from '@gmana/hook'
*
* export default function Component() {
* const { isDarkMode, toggle, enable, disable } = useDarkMode()
*
* return (
* <div>
* <p>Current theme: {isDarkMode ? 'dark' : 'light'}</p>
* <button onClick={toggle}>Toggle</button>
* <button onClick={enable}>Enable</button>
* <button onClick={disable}>Disable</button>
* </div>
* )
* }
*/
declare function useDarkMode(defaultValue?: boolean): UseDarkModeOutput;
//#endregion
//#region src/lib/use-debounce.d.ts
/**
*
* @param value
* @param delay default value `500`
* @returns `debouncedValue`
* @example
*
'use client'
import { useEffect, useState } from 'react'
import { useRouter } from 'next/navigation'
import qs from 'query-string'
import { useDebounce } from '@gmana/tw'
import { Input } from '@gmana/react/input'
const InputSearch = () => {
const router = useRouter()
const [value, setValue] = useState<string>('')
const debouncedValue = useDebounce<string>(value, 500)
useEffect(() => {
const query = {
title: debouncedValue,
}
const url = qs.stringifyUrl({
url: '/docs/hooks/use-debounce',
query,
})
router.push(url)
}, [debouncedValue, router])
return <Input placeholder="What do you want to listen to?" value={value} onChange={(e) => setValue(e.target.value)} />
}
export default InputSearch
*/
declare function useDebounce<T>(value: T, delay?: number): T;
//#endregion
//#region src/lib/use-debounce-a.d.ts
/**
*
* @param value
* @param delay
* @returns
* @example
* import React, { ChangeEvent, useEffect, useState } from 'react'
* import { useDebounce } from '@gmana/hook'
*
* export default function Component() {
* const [value, setValue] = useState<string>('')
* const debouncedValue = useDebounceA<string>(value, 500)
*
* const handleChange = (event: ChangeEvent<HTMLInputElement>) => {
* setValue(event.target.value)
* }
*
* // Fetch API (optional)
* useEffect(() => {
* // Do fetch here...
* // Triggers when "debouncedValue" changes
* }, [debouncedValue])
*
* return (
* <div>
* <p>Value real-time: {value}</p>
* <p>Debounced value: {debouncedValue}</p>
*
* <input type="text" value={value} onChange={handleChange} />
* </div>
* )
* }
*/
declare function useDebounceA<T>(value: T, delay?: number): T;
//#endregion
//#region src/lib/use-debounce-b.d.ts
/**
*
* @deprecated `use useDebounce instead`
* @example
* import { useState } from "react"
* import useDebounce from "./useDebounce"
*
* export default function DebounceComponent() {
* const [count, setCount] = useState(10)
* useDebounce(() => alert(count), 1000, [count])
*
* return (
* <div>
* <div>{count}</div>
* <button onClick={() => setCount(c => c + 1)}>Increment</button>
* </div>
* )
* }
*/
declare function useDebounceB(callback: () => void, delay: number, dependencies: never[]): void;
//#endregion
//#region src/lib/use-dimensions.d.ts
declare function useDimensions(containerRef: React.RefObject<HTMLElement | null>): {
width: number;
height: number;
};
//#endregion
//#region src/lib/use-effect-once.d.ts
/**
*
* @param effect
* @example
* import React, { useEffect, useState } from 'react'
* import { useEffectOnce } from '@gmana/hook'
*
* export default function Component() {
* const [data, setData] = useState<number>(0)
* useEffect(() => {
* console.log('Normal useEffect', { data })
* }, [data])
*
* useEffectOnce(() => {
* console.log('Triggered only once, on mount', { data })
* })
*
* return (
* <div>
* <p>Open your console</p>
* <button onClick={() => setData(Date.now())}>Update data</button>
* </div>
* )
* }
*/
declare function useEffectOnce(effect: EffectCallback): void;
//#endregion
//#region src/lib/use-element-size.d.ts
interface Size {
width: number;
height: number;
}
/**
* @description
* Use EventListener with simplicity by React Hook. It takes as parameters a `eventName`,
* a call-back functions (handler) and optionally a reference `element`. You can see above two examples using `useRef` and `window` based event.
* @returns
* @example
* import React, { useState } from 'react'
* import { useElementSize } from '@gmana/hook'
*
* export default function Component() {
* const [isVisible, setVisible] = useState(true)
* const [squareRef, { width, height }] = useElementSize()
*
* const toggleVisibility = () => setVisible(x => !x)
*
* return (
* <>
* <p>{`The square width is ${width}px and height ${height}px`}</p>
* <p>Try, resize your window and-or click on the button.</p>
*
* <button onClick={toggleVisibility}>
* {isVisible ? 'Hide' : 'Show'} square
* </button>
*
* {isVisible && (
* <div
* ref={squareRef}
* style={{
* width: '50%',
* paddingTop: '50%',
* backgroundColor: 'aquamarine',
* margin: 'auto',
* }}
* />
* )}
* </>
* )
* }
*/
declare function useElementSize<T extends HTMLElement = HTMLDivElement>(): [(node: T | null) => void, Size];
//#endregion
//#region src/lib/use-estimate-storage.d.ts
/**
* Estimates the available storage quota and usage.
* Returns the estimated remaining storage space in MB.
* @example
'use client';
import { useEstimateStorage } from '@gmana/hook';
export function Quota() {
const quota = useEstimateStorage();
return (
<div>
<h1>Quota: {(quota / 1024).toFixed(2)} GB</h1>
</div>
);
}
*/
declare function useEstimateStorage(): number;
//#endregion
//#region src/lib/use-event-listener.d.ts
/**
*
* @param eventName
* @param handler
* @param element
* @example
* import React, { useRef } from 'react'
* import { useEventListener } from '@gmana/hook'
*
* export default function Component() {
* // Define button ref
* const buttonRef = useRef<HTMLButtonElement>(null)
*
* const onScroll = (event: Event) => {
* console.log('window scrolled!', event)
* }
*
* const onClick = (event: Event) => {
* console.log('button clicked!', event)
* }
*
* // example with window based event
* useEventListener('scroll', onScroll)
*
* // example with element based event
* useEventListener('click', onClick, buttonRef)
*
* return (
* <div style={{ minHeight: '200vh' }}>
* <button ref={buttonRef}>Click me</button>
* </div>
* )
* }
*/
declare function useEventListener<K extends keyof WindowEventMap>(eventName: K, handler: (event: WindowEventMap[K]) => void): void;
/**
*
* @param eventName
* @param handler
* @param element
* @example
* import React, { useRef } from 'react'
* import { useEventListener } from '@gmana/hook'
*
* export default function Component() {
* // Define button ref
* const buttonRef = useRef<HTMLButtonElement>(null)
*
* const onScroll = (event: Event) => {
* console.log('window scrolled!', event)
* }
*
* const onClick = (event: Event) => {
* console.log('button clicked!', event)
* }
*
* // example with window based event
* useEventListener('scroll', onScroll)
*
* // example with element based event
* useEventListener('click', onClick, buttonRef)
*
* return (
* <div style={{ minHeight: '200vh' }}>
* <button ref={buttonRef}>Click me</button>
* </div>
* )
* }
*/
declare function useEventListener<K extends keyof HTMLElementEventMap, T extends HTMLElement = HTMLDivElement>(eventName: K, handler: (event: HTMLElementEventMap[K]) => void, element: RefObject<T>): void;
//#endregion
//#region src/lib/use-fetch.d.ts
interface State<T> {
data?: T;
error?: Error;
}
/**
* @description
* Here is a React Hook which aims to retrieve data on an API using the native Fetch API.
*
* For advanced usages and optimizations,
* see these other hooks more powerful like
* - `useSWR`,
* - `useQuery`
* - `Redux Toolkit` (`RTK Query`).
* @param url
* @param options
* @returns
* @example
* import React from 'react'
* import { useFetch } from '@gmana/hook'
*
* const url = `http://jsonplaceholder.typicode.com/posts`
*
* interface Post {
* userId: number
* id: number
* title: string
* body: string
* }
*
* export default function Component() {
* const { data, error } = useFetch<Post[]>(url)
*
* if (error) return <p>There is an error.</p>
* if (!data) return <p>Loading...</p>
* return <p>{data[0].title}</p>
* }
*/
declare function useFetch<T = unknown>(url?: string, options?: RequestInit): State<T>;
//#endregion
//#region src/lib/use-hover.d.ts
/**
* @example
* import React, { useRef } from 'react'
* import { useHover } from '@gmana/hook';
*
* export default function Component() {
* const hoverRef = useRef(null)
* const isHover = useHover(hoverRef)
*
* return (
* <div ref={hoverRef}>
* {`The current div is ${isHover ? `hovered` : `un-hovered`}`}
* </div>
* )
* }
*/
declare function useHover<T extends HTMLElement = HTMLElement>(ComponentRef: RefObject<T>): boolean;
//#endregion
//#region src/lib/use-image-on-load.d.ts
interface ImageStyle {
thumbnail: CSSProperties;
fullSize: CSSProperties;
}
interface ImageOnLoadType {
handleImageOnLoad: () => void;
css: ImageStyle;
}
/**
*
* @returns
* @example
* import React, { CSSProperties } from 'react'
* import { useImageOnLoad } from '@gmana/hook'
*
* export default function Component() {
* const { handleImageOnLoad, css } = useImageOnLoad()
*
* const style: { [key: string]: CSSProperties } = {
* wrap: {
* position: 'relative',
* width: 400,
* height: 400,
* margin: 'auto',
* },
* image: {
* position: 'absolute',
* top: 0,
* left: 0,
* width: `100%`,
* height: `100%`,
* },
* }
*
* return (
* <div style={style.wrap}>
*
* <img
* style={{ ...style.image, ...css.thumbnail }}
* src="https://via.placeholder.com/150"
* alt="thumbnail"
* />
*
* <img
* onLoad={handleImageOnLoad}
* style={{ ...style.image, ...css.fullSize }}
* src="https://via.placeholder.com/600"
* alt="fullImage"
* />
* </div>
* )
* }
*/
declare function useImageOnLoad(): ImageOnLoadType;
//#endregion
//#region src/lib/use-in-view.d.ts
declare const useIntersection: (element: RefObject<HTMLDivElement>, rootMargin: string) => boolean;
//#endregion
//#region src/lib/use-intersection-observer.d.ts
interface Args extends IntersectionObserverInit {
freezeOnceVisible?: boolean;
}
/**
*
* @param ComponentRef
* @param param1
* @returns
* @example
* import React, { useRef } from 'react'
* import { useIntersectionObserver } from '@gmana/hook'
*
* const Section = (props: { title: string }) => {
* const ref = useRef<HTMLDivElement | null>(null)
* const entry = useIntersectionObserver(ref, {})
* const isVisible = !!entry?.isIntersecting
*
* console.log(`Render Section ${props.title}`, { isVisible })
*
* return (
* <div
* ref={ref}
* style={{
* minHeight: '100vh',
* display: 'flex',
* border: '1px dashed #000',
* fontSize: '2rem',
* }}
* >
* <div style={{ margin: 'auto' }}>{props.title}</div>
* </div>
* )
* }
*
* export default function Component() {
* return (
* <>
* {Array.from({ length: 5 }).map((_, index) => (
* <Section key={index + 1} title={`${index + 1}`} />
* ))}
* </>
* )
* }
*/
declare function useIntersectionObserver(ComponentRef: RefObject<Element>, {
threshold,
root,
rootMargin,
freezeOnceVisible
}: Args): IntersectionObserverEntry | undefined;
//#endregion
//#region src/lib/use-interval.d.ts
/**
*
* @param callback
* @param delay
* @example
* import React, { ChangeEvent, useState } from 'react'
* import { useInterval } from '@gmana/hook'
*
* export default function Component() {
* // The counter
* const [count, setCount] = useState<number>(0)
* // Dynamic delay
* const [delay, setDelay] = useState<number>(1000)
* // ON/OFF
* const [isPlaying, setPlaying] = useState<boolean>(false)
*
* useInterval(
* () => {
* // Your custom logic here
* setCount(count + 1)
* },
* // Delay in milliseconds or null to stop it
* isPlaying ? delay : null,
* )
*
* const handleChange = (event: ChangeEvent<HTMLInputElement>) => {
* setDelay(Number(event.target.value))
* }
*
* return (
* <>
* <h1>{count}</h1>
* <button onClick={() => setPlaying(!isPlaying)}>
* {isPlaying ? 'pause' : 'play'}
* </button>
* <p>
* <label htmlFor="delay">Delay: </label>
* <input
* type="number"
* name="delay"
* onChange={handleChange}
* value={delay}
* />
* </p>
* </>
* )
* }
*/
declare function useInterval(callback: () => void, delay: number | null): void;
//#endregion
//#region src/lib/use-is-client.d.ts
/**
*
* @returns
* @example
* import React from 'react'
* import { useIsClient } from '@gmana/hook'
*
* export default function Component() {
* const isClient = useIsClient()
*
* return <div>{isClient ? 'Client' : 'server'}</div>
* }
*/
declare function useIsClient(): boolean;
//#endregion
//#region src/lib/use-is-first-render.d.ts
/**
*
* @returns
* @example
* import React, { useEffect, useState } from 'react'
* import { useIsFirstRender } from '@gmana/hook'
*
* export default function Component() {
* const isFirst = useIsFirstRender()
* const [data, setData] = useState<number>(0)
*
* useEffect(() => {
* console.log('Normal useEffect', { data })
* }, [data])
*
* return (
* <div>
* <p>Open your console</p>
* <p>Is first render: {isFirst ? 'yes' : 'no'}</p>
* <button onClick={() => setData(Date.now())}>Update data</button>
* </div>
* )
* }
*/
declare function useIsFirstRender(): boolean;
//#endregion
//#region src/lib/use-is-mounted.d.ts
/**
*
* @returns
* @example
* import React, { useEffect, useState } from 'react'
* import { useIsMounted } from '@gmana/hook'
*
* const delay = (ms: number) => new Promise(resolve => setTimeout(resolve, ms))
*
* function Child() {
* const [data, setData] = useState('loading')
* const isMounted = useIsMounted()
*
* // simulate an api call and update state
* useEffect(() => {
* void delay(3000).then(() => {
* if (isMounted()) setData('OK')
* })
* }, [isMounted])
*
* return <p>{data}</p>
* }
*
* export default function Component() {
* const [isVisible, setVisible] = useState<boolean>(false)
*
* const toggleVisibility = () => setVisible(state => !state)
*
* return (
* <>
* <button onClick={toggleVisibility}>{isVisible ? 'Hide' : 'Show'}</button>
*
* {isVisible && <Child />}
* </>
* )
* }
*/
declare function useIsMounted(): () => boolean;
//#endregion
//#region src/lib/use-isomorphic-layout-effect.d.ts
/**
*
* @example
* import React from 'react'
* import { useIsomorphicLayoutEffect } from '@gmana/hook'
*
* export default function Component() {
* useIsomorphicLayoutEffect(() => {
* console.log(
* "In the browser, I'm an `useLayoutEffect`, but in SSR, I'm an `useEffect`.",
* )
* }, [])
*
* return <p>Hello, world</p>
* }
*/
declare const useIsomorphicLayoutEffect: typeof useEffect;
//#endregion
//#region src/lib/use-local-storage.d.ts
declare global {
interface WindowEventMap {
"local-storage": CustomEvent;
}
}
type SetValue<T> = Dispatch<SetStateAction<T>>;
/**
*
* @param key
* @param initialValue
* @returns
* @example
* import React from 'react'
* import { useLocalStorage } from '@gmana/hook'
*
* export default function Component() {
* const [isDarkTheme, setDarkTheme] = useLocalStorage('darkTheme', true)
*
* const toggleTheme = () => {
* setDarkTheme(prevValue => !prevValue)
* }
*
* return (
* <button onClick={toggleTheme}>
* {`The current theme is ${isDarkTheme ? `dark` : `light`}`}
* </button>
* )
* }
*/
declare function useLocalStorage<T>(key: string, initialValue: T): [T, SetValue<T>];
//#endregion
//#region src/lib/use-locked-body.d.ts
type ReturnType = [boolean, (locked: boolean) => void];
/**
*
* @param initialLocked
* @returns
* @example
* import React, { CSSProperties, useState } from 'react'
* import { useLockedBody } from '@gmana/hook'
*
* const fixedCenterStyle: CSSProperties = {
* position: 'fixed',
* top: '50%',
* left: '50%',
* transform: 'translate(-50%, -50%)',
* }
*
* const fakeScrollableStyle: CSSProperties = {
* minHeight: '150vh',
* background: 'linear-gradient(palegreen, palegoldenrod, palevioletred)',
* }
*
* // Example 1: useLockedBody as useState()
* export default function App() {
* const [locked, setLocked] = useLockedBody()
*
* const toggleLocked = () => {
* setLocked(!locked)
* }
*
* return (
* <div style={fakeScrollableStyle}>
* <button style={fixedCenterStyle} onClick={toggleLocked}>
* {locked ? 'unlock scroll' : 'lock scroll'}
* </button>
* </div>
* )
* }
*
* // Example 2: useLockedBody with our custom state
* export function App2() {
* const [locked, setLocked] = useState(false)
*
* const toggleLocked = () => {
* setLocked(!locked)
* }
*
* useLockedBody(locked)
*
* return (
* <div style={fakeScrollableStyle}>
* <button style={fixedCenterStyle} onClick={toggleLocked}>
* {locked ? 'unlock scroll' : 'lock scroll'}
* </button>
* </div>
* )
* }
*/
declare function useLockedBody(initialLocked?: boolean): ReturnType;
//#endregion
//#region src/lib/use-map.d.ts
type MapOrEntries<K, V> = Map<K, V> | [K, V][];
interface Actions<K, V> {
set: (key: K, value: V) => void;
setAll: (entries: MapOrEntries<K, V>) => void;
remove: (key: K) => void;
reset: Map<K, V>["clear"];
}
type Return<K, V> = [Omit<Map<K, V>, "set" | "clear" | "delete">, Actions<K, V>];
/**
*
* @param initialState
* @returns
* @example
* import React, { Fragment } from 'react'
* import { MapOrEntries, useMap } from '@gmana/hook'
*
* const initialValues: MapOrEntries<string, string> = [['key', '🆕']]
* const otherValues: MapOrEntries<string, string> = [
* ['hello', '👋'],
* ['data', '📦'],
* ]
*
* export default function Component() {
* const [map, actions] = useMap<string, string>(initialValues)
*
* const set = () => actions.set(String(Date.now()), '📦')
* const setAll = () => actions.setAll(otherValues)
* const reset = () => actions.reset()
* const remove = () => actions.remove('hello')
*
* return (
* <div>
* <button onClick={set}>Add</button>
* <button onClick={reset}>Reset</button>
* <button onClick={setAll}>Set new data</button>
* <button onClick={remove} disabled={!map.get('hello')}>
* {'Remove "hello"'}
* </button>
*
* <pre>
* Map (
* {Array.from(map.entries()).map(([key, value]) => (
* <Fragment key={key}>{`\n ${key}: ${value}`}</Fragment>
* ))}
* <br />)
* </pre>
* </div>
* )
* }
*/
declare function useMap<K, V>(initialState?: MapOrEntries<K, V>): Return<K, V>;
//#endregion
//#region src/lib/use-media-query.d.ts
/**
*
* @param query
* @returns
* @example
const isDesktop = useMediaQuery("(min-width: 768px)")
*/
declare function useMediaQuery(query: string): boolean;
//#endregion
//#region src/lib/use-mobile.d.ts
declare function useIsMobile(): boolean;
//#endregion
//#region src/lib/use-network-information.d.ts
interface INetworkInformation {
isOnline: boolean;
effectiveType: string;
downlink: number;
rtt: number;
}
/**
* Hook that returns network information for the browser,
* including online status, effective connection type,
* downlink speed, and round trip latency.
* @example
import { useNetworkInformation } from "@gmana/hook";
export default function Network() {
const networkState = useNetworkInformation();
return <pre>{JSON.stringify(networkState, null, 2)}</pre>;
}
*/
declare const useNetworkInformation: () => INetworkInformation | null;
//#endregion
//#region src/lib/use-offline-detector.d.ts
/**
* Hook to detect offline status.
* Returns a boolean indicating if offline.
* @example
'use client';
import { useOfflineDetector } from '@gmana/hook';
import { useEffect, useState } from 'react';
export function OfflineBanner() {
const isOffline = useOfflineDetector();
const [showBanner, setShowBanner] = useState(() => isOffline);
useEffect(() => {
setShowBanner(isOffline);
}, [isOffline]);
return showBanner ? (
<div className="bg-gray-950 text-white px-3 py-1 flex justify-between items-center">
{isOffline ? <p>You are currently offline.</p> : <p>You are currently online.</p>}
<button onClick={() => setShowBanner(false)}>Close</button>
</div>
) : null;
}
*/
declare const useOfflineDetector: () => boolean;
//#endregion
//#region src/lib/use-on-click-outside.d.ts
type Handler = (event: MouseEvent) => void;
/**
*
* @param ref
* @param handler
* @param mouseEvent
* @example
* import React, { useRef } from 'react'
* import { useOnClickOutside } from '@gmana/tw'
*
* export default function Component() {
* const ref = useRef(null)
*
* const handleClickOutside = () => {
* // Your custom logic here
* console.log('clicked outside')
* }
*
* const handleClickInside = () => {
* // Your custom logic here
* console.log('clicked inside')
* }
*
* useOnClickOutside(ref, handleClickOutside)
*
* return (
* <button
* ref={ref}
* onClick={handleClickInside}
* style={{ width: 200, height: 200, background: 'cyan' }}
* />
* )
* }
// OR
const ref = useRef(null);
useOnClickOutside(ref, () => {
setIsClick(false);
});
*/
declare function useOnClickOutside<T extends HTMLElement = HTMLElement>(ref: RefObject<T>, handler: Handler, mouseEvent?: "mousedown" | "mouseup"): void;
//#endregion
//#region src/lib/use-read-local-storage.d.ts
type Value<T> = T | null;
/**
*
* @param key
* @returns
* @example
* import React from 'react'
* import { useReadLocalStorage } from '@gmana/hook'
*
* export default function Component() {
* // Assuming a value was set in localStorage with this key
* const darkMode = useReadLocalStorage('darkMode')
*
* return <p>DarkMode is {darkMode ? 'enabled' : 'disabled'}</p>
* }
*/
declare function useReadLocalStorage<T>(key: string): Value<T>;
//#endregion
//#region src/lib/use-screen.d.ts
/**
*
* @returns
* @example
* import React from 'react'
* import { useScreen } from '@gmana/hook'
*
* export default function Component() {
* const screen = useScreen()
*
* return (
* <div>
* The current window dimensions are:{' '}
* <code>
* {JSON.stringify({ width: screen?.width, height: screen?.height })}
* </code>
* </div>
* )
* }
*/
declare function useScreen(): Screen | undefined;
//#endregion
//#region src/lib/use-script.d.ts
type Status = "idle" | "loading" | "ready" | "error";
type ScriptElt = HTMLScriptElement | null;
/**
*
* @param src
* @returns
* @example
* import React, { useEffect } from 'react'
* import { useScript } from '@gmana/hook'
*
* // it's an example, use your types instead
* // eslint-disable-next-line @typescript-eslint/no-explicit-any
* declare const jQuery: any
*
* export default function Component() {
* // Load the script asynchronously
* const status = useScript(`https://code.jquery.com/jquery-3.5.1.min.js`)
*
* useEffect(() => {
* if (typeof jQuery !== 'undefined') {
* // jQuery is loaded => print the version
* // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
* alert(jQuery.fn.jquery)
* }
* }, [status])
*
* return (
* <div>
* <p>{`Current status: ${status}`}</p>
*
* {status === 'ready' && <p>You can use the script here.</p>}
* </div>
* )
* }
*/
declare function useScript(src: string): Status;
//#endregion
//#region src/lib/use-sidebar.d.ts
declare function useSidebar(): {
open: boolean;
onOpenChange: (open: boolean) => void;
};
//#endregion
//#region src/lib/use-ssr.d.ts
/**
*
* @returns
* @example
* import React from 'react'
* import { useSsr } from '@gmana/hook'
*
* export default function Component() {
* const { isBrowser } = useSsr()
*
* return <p>{isBrowser ? 'Browser' : 'Server'}!</p>
* }
*/
declare function useSsr(): {
isBrowser: false | HTMLElement;
isServer: boolean;
};
//#endregion
//#region src/lib/use-step.d.ts
interface Helpers {
goToNextStep: () => void;
goToPrevStep: () => void;
reset: () => void;
canGoToNextStep: boolean;
canGoToPrevStep: boolean;
setStep: Dispatch<SetStateAction<number>>;
}
/**
*
* @param maxStep
* @returns
* @example
* import React from 'react'
* import { useStep } from '@gmana/hook'
*
* export default function Component() {
* const [currentStep, helpers] = useStep(5)
*
* const {
* canGoToPrevStep,
* canGoToNextStep,
* goToNextStep,
* goToPrevStep,
* reset,
* setStep,
* } = helpers
*
* return (
* <>
* <p>Current step is {currentStep}</p>
* <p>Can go to previous step {canGoToPrevStep ? 'yes' : 'no'}</p>
* <p>Can go to next step {canGoToNextStep ? 'yes' : 'no'}</p>
* <button onClick={goToNextStep}>Go to next step</button>
* <button onClick={goToPrevStep}>Go to previous step</button>
* <button onClick={reset}>Reset</button>
* <button onClick={() => setStep(3)}>Set to step 3</button>
* </>
* )
* }
*
*/
declare function useStep(maxStep: number): [number, Helpers];
//#endregion
//#region src/lib/use-ternary-dark-mode.d.ts
type TernaryDarkMode = "system" | "dark" | "light";
interface UseTernaryDarkModeOutput {
isDarkMode: boolean;
ternaryDarkMode: TernaryDarkMode;
setTernaryDarkMode: Dispatch<SetStateAction<TernaryDarkMode>>;
toggleTernaryDarkMode: () => void;
}
/**
*
* @returns
* @example
* import React from 'react'
* import { useTernaryDarkMode } from '@gmana/hook'
*
* export default function Component() {
* const {
* isDarkMode,
* ternaryDarkMode,
* setTernaryDarkMode,
* toggleTernaryDarkMode,
* } = useTernaryDarkMode()
* type TernaryDarkMode = typeof ternaryDarkMode
*
* return (
* <div>
* <p>Current theme: {isDarkMode ? 'dark' : 'light'}</p>
* <p>ternaryMode: {ternaryDarkMode}</p>
* <p>
* Toggle between three modes
* <button onClick={toggleTernaryDarkMode}>
* Toggle from {ternaryDarkMode}
* </button>
* </p>
* <p>
* Select a mode
* <br />
* <select
* name="select-ternaryDarkMode"
* onChange={ev =>
* setTernaryDarkMode(ev.target.value as TernaryDarkMode)
* }
* value={ternaryDarkMode}
* >
* <option value="light">light</option>
* <option value="system">system</option>
* <option value="dark">dark</option>
* </select>
* </p>
* </div>
* )
* }
*
*/
declare function useTernaryDarkMode(): UseTernaryDarkModeOutput;
//#endregion
//#region src/lib/use-timeout.d.ts
/**
* @example
* ```ts
* import { useState } from "react"
* import useTimeout from "@gmana/use-timeout"
*
* export default function TimeoutComponent() {
* const [count, setCount] = useState(10)
* const { clear, reset } = useTimeout(() => setCount(0), 1000)
*
* return (
* <div>
* <div>{count}</div>
* <button onClick={() => setCount(c => c + 1)}>Increment</button>
* <button onClick={clear}>Clear Timeout</button>
* <button onClick={reset}>Reset Timeout</button>
* </div>
* )
* }
* ```
*/
declare function useTimeout(callback: () => void, delay: number): {
reset: () => void;
clear: () => void;
};
//#endregion
//#region src/lib/use-timeout-a.d.ts
/**
* @deprecated use useTimeout instead
* @example
* import React, { useState } from 'react'
* import { useTimeout } from '@gmana/hook'
*
* export default function Component() {
* const [visible, setVisible] = useState(true)
*
* const hide = () => setVisible(false)
*
* useTimeoutA(hide, 5000)
*
* return (
* <div>
* <p>
* {visible
* ? "I'm visible for 5000ms"
* : 'You can no longer see this content'}
* </p>
* </div>
* )
* }
*/
declare function useTimeoutA(callback: () => void, delay: number | null): void;
//#endregion
//#region src/lib/use-toggle.d.ts
/**
*
* @param defaultValue
* @returns
* ```ts
* import useToggle from "@gmana/use-toggle"
*
* export default function ToggleComponent() {
* const [value, toggleValue] = useToggle(false)
*
* return (
* <div>
* <div>{value.toString()}</div>
* <button onClick={toggleValue}>Toggle</button>
* <button onClick={() => toggleValue(true)}>Make True</button>
* <button onClick={() => toggleValue(false)}>Make False</button>
* </div>
* )
* }
* ```
*/
declare function useToggle(defaultValue: boolean): (boolean | ((value: boolean) => void))[];
//#endregion
//#region src/lib/use-toggle-state.d.ts
type StateType = [boolean, () => void, () => void, () => void] & {
state: boolean;
open: () => void;
close: () => void;
toggle: () => void;
};
/**
*
* @param initialState - boolean
* @returns An array like object with `state`, `open`, `close`, and `toggle` properties
* to allow both object and array destructuring
*
* ```
* const [showModal, openModal, closeModal, toggleModal] = useToggleState()
* // or
* const { state, open, close, toggle } = useToggleState()
* ```
*/
//#endregion
//#region src/lib/use-unload-warning.d.ts
declare function useUnloadWarning(condition?: boolean): void;
//#endregion
//#region src/lib/use-update-effect.d.ts
/**
*
* @param effect
* @param deps
* @example
* import React, { useEffect, useState } from 'react'
* import { useUpdateEffect } from '@gmana/hook'
*
* export default function Component() {
* const [data, setData] = useState<number>(0)
* useEffect(() => {
* console.log('Normal useEffect', { data })
* }, [data])
*
* useUpdateEffect(() => {
* console.log('Update useEffect only', { data })
* }, [data])
*
* return (
* <div>
* <p>Open your console</p>
* <button onClick={() => setData(Date.now())}>Update data</button>
* </div>
* )
* }
*/
declare function useUpdateEffect(effect: EffectCallback, deps?: DependencyList): void;
//#endregion
//#region src/lib/use-window-size.d.ts
interface WindowSize {
width: number;
height: number;
}
/**
*
* @returns
* @example
* import React from 'react'
* import { useWindowSize } from '@gmana/hook'
*
* export default function Component() {
* const { width, height } = useWindowSize()
*
* return (
* <div>
* The current window dimensions are:{' '}
* <code>{JSON.stringify({ width, height })}</code>
* </div>
* )
* }
*
*/
declare function useWindowSize(): WindowSize;
//#endregion
export { Actions, INetworkInformation, MapOrEntries, ScriptElt, StateType, Status, getCookie, removeCookie, setCookie, useArray, useBoolean, useClipboard, useCopyToClipboard, useCountdown, useCounter, useDarkMode, useDebounce, useDebounceA, useDebounceB, useDimensions, useEffectOnce, useElementSize, useEstimateStorage, useEventListener, useFetch, useHover, useImageOnLoad, useIntersection, useIntersectionObserver, useInterval, useIsClient, useIsFirstRender, useIsMobile, useIsMounted, useIsomorphicLayoutEffect, useLocalStorage, useLockedBody, useMap, useMediaQuery, useNetworkInformation, useOfflineDetector, useOnClickOutside, useReadLocalStorage, useScreen, useScript, useSidebar, useSsr, useStep, useTernaryDarkMode, useTimeout, useTimeoutA, useToggle, useUnloadWarning, useUpdateEffect, useWindowSize };