react-native-leader-line
Version:
React Native port of leader-line library for drawing arrow lines and connectors
177 lines • 5.92 kB
JavaScript
import { useCallback, useEffect, useRef, useState } from "react";
// Simplified manager for basic functionality
export const useLeaderLineManager = (options = {}) => {
const [lines, setLines] = useState(new Map());
const [isInitialized, setIsInitialized] = useState(false);
// Performance tracking
const [updateQueue, setUpdateQueue] = useState([]);
const updateTimeoutRef = useRef(null);
// Batch updates for better performance
const processBatchUpdates = useCallback(() => {
if (updateQueue.length === 0)
return;
setLines((prev) => {
const newLines = new Map(prev);
updateQueue.forEach(({ id, props }) => {
const existing = newLines.get(id);
if (existing) {
newLines.set(id, {
...existing,
props: { ...existing.props, ...props },
lastUpdate: Date.now(),
});
}
});
return newLines;
});
setUpdateQueue([]);
}, [updateQueue]);
// Debounced batch update
const queueUpdate = useCallback((id, props) => {
setUpdateQueue((prev) => {
const existingIndex = prev.findIndex((item) => item.id === id);
const newQueue = [...prev];
if (existingIndex >= 0) {
const existingItem = newQueue[existingIndex];
if (existingItem) {
newQueue[existingIndex] = {
id,
props: { ...existingItem.props, ...props },
};
}
}
else {
newQueue.push({ id, props });
}
return newQueue;
});
// Clear existing timeout and set new one
if (updateTimeoutRef.current) {
clearTimeout(updateTimeoutRef.current);
}
updateTimeoutRef.current = setTimeout(() => {
processBatchUpdates();
}, 16); // ~60fps batching
}, [processBatchUpdates]);
const createLine = useCallback((id, props = {}) => {
setLines((prev) => {
const newLines = new Map(prev);
newLines.set(id, {
id,
props,
isVisible: true,
lastUpdate: Date.now(),
});
return newLines;
});
return id;
}, []);
// Alias for createLine to match test expectations
const addLine = useCallback((id, props = {}) => {
return createLine(id, props);
}, [createLine]);
const updateLine = useCallback((id, props) => {
if (options.batchUpdates !== false) {
queueUpdate(id, props);
}
else {
// Immediate update
setLines((prev) => {
const newLines = new Map(prev);
const existing = newLines.get(id);
if (existing) {
newLines.set(id, {
...existing,
props: { ...existing.props, ...props },
lastUpdate: Date.now(),
});
}
return newLines;
});
}
}, [options.batchUpdates, queueUpdate]);
// Enhanced bulk operations
const updateMultipleLines = useCallback((updates) => {
setLines((prev) => {
const newLines = new Map(prev);
updates.forEach(({ id, props }) => {
const existing = newLines.get(id);
if (existing) {
newLines.set(id, {
...existing,
props: { ...existing.props, ...props },
lastUpdate: Date.now(),
});
}
});
return newLines;
});
}, []);
const removeLine = useCallback((id) => {
setLines((prev) => {
const newLines = new Map(prev);
newLines.delete(id);
return newLines;
});
}, []);
const showLine = useCallback((id) => {
updateLine(id, { opacity: 1 });
}, [updateLine]);
const hideLine = useCallback((id) => {
updateLine(id, { opacity: 0 });
}, [updateLine]);
const refreshAll = useCallback(() => {
setLines((prev) => {
const newLines = new Map(prev);
for (const [id, line] of newLines) {
newLines.set(id, {
...line,
lastUpdate: Date.now(),
});
}
return newLines;
});
}, []);
const clear = useCallback(() => {
setLines(new Map());
}, []);
// Alias for clear to match test expectations
const clearAll = useCallback(() => {
clear();
}, [clear]);
// Cleanup on unmount
useEffect(() => {
return () => {
if (updateTimeoutRef.current) {
clearTimeout(updateTimeoutRef.current);
}
};
}, []);
useEffect(() => {
setIsInitialized(true);
}, []);
return {
lines: Array.from(lines.values()),
isInitialized,
createLine,
addLine,
updateLine,
updateMultipleLines, // New bulk update method
removeLine,
showLine,
hideLine,
refreshAll,
clear,
clearAll,
getLine: (id) => lines.get(id),
hasLine: (id) => lines.has(id),
// Performance utilities
getPerformanceMetrics: () => ({
totalLines: lines.size,
queuedUpdates: updateQueue.length,
lastUpdateTime: Math.max(...Array.from(lines.values()).map((l) => l.lastUpdate || 0)),
}),
};
};
export default useLeaderLineManager;
//# sourceMappingURL=useLeaderLineManager.js.map