UNPKG

mytril

Version:

Mytril Svelte library component for rapidly building modern websites based on Svelte and Sveltekit

132 lines (131 loc) 6.04 kB
import { innerWidth, innerHeight } from 'svelte/reactivity/window'; export function getPositionsTooltip() { // state const axis = $state({ x: 0, y: 0, location: null }); return { get values() { return axis; }, update(activator, element, location, centered, type, avoidCollisions) { if (!activator || !element) return; const elementRect = element.getBoundingClientRect(); const activatorRect = activator.getBoundingClientRect(); const spacing = 6; if (location === 'top' || location === 'bottom') { if (avoidCollisions) { if (location === 'top') { if (activatorRect.y - (elementRect.height + spacing) < 0) { axis.y = activatorRect.bottom + spacing; axis.location = 'bottom'; } else { axis.y = activatorRect.top - (elementRect.height + spacing); axis.location = 'top'; } } else { if (activatorRect.y + activatorRect.height + (elementRect.height + spacing) > innerHeight.current) { axis.y = activatorRect.top - (elementRect.height + spacing); axis.location = 'top'; } else { axis.y = activatorRect.bottom + spacing; axis.location = 'bottom'; } } } else { if (location === 'top') { axis.y = activatorRect.top - (elementRect.height + spacing); axis.location = 'top'; } else { axis.y = activatorRect.bottom + spacing; axis.location = 'bottom'; } } if (centered && activatorRect.left - (elementRect.width - activatorRect.width) / 2 > 0 && activatorRect.left + elementRect.width < innerWidth.current) { axis.x = activatorRect.left - (elementRect.width - activatorRect.width) / 2; } else if (activatorRect.left + elementRect.width > innerWidth.current) { axis.x = activatorRect.left - (elementRect.width - activatorRect.width); } else { axis.x = activatorRect.left; } } else if (location === 'left' || location === 'right') { if (avoidCollisions) { if (location === 'left' && !(activatorRect.left - elementRect.width < 0)) { axis.x = activatorRect.left - (elementRect.width + spacing); axis.location = 'left'; } else { if (activatorRect.left + activatorRect.width + elementRect.width + spacing > innerWidth.current) { axis.x = activatorRect.left - (elementRect.width + spacing); axis.location = 'left'; } else { axis.x = activatorRect.left + activatorRect.width + spacing; axis.location = 'right'; } } } else { if (location === 'left') { axis.x = activatorRect.left - (elementRect.width + spacing); axis.location = 'left'; } else { axis.x = activatorRect.left + activatorRect.width + spacing; axis.location = 'right'; } } if (centered && activatorRect.top - (elementRect.height - activatorRect.height) / 2 > 0 && activatorRect.top + elementRect.height < innerHeight.current) { axis.y = activatorRect.top - (elementRect.height - activatorRect.height) / 2; } else if (activatorRect.y + elementRect.height > innerHeight.current) { axis.y = activatorRect.y - elementRect.height + activatorRect.height; } else { axis.y = activatorRect.y; } } else { if (centered && activatorRect.left - (elementRect.width - activatorRect.width) / 2 > 0 && activatorRect.left + elementRect.width < innerWidth.current) { axis.x = activatorRect.left - (elementRect.width - activatorRect.width) / 2; } else if (activatorRect.left + elementRect.width > innerWidth.current) { axis.x = activatorRect.left - (elementRect.width - activatorRect.width); } else { axis.x = activatorRect.left; } if (centered && activatorRect.top - (elementRect.height - activatorRect.height) / 2 > 0 && activatorRect.top + elementRect.height < innerHeight.current) { axis.y = activatorRect.top - (elementRect.height - activatorRect.height) / 2; } else if (activatorRect.bottom + elementRect.height > innerHeight.current) { axis.y = activatorRect.top - elementRect.height; } else { axis.y = activatorRect.bottom; } } } }; }