mirror of
https://seed.radicle.dev/rad:z4D5UCArafTzTQpDZNQRuqswh3ury.git
synced 2026-11-13 23:20:49 +08:00
70 lines
1.7 KiB
Svelte
70 lines
1.7 KiB
Svelte
<script lang="ts" module>
|
|
import { writable } from "svelte/store";
|
|
const focused = writable<HTMLDivElement | undefined>(undefined);
|
|
|
|
export function closeFocused() {
|
|
focused.set(undefined);
|
|
}
|
|
</script>
|
|
|
|
<script lang="ts">
|
|
export let popoverContainerMinWidth: string | undefined = undefined;
|
|
export let popoverPadding: string | undefined = undefined;
|
|
export let popoverPositionBottom: string | undefined = undefined;
|
|
export let popoverPositionLeft: string | undefined = undefined;
|
|
export let popoverPositionRight: string | undefined = undefined;
|
|
export let popoverPositionTop: string | undefined = undefined;
|
|
|
|
export let expanded = false;
|
|
let thisComponent: HTMLDivElement;
|
|
|
|
function clickOutside(ev: MouseEvent | TouchEvent) {
|
|
if ($focused && !ev.composedPath().includes($focused)) {
|
|
closeFocused();
|
|
}
|
|
}
|
|
|
|
function toggle() {
|
|
expanded = !expanded;
|
|
if ($focused === thisComponent) {
|
|
closeFocused();
|
|
} else {
|
|
focused.set(thisComponent);
|
|
}
|
|
}
|
|
|
|
$: expanded = $focused === thisComponent;
|
|
</script>
|
|
|
|
<style>
|
|
.container {
|
|
position: relative;
|
|
}
|
|
.popover {
|
|
box-shadow: var(--elevation-low);
|
|
position: absolute;
|
|
z-index: 10;
|
|
}
|
|
</style>
|
|
|
|
<svelte:window onclick={clickOutside} ontouchstart={clickOutside} />
|
|
|
|
<div
|
|
bind:this={thisComponent}
|
|
class="container"
|
|
style:min-width={popoverContainerMinWidth}>
|
|
<slot name="toggle" {expanded} {toggle} />
|
|
|
|
{#if expanded}
|
|
<div
|
|
class="popover"
|
|
style:bottom={popoverPositionBottom}
|
|
style:left={popoverPositionLeft}
|
|
style:right={popoverPositionRight}
|
|
style:top={popoverPositionTop}
|
|
style:padding={popoverPadding}>
|
|
<slot name="popover" {toggle} />
|
|
</div>
|
|
{/if}
|
|
</div>
|