UNPKG

geist-ui-svelte

Version:

<img src="./src/lib/assets/demo-page.png">

186 lines (185 loc) 8.68 kB
export const place = (anchor, element, { placement = "bottom-start", flip = true, offset = { x: 0, y: 0 } }) => { const options = { placement, flip, offset }; switch (placement) { case "bottom": return placeBottom(anchor, element, options); case "bottom-end": return placeBottomEnd(anchor, element, options); case "bottom-start": return placeBottomStart(anchor, element, options); case "top": return placeTop(anchor, element, options); case "top-end": return placeTopEnd(anchor, element, options); case "top-start": return placeTopStart(anchor, element, options); case "right": return placeRight(anchor, element, options); case "right-end": return placeRightEnd(anchor, element, options); case "right-start": return placeRightStart(anchor, element, options); case "left": return placeLeft(anchor, element, options); case "left-end": return placeLeftEnd(anchor, element, options); case "left-start": return placeLeftStart(anchor, element, options); } }; const getMaxes = (element) => { const maxLeft = window.innerWidth + window.scrollX - (element.offsetWidth + 5); const maxTop = window.innerHeight + window.scrollY - (element.offsetHeight + 80); return { left: maxLeft, top: maxTop }; }; const placeBottom = (anchor, element, options, guard = 0) => { const maxes = getMaxes(element); const top = anchor.offsetTop + anchor.offsetHeight + options.offset.y; if (top > maxes.top && options.flip && guard == 0) return placeTop(anchor, element, options, 1); const left = anchor.offsetLeft + anchor.offsetWidth / 2 - element.offsetWidth / 2 + options.offset.x; if (left > maxes.left) return placeBottomEnd(anchor, element, options); if (left < 0) return placeBottomStart(anchor, element, options); element.style.left = `${left}px`; element.style.top = `${top}px`; return "bottom"; }; const placeBottomEnd = (anchor, element, options, guard = 0) => { const maxes = getMaxes(element); const top = anchor.offsetTop + anchor.offsetHeight + options.offset.y; if (top > maxes.top && options.flip && guard == 0) return placeTopEnd(anchor, element, options, 1); const left = anchor.offsetLeft + anchor.offsetWidth - element.offsetWidth + options.offset.x; if (left < 0 && options.flip && guard <= 1) return placeBottomStart(anchor, element, options, 2); element.style.left = `${left}px`; element.style.top = `${top}px`; return "bottom-end"; }; const placeBottomStart = (anchor, element, options, guard = 0) => { const maxes = getMaxes(element); const top = anchor.offsetTop + anchor.offsetHeight + options.offset.y; if (top > maxes.top && options.flip && guard == 0) return placeTopStart(anchor, element, options, 1); const left = anchor.offsetLeft + options.offset.x; if (left > maxes.left && options.flip && guard <= 1) return placeBottomEnd(anchor, element, options, 2); element.style.left = `${left}px`; element.style.top = `${top}px`; return "bottom-start"; }; const placeTop = (anchor, element, options, guard = 0) => { const maxes = getMaxes(element); const top = anchor.offsetTop - element.offsetHeight - options.offset.y; if (top < 0 && options.flip && guard == 0) return placeBottom(anchor, element, options, 1); const left = anchor.offsetLeft + anchor.offsetWidth / 2 - element.offsetWidth / 2 + options.offset.x; if (left > maxes.left) return placeTopEnd(anchor, element, options); if (left < 0) return placeTopStart(anchor, element, options); element.style.left = `${left}px`; element.style.top = `${top}px`; return "top"; }; const placeTopEnd = (anchor, element, options, guard = 0) => { const top = anchor.offsetTop - element.offsetHeight - options.offset.y; if (top < 0 && options.flip && guard == 0) return placeBottomEnd(anchor, element, options, 1); const left = anchor.offsetLeft + anchor.offsetWidth - element.offsetWidth + options.offset.x; if (left < 0 && options.flip && guard <= 1) return placeTopStart(anchor, element, options, 2); element.style.left = `${left}px`; element.style.top = `${top}px`; return "top-end"; }; const placeTopStart = (anchor, element, options, guard = 0) => { const maxes = getMaxes(element); const top = anchor.offsetTop - element.offsetHeight - options.offset.y; if (top < 0 && options.flip && guard == 0) return placeBottomStart(anchor, element, options, 1); const left = anchor.offsetLeft + options.offset.x; if (left > maxes.left && options.flip && guard <= 1) return placeTopEnd(anchor, element, options, 2); element.style.left = `${left}px`; element.style.top = `${top}px`; return "top-start"; }; const placeRight = (anchor, element, options, guard = 0) => { const maxes = getMaxes(element); const top = anchor.offsetTop + (anchor.offsetHeight - element.offsetHeight) / 2 + options.offset.y; if (top < 0 && options.flip && guard == 0) return placeRightStart(anchor, element, options, 1); if (top > maxes.top && options.flip && guard == 0) return placeRightEnd(anchor, element, options, 1); const left = anchor.offsetLeft + anchor.offsetWidth + options.offset.x; if (left > maxes.left && guard <= 1) return placeLeft(anchor, element, options, 2); element.style.left = `${left}px`; element.style.top = `${top}px`; return "right"; }; const placeRightEnd = (anchor, element, options, guard = 0) => { const maxes = getMaxes(element); const top = anchor.offsetTop + anchor.offsetHeight - element.offsetHeight + options.offset.y; if (top < 0 && options.flip && guard == 0) return placeRightStart(anchor, element, options, 1); const left = anchor.offsetLeft + anchor.offsetWidth + options.offset.x; if (left > maxes.left && guard <= 1) return placeLeftStart(anchor, element, options, 2); element.style.left = `${left}px`; element.style.top = `${top}px`; return "right-end"; }; const placeRightStart = (anchor, element, options, guard = 0) => { const maxes = getMaxes(element); const top = anchor.offsetTop + options.offset.y; if (top > maxes.top && options.flip && guard == 0) return placeRightEnd(anchor, element, options, 1); const left = anchor.offsetLeft + anchor.offsetWidth + options.offset.x; if (left > maxes.left && options.flip && guard <= 1) return placeLeftStart(anchor, element, options, 2); element.style.left = `${left}px`; element.style.top = `${top}px`; return "right-start"; }; const placeLeft = (anchor, element, options, guard = 0) => { const maxes = getMaxes(element); const top = anchor.offsetTop + (anchor.offsetHeight - element.offsetHeight) / 2 + options.offset.y; if (top < 0 && options.flip && guard == 0) return placeLeftStart(anchor, element, options, 1); if (top > maxes.top && options.flip && guard == 0) return placeLeftEnd(anchor, element, options, 1); const left = anchor.offsetLeft - element.offsetWidth - options.offset.x; if (left > maxes.left && guard <= 1) return placeRight(anchor, element, options, 2); element.style.left = `${left}px`; element.style.top = `${top}px`; return "left"; }; const placeLeftEnd = (anchor, element, options, guard = 0) => { const maxes = getMaxes(element); const top = anchor.offsetTop + anchor.offsetHeight - element.offsetHeight; if (top < 0 && options.flip && guard == 0) return placeLeftStart(anchor, element, options, 1); const left = anchor.offsetLeft - element.offsetWidth - options.offset.x; if (left > maxes.left && guard <= 1) return placeRightStart(anchor, element, options, 2); element.style.left = `${left}px`; element.style.top = `${top}px`; return "left-end"; }; const placeLeftStart = (anchor, element, options, guard = 0) => { const maxes = getMaxes(element); const top = anchor.offsetTop + options.offset.y; if (top > maxes.top && options.flip && guard == 0) return placeLeftEnd(anchor, element, options, 1); const left = anchor.offsetLeft - element.offsetWidth - options.offset.x; if (left > maxes.left && options.flip && guard <= 1) return placeRightStart(anchor, element, options, 2); element.style.left = `${left}px`; element.style.top = `${top}px`; return "left-start"; };