alistair
Version:
212 lines (208 loc) • 5.59 kB
JavaScript
;
var chunk7JYVLPRQ_cjs = require('./chunk-7JYVLPRQ.cjs');
var react = require('react');
// Copyright 2026 Alistair Smith https://github.com/alii/alistair
function useAsyncFunction(execute) {
const [state, setState] = react.useState({
loading: false,
result: { type: "initial" }
});
const isInFlight = react.useRef(false);
const run = chunk7JYVLPRQ_cjs.useEvent(async (...args) => {
if (isInFlight.current) {
throw new Error("Cannot execute while currently in flight");
}
setState((old) => ({ ...old, loading: true }));
isInFlight.current = true;
try {
const data = await execute(...args);
setState({
loading: false,
result: {
type: "success",
data
}
});
return {
type: "success",
data
};
} catch (error) {
setState({
loading: false,
result: {
type: "error",
error
}
});
return {
type: "error",
error
};
} finally {
isInFlight.current = false;
}
});
const reset = react.useCallback(() => {
setState({
loading: false,
result: { type: "initial" }
});
}, []);
return [state, run, reset];
}
function useInterval(callback, delay, options) {
const runImmediately = options?.runImmediately ?? false;
const savedCallback = react.useRef(callback);
react.useEffect(() => {
savedCallback.current = callback;
}, [callback]);
react.useEffect(() => {
if (delay === null) {
return;
}
const tick = () => {
savedCallback.current();
};
const id = setInterval(tick, delay);
if (runImmediately) {
tick();
}
return () => {
clearInterval(id);
};
}, [delay]);
}
function useIsOnline() {
return react.useSyncExternalStore(
(notify) => {
window.addEventListener("online", notify);
window.addEventListener("offline", notify);
return () => {
window.removeEventListener("online", notify);
window.removeEventListener("offline", notify);
};
},
() => navigator.onLine,
() => false
);
}
function useIsTabFocused() {
return react.useSyncExternalStore(
(notify) => {
const listener = () => {
notify();
};
document.addEventListener("visibilitychange", listener);
return () => {
document.removeEventListener("visibilitychange", listener);
};
},
() => document.visibilityState === "visible",
() => false
);
}
var useTabFocused = useIsTabFocused;
var SENTINEL = {};
function useLazyRef(init) {
const ref = react.useRef(SENTINEL);
if (ref.current === SENTINEL) {
ref.current = init();
}
return ref;
}
function useLocalStorage(key, init) {
const stableInit = react.useRef(init);
react.useEffect(() => {
stableInit.current = init;
}, [init]);
const write = react.useCallback(
(value2) => {
window.localStorage.setItem(key, JSON.stringify(value2));
return value2;
},
[key]
);
const getOrInit = react.useCallback(() => {
if (typeof window === "undefined") {
return stableInit.current();
}
const value2 = window.localStorage.getItem(key);
if (value2 === null) {
const initialised = stableInit.current();
return write(initialised);
}
return JSON.parse(value2);
}, [key, write]);
const [value, setValue] = react.useState(() => getOrInit());
const notify = react.useCallback(() => {
setValue(getOrInit());
}, []);
react.useEffect(() => {
const listener = (event) => {
if (event.key === key) {
notify();
}
};
window.addEventListener("storage", listener);
return () => {
window.removeEventListener("storage", listener);
};
}, []);
const set = react.useCallback(
(action) => {
const current = getOrInit();
let next;
if (action instanceof Function) {
next = write(action(current));
} else {
next = write(action);
}
window.dispatchEvent(
new StorageEvent("storage", {
key,
oldValue: JSON.stringify(current),
newValue: JSON.stringify(next),
url: window.location.href
})
);
},
[getOrInit, write]
);
return [value, set];
}
function useThrottle(value, limit = 1e3) {
const [throttledValue, setThrottledValue] = react.useState(value);
const lastRan = react.useRef(Date.now());
react.useEffect(() => {
const handler = setTimeout(() => {
if (Date.now() - lastRan.current >= limit) {
setThrottledValue(value);
lastRan.current = Date.now();
}
}, limit - (Date.now() - lastRan.current));
return () => {
clearTimeout(handler);
};
}, [value, limit]);
return throttledValue;
}
function useToggle(initialState = false) {
const [state, setState] = react.useState(initialState);
const handlers = {
on: react.useCallback(() => setState(true), []),
off: react.useCallback(() => setState(false), []),
toggle: react.useCallback(() => setState((state2) => !state2), []),
reset: react.useCallback(() => setState(initialState), [initialState])
};
return [state, handlers];
}
exports.useAsyncFunction = useAsyncFunction;
exports.useInterval = useInterval;
exports.useIsOnline = useIsOnline;
exports.useIsTabFocused = useIsTabFocused;
exports.useLazyRef = useLazyRef;
exports.useLocalStorage = useLocalStorage;
exports.useTabFocused = useTabFocused;
exports.useThrottle = useThrottle;
exports.useToggle = useToggle;