react-photo-album
Version:
Responsive photo gallery component for React
56 lines (55 loc) • 2.36 kB
JavaScript
"use client";
import { useCallback, useReducer, useRef, useState } from "react";
//#region src/client/hooks/useArray.ts
function useArray(array) {
const [state, setState] = useState(array);
if (array !== state && (!array || !state || array.length !== state.length || array.some((el, i) => el !== state[i]))) {
setState(array);
return array;
}
return state;
}
//#endregion
//#region src/client/hooks/useContainerWidth.ts
var MAX_SCROLLBAR_WIDTH = 20;
function containerWidthReducer(state, newContainerWidth) {
const [containerWidth, prevContainerWidth] = state;
if (containerWidth === newContainerWidth) return state;
if (prevContainerWidth !== void 0 && newContainerWidth !== void 0 && containerWidth !== void 0 && newContainerWidth === prevContainerWidth && Math.abs(newContainerWidth - containerWidth) <= MAX_SCROLLBAR_WIDTH) {
const min = Math.min(containerWidth, newContainerWidth);
const max = Math.max(containerWidth, newContainerWidth);
return min === containerWidth && max === prevContainerWidth ? state : [min, max];
}
return [newContainerWidth, containerWidth];
}
function resolveContainerWidth(el, breakpoints) {
let width = el?.clientWidth;
if (width !== void 0 && breakpoints && breakpoints.length > 0) {
const sorted = [...breakpoints.filter((x) => x > 0)].sort((a, b) => b - a);
sorted.push(Math.floor(sorted[sorted.length - 1] / 2));
width = sorted.find((breakpoint, index) => breakpoint <= width || index === sorted.length - 1);
}
return width;
}
function useContainerWidth(ref, breakpointsArray, defaultContainerWidth) {
const [[containerWidth], dispatch] = useReducer(containerWidthReducer, [defaultContainerWidth]);
const breakpoints = useArray(breakpointsArray);
const observerRef = useRef(void 0);
return {
containerRef: useCallback((node) => {
observerRef.current?.disconnect();
observerRef.current = void 0;
const updateWidth = () => dispatch(resolveContainerWidth(node, breakpoints));
updateWidth();
if (node && typeof ResizeObserver !== "undefined") {
observerRef.current = new ResizeObserver(updateWidth);
observerRef.current.observe(node);
}
if (typeof ref === "function") ref(node);
else if (ref) ref.current = node;
}, [ref, breakpoints]),
containerWidth
};
}
//#endregion
export { useArray, useContainerWidth, useContainerWidth as useContainerWidth$1 };