@page "/components/animated-beam"

<PageTitle>AnimatedBeam — Lumeo</PageTitle>

<PageHeader Title="AnimatedBeam" Description="SVG beam that traces an animated gradient path between two DOM elements." />

<div class="mt-10 space-y-3">
    <Heading Id="when-to-use" Level="2" Class="scroll-mt-20">When to Use</Heading>
    <ul class="list-disc list-inside space-y-1 text-muted-foreground text-sm">
        <li>Visualize data flows between services in integration or architecture diagrams.</li>
        <li>Connect icon nodes in a feature showcase or product diagram.</li>
        <li>Add motion to "how it works" sections by tracing steps together.</li>
    </ul>
</div>

<Stack Gap="8" Class="mt-8">
    <ComponentDemo Title="Basic Beam" Code="@_basicCode">
        @* ContainerId must match the id of the position:relative wrapper *@
        <div id="beam-demo-1"
             class="relative flex items-center justify-center gap-24 p-10 min-h-[160px] bg-muted/30 rounded-xl border border-border/40 overflow-hidden">
            <div id="beam-from-1"
                 class="z-10 flex items-center justify-center w-12 h-12 rounded-full bg-primary text-primary-foreground shadow-lg">
                <Blazicon Svg="Lucide.Cpu" class="h-6 w-6 text-primary-foreground" />
            </div>
            <AnimatedBeam ContainerId="beam-demo-1" FromId="beam-from-1" ToId="beam-to-1" />
            <div id="beam-to-1"
                 class="z-10 flex items-center justify-center w-12 h-12 rounded-full bg-primary text-primary-foreground shadow-lg">
                <Blazicon Svg="Lucide.Cloud" class="h-6 w-6 text-primary-foreground" />
            </div>
        </div>
    </ComponentDemo>

    <ComponentDemo Title="Curved Beam with Custom Colors" Code="@_curvedCode">
        <div id="beam-demo-2"
             class="relative flex items-center justify-between p-10 min-h-[200px] bg-muted/30 rounded-xl border border-border/40 overflow-hidden">
            <div id="beam-src-2"
                 class="z-10 flex items-center justify-center w-14 h-14 rounded-xl bg-card border border-border shadow">
                <Blazicon Svg="Lucide.Database" class="h-6 w-6 text-foreground/80" />
            </div>
            <AnimatedBeam ContainerId="beam-demo-2"
                          FromId="beam-src-2" ToId="beam-dst-2"
                          GradientStartColor="#f97316" GradientStopColor="#8b5cf6"
                          Curvature="60"
                          DurationMs="2500" />
            <div id="beam-dst-2"
                 class="z-10 flex items-center justify-center w-14 h-14 rounded-xl bg-card border border-border shadow">
                <Blazicon Svg="Lucide.Server" class="h-6 w-6 text-foreground/80" />
            </div>
        </div>
    </ComponentDemo>

    <ComponentDemo Title="Multi-Beam Network" Code="@_networkCode">
        <div id="beam-demo-3"
             class="relative flex items-center justify-around p-8 min-h-[220px] bg-muted/30 rounded-xl border border-border/40 overflow-hidden">
            @* Left column *@
            <div class="flex flex-col gap-8 z-10">
                <div id="bnet-a" class="flex items-center justify-center w-11 h-11 rounded-full bg-card border border-border/60 shadow"><Blazicon Svg="Lucide.Mail" class="h-5 w-5 text-foreground/80" /></div>
                <div id="bnet-b" class="flex items-center justify-center w-11 h-11 rounded-full bg-card border border-border/60 shadow"><Blazicon Svg="Lucide.Bell" class="h-5 w-5 text-foreground/80" /></div>
                <div id="bnet-c" class="flex items-center justify-center w-11 h-11 rounded-full bg-card border border-border/60 shadow"><Blazicon Svg="Lucide.Package" class="h-5 w-5 text-foreground/80" /></div>
            </div>
            @* Center hub *@
            <div id="bnet-hub" class="z-10 flex items-center justify-center w-16 h-16 rounded-2xl bg-primary text-primary-foreground shadow-lg"><Blazicon Svg="Lucide.Zap" class="h-7 w-7 text-primary-foreground" /></div>
            @* Right column *@
            <div class="flex flex-col gap-8 z-10">
                <div id="bnet-d" class="flex items-center justify-center w-11 h-11 rounded-full bg-card border border-border/60 shadow"><Blazicon Svg="Lucide.HardDrive" class="h-5 w-5 text-foreground/80" /></div>
                <div id="bnet-e" class="flex items-center justify-center w-11 h-11 rounded-full bg-card border border-border/60 shadow"><Blazicon Svg="Lucide.Globe" class="h-5 w-5 text-foreground/80" /></div>
            </div>
            @* Beams — all anchored to the same container *@
            <AnimatedBeam ContainerId="beam-demo-3" FromId="bnet-a" ToId="bnet-hub" GradientStartColor="#f97316" GradientStopColor="#ec4899" DurationMs="3000" />
            <AnimatedBeam ContainerId="beam-demo-3" FromId="bnet-b" ToId="bnet-hub" GradientStartColor="#3b82f6" GradientStopColor="#8b5cf6" DurationMs="3500" DelayMs="400" />
            <AnimatedBeam ContainerId="beam-demo-3" FromId="bnet-c" ToId="bnet-hub" GradientStartColor="#10b981" GradientStopColor="#06b6d4" DurationMs="2800" DelayMs="800" />
            <AnimatedBeam ContainerId="beam-demo-3" FromId="bnet-hub" ToId="bnet-d" GradientStartColor="#f97316" GradientStopColor="#eab308" DurationMs="3200" DelayMs="200" />
            <AnimatedBeam ContainerId="beam-demo-3" FromId="bnet-hub" ToId="bnet-e" GradientStartColor="#8b5cf6" GradientStopColor="#ec4899" DurationMs="2600" DelayMs="600" />
        </div>
    </ComponentDemo>

    <ComponentDemo Title="Interactive: Curvature & Duration" Description="Adjust curvature and animation speed live." Code="@_interactiveCode">
        <Stack Gap="3">
            <Flex Align="center" Gap="3" Wrap="true">
                <div class="flex flex-col gap-1 min-w-[220px]">
                    <Lumeo.Text Size="sm" Weight="medium">Curvature: @_animBeamCurvature px</Lumeo.Text>
                    <Slider @bind-Value="_animBeamCurvature" Min="0" Max="100" Step="5" />
                </div>
                <div class="flex flex-col gap-1 min-w-[220px]">
                    <Lumeo.Text Size="sm" Weight="medium">DurationMs: @_animBeamDuration ms</Lumeo.Text>
                    <Slider @bind-Value="_animBeamDuration" Min="500" Max="6000" Step="100" />
                </div>
            </Flex>
            <div id="beam-interactive"
                 class="relative flex items-center justify-center gap-28 p-10 min-h-[160px] bg-muted/30 rounded-xl border border-border/40 overflow-hidden">
                <div id="beam-int-from"
                     class="z-10 flex items-center justify-center w-12 h-12 rounded-full bg-primary text-primary-foreground shadow-lg">
                    <Blazicon Svg="Lucide.Cpu" class="h-6 w-6 text-primary-foreground" />
                </div>
                <AnimatedBeam ContainerId="beam-interactive"
                              FromId="beam-int-from" ToId="beam-int-to"
                              Curvature="@_animBeamCurvature"
                              DurationMs="@((int)_animBeamDuration)" />
                <div id="beam-int-to"
                     class="z-10 flex items-center justify-center w-12 h-12 rounded-full bg-primary text-primary-foreground shadow-lg">
                    <Blazicon Svg="Lucide.Cloud" class="h-6 w-6 text-primary-foreground" />
                </div>
            </div>
        </Stack>
    </ComponentDemo>
