@effect-tui/react 0.1.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (277) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +138 -0
  3. package/dist/jsx-dev-runtime.d.ts +3 -0
  4. package/dist/jsx-dev-runtime.d.ts.map +1 -0
  5. package/dist/jsx-dev-runtime.js +3 -0
  6. package/dist/jsx-dev-runtime.js.map +1 -0
  7. package/dist/jsx-runtime.d.ts +47 -0
  8. package/dist/jsx-runtime.d.ts.map +1 -0
  9. package/dist/jsx-runtime.js +6 -0
  10. package/dist/jsx-runtime.js.map +1 -0
  11. package/dist/src/codeblock.d.ts +9 -0
  12. package/dist/src/codeblock.d.ts.map +1 -0
  13. package/dist/src/codeblock.js +24 -0
  14. package/dist/src/codeblock.js.map +1 -0
  15. package/dist/src/constants.d.ts +3 -0
  16. package/dist/src/constants.d.ts.map +1 -0
  17. package/dist/src/constants.js +3 -0
  18. package/dist/src/constants.js.map +1 -0
  19. package/dist/src/debug/DiagnosticsPanel.d.ts +7 -0
  20. package/dist/src/debug/DiagnosticsPanel.d.ts.map +1 -0
  21. package/dist/src/debug/DiagnosticsPanel.js +13 -0
  22. package/dist/src/debug/DiagnosticsPanel.js.map +1 -0
  23. package/dist/src/highlight.d.ts +20 -0
  24. package/dist/src/highlight.d.ts.map +1 -0
  25. package/dist/src/highlight.js +51 -0
  26. package/dist/src/highlight.js.map +1 -0
  27. package/dist/src/hooks/index.d.ts +4 -0
  28. package/dist/src/hooks/index.d.ts.map +1 -0
  29. package/dist/src/hooks/index.js +3 -0
  30. package/dist/src/hooks/index.js.map +1 -0
  31. package/dist/src/hooks/use-keyboard.d.ts +18 -0
  32. package/dist/src/hooks/use-keyboard.d.ts.map +1 -0
  33. package/dist/src/hooks/use-keyboard.js +26 -0
  34. package/dist/src/hooks/use-keyboard.js.map +1 -0
  35. package/dist/src/hooks/use-paste.d.ts +5 -0
  36. package/dist/src/hooks/use-paste.d.ts.map +1 -0
  37. package/dist/src/hooks/use-paste.js +14 -0
  38. package/dist/src/hooks/use-paste.js.map +1 -0
  39. package/dist/src/hooks/useFrameStats.d.ts +7 -0
  40. package/dist/src/hooks/useFrameStats.d.ts.map +1 -0
  41. package/dist/src/hooks/useFrameStats.js +28 -0
  42. package/dist/src/hooks/useFrameStats.js.map +1 -0
  43. package/dist/src/hosts/base.d.ts +22 -0
  44. package/dist/src/hosts/base.d.ts.map +1 -0
  45. package/dist/src/hosts/base.js +53 -0
  46. package/dist/src/hosts/base.js.map +1 -0
  47. package/dist/src/hosts/box.d.ts +26 -0
  48. package/dist/src/hosts/box.d.ts.map +1 -0
  49. package/dist/src/hosts/box.js +84 -0
  50. package/dist/src/hosts/box.js.map +1 -0
  51. package/dist/src/hosts/canvas.d.ts +48 -0
  52. package/dist/src/hosts/canvas.d.ts.map +1 -0
  53. package/dist/src/hosts/canvas.js +109 -0
  54. package/dist/src/hosts/canvas.js.map +1 -0
  55. package/dist/src/hosts/codeblock.d.ts +32 -0
  56. package/dist/src/hosts/codeblock.d.ts.map +1 -0
  57. package/dist/src/hosts/codeblock.js +118 -0
  58. package/dist/src/hosts/codeblock.js.map +1 -0
  59. package/dist/src/hosts/hstack.d.ts +18 -0
  60. package/dist/src/hosts/hstack.d.ts.map +1 -0
  61. package/dist/src/hosts/hstack.js +45 -0
  62. package/dist/src/hosts/hstack.js.map +1 -0
  63. package/dist/src/hosts/index.d.ts +16 -0
  64. package/dist/src/hosts/index.d.ts.map +1 -0
  65. package/dist/src/hosts/index.js +40 -0
  66. package/dist/src/hosts/index.js.map +1 -0
  67. package/dist/src/hosts/spacer.d.ts +19 -0
  68. package/dist/src/hosts/spacer.d.ts.map +1 -0
  69. package/dist/src/hosts/spacer.js +28 -0
  70. package/dist/src/hosts/spacer.js.map +1 -0
  71. package/dist/src/hosts/text.d.ts +43 -0
  72. package/dist/src/hosts/text.d.ts.map +1 -0
  73. package/dist/src/hosts/text.js +148 -0
  74. package/dist/src/hosts/text.js.map +1 -0
  75. package/dist/src/hosts/vstack.d.ts +18 -0
  76. package/dist/src/hosts/vstack.d.ts.map +1 -0
  77. package/dist/src/hosts/vstack.js +45 -0
  78. package/dist/src/hosts/vstack.js.map +1 -0
  79. package/dist/src/hosts/zstack.d.ts +20 -0
  80. package/dist/src/hosts/zstack.d.ts.map +1 -0
  81. package/dist/src/hosts/zstack.js +65 -0
  82. package/dist/src/hosts/zstack.js.map +1 -0
  83. package/dist/src/index.d.ts +20 -0
  84. package/dist/src/index.d.ts.map +1 -0
  85. package/dist/src/index.js +20 -0
  86. package/dist/src/index.js.map +1 -0
  87. package/dist/src/inline/index.d.ts +32 -0
  88. package/dist/src/inline/index.d.ts.map +1 -0
  89. package/dist/src/inline/index.js +111 -0
  90. package/dist/src/inline/index.js.map +1 -0
  91. package/dist/src/jsx.d.ts +2 -0
  92. package/dist/src/jsx.d.ts.map +1 -0
  93. package/dist/src/jsx.js +4 -0
  94. package/dist/src/jsx.js.map +1 -0
  95. package/dist/src/motion/color-motion-value.d.ts +32 -0
  96. package/dist/src/motion/color-motion-value.d.ts.map +1 -0
  97. package/dist/src/motion/color-motion-value.js +80 -0
  98. package/dist/src/motion/color-motion-value.js.map +1 -0
  99. package/dist/src/motion/color.d.ts +30 -0
  100. package/dist/src/motion/color.d.ts.map +1 -0
  101. package/dist/src/motion/color.js +172 -0
  102. package/dist/src/motion/color.js.map +1 -0
  103. package/dist/src/motion/color.test.d.ts +2 -0
  104. package/dist/src/motion/color.test.d.ts.map +1 -0
  105. package/dist/src/motion/color.test.js +97 -0
  106. package/dist/src/motion/color.test.js.map +1 -0
  107. package/dist/src/motion/event-emitter.d.ts +18 -0
  108. package/dist/src/motion/event-emitter.d.ts.map +1 -0
  109. package/dist/src/motion/event-emitter.js +30 -0
  110. package/dist/src/motion/event-emitter.js.map +1 -0
  111. package/dist/src/motion/frame.d.ts +9 -0
  112. package/dist/src/motion/frame.d.ts.map +1 -0
  113. package/dist/src/motion/frame.js +51 -0
  114. package/dist/src/motion/frame.js.map +1 -0
  115. package/dist/src/motion/hooks.d.ts +75 -0
  116. package/dist/src/motion/hooks.d.ts.map +1 -0
  117. package/dist/src/motion/hooks.js +190 -0
  118. package/dist/src/motion/hooks.js.map +1 -0
  119. package/dist/src/motion/index.d.ts +4 -0
  120. package/dist/src/motion/index.d.ts.map +1 -0
  121. package/dist/src/motion/index.js +7 -0
  122. package/dist/src/motion/index.js.map +1 -0
  123. package/dist/src/motion/motion-value.d.ts +40 -0
  124. package/dist/src/motion/motion-value.d.ts.map +1 -0
  125. package/dist/src/motion/motion-value.js +109 -0
  126. package/dist/src/motion/motion-value.js.map +1 -0
  127. package/dist/src/motion/motion-value.test.d.ts +2 -0
  128. package/dist/src/motion/motion-value.test.d.ts.map +1 -0
  129. package/dist/src/motion/motion-value.test.js +177 -0
  130. package/dist/src/motion/motion-value.test.js.map +1 -0
  131. package/dist/src/motion/spring-math.d.ts +28 -0
  132. package/dist/src/motion/spring-math.d.ts.map +1 -0
  133. package/dist/src/motion/spring-math.js +81 -0
  134. package/dist/src/motion/spring-math.js.map +1 -0
  135. package/dist/src/motion/types.d.ts +25 -0
  136. package/dist/src/motion/types.d.ts.map +1 -0
  137. package/dist/src/motion/types.js +13 -0
  138. package/dist/src/motion/types.js.map +1 -0
  139. package/dist/src/output.d.ts +47 -0
  140. package/dist/src/output.d.ts.map +1 -0
  141. package/dist/src/output.js +125 -0
  142. package/dist/src/output.js.map +1 -0
  143. package/dist/src/profiler.d.ts +6 -0
  144. package/dist/src/profiler.d.ts.map +1 -0
  145. package/dist/src/profiler.js +73 -0
  146. package/dist/src/profiler.js.map +1 -0
  147. package/dist/src/reconciler/host-config.d.ts +16 -0
  148. package/dist/src/reconciler/host-config.d.ts.map +1 -0
  149. package/dist/src/reconciler/host-config.js +174 -0
  150. package/dist/src/reconciler/host-config.js.map +1 -0
  151. package/dist/src/reconciler/types.d.ts +52 -0
  152. package/dist/src/reconciler/types.d.ts.map +1 -0
  153. package/dist/src/reconciler/types.js +2 -0
  154. package/dist/src/reconciler/types.js.map +1 -0
  155. package/dist/src/renderer.d.ts +101 -0
  156. package/dist/src/renderer.d.ts.map +1 -0
  157. package/dist/src/renderer.js +509 -0
  158. package/dist/src/renderer.js.map +1 -0
  159. package/dist/src/terminal.d.ts +37 -0
  160. package/dist/src/terminal.d.ts.map +1 -0
  161. package/dist/src/terminal.js +65 -0
  162. package/dist/src/terminal.js.map +1 -0
  163. package/dist/src/test/index.d.ts +3 -0
  164. package/dist/src/test/index.d.ts.map +1 -0
  165. package/dist/src/test/index.js +3 -0
  166. package/dist/src/test/index.js.map +1 -0
  167. package/dist/src/test/mock-streams.d.ts +44 -0
  168. package/dist/src/test/mock-streams.d.ts.map +1 -0
  169. package/dist/src/test/mock-streams.js +136 -0
  170. package/dist/src/test/mock-streams.js.map +1 -0
  171. package/dist/src/test/render-tui.d.ts +47 -0
  172. package/dist/src/test/render-tui.d.ts.map +1 -0
  173. package/dist/src/test/render-tui.js +76 -0
  174. package/dist/src/test/render-tui.js.map +1 -0
  175. package/dist/src/trace/SpanTree.d.ts +10 -0
  176. package/dist/src/trace/SpanTree.d.ts.map +1 -0
  177. package/dist/src/trace/SpanTree.js +104 -0
  178. package/dist/src/trace/SpanTree.js.map +1 -0
  179. package/dist/src/trace/index.d.ts +30 -0
  180. package/dist/src/trace/index.d.ts.map +1 -0
  181. package/dist/src/trace/index.js +142 -0
  182. package/dist/src/trace/index.js.map +1 -0
  183. package/dist/src/trace/location.d.ts +9 -0
  184. package/dist/src/trace/location.d.ts.map +1 -0
  185. package/dist/src/trace/location.js +88 -0
  186. package/dist/src/trace/location.js.map +1 -0
  187. package/dist/src/trace/span-processor.d.ts +16 -0
  188. package/dist/src/trace/span-processor.d.ts.map +1 -0
  189. package/dist/src/trace/span-processor.js +54 -0
  190. package/dist/src/trace/span-processor.js.map +1 -0
  191. package/dist/src/trace/span-state.d.ts +79 -0
  192. package/dist/src/trace/span-state.d.ts.map +1 -0
  193. package/dist/src/trace/span-state.js +229 -0
  194. package/dist/src/trace/span-state.js.map +1 -0
  195. package/dist/src/trace/tui-logger.d.ts +8 -0
  196. package/dist/src/trace/tui-logger.d.ts.map +1 -0
  197. package/dist/src/trace/tui-logger.js +70 -0
  198. package/dist/src/trace/tui-logger.js.map +1 -0
  199. package/dist/src/utils/border.d.ts +31 -0
  200. package/dist/src/utils/border.d.ts.map +1 -0
  201. package/dist/src/utils/border.js +81 -0
  202. package/dist/src/utils/border.js.map +1 -0
  203. package/dist/src/utils/flex-layout.d.ts +20 -0
  204. package/dist/src/utils/flex-layout.d.ts.map +1 -0
  205. package/dist/src/utils/flex-layout.js +85 -0
  206. package/dist/src/utils/flex-layout.js.map +1 -0
  207. package/dist/src/utils/index.d.ts +5 -0
  208. package/dist/src/utils/index.d.ts.map +1 -0
  209. package/dist/src/utils/index.js +5 -0
  210. package/dist/src/utils/index.js.map +1 -0
  211. package/dist/src/utils/padding.d.ts +26 -0
  212. package/dist/src/utils/padding.d.ts.map +1 -0
  213. package/dist/src/utils/padding.js +34 -0
  214. package/dist/src/utils/padding.js.map +1 -0
  215. package/dist/src/utils/styles.d.ts +13 -0
  216. package/dist/src/utils/styles.d.ts.map +1 -0
  217. package/dist/src/utils/styles.js +5 -0
  218. package/dist/src/utils/styles.js.map +1 -0
  219. package/dist/src/visualize/index.d.ts +50 -0
  220. package/dist/src/visualize/index.d.ts.map +1 -0
  221. package/dist/src/visualize/index.js +194 -0
  222. package/dist/src/visualize/index.js.map +1 -0
  223. package/dist/tsconfig.tsbuildinfo +1 -0
  224. package/package.json +94 -0
  225. package/src/codeblock.tsx +47 -0
  226. package/src/constants.ts +2 -0
  227. package/src/debug/DiagnosticsPanel.tsx +38 -0
  228. package/src/highlight.ts +76 -0
  229. package/src/hooks/index.ts +3 -0
  230. package/src/hooks/use-keyboard.ts +37 -0
  231. package/src/hooks/use-paste.ts +14 -0
  232. package/src/hooks/useFrameStats.ts +32 -0
  233. package/src/hosts/base.ts +65 -0
  234. package/src/hosts/box.ts +105 -0
  235. package/src/hosts/canvas.ts +155 -0
  236. package/src/hosts/codeblock.ts +145 -0
  237. package/src/hosts/hstack.ts +64 -0
  238. package/src/hosts/index.ts +45 -0
  239. package/src/hosts/spacer.ts +40 -0
  240. package/src/hosts/text.ts +175 -0
  241. package/src/hosts/vstack.ts +64 -0
  242. package/src/hosts/zstack.ts +77 -0
  243. package/src/index.ts +62 -0
  244. package/src/inline/index.tsx +181 -0
  245. package/src/jsx.ts +3 -0
  246. package/src/motion/color-motion-value.ts +90 -0
  247. package/src/motion/color.test.ts +115 -0
  248. package/src/motion/color.ts +191 -0
  249. package/src/motion/event-emitter.ts +35 -0
  250. package/src/motion/frame.ts +59 -0
  251. package/src/motion/hooks.ts +237 -0
  252. package/src/motion/index.ts +17 -0
  253. package/src/motion/motion-value.test.ts +222 -0
  254. package/src/motion/motion-value.ts +140 -0
  255. package/src/motion/spring-math.ts +114 -0
  256. package/src/motion/types.ts +34 -0
  257. package/src/output.ts +156 -0
  258. package/src/profiler.ts +88 -0
  259. package/src/reconciler/host-config.ts +277 -0
  260. package/src/reconciler/types.ts +66 -0
  261. package/src/renderer.ts +661 -0
  262. package/src/terminal.ts +67 -0
  263. package/src/test/index.ts +8 -0
  264. package/src/test/mock-streams.ts +149 -0
  265. package/src/test/render-tui.ts +118 -0
  266. package/src/trace/SpanTree.tsx +195 -0
  267. package/src/trace/index.tsx +205 -0
  268. package/src/trace/location.ts +90 -0
  269. package/src/trace/span-processor.ts +65 -0
  270. package/src/trace/span-state.ts +286 -0
  271. package/src/trace/tui-logger.ts +72 -0
  272. package/src/utils/border.ts +108 -0
  273. package/src/utils/flex-layout.ts +125 -0
  274. package/src/utils/index.ts +4 -0
  275. package/src/utils/padding.ts +45 -0
  276. package/src/utils/styles.ts +14 -0
  277. package/src/visualize/index.tsx +305 -0
