diff --git a/example/tree-menu.tsx b/example/tree-menu.tsx index aad5246..f260bc3 100644 --- a/example/tree-menu.tsx +++ b/example/tree-menu.tsx @@ -22,8 +22,8 @@ export const Menu =(props:{children:React.JSX.Element|React.JSX.Element[]})=> const Classes:MenuClassStates = { Keep: "relative transition-all border", - Open: "h-auto w-auto top-10 duration-1000", - Shut: "h-0 w-[300px] top-0 duration-1000", + Open: "h-auto w-auto top-10 duration-700", + Shut: "h-0 w-[300px] top-0 duration-300", Move: "", Exit: "h-auto w-auto top-36 px-4 opacity-0" }; @@ -61,14 +61,15 @@ export function Collapser(inElement:HTMLElement, initialState = false) let userDone:DoneCallback = (openState) => {}; let userMode = initialState; let frameRequest = 0; + let inTransition = false; let transitions = new Set(); + let measurements = false; const run = (inEvent:TransitionEvent)=> { if (inEvent.target == inElement) { - console.log("transition", inEvent.target) transitions.add(inEvent.propertyName); } }; @@ -84,12 +85,28 @@ export function Collapser(inElement:HTMLElement, initialState = false) { inElement.setAttribute("style", ""); } + inTransition = false; userDone(userMode); } } }; + const getMeasurements =(inClasses:Record)=> + { + inElement.setAttribute("style", `transition: none;`); + const initialClasses = inElement.getAttribute("class")||""; + const output = {} as Record; + Object.entries(inClasses).forEach(([key, value])=> + { + inElement.setAttribute("class", value); + output[key] = { width: inElement.clientWidth, height: inElement.clientHeight }; + }); + inElement.removeAttribute("style"); + inElement.setAttribute("class", initialClasses); + return output; + }; + inElement.addEventListener("transitionend", end); inElement.addEventListener("transitionrun", run); @@ -102,41 +119,30 @@ export function Collapser(inElement:HTMLElement, initialState = false) userDone = inDone|| ((m)=>{}) as DoneCallback; userMode = inOpen === true; - // 1) capture current state and possible classes - const h1 = inElement.clientHeight; - const w1 = inElement.clientWidth; - const classesInitial = inElement.getAttribute("class"); - const classesKeep = inElement.getAttribute("data-class-keep"); - const classesEnd = inElement.getAttribute(`data-class-${inOpen?"open":"shut"}`); - - // 2) disable transitions to get immediate results - inElement.setAttribute("style", ""); - inElement.style.transition = "width none, height none"; + if((inOpen || !measurements) && !inTransition) + { + measurements = getMeasurements({ + Open: inElement.getAttribute("data-class-open")||"", + Shut: inElement.getAttribute("data-class-shut")||"", + }); + } + else + { + console.log("inbterrupt"); + } - // 3) add new classes and capture new height - inElement.className = classesKeep + " " + classesEnd; - const h2 = inElement.clientHeight; - const w2 = inElement.clientWidth; - - // 4) put everything back (and turn on overflow hidden) - inElement.style.height = h1+"px"; - inElement.style.width = w1+"px"; + inElement.style.width = inElement.clientWidth + "px"; + inElement.style.height = inElement.clientHeight + "px"; inElement.style.overflow = "hidden"; - inElement.className = classesInitial ?? ""; - console.log(`BEFORE classes:"${inElement.className}" width:"${w1}" height:"${h1}"`); + inTransition = true; frameRequest = requestAnimationFrame(()=> { - inElement.style.transition = ""; - - frameRequest = requestAnimationFrame(()=> - { - inElement.style.height = `${h2}px`; - inElement.style.width = `${w2}px`; - inElement.className = classesKeep + " " + classesEnd; - console.log(`AFTER classes:"${inElement.className}" width:"${w2}" height:"${h2}"`); - }); + const measure = inOpen ? measurements.Open : measurements.Shut; + inElement.style.width = measure.width + "px"; + inElement.style.height = measure.height + "px"; + inElement.className = inElement.getAttribute("data-class-keep") + " " + inElement.getAttribute(`data-class-${inOpen?"open":"shut"}`); }); }