[READ-ONLY] Mirror of https://github.com/bombshell-dev/tty. Platform independent 2D layout engine for terminal applications based on Clay
5

Configure Feed

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

test: failing repro for signed-margin

Nate Moore (Jun 4, 2026, 12:32 AM -0500) cdf98eaa d75fb4b6

+79
+79
test/signed-margin.test.ts
··· 1 + import { describe, expect, it } from "./suite.ts"; 2 + import { createTerm } from "../term.ts"; 3 + import { close, fixed, grow, open, type OpenElement, text } from "../ops.ts"; 4 + 5 + import { print } from "./print.ts"; 6 + 7 + const decode = (b: Uint8Array) => new TextDecoder().decode(b); 8 + 9 + // Proposed (not-yet-implemented) signed offset prop. Cast through this so the 10 + // ops still type-check while `margin` is silently ignored by the current build. 11 + type Margin = { left?: number; right?: number; top?: number; bottom?: number }; 12 + const withMargin = ( 13 + layout: NonNullable<OpenElement["layout"]>, 14 + margin: Margin, 15 + ): NonNullable<OpenElement["layout"]> => 16 + ({ ...layout, margin }) as NonNullable<OpenElement["layout"]>; 17 + 18 + describe("layout margin (signed offset)", () => { 19 + it("positive marginLeft shifts the box origin without shrinking content", async () => { 20 + let term = await createTerm({ width: 20, height: 4 }); 21 + let r = term.render([ 22 + open("root", { 23 + layout: { width: grow(), height: grow(), direction: "ttb" }, 24 + }), 25 + open("box", { 26 + layout: withMargin({ width: fixed(8), direction: "ttb" }, { left: 2 }), 27 + }), 28 + text("Hello W"), 29 + close(), 30 + close(), 31 + ]); 32 + // pins: box origin moves right by 2 cells (margin offsets position, not content) 33 + expect(r.info.get("box")!.bounds.x).toBe(2); 34 + // pins: full 7-cell text still fits on ONE line (margin must not consume width) 35 + expect(r.info.get("box")!.bounds.height).toBe(1); 36 + }); 37 + 38 + it("negative marginLeft pulls the box before the parent origin and clips", async () => { 39 + let term = await createTerm({ width: 20, height: 4 }); 40 + let r = term.render([ 41 + open("root", { 42 + layout: { width: fixed(6), height: grow(), direction: "ttb" }, 43 + clip: { horizontal: true }, 44 + }), 45 + open("box", { 46 + layout: withMargin( 47 + { width: fixed(12), direction: "ttb" }, 48 + { left: -3 }, 49 + ), 50 + }), 51 + text("Hello World"), 52 + close(), 53 + close(), 54 + ]); 55 + let first = print(decode(r.output), 20, 4).split("\n")[0]; 56 + // pins: leftmost 3 cells fall outside the parent and are clipped away 57 + expect(first.slice(0, 6)).toBe("lo Wor"); 58 + }); 59 + 60 + it("negative margin keeps box geometry sane (no unsigned overflow)", async () => { 61 + let term = await createTerm({ width: 20, height: 6 }); 62 + let r = term.render([ 63 + open("root", { 64 + layout: { width: grow(), height: grow(), direction: "ttb" }, 65 + }), 66 + open("box", { 67 + layout: withMargin( 68 + { width: fixed(11), direction: "ttb" }, 69 + { left: -3 }, 70 + ), 71 + }), 72 + text("Hello World"), 73 + close(), 74 + close(), 75 + ]); 76 + // pins: the box origin is pulled left by 3 cells (negative offset is signed) 77 + expect(r.info.get("box")!.bounds.x).toBe(-3); 78 + }); 79 + });