@code-yeongyu/senpi-tui 2026.7.31 → 2026.8.3
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.
- package/README.md +77 -14
- package/dist/TuiAltScreen.d.ts +83 -0
- package/dist/TuiAltScreen.d.ts.map +1 -0
- package/dist/TuiAltScreen.js +687 -0
- package/dist/TuiAltScreen.js.map +1 -0
- package/dist/TuiMainScreen.d.ts +5 -0
- package/dist/TuiMainScreen.d.ts.map +1 -0
- package/dist/TuiMainScreen.js +5 -0
- package/dist/TuiMainScreen.js.map +1 -0
- package/dist/components/alt-screen-flash.d.ts +13 -0
- package/dist/components/alt-screen-flash.d.ts.map +1 -0
- package/dist/components/alt-screen-flash.js +36 -0
- package/dist/components/alt-screen-flash.js.map +1 -0
- package/dist/components/h-stack.d.ts +7 -0
- package/dist/components/h-stack.d.ts.map +1 -0
- package/dist/components/h-stack.js +43 -0
- package/dist/components/h-stack.js.map +1 -0
- package/dist/components/image.d.ts.map +1 -1
- package/dist/components/image.js +4 -4
- package/dist/components/image.js.map +1 -1
- package/dist/components/markdown.d.ts +2 -0
- package/dist/components/markdown.d.ts.map +1 -1
- package/dist/components/markdown.js +3 -2
- package/dist/components/markdown.js.map +1 -1
- package/dist/components/scroll-view.d.ts +51 -0
- package/dist/components/scroll-view.d.ts.map +1 -0
- package/dist/components/scroll-view.js +163 -0
- package/dist/components/scroll-view.js.map +1 -0
- package/dist/components/settings-list.d.ts.map +1 -1
- package/dist/components/settings-list.js +3 -6
- package/dist/components/settings-list.js.map +1 -1
- package/dist/components/stack.d.ts +32 -0
- package/dist/components/stack.d.ts.map +1 -0
- package/dist/components/stack.js +109 -0
- package/dist/components/stack.js.map +1 -0
- package/dist/components/v-stack.d.ts +8 -0
- package/dist/components/v-stack.d.ts.map +1 -0
- package/dist/components/v-stack.js +21 -0
- package/dist/components/v-stack.js.map +1 -0
- package/dist/index.d.ts +10 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -4
- package/dist/index.js.map +1 -1
- package/dist/keybindings.d.ts +30 -0
- package/dist/keybindings.d.ts.map +1 -1
- package/dist/keybindings.js +18 -0
- package/dist/keybindings.js.map +1 -1
- package/dist/layout-node.d.ts +40 -0
- package/dist/layout-node.d.ts.map +1 -0
- package/dist/layout-node.js +6 -0
- package/dist/layout-node.js.map +1 -0
- package/dist/layout.d.ts +40 -0
- package/dist/layout.d.ts.map +1 -0
- package/dist/layout.js +315 -0
- package/dist/layout.js.map +1 -0
- package/dist/mux.js +1 -1
- package/dist/mux.js.map +1 -1
- package/dist/terminal-image.d.ts +10 -0
- package/dist/terminal-image.d.ts.map +1 -1
- package/dist/terminal-image.js +61 -3
- package/dist/terminal-image.js.map +1 -1
- package/dist/terminal-text.d.ts +1 -0
- package/dist/terminal-text.d.ts.map +1 -1
- package/dist/terminal-text.js +12 -2
- package/dist/terminal-text.js.map +1 -1
- package/dist/tui.d.ts +37 -16
- package/dist/tui.d.ts.map +1 -1
- package/dist/tui.js +89 -21
- package/dist/tui.js.map +1 -1
- package/dist/utils.d.ts +10 -0
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +95 -4
- package/dist/utils.js.map +1 -1
- package/package.json +2 -2
package/dist/layout.js
ADDED
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
import { allocateStackSizes, visibleStackEntries } from "./components/stack.js";
|
|
2
|
+
import { getLayoutNode } from "./layout-node.js";
|
|
3
|
+
import { cropKittyImageLine, getKittyImageMetadata, isImageLine } from "./terminal-image.js";
|
|
4
|
+
import { CURSOR_MARKER, compositeTuiLine } from "./tui.js";
|
|
5
|
+
import { extractAnsiCode, getGraphemeCellRange, sliceByColumn, visibleWidth } from "./utils.js";
|
|
6
|
+
const OSC133_ZONE_PREFIX = /^(?:\x1b\]133;[ABC](?:\x07|\x1b\\))+/;
|
|
7
|
+
function intersect(a, b) {
|
|
8
|
+
const x = Math.max(a.x, b.x);
|
|
9
|
+
const y = Math.max(a.y, b.y);
|
|
10
|
+
const right = Math.min(a.x + a.width, b.x + b.width);
|
|
11
|
+
const bottom = Math.min(a.y + a.height, b.y + b.height);
|
|
12
|
+
return { x, y, width: Math.max(0, right - x), height: Math.max(0, bottom - y) };
|
|
13
|
+
}
|
|
14
|
+
function renderCached(context, component, width) {
|
|
15
|
+
const safeWidth = Math.max(1, Math.floor(width));
|
|
16
|
+
let widths = context.renderCache.get(component);
|
|
17
|
+
if (!widths) {
|
|
18
|
+
widths = new Map();
|
|
19
|
+
context.renderCache.set(component, widths);
|
|
20
|
+
}
|
|
21
|
+
let lines = widths.get(safeWidth);
|
|
22
|
+
if (!lines) {
|
|
23
|
+
lines = component.render(safeWidth);
|
|
24
|
+
widths.set(safeWidth, lines);
|
|
25
|
+
}
|
|
26
|
+
return lines;
|
|
27
|
+
}
|
|
28
|
+
function measureHeight(context, component, width) {
|
|
29
|
+
return renderCached(context, component, width).length;
|
|
30
|
+
}
|
|
31
|
+
function measureWidth(context, component, width) {
|
|
32
|
+
return renderCached(context, component, width).reduce((max, line) => Math.max(max, visibleWidth(line)), 0);
|
|
33
|
+
}
|
|
34
|
+
function withParent(box, parent) {
|
|
35
|
+
box.parent = parent;
|
|
36
|
+
return box;
|
|
37
|
+
}
|
|
38
|
+
function translateBox(box, deltaY) {
|
|
39
|
+
box.rect.y += deltaY;
|
|
40
|
+
for (const child of box.children)
|
|
41
|
+
translateBox(child, deltaY);
|
|
42
|
+
}
|
|
43
|
+
function updateClips(box, parentClip) {
|
|
44
|
+
box.clip = intersect(parentClip, box.rect);
|
|
45
|
+
for (const child of box.children)
|
|
46
|
+
updateClips(child, box.clip);
|
|
47
|
+
}
|
|
48
|
+
function layoutComponent(context, component, x, y, width, height, clip) {
|
|
49
|
+
const safeWidth = Math.max(1, Math.floor(width));
|
|
50
|
+
const node = getLayoutNode(component);
|
|
51
|
+
if (!node) {
|
|
52
|
+
const lines = renderCached(context, component, safeWidth);
|
|
53
|
+
const allocatedHeight = height === undefined ? lines.length : Math.max(0, Math.floor(height));
|
|
54
|
+
let lineOffset = 0;
|
|
55
|
+
if (lines.length > allocatedHeight && allocatedHeight > 0) {
|
|
56
|
+
const cursorLine = lines.findIndex((line) => line.includes(CURSOR_MARKER));
|
|
57
|
+
if (cursorLine >= allocatedHeight)
|
|
58
|
+
lineOffset = cursorLine - allocatedHeight + 1;
|
|
59
|
+
}
|
|
60
|
+
return {
|
|
61
|
+
component,
|
|
62
|
+
rect: { x, y, width: safeWidth, height: allocatedHeight },
|
|
63
|
+
clip: intersect(clip, { x, y, width: safeWidth, height: allocatedHeight }),
|
|
64
|
+
children: [],
|
|
65
|
+
lines,
|
|
66
|
+
lineOffset,
|
|
67
|
+
layer: 0,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
if (node.type === "scroll") {
|
|
71
|
+
const previousScrollTop = node.state.scrollTop;
|
|
72
|
+
const contentWidth = node.state.getContentWidth(safeWidth);
|
|
73
|
+
const childBox = layoutComponent(context, node.component, x, y - previousScrollTop, contentWidth, undefined, clip);
|
|
74
|
+
const contentHeight = childBox.rect.height;
|
|
75
|
+
const viewportHeight = height === undefined ? contentHeight : Math.max(0, Math.floor(height));
|
|
76
|
+
node.state.updateLayout(contentHeight, viewportHeight, context.requestRender);
|
|
77
|
+
translateBox(childBox, previousScrollTop - node.state.scrollTop);
|
|
78
|
+
const scrollView = node.state;
|
|
79
|
+
if (node.state.primary || !context.primaryScrollView)
|
|
80
|
+
context.primaryScrollView = scrollView;
|
|
81
|
+
const rect = { x, y, width: safeWidth, height: viewportHeight };
|
|
82
|
+
const childClip = intersect(clip, rect);
|
|
83
|
+
const box = {
|
|
84
|
+
component,
|
|
85
|
+
rect,
|
|
86
|
+
clip: childClip,
|
|
87
|
+
children: [childBox],
|
|
88
|
+
scrollView,
|
|
89
|
+
scrollContentLines: renderCached(context, node.component, contentWidth),
|
|
90
|
+
layer: 0,
|
|
91
|
+
};
|
|
92
|
+
childBox.parent = box;
|
|
93
|
+
updateClips(childBox, childClip);
|
|
94
|
+
return box;
|
|
95
|
+
}
|
|
96
|
+
const entries = visibleStackEntries(node.entries, context.viewport);
|
|
97
|
+
const gapTotal = Math.max(0, entries.length - 1) * node.gap;
|
|
98
|
+
if (node.type === "vstack") {
|
|
99
|
+
const intrinsicHeights = entries.map((entry) => measureHeight(context, entry.component, safeWidth));
|
|
100
|
+
const sizes = allocateStackSizes(entries, intrinsicHeights, height, node.gap);
|
|
101
|
+
const naturalHeight = sizes.reduce((sum, size) => sum + size, 0) + gapTotal;
|
|
102
|
+
const allocatedHeight = height === undefined ? naturalHeight : Math.max(0, Math.floor(height));
|
|
103
|
+
const rect = { x, y, width: safeWidth, height: allocatedHeight };
|
|
104
|
+
const box = {
|
|
105
|
+
component,
|
|
106
|
+
rect,
|
|
107
|
+
clip: intersect(clip, rect),
|
|
108
|
+
children: [],
|
|
109
|
+
layer: 0,
|
|
110
|
+
};
|
|
111
|
+
let childY = y;
|
|
112
|
+
for (let index = 0; index < entries.length; index++) {
|
|
113
|
+
box.children.push(withParent(layoutComponent(context, entries[index].component, x, childY, safeWidth, sizes[index], box.clip), box));
|
|
114
|
+
childY += sizes[index] + node.gap;
|
|
115
|
+
}
|
|
116
|
+
return box;
|
|
117
|
+
}
|
|
118
|
+
const intrinsicWidths = entries.map((entry) => measureWidth(context, entry.component, safeWidth));
|
|
119
|
+
const widths = allocateStackSizes(entries, intrinsicWidths, safeWidth, node.gap);
|
|
120
|
+
const intrinsicHeights = entries.map((entry, index) => measureHeight(context, entry.component, Math.max(1, widths[index])));
|
|
121
|
+
const allocatedHeight = height === undefined
|
|
122
|
+
? intrinsicHeights.reduce((max, childHeight) => Math.max(max, childHeight), 0)
|
|
123
|
+
: Math.max(0, height);
|
|
124
|
+
const rect = { x, y, width: safeWidth, height: allocatedHeight };
|
|
125
|
+
const box = {
|
|
126
|
+
component,
|
|
127
|
+
rect,
|
|
128
|
+
clip: intersect(clip, rect),
|
|
129
|
+
children: [],
|
|
130
|
+
layer: 0,
|
|
131
|
+
};
|
|
132
|
+
let childX = x;
|
|
133
|
+
for (let index = 0; index < entries.length; index++) {
|
|
134
|
+
const naturalChildHeight = intrinsicHeights[index];
|
|
135
|
+
const childHeight = node.align === "stretch" ? allocatedHeight : Math.min(allocatedHeight, naturalChildHeight);
|
|
136
|
+
let childY = y;
|
|
137
|
+
if (node.align === "center")
|
|
138
|
+
childY += Math.floor((allocatedHeight - childHeight) / 2);
|
|
139
|
+
else if (node.align === "end")
|
|
140
|
+
childY += allocatedHeight - childHeight;
|
|
141
|
+
const childWidth = widths[index];
|
|
142
|
+
if (childWidth === 0) {
|
|
143
|
+
box.children.push({
|
|
144
|
+
component: entries[index].component,
|
|
145
|
+
rect: { x: childX, y: childY, width: 0, height: childHeight },
|
|
146
|
+
clip: { x: childX, y: childY, width: 0, height: 0 },
|
|
147
|
+
children: [],
|
|
148
|
+
parent: box,
|
|
149
|
+
layer: 0,
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
box.children.push(withParent(layoutComponent(context, entries[index].component, childX, childY, childWidth, childHeight, box.clip), box));
|
|
154
|
+
}
|
|
155
|
+
childX += childWidth + node.gap;
|
|
156
|
+
}
|
|
157
|
+
return box;
|
|
158
|
+
}
|
|
159
|
+
function styleScrollbarCell(line, column, totalWidth, style) {
|
|
160
|
+
if (isImageLine(line))
|
|
161
|
+
return line;
|
|
162
|
+
const graphemeRange = getGraphemeCellRange(line, column);
|
|
163
|
+
const start = graphemeRange?.start ?? column;
|
|
164
|
+
const end = graphemeRange?.end ?? column + 1;
|
|
165
|
+
const before = sliceByColumn(line, 0, start, true);
|
|
166
|
+
const target = sliceByColumn(line, start, end - start, true);
|
|
167
|
+
const after = sliceByColumn(line, end, Math.max(0, totalWidth - end), true);
|
|
168
|
+
let targetPrefix = "";
|
|
169
|
+
let targetIndex = 0;
|
|
170
|
+
while (targetIndex < target.length) {
|
|
171
|
+
const ansi = extractAnsiCode(target, targetIndex);
|
|
172
|
+
if (!ansi)
|
|
173
|
+
break;
|
|
174
|
+
targetPrefix += ansi.code;
|
|
175
|
+
targetIndex += ansi.length;
|
|
176
|
+
}
|
|
177
|
+
const targetText = target.slice(targetIndex) || " ".repeat(end - start);
|
|
178
|
+
const beforePadding = " ".repeat(Math.max(0, start - visibleWidth(before)));
|
|
179
|
+
return `${before}${beforePadding}${targetPrefix}${style(targetText)}${after}`;
|
|
180
|
+
}
|
|
181
|
+
export function getScrollbarGeometry(box) {
|
|
182
|
+
if (!box.scrollView?.isScrollbarVisible || box.rect.width <= 0 || box.rect.height <= 0)
|
|
183
|
+
return undefined;
|
|
184
|
+
const contentHeight = box.children[0]?.rect.height ?? box.scrollContentLines?.length ?? 0;
|
|
185
|
+
const trackHeight = box.rect.height;
|
|
186
|
+
const minThumbHeight = Math.min(2, trackHeight);
|
|
187
|
+
const thumbHeight = Math.max(minThumbHeight, Math.min(trackHeight, Math.round((trackHeight * trackHeight) / contentHeight)));
|
|
188
|
+
const maxScrollTop = Math.max(0, contentHeight - trackHeight);
|
|
189
|
+
const maxThumbTop = trackHeight - thumbHeight;
|
|
190
|
+
const thumbOffset = maxScrollTop === 0 ? 0 : Math.round((box.scrollView.scrollTop / maxScrollTop) * maxThumbTop);
|
|
191
|
+
const column = box.rect.x + box.rect.width - 1;
|
|
192
|
+
if (column < box.clip.x || column >= box.clip.x + box.clip.width)
|
|
193
|
+
return undefined;
|
|
194
|
+
return {
|
|
195
|
+
column,
|
|
196
|
+
trackTop: box.rect.y,
|
|
197
|
+
trackHeight,
|
|
198
|
+
thumbTop: box.rect.y + thumbOffset,
|
|
199
|
+
thumbHeight,
|
|
200
|
+
maxScrollTop,
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
function paintScrollbar(box, screen, totalWidth) {
|
|
204
|
+
const geometry = getScrollbarGeometry(box);
|
|
205
|
+
if (!geometry || !box.scrollView)
|
|
206
|
+
return;
|
|
207
|
+
for (let offset = 0; offset < geometry.thumbHeight; offset++) {
|
|
208
|
+
const row = geometry.thumbTop + offset;
|
|
209
|
+
if (row < box.clip.y || row >= box.clip.y + box.clip.height || row < 0 || row >= screen.length)
|
|
210
|
+
continue;
|
|
211
|
+
screen[row] = styleScrollbarCell(screen[row] ?? "", geometry.column, totalWidth, box.scrollView.scrollbarStyle);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
function paintBox(box, screen, totalWidth) {
|
|
215
|
+
if (box.lines) {
|
|
216
|
+
const offset = box.lineOffset ?? 0;
|
|
217
|
+
for (let localRow = 0; localRow < box.rect.height; localRow++) {
|
|
218
|
+
const row = box.rect.y + localRow;
|
|
219
|
+
if (row < box.clip.y || row >= box.clip.y + box.clip.height || row < 0 || row >= screen.length)
|
|
220
|
+
continue;
|
|
221
|
+
const sourceLine = box.lines[offset + localRow];
|
|
222
|
+
if (sourceLine === undefined)
|
|
223
|
+
continue;
|
|
224
|
+
let line = sourceLine.replace(OSC133_ZONE_PREFIX, "");
|
|
225
|
+
const imageMetadata = getKittyImageMetadata(line);
|
|
226
|
+
if (imageMetadata) {
|
|
227
|
+
const clipBottom = Math.min(screen.length, box.clip.y + box.clip.height);
|
|
228
|
+
const visibleRows = Math.min(imageMetadata.rows, clipBottom - row);
|
|
229
|
+
if (visibleRows < imageMetadata.rows)
|
|
230
|
+
line = cropKittyImageLine(line, 0, visibleRows);
|
|
231
|
+
}
|
|
232
|
+
if (isImageLine(line) && box.rect.x === 0 && box.rect.width >= totalWidth)
|
|
233
|
+
screen[row] = line;
|
|
234
|
+
else
|
|
235
|
+
screen[row] = compositeTuiLine(screen[row] ?? "", line, box.rect.x, box.rect.width, totalWidth);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
for (const child of box.children)
|
|
239
|
+
paintBox(child, screen, totalWidth);
|
|
240
|
+
if (box.scrollView && box.scrollContentLines && box.scrollView.scrollTop > 0 && box.rect.height > 0) {
|
|
241
|
+
for (let imageRow = box.scrollView.scrollTop - 1; imageRow >= 0; imageRow--) {
|
|
242
|
+
const imageLine = box.scrollContentLines[imageRow] ?? "";
|
|
243
|
+
const metadata = getKittyImageMetadata(imageLine);
|
|
244
|
+
if (metadata) {
|
|
245
|
+
const hiddenRows = box.scrollView.scrollTop - imageRow;
|
|
246
|
+
if (hiddenRows < metadata.rows) {
|
|
247
|
+
const visibleRows = Math.min(box.rect.height, metadata.rows - hiddenRows);
|
|
248
|
+
const cropped = cropKittyImageLine(imageLine, hiddenRows, visibleRows);
|
|
249
|
+
if (box.rect.x === 0 && box.rect.width >= totalWidth)
|
|
250
|
+
screen[box.rect.y] = cropped;
|
|
251
|
+
}
|
|
252
|
+
break;
|
|
253
|
+
}
|
|
254
|
+
if (imageLine !== "")
|
|
255
|
+
break;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
paintScrollbar(box, screen, totalWidth);
|
|
259
|
+
}
|
|
260
|
+
export function renderLayoutFrame(root, width, height, requestRender) {
|
|
261
|
+
const safeWidth = Math.max(1, Math.floor(width));
|
|
262
|
+
const safeHeight = Math.max(1, Math.floor(height));
|
|
263
|
+
const context = {
|
|
264
|
+
viewport: { width: safeWidth, height: safeHeight },
|
|
265
|
+
renderCache: new Map(),
|
|
266
|
+
requestRender,
|
|
267
|
+
primaryScrollView: undefined,
|
|
268
|
+
};
|
|
269
|
+
const rootBox = layoutComponent(context, root, 0, 0, safeWidth, safeHeight, {
|
|
270
|
+
x: 0,
|
|
271
|
+
y: 0,
|
|
272
|
+
width: safeWidth,
|
|
273
|
+
height: safeHeight,
|
|
274
|
+
});
|
|
275
|
+
const lines = Array.from({ length: safeHeight }, () => "");
|
|
276
|
+
paintBox(rootBox, lines, safeWidth);
|
|
277
|
+
return {
|
|
278
|
+
root: rootBox,
|
|
279
|
+
width: safeWidth,
|
|
280
|
+
height: safeHeight,
|
|
281
|
+
lines,
|
|
282
|
+
...(context.primaryScrollView === undefined ? {} : { primaryScrollView: context.primaryScrollView }),
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
function containsPoint(rect, x, y) {
|
|
286
|
+
return x >= rect.x && x < rect.x + rect.width && y >= rect.y && y < rect.y + rect.height;
|
|
287
|
+
}
|
|
288
|
+
export function getScrollViewBox(frame, scrollView) {
|
|
289
|
+
const visit = (box) => {
|
|
290
|
+
if (box.scrollView === scrollView)
|
|
291
|
+
return box;
|
|
292
|
+
for (const child of box.children) {
|
|
293
|
+
const match = visit(child);
|
|
294
|
+
if (match)
|
|
295
|
+
return match;
|
|
296
|
+
}
|
|
297
|
+
return undefined;
|
|
298
|
+
};
|
|
299
|
+
return visit(frame.root);
|
|
300
|
+
}
|
|
301
|
+
export function getScrollViewsAt(frame, x, y) {
|
|
302
|
+
const result = [];
|
|
303
|
+
const visit = (box, depth) => {
|
|
304
|
+
if (!containsPoint(box.clip, x, y))
|
|
305
|
+
return;
|
|
306
|
+
if (box.scrollView && containsPoint(box.rect, x, y))
|
|
307
|
+
result.push({ scrollView: box.scrollView, depth });
|
|
308
|
+
for (const child of box.children)
|
|
309
|
+
visit(child, depth + 1);
|
|
310
|
+
};
|
|
311
|
+
visit(frame.root, 0);
|
|
312
|
+
result.sort((a, b) => b.depth - a.depth);
|
|
313
|
+
return result.map((entry) => entry.scrollView);
|
|
314
|
+
}
|
|
315
|
+
//# sourceMappingURL=layout.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"layout.js","sourceRoot":"","sources":["../src/layout.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAChF,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAC7F,OAAO,EAAkB,aAAa,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAC3E,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAEhG,MAAM,kBAAkB,GAAG,sCAAsC,CAAC;AA8ClE,SAAS,SAAS,CAAC,CAAa,EAAE,CAAa;IAC9C,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAC7B,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAC7B,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;IACrD,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC;IACxD,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,EAAE,CAAC;AACjF,CAAC;AAED,SAAS,YAAY,CAAC,OAAsB,EAAE,SAAoB,EAAE,KAAa;IAChF,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;IACjD,IAAI,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IAChD,IAAI,CAAC,MAAM,EAAE,CAAC;QACb,MAAM,GAAG,IAAI,GAAG,EAAoB,CAAC;QACrC,OAAO,CAAC,WAAW,CAAC,GAAG,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;IAC5C,CAAC;IACD,IAAI,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IAClC,IAAI,CAAC,KAAK,EAAE,CAAC;QACZ,KAAK,GAAG,SAAS,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QACpC,MAAM,CAAC,GAAG,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;IAC9B,CAAC;IACD,OAAO,KAAK,CAAC;AACd,CAAC;AAED,SAAS,aAAa,CAAC,OAAsB,EAAE,SAAoB,EAAE,KAAa;IACjF,OAAO,YAAY,CAAC,OAAO,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC,MAAM,CAAC;AACvD,CAAC;AAED,SAAS,YAAY,CAAC,OAAsB,EAAE,SAAoB,EAAE,KAAa;IAChF,OAAO,YAAY,CAAC,OAAO,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,YAAY,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AAC5G,CAAC;AAED,SAAS,UAAU,CAAC,GAAc,EAAE,MAAiB;IACpD,GAAG,CAAC,MAAM,GAAG,MAAM,CAAC;IACpB,OAAO,GAAG,CAAC;AACZ,CAAC;AAED,SAAS,YAAY,CAAC,GAAc,EAAE,MAAc;IACnD,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,MAAM,CAAC;IACrB,KAAK,MAAM,KAAK,IAAI,GAAG,CAAC,QAAQ;QAAE,YAAY,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;AAC/D,CAAC;AAED,SAAS,WAAW,CAAC,GAAc,EAAE,UAAsB;IAC1D,GAAG,CAAC,IAAI,GAAG,SAAS,CAAC,UAAU,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;IAC3C,KAAK,MAAM,KAAK,IAAI,GAAG,CAAC,QAAQ;QAAE,WAAW,CAAC,KAAK,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;AAChE,CAAC;AAED,SAAS,eAAe,CACvB,OAAsB,EACtB,SAAoB,EACpB,CAAS,EACT,CAAS,EACT,KAAa,EACb,MAA0B,EAC1B,IAAgB;IAEhB,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;IACjD,MAAM,IAAI,GAAG,aAAa,CAAC,SAAS,CAAC,CAAC;IACtC,IAAI,CAAC,IAAI,EAAE,CAAC;QACX,MAAM,KAAK,GAAG,YAAY,CAAC,OAAO,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;QAC1D,MAAM,eAAe,GAAG,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;QAC9F,IAAI,UAAU,GAAG,CAAC,CAAC;QACnB,IAAI,KAAK,CAAC,MAAM,GAAG,eAAe,IAAI,eAAe,GAAG,CAAC,EAAE,CAAC;YAC3D,MAAM,UAAU,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAC;YAC3E,IAAI,UAAU,IAAI,eAAe;gBAAE,UAAU,GAAG,UAAU,GAAG,eAAe,GAAG,CAAC,CAAC;QAClF,CAAC;QACD,OAAO;YACN,SAAS;YACT,IAAI,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,eAAe,EAAE;YACzD,IAAI,EAAE,SAAS,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,eAAe,EAAE,CAAC;YAC1E,QAAQ,EAAE,EAAE;YACZ,KAAK;YACL,UAAU;YACV,KAAK,EAAE,CAAC;SACR,CAAC;IACH,CAAC;IAED,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC5B,MAAM,iBAAiB,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC;QAC/C,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC;QAC3D,MAAM,QAAQ,GAAG,eAAe,CAC/B,OAAO,EACP,IAAI,CAAC,SAAS,EACd,CAAC,EACD,CAAC,GAAG,iBAAiB,EACrB,YAAY,EACZ,SAAS,EACT,IAAI,CACJ,CAAC;QACF,MAAM,aAAa,GAAG,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC;QAC3C,MAAM,cAAc,GAAG,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;QAC9F,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,aAAa,EAAE,cAAc,EAAE,OAAO,CAAC,aAAa,CAAC,CAAC;QAC9E,YAAY,CAAC,QAAQ,EAAE,iBAAiB,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QACjE,MAAM,UAAU,GAAG,IAAI,CAAC,KAAmB,CAAC;QAC5C,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,iBAAiB;YAAE,OAAO,CAAC,iBAAiB,GAAG,UAAU,CAAC;QAC7F,MAAM,IAAI,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC;QAChE,MAAM,SAAS,GAAG,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QACxC,MAAM,GAAG,GAAc;YACtB,SAAS;YACT,IAAI;YACJ,IAAI,EAAE,SAAS;YACf,QAAQ,EAAE,CAAC,QAAQ,CAAC;YACpB,UAAU;YACV,kBAAkB,EAAE,YAAY,CAAC,OAAO,EAAE,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC;YACvE,KAAK,EAAE,CAAC;SACR,CAAC;QACF,QAAQ,CAAC,MAAM,GAAG,GAAG,CAAC;QACtB,WAAW,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;QACjC,OAAO,GAAG,CAAC;IACZ,CAAC;IAED,MAAM,OAAO,GAAG,mBAAmB,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;IACpE,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC;IAC5D,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC5B,MAAM,gBAAgB,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,aAAa,CAAC,OAAO,EAAE,KAAK,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC;QACpG,MAAM,KAAK,GAAG,kBAAkB,CAAC,OAAO,EAAE,gBAAgB,EAAE,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;QAC9E,MAAM,aAAa,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,CAAC,GAAG,GAAG,IAAI,EAAE,CAAC,CAAC,GAAG,QAAQ,CAAC;QAC5E,MAAM,eAAe,GAAG,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;QAC/F,MAAM,IAAI,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,eAAe,EAAE,CAAC;QACjE,MAAM,GAAG,GAAc;YACtB,SAAS;YACT,IAAI;YACJ,IAAI,EAAE,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC;YAC3B,QAAQ,EAAE,EAAE;YACZ,KAAK,EAAE,CAAC;SACR,CAAC;QACF,IAAI,MAAM,GAAG,CAAC,CAAC;QACf,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,OAAO,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC;YACrD,GAAG,CAAC,QAAQ,CAAC,IAAI,CAChB,UAAU,CACT,eAAe,CAAC,OAAO,EAAE,OAAO,CAAC,KAAK,CAAE,CAAC,SAAS,EAAE,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK,CAAC,KAAK,CAAE,EAAE,GAAG,CAAC,IAAI,CAAC,EAClG,GAAG,CACH,CACD,CAAC;YACF,MAAM,IAAI,KAAK,CAAC,KAAK,CAAE,GAAG,IAAI,CAAC,GAAG,CAAC;QACpC,CAAC;QACD,OAAO,GAAG,CAAC;IACZ,CAAC;IAED,MAAM,eAAe,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,YAAY,CAAC,OAAO,EAAE,KAAK,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC;IAClG,MAAM,MAAM,GAAG,kBAAkB,CAAC,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;IACjF,MAAM,gBAAgB,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CACrD,aAAa,CAAC,OAAO,EAAE,KAAK,CAAC,SAAS,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,KAAK,CAAE,CAAC,CAAC,CACpE,CAAC;IACF,MAAM,eAAe,GACpB,MAAM,KAAK,SAAS;QACnB,CAAC,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,WAAW,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,WAAW,CAAC,EAAE,CAAC,CAAC;QAC9E,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;IACxB,MAAM,IAAI,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,eAAe,EAAE,CAAC;IACjE,MAAM,GAAG,GAAc;QACtB,SAAS;QACT,IAAI;QACJ,IAAI,EAAE,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC;QAC3B,QAAQ,EAAE,EAAE;QACZ,KAAK,EAAE,CAAC;KACR,CAAC;IACF,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,OAAO,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC;QACrD,MAAM,kBAAkB,GAAG,gBAAgB,CAAC,KAAK,CAAE,CAAC;QACpD,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,eAAe,EAAE,kBAAkB,CAAC,CAAC;QAC/G,IAAI,MAAM,GAAG,CAAC,CAAC;QACf,IAAI,IAAI,CAAC,KAAK,KAAK,QAAQ;YAAE,MAAM,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,eAAe,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC;aAClF,IAAI,IAAI,CAAC,KAAK,KAAK,KAAK;YAAE,MAAM,IAAI,eAAe,GAAG,WAAW,CAAC;QACvE,MAAM,UAAU,GAAG,MAAM,CAAC,KAAK,CAAE,CAAC;QAClC,IAAI,UAAU,KAAK,CAAC,EAAE,CAAC;YACtB,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC;gBACjB,SAAS,EAAE,OAAO,CAAC,KAAK,CAAE,CAAC,SAAS;gBACpC,IAAI,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE;gBAC7D,IAAI,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE;gBACnD,QAAQ,EAAE,EAAE;gBACZ,MAAM,EAAE,GAAG;gBACX,KAAK,EAAE,CAAC;aACR,CAAC,CAAC;QACJ,CAAC;aAAM,CAAC;YACP,GAAG,CAAC,QAAQ,CAAC,IAAI,CAChB,UAAU,CACT,eAAe,CAAC,OAAO,EAAE,OAAO,CAAC,KAAK,CAAE,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,WAAW,EAAE,GAAG,CAAC,IAAI,CAAC,EACtG,GAAG,CACH,CACD,CAAC;QACH,CAAC;QACD,MAAM,IAAI,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC;IACjC,CAAC;IACD,OAAO,GAAG,CAAC;AACZ,CAAC;AAED,SAAS,kBAAkB,CAAC,IAAY,EAAE,MAAc,EAAE,UAAkB,EAAE,KAA+B;IAC5G,IAAI,WAAW,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IAEnC,MAAM,aAAa,GAAG,oBAAoB,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACzD,MAAM,KAAK,GAAG,aAAa,EAAE,KAAK,IAAI,MAAM,CAAC;IAC7C,MAAM,GAAG,GAAG,aAAa,EAAE,GAAG,IAAI,MAAM,GAAG,CAAC,CAAC;IAC7C,MAAM,MAAM,GAAG,aAAa,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;IACnD,MAAM,MAAM,GAAG,aAAa,CAAC,IAAI,EAAE,KAAK,EAAE,GAAG,GAAG,KAAK,EAAE,IAAI,CAAC,CAAC;IAC7D,MAAM,KAAK,GAAG,aAAa,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,UAAU,GAAG,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC;IAE5E,IAAI,YAAY,GAAG,EAAE,CAAC;IACtB,IAAI,WAAW,GAAG,CAAC,CAAC;IACpB,OAAO,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC;QACpC,MAAM,IAAI,GAAG,eAAe,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;QAClD,IAAI,CAAC,IAAI;YAAE,MAAM;QACjB,YAAY,IAAI,IAAI,CAAC,IAAI,CAAC;QAC1B,WAAW,IAAI,IAAI,CAAC,MAAM,CAAC;IAC5B,CAAC;IACD,MAAM,UAAU,GAAG,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,GAAG,GAAG,KAAK,CAAC,CAAC;IACxE,MAAM,aAAa,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IAC5E,OAAO,GAAG,MAAM,GAAG,aAAa,GAAG,YAAY,GAAG,KAAK,CAAC,UAAU,CAAC,GAAG,KAAK,EAAE,CAAC;AAC/E,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,GAAc;IAClD,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE,kBAAkB,IAAI,GAAG,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC;QAAE,OAAO,SAAS,CAAC;IAEzG,MAAM,aAAa,GAAG,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,MAAM,IAAI,GAAG,CAAC,kBAAkB,EAAE,MAAM,IAAI,CAAC,CAAC;IAC1F,MAAM,WAAW,GAAG,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC;IAEpC,MAAM,cAAc,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC;IAChD,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAC3B,cAAc,EACd,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,WAAW,GAAG,WAAW,CAAC,GAAG,aAAa,CAAC,CAAC,CAC9E,CAAC;IACF,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,aAAa,GAAG,WAAW,CAAC,CAAC;IAC9D,MAAM,WAAW,GAAG,WAAW,GAAG,WAAW,CAAC;IAC9C,MAAM,WAAW,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,SAAS,GAAG,YAAY,CAAC,GAAG,WAAW,CAAC,CAAC;IACjH,MAAM,MAAM,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,GAAG,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC;IAC/C,IAAI,MAAM,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,MAAM,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,GAAG,CAAC,IAAI,CAAC,KAAK;QAAE,OAAO,SAAS,CAAC;IAEnF,OAAO;QACN,MAAM;QACN,QAAQ,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;QACpB,WAAW;QACX,QAAQ,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,WAAW;QAClC,WAAW;QACX,YAAY;KACZ,CAAC;AACH,CAAC;AAED,SAAS,cAAc,CAAC,GAAc,EAAE,MAAgB,EAAE,UAAkB;IAC3E,MAAM,QAAQ,GAAG,oBAAoB,CAAC,GAAG,CAAC,CAAC;IAC3C,IAAI,CAAC,QAAQ,IAAI,CAAC,GAAG,CAAC,UAAU;QAAE,OAAO;IAEzC,KAAK,IAAI,MAAM,GAAG,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC,WAAW,EAAE,MAAM,EAAE,EAAE,CAAC;QAC9D,MAAM,GAAG,GAAG,QAAQ,CAAC,QAAQ,GAAG,MAAM,CAAC;QACvC,IAAI,GAAG,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,GAAG,CAAC,IAAI,CAAC,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,GAAG,IAAI,MAAM,CAAC,MAAM;YAAE,SAAS;QACzG,MAAM,CAAC,GAAG,CAAC,GAAG,kBAAkB,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,QAAQ,CAAC,MAAM,EAAE,UAAU,EAAE,GAAG,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC;IACjH,CAAC;AACF,CAAC;AAED,SAAS,QAAQ,CAAC,GAAc,EAAE,MAAgB,EAAE,UAAkB;IACrE,IAAI,GAAG,CAAC,KAAK,EAAE,CAAC;QACf,MAAM,MAAM,GAAG,GAAG,CAAC,UAAU,IAAI,CAAC,CAAC;QACnC,KAAK,IAAI,QAAQ,GAAG,CAAC,EAAE,QAAQ,GAAG,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,EAAE,EAAE,CAAC;YAC/D,MAAM,GAAG,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,QAAQ,CAAC;YAClC,IAAI,GAAG,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,GAAG,CAAC,IAAI,CAAC,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,GAAG,IAAI,MAAM,CAAC,MAAM;gBAAE,SAAS;YACzG,MAAM,UAAU,GAAG,GAAG,CAAC,KAAK,CAAC,MAAM,GAAG,QAAQ,CAAC,CAAC;YAChD,IAAI,UAAU,KAAK,SAAS;gBAAE,SAAS;YACvC,IAAI,IAAI,GAAG,UAAU,CAAC,OAAO,CAAC,kBAAkB,EAAE,EAAE,CAAC,CAAC;YACtD,MAAM,aAAa,GAAG,qBAAqB,CAAC,IAAI,CAAC,CAAC;YAClD,IAAI,aAAa,EAAE,CAAC;gBACnB,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;gBACzE,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,aAAa,CAAC,IAAI,EAAE,UAAU,GAAG,GAAG,CAAC,CAAC;gBACnE,IAAI,WAAW,GAAG,aAAa,CAAC,IAAI;oBAAE,IAAI,GAAG,kBAAkB,CAAC,IAAI,EAAE,CAAC,EAAE,WAAW,CAAC,CAAC;YACvF,CAAC;YACD,IAAI,WAAW,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,KAAK,IAAI,UAAU;gBAAE,MAAM,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;;gBACzF,MAAM,CAAC,GAAG,CAAC,GAAG,gBAAgB,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC,EAAE,GAAG,CAAC,IAAI,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;QACtG,CAAC;IACF,CAAC;IACD,KAAK,MAAM,KAAK,IAAI,GAAG,CAAC,QAAQ;QAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC;IAEtE,IAAI,GAAG,CAAC,UAAU,IAAI,GAAG,CAAC,kBAAkB,IAAI,GAAG,CAAC,UAAU,CAAC,SAAS,GAAG,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACrG,KAAK,IAAI,QAAQ,GAAG,GAAG,CAAC,UAAU,CAAC,SAAS,GAAG,CAAC,EAAE,QAAQ,IAAI,CAAC,EAAE,QAAQ,EAAE,EAAE,CAAC;YAC7E,MAAM,SAAS,GAAG,GAAG,CAAC,kBAAkB,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;YACzD,MAAM,QAAQ,GAAG,qBAAqB,CAAC,SAAS,CAAC,CAAC;YAClD,IAAI,QAAQ,EAAE,CAAC;gBACd,MAAM,UAAU,GAAG,GAAG,CAAC,UAAU,CAAC,SAAS,GAAG,QAAQ,CAAC;gBACvD,IAAI,UAAU,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC;oBAChC,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,IAAI,GAAG,UAAU,CAAC,CAAC;oBAC1E,MAAM,OAAO,GAAG,kBAAkB,CAAC,SAAS,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC;oBACvE,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,KAAK,IAAI,UAAU;wBAAE,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC;gBACpF,CAAC;gBACD,MAAM;YACP,CAAC;YACD,IAAI,SAAS,KAAK,EAAE;gBAAE,MAAM;QAC7B,CAAC;IACF,CAAC;IAED,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC;AACzC,CAAC;AAED,MAAM,UAAU,iBAAiB,CAChC,IAAe,EACf,KAAa,EACb,MAAc,EACd,aAAyB;IAEzB,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;IACjD,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;IACnD,MAAM,OAAO,GAAkB;QAC9B,QAAQ,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE;QAClD,WAAW,EAAE,IAAI,GAAG,EAAE;QACtB,aAAa;QACb,iBAAiB,EAAE,SAAS;KAC5B,CAAC;IACF,MAAM,OAAO,GAAG,eAAe,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,EAAE,SAAS,EAAE,UAAU,EAAE;QAC3E,CAAC,EAAE,CAAC;QACJ,CAAC,EAAE,CAAC;QACJ,KAAK,EAAE,SAAS;QAChB,MAAM,EAAE,UAAU;KAClB,CAAC,CAAC;IACH,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;IAC3D,QAAQ,CAAC,OAAO,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC;IACpC,OAAO;QACN,IAAI,EAAE,OAAO;QACb,KAAK,EAAE,SAAS;QAChB,MAAM,EAAE,UAAU;QAClB,KAAK;QACL,GAAG,CAAC,OAAO,CAAC,iBAAiB,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,iBAAiB,EAAE,OAAO,CAAC,iBAAiB,EAAE,CAAC;KACpG,CAAC;AACH,CAAC;AAED,SAAS,aAAa,CAAC,IAAgB,EAAE,CAAS,EAAE,CAAS;IAC5D,OAAO,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC;AAC1F,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,KAAkB,EAAE,UAAsB;IAC1E,MAAM,KAAK,GAAG,CAAC,GAAc,EAAyB,EAAE;QACvD,IAAI,GAAG,CAAC,UAAU,KAAK,UAAU;YAAE,OAAO,GAAG,CAAC;QAC9C,KAAK,MAAM,KAAK,IAAI,GAAG,CAAC,QAAQ,EAAE,CAAC;YAClC,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC;YAC3B,IAAI,KAAK;gBAAE,OAAO,KAAK,CAAC;QACzB,CAAC;QACD,OAAO,SAAS,CAAC;IAClB,CAAC,CAAC;IACF,OAAO,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,KAAkB,EAAE,CAAS,EAAE,CAAS;IACxE,MAAM,MAAM,GAAqD,EAAE,CAAC;IACpE,MAAM,KAAK,GAAG,CAAC,GAAc,EAAE,KAAa,EAAQ,EAAE;QACrD,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC;YAAE,OAAO;QAC3C,IAAI,GAAG,CAAC,UAAU,IAAI,aAAa,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC;YAAE,MAAM,CAAC,IAAI,CAAC,EAAE,UAAU,EAAE,GAAG,CAAC,UAAU,EAAE,KAAK,EAAE,CAAC,CAAC;QACxG,KAAK,MAAM,KAAK,IAAI,GAAG,CAAC,QAAQ;YAAE,KAAK,CAAC,KAAK,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC;IAC3D,CAAC,CAAC;IACF,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IACrB,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;IACzC,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;AAChD,CAAC","sourcesContent":["import type { ScrollView } from \"./components/scroll-view.ts\";\nimport { allocateStackSizes, visibleStackEntries } from \"./components/stack.ts\";\nimport { getLayoutNode } from \"./layout-node.ts\";\nimport { cropKittyImageLine, getKittyImageMetadata, isImageLine } from \"./terminal-image.ts\";\nimport { type Component, CURSOR_MARKER, compositeTuiLine } from \"./tui.ts\";\nimport { extractAnsiCode, getGraphemeCellRange, sliceByColumn, visibleWidth } from \"./utils.ts\";\n\nconst OSC133_ZONE_PREFIX = /^(?:\\x1b\\]133;[ABC](?:\\x07|\\x1b\\\\))+/;\n\nexport interface LayoutRect {\n\tx: number;\n\ty: number;\n\twidth: number;\n\theight: number;\n}\n\nexport interface LayoutBox {\n\tcomponent: Component;\n\trect: LayoutRect;\n\tclip: LayoutRect;\n\tchildren: LayoutBox[];\n\tparent?: LayoutBox;\n\tlines?: readonly string[];\n\tlineOffset?: number;\n\tscrollView?: ScrollView;\n\tscrollContentLines?: readonly string[];\n\tlayer: number;\n}\n\nexport interface LayoutFrame {\n\troot: LayoutBox;\n\twidth: number;\n\theight: number;\n\tlines: string[];\n\tprimaryScrollView?: ScrollView;\n}\n\nexport interface ScrollbarGeometry {\n\tcolumn: number;\n\ttrackTop: number;\n\ttrackHeight: number;\n\tthumbTop: number;\n\tthumbHeight: number;\n\tmaxScrollTop: number;\n}\n\ninterface LayoutContext {\n\tviewport: { width: number; height: number };\n\trenderCache: Map<Component, Map<number, string[]>>;\n\trequestRender: () => void;\n\tprimaryScrollView: ScrollView | undefined;\n}\n\nfunction intersect(a: LayoutRect, b: LayoutRect): LayoutRect {\n\tconst x = Math.max(a.x, b.x);\n\tconst y = Math.max(a.y, b.y);\n\tconst right = Math.min(a.x + a.width, b.x + b.width);\n\tconst bottom = Math.min(a.y + a.height, b.y + b.height);\n\treturn { x, y, width: Math.max(0, right - x), height: Math.max(0, bottom - y) };\n}\n\nfunction renderCached(context: LayoutContext, component: Component, width: number): string[] {\n\tconst safeWidth = Math.max(1, Math.floor(width));\n\tlet widths = context.renderCache.get(component);\n\tif (!widths) {\n\t\twidths = new Map<number, string[]>();\n\t\tcontext.renderCache.set(component, widths);\n\t}\n\tlet lines = widths.get(safeWidth);\n\tif (!lines) {\n\t\tlines = component.render(safeWidth);\n\t\twidths.set(safeWidth, lines);\n\t}\n\treturn lines;\n}\n\nfunction measureHeight(context: LayoutContext, component: Component, width: number): number {\n\treturn renderCached(context, component, width).length;\n}\n\nfunction measureWidth(context: LayoutContext, component: Component, width: number): number {\n\treturn renderCached(context, component, width).reduce((max, line) => Math.max(max, visibleWidth(line)), 0);\n}\n\nfunction withParent(box: LayoutBox, parent: LayoutBox): LayoutBox {\n\tbox.parent = parent;\n\treturn box;\n}\n\nfunction translateBox(box: LayoutBox, deltaY: number): void {\n\tbox.rect.y += deltaY;\n\tfor (const child of box.children) translateBox(child, deltaY);\n}\n\nfunction updateClips(box: LayoutBox, parentClip: LayoutRect): void {\n\tbox.clip = intersect(parentClip, box.rect);\n\tfor (const child of box.children) updateClips(child, box.clip);\n}\n\nfunction layoutComponent(\n\tcontext: LayoutContext,\n\tcomponent: Component,\n\tx: number,\n\ty: number,\n\twidth: number,\n\theight: number | undefined,\n\tclip: LayoutRect,\n): LayoutBox {\n\tconst safeWidth = Math.max(1, Math.floor(width));\n\tconst node = getLayoutNode(component);\n\tif (!node) {\n\t\tconst lines = renderCached(context, component, safeWidth);\n\t\tconst allocatedHeight = height === undefined ? lines.length : Math.max(0, Math.floor(height));\n\t\tlet lineOffset = 0;\n\t\tif (lines.length > allocatedHeight && allocatedHeight > 0) {\n\t\t\tconst cursorLine = lines.findIndex((line) => line.includes(CURSOR_MARKER));\n\t\t\tif (cursorLine >= allocatedHeight) lineOffset = cursorLine - allocatedHeight + 1;\n\t\t}\n\t\treturn {\n\t\t\tcomponent,\n\t\t\trect: { x, y, width: safeWidth, height: allocatedHeight },\n\t\t\tclip: intersect(clip, { x, y, width: safeWidth, height: allocatedHeight }),\n\t\t\tchildren: [],\n\t\t\tlines,\n\t\t\tlineOffset,\n\t\t\tlayer: 0,\n\t\t};\n\t}\n\n\tif (node.type === \"scroll\") {\n\t\tconst previousScrollTop = node.state.scrollTop;\n\t\tconst contentWidth = node.state.getContentWidth(safeWidth);\n\t\tconst childBox = layoutComponent(\n\t\t\tcontext,\n\t\t\tnode.component,\n\t\t\tx,\n\t\t\ty - previousScrollTop,\n\t\t\tcontentWidth,\n\t\t\tundefined,\n\t\t\tclip,\n\t\t);\n\t\tconst contentHeight = childBox.rect.height;\n\t\tconst viewportHeight = height === undefined ? contentHeight : Math.max(0, Math.floor(height));\n\t\tnode.state.updateLayout(contentHeight, viewportHeight, context.requestRender);\n\t\ttranslateBox(childBox, previousScrollTop - node.state.scrollTop);\n\t\tconst scrollView = node.state as ScrollView;\n\t\tif (node.state.primary || !context.primaryScrollView) context.primaryScrollView = scrollView;\n\t\tconst rect = { x, y, width: safeWidth, height: viewportHeight };\n\t\tconst childClip = intersect(clip, rect);\n\t\tconst box: LayoutBox = {\n\t\t\tcomponent,\n\t\t\trect,\n\t\t\tclip: childClip,\n\t\t\tchildren: [childBox],\n\t\t\tscrollView,\n\t\t\tscrollContentLines: renderCached(context, node.component, contentWidth),\n\t\t\tlayer: 0,\n\t\t};\n\t\tchildBox.parent = box;\n\t\tupdateClips(childBox, childClip);\n\t\treturn box;\n\t}\n\n\tconst entries = visibleStackEntries(node.entries, context.viewport);\n\tconst gapTotal = Math.max(0, entries.length - 1) * node.gap;\n\tif (node.type === \"vstack\") {\n\t\tconst intrinsicHeights = entries.map((entry) => measureHeight(context, entry.component, safeWidth));\n\t\tconst sizes = allocateStackSizes(entries, intrinsicHeights, height, node.gap);\n\t\tconst naturalHeight = sizes.reduce((sum, size) => sum + size, 0) + gapTotal;\n\t\tconst allocatedHeight = height === undefined ? naturalHeight : Math.max(0, Math.floor(height));\n\t\tconst rect = { x, y, width: safeWidth, height: allocatedHeight };\n\t\tconst box: LayoutBox = {\n\t\t\tcomponent,\n\t\t\trect,\n\t\t\tclip: intersect(clip, rect),\n\t\t\tchildren: [],\n\t\t\tlayer: 0,\n\t\t};\n\t\tlet childY = y;\n\t\tfor (let index = 0; index < entries.length; index++) {\n\t\t\tbox.children.push(\n\t\t\t\twithParent(\n\t\t\t\t\tlayoutComponent(context, entries[index]!.component, x, childY, safeWidth, sizes[index]!, box.clip),\n\t\t\t\t\tbox,\n\t\t\t\t),\n\t\t\t);\n\t\t\tchildY += sizes[index]! + node.gap;\n\t\t}\n\t\treturn box;\n\t}\n\n\tconst intrinsicWidths = entries.map((entry) => measureWidth(context, entry.component, safeWidth));\n\tconst widths = allocateStackSizes(entries, intrinsicWidths, safeWidth, node.gap);\n\tconst intrinsicHeights = entries.map((entry, index) =>\n\t\tmeasureHeight(context, entry.component, Math.max(1, widths[index]!)),\n\t);\n\tconst allocatedHeight =\n\t\theight === undefined\n\t\t\t? intrinsicHeights.reduce((max, childHeight) => Math.max(max, childHeight), 0)\n\t\t\t: Math.max(0, height);\n\tconst rect = { x, y, width: safeWidth, height: allocatedHeight };\n\tconst box: LayoutBox = {\n\t\tcomponent,\n\t\trect,\n\t\tclip: intersect(clip, rect),\n\t\tchildren: [],\n\t\tlayer: 0,\n\t};\n\tlet childX = x;\n\tfor (let index = 0; index < entries.length; index++) {\n\t\tconst naturalChildHeight = intrinsicHeights[index]!;\n\t\tconst childHeight = node.align === \"stretch\" ? allocatedHeight : Math.min(allocatedHeight, naturalChildHeight);\n\t\tlet childY = y;\n\t\tif (node.align === \"center\") childY += Math.floor((allocatedHeight - childHeight) / 2);\n\t\telse if (node.align === \"end\") childY += allocatedHeight - childHeight;\n\t\tconst childWidth = widths[index]!;\n\t\tif (childWidth === 0) {\n\t\t\tbox.children.push({\n\t\t\t\tcomponent: entries[index]!.component,\n\t\t\t\trect: { x: childX, y: childY, width: 0, height: childHeight },\n\t\t\t\tclip: { x: childX, y: childY, width: 0, height: 0 },\n\t\t\t\tchildren: [],\n\t\t\t\tparent: box,\n\t\t\t\tlayer: 0,\n\t\t\t});\n\t\t} else {\n\t\t\tbox.children.push(\n\t\t\t\twithParent(\n\t\t\t\t\tlayoutComponent(context, entries[index]!.component, childX, childY, childWidth, childHeight, box.clip),\n\t\t\t\t\tbox,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t\tchildX += childWidth + node.gap;\n\t}\n\treturn box;\n}\n\nfunction styleScrollbarCell(line: string, column: number, totalWidth: number, style: (text: string) => string): string {\n\tif (isImageLine(line)) return line;\n\n\tconst graphemeRange = getGraphemeCellRange(line, column);\n\tconst start = graphemeRange?.start ?? column;\n\tconst end = graphemeRange?.end ?? column + 1;\n\tconst before = sliceByColumn(line, 0, start, true);\n\tconst target = sliceByColumn(line, start, end - start, true);\n\tconst after = sliceByColumn(line, end, Math.max(0, totalWidth - end), true);\n\n\tlet targetPrefix = \"\";\n\tlet targetIndex = 0;\n\twhile (targetIndex < target.length) {\n\t\tconst ansi = extractAnsiCode(target, targetIndex);\n\t\tif (!ansi) break;\n\t\ttargetPrefix += ansi.code;\n\t\ttargetIndex += ansi.length;\n\t}\n\tconst targetText = target.slice(targetIndex) || \" \".repeat(end - start);\n\tconst beforePadding = \" \".repeat(Math.max(0, start - visibleWidth(before)));\n\treturn `${before}${beforePadding}${targetPrefix}${style(targetText)}${after}`;\n}\n\nexport function getScrollbarGeometry(box: LayoutBox): ScrollbarGeometry | undefined {\n\tif (!box.scrollView?.isScrollbarVisible || box.rect.width <= 0 || box.rect.height <= 0) return undefined;\n\n\tconst contentHeight = box.children[0]?.rect.height ?? box.scrollContentLines?.length ?? 0;\n\tconst trackHeight = box.rect.height;\n\n\tconst minThumbHeight = Math.min(2, trackHeight);\n\tconst thumbHeight = Math.max(\n\t\tminThumbHeight,\n\t\tMath.min(trackHeight, Math.round((trackHeight * trackHeight) / contentHeight)),\n\t);\n\tconst maxScrollTop = Math.max(0, contentHeight - trackHeight);\n\tconst maxThumbTop = trackHeight - thumbHeight;\n\tconst thumbOffset = maxScrollTop === 0 ? 0 : Math.round((box.scrollView.scrollTop / maxScrollTop) * maxThumbTop);\n\tconst column = box.rect.x + box.rect.width - 1;\n\tif (column < box.clip.x || column >= box.clip.x + box.clip.width) return undefined;\n\n\treturn {\n\t\tcolumn,\n\t\ttrackTop: box.rect.y,\n\t\ttrackHeight,\n\t\tthumbTop: box.rect.y + thumbOffset,\n\t\tthumbHeight,\n\t\tmaxScrollTop,\n\t};\n}\n\nfunction paintScrollbar(box: LayoutBox, screen: string[], totalWidth: number): void {\n\tconst geometry = getScrollbarGeometry(box);\n\tif (!geometry || !box.scrollView) return;\n\n\tfor (let offset = 0; offset < geometry.thumbHeight; offset++) {\n\t\tconst row = geometry.thumbTop + offset;\n\t\tif (row < box.clip.y || row >= box.clip.y + box.clip.height || row < 0 || row >= screen.length) continue;\n\t\tscreen[row] = styleScrollbarCell(screen[row] ?? \"\", geometry.column, totalWidth, box.scrollView.scrollbarStyle);\n\t}\n}\n\nfunction paintBox(box: LayoutBox, screen: string[], totalWidth: number): void {\n\tif (box.lines) {\n\t\tconst offset = box.lineOffset ?? 0;\n\t\tfor (let localRow = 0; localRow < box.rect.height; localRow++) {\n\t\t\tconst row = box.rect.y + localRow;\n\t\t\tif (row < box.clip.y || row >= box.clip.y + box.clip.height || row < 0 || row >= screen.length) continue;\n\t\t\tconst sourceLine = box.lines[offset + localRow];\n\t\t\tif (sourceLine === undefined) continue;\n\t\t\tlet line = sourceLine.replace(OSC133_ZONE_PREFIX, \"\");\n\t\t\tconst imageMetadata = getKittyImageMetadata(line);\n\t\t\tif (imageMetadata) {\n\t\t\t\tconst clipBottom = Math.min(screen.length, box.clip.y + box.clip.height);\n\t\t\t\tconst visibleRows = Math.min(imageMetadata.rows, clipBottom - row);\n\t\t\t\tif (visibleRows < imageMetadata.rows) line = cropKittyImageLine(line, 0, visibleRows);\n\t\t\t}\n\t\t\tif (isImageLine(line) && box.rect.x === 0 && box.rect.width >= totalWidth) screen[row] = line;\n\t\t\telse screen[row] = compositeTuiLine(screen[row] ?? \"\", line, box.rect.x, box.rect.width, totalWidth);\n\t\t}\n\t}\n\tfor (const child of box.children) paintBox(child, screen, totalWidth);\n\n\tif (box.scrollView && box.scrollContentLines && box.scrollView.scrollTop > 0 && box.rect.height > 0) {\n\t\tfor (let imageRow = box.scrollView.scrollTop - 1; imageRow >= 0; imageRow--) {\n\t\t\tconst imageLine = box.scrollContentLines[imageRow] ?? \"\";\n\t\t\tconst metadata = getKittyImageMetadata(imageLine);\n\t\t\tif (metadata) {\n\t\t\t\tconst hiddenRows = box.scrollView.scrollTop - imageRow;\n\t\t\t\tif (hiddenRows < metadata.rows) {\n\t\t\t\t\tconst visibleRows = Math.min(box.rect.height, metadata.rows - hiddenRows);\n\t\t\t\t\tconst cropped = cropKittyImageLine(imageLine, hiddenRows, visibleRows);\n\t\t\t\t\tif (box.rect.x === 0 && box.rect.width >= totalWidth) screen[box.rect.y] = cropped;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (imageLine !== \"\") break;\n\t\t}\n\t}\n\n\tpaintScrollbar(box, screen, totalWidth);\n}\n\nexport function renderLayoutFrame(\n\troot: Component,\n\twidth: number,\n\theight: number,\n\trequestRender: () => void,\n): LayoutFrame {\n\tconst safeWidth = Math.max(1, Math.floor(width));\n\tconst safeHeight = Math.max(1, Math.floor(height));\n\tconst context: LayoutContext = {\n\t\tviewport: { width: safeWidth, height: safeHeight },\n\t\trenderCache: new Map(),\n\t\trequestRender,\n\t\tprimaryScrollView: undefined,\n\t};\n\tconst rootBox = layoutComponent(context, root, 0, 0, safeWidth, safeHeight, {\n\t\tx: 0,\n\t\ty: 0,\n\t\twidth: safeWidth,\n\t\theight: safeHeight,\n\t});\n\tconst lines = Array.from({ length: safeHeight }, () => \"\");\n\tpaintBox(rootBox, lines, safeWidth);\n\treturn {\n\t\troot: rootBox,\n\t\twidth: safeWidth,\n\t\theight: safeHeight,\n\t\tlines,\n\t\t...(context.primaryScrollView === undefined ? {} : { primaryScrollView: context.primaryScrollView }),\n\t};\n}\n\nfunction containsPoint(rect: LayoutRect, x: number, y: number): boolean {\n\treturn x >= rect.x && x < rect.x + rect.width && y >= rect.y && y < rect.y + rect.height;\n}\n\nexport function getScrollViewBox(frame: LayoutFrame, scrollView: ScrollView): LayoutBox | undefined {\n\tconst visit = (box: LayoutBox): LayoutBox | undefined => {\n\t\tif (box.scrollView === scrollView) return box;\n\t\tfor (const child of box.children) {\n\t\t\tconst match = visit(child);\n\t\t\tif (match) return match;\n\t\t}\n\t\treturn undefined;\n\t};\n\treturn visit(frame.root);\n}\n\nexport function getScrollViewsAt(frame: LayoutFrame, x: number, y: number): ScrollView[] {\n\tconst result: Array<{ scrollView: ScrollView; depth: number }> = [];\n\tconst visit = (box: LayoutBox, depth: number): void => {\n\t\tif (!containsPoint(box.clip, x, y)) return;\n\t\tif (box.scrollView && containsPoint(box.rect, x, y)) result.push({ scrollView: box.scrollView, depth });\n\t\tfor (const child of box.children) visit(child, depth + 1);\n\t};\n\tvisit(frame.root, 0);\n\tresult.sort((a, b) => b.depth - a.depth);\n\treturn result.map((entry) => entry.scrollView);\n}\n"]}
|
package/dist/mux.js
CHANGED
|
@@ -5,6 +5,6 @@ export function useLegacyMuxRender() {
|
|
|
5
5
|
return process.env.PI_TUI_LEGACY_MUX_RENDER === "1";
|
|
6
6
|
}
|
|
7
7
|
export function viewportRenderEnabled() {
|
|
8
|
-
return process.env.PI_TUI_VIEWPORT_RENDER
|
|
8
|
+
return process.env.PI_TUI_VIEWPORT_RENDER !== "0";
|
|
9
9
|
}
|
|
10
10
|
//# sourceMappingURL=mux.js.map
|
package/dist/mux.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mux.js","sourceRoot":"","sources":["../src/mux.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,oBAAoB;IACnC,OAAO,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,OAAO,CAAC,GAAG,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;AACpG,CAAC;AAED,MAAM,UAAU,kBAAkB;IACjC,OAAO,OAAO,CAAC,GAAG,CAAC,wBAAwB,KAAK,GAAG,CAAC;AACrD,CAAC;AAED,MAAM,UAAU,qBAAqB;IACpC,OAAO,OAAO,CAAC,GAAG,CAAC,sBAAsB,KAAK,GAAG,CAAC;AACnD,CAAC","sourcesContent":["export function isMultiplexerSession(): boolean {\n\treturn Boolean(process.env.TMUX || process.env.TMUX_PANE || process.env.STY || process.env.ZELLIJ);\n}\n\nexport function useLegacyMuxRender(): boolean {\n\treturn process.env.PI_TUI_LEGACY_MUX_RENDER === \"1\";\n}\n\nexport function viewportRenderEnabled(): boolean {\n\treturn process.env.PI_TUI_VIEWPORT_RENDER
|
|
1
|
+
{"version":3,"file":"mux.js","sourceRoot":"","sources":["../src/mux.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,oBAAoB;IACnC,OAAO,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,OAAO,CAAC,GAAG,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;AACpG,CAAC;AAED,MAAM,UAAU,kBAAkB;IACjC,OAAO,OAAO,CAAC,GAAG,CAAC,wBAAwB,KAAK,GAAG,CAAC;AACrD,CAAC;AAED,MAAM,UAAU,qBAAqB;IACpC,OAAO,OAAO,CAAC,GAAG,CAAC,sBAAsB,KAAK,GAAG,CAAC;AACnD,CAAC","sourcesContent":["export function isMultiplexerSession(): boolean {\n\treturn Boolean(process.env.TMUX || process.env.TMUX_PANE || process.env.STY || process.env.ZELLIJ);\n}\n\nexport function useLegacyMuxRender(): boolean {\n\treturn process.env.PI_TUI_LEGACY_MUX_RENDER === \"1\";\n}\n\nexport function viewportRenderEnabled(): boolean {\n\treturn process.env.PI_TUI_VIEWPORT_RENDER !== \"0\";\n}\n"]}
|
package/dist/terminal-image.d.ts
CHANGED
|
@@ -87,6 +87,14 @@ export interface ImageCellSize {
|
|
|
87
87
|
columns: number;
|
|
88
88
|
rows: number;
|
|
89
89
|
}
|
|
90
|
+
export interface KittyImageMetadata extends ImageCellSize {
|
|
91
|
+
imageId: number;
|
|
92
|
+
widthPx: number;
|
|
93
|
+
heightPx: number;
|
|
94
|
+
}
|
|
95
|
+
export declare function registerKittyImageMetadata(metadata: KittyImageMetadata): void;
|
|
96
|
+
export declare function getKittyImageMetadata(line: string): KittyImageMetadata | undefined;
|
|
97
|
+
export declare function cropKittyImageLine(line: string, hiddenRows: number, visibleRows: number): string;
|
|
90
98
|
export declare function calculateImageCellSize(imageDimensions: ImageDimensions, maxWidthCells: number, maxHeightCells?: number, cellDimensions?: CellDimensions): ImageCellSize;
|
|
91
99
|
export declare function getPngDimensions(base64Data: string): ImageDimensions | null;
|
|
92
100
|
export declare function getJpegDimensions(base64Data: string): ImageDimensions | null;
|
|
@@ -95,6 +103,7 @@ export declare function getWebpDimensions(base64Data: string): ImageDimensions |
|
|
|
95
103
|
export declare function getImageDimensions(base64Data: string, mimeType: string): ImageDimensions | null;
|
|
96
104
|
export declare function renderImage(base64Data: string, imageDimensions: ImageDimensions, options?: ImageRenderOptions): {
|
|
97
105
|
sequence: string;
|
|
106
|
+
columns: number;
|
|
98
107
|
rows: number;
|
|
99
108
|
imageId?: number;
|
|
100
109
|
lines?: string[];
|
|
@@ -110,4 +119,5 @@ export declare function renderImage(base64Data: string, imageDimensions: ImageDi
|
|
|
110
119
|
* @param url - The URL to link to
|
|
111
120
|
*/
|
|
112
121
|
export declare function hyperlink(text: string, url: string): string;
|
|
122
|
+
export declare function imageFallback(mimeType: string, dimensions?: ImageDimensions, filename?: string): string;
|
|
113
123
|
//# sourceMappingURL=terminal-image.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"terminal-image.d.ts","sourceRoot":"","sources":["../src/terminal-image.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"terminal-image.d.ts","sourceRoot":"","sources":["../src/terminal-image.ts"],"names":[],"mappings":"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"}
|
package/dist/terminal-image.js
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
|
+
import { isAbsolute } from "node:path";
|
|
2
|
+
import { pathToFileURL } from "node:url";
|
|
1
3
|
import { detectTerminalCapabilities, } from "./terminal-capabilities.js";
|
|
4
|
+
import { sanitizeTerminalLabel, shortenImagePath } from "./terminal-text.js";
|
|
2
5
|
export { outerKittyGraphicsMode } from "./terminal-capabilities.js";
|
|
3
6
|
let cachedCapabilities = null;
|
|
4
7
|
// Default cell dimensions - updated by TUI when terminal responds to query
|
|
@@ -203,6 +206,38 @@ export function encodeITerm2(base64Data, options = {}) {
|
|
|
203
206
|
}
|
|
204
207
|
return `\x1b]1337;File=${params.join(";")}:${base64Data}\x07`;
|
|
205
208
|
}
|
|
209
|
+
const kittyImageMetadata = new Map();
|
|
210
|
+
export function registerKittyImageMetadata(metadata) {
|
|
211
|
+
kittyImageMetadata.delete(metadata.imageId);
|
|
212
|
+
kittyImageMetadata.set(metadata.imageId, metadata);
|
|
213
|
+
if (kittyImageMetadata.size > 1000) {
|
|
214
|
+
const oldestImageId = kittyImageMetadata.keys().next().value;
|
|
215
|
+
if (oldestImageId !== undefined)
|
|
216
|
+
kittyImageMetadata.delete(oldestImageId);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
export function getKittyImageMetadata(line) {
|
|
220
|
+
const controls = /\x1b_G([^;]*);/.exec(line)?.[1];
|
|
221
|
+
if (!controls)
|
|
222
|
+
return undefined;
|
|
223
|
+
const imageId = /(?:^|,)i=(\d+)(?:,|$)/.exec(controls)?.[1];
|
|
224
|
+
return imageId === undefined ? undefined : kittyImageMetadata.get(Number.parseInt(imageId, 10));
|
|
225
|
+
}
|
|
226
|
+
export function cropKittyImageLine(line, hiddenRows, visibleRows) {
|
|
227
|
+
const metadata = getKittyImageMetadata(line);
|
|
228
|
+
const match = /\x1b_G([^;]*);/.exec(line);
|
|
229
|
+
if (!metadata || !match || hiddenRows < 0 || hiddenRows >= metadata.rows || visibleRows <= 0)
|
|
230
|
+
return line;
|
|
231
|
+
const croppedRows = Math.min(visibleRows, metadata.rows - hiddenRows);
|
|
232
|
+
if (hiddenRows === 0 && croppedRows === metadata.rows)
|
|
233
|
+
return line;
|
|
234
|
+
const sourceY = Math.floor((metadata.heightPx * hiddenRows) / metadata.rows);
|
|
235
|
+
const sourceEnd = Math.ceil((metadata.heightPx * (hiddenRows + croppedRows)) / metadata.rows);
|
|
236
|
+
const sourceHeight = Math.max(1, Math.min(metadata.heightPx, sourceEnd) - sourceY);
|
|
237
|
+
const controls = match[1].split(",").filter((control) => !/^[yhr]=/.test(control));
|
|
238
|
+
controls.push(`y=${sourceY}`, `h=${sourceHeight}`, `r=${croppedRows}`);
|
|
239
|
+
return `${line.slice(0, match.index)}\x1b_G${controls.join(",")};${line.slice(match.index + match[0].length)}`;
|
|
240
|
+
}
|
|
206
241
|
export function calculateImageCellSize(imageDimensions, maxWidthCells, maxHeightCells, cellDimensions = { widthPx: 9, heightPx: 18 }) {
|
|
207
242
|
const maxWidth = Math.max(1, Math.floor(maxWidthCells));
|
|
208
243
|
const maxHeight = maxHeightCells === undefined ? undefined : Math.max(1, Math.floor(maxHeightCells));
|
|
@@ -366,16 +401,25 @@ export function renderImage(base64Data, imageDimensions, options = {}) {
|
|
|
366
401
|
const placeholderRow = buildKittyPlaceholderRow(imageId, row, columns);
|
|
367
402
|
lines.push(row === 0 ? sequence + placeholderRow : placeholderRow);
|
|
368
403
|
}
|
|
369
|
-
return { sequence, rows, imageId, lines };
|
|
404
|
+
return { sequence, columns, rows, imageId, lines };
|
|
370
405
|
}
|
|
371
406
|
if (caps.images === "kitty") {
|
|
407
|
+
if (options.imageId !== undefined) {
|
|
408
|
+
registerKittyImageMetadata({
|
|
409
|
+
imageId: options.imageId,
|
|
410
|
+
columns: size.columns,
|
|
411
|
+
rows: size.rows,
|
|
412
|
+
widthPx: imageDimensions.widthPx,
|
|
413
|
+
heightPx: imageDimensions.heightPx,
|
|
414
|
+
});
|
|
415
|
+
}
|
|
372
416
|
const sequence = encodeKitty(base64Data, {
|
|
373
417
|
columns: size.columns,
|
|
374
418
|
rows: size.rows,
|
|
375
419
|
imageId: options.imageId,
|
|
376
420
|
moveCursor: options.moveCursor,
|
|
377
421
|
});
|
|
378
|
-
return { sequence, rows: size.rows, imageId: options.imageId };
|
|
422
|
+
return { sequence, columns: size.columns, rows: size.rows, imageId: options.imageId };
|
|
379
423
|
}
|
|
380
424
|
if (caps.images === "iterm2") {
|
|
381
425
|
const sequence = encodeITerm2(base64Data, {
|
|
@@ -383,7 +427,7 @@ export function renderImage(base64Data, imageDimensions, options = {}) {
|
|
|
383
427
|
height: "auto",
|
|
384
428
|
preserveAspectRatio: options.preserveAspectRatio ?? true,
|
|
385
429
|
});
|
|
386
|
-
return { sequence, rows: size.rows };
|
|
430
|
+
return { sequence, columns: size.columns, rows: size.rows };
|
|
387
431
|
}
|
|
388
432
|
return null;
|
|
389
433
|
}
|
|
@@ -400,4 +444,18 @@ export function renderImage(base64Data, imageDimensions, options = {}) {
|
|
|
400
444
|
export function hyperlink(text, url) {
|
|
401
445
|
return `\x1b]8;;${url}\x1b\\${text}\x1b]8;;\x1b\\`;
|
|
402
446
|
}
|
|
447
|
+
export function imageFallback(mimeType, dimensions, filename) {
|
|
448
|
+
const parts = [];
|
|
449
|
+
if (filename) {
|
|
450
|
+
const sanitized = sanitizeTerminalLabel(filename);
|
|
451
|
+
const display = shortenImagePath(sanitized);
|
|
452
|
+
parts.push(getCapabilities().hyperlinks && isAbsolute(sanitized)
|
|
453
|
+
? hyperlink(display, pathToFileURL(sanitized).href)
|
|
454
|
+
: display);
|
|
455
|
+
}
|
|
456
|
+
parts.push(`[${sanitizeTerminalLabel(mimeType)}]`);
|
|
457
|
+
if (dimensions)
|
|
458
|
+
parts.push(`${dimensions.widthPx}x${dimensions.heightPx}`);
|
|
459
|
+
return `[Image: ${parts.join(" ")}]`;
|
|
460
|
+
}
|
|
403
461
|
//# sourceMappingURL=terminal-image.js.map
|