https://domlink.deployments.hotsocket.fyi/
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at work 116 lines 3.5 kB view raw
1import { string } from "../out/main.js"; 2import { Button, Container, Label, Node } from "./domlink.ts"; 3 4 5class TitleBar extends Container { 6 label: Label; 7 closeButton: Button; 8 constructor(title: string, closeCallback: EventListener) { 9 super(); 10 this.class("LWindowHandle"); 11 this.label = new Label(title); 12 this.closeButton = new Button("x", closeCallback); 13 this.with(this.label,this.closeButton); 14 } 15 get closable(): boolean { 16 return this.closeButton.wraps.style.display != "none"; 17 } 18 set closable(x: boolean) { 19 this.closeButton.wraps.style.display = x ? "inline-block" : "none"; 20 } 21} 22export class Window extends Container { 23 private static currentlyDragged: Window | null = null; 24 private static mouseRelX = 0; 25 private static mouseRelY = 0; 26 private static zIndexCounter = 100; 27 titleBar: TitleBar; 28 content = new Container().class("LWindowContent"); 29 30 constructor(title: string = "New Window", height: number = 300, width: number = 400) { 31 super(); 32 this.class("LWindow"); 33 this.titleBar = new TitleBar(title, ()=>{this.wraps.remove();}); 34 this.add(this.titleBar); 35 this.titleBar.wraps.addEventListener("mousedown", this.titleGrabHandler.bind(this)); 36 this.wraps.addEventListener("mousedown", ()=>{this.wraps.style.zIndex = `${Window.zIndexCounter++}`;}); 37 this.add(this.content); 38 this.style((s)=>{ 39 s.width = `${width}px`; 40 s.height = `${height}px`; 41 s.top = "0px"; 42 s.left = "0px"; 43 }); 44 } 45 override with(...nodes: (Node | string)[]): this { 46 const w = this.wraps.style.width; 47 const h = this.wraps.style.height; 48 this.content.with(...nodes); 49 this.wraps.style.width = w; 50 this.wraps.style.height = h; 51 return this; 52 } 53 54 get title() { 55 return (this.titleBar.children[0] as Label).text; 56 } 57 set title(newTitle: string) { 58 (this.titleBar.children[0] as Label).text = newTitle; 59 } 60 public closable(can: boolean = true) { 61 this.titleBar.closable = can; 62 return this; 63 } 64 65 private titleGrabHandler(ev: MouseEvent) { 66 if (ev.button !== 0) return; 67 68 Window.currentlyDragged = this; 69 this.titleBar.wraps.style.cursor = 'grabbing'; 70 71 const rect = this.wraps.getBoundingClientRect(); 72 Window.mouseRelX = ev.clientX - rect.left; 73 Window.mouseRelY = ev.clientY - rect.top; 74 75 ev.preventDefault(); 76 } 77 78 private static onMouseMove(ev: MouseEvent) { 79 const draggedWindow = Window.currentlyDragged; 80 if (draggedWindow) { 81 const viewportWidth = document.documentElement.clientWidth; 82 const viewportHeight = document.documentElement.clientHeight; 83 84 const newLeft = ev.clientX - Window.mouseRelX; 85 const newTop = ev.clientY - Window.mouseRelY; 86 87 const clampedLeft = Math.min(Math.max(0, newLeft), viewportWidth - draggedWindow.wraps.offsetWidth); 88 const clampedTop = Math.min(Math.max(0, newTop), viewportHeight - draggedWindow.wraps.offsetHeight); 89 90 draggedWindow.wraps.style.left = `${clampedLeft}px`; 91 draggedWindow.wraps.style.top = `${clampedTop}px`; 92 } 93 } 94 95 private static onMouseUp(_ev: MouseEvent) { 96 if (Window.currentlyDragged) { 97 Window.currentlyDragged.titleBar.wraps.style.cursor = 'grab'; 98 Window.currentlyDragged = null; 99 } 100 } 101 102 // A single place to initialize global listeners 103 private static _initialized = false; 104 private static initializeGlobalListeners() { 105 if (this._initialized) return; 106 globalThis.addEventListener("mousemove", this.onMouseMove); 107 globalThis.addEventListener("mouseup", this.onMouseUp); 108 this._initialized = true; 109 } 110 111 // Static initializer block to set up listeners once 112 static { 113 this.initializeGlobalListeners(); 114 } 115} 116