@modern-kit/react
Version:
89 lines (86 loc) • 2.5 kB
JavaScript
import { isFunction, at } from '@modern-kit/utils';
import { useState, useMemo, useCallback } from 'react';
function useHistoryState(initialValue, capacity = 10) {
const initialValueToUse = isFunction(initialValue) ? initialValue() : initialValue;
const [state, innerSetState] = useState({
history: [initialValueToUse],
current: initialValueToUse,
pointer: 0
});
const canForward = useMemo(
() => state.pointer < state.history.length - 1,
[state.pointer, state.history.length]
);
const canBack = useMemo(() => state.pointer > 0, [state.pointer]);
const setState = useCallback(
(newState) => {
innerSetState((prev) => {
const history = [...prev.history];
const newStateToUse = isFunction(newState) ? newState(history[prev.pointer]) : newState;
if (history.length === capacity) {
history.shift();
}
history.push(newStateToUse);
const pointer = history.length - 1;
return { history, current: newStateToUse, pointer };
});
},
[capacity]
);
const replaceState = useCallback((newState) => {
innerSetState((prev) => {
const history = [...prev.history];
const newStateToUse = isFunction(newState) ? newState(history[prev.pointer]) : newState;
history[prev.pointer] = newStateToUse;
return { ...prev, history, current: newStateToUse };
});
}, []);
const back = useCallback(() => {
innerSetState((prev) => {
if (prev.pointer < 1) {
return prev;
}
const pointer = prev.pointer - 1;
return {
...prev,
current: prev.history[pointer],
pointer
};
});
}, []);
const forward = useCallback(() => {
innerSetState((prev) => {
if (prev.pointer >= prev.history.length - 1) {
return prev;
}
const pointer = prev.pointer + 1;
return {
...prev,
current: prev.history[pointer],
pointer
};
});
}, []);
const go = useCallback((index) => {
innerSetState((prev) => {
const element = at(prev.history, index);
if (element == null) {
return prev;
}
const pointer = index < 0 ? prev.history.length + index : index;
return { ...prev, current: element, pointer };
});
}, []);
return {
state: state.current,
canForward,
canBack,
setState,
replaceState,
forward,
back,
go
};
}
export { useHistoryState };
//# sourceMappingURL=index.mjs.map