collapse context reset

This commit is contained in:
Seth Trowbridge 2023-01-24 17:28:17 -05:00
parent 9fc85f1901
commit dc601637a8
2 changed files with 29 additions and 18 deletions

View File

@ -89,16 +89,20 @@ export default () => {
<div class="px-2">
<${PersonForm}/>
<${PersonTable}/>
<${Tree.Branch}>
<${Tree.Button}><//>
<${Tree.Menu}>
<div class=${"p-4"}>
<p>
The method addEventListener() works by adding a function, or an object that implements EventListener, to the list of event listeners for the specified event type on the EventTarget on which it's called. If the function or object is already in the list of event listeners for this target, the function or object is not added a second time.
</p>
</div>
<${Tree.Button}/>
<${Tree.Menu} class="shadow-lg rounded-lg bg-white">
<p>hey</p>
<${Tree.Branch}>
<${Tree.Button} class="p-4 bg-red-500 text-white"/>
<${Tree.Menu}>
<p>sup.</p>
<//>
<//>
<//>
<//>
</div>
</div>`;
};

View File

@ -1,7 +1,7 @@
import { html } from "htm";
import * as React from "preact";
/** @typedef {({children, classes}:{children:preact.VNode, classes:string|null})=>preact.VNode} BasicElement */
/** @typedef {(props:{children:preact.VNode, class:string|null})=>preact.VNode} BasicElement */
/** @typedef {{Open:boolean, Done:boolean}} Stage*/
/** @typedef {[set:Stage, get:React.StateUpdater<Stage>]} Binding */
@ -9,6 +9,8 @@ const BranchContext = React.createContext(
/** @type Binding */ ([{ Open: false, Done: true }, (_n) => {}]),
);
export { BranchContext as Context };
/** @type BasicElement */
export const Branch = (props) => {
/** @type Binding */ const stage = React.useState(
@ -17,7 +19,8 @@ export const Branch = (props) => {
/** @type Binding */ const stageParent = React.useContext(BranchContext);
React.useEffect(() => {
const [{ Open, Done }, Shut] = stageParent;
const [{ Open, Done }] = stageParent;
const [, Shut] = stage;
if (!Open && Done) {
Shut({ Open: false, Done: true });
}
@ -40,7 +43,7 @@ export const Button = (props) => {
console.log(value);
};
return html`<button onClick=${handler} class=${props.classes}>stage: ${
return html`<button onClick=${handler} class=${props.class}>stage: ${
JSON.stringify(stageGet)
}
${props.children}
@ -51,22 +54,25 @@ export const Button = (props) => {
export const Menu = (props) => {
const [stageGet, stageSet] = React.useContext(BranchContext);
const refElement = React.useRef(null);
/** @type {React.MutableRefObject<null|Toggler>} */
const refCollapser = React.useRef(null);
React.useEffect(() => {
refCollapser.current = Collapser(refElement.current);
refElement.current &&
(refCollapser.current = Collapser(refElement.current));
}, []);
React.useEffect(() => {
refCollapser.current(
const instant = stageGet.Open == false && stageGet.Done;
refCollapser.current && refCollapser.current(
stageGet.Open,
stageGet.Open == false && stageGet.Done ? 0 : 600,
instant ? 0 : 600,
() => stageSet({ ...stageGet, Done: true }),
);
}, [stageGet.Open]);
return html`
<div ref=${refElement} class=${props.classes}>
<div ref=${refElement} class=${props.class}>
${props.children}
</div>
`;
@ -74,18 +80,18 @@ export const Menu = (props) => {
/** @typedef {(Open:boolean)=>void} UserDone */
/** @typedef {(inOpen:boolean, inMilliseconds:number, inUserDone:UserDone)=>void} Toggler */
/** @type {(inElement:HTMLElement)=>Toggler} */
/** @typedef {(inElement:HTMLElement)=>Toggler} Collapse */
/** @type Collapse */
const Collapser = (inElement) => {
console.log("Collapser initialized");
/** @type UserDone */
let userDone = () => {};
let userMode = false;
const collapse = inElement;
/** @type {(inEvent:TransitionEvent)=>void} */
const done = (inEvent) => {
if (inEvent.propertyName == "height" && inEvent.target == collapse) {
inEvent.stopPropagation();
if (collapse.clientHeight > 0) {
if (userMode) {
collapse.style.height = "auto";
collapse.style.overflow = "visible";
userDone(true);
@ -96,6 +102,7 @@ const Collapser = (inElement) => {
};
/** @type Toggler */
const show = (inOpen, inMs, inDone) => {
userMode = inOpen;
collapse.removeEventListener("transitionend", done);
userDone = inDone;
collapse.addEventListener("transitionend", done);