@alchemy.run/sigil 0.0.0-alpha.5 → 0.0.0-alpha.7

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 (46) hide show
  1. package/README.md +1 -1
  2. package/dist/{Text-D5HUf3Fj.d.ts → Text-DV9CuzAT.d.ts} +3 -3
  3. package/dist/ansi.d.ts +1 -1
  4. package/dist/ansi.js +2 -2
  5. package/dist/capabilities.d.ts +4 -4
  6. package/dist/capabilities.js +2 -2
  7. package/dist/{color-policy-BMzMwV7Q.d.ts → color-policy-CCxuHIdD.d.ts} +2 -2
  8. package/dist/{color-policy-SVj1pYTA.js → color-policy-DlrZXC0f.js} +31 -13
  9. package/dist/{color-profile-u0Nhe9Nv.d.ts → color-profile-CyeHnG1T.d.ts} +1 -1
  10. package/dist/color.d.ts +2 -2
  11. package/dist/{detect-BuTXtY6e.js → detect-B3dL4Q11.js} +3 -2
  12. package/dist/{detect-Bh4yGP6w.d.ts → detect-Db6GbKOm.d.ts} +9 -0
  13. package/dist/{index-Bmc2tRPk.d.ts → index-D48vQhhe.d.ts} +2 -2
  14. package/dist/index.d.ts +10 -6
  15. package/dist/index.js +85 -72
  16. package/dist/{osc-CCH7xDoS.js → osc-BFKKSqpg.js} +1 -1
  17. package/dist/{paint-C19minOS.d.ts → paint-Cx-zC_sX.d.ts} +2 -2
  18. package/dist/{query-vaIeGOkH.d.ts → query-BNc2B8GD.d.ts} +1 -1
  19. package/dist/router.d.ts +1 -1
  20. package/dist/router.js +1 -1
  21. package/dist/{screen-BReKIheE.d.ts → screen-CgC2WlVM.d.ts} +12 -3
  22. package/dist/{screen-BOh__-65.js → screen-CiPytswf.js} +30 -12
  23. package/dist/screen.d.ts +3 -3
  24. package/dist/screen.js +1 -1
  25. package/dist/{session-BJmzX2NJ.js → session-Cg6STjFV.js} +45 -9
  26. package/dist/{store-CgrG9K4y.d.ts → store-C1P5fOUi.d.ts} +1 -1
  27. package/dist/terminal.d.ts +8 -5
  28. package/dist/terminal.js +1 -1
  29. package/dist/{use-focus-C2sciZOo.js → use-focus-DSV01Ulb.js} +3 -1
  30. package/package.json +1 -1
  31. package/src/capabilities/detect.ts +15 -1
  32. package/src/capabilities/store.ts +17 -2
  33. package/src/components/Text.tsx +1 -1
  34. package/src/dom.ts +6 -0
  35. package/src/hooks/use-window-size.ts +8 -19
  36. package/src/ink.tsx +93 -23
  37. package/src/paint-tree.ts +7 -3
  38. package/src/screen/canvas.ts +49 -26
  39. package/src/screen/screen.ts +45 -12
  40. package/src/structured-text.ts +4 -0
  41. package/src/styles.ts +7 -1
  42. package/src/terminal/screen-presenter.ts +62 -8
  43. package/src/terminal/session.ts +3 -2
  44. package/src/testing/terminal.ts +15 -3
  45. package/src/wrap-text.ts +4 -0
  46. package/src/utils.ts +0 -40
package/README.md CHANGED
@@ -2254,7 +2254,7 @@ Type: `number`
2254
2254
  Number of rows (vertical character cells).
2255
2255
 
2256
2256
  > [!NOTE]
2257
- > When the terminal is resized narrower, ghost lines may briefly appear depending on the terminal emulator's reflow behavior.
2257
+ > On terminals that send in-band size reports (mode 2048, e.g. Ghostty, kitty, foot) the frame is repainted as soon as the report arrives, since the emulator has already rewrapped by then. Elsewhere the size comes from the PTY, which can run ahead of or behind the emulator, so resize events are coalesced: the frame is erased and repainted about 50 ms after the size stops changing and is briefly absent during a window drag. Painting mid-rewrap is what leaves ghost rows behind.
2258
2258
 
2259
2259
  ### useFocus(options?)
2260
2260
 
@@ -1,4 +1,4 @@
1
- import { s as Paint } from "./paint-C19minOS.js";
1
+ import { s as Paint } from "./paint-Cx-zC_sX.js";
2
2
  import { ReactNode } from "react";
3
3
  //#region src/glyphs.d.ts
