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

added windowing toy

+192 -4
+4 -4
src/main.ts
··· 1 1 // yeah this is mildly busted so dont get too excited 2 2 3 3 import { Client, ok, simpleFetchHandler, AtpSessionData, CredentialManager } from "@atcute/client"; 4 - import { Body, Button, Column, Container, Image, Input, Label, Modal, Row } from "./domlink.js"; 4 + import { Body, Button, Column, Container, Image, Input, Label, Modal, Row } from "./domlink.ts"; 5 5 import { AppBskyFeedDefs, AppBskyFeedPost } from '@atcute/bluesky'; 6 6 import { CompositeDidDocumentResolver, CompositeHandleResolver, DohJsonHandleResolver, PlcDidDocumentResolver, WebDidDocumentResolver, WellKnownHandleResolver } from "@atcute/identity-resolver"; 7 7 ··· 18 18 web: new WebDidDocumentResolver(), 19 19 }, 20 20 }); 21 - const handler = simpleFetchHandler({service: "https://public.api.zeppelin.social"}); 21 + const handler = simpleFetchHandler({service: "https://api.bsky.app"}); 22 22 const client = new Client({handler}); 23 23 let manager: CredentialManager | undefined; 24 24 const MY_DID = "did:plc:jlplwn5pi4dqrls7i6dx2me7"; ··· 90 90 async function main() { 91 91 const postsColumn = new Column().class("PostsColumn"); 92 92 const mainColumn = new Column().with( 93 - new AccountPanel(client), 94 - new Label("who up skeeting they deck"), 93 + //new AccountPanel(client), 94 + //new Label("who up skeeting they deck"), 95 95 postsColumn 96 96 ); 97 97 Body.add(mainColumn);
+38
src/windowing.ts
··· 1 + import { Button, Container, Body, Node, Row, Column, Image } from "./domlink.ts"; 2 + import { Window } from "./windowing_mod.ts"; 3 + 4 + function webFrame(url: string) { 5 + const frame = document.createElement("iframe"); 6 + frame.src = url; 7 + frame.style.width = "100%"; 8 + frame.style.height = "100%"; 9 + const controls = new Row().with( 10 + "Web Frame Controls:", 11 + new Button("reload", ()=>{frame.contentWindow?.location.reload();}) 12 + ); 13 + 14 + return new Column().with( 15 + controls, 16 + new Node(frame) 17 + ).style((s)=>{ 18 + s.width = "100%"; 19 + s.height = "100%"; 20 + }); 21 + } 22 + const userListWindow = new Window("User List").with(webFrame("./pds.html")); 23 + const issuesWindow = new Window("Tangled Issues").with(webFrame("./issuesearch.html")); 24 + const feedWindow = new Window("My Posts").with(webFrame("./main.html")); 25 + 26 + // Example usage to demonstrate the new Window class 27 + Body.with( 28 + "you know, i really should check if adding elements normally works", 29 + userListWindow, 30 + issuesWindow, 31 + feedWindow, 32 + new Window('"native" window').with( 33 + new Column().with( 34 + "this doesnt have a web frame in it, but it does have a dog", 35 + new Image("./media/dog.jpeg") 36 + ) 37 + ) 38 + );
+106
src/windowing_mod.ts
··· 1 + import { string } from "../out/main.js"; 2 + import { Button, Container, Label, Node } from "./domlink.ts"; 3 + 4 + 5 + class 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 + } 22 + export 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") { 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 + } 39 + override with(...nodes: (Node | string)[]): this { 40 + this.content.with(...nodes); 41 + return this; 42 + } 43 + 44 + get title() { 45 + return (this.titleBar.children[0] as Label).text; 46 + } 47 + set title(newTitle: string) { 48 + (this.titleBar.children[0] as Label).text = newTitle; 49 + } 50 + public closable(can: boolean = true) { 51 + this.titleBar.closable = can; 52 + return this; 53 + } 54 + 55 + private titleGrabHandler(ev: MouseEvent) { 56 + if (ev.button !== 0) return; 57 + 58 + Window.currentlyDragged = this; 59 + this.titleBar.wraps.style.cursor = 'grabbing'; 60 + 61 + const rect = this.wraps.getBoundingClientRect(); 62 + Window.mouseRelX = ev.clientX - rect.left; 63 + Window.mouseRelY = ev.clientY - rect.top; 64 + 65 + ev.preventDefault(); 66 + } 67 + 68 + private static onMouseMove(ev: MouseEvent) { 69 + const draggedWindow = Window.currentlyDragged; 70 + if (draggedWindow) { 71 + const viewportWidth = document.documentElement.clientWidth; 72 + const viewportHeight = document.documentElement.clientHeight; 73 + 74 + const newLeft = ev.clientX - Window.mouseRelX; 75 + const newTop = ev.clientY - Window.mouseRelY; 76 + 77 + const clampedLeft = Math.min(Math.max(0, newLeft), viewportWidth - draggedWindow.wraps.offsetWidth); 78 + const clampedTop = Math.min(Math.max(0, newTop), viewportHeight - draggedWindow.wraps.offsetHeight); 79 + 80 + draggedWindow.wraps.style.left = `${clampedLeft}px`; 81 + draggedWindow.wraps.style.top = `${clampedTop}px`; 82 + } 83 + } 84 + 85 + private static onMouseUp(_ev: MouseEvent) { 86 + if (Window.currentlyDragged) { 87 + Window.currentlyDragged.titleBar.wraps.style.cursor = 'grab'; 88 + Window.currentlyDragged = null; 89 + } 90 + } 91 + 92 + // A single place to initialize global listeners 93 + private static _initialized = false; 94 + private static initializeGlobalListeners() { 95 + if (this._initialized) return; 96 + globalThis.addEventListener("mousemove", this.onMouseMove); 97 + globalThis.addEventListener("mouseup", this.onMouseUp); 98 + this._initialized = true; 99 + } 100 + 101 + // Static initializer block to set up listeners once 102 + static { 103 + this.initializeGlobalListeners(); 104 + } 105 + } 106 +
static/media/dog.jpeg

This is a binary file and will not be displayed.

+3
static/styles/domlink.css
··· 1 + /* fancy separation */ 1 2 @import url("reset.css"); 2 3 @import url("domlink-visual.css"); 3 4 @import url("domlink-functional.css"); 5 + /* modules idk */ 6 + @import url("domlink-windowing.css");
+13
static/windowing.html
··· 1 + <!DOCTYPE html> 2 + <html lang="en"> 3 + <head> 4 + <meta charset="UTF-8"> 5 + <meta name="viewport" content="width=device-width, initial-scale=1.0"> 6 + <title>windowing</title> 7 + <link rel="stylesheet" href="styles/domlink.css"> 8 + </head> 9 + <body> 10 + <noscript>enable js or fukc off</noscript> 11 + <script src="windowing.js" type="module"></script> 12 + </body> 13 + </html>