@necto/popper
v0.5.11
Published
Necto's library for providing positioning and popover utilities.
Readme
📚 Usage
Basic Example
import { computePosition, offset, flip, shift } from '@necto/popper';
const button = document.querySelector('#button')!;
const tooltip = document.querySelector('#tooltip')!;
// Async for potential future middleware
const { x, y, placement, middlewareData } = await computePosition(button, tooltip, {
placement: 'top',
strategy: 'absolute',
middleware: [
offset(8), // 8px gap
flip(), // Auto-flip if no space
shift() // Shift to stay in viewport
]
});
// Apply position
Object.assign(tooltip.style, {
position: 'absolute',
left: `${x}px`,
top: `${y}px`
});
// Access middleware data
console.log(middlewareData.flip); // { flipped: true, originalPlacement: 'top' }Advanced Example with Options
const { x, y, placement } = await computePosition(button, tooltip, {
placement: 'bottom-start',
strategy: 'fixed',
middleware: [
offset({ value: 12 }),
flip({
boundary: document.querySelector('#container'),
padding: { top: 10, bottom: 10 }
}),
shift({
padding: 8,
maxShift: 100, // Don't shift more than 100px
axis: 'x' // Only shift horizontally
})
]
});Type-Safe Helpers
import { getSide, getAlignment, getOppositeSide, isPlacement } from '@necto/popper';
// Extract placement parts
const side = getSide('top-start'); // 'top'
const alignment = getAlignment('top-start'); // 'start'
// Get opposites
const opposite = getOppositeSide('top'); // 'bottom'
// Runtime validation
if (isPlacement(userInput)) {
// TypeScript knows userInput is Placement
}React code interop
// React wrapper - just 20 lines!
import { computePosition } from '@necto/popper';
import type { ComputePositionOptions } from '@necto/popper';
export function usePopper(
reference: Element | null,
floating: HTMLElement | null,
options: ComputePositionOptions = {}
) {
const [position, setPosition] = useState({ x: 0, y: 0 });
useEffect(() => {
if (!reference || !floating) return;
// All the logic is in @necto/popper!
computePosition(reference, floating, options).then(setPosition);
}, [reference, floating, options]);
return position;
}That's it! The vanilla package handles:
- ✅ All positioning logic
- ✅ All type definitions
- ✅ All middleware
- ✅ All validation
- ✅ All utilities
The React package just wraps it with hooks!
