react-native-sortables
Version:
Powerful Sortable Components for Flexible Content Reordering in React Native
154 lines (151 loc) • 5.05 kB
JavaScript
;
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { cancelAnimation, makeMutable, runOnUI, useAnimatedRef } from 'react-native-reanimated';
import { useDebouncedStableCallback } from '../../hooks';
import { createProvider } from '../../providers/utils';
import { DebugComponentType } from '../../types/debug';
const {
DebugProvider,
useDebugContext
} = createProvider('Debug', {
guarded: false
})(({
enabled
}) => {
const debugIdRef = useRef(0);
const debugViewsRef = useRef({});
const observersRef = useRef(new Set());
const debugOutletRef = useAnimatedRef();
const getNextKey = useCallback(() => debugIdRef.current++, []);
const notifyObservers = useDebouncedStableCallback(() => {
const views = debugViewsRef.current;
for (const observer of observersRef.current) {
observer({
...views
});
}
});
const createUpdater = useCallback(type => {
const props = makeMutable({
visible: false
});
return {
hide() {
'worklet';
props.value = {
...props.value,
visible: false
};
},
props,
set(newProps) {
'worklet';
if (typeof newProps === 'function') {
const prevProps = props.value;
props.value = newProps(prevProps);
} else {
props.value = newProps;
}
},
type
};
}, []);
const addUpdater = useCallback((key, updater) => {
debugViewsRef.current[key] = updater;
notifyObservers();
return updater;
}, [notifyObservers]);
const removeUpdater = useCallback(key => {
const updater = debugViewsRef.current[key];
if (!updater) {
return;
}
runOnUI(cancelAnimation)(updater.props);
delete debugViewsRef.current[key];
notifyObservers();
}, [notifyObservers]);
const useDebugComponent = useCallback(type => {
const key = useMemo(getNextKey, []);
const updater = useMemo(() => addUpdater(key, createUpdater(type)), [type, key]);
useEffect(() => {
return () => {
removeUpdater(key);
};
}, [updater, key]);
return updater;
}, [removeUpdater, createUpdater, addUpdater, getNextKey]);
const useDebugComponents = useCallback((type, keysOrCount) => {
const isNumber = typeof keysOrCount === 'number';
const [keys] = useState(isNumber ? [] : {});
const [updaters] = useState(() => isNumber ? [] : {});
useEffect(() => {
return () => {
for (const key of Object.values(keys)) {
removeUpdater(key);
}
};
}, [keys]);
if (isNumber && Array.isArray(keys) && Array.isArray(updaters)) {
if (keys.length < keysOrCount) {
for (let i = keys.length; i < keysOrCount; i++) {
const key = getNextKey();
keys.push(key);
updaters.push(addUpdater(key, createUpdater(type)));
}
} else {
const removedKeys = keys.splice(keysOrCount);
updaters.splice(keysOrCount);
removedKeys.forEach(removeUpdater);
}
} else if (!isNumber && !Array.isArray(keys) && !Array.isArray(updaters)) {
const resultKeySet = new Set(keysOrCount);
for (const [resultKey, key] of Object.entries(keys)) {
if (!resultKeySet.has(resultKey)) {
removeUpdater(key);
delete keys[resultKey];
delete updaters[resultKey];
}
}
for (const resultKey of keysOrCount) {
if (!updaters[resultKey]) {
const key = getNextKey();
keys[resultKey] = key;
updaters[resultKey] = addUpdater(key, createUpdater(type));
}
}
}
return Array.isArray(updaters) ? [...updaters] : {
...updaters
};
}, [removeUpdater, createUpdater, addUpdater, getNextKey]);
const useDebugLine = useCallback(() => useDebugComponent(DebugComponentType.LINE), [useDebugComponent]);
const useDebugRect = useCallback(() => useDebugComponent(DebugComponentType.RECT), [useDebugComponent]);
const useDebugCross = useCallback(() => useDebugComponent(DebugComponentType.CROSS), [useDebugComponent]);
const useDebugLines = useCallback(keysOrCount => useDebugComponents(DebugComponentType.LINE, keysOrCount), [useDebugComponents]);
const useDebugRects = useCallback(keysOrCount => useDebugComponents(DebugComponentType.RECT, keysOrCount), [useDebugComponents]);
const useObserver = useCallback(observer => {
useEffect(() => {
const observers = observersRef.current;
observers.add(observer);
// Notify the observer immediately after adding it
observer(debugViewsRef.current);
return () => {
observers.delete(observer);
};
}, [observer]);
}, []);
return {
enabled,
value: {
debugOutletRef,
useDebugCross,
useDebugLine,
useDebugLines: useDebugLines,
useDebugRect,
useDebugRects: useDebugRects,
useObserver
}
};
});
export { DebugProvider, useDebugContext };
//# sourceMappingURL=DebugProvider.js.map