@lyonph/preact-hooks
Version:
Collection of useful Preact Hooks
672 lines (631 loc) • 20.3 kB
JavaScript
;
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