2024-09-25 20:46:10 +00:00
|
|
|
<script lang="ts">
|
2024-10-15 19:02:11 +00:00
|
|
|
import "tippy.js/animations/shift-away.css"
|
2024-10-14 19:35:08 +00:00
|
|
|
|
2025-02-03 23:40:00 +00:00
|
|
|
import tippy from "tippy.js"
|
2026-07-28 00:13:14 +00:00
|
|
|
import type {Instance} from "tippy.js"
|
|
|
|
|
import {onMount, mount, unmount} from "svelte"
|
2025-07-31 17:25:55 +00:00
|
|
|
import {isMobile} from "@lib/html"
|
2024-09-25 20:46:10 +00:00
|
|
|
|
2025-02-03 23:50:19 +00:00
|
|
|
let {
|
|
|
|
|
component,
|
|
|
|
|
children = undefined,
|
|
|
|
|
props = {},
|
|
|
|
|
params = {},
|
|
|
|
|
popover = $bindable(),
|
|
|
|
|
instance = $bindable(),
|
|
|
|
|
...restProps
|
|
|
|
|
} = $props()
|
|
|
|
|
|
2025-02-03 23:40:00 +00:00
|
|
|
let element: Element
|
2024-09-25 20:46:10 +00:00
|
|
|
|
2026-07-03 23:48:23 +00:00
|
|
|
// `mount` only tracks prop changes when the props come from a `$state` object,
|
|
|
|
|
// so sync incoming props into a reactive one. Without this the popover keeps
|
|
|
|
|
// the props it was first mounted with, showing stale data after the source updates.
|
|
|
|
|
const mountedProps = $state({...props})
|
|
|
|
|
|
|
|
|
|
$effect(() => {
|
|
|
|
|
Object.assign(mountedProps, props)
|
|
|
|
|
})
|
|
|
|
|
|
2024-09-25 20:46:10 +00:00
|
|
|
onMount(() => {
|
2025-02-03 23:50:19 +00:00
|
|
|
const target = document.createElement("div")
|
|
|
|
|
|
|
|
|
|
popover = tippy(element, {
|
|
|
|
|
content: target,
|
|
|
|
|
animation: "shift-away",
|
|
|
|
|
appendTo: document.querySelector(".tippy-target")!,
|
2025-07-31 17:25:55 +00:00
|
|
|
trigger: isMobile ? "click" : "mouseenter focus",
|
2025-02-03 23:50:19 +00:00
|
|
|
...params,
|
2026-07-28 00:13:14 +00:00
|
|
|
onShow: (tippyInstance: Instance) => {
|
|
|
|
|
instance ??= mount(component, {target, props: mountedProps})
|
2025-02-03 23:50:19 +00:00
|
|
|
|
2026-07-28 00:13:14 +00:00
|
|
|
return params.onShow?.(tippyInstance)
|
|
|
|
|
},
|
|
|
|
|
})
|
2025-02-03 23:50:19 +00:00
|
|
|
|
|
|
|
|
return () => {
|
|
|
|
|
popover?.destroy()
|
2026-07-28 00:13:14 +00:00
|
|
|
|
|
|
|
|
if (instance) {
|
|
|
|
|
unmount(instance)
|
|
|
|
|
}
|
2024-09-25 20:46:10 +00:00
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
</script>
|
|
|
|
|
|
2025-02-03 23:40:00 +00:00
|
|
|
<div bind:this={element} class={restProps.class}>
|
|
|
|
|
{@render children?.()}
|
2024-10-03 21:32:55 +00:00
|
|
|
</div>
|