1
0
Fork 0
mirror of synced 2024-06-01 10:09:48 +12:00
budibase/packages/bbui/src/Popover/Popover.svelte

96 lines
2.1 KiB
Svelte

<script>
import "@spectrum-css/popover/dist/index-vars.css"
import Portal from "svelte-portal"
import { createEventDispatcher } from "svelte"
import positionDropdown from "../Actions/position_dropdown"
import clickOutside from "../Actions/click_outside"
import { fly } from "svelte/transition"
import { getContext } from "svelte"
import Context from "../context"
const dispatch = createEventDispatcher()
export let anchor
export let align = "right"
export let portalTarget
export let maxWidth
export let maxHeight
export let open = false
export let useAnchorWidth = false
export let dismissible = true
export let offset = 5
export let customHeight
export let animate = true
$: target = portalTarget || getContext(Context.PopoverRoot) || ".spectrum"
export const show = () => {
dispatch("open")
open = true
}
export const hide = () => {
dispatch("close")
open = false
}
const handleOutsideClick = e => {
if (open) {
// Stop propagation if the source is the anchor
let node = e.target
let fromAnchor = false
while (!fromAnchor && node && node.parentNode) {
fromAnchor = node === anchor
node = node.parentNode
}
if (fromAnchor) {
e.stopPropagation()
}
// Hide the popover
hide()
}
}
function handleEscape(e) {
if (open && e.key === "Escape") {
hide()
}
}
</script>
{#if open}
<Portal {target}>
<div
tabindex="0"
use:positionDropdown={{
anchor,
align,
maxHeight,
maxWidth,
useAnchorWidth,
offset,
}}
use:clickOutside={{
callback: dismissible ? handleOutsideClick : () => {},
anchor,
}}
on:keydown={handleEscape}
class="spectrum-Popover is-open"
role="presentation"
style="height: {customHeight}"
transition:fly|local={{ y: -20, duration: animate ? 200 : 0 }}
>
<slot />
</div>
</Portal>
{/if}
<style>
.spectrum-Popover {
min-width: var(--spectrum-global-dimension-size-2000);
border-color: var(--spectrum-global-color-gray-300);
overflow: auto;
}
</style>