@kietpt2003/react-native-core-ui
Version:
React Native Core UI components by KietPT
147 lines (146 loc) • 6.93 kB
JavaScript
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
import { jsx as _jsx } from "react/jsx-runtime";
import React from "react";
import { findNodeHandle, } from "react-native";
import Animated, { runOnUI, useAnimatedStyle, useSharedValue, } from "react-native-reanimated";
import { typedMemo } from "../utils/DraggableFlatList/typedMemo";
import { WEB } from "../utils";
import { CellProvider } from "../context/DraggableFlatList/cellContext";
import { useRefs } from "../context/DraggableFlatList/refContext";
import { useDraggableFlatListContext } from "../context/DraggableFlatList/draggableFlatListContext";
import { useAnimatedValues } from "../context/DraggableFlatList/animatedValueContext";
import { useStableCallback } from "../hooks/DraggableFlatList/useStableCallback";
import { useCellTranslate } from "../hooks/DraggableFlatList/useCellTranslate";
function CellRendererComponent(props) {
const { item, index, onLayout, children } = props, rest = __rest(props, ["item", "index", "onLayout", "children"]);
const viewRef = React.useRef(null);
const { cellDataRef, propsRef, containerRef } = useRefs();
const { horizontalAnim, scrollOffset } = useAnimatedValues();
const { activeKey, keyExtractor, horizontal, layoutAnimationDisabled } = useDraggableFlatListContext();
const key = keyExtractor(item, index);
const offset = useSharedValue(-1);
const size = useSharedValue(-1);
const heldTanslate = useSharedValue(0);
const translate = useCellTranslate({
cellOffset: offset,
cellSize: size,
cellIndex: index,
});
const isActive = activeKey === key;
const animStyle = useAnimatedStyle(() => {
// When activeKey becomes null at the end of a drag and the list reorders,
// the animated style may apply before the next paint, causing a flicker.
// Solution is to hold over the last animated value until the next onLayout.
// (Not required in web)
if (translate.value && !WEB) {
heldTanslate.value = translate.value;
}
const t = activeKey ? translate.value : heldTanslate.value;
return {
transform: [horizontalAnim.value ? { translateX: t } : { translateY: t }],
};
}, [translate, activeKey]);
const updateCellMeasurements = useStableCallback(() => {
const onSuccess = (x, y, w, h) => {
if (WEB && horizontal)
x += scrollOffset.value;
const cellOffset = horizontal ? x : y;
const cellSize = horizontal ? w : h;
cellDataRef.current.set(key, {
measurements: { size: cellSize, offset: cellOffset },
});
size.value = cellSize;
offset.value = cellOffset;
};
const onFail = () => {
var _a;
if ((_a = propsRef.current) === null || _a === void 0 ? void 0 : _a.debug) {
console.log(`## on measure fail, index: ${index}`);
}
};
const containerNode = containerRef.current;
const viewNode = viewRef.current;
const nodeHandle = containerNode;
if (viewNode && nodeHandle) {
//@ts-ignore
viewNode.measureLayout(nodeHandle, onSuccess, onFail);
}
});
const onCellLayout = useStableCallback((e) => {
heldTanslate.value = 0;
updateCellMeasurements();
if (onLayout && e)
onLayout(e);
});
React.useEffect(() => {
if (WEB) {
// onLayout isn't called on web when the cell index changes, so we manually re-measure
requestAnimationFrame(() => {
onCellLayout();
});
}
}, [index, onCellLayout]);
const baseStyle = React.useMemo(() => {
return {
elevation: isActive ? 1 : 0,
zIndex: isActive ? 999 : 0,
flexDirection: horizontal ? "row" : "column",
};
}, [isActive, horizontal]);
const { itemEnteringAnimation, itemExitingAnimation, itemLayoutAnimation } = propsRef.current;
React.useEffect(() => {
// NOTE: Keep an eye on reanimated LayoutAnimation refactor:
// https://github.com/software-mansion/react-native-reanimated/pull/3332/files
// We might have to change the way we register/unregister LayouAnimations:
// - get native module: https://github.com/software-mansion/react-native-reanimated/blob/cf59766460d05eb30357913455318d8a95909468/src/reanimated2/NativeReanimated/NativeReanimated.ts#L18
// - register layout animation for tag: https://github.com/software-mansion/react-native-reanimated/blob/cf59766460d05eb30357913455318d8a95909468/src/reanimated2/NativeReanimated/NativeReanimated.ts#L99
if (!propsRef.current.enableLayoutAnimationExperimental)
return;
const tag = findNodeHandle(viewRef.current);
runOnUI((t, _layoutDisabled) => {
"worklet";
if (!t)
return;
const config = global.LayoutAnimationRepository.configs[t];
if (config)
stashConfig(t, config);
const stashedConfig = getStashedConfig(t);
if (_layoutDisabled) {
global.LayoutAnimationRepository.removeConfig(t);
}
else if (stashedConfig) {
global.LayoutAnimationRepository.registerConfig(t, stashedConfig);
}
})(tag, layoutAnimationDisabled);
}, [layoutAnimationDisabled]);
return (_jsx(Animated.View, Object.assign({}, rest, { ref: viewRef, onLayout: onCellLayout, entering: itemEnteringAnimation, exiting: itemExitingAnimation, layout: propsRef.current.enableLayoutAnimationExperimental
? itemLayoutAnimation
: undefined, style: [props.style, baseStyle, animStyle], pointerEvents: activeKey ? "none" : "auto", children: _jsx(CellProvider, { isActive: isActive, children: children }) })));
}
export default typedMemo(CellRendererComponent);
runOnUI(() => {
"worklet";
global.RNDFLLayoutAnimationConfigStash = {};
})();
function stashConfig(tag, config) {
"worklet";
if (!global.RNDFLLayoutAnimationConfigStash)
global.RNDFLLayoutAnimationConfigStash = {};
global.RNDFLLayoutAnimationConfigStash[tag] = config;
}
function getStashedConfig(tag) {
"worklet";
if (!global.RNDFLLayoutAnimationConfigStash)
return null;
return global.RNDFLLayoutAnimationConfigStash[tag];
}