4
4
  declare const BOXES: {
@@ -100,7 +100,7 @@ type BoxGlyphs = {
100
100
  //#endregion
101
101
  //#region src/styles.d.ts
102
102
  type Styles = {
103
- readonly textWrap?: "wrap" | "hard" | "truncate-end" | "truncate" | "truncate-middle" | "truncate-start";
103
+ readonly textWrap?: "wrap" | "hard" | "truncate-end" | "truncate" | "truncate-middle" | "truncate-start" | "none";
104
104
  /**
105
105
  Controls how the element is positioned.
106
106
 
@@ -439,7 +439,7 @@ type Props = {
439
439
  */
440
440
  readonly inverse?: boolean;
441
441
  /**
442
- This property tells Ink to wrap or truncate text if its width is larger than the container. If `wrap` is passed (the default), Ink will wrap text and split it into multiple lines. If `hard` is passed, Ink will fill each line to the full column width, breaking words as necessary. If `truncate-*` is passed, Ink will truncate text instead, resulting in one line of text with the rest cut off.
442
+ This property tells Ink to wrap or truncate text if its width is larger than the container. If `wrap` is passed (the default), Ink will wrap text and split it into multiple lines. If `hard` is passed, Ink will fill each line to the full column width, breaking words as necessary. If `truncate-*` is passed, Ink will truncate text instead, resulting in one line of text with the rest cut off. If `none` is passed, the text is neither wrapped nor truncated — it overflows the container (and the screen's nominal width), which is intended for log lines committed to scrollback (e.g. inside `<Static>`), not for live regions.
443
443
  */
444
444
  readonly wrap?: Styles["textWrap"];
445
445
  readonly children?: ReactNode;
package/dist/ansi.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { i as ColorSupportLevel, n as ColorInfo } from "./detect-Bh4yGP6w.js";
1
+ import { i as ColorSupportLevel, n as ColorInfo } from "./detect-Db6GbKOm.js";
2
2
  import { A as exitAlternativeScreen, C as enableBracketedPaste, D as eraseLines, E as eraseLine, F as popKittyKeyboard, I as pushKittyKeyboard, L as resetCursorColor, M as link, N as pasteEnd, O as eraseScreen, P as pasteStart, S as disableBracketedPaste, T as eraseEndLine, _ as cursorNextLine, a as CursorShape, b as cursorTo, c as OSC, d as bsu, f as clearTerminal, g as cursorLeft, h as cursorHide, i as CSI, j as kittyQuery, k as esu, l as ST, m as cursorDown, n as C1_CSI, o as DEL, p as cursorColor, r as C1_ST, s as ESC, t as BEL, u as ansiEscapes, v as cursorShape, w as enterAlternativeScreen, x as cursorUp, y as cursorShow } from "./escapes-CB_6CWOE.js";
3
3
  import { a as queryClipboard, c as setTerminalProgress, d as tmuxPassthrough, i as notify, l as setWindowTitle, n as TerminalProgressState, o as setClipboard, r as clearClipboard, s as setPointerShape, t as ClipboardSelection, u as setWorkingDirectory } from "./osc-Cn0fw77g.js";
4
4
  import { _ as tokenize, a as StyledChar, c as diffAnsiCodes, d as getLinkStartCode, f as isIntensityCode, g as styledCharsToString, h as styledCharsFromTokens, i as ControlToken, l as endCodesSet, m as reduceAnsiCodesIncremental, n as AnsiToken, o as Token, p as reduceAnsiCodes, r as CharToken, s as ansiCodesToString, t as AnsiCode, u as getEndCode, v as undoAnsiCodes } from "./tokenize-Dx1y_l5H.js";
package/dist/ansi.js CHANGED
@@ -2,8 +2,8 @@ import { A as cursorShape, B as eraseScreen, C as bsu, D as cursorHide, E as cur
2
2
  import { A as isFullwidthCodePoint, C as fullwidthRanges, D as halfwidthRanges, E as halfwidthMinimalCodePoint, F as narrowMinimalCodePoint, I as narrowRanges, L as wideMaximumCodePoint, M as isWide, N as isWideNotCJKTNotEmoji, O as isAmbiguous, P as narrowMaximumCodePoint, R as wideMinimalCodePoint, S as fullwidthMinimalCodePoint, T as halfwidthMaximumCodePoint, _ as ambiguousMinimalCodePoint, a as getLinkStartCode, b as eastAsianWidthType, c as reduceAnsiCodesIncremental, d as tokenize, f as undoAnsiCodes, g as ambiguousMaximumCodePoint, i as getEndCode, j as isFullwidthGrapheme, k as isFullWidth, l as styledCharsFromTokens, n as diffAnsiCodes, o as isIntensityCode, r as endCodesSet, s as reduceAnsiCodes, t as ansiCodesToString, u as styledCharsToString, v as ambiguousRanges, w as getCategory, x as fullwidthMaximumCodePoint, y as eastAsianWidth, z as wideRanges } from "./tokenize-AjqbvtiT.js";
3
3
  import { n as widestLine, t as stringWidth } from "./string-width-CijQwpIk.js";
4
4
  import { n as sliceAnsi, r as wrapAnsi, t as cliTruncate } from "./truncate-D31fhU6i.js";
5
- import { i as detectHyperlinkSupport, t as createSupportsColor } from "./detect-BuTXtY6e.js";
6
- import { a as setPointerShape, c as setWorkingDirectory, i as setClipboard, l as tmuxPassthrough, n as notify, o as setTerminalProgress, r as queryClipboard, s as setWindowTitle, t as clearClipboard, u as cliCursor } from "./osc-CCH7xDoS.js";
5
+ import { i as detectHyperlinkSupport, t as createSupportsColor } from "./detect-B3dL4Q11.js";
6
+ import { a as setPointerShape, c as setWorkingDirectory, i as setClipboard, l as tmuxPassthrough, n as notify, o as setTerminalProgress, r as queryClipboard, s as setWindowTitle, t as clearClipboard, u as cliCursor } from "./osc-BFKKSqpg.js";
7
7
  import { t as stripAnsi } from "./strip-BvU4toXG.js";
8
8
  import { isatty } from "node:tty";
9
9
  //#region src/ansi/chalk.ts
@@ -1,5 +1,5 @@
1
- import { a as Multiplexer, c as TerminalAppearance, d as detectCapabilities, f as detectColorLevel, h as detectUnicodeSupport, i as ColorSupportLevel, l as TerminalIdentity, m as detectTerminal, n as ColorInfo, o as PixelGeometry, p as detectHyperlinkSupport, r as ColorSupport, s as RgbColor, t as Capabilities, u as createSupportsColor } from "./detect-Bh4yGP6w.js";
2
- import { a as getTerminalQuery, i as applyTerminalQuery, n as TerminalQueryOptions, o as queryTerminal, r as TerminalQueryResult, s as refreshTerminalQuery, t as PixelSize } from "./query-vaIeGOkH.js";
3
- import { n as capabilities, r as getCapabilities, t as CapabilitiesStore } from "./store-CgrG9K4y.js";
4
- import { i as resolveColorProfile, n as ColorState, r as colorState, t as ColorPolicy } from "./color-policy-BMzMwV7Q.js";
1
+ import { a as Multiplexer, c as TerminalAppearance, d as detectCapabilities, f as detectColorLevel, h as detectUnicodeSupport, i as ColorSupportLevel, l as TerminalIdentity, m as detectTerminal, n as ColorInfo, o as PixelGeometry, p as detectHyperlinkSupport, r as ColorSupport, s as RgbColor, t as Capabilities, u as createSupportsColor } from "./detect-Db6GbKOm.js";
2
+ import { a as getTerminalQuery, i as applyTerminalQuery, n as TerminalQueryOptions, o as queryTerminal, r as TerminalQueryResult, s as refreshTerminalQuery, t as PixelSize } from "./query-BNc2B8GD.js";
3
+ import { n as capabilities, r as getCapabilities, t as CapabilitiesStore } from "./store-C1P5fOUi.js";
4
+ import { i as resolveColorProfile, n as ColorState, r as colorState, t as ColorPolicy } from "./color-policy-CCxuHIdD.js";
5
5
  export { type Capabilities, type CapabilitiesStore, type ColorInfo, type ColorPolicy, type ColorState, type ColorSupport, type ColorSupportLevel, type Multiplexer, type PixelGeometry, type PixelSize, type RgbColor, type TerminalAppearance, type TerminalIdentity, type TerminalQueryOptions, type TerminalQueryResult, applyTerminalQuery, capabilities, colorState, createSupportsColor, detectCapabilities, detectColorLevel, detectHyperlinkSupport, detectTerminal, detectUnicodeSupport, getCapabilities, getTerminalQuery, queryTerminal, refreshTerminalQuery, resolveColorProfile };
@@ -1,3 +1,3 @@
1
- import { a as detectTerminal, i as detectHyperlinkSupport, n as detectCapabilities, o as detectUnicodeSupport, r as detectColorLevel, t as createSupportsColor } from "./detect-BuTXtY6e.js";
2
- import { d as queryTerminal, f as refreshTerminalQuery, i as getCapabilities, l as getTerminalQuery, n as resolveColorProfile, r as capabilities, s as applyTerminalQuery, t as colorState } from "./color-policy-SVj1pYTA.js";
1
+ import { a as detectTerminal, i as detectHyperlinkSupport, n as detectCapabilities, o as detectUnicodeSupport, r as detectColorLevel, t as createSupportsColor } from "./detect-B3dL4Q11.js";
2
+ import { d as queryTerminal, f as refreshTerminalQuery, i as getCapabilities, l as getTerminalQuery, n as resolveColorProfile, r as capabilities, s as applyTerminalQuery, t as colorState } from "./color-policy-DlrZXC0f.js";
3
3
  export { applyTerminalQuery, capabilities, colorState, createSupportsColor, detectCapabilities, detectColorLevel, detectHyperlinkSupport, detectTerminal, detectUnicodeSupport, getCapabilities, getTerminalQuery, queryTerminal, refreshTerminalQuery, resolveColorProfile };
@@ -1,5 +1,5 @@
1
- import { i as ColorSupportLevel } from "./detect-Bh4yGP6w.js";
2
- import { t as ColorProfile } from "./color-profile-u0Nhe9Nv.js";
1
+ import { i as ColorSupportLevel } from "./detect-Db6GbKOm.js";
2
+ import { t as ColorProfile } from "./color-profile-CyeHnG1T.js";
3
3
  //#region src/capabilities/color-policy.d.ts
4
4
  /** A user-selected output policy. `auto` follows the target stream. */
5
5
  type ColorPolicy = "auto" | ColorProfile;
@@ -1,6 +1,6 @@
1
1
  import { _ as CSI, b as OSC } from "./sgr-BhwaWAJB.js";
2
2
  import { a as isTty } from "./env-YVw64yZS.js";
3
- import { c as signalExit, n as detectCapabilities } from "./detect-BuTXtY6e.js";
3
+ import { n as detectCapabilities, s as signalExit } from "./detect-B3dL4Q11.js";
4
4
  import { t as colorProfileFromLevel } from "./color-profile-DHhQHY55.js";
5
5
  //#region src/capabilities/query.ts
6
6
  /**
@@ -373,25 +373,36 @@ const createStore = (stdin, stdout) => {
373
373
  const listeners = /* @__PURE__ */ new Set();
374
374
  let resizeSubscribers = 0;
375
375
  let focused;
376
+ let reportedSize;
376
377
  let snapshot;
377
378
  let snapshotQuery;
378
379
  let snapshotColumns;
379
380
  let snapshotRows;
380
381
  let snapshotFocused;
382
+ let snapshotReportedSize;
381
383
  const current = () => {
382
384
  const query = getTerminalQuery(stdout);
383
385
  const { columns, rows } = stdout;
384
- if (!snapshot || query !== snapshotQuery || columns !== snapshotColumns || rows !== snapshotRows || focused !== snapshotFocused) {
386
+ if (!snapshot || query !== snapshotQuery || columns !== snapshotColumns || rows !== snapshotRows || focused !== snapshotFocused || reportedSize !== snapshotReportedSize) {
385
387
  const detected = detectCapabilities({ stdout });
386
388
  const applied = query ? applyTerminalQuery(detected, query) : detected;
387
- snapshot = focused === void 0 ? applied : {
389
+ const sized = reportedSize ? {
388
390
  ...applied,
391
+ size: {
392
+ ...applied.size,
393
+ ...reportedSize,
394
+ source: "terminal"
395
+ }
396
+ } : applied;
397
+ snapshot = focused === void 0 ? sized : {
398
+ ...sized,
389
399
  focused
390
400
  };
391
401
  snapshotQuery = query;
392
402
  snapshotColumns = columns;
393
403
  snapshotRows = rows;
394
404
  snapshotFocused = focused;
405
+ snapshotReportedSize = reportedSize;
395
406
  }
396
407
  return snapshot;
397
408
  };
@@ -431,6 +442,7 @@ const createStore = (stdin, stdout) => {
431
442
  integration?.setReportFeed?.(false);
432
443
  removeExitHandler?.();
433
444
  removeExitHandler = void 0;
445
+ reportedSize = void 0;
434
446
  }
435
447
  };
436
448
  reportingUpdaters.set(stdout, updateReporting);
@@ -457,16 +469,22 @@ const createStore = (stdin, stdout) => {
457
469
  const resize = sequence.match(inBandResizeReport);
458
470
  if (resize) {
459
471
  const [, rows, columns, pixelHeight, pixelWidth] = resize.map(Number);
460
- if (columns && rows) patchTerminalQuery(stdout, {
461
- textAreaPixels: pixelWidth && pixelHeight ? {
462
- width: pixelWidth,
463
- height: pixelHeight
464
- } : void 0,
465
- cellPixels: pixelWidth && pixelHeight ? {
466
- width: Math.round(pixelWidth / columns),
467
- height: Math.round(pixelHeight / rows)
468
- } : void 0
469
- });
472
+ if (columns && rows) {
473
+ reportedSize = {
474
+ columns,
475
+ rows
476
+ };
477
+ patchTerminalQuery(stdout, {
478
+ textAreaPixels: pixelWidth && pixelHeight ? {
479
+ width: pixelWidth,
480
+ height: pixelHeight
481
+ } : void 0,
482
+ cellPixels: pixelWidth && pixelHeight ? {
483
+ width: Math.round(pixelWidth / columns),
484
+ height: Math.round(pixelHeight / rows)
485
+ } : void 0
486
+ });
487
+ }
470
488
  notify();
471
489
  return true;
472
490
  }
@@ -1,4 +1,4 @@
1
- import { i as ColorSupportLevel } from "./detect-Bh4yGP6w.js";
1
+ import { i as ColorSupportLevel } from "./detect-Db6GbKOm.js";
2
2
  //#region src/screen/cell.d.ts
3
3
  /**
4
4
  A terminal color before it is converted to an output profile.
package/dist/color.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { c as Color, d as RgbColor } from "./color-profile-u0Nhe9Nv.js";
2
- import { _ as perimeterGradient, a as LinearGradient, c as PaintContext, d as adaptive, f as ansi, g as perProfile, h as named, i as InterpolationSpace, l as PerimeterGradient, m as linearGradient, n as ColorInput, o as NamedColor, p as ansi256, r as GradientStop, s as Paint, t as AdaptiveColor, u as ProfileColor, v as rgb } from "./paint-C19minOS.js";
1
+ import { c as Color, d as RgbColor } from "./color-profile-CyeHnG1T.js";
2
+ import { _ as perimeterGradient, a as LinearGradient, c as PaintContext, d as adaptive, f as ansi, g as perProfile, h as named, i as InterpolationSpace, l as PerimeterGradient, m as linearGradient, n as ColorInput, o as NamedColor, p as ansi256, r as GradientStop, s as Paint, t as AdaptiveColor, u as ProfileColor, v as rgb } from "./paint-Cx-zC_sX.js";
3
3
  import { n as Rect } from "./geometry-BxXOzJgo.js";
4
4
  //#region src/color/palette.d.ts
5
5
  declare const canonicalAnsiPalette: readonly RgbColor[];
@@ -356,7 +356,8 @@ function detectCapabilities({ stdout = process.stdout } = {}) {
356
356
  columns: stdout.columns,
357
357
  rows: stdout.rows
358
358
  } : terminalSize(),
359
- pixels: void 0
359
+ pixels: void 0,
360
+ source: "pty"
360
361
  },
361
362
  focused: void 0,
362
363
  theme: {
@@ -370,4 +371,4 @@ function detectCapabilities({ stdout = process.stdout } = {}) {
370
371
  };
371
372
  }
372
373
  //#endregion
373
- export { detectTerminal as a, signalExit as c, detectHyperlinkSupport as i, detectCapabilities as n, detectUnicodeSupport as o, detectColorLevel as r, terminalSize as s, createSupportsColor as t };
374
+ export { detectTerminal as a, detectHyperlinkSupport as i, detectCapabilities as n, detectUnicodeSupport as o, detectColorLevel as r, signalExit as s, createSupportsColor as t };
@@ -64,11 +64,20 @@ type Capabilities = {
64
64
  /**
65
65
  Current terminal dimensions in cells, plus pixel geometry once the
66
66
  terminal has answered the query.
67
+
68
+ `source` tells where the cell dimensions come from. `"pty"` is the
69
+ stream's own `columns`/`rows`, updated by the OS on SIGWINCH — which says
70
+ nothing about whether the emulator has finished rewrapping its screen.
71
+ `"terminal"` is the emulator's in-band size report (mode 2048), which
72
+ arrives in the input stream after the rewrap and so describes the screen
73
+ exactly as later output will find it. While the terminal reports, its
74
+ size wins over the stream's.
67
75
  */
68
76
  size: {
69
77
  columns: number;
70
78
  rows: number;
71
79
  pixels: PixelGeometry | undefined;
80
+ source: "pty" | "terminal";
72
81
  };
73
82
  platform: NodeJS.Platform;
74
83
  /**
@@ -1,6 +1,6 @@
1
1
  import { a as StyledChar } from "./tokenize-Dx1y_l5H.js";
2
- import { i as Cell, t as ColorProfile } from "./color-profile-u0Nhe9Nv.js";
3
- import { n as Screen, t as Line } from "./screen-BReKIheE.js";
2
+ import { i as Cell, t as ColorProfile } from "./color-profile-CyeHnG1T.js";
3
+ import { n as Screen, t as Line } from "./screen-CgC2WlVM.js";
4
4
  //#region src/screen/ansi.d.ts
5
5
  /** Converts the renderer's canonical ANSI state into backend-neutral cells. */
6
6
  declare function cellsFromAnsi(text: string): Cell[];
package/dist/index.d.ts CHANGED
@@ -1,10 +1,10 @@
1
- import { a as Multiplexer, c as TerminalAppearance, d as detectCapabilities, f as detectColorLevel, h as detectUnicodeSupport, i as ColorSupportLevel, l as TerminalIdentity, m as detectTerminal, n as ColorInfo, o as PixelGeometry, p as detectHyperlinkSupport, r as ColorSupport, s as RgbColor, t as Capabilities, u as createSupportsColor } from "./detect-Bh4yGP6w.js";
1
+ import { a as Multiplexer, c as TerminalAppearance, d as detectCapabilities, f as detectColorLevel, h as detectUnicodeSupport, i as ColorSupportLevel, l as TerminalIdentity, m as detectTerminal, n as ColorInfo, o as PixelGeometry, p as detectHyperlinkSupport, r as ColorSupport, s as RgbColor, t as Capabilities, u as createSupportsColor } from "./detect-Db6GbKOm.js";
2
2
  import { n as TerminalProgressState, t as ClipboardSelection } from "./osc-Cn0fw77g.js";
3
- import { a as getTerminalQuery, i as applyTerminalQuery, n as TerminalQueryOptions, o as queryTerminal, r as TerminalQueryResult, s as refreshTerminalQuery, t as PixelSize } from "./query-vaIeGOkH.js";
4
- import { i as OutputStream, n as capabilities, r as getCapabilities, t as CapabilitiesStore } from "./store-CgrG9K4y.js";
5
- import { s as CellStyle, t as ColorProfile } from "./color-profile-u0Nhe9Nv.js";
6
- import { s as Paint } from "./paint-C19minOS.js";
7
- import { n as Text, r as Styles, t as Props$8 } from "./Text-D5HUf3Fj.js";
3
+ import { a as getTerminalQuery, i as applyTerminalQuery, n as TerminalQueryOptions, o as queryTerminal, r as TerminalQueryResult, s as refreshTerminalQuery, t as PixelSize } from "./query-BNc2B8GD.js";
4
+ import { i as OutputStream, n as capabilities, r as getCapabilities, t as CapabilitiesStore } from "./store-C1P5fOUi.js";
5
+ import { s as CellStyle, t as ColorProfile } from "./color-profile-CyeHnG1T.js";
6
+ import { s as Paint } from "./paint-Cx-zC_sX.js";
7
+ import { n as Text, r as Styles, t as Props$8 } from "./Text-DV9CuzAT.js";
8
8
  import { i as Node } from "./index-DDVME65c.js";
9
9
  import { t as CursorPosition } from "./cursor-position-D2LAkRG0.js";
10
10
  import { Writable } from "node:stream";
@@ -1046,6 +1046,10 @@ type WindowSize = {
1046
1046
  };
1047
1047
  /**
1048
1048
  A React hook that returns the current terminal window dimensions and re-renders the component whenever the terminal is resized.
1049
+
1050
+ Reads the capabilities store, so on terminals that send in-band size reports
1051
+ (mode 2048) the dimensions are the emulator's own, arriving after it has
1052
+ rewrapped its screen; elsewhere they are the stream's `columns`/`rows`.
1049
1053
  */
1050
1054
  declare const useWindowSize: () => WindowSize;
1051
1055
  //#endregion
package/dist/index.js CHANGED
@@ -2,17 +2,17 @@ import { C as bsu, S as ansiEscapes, V as esu, W as link, _ as CSI } from "./sgr
2
2
  import { h as tokenizeAnsi, p as graphemes } from "./tokenize-AjqbvtiT.js";
3
3
  import { t as stringWidth } from "./string-width-CijQwpIk.js";
4
4
  import { n as sliceAnsi, r as wrapAnsi } from "./truncate-D31fhU6i.js";
5
- import { _ as squashTextNodes, a as reconciler, c as kittyModifiers, d as FocusContext, f as Text, g as transformAnsiLine, h as emitLayoutListeners, i as useStdinContext, l as resolveFlags, m as createNode, n as useInput, o as detectKittySupport, p as addLayoutListener, r as useStdin, s as kittyFlags, t as useFocus, u as StdinContext, v as accessibilityContext } from "./use-focus-C2sciZOo.js";
5
+ import { _ as squashTextNodes, a as reconciler, c as kittyModifiers, d as FocusContext, f as Text, g as transformAnsiLine, h as emitLayoutListeners, i as useStdinContext, l as resolveFlags, m as createNode, n as useInput, o as detectKittySupport, p as addLayoutListener, r as useStdin, s as kittyFlags, t as useFocus, u as StdinContext, v as accessibilityContext } from "./use-focus-DSV01Ulb.js";
6
6
  import { a as isTty, i as isSigilDev, o as isWindows, r as isScreenReader, t as isInCi } from "./env-YVw64yZS.js";
7
- import { a as detectTerminal, c as signalExit, i as detectHyperlinkSupport, n as detectCapabilities, o as detectUnicodeSupport, r as detectColorLevel, s as terminalSize, t as createSupportsColor } from "./detect-BuTXtY6e.js";
8
- import { u as cliCursor } from "./osc-CCH7xDoS.js";
9
- import { a as registerTerminalIntegration, c as ensureTerminalQuery, d as queryTerminal, f as refreshTerminalQuery, i as getCapabilities, l as getTerminalQuery, o as getRawModeStream, r as capabilities, s as applyTerminalQuery, u as getTerminalQueryPromise } from "./color-policy-SVj1pYTA.js";
10
- import { a as buildCursorSuffix, c as hideCursorEscape, i as buildCursorOnlySequence, o as buildReturnToBottomPrefix, s as cursorPositionChanged, t as TerminalSession } from "./session-BJmzX2NJ.js";
7
+ import { a as detectTerminal, i as detectHyperlinkSupport, n as detectCapabilities, o as detectUnicodeSupport, r as detectColorLevel, s as signalExit, t as createSupportsColor } from "./detect-B3dL4Q11.js";
8
+ import { u as cliCursor } from "./osc-BFKKSqpg.js";
9
+ import { a as registerTerminalIntegration, c as ensureTerminalQuery, d as queryTerminal, f as refreshTerminalQuery, i as getCapabilities, l as getTerminalQuery, o as getRawModeStream, r as capabilities, s as applyTerminalQuery, u as getTerminalQueryPromise } from "./color-policy-DlrZXC0f.js";
10
+ import { a as buildCursorSuffix, c as hideCursorEscape, i as buildCursorOnlySequence, o as buildReturnToBottomPrefix, s as cursorPositionChanged, t as TerminalSession } from "./session-Cg6STjFV.js";
11
11
  import { t as Yoga } from "./yoga-5jKhYCJC.js";
12
12
  import { r as createCell, t as cellAttributes } from "./cell-_ZVhbfl0.js";
13
13
  import { i as semanticTextStyleToCellStyle, n as mergeSemanticTextStyles, t as emptySemanticTextStyle } from "./semantic-text-style-DIMzC7xt.js";
14
14
  import { a as samplePaint } from "./sample-Cqw1bjUL.js";
15
- import { n as cellFromStyledChar, r as cellsFromAnsi, t as Screen } from "./screen-BOh__-65.js";
15
+ import { n as cellFromStyledChar, r as cellsFromAnsi, t as Screen } from "./screen-CiPytswf.js";
16
16
  import { t as colorProfileFromLevel } from "./color-profile-DHhQHY55.js";
17
17
  import { n as serializeScreen, t as serializeLine } from "./serialize-BTkAZgw1.js";
18
18
  import { t as stripAnsi } from "./strip-BvU4toXG.js";
@@ -1115,6 +1115,7 @@ function structuredTextBaseStyle(node) {
1115
1115
  }
1116
1116
  /** Wraps or truncates semantic cells without converting them through ANSI. */
1117
1117
  function wrapStructuredText(input, maxWidth, wrap, baseStyle) {
1118
+ if (wrap === "none") return input.map((line) => [...line]);
1118
1119
  if (maxWidth < 1) return [[]];
1119
1120
  return input.flatMap((line) => {
1120
1121
  if (lineWidth(line) <= maxWidth) return [[...line]];
@@ -1301,7 +1302,9 @@ const paintTree = (node, output, options) => {
1301
1302
  const firstChildYoga = node.childNodes[0]?.yogaNode;
1302
1303
  const paddingX = firstChildYoga?.getComputedLeft() ?? 0;
1303
1304
  const paddingY = firstChildYoga?.getComputedTop() ?? 0;
1304
- const lines = wrapStructuredText(structuredTextLines(node), maxWidth, node.style.textWrap ?? "wrap", structuredTextBaseStyle(node));
1305
+ const textWrap = node.style.textWrap ?? "wrap";
1306
+ const overflow = textWrap === "none";
1307
+ const lines = wrapStructuredText(structuredTextLines(node), maxWidth, textWrap, structuredTextBaseStyle(node));
1305
1308
  const paintBounds = {
1306
1309
  x: x + paddingX,
1307
1310
  y: y + paddingY,
@@ -1314,8 +1317,11 @@ const paintTree = (node, output, options) => {
1314
1317
  output.writeAnsi(paintBounds.x, paintBounds.y, sampled.map((line) => serializeLine(line, {
1315
1318
  colorProfile: output.paintContext.profile ?? "truecolor",
1316
1319
  trimEnd: false
1317
- })).join("\n"), { transformers: textTransformers });
1318
- } else output.writeCells(paintBounds.x, paintBounds.y, sampled);
1320
+ })).join("\n"), {
1321
+ transformers: textTransformers,
1322
+ overflow
1323
+ });
1324
+ } else output.writeCells(paintBounds.x, paintBounds.y, sampled, { overflow });
1319
1325
  }
1320
1326
  return;
1321
1327
  }
@@ -1375,15 +1381,16 @@ var Canvas = class {
1375
1381
  };
1376
1382
  this.#screen = new Screen(this.width, this.height);
1377
1383
  }
1378
- writeCells(x, y, lines) {
1384
+ writeCells(x, y, lines, options) {
1379
1385
  const clip = this.#clips.at(-1);
1386
+ const overflow = options?.overflow === true;
1380
1387
  for (const [rowOffset, line] of lines.entries()) {
1381
1388
  const currentY = y + rowOffset;
1382
1389
  if (!this.#insideY(currentY, clip)) continue;
1383
1390
  let currentX = x;
1384
1391
  for (const cell of line) {
1385
1392
  const endX = currentX + cell.width;
1386
- if (!(clip?.x1 !== void 0 && currentX < clip.x1 || clip?.x2 !== void 0 && endX > clip.x2)) this.#composeNativeCell(currentX, currentY, cell);
1393
+ if (!(clip?.x1 !== void 0 && currentX < clip.x1 || clip?.x2 !== void 0 && endX > clip.x2)) this.#composeNativeCell(currentX, currentY, cell, overflow);
1387
1394
  currentX = endX;
1388
1395
  }
1389
1396
  }
@@ -1392,6 +1399,7 @@ var Canvas = class {
1392
1399
  if (!text) return;
1393
1400
  let lines = text.split("\n");
1394
1401
  const clip = this.#clips.at(-1);
1402
+ const overflow = options.overflow === true;
1395
1403
  if (clip?.y1 !== void 0 && y < clip.y1) {
1396
1404
  lines = lines.slice(clip.y1 - y);
1397
1405
  y = clip.y1;
@@ -1410,7 +1418,7 @@ var Canvas = class {
1410
1418
  for (const character of transformAnsiLine(line, lineIndex, options.transformers)) {
1411
1419
  const width = Math.max(1, stringWidth(character.value));
1412
1420
  if (clip?.x2 !== void 0 && currentX + width > clip.x2) break;
1413
- this.#writeCompatibilityCell(currentX, currentY, character, width);
1421
+ this.#writeCompatibilityCell(currentX, currentY, character, width, overflow);
1414
1422
  currentX += width;
1415
1423
  }
1416
1424
  }
@@ -1427,8 +1435,8 @@ var Canvas = class {
1427
1435
  #insideY(y, clip) {
1428
1436
  return y >= 0 && y < this.#screen.height && (clip?.y1 === void 0 || y >= clip.y1) && (clip?.y2 === void 0 || y < clip.y2);
1429
1437
  }
1430
- #composeNativeCell(x, y, cell) {
1431
- if (x >= this.#screen.width) return;
1438
+ #composeNativeCell(x, y, cell, overflow = false) {
1439
+ if (!overflow && x >= this.#screen.width) return;
1432
1440
  this.#screen.composeCell(x, y, {
1433
1441
  content: {
1434
1442
  grapheme: cell.grapheme,
@@ -1440,10 +1448,10 @@ var Canvas = class {
1440
1448
  underline: cell.style.underline,
1441
1449
  attributes: cell.style.attributes,
1442
1450
  hyperlink: cell.hyperlink ?? null
1443
- });
1451
+ }, { overflow });
1444
1452
  }
1445
- #writeCompatibilityCell(x, y, character, width) {
1446
- if (x >= this.#screen.width) return;
1453
+ #writeCompatibilityCell(x, y, character, width, overflow = false) {
1454
+ if (!overflow && x >= this.#screen.width) return;
1447
1455
  const cell = cellFromStyledChar(character, width);
1448
1456
  this.#screen.composeCell(x, y, {
1449
1457
  content: {
@@ -1456,7 +1464,7 @@ var Canvas = class {
1456
1464
  underline: cell.style.underline,
1457
1465
  attributes: cell.style.attributes,
1458
1466
  hyperlink: cell.hyperlink ?? null
1459
- });
1467
+ }, { overflow });
1460
1468
  }
1461
1469
  };
1462
1470
  //#endregion
@@ -1652,31 +1660,6 @@ function createRenderScheduler(render, options) {
1652
1660
  };
1653
1661
  }
1654
1662
  //#endregion
1655
- //#region src/utils.ts
1656
- const resolveDimension = (value, fallback, defaultValue) => {
1657
- if (value !== void 0 && value > 0) return value;
1658
- if (fallback !== void 0 && fallback > 0) return fallback;
1659
- return defaultValue;
1660
- };
1661
- /**
1662
- Get the effective terminal dimensions from the given stdout stream.
1663
-
1664
- Falls back to `terminal-size` for columns in piped processes where `stdout.columns` is 0, and uses standard defaults (80×24) when dimensions cannot be determined.
1665
- */
1666
- const getWindowSize = (stdout) => {
1667
- const columns = stdout.columns ?? 0;
1668
- const rows = stdout.rows ?? 0;
1669
- if (columns && rows) return {
1670
- columns,
1671
- rows
1672
- };
1673
- const fallbackSize = terminalSize();
1674
- return {
1675
- columns: resolveDimension(columns, fallbackSize.columns, 80),
1676
- rows: resolveDimension(rows, fallbackSize.rows, 24)
1677
- };
1678
- };
1679
- //#endregion
1680
1663
  //#region src/ink.tsx
1681
1664
  /** @jsxImportSource react */
1682
1665
  const noop = () => {};
@@ -1702,6 +1685,7 @@ function bottomRows(screen, height) {
1702
1685
  }
1703
1686
  return cropped;
1704
1687
  }
1688
+ const RESIZE_SETTLE_MS = 50;
1705
1689
  const shouldClearTerminalForFrame = ({ isTTY, viewportRows, previousOutputHeight, nextOutputHeight, isUnmounting }) => {
1706
1690
  if (!isTTY) return false;
1707
1691
  const hadPreviousFrame = previousOutputHeight > 0;
@@ -1793,8 +1777,10 @@ const createInk = (options) => {
1793
1777
  let lastOutputToRender = "";
1794
1778
  let lastOutputHeight = 0;
1795
1779
  let lastScreen;
1796
- let lastTerminalWidth = getWindowSize(options.stdout).columns;
1797
- let lastTerminalHeight = getWindowSize(options.stdout).rows;
1780
+ const windowSize = () => capabilitiesStore.current.size;
1781
+ let lastTerminalWidth = windowSize().columns;
1782
+ let lastTerminalHeight = windowSize().rows;
1783
+ let resizeSettle;
1798
1784
  let fullStaticOutput = "";
1799
1785
  let exitResult;
1800
1786
  let unsubscribeBeforeExit;
@@ -1817,29 +1803,48 @@ const createInk = (options) => {
1817
1803
  if (isSigilDev) reconciler.injectIntoDevTools();
1818
1804
  if (options.patchConsole) installConsolePatch();
1819
1805
  if (interactive) {
1820
- options.stdout.on("resize", resized);
1821
- unsubscribeResize = () => {
1822
- options.stdout.off("resize", resized);
1823
- };
1806
+ let seenColumns = lastTerminalWidth;
1807
+ let seenRows = lastTerminalHeight;
1808
+ unsubscribeResize = capabilitiesStore.subscribe(({ size }) => {
1809
+ if (size.columns === seenColumns && size.rows === seenRows) return;
1810
+ seenColumns = size.columns;
1811
+ seenRows = size.rows;
1812
+ resized(size.source);
1813
+ });
1824
1814
  }
1825
1815
  initKittyKeyboard();
1826
1816
  const { promise: exitPromise, resolve: resolveExitPromise, reject: rejectExitPromise } = Promise.withResolvers();
1827
1817
  exitPromise.catch(noop);
1828
- function resized() {
1829
- const currentWidth = getWindowSize(options.stdout).columns;
1830
- const currentHeight = getWindowSize(options.stdout).rows;
1818
+ function resized(source) {
1819
+ if (resizeSettle !== void 0) {
1820
+ clearTimeout(resizeSettle);
1821
+ resizeSettle = void 0;
1822
+ }
1823
+ if (source === "terminal") {
1824
+ settleResize();
1825
+ return;
1826
+ }
1827
+ resizeSettle = setTimeout(settleResize, RESIZE_SETTLE_MS);
1828
+ }
1829
+ function settleResize() {
1830
+ resizeSettle = void 0;
1831
+ if (isUnmounted || isUnmounting) return;
1832
+ const { columns: currentWidth, rows: currentHeight } = windowSize();
1831
1833
  if (currentWidth < lastTerminalWidth || currentHeight !== lastTerminalHeight) {
1832
- clearLiveOutput();
1834
+ clearLiveOutput(rewrapsOnResize() ? currentWidth : void 0);
1833
1835
  resetLiveOutput();
1834
1836
  lastOutput = "";
1835
1837
  lastOutputToRender = "";
1836
1838
  lastOutputHeight = 0;
1837
1839
  }
1840
+ lastTerminalWidth = currentWidth;
1841
+ lastTerminalHeight = currentHeight;
1838
1842
  calculateLayout();
1839
1843
  emitLayoutListeners(rootNode);
1840
1844
  onRender();
1841
- lastTerminalWidth = currentWidth;
1842
- lastTerminalHeight = currentHeight;
1845
+ }
1846
+ function rewrapsOnResize() {
1847
+ return !isWindows && capabilitiesStore.current.terminal.name !== "apple-terminal";
1843
1848
  }
1844
1849
  function handleAppExit(errorOrResult) {
1845
1850
  if (isUnmounted || isUnmounting) return;
@@ -1864,9 +1869,9 @@ const createInk = (options) => {
1864
1869
  forceRewrite: true
1865
1870
  });
1866
1871
  }
1867
- function clearLiveOutput() {
1872
+ function clearLiveOutput(columns) {
1868
1873
  if (isScreenReaderEnabled) accessiblePresenter.clear();
1869
- else terminal.clearFrame();
1874
+ else terminal.clearFrame({ columns });
1870
1875
  }
1871
1876
  function finishLiveOutput() {
1872
1877
  if (isScreenReaderEnabled) accessiblePresenter.done();
@@ -1877,7 +1882,7 @@ const createInk = (options) => {
1877
1882
  else terminal.resetFrame();
1878
1883
  }
1879
1884
  function calculateLayout() {
1880
- const terminalWidth = getWindowSize(options.stdout).columns;
1885
+ const terminalWidth = windowSize().columns;
1881
1886
  rootNode.yogaNode.setWidth(terminalWidth);
1882
1887
  rootNode.yogaNode.calculateLayout(void 0, void 0, Yoga.DIRECTION_LTR);
1883
1888
  }
@@ -1894,6 +1899,13 @@ const createInk = (options) => {
1894
1899
  }
1895
1900
  return;
1896
1901
  }
1902
+ if (resizeSettle !== void 0 && !isUnmounting) {
1903
+ if (nextRenderCommit) {
1904
+ nextRenderCommit.resolve();
1905
+ nextRenderCommit = void 0;
1906
+ }
1907
+ return;
1908
+ }
1897
1909
  if (nextRenderCommit) {
1898
1910
  nextRenderCommit.resolve();
1899
1911
  nextRenderCommit = void 0;
@@ -1940,7 +1952,7 @@ const createInk = (options) => {
1940
1952
  if (sync) options.stdout.write(esu);
1941
1953
  return;
1942
1954
  }
1943
- const terminalWidth = getWindowSize(options.stdout).columns;
1955
+ const terminalWidth = windowSize().columns;
1944
1956
  const wrappedOutput = wrapAnsi(output, terminalWidth, {
1945
1957
  trim: false,
1946
1958
  hard: true
@@ -2029,6 +2041,10 @@ const createInk = (options) => {
2029
2041
  function unmount(error) {
2030
2042
  if (isUnmounted || isUnmounting) return;
2031
2043
  isUnmounting = true;
2044
+ if (resizeSettle !== void 0) {
2045
+ clearTimeout(resizeSettle);
2046
+ resizeSettle = void 0;
2047
+ }
2032
2048
  unsubscribeBeforeExit?.();
2033
2049
  unsubscribeBeforeExit = void 0;
2034
2050
  const { canWriteToStdout } = getWritableStreamState(options.stdout);
@@ -2213,7 +2229,7 @@ const createInk = (options) => {
2213
2229
  if (!screen) return;
2214
2230
  const hasStaticOutput = staticOutput !== "";
2215
2231
  const isTTY = Boolean(options.stdout.isTTY);
2216
- const viewportRows = isTTY ? getWindowSize(options.stdout).rows : 24;
2232
+ const viewportRows = isTTY ? windowSize().rows : 24;
2217
2233
  if (isTTY && outputHeight > viewportRows) {
2218
2234
  const lines = output.split("\n");
2219
2235
  output = lines.slice(lines.length - viewportRows).join("\n");
@@ -2899,20 +2915,17 @@ const usePointerShape = (shape) => {
2899
2915
  //#region src/hooks/use-window-size.ts
2900
2916
  /**
2901
2917
  A React hook that returns the current terminal window dimensions and re-renders the component whenever the terminal is resized.
2918
+
2919
+ Reads the capabilities store, so on terminals that send in-band size reports
2920
+ (mode 2048) the dimensions are the emulator's own, arriving after it has
2921
+ rewrapped its screen; elsewhere they are the stream's `columns`/`rows`.
2902
2922
  */
2903
2923
  const useWindowSize = () => {
2904
- const { stdout } = useStdout();
2905
- const [size, setSize] = useState(() => getWindowSize(stdout));
2906
- useEffect(() => {
2907
- const onResize = () => {
2908
- setSize(getWindowSize(stdout));
2909
- };
2910
- stdout.on("resize", onResize);
2911
- return () => {
2912
- stdout.off("resize", onResize);
2913
- };
2914
- }, [stdout]);
2915
- return size;
2924
+ const { size } = useCapabilities();
2925
+ return useMemo(() => ({
2926
+ columns: size.columns,
2927
+ rows: size.rows
2928
+ }), [size.columns, size.rows]);
2916
2929
  };
2917
2930
  //#endregion
2918
2931
  //#region src/hooks/use-box-metrics.ts
@@ -1,5 +1,5 @@
1
1
  import { D as cursorHide, b as OSC, j as cursorShow, x as ST } from "./sgr-BhwaWAJB.js";
2
- import { c as signalExit } from "./detect-BuTXtY6e.js";
2
+ import { s as signalExit } from "./detect-B3dL4Q11.js";
3
3
  import { pathToFileURL } from "node:url";
4
4
  //#region src/ansi/cursor.ts
5
5
  let restoreRegistered = false;
@@ -1,5 +1,5 @@
1
- import { c as TerminalAppearance } from "./detect-Bh4yGP6w.js";
2
- import { c as Color, d as RgbColor, t as ColorProfile } from "./color-profile-u0Nhe9Nv.js";
1
+ import { c as TerminalAppearance } from "./detect-Db6GbKOm.js";
2
+ import { c as Color, d as RgbColor, t as ColorProfile } from "./color-profile-CyeHnG1T.js";
3
3
  //#region src/color/paint.d.ts
4
4
  type ColorInput = Color | string;
5
5
  type InterpolationSpace = "oklab" | "lab" | "rgb" | "hsv";
@@ -1,4 +1,4 @@
1
- import { c as TerminalAppearance, s as RgbColor, t as Capabilities } from "./detect-Bh4yGP6w.js";
1
+ import { c as TerminalAppearance, s as RgbColor, t as Capabilities } from "./detect-Db6GbKOm.js";
2
2
  //#region src/capabilities/query.d.ts
3
3
  type PixelSize = {
4
4
  width: number;
package/dist/router.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { t as Props } from "./Text-D5HUf3Fj.js";
1
+ import { t as Props } from "./Text-DV9CuzAT.js";
2
2
  import { ReactElement, ReactNode } from "react";
3
3
  //#region src/router/history.d.ts
4
4
  /**
package/dist/router.js CHANGED
@@ -1,4 +1,4 @@
1
- import { f as Text, n as useInput, t as useFocus } from "./use-focus-C2sciZOo.js";
1
+ import { f as Text, n as useInput, t as useFocus } from "./use-focus-DSV01Ulb.js";
2
2
  import { Children, Fragment, createContext, isValidElement, startTransition, useCallback, useContext, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
3
3
  import { Fragment as Fragment$1, jsx } from "react/jsx-runtime";
4
4
  //#region src/router/history.ts