From 608e482469680d84c0f252df5891c63a8fd3ecaf Mon Sep 17 00:00:00 2001 From: Seth Trowbridge Date: Mon, 15 May 2023 07:26:18 -0400 Subject: [PATCH] start collapse --- app.tsx | 36 ++++++++++++----- components/collapse.tsx | 87 +++++++++++++++++++++++++++++++++++++++++ deep/component.tsx | 5 +-- deno.jsonc | 3 +- 4 files changed, 117 insertions(+), 14 deletions(-) create mode 100644 components/collapse.tsx diff --git a/app.tsx b/app.tsx index abb53d3..954a309 100644 --- a/app.tsx +++ b/app.tsx @@ -1,22 +1,27 @@ import React from "react"; import * as Iso from "@eno/iso"; +import Collapse from "$/collapse.tsx"; const Comp = React.lazy(()=>import("./deep/component.tsx")); export default ()=> { const [countGet, countSet] = React.useState(1); - return
+ return
-
-
; +}; + +export const CSS = { + rules: + [ + ["layout-middle", "w-full max-w-4xl p-4"] + ] }; \ No newline at end of file diff --git a/components/collapse.tsx b/components/collapse.tsx new file mode 100644 index 0000000..7c689e2 --- /dev/null +++ b/components/collapse.tsx @@ -0,0 +1,87 @@ +import React from "react"; + +export default (props:{open:boolean, children:React.JSX.Element|React.JSX.Element[]})=> +{ + const [openGet, openSet] = React.useState(props.open); + const [doneGet, doneSet] = React.useState(true); + const refEl:React.RefObject = React.useRef(null); + const refCollapse:React.RefObject = React.useRef(null); + + React.useEffect(()=> + { + if(refEl.current) + { + refCollapse.current = Collapser(refEl.current, openGet); + } + return ()=> refCollapse.current && refCollapse.current(); + } + , []); + const Handler =()=> + { + openSet((old)=> + { + if(refCollapse.current) + { + doneSet(false); + refCollapse.current(!old, 1000, ()=>doneSet(true)); + } + return !old; + }); + }; + + return
+ +
}> + {!(!openGet && doneGet) && props.children} +
+
+}; + +type DoneCallback =(openState:boolean)=>void; +type CollapseControls =(inOpen?:boolean, inMs?:number, inDone?:DoneCallback)=>void; + +export function Collapser(inElement:HTMLElement, initialState = false) +{ + let userDone:DoneCallback = (openState) => {}; + let userMode = initialState; + let frameRequest = 0; + + const done = (inEvent:TransitionEvent)=> + { + if (inEvent.propertyName == "height" && inEvent.target == inElement) + { + inEvent.stopPropagation(); + if (userMode) + { + inElement.style.height = "auto"; + inElement.style.overflow = "visible"; + } + userDone(userMode); + } + }; + inElement.addEventListener("transitionend", done); + + /** @type Toggler */ + return function(inOpen?:boolean, inMs?:number, inDone?:DoneCallback) + { + cancelAnimationFrame(frameRequest); + + if(arguments.length) + { + userDone = inDone|| ((m)=>{}) as DoneCallback; + userMode = inOpen||!userMode; + inElement.style.height = inElement.clientHeight + "px"; + inElement.style.overflow = "hidden"; + inElement.style.transition = "none"; + frameRequest = requestAnimationFrame(()=> + { + inElement.style.height = `${inOpen ? inElement.scrollHeight : 0}px`; + inElement.style.transition = `height ${(inMs||1000) / 1000}s`; + }); + } + else + { + inElement.removeEventListener("transitionend", done); + } + } as CollapseControls; +} \ No newline at end of file diff --git a/deep/component.tsx b/deep/component.tsx index 39f4ed4..8e175be 100644 --- a/deep/component.tsx +++ b/deep/component.tsx @@ -9,11 +9,8 @@ export default ()=> type CatFact = {fact:string, length:number}|undefined; const [Data, Updating] = Iso.Fetch.Use(`https://catfact.ninja/fact`); - - console.log("component.tsx render!!") - return
- + Component Route is: {routeGet.Path.toString()} a link diff --git a/deno.jsonc b/deno.jsonc index e6c2c3b..02b5134 100644 --- a/deno.jsonc +++ b/deno.jsonc @@ -4,7 +4,8 @@ { "react": "https://esm.sh/stable/preact@10.13.2/compat", "@eno/app": "./app.tsx", - "@eno/iso": "https://gitea.hptrow.me/SethTrowbridge/eno/raw/tag/0.0.2/lib/iso.tsx/" + "@eno/iso": "https://gitea.hptrow.me/SethTrowbridge/eno/raw/tag/0.0.2/lib/iso.tsx/", + "$/": "./components/" }, "tasks": { "dev": "deno run -A --unstable --no-lock app.tsx --port=3000 --dev",