<!--
    Component: SidebarMenu
    Slides out from the right, closes on click outside
-->
<script lang="ts">
import { cn } from '$shared/shadcn/utils/shadcn-utils';
import type { Snippet } from 'svelte';
import { cubicOut } from 'svelte/easing';
import {
    fade,
    slide,
} from 'svelte/transition';

interface Props {
    /**
     * Children to render conditionally
     */
    children?: Snippet;
    /**
     * Action (always visible) to render
     */
    action?: Snippet;
    /**
     * Wrapper reference to bind
     */
    wrapper?: HTMLElement | null;
    /**
     * Class to add to the wrapper
     */
    class?: string;
    /**
     * Bindable visibility flag
     */
    visible?: boolean;
    /**
     * Handler for click outside
     */
    onClickOutside?: () => void;
}

let {
    children,
    action,
    wrapper = $bindable<HTMLElement | null>(null),
    class: className,
    visible = $bindable(false),
    onClickOutside,
}: Props = $props();

/**
 * Closes menu on click outside
 */
function handleClick(event: MouseEvent) {
    if (!wrapper || !visible) {
        return;
    }
    if (!wrapper.contains(event.target as Node)) {
        visible = false;
        onClickOutside?.();
    }
}
</script>

<svelte:window on:click={handleClick} />

<div
    class={cn(
        'transition-all duration-300 delay-200 cubic-bezier-out',
        className,
    )}
    bind:this={wrapper}
>
    {@render action?.()}
    {#if visible}
        <div
            class="relative z-20 h-full w-auto flex flex-col gap-4"
            in:fade={{ duration: 300, delay: 400, easing: cubicOut }}
            out:fade={{ duration: 150, easing: cubicOut }}
        >
            {@render children?.()}
        </div>

        <!-- Background Gradient -->
        <div
            class="
                absolute inset-0 z-10 h-full transition-all duration-700
                bg-linear-to-r from-white/75 via-white/45 to-white/10
                bg-[radial-gradient(ellipse_at_left,_rgba(255,252,245,0.4)_0%,_transparent_70%)]
                shadow-[_inset_-1px_0_0_rgba(0,0,0,0.04)]
                border-r border-white/90
                after:absolute after:right-[-1px] after:top-0 after:h-full after:w-[1px] after:bg-black/[0.05]
                backdrop-blur-md
            "
            in:slide={{ axis: 'x', duration: 250, delay: 100, easing: cubicOut }}
            out:slide={{ axis: 'x', duration: 150, easing: cubicOut }}
        >
        </div>
    {/if}
</div>
