import { componentsById } from "../componentManagement"; import { ComponentId } from "../dataModels"; import { ComponentBase, ComponentState } from "./componentBase"; export type FlowState = ComponentState & { _type_: "FlowContainer-builtin"; children?: ComponentId[]; row_spacing?: number; column_spacing?: number; justify?: "left" | "center" | "right" | "justify" | "grow"; }; export class FlowComponent extends ComponentBase { state: Required; private innerElement: HTMLElement; createElement(): HTMLElement { let element = document.createElement("div"); element.classList.add("rio-flow-container"); this.innerElement = document.createElement("div"); this.innerElement.classList.add("rio-flow-inner"); element.appendChild(this.innerElement); return element; } updateElement( deltaState: FlowState, latentComponents: Set ): void { super.updateElement(deltaState, latentComponents); if (deltaState.row_spacing !== undefined) { this.innerElement.style.rowGap = `${deltaState.row_spacing}rem`; } if (deltaState.column_spacing !== undefined) { this.innerElement.style.columnGap = `${deltaState.column_spacing}rem`; } if (deltaState.justify !== undefined) { this.innerElement.style.justifyContent = { left: "start", right: "end", center: "center", justify: "space-between", grow: "stretch", }[deltaState.justify]; } if (deltaState.children !== undefined) { this.replaceChildren( latentComponents, deltaState.children, this.innerElement, true ); this.updateChildGrows( deltaState.children, deltaState.justify ?? this.state.justify ); } } onChildGrowChanged(): void { this.updateChildGrows(this.state.children, this.state.justify); } private updateChildGrows(children: ComponentId[], justify: string): void { // Set the children's `flex-grow` let hasGrowers = false; for (let [index, childId] of children.entries()) { let childComponent = componentsById[childId]!; let childWrapper = this.innerElement.children[index] as HTMLElement; if (childComponent.state._grow_[0]) { hasGrowers = true; childWrapper.style.flexGrow = "1"; } else { childWrapper.style.flexGrow = "0"; } } // If nobody wants to grow, all of them do if (justify === "grow" && !hasGrowers) { for (let childWrapper of this.innerElement.children) { (childWrapper as HTMLElement).style.flexGrow = "1"; } } } }