mirror of
https://github.com/rio-labs/rio.git
synced 2026-01-04 20:29:55 -06:00
92 lines
2.9 KiB
TypeScript
92 lines
2.9 KiB
TypeScript
import { componentsById } from "../componentManagement";
|
|
import { ComponentId } from "../dataModels";
|
|
import { ComponentBase, ComponentState, DeltaState } 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<FlowState> {
|
|
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: DeltaState<FlowState>,
|
|
latentComponents: Set<ComponentBase>
|
|
): 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";
|
|
}
|
|
}
|
|
}
|
|
}
|