import type { WsConnection } from "../socket/ws"; import { type Countdown, type CountdownOptions } from "../Utils/countdown"; type CleanupFn = () => void; /** * Synthetic events derived from the `wheel` event, filtered by scroll direction. * * - `'wheelUp'` fires when `deltaY < 0` (user scrolled / wheeled upward) * - `'wheelDown'` fires when `deltaY > 0` (user scrolled / wheeled downward) */ export type WheelDirectionEvent = "wheelUp" | "wheelDown"; /** * All event names accepted by `onWindow` and `onWindowCapture`: * every key from `WindowEventMap` plus the synthetic `wheelUp` / `wheelDown`. */ export type WindowHookEventName = keyof WindowEventMap | WheelDirectionEvent; /** * Handler type for `onWindow` / `onWindowCapture`. * * - `'wheelUp'` / `'wheelDown'` → handler receives a `WheelEvent` * - Any other event name → handler receives the native event type * from `WindowEventMap` */ export type WindowHookHandler = K extends WheelDirectionEvent ? (event: WheelEvent) => CleanupFn | undefined : K extends keyof WindowEventMap ? (event: WindowEventMap[K]) => CleanupFn | undefined : never; /** * Attaches a **bubble-phase** listener on `window`, tied to the component * lifecycle. The listener is automatically removed when the component unmounts. * * Supports all standard `WindowEventMap` events plus the synthetic * `'wheelUp'` and `'wheelDown'` events. * * The handler may optionally return a cleanup function — it is called before * the next invocation and on component unmount. * * @example * ```ts * // Close a dropdown on any click * onWindow("click", () => isOpen.set(false)); * * // Global keyboard shortcut * onWindow("keydown", (e) => { * if (e.key === "Escape") closeModal(); * }); * * // Wheel direction * onWindow("wheelUp", () => zoom.set(z => z + 0.1)); * onWindow("wheelDown", () => zoom.set(z => z - 0.1)); * ``` */ export declare function onWindow(eventName: K, fn: WindowHookHandler): void; /** * Attaches a **capture-phase** listener on `window`, tied to the component * lifecycle. The listener is automatically removed when the component unmounts. * * Use capture when: * - You need to intercept events before they reach their target element * - The event does not bubble (`'scroll'`, `'focus'`, `'blur'`) * - You want to catch scroll on nested scrollable containers * * Supports all standard `WindowEventMap` events plus `'wheelUp'` / `'wheelDown'`. * * @example * ```ts * // Intercept all clicks before any element handler runs * onWindowCapture("click", (e) => { * if ((e.target as HTMLElement).closest(".protected")) { * e.stopPropagation(); * } * }); * * // Catch scroll on any element — scroll does not bubble * onWindowCapture("scroll", (e) => trackScrollDepth(e.target)); * ``` */ export declare function onWindowCapture(eventName: K, fn: WindowHookHandler): void; /** * Attaches a capture-phase `scroll` listener on `window`, tied to the * component lifecycle. * * Capture is required here because `scroll` does not bubble — only capture * allows intercepting scroll events from nested scrollable containers. * * `passive: true` is set automatically so the browser can scroll without * waiting for the handler. * * The listener is automatically removed when the component unmounts. * The handler may optionally return a cleanup function. * * @example * ```ts * onWindowScroll((e) => { * const el = e.target as Element; * scrollDepth.set(el.scrollTop ?? window.scrollY); * }); * ``` */ export declare const onWindowScroll: (fn: (e: Event) => CleanupFn | undefined) => void; export declare const onBlur: (fn: () => CleanupFn | undefined) => void; export declare const onFocus: (fn: () => CleanupFn | undefined) => void; export declare const onOnline: (fn: () => CleanupFn | undefined) => void; export declare const onOffline: (fn: () => CleanupFn | undefined) => void; export declare const onWindowResize: (fn: () => CleanupFn | undefined) => void; export declare const onWindowBeforeUnload: (fn: (e: BeforeUnloadEvent) => CleanupFn | undefined) => void; /** * Fires whenever the user pastes inside the page (`Ctrl+V`, right-click Paste, * or a programmatic paste). Receives the native `ClipboardEvent` so you can * read `e.clipboardData.getData('text/plain')` or inspect `e.clipboardData.files` * for images and binary content. * * Listener is automatically removed when the component unmounts. * The handler may optionally return a cleanup function. * * @example * ```ts * onPaste((e) => { * const text = e.clipboardData?.getData('text/plain') ?? ''; * content.set(text); * }); * * // Handle pasted images * onPaste((e) => { * const file = e.clipboardData?.files[0]; * if (file?.type.startsWith('image/')) uploadImage(file); * }); * ``` */ export declare const onPaste: (fn: (e: ClipboardEvent) => CleanupFn | undefined) => void; /** * Fires whenever the user copies selected content inside the page. * Receives the native `ClipboardEvent` — you can call `e.preventDefault()` * and write custom data to the clipboard via `e.clipboardData.setData(...)`. * * Listener is automatically removed when the component unmounts. * * @example * ```ts * onCopy((e) => { * const selected = window.getSelection()?.toString() ?? ''; * analytics.track('copy', { chars: selected.length }); * }); * ``` */ export declare const onCopy: (fn: (e: ClipboardEvent) => CleanupFn | undefined) => void; /** * Fires whenever the user cuts selected content inside the page. * Receives the native `ClipboardEvent`. * * Listener is automatically removed when the component unmounts. * * @example * ```ts * onCut((e) => { * isDirty.set(true); * }); * ``` */ export declare const onCut: (fn: (e: ClipboardEvent) => CleanupFn | undefined) => void; /** * Attaches a global `keydown` listener on `window`, tied to the component * lifecycle. Ideal for keyboard shortcuts that should be active whenever * this component is mounted. * * Listener is automatically removed when the component unmounts. * The handler may optionally return a cleanup function. * * @example * ```ts * onKeyDown((e) => { * if (e.key === 'Escape') closeModal(); * if (e.ctrlKey && e.key === 's') { e.preventDefault(); save(); } * if (e.ctrlKey && e.key === 'Enter') submit(); * }); * ``` */ export declare const onKeyDown: (fn: (e: KeyboardEvent) => CleanupFn | undefined) => void; /** * Attaches a global `keyup` listener on `window`, tied to the component * lifecycle. * * Listener is automatically removed when the component unmounts. * * @example * ```ts * onKeyUp((e) => { * if (e.key === 'Shift') multiSelect.set(false); * }); * ``` */ export declare const onKeyUp: (fn: (e: KeyboardEvent) => CleanupFn | undefined) => void; /** * Fires whenever the page's visibility changes — i.e. the user switches tabs, * minimises the window, or returns to the page. The handler receives a plain * `boolean`: `true` when the tab is now hidden, `false` when it is visible. * * Uses the `visibilitychange` event on `document` (not `window`) which is the * correct target per the Page Visibility API spec. * * Listener is automatically removed when the component unmounts. * * @example * ```ts * onVisibilityChange((hidden) => { * if (hidden) pauseVideo(); * else resumeVideo(); * }); * * // Pause a polling interval while the tab is hidden * onVisibilityChange((hidden) => { * if (hidden) return startPolling(); // returns cleanup * }); * ``` */ export declare const onVisibilityChange: (fn: (hidden: boolean) => CleanupFn | undefined) => void; /** * Fires whenever the user's text selection changes anywhere on the page. * The handler receives the current `Selection` object (or `null` when nothing * is selected), already fetched via `window.getSelection()`. * * Uses the `selectionchange` event on `document`. * * Listener is automatically removed when the component unmounts. * * @example * ```ts * onSelectionChange((selection) => { * const text = selection?.toString() ?? ''; * selectedText.set(text); * showToolbar.set(text.length > 0); * }); * ``` */ export declare const onSelectionChange: (fn: (selection: Selection | null) => CleanupFn | undefined) => void; /** * Fires when `localStorage` or `sessionStorage` is mutated by **another tab * or window** in the same origin. This is the standard mechanism for * cross-tab state synchronisation. * * The handler receives the native `StorageEvent` which includes: * - `e.key` — the key that changed (`null` when `clear()` was called) * - `e.oldValue` — the previous value (or `null`) * - `e.newValue` — the new value (or `null` if the key was removed) * - `e.storageArea` — the `Storage` object that was affected * - `e.url` — the URL of the document that made the change * * Does **not** fire for changes made by the current tab. * * Listener is automatically removed when the component unmounts. * * @example * ```ts * onStorageChange((e) => { * if (e.key === 'theme') applyTheme(e.newValue ?? 'light'); * if (e.key === 'auth') revalidateSession(); * }); * ``` */ export declare const onStorageChange: (fn: (e: StorageEvent) => CleanupFn | undefined) => void; /** * Attaches a window-level file drop handler, allowing users to drop files * anywhere on the page. Automatically prevents the browser's default behaviour * (navigating to the dropped file) and suppresses the `dragover` visual cursor * change. * * The handler receives the native `DragEvent` — access dropped files via * `e.dataTransfer.files` or `e.dataTransfer.items`. * * Both the `dragover` and `drop` listeners are automatically removed when the * component unmounts. * * @example * ```ts * onFileDrop((e) => { * const files = Array.from(e.dataTransfer?.files ?? []); * files.forEach(uploadFile); * }); * * // Filter by type * onFileDrop((e) => { * const images = Array.from(e.dataTransfer?.files ?? []) * .filter(f => f.type.startsWith('image/')); * if (images.length) setImages(images); * }); * ``` */ export declare const onFileDrop: (fn: (e: DragEvent) => CleanupFn | undefined) => void; /** * Calls `fn` when the user clicks outside the current component's host element. * Uses mousedown so it runs before click handlers. Listener is removed on unmount. */ export declare const onClickAway: (fn: (e: MouseEvent) => void) => void; /** * Attaches a passive `scroll` listener on a target element (defaults to * `window`). Tied to the component lifecycle — removed on unmount. * * For intercepting scroll on nested containers at the window level, prefer * `onWindowScroll` which uses capture mode. */ export declare const onScroll: (fn: (e: Event) => CleanupFn | undefined, target?: EventTarget) => void; /** * Observes size changes on a target element (defaults to the host component * element) via `ResizeObserver`. Tied to the component lifecycle. * * When no `target` is passed, observation starts after DOM ready so the host * has children / computed styles, and the host is made layout-observable if it * would otherwise be a non-atomic inline. */ export declare const onResize: (fn: (entry: ResizeObserverEntry) => CleanupFn | undefined, target?: HTMLElement) => void; export declare const onNavigate: (fn: (path: string) => CleanupFn | undefined | void) => void; export declare const onInterval: (fn: () => CleanupFn | undefined, ms: number) => void; export declare const onTimeout: (fn: () => CleanupFn | undefined, ms: number) => void; /** * Create a {@link Countdown} scoped to the component lifetime. * * The returned timer is automatically stopped on unmount. Call `start()`, * `pause()`, `resume()`, or `restart()` as needed — typically right after * receiving the handle. * * @example * const t = onCountdown(() => dismiss(id), 6000); * t.start(); * * @example * // Pause on hover without manual cleanup * const t = onCountdown(() => toast.leave(), 6000, { * onTick: ({ progress }) => { bar.style.width = `${progress * 100}%`; }, * }); * t.start(); * el.onpointerenter = () => t.pause(); * el.onpointerleave = () => t.resume(); */ export declare const onCountdown: (callback: () => void, duration: number, options?: CountdownOptions) => Countdown; /** * Subscribe `handler` to one or more WebSocket connections. * * Registered on mount, automatically unsubscribed when the component unmounts. * * ```ts * onSocket((msg: ChatMessage) => { * messages.update(d => { d.push(msg); }); * }, [chatSocket]); * ``` */ export declare function onSocket(handler: (data: T) => void, sockets: WsConnection[]): void; export declare const onUpdate: (fn: () => CleanupFn | undefined) => void; export {}; //# sourceMappingURL=hooks.d.ts.map