"use client"; import { motion } from "motion/react"; import type { RefObject } from "react"; import React, { useRef } from "react"; import { useEffect, useId, useState } from "react"; import { Globe } from "@/components/magicui/globe"; import { Card, CardContent, CardHeader } from "@/components/ui/card"; import { cn } from "@/lib/utils"; interface Feature251Props { className?: string; } const Feature251 = ({ className }: Feature251Props) => { const containerRef1 = useRef(null); const containerRef2 = useRef(null); const div1Ref = useRef(null); const div2Ref = useRef(null); const div3Ref = useRef(null); const div4Ref = useRef(null); const div5Ref = useRef(null); const div6Ref = useRef(null); const div7Ref = useRef(null); return (

تریگر رویداد

شرط هوشمند

} src="/block-media/shadcnblocks/block/logos/google-icon.svg" imageAlt="سازنده گردش‌کار" className="mb-3" /> } src="/block-media/shadcnblocks/block/logos/figma-icon.svg" imageAlt="نمای اتوماسیون فرایند" className="translate-x-32 rtl:-translate-x-32" /> } src="/block-media/shadcnblocks/block/logos/notion-icon.svg" imageAlt="لاگ اجرای خودکار" className="mt-3" /> } src="/block-media/shadcnblocks/block/block-1.svg" imageAlt="سازنده گردش‌کار" className="absolute end-12 top-1/2 -translate-y-1/2" />
} className="absolute top-1/2 left-1/2 z-99 h-4 w-4 -translate-y-1/2 rounded-full border bg-muted" />

اعلان خودکار

تأیید چندمرحله‌ای

} src="/block-media/shadcnblocks/block/block-1.svg" imageAlt="نمای اتوماسیون فرایند" className="mb-3" /> } src="/block-media/shadcnblocks/block/logos/g2-icon.svg" imageAlt="لاگ اجرای خودکار" className="mt-3" /> } direction="vertical" curvature={40} toRef={div7Ref as React.RefObject} />
سازنده گردش‌کار

لاگ اجرا

قالب آماده

اتصال ابزار

سازنده گردش‌کار

); }; export { Feature251 }; const IconCard = ({ src, imageAlt, className, ref, }: { src: string; imageAlt: string; className?: string; ref: React.RefObject; }) => { return (
{imageAlt}
); }; const HandleIcon = (props: React.SVGProps) => { return ( ); }; // Below is the modified component from Magic UI // Original source: https://magicui.design/docs/components/animated-beam // Modified to follow our coding standards and design system // We respect copyright and attribution to the original creators export interface AnimatedBeamProps { className?: string; containerRef: RefObject; // Container ref fromRef: RefObject; toRef: RefObject; curvature?: number; reverse?: boolean; pathColor?: string; pathWidth?: number; pathOpacity?: number; gradientStartColor?: string; gradientStopColor?: string; delay?: number; duration?: number; startXOffset?: number; startYOffset?: number; endXOffset?: number; endYOffset?: number; direction?: "horizontal" | "vertical"; } export const AnimatedBeam: React.FC = ({ className, containerRef, fromRef, toRef, curvature = 0, reverse = false, // Include the reverse prop duration = Math.random() * 3 + 4, delay = 0, pathColor = "gray", pathWidth = 2, pathOpacity = 0.2, gradientStartColor = "#ffaa40", gradientStopColor = "#9c40ff", startXOffset = 0, startYOffset = 0, endXOffset = 0, endYOffset = 0, direction = "horizontal", }) => { const id = useId(); const [pathD, setPathD] = useState(""); const [svgDimensions, setSvgDimensions] = useState({ width: 0, height: 0 }); // Calculate the gradient coordinates based on the reverse prop const gradientCoordinates = direction === "vertical" ? reverse ? { x1: ["0%", "0%"], x2: ["0%", "0%"], y1: ["90%", "-10%"], y2: ["100%", "0%"], } : { x1: ["0%", "0%"], x2: ["0%", "0%"], y1: ["10%", "110%"], y2: ["0%", "100%"], } : reverse ? { // Horizontal (existing logic) x1: ["90%", "-10%"], x2: ["100%", "0%"], y1: ["0%", "0%"], y2: ["0%", "0%"], } : { x1: ["10%", "110%"], x2: ["0%", "100%"], y1: ["0%", "0%"], y2: ["0%", "0%"], }; useEffect(() => { const updatePath = () => { if (containerRef.current && fromRef.current && toRef.current) { const containerRect = containerRef.current.getBoundingClientRect(); const rectA = fromRef.current.getBoundingClientRect(); const rectB = toRef.current.getBoundingClientRect(); const svgWidth = containerRect.width; const svgHeight = containerRect.height; setSvgDimensions({ width: svgWidth, height: svgHeight }); const startX = rectA.left - containerRect.left + rectA.width / 2 + startXOffset; const startY = rectA.top - containerRect.top + rectA.height / 2 + startYOffset; const endX = rectB.left - containerRect.left + rectB.width / 2 + endXOffset; const endY = rectB.top - containerRect.top + rectB.height / 2 + endYOffset; const controlY = startY - curvature; const d = `M ${startX},${startY} Q ${ (startX + endX) / 2 },${controlY} ${endX},${endY}`; setPathD(d); } }; // Initialize ResizeObserver const resizeObserver = new ResizeObserver((entries) => { // For all entries, recalculate the path for (const _entry of entries) { updatePath(); } }); // Observe the container element if (containerRef.current) { resizeObserver.observe(containerRef.current); } // Call the updatePath initially to set the initial path updatePath(); // Clean up the observer on component unmount return () => { resizeObserver.disconnect(); }; }, [ containerRef, fromRef, toRef, curvature, startXOffset, startYOffset, endXOffset, endYOffset, ]); return ( ); };