</Stack>

<Stack Gap="6" Class="mt-12">
    <Heading Level="2">API Reference</Heading>
    <Stack Class="rounded-lg border border-border/40 overflow-x-auto">
        <table class="w-full min-w-[600px] text-sm">
            <thead>
                <tr class="border-b border-border/40 bg-muted/40">
                    <th class="text-left p-3 font-medium text-foreground">Property</th>
                    <th class="text-left p-3 font-medium text-foreground">Type</th>
                    <th class="text-left p-3 font-medium text-foreground">Default</th>
                    <th class="text-left p-3 font-medium text-foreground">Description</th>
                </tr>
            </thead>
            <tbody class="divide-y divide-border/40">
                <tr><td class="p-3 font-mono text-xs text-primary">ContainerId</td><td class="p-3 font-mono text-xs text-muted-foreground">string?</td><td class="p-3 font-mono text-xs text-muted-foreground">null</td><td class="p-3 text-muted-foreground">Id of the <code class="text-xs">position:relative</code> container. Coordinates are measured relative to it.</td></tr>
                <tr><td class="p-3 font-mono text-xs text-primary">FromId</td><td class="p-3 font-mono text-xs text-muted-foreground">string?</td><td class="p-3 font-mono text-xs text-muted-foreground">null</td><td class="p-3 text-muted-foreground">The <code class="text-xs">id</code> of the source element.</td></tr>
                <tr><td class="p-3 font-mono text-xs text-primary">ToId</td><td class="p-3 font-mono text-xs text-muted-foreground">string?</td><td class="p-3 font-mono text-xs text-muted-foreground">null</td><td class="p-3 text-muted-foreground">The <code class="text-xs">id</code> of the destination element.</td></tr>
                <tr><td class="p-3 font-mono text-xs text-primary">DurationMs</td><td class="p-3 font-mono text-xs text-muted-foreground">int</td><td class="p-3 font-mono text-xs text-muted-foreground">3000</td><td class="p-3 text-muted-foreground">Duration of one traversal in milliseconds.</td></tr>
                <tr><td class="p-3 font-mono text-xs text-primary">DelayMs</td><td class="p-3 font-mono text-xs text-muted-foreground">int</td><td class="p-3 font-mono text-xs text-muted-foreground">0</td><td class="p-3 text-muted-foreground">Delay before the first cycle.</td></tr>
                <tr><td class="p-3 font-mono text-xs text-primary">Curvature</td><td class="p-3 font-mono text-xs text-muted-foreground">double</td><td class="p-3 font-mono text-xs text-muted-foreground">0</td><td class="p-3 text-muted-foreground">Bezier control point offset in px (positive = bows up).</td></tr>
                <tr><td class="p-3 font-mono text-xs text-primary">Reverse</td><td class="p-3 font-mono text-xs text-muted-foreground">bool</td><td class="p-3 font-mono text-xs text-muted-foreground">false</td><td class="p-3 text-muted-foreground">Reverses direction of travel.</td></tr>
                <tr><td class="p-3 font-mono text-xs text-primary">GradientStartColor</td><td class="p-3 font-mono text-xs text-muted-foreground">string</td><td class="p-3 font-mono text-xs text-muted-foreground">"#ffaa40"</td><td class="p-3 text-muted-foreground">Start color of the beam gradient.</td></tr>
                <tr><td class="p-3 font-mono text-xs text-primary">GradientStopColor</td><td class="p-3 font-mono text-xs text-muted-foreground">string</td><td class="p-3 font-mono text-xs text-muted-foreground">"#9c40ff"</td><td class="p-3 text-muted-foreground">End color of the beam gradient.</td></tr>
                <tr><td class="p-3 font-mono text-xs text-primary">PathColor</td><td class="p-3 font-mono text-xs text-muted-foreground">string</td><td class="p-3 font-mono text-xs text-muted-foreground">"var(--color-border)"</td><td class="p-3 text-muted-foreground">Color of the guide track.</td></tr>
                <tr><td class="p-3 font-mono text-xs text-primary">PathOpacity</td><td class="p-3 font-mono text-xs text-muted-foreground">double</td><td class="p-3 font-mono text-xs text-muted-foreground">0.3</td><td class="p-3 text-muted-foreground">Opacity of the guide track (0–1).</td></tr>
                <tr><td class="p-3 font-mono text-xs text-primary">PathWidth</td><td class="p-3 font-mono text-xs text-muted-foreground">double</td><td class="p-3 font-mono text-xs text-muted-foreground">2</td><td class="p-3 text-muted-foreground">Width of the guide track path in px.</td></tr>
                <tr><td class="p-3 font-mono text-xs text-primary">BeamWidth</td><td class="p-3 font-mono text-xs text-muted-foreground">double</td><td class="p-3 font-mono text-xs text-muted-foreground">2</td><td class="p-3 text-muted-foreground">Width of the animated beam stroke in px.</td></tr>
            </tbody>
        </table>
    </Stack>
