Initial move

This commit is contained in:
2024-09-03 14:50:33 +02:00
parent adb6be0006
commit 9fa656ed5e
138 changed files with 13117 additions and 0 deletions

102
frontend/src/ui/tab-bar.ts Normal file
View File

@@ -0,0 +1,102 @@
import { UINode } from "./node";
import { UITab } from "./tab";
export class TabBar extends UINode {
private tabs: UITab[];
private tabBarContainer: HTMLDivElement;
private onTabChangeCallback?: (index: number) => void;
private focused: number;
public constructor(title: string = "tab bar") {
super(title);
this.tabs = [];
this.tabBarContainer = document.createElement("div");
this.tabBarContainer.setAttribute("role", "tablist");
this.tabBarContainer.style.display = "flex";
this.tabBarContainer.style.alignItems = "center";
// this.tabBarContainer.style.justifyContent = "space-between";
this.tabBarContainer.style.overflow = "hidden";
this.element.appendChild(this.tabBarContainer);
this.focused = 0;
}
public _onFocus() {
this.tabs[this.focused].focus();
return this;
}
public focus() {
this.tabs[this.focused].focus();
return this;
}
public add(title: string) {
const idx = this.tabs.length;
const elem = new UITab(title);
elem.onClick(() => {
this.selectTab(idx);
});
this.tabs.push(elem);
this.tabBarContainer.appendChild(elem.render());
elem._onConnect();
if (this.tabs.length === 1) this.calculateTabIndex();
return this;
}
public onTabChange(f: (index: number) => void) {
this.onTabChangeCallback = f;
return this;
}
private selectTab(idx: number) {
if (idx !== this.focused) {
this.tabs[this.focused].setTabbable(false);
this.focused = idx;
}
if (!this.onTabChangeCallback) return;
this.onTabChangeCallback(idx);
this.tabs[idx].setTabbable(true);
this.tabs[idx].focus();
this.updateView();
}
public _onKeydown(key: string): boolean {
switch (key) {
case "ArrowLeft":
this.tabs[this.focused].setTabbable(false);
this.focused = Math.max(0, this.focused - 1);
this.tabs[this.focused].setTabbable(true);
this.selectTab(this.focused);
return true;
break;
case "ArrowRight":
this.tabs[this.focused].setTabbable(false);
this.focused = Math.min(this.tabs.length - 1, this.focused + 1);
this.tabs[this.focused].setTabbable(true);
this.selectTab(this.focused);
return true;
break;
default:
return false;
break;
}
return false;
}
private updateView() {
for (let i = 0; i < this.tabs.length; i++) {
this.tabs[i].setSelected(i === this.focused);
}
}
public getElement(): HTMLElement {
return this.element;
}
public calculateTabIndex() {
this.tabs[this.focused].setTabbable(true);
return this;
}
}