UNPKG

@lyonph/preact-hooks

Version:

Collection of useful Preact Hooks

652 lines (612 loc) 18.7 kB
var __defProp = Object.defineProperty; var __defProps = Object.defineProperties; var __getOwnPropDescs = Object.getOwnPropertyDescriptors; var __getOwnPropSymbols = Object.getOwnPropertySymbols; var __hasOwnProp = Object.prototype.hasOwnProperty; var __propIsEnum = Object.prototype.propertyIsEnumerable; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __spreadValues = (a, b) => { for (var prop in b || (b = {})) if (__hasOwnProp.call(b, prop)) __defNormalProp(a, prop, b[prop]); if (__getOwnPropSymbols) for (var prop of __getOwnPropSymbols(b)) { if (__propIsEnum.call(b, prop)) __defNormalProp(a, prop, b[prop]); } return a; }; var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b)); // src/useAsyncMemo.ts import { useEffect as useEffect2 } from "preact/hooks"; // src/useConditionalCallback.tsx import { useRef as useRef2 } from "preact/hooks"; // src/useDependencyChanged.tsx import { useDebugValue, useRef } from "preact/hooks"; function defaultCompare(a, b) { return !Object.is(a, b); } function useDependencyChanged(dependency, shouldUpdate = defaultCompare) { const prevDeps = useRef(dependency); const result = shouldUpdate(prevDeps.current, dependency); if (result) { prevDeps.current = dependency; } useDebugValue(result); return result; } // src/useConditionalCallback.tsx function useConditionalCallback(supplier, dependency, shouldUpdate = defaultCompare) { const value = useRef2(supplier); const dependencyChanged = useDependencyChanged(dependency, shouldUpdate); if (dependencyChanged) { value.current = supplier; } return value.current; } // src/useFreshState.tsx import { useDebugValue as useDebugValue4 } from "preact/hooks"; // src/useConstant.ts import { useDebugValue as useDebugValue3 } from "preact/hooks"; // src/useLazyRef.ts import { useDebugValue as useDebugValue2, useRef as useRef3 } from "preact/hooks"; function useLazyRef(supplier) { const ref = useRef3(); if (!ref.current) { ref.current = { current: supplier() }; } useDebugValue2(ref.current); return ref.current; } // src/useConstant.ts function useConstant(supplier) { const { current } = useLazyRef(supplier); useDebugValue3(current); return current; } // src/useConstantCallback.ts function useConstantCallback(cb) { return useConstant(() => cb); } // src/useForceUpdate.ts import { useReducer } from "preact/hooks"; function useForceUpdate() { return useReducer(() => [], [])[1]; } // src/useFreshLazyRef.tsx function useFreshLazyRef(supplier, dependency, shouldUpdate = defaultCompare) { const value = useLazyRef(supplier); const dependencyChanged = useDependencyChanged(dependency, shouldUpdate); if (dependencyChanged) { value.current = supplier(); } return value; } // src/useMountedState.ts import { useRef as useRef4 } from "preact/hooks"; // src/useIsomorphicEffect.ts import { useEffect, useLayoutEffect } from "preact/hooks"; // src/utils/is-client.ts var IS_CLIENT = typeof window !== "undefined" && typeof window.document !== "undefined" && typeof window.document.createElement !== "undefined"; var is_client_default = IS_CLIENT; // src/useIsomorphicEffect.ts var useIsomorphicEffect = is_client_default ? useLayoutEffect : useEffect; var useIsomorphicEffect_default = useIsomorphicEffect; // src/useMountedState.ts function useMountedState() { const alive = useRef4(false); useIsomorphicEffect_default(() => { alive.current = true; return () => { alive.current = false; }; }, []); return useConstantCallback(() => alive.current); } // src/useFreshState.tsx function isRefreshStateInitialAction(initial) { return typeof initial === "function"; } function isRefreshStateAction(state) { return typeof state === "function"; } function useFreshState(initialState, dependencies, shouldUpdate = defaultCompare) { const stateRef = useFreshLazyRef( () => isRefreshStateInitialAction(initialState) ? initialState() : initialState, dependencies, shouldUpdate ); const forceUpdate = useForceUpdate(); const isMounted = useMountedState(); const setState = useConstantCallback( (action) => { if (isMounted()) { const { current } = stateRef; const newState = isRefreshStateAction(action) ? action(current) : action; if (!Object.is(current, newState)) { stateRef.current = newState; forceUpdate(); } } } ); useDebugValue4(stateRef.current); return [stateRef.current, setState]; } // src/useAsyncMemo.ts function useAsyncMemo(supplier, dependency, shouldUpdate = defaultCompare) { const [state, setState] = useFreshState( () => ({ status: "pending" }), dependency, shouldUpdate ); const request = useConditionalCallback(supplier, dependency, shouldUpdate); useEffect2(() => { let mounted = true; request().then((value) => { if (mounted) { setState({ status: "success", value }); } }, (value) => { if (mounted) { setState({ status: "failure", value }); } }); return () => { mounted = false; }; }, [request, setState]); return state; } // src/useConditionalEffect.tsx import { useEffect as useEffect3 } from "preact/hooks"; // src/useDependencyVersion.tsx import { useDebugValue as useDebugValue5, useRef as useRef5 } from "preact/hooks"; function useDependencyVersion(dependency, shouldUpdate = defaultCompare) { const dependencyChanged = useDependencyChanged(dependency, shouldUpdate); const version = useRef5(0); if (dependencyChanged) { version.current += 1; } useDebugValue5(version.current); return version.current; } // src/useConditionalEffect.tsx function useConditionalEffect(supplier, dependency, shouldUpdate = defaultCompare) { const version = useDependencyVersion(dependency, shouldUpdate); useEffect3(supplier, [version]); } // src/useConditionalLayoutEffect.tsx import { useLayoutEffect as useLayoutEffect2 } from "preact/hooks"; function useConditionalLayoutEffect(supplier, dependency, shouldUpdate = defaultCompare) { const version = useDependencyVersion(dependency, shouldUpdate); useLayoutEffect2(supplier, [version]); } // src/useConditionalMemo.tsx import { useDebugValue as useDebugValue6 } from "preact/hooks"; function useConditionalMemo(supplier, dependency, shouldUpdate = defaultCompare) { const value = useFreshLazyRef( supplier, dependency, shouldUpdate ).current; useDebugValue6(value); return value; } // src/useFullscreenElement.tsx import { useDebugValue as useDebugValue8 } from "preact/hooks"; // src/useSubscription.ts import { useDebugValue as useDebugValue7, useEffect as useEffect4, useState } from "preact/hooks"; function useSubscription({ read, subscribe, shouldUpdate = defaultCompare }) { const [state, setState] = useState(() => ({ read, subscribe, shouldUpdate, value: read() })); let currentValue = state.value; if (state.read !== read || state.subscribe !== subscribe || state.shouldUpdate !== shouldUpdate) { currentValue = read(); setState({ read, subscribe, shouldUpdate, value: currentValue }); } useDebugValue7(currentValue); useEffect4(() => { let mounted = true; const readCurrent = () => { if (mounted) { const nextValue = read(); setState((prev) => { if (prev.read !== read || prev.subscribe !== subscribe || prev.shouldUpdate !== shouldUpdate) { return prev; } if (!shouldUpdate(prev.value, nextValue)) { return prev; } return __spreadProps(__spreadValues({}, prev), { value: nextValue }); }); } }; const unsubscribe = subscribe(readCurrent); readCurrent(); return () => { mounted = false; if (unsubscribe) { unsubscribe(); } }; }, [read, subscribe, shouldUpdate]); return currentValue; } // src/useFullscreenElement.tsx var SUBSCRIPTION = { read: () => { if (is_client_default && document.fullscreenElement) { return document.fullscreenElement; } return void 0; }, subscribe: (callback) => { if (is_client_default) { document.addEventListener("fullscreenchange", callback); return () => { document.removeEventListener("fullscreenchange", callback); }; } return void 0; } }; function useFullscreenElement() { const value = useSubscription(SUBSCRIPTION); useDebugValue8(value); return value; } // src/useMediaQuery.tsx import { useDebugValue as useDebugValue9 } from "preact/hooks"; var MEDIA = /* @__PURE__ */ new Map(); function getMediaMatcher(query) { const media = MEDIA.get(query); if (media) { return media; } const newMedia = window.matchMedia(query); MEDIA.set(query, newMedia); return newMedia; } function useMediaQuery(query) { const media = useConditionalMemo(() => { if (is_client_default) { return getMediaMatcher(query); } return void 0; }, query); const subscription = useConditionalMemo(() => ({ read: () => !!(media == null ? void 0 : media.matches), subscribe: (callback) => { if (media) { media.addEventListener("change", callback); return () => { media.removeEventListener("change", callback); }; } return void 0; } }), media); const value = useSubscription(subscription); useDebugValue9(value); return value; } // src/useOnlineStatus.ts import { useDebugValue as useDebugValue10 } from "preact/hooks"; var SUBSCRIPTION2 = { read: () => { if (is_client_default) { return navigator.onLine; } return true; }, subscribe: (callback) => { if (is_client_default) { window.addEventListener("online", callback, false); window.addEventListener("offline", callback, false); return () => { window.removeEventListener("online", callback, false); window.removeEventListener("offline", callback, false); }; } return void 0; } }; function useOnlineStatus() { const value = useSubscription(SUBSCRIPTION2); useDebugValue10(value); return value; } // src/usePageVisibility.ts import { useDebugValue as useDebugValue11 } from "preact/hooks"; var SUBSCRIPTION3 = { read: () => { if (is_client_default) { return document.visibilityState === "visible"; } return true; }, subscribe: (callback) => { if (is_client_default) { document.addEventListener("visibilitychange", callback, false); return () => { document.removeEventListener("visibilitychange", callback, false); }; } return void 0; } }; function usePageVisibility() { const value = useSubscription(SUBSCRIPTION3); useDebugValue11(value); return value; } // src/usePartialState.tsx import { useState as useState2 } from "preact/hooks"; function isActionFunc(action) { return typeof action === "function"; } function usePartialState(initialState) { const [state, setState] = useState2(initialState); const setPartialState = useConstantCallback((action) => { setState((current) => { const newValue = isActionFunc(action) ? action(current) : action; return __spreadValues(__spreadValues({}, current), newValue); }); }); return [state, setPartialState]; } // src/usePrefersDarkTheme.tsx function usePrefersDarkTheme() { return useMediaQuery("(prefers-color-scheme: dark)"); } // src/usePrefersLightTheme.tsx function usePrefersLightTheme() { return useMediaQuery("(prefers-color-scheme: light)"); } // src/usePrefersReducedMotion.tsx function usePrefersReducedMotion() { return useMediaQuery("(prefers-reduced-motion)"); } // src/useReadyState.tsx import { useDebugValue as useDebugValue12 } from "preact/hooks"; var SUBSCRIPTION4 = { read: () => { if (is_client_default) { return document.readyState; } return void 0; }, subscribe: (callback) => { if (is_client_default) { document.addEventListener("readystatechange", callback, false); return () => { document.removeEventListener("readystatechange", callback, false); }; } return void 0; } }; function useReadyState() { const value = useSubscription(SUBSCRIPTION4); useDebugValue12(value); return value; } // src/useReactiveObject.tsx import { useDebugValue as useDebugValue13 } from "preact/hooks"; function useReactiveObject(supplier) { const object = useConstant(supplier); const forceUpdate = useForceUpdate(); const proxyObject = useConstant(() => new Proxy(object, { get(target, property, handler) { return Reflect.get(target, property, handler); }, set(target, property, value, receiver) { if (!Object.is(Reflect.get(target, property, receiver), value)) { Reflect.set(target, property, value, receiver); forceUpdate(); } return true; } })); useDebugValue13(proxyObject); return proxyObject; } // src/useReactiveRef.ts import { useDebugValue as useDebugValue14 } from "preact/hooks"; function useReactiveRef(supplier) { const forceUpdate = useForceUpdate(); const ref = useLazyRef(supplier); const proxyObject = useConstant(() => ({ get current() { return ref.current; }, set current(value) { if (!Object.is(value, ref.current)) { ref.current = value; forceUpdate(); } } })); useDebugValue14(proxyObject); return proxyObject; } // src/useRenderCount.ts import { useDebugValue as useDebugValue15, useRef as useRef6 } from "preact/hooks"; function useRenderCount() { const ref = useRef6(0); ref.current += 1; useDebugValue15(ref.current); return ref.current; } // src/useWindowScroll.tsx import { useDebugValue as useDebugValue16 } from "preact/hooks"; var SUBSCRIPTION5 = { read: () => { if (is_client_default) { return { x: window.pageXOffset, y: window.pageYOffset }; } return void 0; }, subscribe: (callback) => { if (is_client_default) { window.addEventListener("scroll", callback, { capture: false, passive: true }); return () => { window.removeEventListener("scroll", callback); }; } return void 0; } }; function useWindowScroll() { const value = useSubscription(SUBSCRIPTION5); useDebugValue16(value); return value; } // src/useWindowSize.ts import { useDebugValue as useDebugValue17 } from "preact/hooks"; var SUBSCRIPTION6 = { read: () => { if (is_client_default) { return { width: window.innerWidth, height: window.innerHeight }; } return void 0; }, subscribe: (callback) => { if (is_client_default) { window.addEventListener("resize", callback, false); return () => { window.removeEventListener("resize", callback, false); }; } return void 0; } }; function useWindowSize() { const value = useSubscription(SUBSCRIPTION6); useDebugValue17(value); return value; } export { defaultCompare, useAsyncMemo, useConditionalCallback as useCallbackCondition, useConditionalCallback, useConditionalEffect, useConditionalLayoutEffect, useConditionalMemo, useConstant, useConstantCallback, useDependencyChanged, useDependencyVersion, useConditionalEffect as useEffectCondition, useForceUpdate, useFreshLazyRef, useFreshState, useFullscreenElement, useIsomorphicEffect_default as useIsomorphicEffect, useLazyRef, useMediaQuery, useConditionalMemo as useMemoCondition, useMountedState, useOnlineStatus, usePageVisibility, usePartialState, usePrefersDarkTheme, usePrefersLightTheme, usePrefersReducedMotion, useReactiveObject, useReactiveRef, useReadyState, useRenderCount, useSubscription, useWindowScroll, useWindowSize }; /** * @license * MIT License * * Copyright (c) 2021 Lyon Software Technologies, Inc. * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * * * @author Lyon Software Technologies, Inc. * @copyright Lyon Software Technologies, Inc. 2021 */ /** * @license * MIT License * * Copyright (c) 2021 Lyon Software Technologies, Inc. * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the 'Software'), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * * * @author Lyon Software Technologies, Inc. * @copyright Lyon Software Technologies, Inc. 2021 */ //# sourceMappingURL=index.mjs.map