start collapse

This commit is contained in:
Seth Trowbridge 2023-05-15 07:26:18 -04:00
parent b337c72331
commit 608e482469
4 changed files with 117 additions and 14 deletions

36
app.tsx
View File

@ -1,22 +1,27 @@
import React from "react"; import React from "react";
import * as Iso from "@eno/iso"; import * as Iso from "@eno/iso";
import Collapse from "$/collapse.tsx";
const Comp = React.lazy(()=>import("./deep/component.tsx")); const Comp = React.lazy(()=>import("./deep/component.tsx"));
export default ()=> export default ()=>
{ {
const [countGet, countSet] = React.useState(1); const [countGet, countSet] = React.useState(1);
return <div class="p-4 font-sans"> return <div class="font-sans flex flex-col items-center min-h-[100vh]">
<Iso.Meta.Metas title="Main Page!"/> <Iso.Meta.Metas title="Main Page!"/>
<header class="max-w-4xl mx-auto"> <header class="layout-middle border-b">
<nav class="p-4 flex gap-8 border-b font-black text-sm"> <nav class="flex gap-8 font-black text-sm">
<a class="" href="/">Home</a> <a class="" href="/">Home</a>
<a href="/about">About</a> <a href="/about">About</a>
<a href="/details">Details</a> <a href="/details">Details</a>
<a href="/data">Data Fetching</a>
</nav> </nav>
<Collapse open={false}>
<p>Hello!</p>
</Collapse>
</header> </header>
<main class="max-w-4xl mx-auto p-4"> <main class="layout-middle">
<Iso.Switch> <Iso.Switch>
<Iso.Case value="/"> <Iso.Case value="/">
<> <>
@ -38,7 +43,7 @@ export default ()=>
</> </>
</Iso.Case> </Iso.Case>
<Iso.Case value="details"> <Iso.Case value="details">
<> <div class="flex flex-col gap-y-2">
<h1>Details</h1> <h1>Details</h1>
<p> <p>
Iso uses Preact/Compat and Twind in lieu of React and Tailwind so you can keep the API's you know, serve less kilobytes, and gain new ways to simplify your layout code. Iso uses Preact/Compat and Twind in lieu of React and Tailwind so you can keep the API's you know, serve less kilobytes, and gain new ways to simplify your layout code.
@ -59,16 +64,29 @@ export default ()=>
<li>Use file extensions in import statements</li> <li>Use file extensions in import statements</li>
<li>Add new modules to the deno.jsonc config</li> <li>Add new modules to the deno.jsonc config</li>
</ol> </ol>
</> </div>
</Iso.Case>
<Iso.Case value="data">
<React.Suspense fallback={<p>Loading...</p>}>
<Comp/>
</React.Suspense>
</Iso.Case> </Iso.Case>
<Iso.Case value="lol/idk">lol/idk</Iso.Case>
<Iso.Case default><p>404!</p></Iso.Case> <Iso.Case default><p>404!</p></Iso.Case>
</Iso.Switch> </Iso.Switch>
</main> </main>
<footer> <footer class="bg-black grow w-full">
footer <div class="layout-middle mx-auto text-white">
&copy; {new Date().getFullYear()} Seth Trowbridge
</div>
</footer> </footer>
</div>; </div>;
}; };
export const CSS = {
rules:
[
["layout-middle", "w-full max-w-4xl p-4"]
]
};

87
components/collapse.tsx Normal file
View File

@ -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<HTMLElement> = React.useRef(null);
const refCollapse:React.RefObject<CollapseControls> = 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 <div>
<button onClick={Handler}>{openGet ? "Close this" : "Open it"}{doneGet ? "." : "..."}</button>
<div ref={refEl as React.RefObject<HTMLDivElement>}>
{!(!openGet && doneGet) && props.children}
</div>
</div>
};
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;
}

View File

@ -9,11 +9,8 @@ export default ()=>
type CatFact = {fact:string, length:number}|undefined; type CatFact = {fact:string, length:number}|undefined;
const [Data, Updating] = Iso.Fetch.Use(`https://catfact.ninja/fact`); const [Data, Updating] = Iso.Fetch.Use(`https://catfact.ninja/fact`);
console.log("component.tsx render!!")
return <div class="p-4 text-red-500"> return <div class="p-4 text-red-500">
<Iso.Meta.Metas title="Component!"/> <Iso.Meta.Metas title="Cat Fact!"/>
Component Route is: {routeGet.Path.toString()} Component Route is: {routeGet.Path.toString()}
<button className="p-4 bg-green-500 text-white" onClick={e=>{countSet(countGet+1); routeSet(["lol", "idk"], {count:countGet+1});}}>{countGet}</button> <button className="p-4 bg-green-500 text-white" onClick={e=>{countSet(countGet+1); routeSet(["lol", "idk"], {count:countGet+1});}}>{countGet}</button>
<a href="/page/about-us" className="p-2 text(lg blue-500) font-bold">a link</a> <a href="/page/about-us" className="p-2 text(lg blue-500) font-bold">a link</a>

View File

@ -4,7 +4,8 @@
{ {
"react": "https://esm.sh/stable/preact@10.13.2/compat", "react": "https://esm.sh/stable/preact@10.13.2/compat",
"@eno/app": "./app.tsx", "@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": { "tasks": {
"dev": "deno run -A --unstable --no-lock app.tsx --port=3000 --dev", "dev": "deno run -A --unstable --no-lock app.tsx --port=3000 --dev",