← back to karsenkoltun__kk1

Function bodies 113 total

All specs Real LLM only Function bodies
ListingCard function · typescript · L88-L163 (76 LOC)
src/components/sections/FeaturedListings.tsx
function ListingCard({ listing, index }: { listing: Listing; index: number }) {
  return (
    <AnimateIn delay={index * 0.1}>
      <div className="group min-w-[85vw] cursor-pointer border border-border bg-background transition-all duration-500 hover:border-accent/30 sm:min-w-[280px] md:min-w-0">
        {/* Image placeholder */}
        <div className="relative aspect-[4/3] overflow-hidden bg-background-tertiary">
          {/* Hover zoom effect on placeholder */}
          <div className="absolute inset-0 flex items-center justify-center transition-transform duration-700 group-hover:scale-110">
            <span className="text-xs tracking-[0.2em] text-text-muted uppercase">
              Listing Photo
            </span>
          </div>

          {/* Hover overlay */}
          <div className="absolute inset-0 bg-accent/0 transition-all duration-500 group-hover:bg-accent/10" />

          {/* Featured badge */}
          {listing.featured && (
            <div className="absolute
FeaturedListings function · typescript · L165-L216 (52 LOC)
src/components/sections/FeaturedListings.tsx
export default function FeaturedListings() {
  const scrollRef = useRef<HTMLDivElement>(null);

  return (
    <section className="bg-background-secondary py-16 md:py-24 lg:py-32">
      <div className="mx-auto max-w-7xl px-6 lg:px-10">
        <AnimateIn>
          <div className="flex flex-col items-center text-center">
            <p className="text-xs font-medium tracking-[0.3em] text-accent uppercase">
              Featured Properties
            </p>
            <h2 className="mt-4 font-heading text-4xl font-light tracking-tight text-text-primary md:text-5xl">
              Active Listings
            </h2>
            <p className="mt-2 text-sm text-text-muted">
              {activeCount} Active Listing{activeCount !== 1 ? "s" : ""}
            </p>
            <p className="mt-3 max-w-lg text-text-secondary">
              Explore curated properties across the Okanagan. Updated daily from
              the MLS.
            </p>
          </div>
        </AnimateIn>

        {
Dropdown function · typescript · L117-L189 (73 LOC)
src/components/sections/Hero.tsx
function Dropdown({ label, value, options, onChange }: DropdownProps) {
  const [open, setOpen] = useState(false);
  const ref = useRef<HTMLDivElement>(null);

  useEffect(() => {
    function handleClickOutside(e: MouseEvent) {
      if (ref.current && !ref.current.contains(e.target as Node)) {
        setOpen(false);
      }
    }
    document.addEventListener("mousedown", handleClickOutside);
    return () => document.removeEventListener("mousedown", handleClickOutside);
  }, []);

  return (
    <div ref={ref} className="relative flex-1 min-w-0 sm:min-w-[130px]">
      <button
        onClick={() => setOpen((prev) => !prev)}
        className={cn(
          "flex w-full items-center justify-between gap-2 px-3 py-3 text-left sm:px-4",
          "text-sm text-text-secondary transition-colors duration-200",
          "hover:text-text-primary focus:outline-none",
          open && "text-text-primary"
        )}
        type="button"
      >
        <span className="flex flex-col">
    
handleClickOutside function · typescript · L122-L126 (5 LOC)
src/components/sections/Hero.tsx
    function handleClickOutside(e: MouseEvent) {
      if (ref.current && !ref.current.contains(e.target as Node)) {
        setOpen(false);
      }
    }
SellTabContent function · typescript · L194-L235 (42 LOC)
src/components/sections/Hero.tsx
function SellTabContent() {
  return (
    <div className="glass rounded-2xl p-6 sm:p-8">
      {/* 3-step process */}
      <div className="grid gap-6 sm:grid-cols-3 sm:gap-4">
        {sellSteps.map((step, i) => (
          <div
            key={step.step}
            className="relative flex flex-col items-center text-center"
          >
            {/* Step number badge */}
            <div className="flex h-11 w-11 items-center justify-center rounded-full border border-accent/30 bg-accent/10">
              <span className="text-sm font-semibold text-accent">
                {step.step}
              </span>
            </div>
            {/* Connector line (desktop only) */}
            {i < sellSteps.length - 1 && (
              <div className="absolute top-[22px] left-[calc(50%+28px)] hidden h-px w-[calc(100%-56px)] bg-gradient-to-r from-accent/30 to-accent/10 sm:block" />
            )}
            <h3 className="mt-4 text-sm font-medium tracking-wide text-text-primary">
    
MoveTabContent function · typescript · L240-L281 (42 LOC)
src/components/sections/Hero.tsx
function MoveTabContent() {
  return (
    <div className="glass rounded-2xl p-6 sm:p-8">
      <div className="flex flex-col items-center text-center">
        {/* Icon */}
        <div className="flex h-14 w-14 items-center justify-center rounded-full border border-accent/20 bg-accent/5">
          <Phone className="h-6 w-6 text-accent" />
        </div>
        {/* Copy */}
        <h3 className="mt-5 font-heading text-2xl font-light tracking-tight text-text-primary sm:text-3xl">
          Your Next Move,{" "}
          <span className="italic text-accent">Strategically Planned</span>
        </h3>
        <p className="mt-3 max-w-lg text-sm leading-relaxed text-text-secondary">
          Whether you&apos;re upsizing, downsizing, or relocating to the
          Okanagan &mdash; I&apos;ll build a custom plan that aligns your
          timeline, budget, and goals.
        </p>
        {/* Testimonial quote */}
        <div className="mt-6 border-t border-border/50 pt-6">
          <blo
KarsenTabContent function · typescript · L286-L338 (53 LOC)
src/components/sections/Hero.tsx
function KarsenTabContent() {
  return (
    <div className="glass rounded-2xl p-6 sm:p-8">
      <div className="flex flex-col items-center text-center sm:flex-row sm:items-start sm:gap-8 sm:text-left">
        {/* Headshot placeholder */}
        <div className="shrink-0">
          <div className="relative h-24 w-24 overflow-hidden rounded-full border border-accent/20 bg-background-secondary sm:h-28 sm:w-28">
            <div className="flex h-full w-full items-center justify-center">
              <User className="h-8 w-8 text-text-muted/40" />
            </div>
          </div>
        </div>
        {/* Content */}
        <div className="mt-5 sm:mt-0">
          <h3 className="font-heading text-2xl font-light tracking-tight text-text-primary">
            Karsen Koltun
          </h3>
          <p className="mt-1 text-xs tracking-[0.15em] text-accent uppercase">
            Realtor &middot; Royal LePage
          </p>
          <p className="mt-3 max-w-md text-sm leading-relaxe
About: code-quality intelligence by Repobility · https://repobility.com
Hero function · typescript · L343-L645 (303 LOC)
src/components/sections/Hero.tsx
export default function Hero() {
  const router = useRouter();
  const [wordIndex, setWordIndex] = useState(0);
  const [activeTab, setActiveTab] = useState("buy");
  const sectionRef = useRef<HTMLElement>(null);

  /* Search state */
  const [location, setLocation] = useState("All Kelowna");
  const [priceMin, setPriceMin] = useState("Any");
  const [priceMax, setPriceMax] = useState("Any");
  const [beds, setBeds] = useState("Any");

  /* Parallax */
  const { scrollYProgress } = useScroll({
    target: sectionRef,
    offset: ["start start", "end start"],
  });

  const headingY = useTransform(scrollYProgress, [0, 1], [0, -80]);
  const overlayOpacity = useTransform(scrollYProgress, [0, 0.8], [0.55, 0.92]);

  /* Rotating word timer */
  useEffect(() => {
    const interval = setInterval(() => {
      setWordIndex((prev) => (prev + 1) % rotatingWords.length);
    }, 3000);
    return () => clearInterval(interval);
  }, []);

  /* Handle search */
  function handleSearch() {
    cons
handleSearch function · typescript · L373-L381 (9 LOC)
src/components/sections/Hero.tsx
  function handleSearch() {
    const params = new URLSearchParams();
    if (location !== "All Kelowna") params.set("location", location);
    if (priceMin !== "Any") params.set("priceMin", priceMin);
    if (priceMax !== "Any") params.set("priceMax", priceMax);
    if (beds !== "Any") params.set("beds", beds);
    const query = params.toString();
    router.push(`/search${query ? `?${query}` : ""}`);
  }
Newsletter function · typescript · L17-L323 (307 LOC)
src/components/sections/Newsletter.tsx
export default function Newsletter() {
  const [email, setEmail] = useState("");
  const [interest, setInterest] = useState("");
  const [isSubmitted, setIsSubmitted] = useState(false);

  const [isSubmitting, setIsSubmitting] = useState(false);
  const [honey, setHoney] = useState("");

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    if (!email) return;
    setIsSubmitting(true);

    try {
      await fetch("/api/lead", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          name: email.split("@")[0],
          email,
          source: "Newsletter Signup",
          tags: [
            "newsletter",
            "market-report",
            ...(interest ? [`interest-${interest}`] : []),
          ],
          customFields: {
            interest: interest || "Not specified",
          },
          _honey: honey,
        }),
      });

      setIsSubmitted(true);
    } catch (err) {
 
SocialBar function · typescript · L60-L127 (68 LOC)
src/components/sections/SocialBar.tsx
export default function SocialBar() {
  const [hoveredPlatform, setHoveredPlatform] = useState<string | null>(null);

  return (
    <section className="border-y border-border bg-background py-14">
      <div className="mx-auto max-w-7xl px-6 lg:px-10">
        <AnimateIn>
          {/* "Follow Along" header text */}
          <p className="mb-8 text-center text-xs font-medium tracking-[0.4em] text-accent uppercase">
            Follow Along
          </p>

          <div className="flex flex-wrap items-center justify-center gap-8 md:gap-14">
            {socials.map((social) => (
              <a
                key={social.label}
                href={social.href}
                target="_blank"
                rel="noopener noreferrer"
                className="group flex items-center gap-3 transition-all duration-300"
                onMouseEnter={() => setHoveredPlatform(social.hoverBg)}
                onMouseLeave={() => setHoveredPlatform(null)}
              >
               
useCountUp function · typescript · L14-L49 (36 LOC)
src/components/sections/StatsBar.tsx
function useCountUp(
  target: number,
  decimals: number,
  duration: number = 2000,
  trigger: boolean = false
) {
  const [value, setValue] = useState(0);
  const frameRef = useRef<number>(0);

  useEffect(() => {
    if (!trigger) return;

    const startTime = performance.now();

    const animate = (currentTime: number) => {
      const elapsed = currentTime - startTime;
      const progress = Math.min(elapsed / duration, 1);

      // Ease-out cubic
      const eased = 1 - Math.pow(1 - progress, 3);
      const current = eased * target;

      setValue(Number(current.toFixed(decimals)));

      if (progress < 1) {
        frameRef.current = requestAnimationFrame(animate);
      }
    };

    frameRef.current = requestAnimationFrame(animate);

    return () => cancelAnimationFrame(frameRef.current);
  }, [target, decimals, duration, trigger]);

  return value;
}
StatsBar function · typescript · L111-L128 (18 LOC)
src/components/sections/StatsBar.tsx
export default function StatsBar() {
  return (
    <section className="border-y border-border bg-background-secondary">
      <div className="mx-auto max-w-7xl px-6 py-14 lg:px-10">
        <div className="grid grid-cols-2 gap-8 md:grid-cols-4">
          {stats.map((stat, i) => (
            <StatItem
              key={stat.label}
              stat={stat}
              index={i}
              isLast={i === stats.length - 1}
            />
          ))}
        </div>
      </div>
    </section>
  );
}
GoogleLogo function · typescript · L14-L35 (22 LOC)
src/components/sections/Testimonials.tsx
function GoogleLogo({ className }: { className?: string }) {
  return (
    <svg className={className} viewBox="0 0 24 24" fill="none" aria-hidden="true">
      <path
        d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92a5.06 5.06 0 0 1-2.2 3.32v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.1z"
        fill="#4285F4"
      />
      <path
        d="M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z"
        fill="#34A853"
      />
      <path
        d="M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z"
        fill="#FBBC05"
      />
      <path
        d="M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z"
        fill="#EA4335"
      />
    </svg>
  );
}
InstagramLogo function · typescript · L37-L54 (18 LOC)
src/components/sections/Testimonials.tsx
function InstagramLogo({ className }: { className?: string }) {
  return (
    <svg className={className} viewBox="0 0 24 24" fill="none" aria-hidden="true">
      <defs>
        <linearGradient id="ig-grad" x1="0%" y1="100%" x2="100%" y2="0%">
          <stop offset="0%" stopColor="#FED373" />
          <stop offset="25%" stopColor="#F15245" />
          <stop offset="50%" stopColor="#D92E7F" />
          <stop offset="75%" stopColor="#9B36B7" />
          <stop offset="100%" stopColor="#515ECF" />
        </linearGradient>
      </defs>
      <rect x="2" y="2" width="20" height="20" rx="5" stroke="url(#ig-grad)" strokeWidth="2" />
      <circle cx="12" cy="12" r="5" stroke="url(#ig-grad)" strokeWidth="2" />
      <circle cx="17.5" cy="6.5" r="1.5" fill="url(#ig-grad)" />
    </svg>
  );
}
Want fix-PRs on findings? Install Repobility's GitHub App · github.com/apps/repobility-bot
FacebookLogo function · typescript · L56-L65 (10 LOC)
src/components/sections/Testimonials.tsx
function FacebookLogo({ className }: { className?: string }) {
  return (
    <svg className={className} viewBox="0 0 24 24" fill="none" aria-hidden="true">
      <path
        d="M24 12c0-6.627-5.373-12-12-12S0 5.373 0 12c0 5.99 4.388 10.954 10.125 11.854V15.47H7.078V12h3.047V9.356c0-3.007 1.792-4.668 4.533-4.668 1.312 0 2.686.234 2.686.234v2.953H15.83c-1.491 0-1.956.925-1.956 1.875V12h3.328l-.532 3.47h-2.796v8.385C19.612 22.954 24 17.99 24 12z"
        fill="#1877F2"
      />
    </svg>
  );
}
LinkedInLogo function · typescript · L67-L76 (10 LOC)
src/components/sections/Testimonials.tsx
function LinkedInLogo({ className }: { className?: string }) {
  return (
    <svg className={className} viewBox="0 0 24 24" fill="none" aria-hidden="true">
      <path
        d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433a2.062 2.062 0 1 1 0-4.124 2.062 2.062 0 0 1 0 4.124zM6.89 20.452H3.58V9h3.31v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z"
        fill="#0A66C2"
      />
    </svg>
  );
}
RateMyAgentLogo function · typescript · L78-L88 (11 LOC)
src/components/sections/Testimonials.tsx
function RateMyAgentLogo({ className }: { className?: string }) {
  return (
    <svg className={className} viewBox="0 0 24 24" fill="none" aria-hidden="true">
      <rect x="1" y="1" width="22" height="22" rx="4" fill="#00B67A" />
      <path
        d="M12 5l1.76 3.56L17.5 9.2l-2.75 2.68.65 3.78L12 13.86l-3.4 1.8.65-3.78L6.5 9.2l3.74-.64L12 5z"
        fill="white"
      />
    </svg>
  );
}
TestimonialCard function · typescript · L195-L238 (44 LOC)
src/components/sections/Testimonials.tsx
function TestimonialCard({ testimonial }: { testimonial: Testimonial }) {
  return (
    <div
      className={cn(
        "mb-4 flex w-full cursor-default break-inside-avoid flex-col justify-between gap-5 p-6",
        "border border-border bg-background-secondary/50",
        "transition-all duration-300 hover:-translate-y-0.5 hover:border-accent/20 hover:shadow-lg hover:shadow-accent/5"
      )}
    >
      {/* Stars */}
      <div>
        <div className="flex gap-0.5">
          {Array.from({ length: 5 }).map((_, i) => (
            <Star key={i} className="h-3.5 w-3.5 fill-warm text-warm" />
          ))}
        </div>

        {/* Quote */}
        <blockquote className="mt-4 text-sm leading-relaxed text-text-secondary">
          &ldquo;{testimonial.quote}&rdquo;
        </blockquote>
      </div>

      {/* Attribution */}
      <div className="flex items-center gap-3 border-t border-border pt-4">
        {/* Avatar placeholder with initials */}
        <div className="flex h
Testimonials function · typescript · L244-L371 (128 LOC)
src/components/sections/Testimonials.tsx
export default function Testimonials() {
  return (
    <section className="relative bg-background py-16 md:py-24 lg:py-32 overflow-hidden">
      {/* Decorative blurs */}
      <div className="absolute top-20 -left-20 h-64 w-64 rounded-full bg-accent/5 blur-[100px]" />
      <div className="absolute -right-20 bottom-20 h-64 w-64 rounded-full bg-warm/5 blur-[100px]" />

      <div className="relative mx-auto max-w-7xl px-6 lg:px-10">
        {/* Header */}
        <AnimateIn>
          <div className="text-center">
            <p className="text-xs font-medium tracking-[0.3em] text-accent uppercase">
              Testimonials
            </p>
            <h2 className="mt-4 font-heading text-4xl font-light tracking-tight text-text-primary md:text-5xl">
              What Clients Say
            </h2>
            <p className="mx-auto mt-4 max-w-lg text-text-secondary">
              Don&apos;t just take my word for it. Here&apos;s what{" "}
              <span className="font-medium t
handleMouseMove function · typescript · L18-L26 (9 LOC)
src/components/ui/aceternity-input.tsx
    function handleMouseMove({
      currentTarget,
      clientX,
      clientY,
    }: React.MouseEvent) {
      const { left, top } = currentTarget.getBoundingClientRect();
      mouseX.set(clientX - left);
      mouseY.set(clientY - top);
    }
AnimateIn function · typescript · L13-L38 (26 LOC)
src/components/ui/AnimateIn.tsx
export default function AnimateIn({
  children,
  className,
  delay = 0,
  direction = "up",
}: AnimateInProps) {
  const directionOffset = {
    up: { y: 40 },
    down: { y: -40 },
    left: { x: 40 },
    right: { x: -40 },
    none: {},
  };

  return (
    <motion.div
      initial={{ opacity: 0, ...directionOffset[direction] }}
      whileInView={{ opacity: 1, x: 0, y: 0 }}
      viewport={{ once: true, margin: "-80px" }}
      transition={{ duration: 0.7, delay, ease: [0.25, 0.4, 0.25, 1] }}
      className={cn(className)}
    >
      {children}
    </motion.div>
  );
}
BackToTop function · typescript · L7-L42 (36 LOC)
src/components/ui/BackToTop.tsx
export default function BackToTop() {
  const [visible, setVisible] = useState(false);

  useEffect(() => {
    function handleScroll() {
      setVisible(window.scrollY > 500);
    }

    window.addEventListener("scroll", handleScroll, { passive: true });
    handleScroll();

    return () => window.removeEventListener("scroll", handleScroll);
  }, []);

  function scrollToTop() {
    window.scrollTo({ top: 0, behavior: "smooth" });
  }

  return (
    <AnimatePresence>
      {visible ? (
        <motion.button
          initial={{ opacity: 0, scale: 0.8 }}
          animate={{ opacity: 1, scale: 1 }}
          exit={{ opacity: 0, scale: 0.8 }}
          transition={{ duration: 0.3, ease: [0.25, 0.4, 0.25, 1] }}
          onClick={scrollToTop}
          aria-label="Back to top"
          className="fixed bottom-24 right-4 z-50 flex h-11 w-11 items-center justify-center rounded-full border border-accent bg-background text-accent transition-colors duration-300 hover:bg-accent hover:text
Repobility — same analyzer, your code, free for public repos · /scan/
handleScroll function · typescript · L11-L13 (3 LOC)
src/components/ui/BackToTop.tsx
    function handleScroll() {
      setVisible(window.scrollY > 500);
    }
scrollToTop function · typescript · L21-L23 (3 LOC)
src/components/ui/BackToTop.tsx
  function scrollToTop() {
    window.scrollTo({ top: 0, behavior: "smooth" });
  }
Badge function · typescript · L25-L41 (17 LOC)
src/components/ui/Badge.tsx
export default function Badge({
  children,
  variant = "accent",
  size = "sm",
}: BadgeProps) {
  return (
    <span
      className={cn(
        "inline-flex items-center rounded-full border font-medium tracking-[0.1em] uppercase",
        variantStyles[variant],
        sizeStyles[size]
      )}
    >
      {children}
    </span>
  );
}
Button function · typescript · L58-L111 (54 LOC)
src/components/ui/Button.tsx
export default function Button({
  variant = "primary",
  size = "md",
  href,
  showArrow = false,
  loading = false,
  children,
  className,
  ...rest
}: ButtonProps) {
  const baseClasses = cn(
    "group inline-flex items-center justify-center font-medium uppercase transition-all duration-300",
    variantStyles[variant],
    sizeStyles[size],
    loading && "pointer-events-none opacity-70",
    className
  );

  const content = (
    <>
      {loading ? (
        <Loader2 className="h-3.5 w-3.5 animate-spin" />
      ) : null}
      <span>{children}</span>
      {showArrow && !loading ? (
        <ArrowRight className="h-3.5 w-3.5 transition-transform duration-300 group-hover:translate-x-1" />
      ) : null}
    </>
  );

  if (href) {
    const { disabled } = rest as ButtonAsLink;
    if (disabled) {
      return (
        <span className={cn(baseClasses, "pointer-events-none opacity-40")} aria-disabled="true">
          {content}
        </span>
      );
    }
    return (
   
Card function · typescript · L20-L48 (29 LOC)
src/components/ui/Card.tsx
export default function Card({
  href,
  children,
  className,
  hoverable = true,
  padding = "md",
}: CardProps) {
  const cardClasses = cn(
    "border border-border bg-background-secondary transition-all duration-500",
    paddingMap[padding],
    hoverable && "hover:border-accent/30",
    href && hoverable && "cursor-pointer",
    className
  );

  if (href) {
    return (
      <Link href={href} className={cn(cardClasses, "block")}>
        {children}
      </Link>
    );
  }

  return (
    <div className={cardClasses}>
      {children}
    </div>
  );
}
Container function · typescript · L18-L35 (18 LOC)
src/components/ui/Container.tsx
export default function Container({
  size = "lg",
  children,
  className,
  as: Component = "div",
}: ContainerProps) {
  return (
    <Component
      className={cn(
        "mx-auto px-6 lg:px-10",
        sizeMap[size],
        className
      )}
    >
      {children}
    </Component>
  );
}
GradualBlur function · typescript · L56-L170 (115 LOC)
src/components/ui/GradualBlur.tsx
function GradualBlur({
  position = "bottom",
  strength = 2,
  height = "6rem",
  divCount = 5,
  exponential = false,
  zIndex = 1000,
  opacity = 1,
  curve = "linear",
  target = "parent",
  className = "",
  style = {},
}: GradualBlurProps) {
  const containerRef = useRef<HTMLDivElement>(null);
  const [mounted, setMounted] = useState(false);

  useEffect(() => {
    setMounted(true);
  }, []);

  /* Build the layered blur divs */
  const blurDivs = useMemo(() => {
    const divs: React.ReactNode[] = [];
    const increment = 100 / divCount;
    const curveFunc = CURVE_FUNCTIONS[curve] || CURVE_FUNCTIONS.linear;
    const direction = GRADIENT_DIRECTION[position] || "to bottom";

    for (let i = 1; i <= divCount; i++) {
      let progress = i / divCount;
      progress = curveFunc(progress);

      const blurValue = exponential
        ? Math.pow(2, progress * 4) * 0.0625 * strength
        : 0.0625 * (progress * divCount + 1) * strength;

      const p1 = Math.round((increment * 
Input function · typescript · L28-L119 (92 LOC)
src/components/ui/Input.tsx
  function Input(
    {
      label,
      type = "text",
      error,
      required,
      as = "input",
      options = [],
      rows = 5,
      className,
      id,
      ...rest
    },
    ref
  ) {
    const fieldId = id || (label ? label.toLowerCase().replace(/\s+/g, "-") : undefined);

    const fieldClasses = cn(
      baseFieldStyles,
      error && "border-red-500 focus:border-red-500",
      className
    );

    const renderField = () => {
      if (as === "textarea") {
        return (
          <textarea
            ref={ref as React.Ref<HTMLTextAreaElement>}
            id={fieldId}
            rows={rows}
            required={required}
            className={cn(fieldClasses, "resize-none")}
            {...(rest as React.TextareaHTMLAttributes<HTMLTextAreaElement>)}
          />
        );
      }

      if (as === "select") {
        return (
          <select
            ref={ref as React.Ref<HTMLSelectElement>}
            id={fieldId}
            required={requir
Repobility · code-quality intelligence · https://repobility.com
Marquee function · typescript · L13-L51 (39 LOC)
src/components/ui/Marquee.tsx
export function Marquee({
  className,
  reverse = false,
  pauseOnHover = false,
  children,
  vertical = false,
  repeat = 4,
  ...props
}: MarqueeProps) {
  return (
    <div
      {...props}
      className={cn(
        "group flex overflow-hidden p-2 [--duration:40s] [--gap:1rem] [gap:var(--gap)]",
        {
          "flex-row": !vertical,
          "flex-col": vertical,
        },
        className
      )}
    >
      {Array(repeat)
        .fill(0)
        .map((_, i) => (
          <div
            key={i}
            className={cn("flex shrink-0 justify-around [gap:var(--gap)]", {
              "animate-marquee flex-row": !vertical,
              "animate-marquee-vertical flex-col": vertical,
              "group-hover:[animation-play-state:paused]": pauseOnHover,
              "[animation-direction:reverse]": reverse,
            })}
          >
            {children}
          </div>
        ))}
    </div>
  );
}
PageBlurEdges function · typescript · L12-L42 (31 LOC)
src/components/ui/PageBlurEdges.tsx
export default function PageBlurEdges() {
  return (
    <>
      {/* Top edge — below navbar */}
      <GradualBlur
        target="page"
        position="top"
        height="7rem"
        strength={2}
        divCount={5}
        curve="bezier"
        exponential
        opacity={1}
        zIndex={30}
      />

      {/* Bottom edge — above footer */}
      <GradualBlur
        target="page"
        position="bottom"
        height="7rem"
        strength={2}
        divCount={5}
        curve="bezier"
        exponential
        opacity={1}
        zIndex={30}
      />
    </>
  );
}
PageHero function · typescript · L21-L82 (62 LOC)
src/components/ui/PageHero.tsx
export default function PageHero({
  label,
  heading,
  accentText,
  description,
  children,
  size = "md",
}: PageHeroProps) {
  return (
    <section
      className={cn(
        "relative flex items-center justify-center overflow-hidden",
        sizeMap[size]
      )}
    >
      {/* Background gradient */}
      <div className="absolute inset-0">
        <div className="absolute inset-0 bg-gradient-to-b from-background-tertiary via-background to-background" />
        <div className="absolute inset-0 opacity-[0.03]" style={{
          backgroundImage: `url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noise'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noise)'/%3E%3C/svg%3E")`,
        }} />
      </div>

      {/* Subtle glow orbs */}
      <div className="absolute top-1/3 left-1/2 h-[400px] w-[400px] -tran
Progress function · typescript · L11-L25 (15 LOC)
src/components/ui/Progress.tsx
export default function Progress({ value, className }: ProgressProps) {
  return (
    <div
      className={cn(
        "h-1.5 w-full overflow-hidden rounded-full bg-background-secondary",
        className
      )}
    >
      <div
        className="h-full rounded-full bg-warm transition-all duration-500 ease-out"
        style={{ width: `${Math.min(100, Math.max(0, value))}%` }}
      />
    </div>
  );
}
ScrollProgress function · typescript · L5-L36 (32 LOC)
src/components/ui/ScrollProgress.tsx
export default function ScrollProgress() {
  const [progress, setProgress] = useState(0);

  useEffect(() => {
    function handleScroll() {
      const scrollTop = window.scrollY;
      const docHeight = document.documentElement.scrollHeight - window.innerHeight;

      if (docHeight <= 0) {
        setProgress(0);
        return;
      }

      const scrollPercent = (scrollTop / docHeight) * 100;
      setProgress(Math.min(scrollPercent, 100));
    }

    window.addEventListener("scroll", handleScroll, { passive: true });
    handleScroll();

    return () => window.removeEventListener("scroll", handleScroll);
  }, []);

  return (
    <div className="fixed top-0 left-0 right-0 z-50 h-[2px] bg-transparent">
      <div
        className="h-full bg-accent transition-[width] duration-100 ease-out"
        style={{ width: `${progress}%` }}
      />
    </div>
  );
}
handleScroll function · typescript · L9-L20 (12 LOC)
src/components/ui/ScrollProgress.tsx
    function handleScroll() {
      const scrollTop = window.scrollY;
      const docHeight = document.documentElement.scrollHeight - window.innerHeight;

      if (docHeight <= 0) {
        setProgress(0);
        return;
      }

      const scrollPercent = (scrollTop / docHeight) * 100;
      setProgress(Math.min(scrollPercent, 100));
    }
ScrollRestoration function · typescript · L10-L18 (9 LOC)
src/components/ui/ScrollRestoration.tsx
export default function ScrollRestoration() {
  const pathname = usePathname();

  useEffect(() => {
    window.scrollTo({ top: 0, left: 0, behavior: "instant" });
  }, [pathname]);

  return null;
}
SectionHeader function · typescript · L12-L55 (44 LOC)
src/components/ui/SectionHeader.tsx
export default function SectionHeader({
  label,
  heading,
  accentText,
  description,
  align = "center",
  className,
}: SectionHeaderProps) {
  return (
    <div
      className={cn(
        align === "center" ? "text-center" : "text-left",
        className
      )}
    >
      {label ? (
        <p className="mb-4 text-xs font-medium tracking-[0.3em] text-accent uppercase">
          {label}
        </p>
      ) : null}

      <h2 className="font-heading text-3xl font-light leading-tight tracking-tight text-text-primary sm:text-4xl md:text-5xl">
        {heading}
        {accentText ? (
          <>
            {" "}
            <span className="italic text-accent">{accentText}</span>
          </>
        ) : null}
      </h2>

      {description ? (
        <p
          className={cn(
            "mt-5 text-base leading-relaxed text-text-secondary",
            align === "center" && "mx-auto max-w-2xl"
          )}
        >
          {description}
        </p>
      ) : null}
About: code-quality intelligence by Repobility · https://repobility.com
Skeleton function · typescript · L17-L31 (15 LOC)
src/components/ui/Skeleton.tsx
export default function Skeleton({
  className,
  variant = "text",
}: SkeletonProps) {
  return (
    <div
      className={cn(
        "animate-shimmer bg-background-secondary",
        variantStyles[variant],
        className
      )}
      aria-hidden="true"
    />
  );
}
getAllPosts function · typescript · L5-L9 (5 LOC)
src/lib/blog.ts
export function getAllPosts(): BlogPost[] {
  return [...posts].sort(
    (a, b) => new Date(b.date).getTime() - new Date(a.date).getTime()
  );
}
getPostBySlug function · typescript · L12-L14 (3 LOC)
src/lib/blog.ts
export function getPostBySlug(slug: string): BlogPost | undefined {
  return posts.find((p) => p.slug === slug);
}
getAllSlugs function · typescript · L17-L19 (3 LOC)
src/lib/blog.ts
export function getAllSlugs(): string[] {
  return posts.filter((p) => p.content).map((p) => p.slug);
}
getCategories function · typescript · L22-L25 (4 LOC)
src/lib/blog.ts
export function getCategories(): string[] {
  const cats = new Set(posts.map((p) => p.category));
  return Array.from(cats).sort();
}
createMetadata function · typescript · L24-L76 (53 LOC)
src/lib/metadata.ts
export function createMetadata({
  title,
  description = "Premium real estate services in Kelowna, BC. Buy, sell, or get your home value with Karsen Koltun at Royal LePage.",
  path = "",
  ogImage = "/og-image.jpg",
  noIndex = false,
}: CreateMetadataOptions = {}): Metadata {
  const url = `${BASE_URL}${path}`;
  const fullOgImage = ogImage.startsWith("http")
    ? ogImage
    : `${BASE_URL}${ogImage}`;

  return {
    title: title ?? {
      default: "Karsen Koltun | Kelowna Real Estate",
      template: "%s | Karsen Koltun",
    },
    description,
    metadataBase: new URL(BASE_URL),
    alternates: {
      canonical: url,
    },
    openGraph: {
      type: "website",
      locale: "en_CA",
      url,
      siteName: "Karsen Koltun | Kelowna Real Estate",
      title: title
        ? `${title} | Karsen Koltun`
        : "Karsen Koltun | Kelowna Real Estate",
      description,
      images: [
        {
          url: fullOgImage,
          width: 1200,
          height: 630,
   
getMonthlyRate function · typescript · L73-L77 (5 LOC)
src/lib/mortgage.ts
export function getMonthlyRate(annualRate: number): number {
  if (annualRate <= 0) return 0;
  const semiAnnualRate = annualRate / 2;
  return Math.pow(1 + semiAnnualRate, 1 / 6) - 1;
}
calcMonthlyPayment function · typescript · L81-L90 (10 LOC)
src/lib/mortgage.ts
export function calcMonthlyPayment(
  principal: number,
  annualRate: number,
  amortYears: number
): number {
  const r = getMonthlyRate(annualRate);
  const n = amortYears * 12;
  if (r === 0) return principal / n;
  return (principal * (r * Math.pow(1 + r, n))) / (Math.pow(1 + r, n) - 1);
}
Want fix-PRs on findings? Install Repobility's GitHub App · github.com/apps/repobility-bot
calcCMHC function · typescript · L94-L115 (22 LOC)
src/lib/mortgage.ts
export function calcCMHC(
  homePrice: number,
  downPayment: number,
  amortYears: number,
  isFirstTimeBuyer: boolean
): number {
  const mortgageAmount = homePrice - downPayment;
  const ltv = mortgageAmount / homePrice;

  if (ltv <= 0.8) return 0;
  if (homePrice > 1_500_000) return 0;

  let rate: number;
  if (ltv > 0.9) rate = 0.04;
  else if (ltv > 0.85) rate = 0.031;
  else rate = 0.028;

  // 30yr surcharge for eligible buyers
  if (amortYears > 25 && isFirstTimeBuyer) rate += 0.002;

  return mortgageAmount * rate;
}
calcMinimumDownPayment function · typescript · L119-L127 (9 LOC)
src/lib/mortgage.ts
export function calcMinimumDownPayment(homePrice: number): number {
  if (homePrice <= 500_000) {
    return homePrice * 0.05;
  } else if (homePrice < 1_500_000) {
    return 500_000 * 0.05 + (homePrice - 500_000) * 0.1;
  } else {
    return homePrice * 0.2;
  }
}
calcBCPTT function · typescript · L131-L149 (19 LOC)
src/lib/mortgage.ts
export function calcBCPTT(homePrice: number): number {
  let tax = 0;
  if (homePrice > 3_000_000) {
    tax += (homePrice - 3_000_000) * 0.05;
    tax += 1_000_000 * 0.03;
    tax += 1_800_000 * 0.02;
    tax += 200_000 * 0.01;
  } else if (homePrice > 2_000_000) {
    tax += (homePrice - 2_000_000) * 0.03;
    tax += 1_800_000 * 0.02;
    tax += 200_000 * 0.01;
  } else if (homePrice > 200_000) {
    tax += (homePrice - 200_000) * 0.02;
    tax += 200_000 * 0.01;
  } else {
    tax += homePrice * 0.01;
  }
  return tax;
}
‹ prevpage 2 / 3next ›