{"version":3,"file":"bordered-box.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/bordered-box.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAgB,MAAM,wBAAwB,CAAC;AAStE;;GAEG;AACH,qBAAa,WAAY,YAAW,SAAS;IAC5C,QAAQ,EAAE,SAAS,EAAE,CAAM;IAC3B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,aAAa,CAA2B;IAGhD,OAAO,CAAC,KAAK,CAAC,CAAc;IAE5B,YAAY,QAAQ,SAAI,EAAE,QAAQ,SAAI,EAAE,aAAa,GAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAqB,EAI7F;IAED,QAAQ,CAAC,SAAS,EAAE,SAAS,GAAG,IAAI,CAGnC;IAED,WAAW,CAAC,SAAS,EAAE,SAAS,GAAG,IAAI,CAMtC;IAED,KAAK,IAAI,IAAI,CAGZ;IAED,gBAAgB,CAAC,aAAa,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAG9D;IAED,OAAO,CAAC,eAAe;IAIvB,OAAO,CAAC,UAAU;IAWlB,UAAU,IAAI,IAAI,CAKjB;IAED,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CA6D9B;CACD","sourcesContent":["import { type Component, visibleWidth } from \"@apholdings/jensen-tui\";\n\ntype RenderCache = {\n\tchildLines: string[];\n\twidth: number;\n\tborderColorSample: string | undefined;\n\tlines: string[];\n};\n\n/**\n * BorderedBox component - a container that applies a rounded border and padding to all children\n */\nexport class BorderedBox implements Component {\n\tchildren: Component[] = [];\n\tprivate paddingX: number;\n\tprivate paddingY: number;\n\tprivate borderColorFn: (text: string) => string;\n\n\t// Cache for rendered output\n\tprivate cache?: RenderCache;\n\n\tconstructor(paddingX = 1, paddingY = 0, borderColorFn: (text: string) => string = (str) => str) {\n\t\tthis.paddingX = paddingX;\n\t\tthis.paddingY = paddingY;\n\t\tthis.borderColorFn = borderColorFn;\n\t}\n\n\taddChild(component: Component): void {\n\t\tthis.children.push(component);\n\t\tthis.invalidateCache();\n\t}\n\n\tremoveChild(component: Component): void {\n\t\tconst index = this.children.indexOf(component);\n\t\tif (index !== -1) {\n\t\t\tthis.children.splice(index, 1);\n\t\t\tthis.invalidateCache();\n\t\t}\n\t}\n\n\tclear(): void {\n\t\tthis.children = [];\n\t\tthis.invalidateCache();\n\t}\n\n\tsetBorderColorFn(borderColorFn: (text: string) => string): void {\n\t\tthis.borderColorFn = borderColorFn;\n\t\t// Don't invalidate here - we'll detect changes by sampling output\n\t}\n\n\tprivate invalidateCache(): void {\n\t\tthis.cache = undefined;\n\t}\n\n\tprivate matchCache(width: number, childLines: string[], borderColorSample: string | undefined): boolean {\n\t\tconst cache = this.cache;\n\t\treturn (\n\t\t\t!!cache &&\n\t\t\tcache.width === width &&\n\t\t\tcache.borderColorSample === borderColorSample &&\n\t\t\tcache.childLines.length === childLines.length &&\n\t\t\tcache.childLines.every((line, i) => line === childLines[i])\n\t\t);\n\t}\n\n\tinvalidate(): void {\n\t\tthis.invalidateCache();\n\t\tfor (const child of this.children) {\n\t\t\tchild.invalidate?.();\n\t\t}\n\t}\n\n\trender(width: number): string[] {\n\t\tif (this.children.length === 0) {\n\t\t\treturn [];\n\t\t}\n\n\t\t// Calculate available width for content\n\t\t// Border takes 1 char on each side + paddingX\n\t\tconst contentWidth = Math.max(1, width - 2 - this.paddingX * 2);\n\n\t\t// Render all children\n\t\tconst childLines: string[] = [];\n\t\tfor (const child of this.children) {\n\t\t\tchildLines.push(...child.render(contentWidth));\n\t\t}\n\n\t\tif (childLines.length === 0) {\n\t\t\treturn [];\n\t\t}\n\n\t\t// Check if borderColorFn output changed by sampling\n\t\tconst borderColorSample = this.borderColorFn(\"test\");\n\n\t\t// Check cache validity\n\t\tif (this.matchCache(width, childLines, borderColorSample)) {\n\t\t\treturn this.cache!.lines;\n\t\t}\n\n\t\tconst result: string[] = [];\n\t\tconst c = this.borderColorFn;\n\n\t\t// Top border: ╭─...─╮\n\t\tconst horizontalBorder = \"─\".repeat(Math.max(0, width - 2));\n\t\tresult.push(c(`╭${horizontalBorder}╮`));\n\n\t\t// Top padding\n\t\tconst emptyMiddle = \" \".repeat(Math.max(0, width - 2));\n\t\tfor (let i = 0; i < this.paddingY; i++) {\n\t\t\tresult.push(c(\"│\") + emptyMiddle + c(\"│\"));\n\t\t}\n\n\t\t// Content\n\t\tconst leftPad = \" \".repeat(this.paddingX);\n\t\tconst rightPad = \" \".repeat(this.paddingX);\n\t\tfor (const line of childLines) {\n\t\t\tconst visLen = visibleWidth(line);\n\t\t\tconst extraPad = Math.max(0, contentWidth - visLen);\n\t\t\tresult.push(c(\"│\") + leftPad + line + \" \".repeat(extraPad) + rightPad + c(\"│\"));\n\t\t}\n\n\t\t// Bottom padding\n\t\tfor (let i = 0; i < this.paddingY; i++) {\n\t\t\tresult.push(c(\"│\") + emptyMiddle + c(\"│\"));\n\t\t}\n\n\t\t// Bottom border: ╰─...─╯\n\t\tresult.push(c(`╰${horizontalBorder}╯`));\n\n\t\t// Update cache\n\t\tthis.cache = { childLines, width, borderColorSample, lines: result };\n\n\t\treturn result;\n\t}\n}\n"]}