@@ -0,0 +1,9 @@
1
+ import type { SourceLocation } from "./span-state.js";
2
+ export declare function normalizeFile(file: string): string;
3
+ export declare function isAppPath(file: string): boolean;
4
+ export declare function isLibraryPath(file: string): boolean;
5
+ export declare function pickBestLocation(candidates: SourceLocation[]): SourceLocation | undefined;
6
+ export declare function parseStackLine(line: string): SourceLocation | undefined;
7
+ export declare function parseStackTrace(stack?: unknown): SourceLocation | undefined;
8
+ export declare function captureAppLocation(ignore?: Array<RegExp | string>): SourceLocation | undefined;
9
+ //# sourceMappingURL=location.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"location.d.ts","sourceRoot":"","sources":["../../../src/trace/location.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAIrD,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAGlD;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAK/C;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAOnD;AAED,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,cAAc,EAAE,GAAG,cAAc,GAAG,SAAS,CAMzF;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS,CAWvE;AAED,wBAAgB,eAAe,CAAC,KAAK,CAAC,EAAE,OAAO,GAAG,cAAc,GAAG,SAAS,CAS3E;AAED,wBAAgB,kBAAkB,CAAC,MAAM,GAAE,KAAK,CAAC,MAAM,GAAG,MAAM,CAAM,GAAG,cAAc,GAAG,SAAS,CA8BlG"}
@@ -0,0 +1,88 @@
1
+ import * as path from "node:path";
2
+ import { fileURLToPath } from "node:url";
3
+ const cwd = process.cwd();
4
+ export function normalizeFile(file) {
5
+ if (file.startsWith("file://"))
6
+ return fileURLToPath(file);
7
+ return file;
8
+ }
9
+ export function isAppPath(file) {
10
+ const normalized = normalizeFile(file);
11
+ if (normalized.includes(`${path.sep}node_modules${path.sep}`))
12
+ return false;
13
+ if (normalized.includes(`${path.sep}.bun${path.sep}`))
14
+ return false;
15
+ return normalized.startsWith(cwd);
16
+ }
17
+ export function isLibraryPath(file) {
18
+ const normalized = normalizeFile(file);
19
+ return (normalized.includes(`${path.sep}node_modules${path.sep}`) ||
20
+ normalized.includes("fiberRuntime") ||
21
+ normalized.includes("native"));
22
+ }
23
+ export function pickBestLocation(candidates) {
24
+ if (candidates.length === 0)
25
+ return undefined;
26
+ const app = candidates.find((c) => isAppPath(c.file));
27
+ if (app)
28
+ return app;
29
+ const nonLib = candidates.find((c) => !isLibraryPath(c.file));
30
+ return nonLib ?? candidates[0];
31
+ }
32
+ export function parseStackLine(line) {
33
+ const re = /at\s+(?:.+?\s+\()?((?:file:\/\/)?[^):]+):(\d+):(\d+)\)?$/;
34
+ const match = re.exec(line.trim());
35
+ if (match) {
36
+ const file = normalizeFile(match[1]);
37
+ return {
38
+ file,
39
+ line: Number(match[2]),
40
+ column: Number(match[3]),
41
+ };
42
+ }
43
+ }
44
+ export function parseStackTrace(stack) {
45
+ if (typeof stack !== "string")
46
+ return;
47
+ const lines = stack.split("\n");
48
+ const parsed = [];
49
+ for (const line of lines) {
50
+ const loc = parseStackLine(line);
51
+ if (loc)
52
+ parsed.push(loc);
53
+ }
54
+ return pickBestLocation(parsed);
55
+ }
56
+ export function captureAppLocation(ignore = []) {
57
+ const prev = Error.prepareStackTrace;
58
+ try {
59
+ Error.prepareStackTrace = (_err, structured) => structured;
60
+ const err = new Error();
61
+ Error.captureStackTrace(err, captureAppLocation);
62
+ const stack = err.stack;
63
+ if (!stack)
64
+ return;
65
+ const isIgnored = (file) => {
66
+ if (!file)
67
+ return false;
68
+ return ignore.some((p) => typeof p === "string" ? file.includes(p) : p.test(file));
69
+ };
70
+ const candidates = [];
71
+ for (const frame of stack) {
72
+ const file = frame.getFileName() || frame.getScriptNameOrSourceURL();
73
+ if (!file || isIgnored(file))
74
+ continue;
75
+ const loc = {
76
+ file: normalizeFile(file),
77
+ line: frame.getLineNumber() ?? 0,
78
+ column: frame.getColumnNumber() ?? undefined,
79
+ };
80
+ candidates.push(loc);
81
+ }
82
+ return pickBestLocation(candidates);
83
+ }
84
+ finally {
85
+ Error.prepareStackTrace = prev;
86
+ }
87
+ }
88
+ //# sourceMappingURL=location.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"location.js","sourceRoot":"","sources":["../../../src/trace/location.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import type { Context, Span } from "@opentelemetry/api";
2
+ import type { ReadableSpan, SpanProcessor } from "@opentelemetry/sdk-trace-base";
3
+ import type { SpanTreeState } from "./span-state.js";
4
+ /**
5
+ * OpenTelemetry SpanProcessor that updates SpanTreeState for TUI visualization.
6
+ */
7
+ export declare class TuiSpanProcessor implements SpanProcessor {
8
+ private state;
9
+ private onUpdate;
10
+ constructor(state: SpanTreeState, onUpdate: () => void);
11
+ onStart(span: Span, parentContext: Context): void;
12
+ onEnd(span: ReadableSpan): void;
13
+ forceFlush(): Promise<void>;
14
+ shutdown(): Promise<void>;
15
+ }
16
+ //# sourceMappingURL=span-processor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"span-processor.d.ts","sourceRoot":"","sources":["../../../src/trace/span-processor.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAA;AACvD,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAA;AAEhF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAGpD;;GAEG;AACH,qBAAa,gBAAiB,YAAW,aAAa;IAElD,OAAO,CAAC,KAAK;IACb,OAAO,CAAC,QAAQ;gBADR,KAAK,EAAE,aAAa,EACpB,QAAQ,EAAE,MAAM,IAAI;IAG9B,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,aAAa,EAAE,OAAO,GAAG,IAAI;IAoBjD,KAAK,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI;IAoB/B,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAI3B,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;CAG1B"}
@@ -0,0 +1,54 @@
1
+ // Custom SpanProcessor that feeds into TUI visualization
2
+ import { SpanStatusCode } from "@opentelemetry/api";
3
+ import { captureAppLocation, parseStackTrace } from "./location.js";
4
+ /**
5
+ * OpenTelemetry SpanProcessor that updates SpanTreeState for TUI visualization.
6
+ */
7
+ export class TuiSpanProcessor {
8
+ state;
9
+ onUpdate;
10
+ constructor(state, onUpdate) {
11
+ this.state = state;
12
+ this.onUpdate = onUpdate;
13
+ }
14
+ onStart(span, parentContext) {
15
+ const spanContext = span.spanContext();
16
+ const parentSpanContext = parentContext.getValue(Symbol.for("OpenTelemetry Context Key SPAN"));
17
+ const location = captureAppLocation([/span-processor/, /SpanProcessor/, /@effect-tui\/react/]);
18
+ // Extract parent span ID if available
19
+ let parentId = null;
20
+ if (parentSpanContext && typeof parentSpanContext === "object" && "spanContext" in parentSpanContext) {
21
+ const parentCtx = parentSpanContext.spanContext();
22
+ parentId = parentCtx.spanId;
23
+ }
24
+ // Get span name - the span object has a private _name, but we can get it from ReadableSpan later
25
+ // For now use the spanId as placeholder, we'll update on end
26
+ const name = span.name || spanContext.spanId;
27
+ this.state.addSpan(spanContext.spanId, parentId, name, location);
28
+ this.onUpdate();
29
+ }
30
+ onEnd(span) {
31
+ const spanContext = span.spanContext();
32
+ const status = span.status;
33
+ let location = parseStackTrace(span.attributes?.["code.stacktrace"]);
34
+ if (!location) {
35
+ location = captureAppLocation([/span-processor/, /SpanProcessor/]);
36
+ if (!location && process.env.EFFECT_TUI_DEBUG_STACKS === "1") {
37
+ // eslint-disable-next-line no-console
38
+ console.error("[effect-tui] span end missing location; attributes stack:", span.attributes?.["code.stacktrace"]);
39
+ }
40
+ }
41
+ // Determine success/failure from span status
42
+ const isSuccess = status.code !== SpanStatusCode.ERROR;
43
+ const error = status.code === SpanStatusCode.ERROR ? status.message : undefined;
44
+ this.state.endSpan(spanContext.spanId, isSuccess ? "success" : "failure", error, location);
45
+ this.onUpdate();
46
+ }
47
+ forceFlush() {
48
+ return Promise.resolve();
49
+ }
50
+ shutdown() {
51
+ return Promise.resolve();
52
+ }
53
+ }
54
+ //# sourceMappingURL=span-processor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"span-processor.js","sourceRoot":"","sources":["../../../src/trace/span-processor.ts"],"names":[],"mappings":"AAAA,yDAAyD;AAIzD,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AAEnD,OAAO,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAEnE;;GAEG;AACH,MAAM,OAAO,gBAAgB;IAEjB;IACA;IAFV,YACU,KAAoB,EACpB,QAAoB;QADpB,UAAK,GAAL,KAAK,CAAe;QACpB,aAAQ,GAAR,QAAQ,CAAY;IAC3B,CAAC;IAEJ,OAAO,CAAC,IAAU,EAAE,aAAsB;QACxC,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,EAAE,CAAA;QACtC,MAAM,iBAAiB,GAAG,aAAa,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,gCAAgC,CAAC,CAAC,CAAA;QAC9F,MAAM,QAAQ,GAAG,kBAAkB,CAAC,CAAC,gBAAgB,EAAE,eAAe,EAAE,oBAAoB,CAAC,CAAC,CAAA;QAE9F,sCAAsC;QACtC,IAAI,QAAQ,GAAkB,IAAI,CAAA;QAClC,IAAI,iBAAiB,IAAI,OAAO,iBAAiB,KAAK,QAAQ,IAAI,aAAa,IAAI,iBAAiB,EAAE,CAAC;YACrG,MAAM,SAAS,GAAI,iBAA0B,CAAC,WAAW,EAAE,CAAA;YAC3D,QAAQ,GAAG,SAAS,CAAC,MAAM,CAAA;QAC7B,CAAC;QAED,iGAAiG;QACjG,6DAA6D;QAC7D,MAAM,IAAI,GAAI,IAAY,CAAC,IAAI,IAAI,WAAW,CAAC,MAAM,CAAA;QAErD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAA;QAChE,IAAI,CAAC,QAAQ,EAAE,CAAA;IACjB,CAAC;IAED,KAAK,CAAC,IAAkB;QACtB,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,EAAE,CAAA;QACtC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAA;QAC1B,IAAI,QAAQ,GAAG,eAAe,CAAE,IAAI,CAAC,UAAkB,EAAE,CAAC,iBAAiB,CAAC,CAAC,CAAA;QAC7E,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,QAAQ,GAAG,kBAAkB,CAAC,CAAC,gBAAgB,EAAE,eAAe,CAAC,CAAC,CAAA;YAClE,IAAI,CAAC,QAAQ,IAAI,OAAO,CAAC,GAAG,CAAC,uBAAuB,KAAK,GAAG,EAAE,CAAC;gBAC7D,sCAAsC;gBACtC,OAAO,CAAC,KAAK,CAAC,2DAA2D,EAAG,IAAI,CAAC,UAAkB,EAAE,CAAC,iBAAiB,CAAC,CAAC,CAAA;YAC3H,CAAC;QACH,CAAC;QAED,6CAA6C;QAC7C,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,KAAK,cAAc,CAAC,KAAK,CAAA;QACtD,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,KAAK,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAA;QAE/E,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAA;QAC1F,IAAI,CAAC,QAAQ,EAAE,CAAA;IACjB,CAAC;IAED,UAAU;QACR,OAAO,OAAO,CAAC,OAAO,EAAE,CAAA;IAC1B,CAAC;IAED,QAAQ;QACN,OAAO,OAAO,CAAC,OAAO,EAAE,CAAA;IAC1B,CAAC;CACF"}
@@ -0,0 +1,79 @@
1
+ export type SpanStatus = "running" | "success" | "failure";
2
+ export type LogLevel = "INFO" | "WARN" | "ERROR" | "DEBUG" | "TRACE";
3
+ export interface SourceLocation {
4
+ file: string;
5
+ line: number;
6
+ column?: number;
7
+ }
8
+ export interface LogEntry {
9
+ level: LogLevel;
10
+ message: string;
11
+ timestamp: number;
12
+ location?: SourceLocation;
13
+ }
14
+ export interface LogCounts {
15
+ info: number;
16
+ warn: number;
17
+ error: number;
18
+ debug: number;
19
+ total: number;
20
+ }
21
+ export interface SpanNode {
22
+ id: string;
23
+ parentId: string | null;
24
+ name: string;
25
+ status: SpanStatus;
26
+ startTime: number;
27
+ endTime?: number;
28
+ duration?: number;
29
+ error?: string;
30
+ logEntries: LogEntry[];
31
+ children: SpanNode[];
32
+ completedAt?: number;
33
+ opacity: number;
34
+ targetOpacity: number;
35
+ opacityVelocity: number;
36
+ location?: SourceLocation;
37
+ }
38
+ /**
39
+ * Manages span tree state for visualization.
40
+ * Tracks hierarchy, status, and notifies listeners on changes.
41
+ */
42
+ export declare class SpanTreeState {
43
+ private roots;
44
+ private nodesById;
45
+ private listeners;
46
+ selectedSpanId: string | null;
47
+ expandedSpanIds: Set<string>;
48
+ spinnerIndex: number;
49
+ private lastSpinnerTime;
50
+ private lastTickTime;
51
+ /** Add a new running span */
52
+ addSpan(id: string, parentId: string | null, name: string, location?: SourceLocation): void;
53
+ /** Mark a span as completed */
54
+ endSpan(id: string, status: "success" | "failure", error?: string, location?: SourceLocation): void;
55
+ /** Add a log entry to a span (called by custom logger) */
56
+ addLog(spanId: string, level: LogLevel, message: string, location?: SourceLocation): void;
57
+ /** Get all spans that have logs or captured locations (for navigation) in tree order */
58
+ getSpansWithLogs(): SpanNode[];
59
+ /** Select next span with logs */
60
+ selectNext(): void;
61
+ /** Select previous span with logs */
62
+ selectPrev(): void;
63
+ /** Toggle expansion of selected span */
64
+ toggleExpand(): void;
65
+ /** Tick animations (spinner + fades). Call at 60fps for smooth rendering. */
66
+ tick(): void;
67
+ /** Get all root spans */
68
+ getRoots(): readonly SpanNode[];
69
+ /** Get a span by ID */
70
+ getSpan(id: string): SpanNode | undefined;
71
+ /** Best-effort source location for the currently selected span or its logs */
72
+ getOpenTarget(): SourceLocation | null;
73
+ /** Check if any spans are still running */
74
+ hasRunning(): boolean;
75
+ /** Subscribe to state changes */
76
+ subscribe(listener: () => void): () => void;
77
+ private notify;
78
+ }
79
+ //# sourceMappingURL=span-state.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"span-state.d.ts","sourceRoot":"","sources":["../../../src/trace/span-state.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,229 @@
1
+ import { isAppPath } from "./location.js";
2
+ const SPINNER_FRAMES_COUNT = 6;
3
+ const SPIN_INTERVAL_MS = 80;
4
+ /**
5
+ * Manages span tree state for visualization.
6
+ * Tracks hierarchy, status, and notifies listeners on changes.
7
+ */
8
+ export class SpanTreeState {
9
+ roots = [];
10
+ nodesById = new Map();
11
+ listeners = new Set();
12
+ // Selection state for log navigation
13
+ selectedSpanId = null;
14
+ expandedSpanIds = new Set();
15
+ // Animation timing (managed here to decouple from React)
16
+ spinnerIndex = 0;
17
+ lastSpinnerTime = performance.now();
18
+ lastTickTime = performance.now();
19
+ /** Add a new running span */
20
+ addSpan(id, parentId, name, location) {
21
+ const node = {
22
+ id,
23
+ parentId,
24
+ name,
25
+ status: "running",
26
+ startTime: Date.now(),
27
+ logEntries: [],
28
+ children: [],
29
+ opacity: 1,
30
+ targetOpacity: 1,
31
+ opacityVelocity: 0,
32
+ location,
33
+ };
34
+ this.nodesById.set(id, node);
35
+ if (parentId) {
36
+ const parent = this.nodesById.get(parentId);
37
+ if (parent) {
38
+ parent.children.push(node);
39
+ }
40
+ else {
41
+ // Parent not found, add as root
42
+ this.roots.push(node);
43
+ }
44
+ }
45
+ else {
46
+ this.roots.push(node);
47
+ }
48
+ this.notify();
49
+ }
50
+ /** Mark a span as completed */
51
+ endSpan(id, status, error, location) {
52
+ const node = this.nodesById.get(id);
53
+ if (!node)
54
+ return;
55
+ const endTime = Date.now();
56
+ node.status = status;
57
+ node.endTime = endTime;
58
+ node.duration = endTime - node.startTime;
59
+ node.completedAt = performance.now(); // Use perf time for fade animation timing
60
+ // Keep opaque for now, fade will start after FADE_DELAY_MS in tickAnimations
61
+ node.targetOpacity = 1;
62
+ if (error)
63
+ node.error = error;
64
+ if (location)
65
+ node.location = location;
66
+ this.notify();
67
+ }
68
+ /** Add a log entry to a span (called by custom logger) */
69
+ addLog(spanId, level, message, location) {
70
+ const node = this.nodesById.get(spanId);
71
+ if (!node)
72
+ return;
73
+ node.logEntries.push({
74
+ level,
75
+ message,
76
+ timestamp: Date.now(),
77
+ location,
78
+ });
79
+ this.notify();
80
+ }
81
+ /** Get all spans that have logs or captured locations (for navigation) in tree order */
82
+ getSpansWithLogs() {
83
+ const result = [];
84
+ const visit = (node) => {
85
+ if (node.logEntries.length > 0 || node.location)
86
+ result.push(node);
87
+ for (const child of node.children)
88
+ visit(child);
89
+ };
90
+ for (const root of this.roots)
91
+ visit(root);
92
+ return result;
93
+ }
94
+ /** Select next span with logs */
95
+ selectNext() {
96
+ const spans = this.getSpansWithLogs();
97
+ if (spans.length === 0)
98
+ return;
99
+ if (this.selectedSpanId === null) {
100
+ this.selectedSpanId = spans[0]?.id;
101
+ }
102
+ else {
103
+ const idx = spans.findIndex((s) => s.id === this.selectedSpanId);
104
+ if (idx < spans.length - 1) {
105
+ this.selectedSpanId = spans[idx + 1]?.id;
106
+ }
107
+ }
108
+ this.notify();
109
+ }
110
+ /** Select previous span with logs */
111
+ selectPrev() {
112
+ const spans = this.getSpansWithLogs();
113
+ if (spans.length === 0)
114
+ return;
115
+ if (this.selectedSpanId === null) {
116
+ this.selectedSpanId = spans[spans.length - 1]?.id;
117
+ }
118
+ else {
119
+ const idx = spans.findIndex((s) => s.id === this.selectedSpanId);
120
+ if (idx > 0) {
121
+ this.selectedSpanId = spans[idx - 1]?.id;
122
+ }
123
+ }
124
+ this.notify();
125
+ }
126
+ /** Toggle expansion of selected span */
127
+ toggleExpand() {
128
+ if (this.selectedSpanId === null)
129
+ return;
130
+ if (this.expandedSpanIds.has(this.selectedSpanId)) {
131
+ this.expandedSpanIds.delete(this.selectedSpanId);
132
+ }
133
+ else {
134
+ this.expandedSpanIds.add(this.selectedSpanId);
135
+ }
136
+ this.notify();
137
+ }
138
+ /** Tick animations (spinner + fades). Call at 60fps for smooth rendering. */
139
+ tick() {
140
+ const now = performance.now();
141
+ // Cap dt to prevent large jumps when frames are delayed (GC, etc.)
142
+ const dt = Math.min((now - this.lastTickTime) / 1000, 0.05);
143
+ this.lastTickTime = now;
144
+ // Advance spinner at its own rate
145
+ if (now - this.lastSpinnerTime >= SPIN_INTERVAL_MS) {
146
+ this.spinnerIndex = (this.spinnerIndex + 1) % SPINNER_FRAMES_COUNT;
147
+ this.lastSpinnerTime = now;
148
+ }
149
+ // Fade animations
150
+ const fadeDelayMs = 1000;
151
+ const halfLife = 0.3;
152
+ const decay = 0.5 ** (dt / halfLife);
153
+ const epsilon = 0.01;
154
+ for (const node of this.nodesById.values()) {
155
+ // Check if completed span should start fading
156
+ if (node.completedAt && node.targetOpacity === 1) {
157
+ if (now - node.completedAt >= fadeDelayMs) {
158
+ node.targetOpacity = 0.4; // Start fading
159
+ }
160
+ }
161
+ const diff = Math.abs(node.opacity - node.targetOpacity);
162
+ if (diff > epsilon) {
163
+ // Exponential decay toward target - unconditionally stable
164
+ node.opacity = node.targetOpacity + (node.opacity - node.targetOpacity) * decay;
165
+ }
166
+ else if (diff > 0) {
167
+ // Snap to target when close enough
168
+ node.opacity = node.targetOpacity;
169
+ }
170
+ }
171
+ }
172
+ /** Get all root spans */
173
+ getRoots() {
174
+ return this.roots;
175
+ }
176
+ /** Get a span by ID */
177
+ getSpan(id) {
178
+ return this.nodesById.get(id);
179
+ }
180
+ /** Best-effort source location for the currently selected span or its logs */
181
+ getOpenTarget() {
182
+ if (!this.selectedSpanId)
183
+ return null;
184
+ const node = this.nodesById.get(this.selectedSpanId);
185
+ if (!node)
186
+ return null;
187
+ let fallback;
188
+ // Prefer app-path log entries (latest first)
189
+ for (let i = node.logEntries.length - 1; i >= 0; i--) {
190
+ const entry = node.logEntries[i];
191
+ if (entry.location) {
192
+ if (isAppPath(entry.location.file))
193
+ return entry.location;
194
+ if (!fallback)
195
+ fallback = entry.location;
196
+ }
197
+ }
198
+ if (node.location) {
199
+ if (isAppPath(node.location.file))
200
+ return node.location;
201
+ if (!fallback)
202
+ fallback = node.location;
203
+ }
204
+ if (!fallback)
205
+ return null;
206
+ if (process.env.EFFECT_TUI_DEBUG_STACKS === "1") {
207
+ // eslint-disable-next-line no-console
208
+ console.error("[effect-tui] only non-app locations available", fallback);
209
+ }
210
+ return null;
211
+ }
212
+ /** Check if any spans are still running */
213
+ hasRunning() {
214
+ for (const node of this.nodesById.values()) {
215
+ if (node.status === "running")
216
+ return true;
217
+ }
218
+ return false;
219
+ }
220
+ /** Subscribe to state changes */
221
+ subscribe(listener) {
222
+ this.listeners.add(listener);
223
+ return () => this.listeners.delete(listener);
224
+ }
225
+ notify() {
226
+ this.listeners.forEach((l) => l());
227
+ }
228
+ }
229
+ //# sourceMappingURL=span-state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"span-state.js","sourceRoot":"","sources":["../../../src/trace/span-state.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import { Logger } from "effect";
2
+ import type { SpanTreeState } from "./span-state.js";
3
+ /**
4
+ * Create a Logger that feeds log entries into SpanTreeState.
5
+ * Logs are associated with the current span and displayed in the TUI.
6
+ */
7
+ export declare function makeTuiLogger(state: SpanTreeState, onUpdate: () => void): Logger.Logger<unknown, void>;
8
+ //# sourceMappingURL=tui-logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tui-logger.d.ts","sourceRoot":"","sources":["../../../src/trace/tui-logger.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAA+C,MAAM,QAAQ,CAAA;AAC5E,OAAO,KAAK,EAA4B,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAqB9E;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,IAAI,CAAC,CA2CtG"}
@@ -0,0 +1,70 @@
1
+ // Custom Effect logger that feeds logs into SpanTreeState for TUI visualization
2
+ import { Logger, FiberRef, FiberRefs, Cause, Context, Tracer } from "effect";
3
+ import { captureAppLocation, parseStackLine, pickBestLocation } from "./location.js";
4
+ function captureCallerLocation() {
5
+ const err = new Error();
6
+ const stack = err.stack;
7
+ if (!stack)
8
+ return;
9
+ const lines = stack.split("\n").slice(1);
10
+ const parsed = [];
11
+ for (const line of lines) {
12
+ if (line.includes("tui-logger") || line.includes("makeTuiLogger"))
13
+ continue;
14
+ const loc = parseStackLine(line);
15
+ if (loc)
16
+ parsed.push(loc);
17
+ }
18
+ const best = pickBestLocation(parsed);
19
+ if (best)
20
+ return best;
21
+ return captureAppLocation([/tui-logger/, /makeTuiLogger/]);
22
+ }
23
+ /**
24
+ * Create a Logger that feeds log entries into SpanTreeState.
25
+ * Logs are associated with the current span and displayed in the TUI.
26
+ */
27
+ export function makeTuiLogger(state, onUpdate) {
28
+ return Logger.make(({ logLevel, message, cause, context }) => {
29
+ const debugStacks = process.env.EFFECT_TUI_DEBUG_STACKS === "1";
30
+ // Get current context from fiber refs
31
+ const ctx = FiberRefs.getOrDefault(context, FiberRef.currentContext);
32
+ // Get current span from context
33
+ const spanOption = Context.getOption(ctx, Tracer.ParentSpan);
34
+ if (spanOption._tag !== "Some")
35
+ return;
36
+ const span = spanOption.value;
37
+ if (!span || typeof span !== "object")
38
+ return;
39
+ // Get span ID - Effect spans have spanContext() method
40
+ const anySpan = span;
41
+ const spanId = typeof anySpan.spanContext === "function" ? anySpan.spanContext().spanId : anySpan.spanId;
42
+ if (!spanId)
43
+ return;
44
+ // Map Effect log level to our level
45
+ let level = "INFO";
46
+ const levelLabel = logLevel.label.toUpperCase();
47
+ if (levelLabel === "ERROR" || levelLabel === "FATAL")
48
+ level = "ERROR";
49
+ else if (levelLabel === "WARNING" || levelLabel === "WARN")
50
+ level = "WARN";
51
+ else if (levelLabel === "DEBUG")
52
+ level = "DEBUG";
53
+ else if (levelLabel === "TRACE")
54
+ level = "TRACE";
55
+ // Format message
56
+ let text = String(message);
57
+ // Add cause if present
58
+ if (cause && !Cause.isEmpty(cause)) {
59
+ text += ` ${Cause.pretty(cause)}`;
60
+ }
61
+ const location = captureCallerLocation();
62
+ state.addLog(spanId, level, text, location);
63
+ if (!location && debugStacks) {
64
+ // eslint-disable-next-line no-console
65
+ console.error("[effect-tui] no location for log; stack:", new Error().stack);
66
+ }
67
+ onUpdate();
68
+ });
69
+ }
70
+ //# sourceMappingURL=tui-logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tui-logger.js","sourceRoot":"","sources":["../../../src/trace/tui-logger.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Border utilities shared between box and canvas hosts.
3
+ */
4
+ import type { CellBuffer } from "@effect-tui/core";
5
+ export type BorderKind = "none" | "rounded" | "square" | "ascii";
6
+ export interface BorderChars {
7
+ tl: string;
8
+ tr: string;
9
+ bl: string;
10
+ br: string;
11
+ h: string;
12
+ v: string;
13
+ }
14
+ /**
15
+ * Get border characters for a given border style.
16
+ * Returns empty strings for "none" (drawing code should skip when border is "none").
17
+ */
18
+ export declare function borderChars(kind: BorderKind): BorderChars;
19
+ export interface ClipRect {
20
+ ox: number;
21
+ oy: number;
22
+ w: number;
23
+ h: number;
24
+ }
25
+ /**
26
+ * Draw a border around a rectangle.
27
+ * If clip is provided, only draws within the clip bounds (for canvas).
28
+ * If clip is not provided, draws the full border (for box).
29
+ */
30
+ export declare function drawBorder(buffer: CellBuffer, x: number, y: number, w: number, h: number, chars: BorderChars, style: number, clip?: ClipRect): void;
31
+ //# sourceMappingURL=border.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"border.d.ts","sourceRoot":"","sources":["../../../src/utils/border.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAElD,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,SAAS,GAAG,QAAQ,GAAG,OAAO,CAAA;AAEhE,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAA;IACV,EAAE,EAAE,MAAM,CAAA;IACV,EAAE,EAAE,MAAM,CAAA;IACV,EAAE,EAAE,MAAM,CAAA;IACV,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;CACV;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,UAAU,GAAG,WAAW,CAWzD;AAED,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAA;IACV,EAAE,EAAE,MAAM,CAAA;IACV,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;CACV;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CACxB,MAAM,EAAE,UAAU,EAClB,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,EACT,KAAK,EAAE,WAAW,EAClB,KAAK,EAAE,MAAM,EACb,IAAI,CAAC,EAAE,QAAQ,GACd,IAAI,CAoDN"}