@develemit/web-hooks 0.3.1 → 0.5.0

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.
@@ -0,0 +1,143 @@
1
+ "use client";
2
+ import {
3
+ Screen,
4
+ feedAnsi
5
+ } from "./chunk-IVLRQ23V.js";
6
+
7
+ // src/terminal-output/line-split.ts
8
+ var INCOMPLETE_ESCAPE = /\x1b(?:\[[0-?]*[ -/]*|\][^\x07\x1b]*\x1b?|[ -/]*)$/;
9
+ function splitIncompleteEscape(text) {
10
+ const match = INCOMPLETE_ESCAPE.exec(text);
11
+ if (!match) return { complete: text, held: "" };
12
+ return { complete: text.slice(0, match.index), held: match[0] };
13
+ }
14
+ function splitLines(text) {
15
+ const pieces = text.split("\n");
16
+ const rest = pieces.pop() ?? "";
17
+ const lines = pieces.map((line) => line.endsWith("\r") ? line.slice(0, -1) : line);
18
+ return { lines, rest };
19
+ }
20
+
21
+ // src/terminal-output/line-buffer.ts
22
+ function createLineBuffer({ maxLines }) {
23
+ let decoder = new TextDecoder("utf-8");
24
+ let lines = [];
25
+ let pending = "";
26
+ let cursor;
27
+ let dropped = 0;
28
+ function keep(added) {
29
+ lines.push(...added);
30
+ const over = Math.max(0, lines.length - maxLines);
31
+ if (over > 0) lines.splice(0, over);
32
+ dropped += over;
33
+ return over;
34
+ }
35
+ function update(added, over) {
36
+ return { lines: added, partial: splitIncompleteEscape(pending).complete, dropped: over };
37
+ }
38
+ return {
39
+ push(chunk, options) {
40
+ const text = typeof chunk === "string" ? chunk : decoder.decode(chunk, { stream: true });
41
+ if (options?.cursor !== void 0) cursor = options.cursor;
42
+ const { lines: added, rest } = splitLines(pending + text);
43
+ pending = rest;
44
+ return update(added, keep(added));
45
+ },
46
+ flush() {
47
+ const tail = pending + decoder.decode();
48
+ pending = "";
49
+ const added = tail === "" ? [] : [tail];
50
+ return update(added, keep(added));
51
+ },
52
+ reset() {
53
+ decoder = new TextDecoder("utf-8");
54
+ lines = [];
55
+ pending = "";
56
+ cursor = void 0;
57
+ dropped = 0;
58
+ },
59
+ get lines() {
60
+ return lines;
61
+ },
62
+ get partial() {
63
+ return splitIncompleteEscape(pending).complete;
64
+ },
65
+ get cursor() {
66
+ return cursor;
67
+ },
68
+ get dropped() {
69
+ return dropped;
70
+ }
71
+ };
72
+ }
73
+
74
+ // src/terminal-output/ansi-stream.ts
75
+ var DEFAULT_TAIL = 50;
76
+ var CURSOR_UP = /\x1b\[(\d*)A/g;
77
+ function largestCursorUp(text) {
78
+ let largest = 0;
79
+ for (const m of text.matchAll(CURSOR_UP)) largest = Math.max(largest, Number(m[1] || 1));
80
+ return largest;
81
+ }
82
+ function sameLine(a, b) {
83
+ return a !== void 0 && (a === b || JSON.stringify(a) === JSON.stringify(b));
84
+ }
85
+ function createAnsiStream(options = {}) {
86
+ let tail = options.tailLines ?? DEFAULT_TAIL;
87
+ let screen = new Screen();
88
+ let state = { style: {} };
89
+ let frozen = 0;
90
+ let shown = [];
91
+ let lastPartial = "";
92
+ let finished = false;
93
+ function render(partial) {
94
+ tail = Math.max(tail, largestCursorUp(partial));
95
+ screen.lines();
96
+ const draft = screen.clone();
97
+ feedAnsi(draft, { ...state }, partial, options);
98
+ const rows = draft.lines();
99
+ const first = rows.findIndex((row, i) => !sameLine(shown[i], row));
100
+ const from = first === -1 ? rows.length < shown.length ? rows.length : -1 : first;
101
+ shown = rows;
102
+ const update = from === -1 ? {} : { replaced: { from: frozen + from, lines: rows.slice(from) } };
103
+ const freeze = screen.cursorRow - tail;
104
+ if (freeze > 0) {
105
+ const dropped = screen.dropTop(freeze);
106
+ shown = shown.slice(dropped);
107
+ frozen += dropped;
108
+ }
109
+ return update;
110
+ }
111
+ return {
112
+ push(lines, partial = "") {
113
+ if (finished) return {};
114
+ for (const line of lines) {
115
+ tail = Math.max(tail, largestCursorUp(line));
116
+ feedAnsi(screen, state, `${line}
117
+ `, options);
118
+ }
119
+ lastPartial = partial;
120
+ return render(partial);
121
+ },
122
+ finish(partial = lastPartial) {
123
+ if (finished) return {};
124
+ const update = render(partial);
125
+ finished = true;
126
+ return update;
127
+ },
128
+ reset() {
129
+ finished = false;
130
+ lastPartial = "";
131
+ screen = new Screen();
132
+ state = { style: {} };
133
+ frozen = 0;
134
+ shown = [];
135
+ tail = options.tailLines ?? DEFAULT_TAIL;
136
+ }
137
+ };
138
+ }
139
+
140
+ export {
141
+ createLineBuffer,
142
+ createAnsiStream
143
+ };