UNPKG

@lyonph/preact-hooks

Version:

Collection of useful Preact Hooks

672 lines (631 loc) 20.3 kB
"use strict"; var __defProp = Object.defineProperty; var __defProps = Object.defineProperties; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropDescs = Object.getOwnPropertyDescriptors; var __getOwnPropNames = Object.getOwnPropertyNames; 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)); var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/index.ts var src_exports = {}; __export(src_exports, { defaultCompare: () => defaultCompare, useAsyncMemo: () => useAsyncMemo, useCallbackCondition: () => useConditionalCallback, useConditionalCallback: () => useConditionalCallback, useConditionalEffect: () => useConditionalEffect, useConditionalLayoutEffect: () => useConditionalLayoutEffect, useConditionalMemo: () => useConditionalMemo, useConstant: () => useConstant, useConstantCallback: () => useConstantCallback, useDependencyChanged: () => useDependencyChanged, useDependencyVersion: () => useDependencyVersion, useEffectCondition: () => useConditionalEffect, useForceUpdate: () => useForceUpdate, useFreshLazyRef: () => useFreshLazyRef, useFreshState: () => useFreshState, useFullscreenElement: () => useFullscreenElement, useIsomorphicEffect: () => useIsomorphicEffect_default, useLazyRef: () => useLazyRef, useMediaQuery: () => useMediaQuery, useMemoCondition: () => useConditionalMemo, useMountedState: () => useMountedState, useOnlineStatus: () => useOnlineStatus, usePageVisibility: () => usePageVisibility, usePartialState: () => usePartialState, usePrefersDarkTheme: () => usePrefersDarkTheme, usePrefersLightTheme: () => usePrefersLightTheme, usePrefersReducedMotion: () => usePrefersReducedMotion, useReactiveObject: () => useReactiveObject, useReactiveRef: () => useReactiveRef, useReadyState: () => useReadyState, useRenderCount: () => useRenderCount, useSubscription: () => useSubscription, useWindowScroll: () => useWindowScroll, useWindowSize: () => useWindowSize }); module.exports = __toCommonJS(src_exports); // src/useAsyncMemo.ts var import_hooks9 = require("preact/hooks"); // src/useConditionalCallback.tsx var import_hooks2 = require("preact/hooks"); // src/useDependencyChanged.tsx var import_hooks = require("preact/hooks"); function defaultCompare(a, b) { return !Object.is(a, b); } function useDependencyChanged(dependency, shouldUpdate = defaultCompare) { const prevDeps = (0, import_hooks.useRef)(dependency); const result = shouldUpdate(prevDeps.current, dependency); if (result) { prevDeps.current = dependency; } (0, import_hooks.useDebugValue)(result); return result; } // src/useConditionalCallback.tsx function useConditionalCallback(supplier, dependency, shouldUpdate = defaultCompare) { const value = (0, import_hooks2.useRef)(supplier); const dependencyChanged = useDependencyChanged(dependency, shouldUpdate); if (dependencyChanged) { value.current = supplier; } return value.current; } // src/useFreshState.tsx var import_hooks8 = require("preact/hooks"); // src/useConstant.ts var import_hooks4 = require("preact/hooks"); // src/useLazyRef.ts var import_hooks3 = require("preact/hooks"); function useLazyRef(supplier) { const ref = (0, import_hooks3.useRef)(); if (!ref.current) { ref.current = { current: supplier() }; } (0, import_hooks3.useDebugValue)(ref.current); return ref.current; } // src/useConstant.ts function useConstant(supplier) { const { current } = useLazyRef(supplier); (0, import_hooks4.useDebugValue)(current); return current; } // src/useConstantCallback.ts function useConstantCallback(cb) { return useConstant(() => cb); } // src/useForceUpdate.ts var import_hooks5 = require("preact/hooks"); function useForceUpdate() { return (0, import_hooks5.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 var import_hooks7 = require("preact/hooks"); // src/useIsomorphicEffect.ts var import_hooks6 = require("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 ? import_hooks6.useLayoutEffect : import_hooks6.useEffect; var useIsomorphicEffect_default = useIsomorphicEffect; // src/useMountedState.ts function useMountedState() { const alive = (0, import_hooks7.useRef)(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(); } } } ); (0, import_hooks8.useDebugValue)(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); (0, import_hooks9.useEffect)(() => { 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 var import_hooks11 = require("preact/hooks"); // src/useDependencyVersion.tsx var import_hooks10 = require("preact/hooks"); function useDependencyVersion(dependency, shouldUpdate = defaultCompare) { const dependencyChanged = useDependencyChanged(dependency, shouldUpdate); const version = (0, import_hooks10.useRef)(0); if (dependencyChanged) { version.current += 1; } (0, import_hooks10.useDebugValue)(version.current); return version.current; } // src/useConditionalEffect.tsx function useConditionalEffect(supplier, dependency, shouldUpdate = defaultCompare) { const version = useDependencyVersion(dependency, shouldUpdate); (0, import_hooks11.useEffect)(supplier, [version]); } // src/useConditionalLayoutEffect.tsx var import_hooks12 = require("preact/hooks"); function useConditionalLayoutEffect(supplier, dependency, shouldUpdate = defaultCompare) { const version = useDependencyVersion(dependency, shouldUpdate); (0, import_hooks12.useLayoutEffect)(supplier, [version]); } // src/useConditionalMemo.tsx var import_hooks13 = require("preact/hooks"); function useConditionalMemo(supplier, dependency, shouldUpdate = defaultCompare) { const value = useFreshLazyRef( supplier, dependency, shouldUpdate ).current; (0, import_hooks13.useDebugValue)(value); return value; } // src/useFullscreenElement.tsx var import_hooks15 = require("preact/hooks"); // src/useSubscription.ts var import_hooks14 = require("preact/hooks"); function useSubscription({ read, subscribe, shouldUpdate = defaultCompare }) { const [state, setState] = (0, import_hooks14.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 }); } (0, import_hooks14.useDebugValue)(currentValue); (0, import_hooks14.useEffect)(() => { 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); (0, import_hooks15.useDebugValue)(value); return value; } // src/useMediaQuery.tsx var import_hooks16 = require("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); (0, import_hooks16.useDebugValue)(value); return value; } // src/useOnlineStatus.ts var import_hooks17 = require("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); (0, import_hooks17.useDebugValue)(value); return value; } // src/usePageVisibility.ts var import_hooks18 = require("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); (0, import_hooks18.useDebugValue)(value); return value; } // src/usePartialState.tsx var import_hooks19 = require("preact/hooks"); function isActionFunc(action) { return typeof action === "function"; } function usePartialState(initialState) { const [state, setState] = (0, import_hooks19.useState)(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 var import_hooks20 = require("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); (0, import_hooks20.useDebugValue)(value); return value; } // src/useReactiveObject.tsx var import_hooks21 = require("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; } })); (0, import_hooks21.useDebugValue)(proxyObject); return proxyObject; } // src/useReactiveRef.ts var import_hooks22 = require("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(); } } })); (0, import_hooks22.useDebugValue)(proxyObject); return proxyObject; } // src/useRenderCount.ts var import_hooks23 = require("preact/hooks"); function useRenderCount() { const ref = (0, import_hooks23.useRef)(0); ref.current += 1; (0, import_hooks23.useDebugValue)(ref.current); return ref.current; } // src/useWindowScroll.tsx var import_hooks24 = require("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); (0, import_hooks24.useDebugValue)(value); return value; } // src/useWindowSize.ts var import_hooks25 = require("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); (0, import_hooks25.useDebugValue)(value); return value; } /** * @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.cjs.map