From a369b606a52d57e6f52d668d2dfbc29d4669e518 Mon Sep 17 00:00:00 2001 From: Maze Winther Date: Sat, 26 Jul 2025 11:19:48 +0200 Subject: [PATCH] Merge pull request [#459](https://github.com/mazeincoding/AppCut/issues/459) --- .../web/src/components/landing/handlebars.tsx | 175 ++++++------------ 1 file changed, 58 insertions(+), 117 deletions(-) diff --git a/apps/web/src/components/landing/handlebars.tsx b/apps/web/src/components/landing/handlebars.tsx index 94764dbe..26cf9254 100644 --- a/apps/web/src/components/landing/handlebars.tsx +++ b/apps/web/src/components/landing/handlebars.tsx @@ -1,163 +1,104 @@ "use client"; -import React, { useState, useRef, useEffect } from "react"; -import { motion, useMotionValue, useTransform, PanInfo } from "motion/react"; +import { + motion, + useMotionTemplate, + useMotionValue, + useMotionValueEvent, + useTransform, +} from "motion/react"; +import { type PropsWithChildren, useEffect, useRef, useState } from "react"; -interface HandlebarsProps { - children: React.ReactNode; - minWidth?: number; - maxWidth?: number; - onRangeChange?: (left: number, right: number) => void; -} +type HandlebarsProps = PropsWithChildren; + +export function Handlebars({ children }: HandlebarsProps) { + const containerRef = useRef(null); + + const [width, setWidth] = useState(0); -export function Handlebars({ - children, - minWidth = 50, - maxWidth = 400, - onRangeChange, -}: HandlebarsProps) { const [leftHandle, setLeftHandle] = useState(0); - const [rightHandle, setRightHandle] = useState(maxWidth); - const [contentWidth, setContentWidth] = useState(maxWidth); + const [rightHandle, setRightHandle] = useState(width); const leftHandleX = useMotionValue(0); - const rightHandleX = useMotionValue(maxWidth); - - const visibleWidth = useTransform( - [leftHandleX, rightHandleX], - (values: number[]) => values[1] - values[0] - ); - - const contentLeft = useTransform(leftHandleX, (left: number) => -left); - - const containerRef = useRef(null); - const measureRef = useRef(null); + const rightHandleX = useMotionValue(width); useEffect(() => { - if (!measureRef.current) return; + const el = containerRef.current; + if (!el) return; - const measureContent = () => { - if (measureRef.current) { - const width = measureRef.current.scrollWidth; - const paddedWidth = width + 32; - setContentWidth(paddedWidth); - setRightHandle(paddedWidth); - rightHandleX.set(paddedWidth); - } - }; + const observer = new ResizeObserver(() => { + setWidth(el.offsetWidth); + setRightHandle(el.offsetWidth); + rightHandleX.set(el.offsetWidth); + }); - measureContent(); - const timer = setTimeout(measureContent, 50); + observer.observe(el); + return () => observer.disconnect(); + }, [rightHandleX.set]); - return () => clearTimeout(timer); - }, [children, rightHandleX]); - - useEffect(() => { - leftHandleX.set(leftHandle); - }, [leftHandle, leftHandleX]); - - useEffect(() => { - rightHandleX.set(rightHandle); - }, [rightHandle, rightHandleX]); - - useEffect(() => { - onRangeChange?.(leftHandle, rightHandle); - }, [leftHandle, rightHandle, onRangeChange]); - - const handleLeftDrag = (event: any, info: PanInfo) => { - const newLeft = Math.max( - 0, - Math.min(leftHandle + info.offset.x, rightHandle - minWidth) - ); - setLeftHandle(newLeft); - }; - - const handleRightDrag = (event: any, info: PanInfo) => { - const newRight = Math.max( - leftHandle + minWidth, - Math.min(contentWidth, rightHandle + info.offset.x) - ); - setRightHandle(newRight); - }; + useMotionValueEvent(leftHandleX, "change", () => { + setLeftHandle(leftHandleX.get()); + }); + useMotionValueEvent(rightHandleX, "change", () => { + setRightHandle(rightHandleX.get()); + }); + const leftGradient = useTransform(leftHandleX, [0, width - 10], [0, 100]); + const rightGradient = useTransform(rightHandleX, [0, width + 10], [0, 100]); return (
-
- {children} -
- -
-
+
+
-
+
-
+
- - - {children} - - + {children} +
);