react-native-chart-kit
Version:
Beautiful React Native charts for dashboards, reports, and data-rich mobile apps.
93 lines (92 loc) • 4.03 kB
JavaScript
import { jsx as _jsx } from "react/jsx-runtime";
import { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState } from "react";
import { View } from "react-native";
import { getScopedChartSelectionClearReason, shouldClearScopedChartSelection } from "./scope";
const ChartSelectionContext = createContext(undefined);
export const ChartSelectionProvider = ({ children, dismissOnPressOutside = false, style }) => {
const pendingDismissTimeoutRef = useRef(null);
const [state, setState] = useState({
activeChartId: undefined,
dismissRevision: 0
});
const cancelPendingOutsideDismiss = useCallback(() => {
if (pendingDismissTimeoutRef.current) {
clearTimeout(pendingDismissTimeoutRef.current);
pendingDismissTimeoutRef.current = null;
}
}, []);
const applyDismissSelection = useCallback(() => {
setState((current) => ({
activeChartId: undefined,
dismissRevision: current.dismissRevision + 1
}));
}, []);
const selectChart = useCallback((chartId) => {
cancelPendingOutsideDismiss();
setState((current) => current.activeChartId === chartId
? current
: { ...current, activeChartId: chartId });
}, [cancelPendingOutsideDismiss]);
const dismissSelection = useCallback(() => {
cancelPendingOutsideDismiss();
applyDismissSelection();
}, [applyDismissSelection, cancelPendingOutsideDismiss]);
const scheduleOutsideDismiss = useCallback(() => {
cancelPendingOutsideDismiss();
pendingDismissTimeoutRef.current = setTimeout(() => {
pendingDismissTimeoutRef.current = null;
applyDismissSelection();
}, 0);
}, [applyDismissSelection, cancelPendingOutsideDismiss]);
const handleStartShouldSetResponderCapture = useCallback((_event) => {
scheduleOutsideDismiss();
return false;
}, [scheduleOutsideDismiss]);
useEffect(() => cancelPendingOutsideDismiss, [cancelPendingOutsideDismiss]);
const value = useMemo(() => ({
...state,
dismissSelection,
selectChart
}), [dismissSelection, selectChart, state]);
return (_jsx(ChartSelectionContext.Provider, { value: value, children: dismissOnPressOutside ? (_jsx(View, { collapsable: false, onStartShouldSetResponderCapture: handleStartShouldSetResponderCapture, style: style, children: children })) : (children) }));
};
export const useChartSelection = () => useContext(ChartSelectionContext);
export const useDismissChartSelection = () => {
const context = useChartSelection();
return useCallback((reason) => {
context?.dismissSelection(reason);
}, [context]);
};
export const useScopedChartSelection = ({ chartId, controlled, hasSelection, onClear }) => {
const context = useChartSelection();
const lastDismissRevisionRef = useRef(context?.dismissRevision ?? 0);
useEffect(() => {
if (!context) {
return;
}
const lastDismissRevision = lastDismissRevisionRef.current;
const shouldClear = !controlled &&
shouldClearScopedChartSelection({
activeChartId: context.activeChartId,
chartId,
dismissRevision: context.dismissRevision,
hasSelection,
lastDismissRevision
});
lastDismissRevisionRef.current = context.dismissRevision;
if (shouldClear) {
onClear(getScopedChartSelectionClearReason({
activeChartId: context.activeChartId,
chartId,
dismissRevision: context.dismissRevision,
lastDismissRevision
}) ?? "programmatic");
}
}, [chartId, context, controlled, hasSelection, onClear]);
return useMemo(() => ({
dismissSelection: context?.dismissSelection,
selectChart: () => {
context?.selectChart(chartId);
}
}), [chartId, context]);
};