import { html } from "htm";
import * as React from "preact";
/** @typedef {({children, classes}:{children:preact.VNode, classes:string|null})=>preact.VNode} BasicElement */
/** @typedef {{Open:boolean, Done:boolean}} Stage*/
/** @typedef {[set:Stage, get:React.StateUpdater]} Binding */
const BranchContext = React.createContext(
/** @type Binding */ ([{ Open: false, Done: true }, (_n) => {}]),
);
/** @type BasicElement */
export const Branch = (props) => {
/** @type Binding */ const stage = React.useState(
/** @type Stage */ ({ Open: false, Done: true }),
);
/** @type Binding */ const stageParent = React.useContext(BranchContext);
React.useEffect(() => {
const [{ Open, Done }, Shut] = stageParent;
if (!Open && Done) {
Shut({ Open: false, Done: true });
}
}, [stageParent]);
return React.createElement(BranchContext.Provider, {
value: stage,
children: props.children,
});
};
/** @type BasicElement */
export const Button = (props) => {
/** @type Binding */
const [stageGet, stageSet] = React.useContext(BranchContext);
const handler = () => {
const value = { Open: !stageGet.Open, Done: false };
stageSet(value);
console.log(value);
};
return html``;
};
/** @type BasicElement */
export const Menu = (props) => {
const [stageGet, stageSet] = React.useContext(BranchContext);
const refElement = React.useRef(null);
React.useEffect(() => {
console.log(`menu should change`, stageGet);
Collapser(refElement.current, () => {
stageSet({ ...stageGet, Done: true });
})(stageGet.Open, stageGet.Open == false && stageGet.Done ? 0 : 600);
}, [stageGet.Open]);
return html`
${props.children}
`;
};
/** @type BasicElement */
export const Collapse = (props) => {
const ref = React.useRef();
const style = { overflow: "visible", height: "auto" };
return html`${props.children}
`;
};
/** @typedef {(inOpen:boolean, inMilliseconds:number)=>void} Toggler */
/** @type {(inElement:HTMLElement, inUserDone:(Open:boolean)=>void)=>Toggler} */
const Collapser = (inElement, inUserDone) => {
const collapse = inElement;
/** @type {(inEvent:TransitionEvent)=>void} */
const done = (inEvent) => {
if (inEvent.propertyName == "height" && inEvent.target == collapse) {
inEvent.stopPropagation();
if (collapse.clientHeight > 0) {
collapse.style.height = "auto";
collapse.style.overflow = "visible";
inUserDone(true);
} else {
inUserDone(false);
}
}
};
/** @type Toggler */
const show = (inOpen, inMs) => {
collapse.removeEventListener("transitionend", done);
collapse.addEventListener("transitionend", done);
collapse.style.height = collapse.clientHeight + "px";
collapse.style.overflow = "hidden";
collapse.style.transition = "none";
requestAnimationFrame(() => {
collapse.style.height = `${inOpen ? collapse.scrollHeight : 0}px`;
collapse.style.transition = `height ${inMs / 1000}s`;
});
};
return show;
};