From 4663698923b9cf30bd57a09358b950cb768b0280 Mon Sep 17 00:00:00 2001 From: Seth Trowbridge Date: Mon, 15 May 2023 11:35:33 -0400 Subject: [PATCH] context started --- app.tsx | 8 ++++++-- components/collapse.tsx | 38 ++++++++++++++++++++++++++++++++++++-- 2 files changed, 42 insertions(+), 4 deletions(-) diff --git a/app.tsx b/app.tsx index 954a309..1b2ba86 100644 --- a/app.tsx +++ b/app.tsx @@ -1,6 +1,6 @@ import React from "react"; import * as Iso from "@eno/iso"; -import Collapse from "$/collapse.tsx"; +import Collapse, {CollapseButton, CollapseGroup} from "$/collapse.tsx"; const Comp = React.lazy(()=>import("./deep/component.tsx")); @@ -20,7 +20,11 @@ export default ()=>

Hello!

- +
+ + + +
diff --git a/components/collapse.tsx b/components/collapse.tsx index 7c689e2..6954538 100644 --- a/components/collapse.tsx +++ b/components/collapse.tsx @@ -37,9 +37,44 @@ export default (props:{open:boolean, children:React.JSX.Element|React.JSX.Elemen }; +export function useAway(inRef:React.Ref, inHandler:(inAway:boolean)=>void) +{ + const handlerRef = React.useRef(inHandler); + handlerRef.current = inHandler; + React.useEffect(()=> + { + const iterate = (element:EventTarget)=>element === inRef.current; + const handler = (event:MouseEvent)=> handlerRef.current( event.composedPath().find(iterate) ? false : true ); + document.body.addEventListener("click", handler); + return ()=> document.body.removeEventListener("click", handler); + } + , []); +} + +type CollapseStateGet = {Done:boolean, Open:boolean, Away:boolean}; +type CollapseStateSet = (args:{Done?:boolean, Open?:boolean, Away?:boolean})=>void; +type CollapseStateBinding = [state:CollapseStateGet, update:CollapseStateSet]; +const CollapseContext = React.createContext([{Done:true, Open:true, Away:false}, (args)=>{}] as CollapseStateBinding); +export const CollapseGroup =({children}:{children:React.JSX.Element|React.JSX.Element[]})=> +{ + const [stateGet, stateSet] = React.useState({Done:true, Open:false, Away:false} as CollapseStateGet); + const setAny:CollapseStateSet =(params)=> stateSet((old)=> ({...old, ...params})); + React.useEffect(()=>{stateGet.Away && setAny({Open:false})}, [stateGet.Away]); + return {children}; +}; + +export const CollapseButton =()=> +{ + const [stateGet, stateSet] = React.useContext(CollapseContext); + const buttonRef:React.Ref = React.useRef(null); + useAway(buttonRef, (Away)=>stateSet({Away})); + return +} + 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) => {}; @@ -61,7 +96,6 @@ export function Collapser(inElement:HTMLElement, initialState = false) }; inElement.addEventListener("transitionend", done); - /** @type Toggler */ return function(inOpen?:boolean, inMs?:number, inDone?:DoneCallback) { cancelAnimationFrame(frameRequest);