@react-awesome/use-breakpoint
Version:
useBreakpoint triggers callback when a container's size is equal to one specific breakpoint.
97 lines (96 loc) • 3.12 kB
JavaScript
;
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const react = require("react");
const smaller = require("../helpers/smaller/smaller.cjs");
const smallerOrEqual = require("../helpers/smallerOrEqual/smallerOrEqual.cjs");
const greater = require("../helpers/greater/greater.cjs");
const greaterOrEqual = require("../helpers/greaterOrEqual/greaterOrEqual.cjs");
const between = require("../helpers/between/between.cjs");
const DEFAULT_BREAKPOINTS = {
sm: 640,
md: 768,
lg: 1024,
xl: 1280,
"2xl": 1536
};
function useBreakpoint(opts = {}) {
const {
breakpoints: BPS = DEFAULT_BREAKPOINTS,
callbacks,
fallbackValue,
containerEl
} = opts;
const [currentBreakpoint, setCurrentBreakpoint] = react.useState(fallbackValue);
const [el, setEl] = react.useState(null);
const BPS_VALUES_ARR = react.useMemo(
() => Object.values(BPS).sort((a, b) => a - b),
[BPS]
);
const BPS_BY_KEYS = react.useMemo(
() => Object.keys(BPS).reduce((obj, key) => {
const bpKey = BPS[key];
if (obj[bpKey]) {
throw new Error(
`Found two breakpoints has the same value: ${obj[bpKey]} and ${key}`
);
}
obj[bpKey] = key;
return obj;
}, {}),
[BPS]
);
const determineCurrentBreakpoint = react.useCallback(
({ width }) => {
let currentBp = BPS_VALUES_ARR[0];
for (let i = 0; i < BPS_VALUES_ARR.length; i++) {
currentBp = BPS_VALUES_ARR[i];
if (i === 0 && width <= currentBp) {
setCurrentBreakpoint(BPS_BY_KEYS[currentBp.toString()]);
break;
} else if (width > BPS_VALUES_ARR[i - 1] && width <= currentBp) {
setCurrentBreakpoint(BPS_BY_KEYS[currentBp.toString()]);
break;
} else if (i + 1 === BPS_VALUES_ARR.length && width > currentBp) {
setCurrentBreakpoint(BPS_BY_KEYS[currentBp.toString()]);
break;
}
}
return BPS_BY_KEYS[currentBp];
},
[BPS_BY_KEYS, BPS_VALUES_ARR]
);
react.useEffect(() => {
if (typeof containerEl === "undefined")
setEl(window.document.body);
else if (containerEl !== el)
setEl(containerEl);
}, [containerEl, el]);
react.useEffect(() => {
if (!el)
return;
const callback = (entries) => {
var _a;
const [entry] = entries;
const { width, height } = entry.contentRect;
const currentBp = determineCurrentBreakpoint({
width,
height
});
(_a = callbacks == null ? void 0 : callbacks[currentBp]) == null ? void 0 : _a.call(callbacks);
};
const resizeObserver = new ResizeObserver(callback);
resizeObserver.observe(el);
return () => {
resizeObserver.disconnect();
};
}, [callbacks, determineCurrentBreakpoint, el]);
return {
currentBreakpoint,
smaller: smaller.smaller(BPS, el),
smallerOrEqual: smallerOrEqual.smallerOrEqual(BPS, el),
greater: greater.greater(BPS, el),
greaterOrEqual: greaterOrEqual.greaterOrEqual(BPS, el),
between: between.between(BPS, el)
};
}
exports.useBreakpoint = useBreakpoint;