@kubit-ui-web/react-components
Version:
Kubit React Components is a customizable, accessible library of React web components, designed to enhance your application's user experience
86 lines • 3.71 kB
JavaScript
import { detectOverflow } from '../utils/detectOverflow';
import { getAlignmentSides } from '../utils/getAlignmentSides';
import { getOppositePlacement } from '../utils/getOppositePlacement';
/**
* Optimizes the visibility of the floating element by flipping the `placement`
* in order to keep it in view when the preferred placement(s) will overflow the
* clipping boundary. Alternative to `autoPlacement`.
* @see https://floating-ui.com/docs/flip
*/
export const flip = (options = {}) => ({
name: 'flip',
options,
fn(state) {
const { placement, middlewareData, rects, initialPlacement } = state;
const { mainAxis: checkMainAxis = true, crossAxis: checkCrossAxis = true, fallbackPlacements: specifiedFallbackPlacements, fallbackStrategy = 'bestFit', ...detectOverflowOptions } = options;
const fallbackPlacements = specifiedFallbackPlacements || [
getOppositePlacement(initialPlacement),
];
const placements = [initialPlacement, ...fallbackPlacements];
const overflow = detectOverflow(state, detectOverflowOptions);
const overflows = [];
let overflowsData = middlewareData.flip?.overflows || [];
if (checkMainAxis) {
overflows.push(overflow[placement]);
}
if (checkCrossAxis) {
const { main, cross } = getAlignmentSides(placement, rects);
overflows.push(overflow[main], overflow[cross]);
}
overflowsData = [...overflowsData, { placement, overflows }];
// One or more sides is overflowing.
if (!overflows.every(side => side <= 0)) {
const nextIndex = (middlewareData.flip?.index || 0) + 1;
const nextPlacement = placements[nextIndex];
if (nextPlacement) {
// Try next placement and re-run the lifecycle.
return {
data: {
index: nextIndex,
overflows: overflowsData,
},
reset: {
placement: nextPlacement,
},
};
}
// First, find the candidates that fit on the mainAxis side of overflow,
// then find the placement that fits the best on the main crossAxis side.
let resetPlacement = overflowsData
.filter(d => d.overflows[0] <= 0)
.sort((a, b) => a.overflows[1] - b.overflows[1])[0]?.placement;
// Otherwise fallback.
if (!resetPlacement) {
switch (fallbackStrategy) {
case 'bestFit': {
const placement = overflowsData
.map(d => [
d.placement,
d.overflows
.filter(overflow => overflow > 0)
.reduce((acc, overflow) => acc + overflow, 0),
])
.sort((a, b) => a[1] - b[1])[0]?.[0];
if (placement) {
resetPlacement = placement;
}
break;
}
case 'initialPlacement':
resetPlacement = initialPlacement;
break;
default:
}
}
if (placement !== resetPlacement) {
return {
reset: {
placement: resetPlacement,
},
};
}
}
return {};
},
});
//# sourceMappingURL=flip.js.map