From eb64cb95b19ef5e8bc48b69692617ebb06781fa9 Mon Sep 17 00:00:00 2001 From: Seth Trowbridge Date: Sun, 21 May 2023 22:12:47 -0400 Subject: [PATCH] start class states --- example/app.tsx | 12 ------ example/tree-menu.tsx | 88 ++++++++++++++++++++++++++++--------------- 2 files changed, 58 insertions(+), 42 deletions(-) diff --git a/example/app.tsx b/example/app.tsx index 4d3d993..383000c 100644 --- a/example/app.tsx +++ b/example/app.tsx @@ -41,18 +41,6 @@ export default ()=>

hello!

hello!

hello!

- - - -

hello!

-

hello!

-

hello!

-

hello!

-

hello!

-

hello!

-

hello!

-
-

hello!

hello!

hello!

diff --git a/example/tree-menu.tsx b/example/tree-menu.tsx index 8d15542..aad5246 100644 --- a/example/tree-menu.tsx +++ b/example/tree-menu.tsx @@ -17,19 +17,31 @@ export const Menu =(props:{children:React.JSX.Element|React.JSX.Element[]})=> const [stateGet, stateSet] = React.useContext(CTX); const refElement:React.MutableRefObject = React.useRef( null ); const refControl:React.MutableRefObject = React.useRef( null ); - - const classDefault = "relative transition-all duration-700 border"; - const classOpen = "h-auto w-auto top-10 px-4 "; - const classShut = "h-0 w-[300px] top-0 px-0"; - window.TwindInst(classDefault); - window.TwindInst(classOpen); - window.TwindInst(classShut); + type MenuClassStates = {Keep:string, Open:string, Shut:string, Move:string, Exit:string}; + 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", + Move: "", + Exit: "h-auto w-auto top-36 px-4 opacity-0" + }; + const Window = window as {TwindInst?:(c:string)=>string}; + if(Window.TwindInst) + { + for(let stateName in Classes) + { + Classes[stateName as keyof MenuClassStates] = Window.TwindInst(Classes[stateName as keyof MenuClassStates]); + } + } React.useEffect(()=>refControl.current = Collapser(refElement.current as HTMLElement, true), []); React.useEffect(()=> {refControl.current && refControl.current(stateGet.open, 1000, ()=>stateSet({done:true}))}, [stateGet.open]) - return
}>{props.children}
; + return
}> + { (!stateGet.open && stateGet.done) ? null : props.children} +
; }; export const Button =()=> @@ -50,21 +62,36 @@ export function Collapser(inElement:HTMLElement, initialState = false) let userMode = initialState; let frameRequest = 0; - const done = (inEvent:TransitionEvent)=> + let transitions = new Set(); + + const run = (inEvent:TransitionEvent)=> { - if (inEvent.propertyName == "height" && inEvent.target == inElement) + if (inEvent.target == inElement) { - inEvent.stopPropagation(); - if (userMode) - { - inElement.style.height = ""; - inElement.style.width = ""; - inElement.style.overflow = "visible"; - } - userDone(userMode); + console.log("transition", inEvent.target) + transitions.add(inEvent.propertyName); } }; - inElement.addEventListener("transitionend", done); + + const end = (inEvent:TransitionEvent)=> + { + if (inEvent.target == inElement) + { + transitions.delete(inEvent.propertyName); + if(transitions.size === 0) + { + if (userMode) + { + inElement.setAttribute("style", ""); + } + userDone(userMode); + } + + } + }; + + inElement.addEventListener("transitionend", end); + inElement.addEventListener("transitionrun", run); return function(inOpen, inMs, inDone) { @@ -79,16 +106,15 @@ export function Collapser(inElement:HTMLElement, initialState = false) const h1 = inElement.clientHeight; const w1 = inElement.clientWidth; const classesInitial = inElement.getAttribute("class"); - const classesStart = inElement.getAttribute("data-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.style.transition = "none"; - inElement.style.height = ""; - inElement.style.width = ""; + inElement.setAttribute("style", ""); + inElement.style.transition = "width none, height none"; // 3) add new classes and capture new height - inElement.className = classesStart + " " + classesEnd; + inElement.className = classesKeep + " " + classesEnd; const h2 = inElement.clientHeight; const w2 = inElement.clientWidth; @@ -96,26 +122,28 @@ export function Collapser(inElement:HTMLElement, initialState = false) inElement.style.height = h1+"px"; inElement.style.width = w1+"px"; inElement.style.overflow = "hidden"; - inElement.className = classesInitial; + inElement.className = classesInitial ?? ""; console.log(`BEFORE classes:"${inElement.className}" width:"${w1}" height:"${h1}"`); frameRequest = requestAnimationFrame(()=> { inElement.style.transition = ""; + frameRequest = requestAnimationFrame(()=> { - inElement.style.height = `${h2}px`; - inElement.style.width = `${w2}px`; - inElement.className = classesStart + " " + classesEnd; - console.log(`AFTER classes:"${inElement.className}" width:"${w2}" height:"${h2}"`); + inElement.style.height = `${h2}px`; + inElement.style.width = `${w2}px`; + inElement.className = classesKeep + " " + classesEnd; + console.log(`AFTER classes:"${inElement.className}" width:"${w2}" height:"${h2}"`); }); }); } else { - inElement.removeEventListener("transitionend", done); + inElement.removeEventListener("transitionrun", run); + inElement.removeEventListener("transitionend", end); } } as CollapseControls; } \ No newline at end of file