</Stack>

<div class="mt-12">
    <Heading Id="related" Level="2" Class="scroll-mt-20">Related Components</Heading>
    <ul class="mt-4 space-y-2 text-sm">
        <li><a href="/components/sparkles" class="text-primary hover:underline">Sparkles</a> — Decorative sparkle particle animation.</li>
        <li><a href="/components/confetti" class="text-primary hover:underline">Confetti</a> — Burst confetti canvas animation triggered on demand.</li>
    </ul>
</div>

@code {
    private const string _basicCode =
@"<div id=""container"" class=""relative flex items-center justify-center gap-24 p-10 min-h-[160px] overflow-hidden"">
    <div id=""from"" class=""z-10 w-12 h-12 rounded-full bg-primary text-primary-foreground flex items-center justify-center"">
        <Blazicon Svg=""Lucide.Cpu"" class=""h-6 w-6"" />
    </div>
    <AnimatedBeam ContainerId=""container"" FromId=""from"" ToId=""to"" />
    <div id=""to"" class=""z-10 w-12 h-12 rounded-full bg-primary text-primary-foreground flex items-center justify-center"">
        <Blazicon Svg=""Lucide.Cloud"" class=""h-6 w-6"" />
    </div>
</div>";

    private const string _curvedCode =
@"<div id=""container"" class=""relative flex items-center justify-between p-10 min-h-[200px] overflow-hidden"">
    <div id=""src"" class=""z-10 w-14 h-14 rounded-xl bg-card border border-border flex items-center justify-center"">
        <Blazicon Svg=""Lucide.Database"" class=""h-6 w-6"" />
    </div>
    <AnimatedBeam ContainerId=""container""
                  FromId=""src"" ToId=""dst""
                  GradientStartColor=""#f97316"" GradientStopColor=""#8b5cf6""
                  Curvature=""60"" DurationMs=""2500"" />
    <div id=""dst"" class=""z-10 w-14 h-14 rounded-xl bg-card border border-border flex items-center justify-center"">
        <Blazicon Svg=""Lucide.Server"" class=""h-6 w-6"" />
    </div>
</div>";

    private const string _networkCode =
@"@* Multiple beams sharing one container — hub-and-spoke pattern *@
<div id=""net"" class=""relative flex items-center justify-around p-8 min-h-[220px] overflow-hidden"">
    <div id=""a"" class=""z-10 w-11 h-11 rounded-full bg-card border border-border/60 flex items-center justify-center"">
        <Blazicon Svg=""Lucide.Mail"" class=""h-5 w-5"" />
    </div>
    <div id=""hub"" class=""z-10 w-16 h-16 rounded-2xl bg-primary text-primary-foreground flex items-center justify-center"">
        <Blazicon Svg=""Lucide.Zap"" class=""h-7 w-7"" />
    </div>
    <div id=""b"" class=""z-10 w-11 h-11 rounded-full bg-card border border-border/60 flex items-center justify-center"">
        <Blazicon Svg=""Lucide.HardDrive"" class=""h-5 w-5"" />
    </div>
    <AnimatedBeam ContainerId=""net"" FromId=""a"" ToId=""hub"" />
    <AnimatedBeam ContainerId=""net"" FromId=""hub"" ToId=""b"" Reverse />
</div>";

    private double _animBeamCurvature = 30;
    private double _animBeamDuration = 2500;

    private const string _interactiveCode =
@"<div id=""container"" class=""relative flex items-center justify-center gap-28 p-10 min-h-[160px] overflow-hidden"">
    <div id=""from"" class=""z-10 w-12 h-12 rounded-full bg-primary text-primary-foreground flex items-center justify-center"">
        <Blazicon Svg=""Lucide.Cpu"" class=""h-6 w-6"" />
    </div>
    <AnimatedBeam ContainerId=""container""
                  FromId=""from"" ToId=""to""
                  Curvature=""30"" DurationMs=""2500"" />
    <div id=""to"" class=""z-10 w-12 h-12 rounded-full bg-primary text-primary-foreground flex items-center justify-center"">
        <Blazicon Svg=""Lucide.Cloud"" class=""h-6 w-6"" />
    </div>
</div>";
}
