react-storage-drafts
Version:
React Drafts is a library for creating, saving, and managing local documents in React applications.
113 lines (112 loc) • 4.68 kB
JavaScript
import { jsx as _jsx } from "react/jsx-runtime";
import { useCallback, useEffect, useMemo, useState } from 'react';
import { nanoid } from 'nanoid';
import DraftsContext from './Context';
import useOnline from './useOnline';
import { EDraftStatus } from './types';
export default function Provider({ referenceKey = '_duid', syncTrigger, syncInterval = 120, ...props }) {
const isOnline = useOnline({
enabled: syncTrigger === 'connection',
});
const [allDrafts, setDrafts] = useState([]);
const [count, setCount] = useState(0);
const [isLoadedStore, setIsLoadedStore] = useState(false);
const drafts = useMemo(() => {
return allDrafts.filter((draft) => (draft === null || draft === void 0 ? void 0 : draft.status) !== EDraftStatus.REMOVED);
}, [allDrafts]);
const unsyncedDrafts = useMemo(() => {
return allDrafts.filter((draft) => (draft === null || draft === void 0 ? void 0 : draft.status) === EDraftStatus.CHANGED || (draft === null || draft === void 0 ? void 0 : draft.status) === EDraftStatus.REMOVED);
}, [allDrafts]);
const loadStoredData = useCallback(async () => {
if (typeof (props === null || props === void 0 ? void 0 : props.onLoadStoredData) !== 'function') {
return;
}
const storedData = await (props === null || props === void 0 ? void 0 : props.onLoadStoredData());
setDrafts(storedData);
setIsLoadedStore(true);
}, [props === null || props === void 0 ? void 0 : props.onLoadStoredData]);
useEffect(() => {
if (isLoadedStore) {
return;
}
loadStoredData();
}, [isLoadedStore, loadStoredData]);
const getDraft = useCallback((draftKey) => {
var _a;
return (_a = drafts.find((current) => current[referenceKey] === draftKey)) !== null && _a !== void 0 ? _a : null;
}, [drafts, referenceKey]);
const addDraft = useCallback((draft) => {
if (!(draft === null || draft === void 0 ? void 0 : draft[referenceKey])) {
draft._duid = nanoid();
}
setDrafts((prev) => [...prev, { ...draft, status: EDraftStatus.CHANGED }]);
}, [referenceKey]);
const updateDraft = useCallback((draftKey, changes) => {
setDrafts((prev) => prev.map((current) => {
if (current[referenceKey] === draftKey) {
current = { ...current, ...changes, status: EDraftStatus.CHANGED };
}
return current;
}));
}, [referenceKey]);
const removeDraft = useCallback((draftKey) => {
setDrafts((prev) => prev.map((current) => {
if (current[referenceKey] === draftKey) {
current = { ...current, status: EDraftStatus.REMOVED };
}
return current;
}));
}, [referenceKey]);
const clearDrafts = useCallback(() => {
setDrafts((prev) => prev.map((current) => ({
...current,
status: EDraftStatus.REMOVED
})));
}, []);
useEffect(() => {
setCount(drafts === null || drafts === void 0 ? void 0 : drafts.length);
}, [drafts]);
const handleSync = useCallback(async () => {
if (!unsyncedDrafts.length || typeof (props === null || props === void 0 ? void 0 : props.onSync) !== 'function') {
return;
}
props.onSync(unsyncedDrafts);
setDrafts((drafts) => drafts.reduce((prev, { status, ...draft }) => {
if (status !== EDraftStatus.REMOVED) {
prev.push(draft);
}
return prev;
}, []));
}, [props === null || props === void 0 ? void 0 : props.onSync, unsyncedDrafts]);
useEffect(() => {
if (syncTrigger === 'interval' || syncTrigger === 'manual') {
return;
}
if (syncTrigger === 'onChange' || (syncTrigger === 'connection' && isOnline)) {
handleSync();
}
}, [isOnline, handleSync, syncTrigger]);
useEffect(() => {
if (syncTrigger !== 'interval') {
return;
}
const interval = setInterval(() => {
handleSync();
}, syncInterval * 1000);
return () => {
clearInterval(interval);
};
}, [handleSync, syncInterval, syncTrigger]);
const value = useMemo(() => ({
count,
drafts,
addDraft,
getDraft,
clearDrafts,
removeDraft,
updateDraft,
referenceKey,
handleSync,
}), [count, drafts, addDraft, clearDrafts, getDraft, removeDraft, updateDraft, referenceKey, handleSync]);
return _jsx(DraftsContext.Provider, { value: value, children: props.children });
}