@tuidom/core 0.6.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,6 +2,15 @@ import type { Point, Size } from "../common/geometryPromitives.js";
2
2
  import type { KeyPressEvent } from "../input/keyEvent.js";
3
3
  import type { MouseToken } from "../input/rawTerminalToken.js";
4
4
  import type { Grid } from "../rendering/grid.js";
5
+ /** Colors the host terminal reported ({@link ITerminalBackend.probeHostColors}); packed RGB. */
6
+ export interface HostTerminalColors {
7
+ readonly foreground: number | undefined;
8
+ readonly background: number | undefined;
9
+ /** ANSI palette 0..15 (always 16 entries); `undefined` — this entry wasn't reported. */
10
+ readonly ansi: readonly (number | undefined)[];
11
+ }
12
+ /** The terminal reported none of its colors — the answer of a backend without a terminal. */
13
+ export declare const NO_HOST_COLORS: HostTerminalColors;
5
14
  /**
6
15
  * Unified abstraction over terminal I/O.
7
16
  *
@@ -37,6 +46,16 @@ export interface ITerminalBackend {
37
46
  * Fire-and-forget — callers must not block on it.
38
47
  */
39
48
  probeTerminalVersion(onResult: (nameAndVersion: string | undefined) => void): void;
49
+ /**
50
+ * Asynchronously ask the terminal for its own colors: the default foreground and
51
+ * background (OSC 10/11) and the 16 ANSI palette entries (OSC 4, indices 0..15).
52
+ * `onResult` fires exactly once; every color the terminal didn't report (no OSC
53
+ * support, GNU Screen, timeout) is `undefined`, so callers fall back per entry.
54
+ * Replies are consumed by the backend: they still reach `onOscResponse`, never
55
+ * `onInput`. Inside tmux the queries go to tmux itself, which answers from the
56
+ * outer terminal (tmux ≥ 3.4 for fg/bg, ≥ 3.6 for the palette). Fire-and-forget.
57
+ */
58
+ probeHostColors(onResult: (colors: HostTerminalColors) => void): void;
40
59
  /**
41
60
  * Render a frame: receive the current grid and cursor position.
42
61
  * The backend decides how to output it (ANSI diffing, simple copy, etc.).
@@ -1 +1,6 @@
1
- export {};
1
+ /** The terminal reported none of its colors — the answer of a backend without a terminal. */
2
+ export const NO_HOST_COLORS = Object.freeze({
3
+ foreground: undefined,
4
+ background: undefined,
5
+ ansi: Object.freeze(new Array(16).fill(undefined)),
6
+ });
@@ -60,6 +60,14 @@ export declare function compositeOver(color: number, under: number): number;
60
60
  * должен падать на разборе, а не красить в чёрный.
61
61
  */
62
62
  export declare function parseHexColor(hex: string): number;
63
+ /**
64
+ * Разбирает цвет в формате X11, которым терминалы отвечают на OSC 4/10/11
65
+ * (`XParseColor`): `rgb:R/G/B` с 1–4 hex-цифрами на канал (обычно 4 —
66
+ * `rgb:ffff/8080/0000`) и устаревший `#RGB`/`#RRGGBB`/`#RRRGGGBBB`/`#RRRRGGGGBBBB`.
67
+ * Канал масштабируется к 8 битам по своей разрядности. Непонятная строка —
68
+ * `undefined`: ответ терминала — внешние данные, бросать на них нельзя.
69
+ */
70
+ export declare function parseXColor(spec: string): number | undefined;
63
71
  /**
64
72
  * Обратное к {@link parseHexColor}: `#rrggbb` для непрозрачного, `#rrggbbaa`
65
73
  * с альфой, `#00000000` для {@link TRANSPARENT_COLOR}. `DEFAULT_COLOR` hex не
@@ -115,6 +115,30 @@ export function parseHexColor(hex) {
115
115
  const hasAlpha = digits.length === 4 || digits.length === 8;
116
116
  return packRgba(channel(0), channel(1), channel(2), hasAlpha ? channel(3) : 0xff);
117
117
  }
118
+ /**
119
+ * Разбирает цвет в формате X11, которым терминалы отвечают на OSC 4/10/11
120
+ * (`XParseColor`): `rgb:R/G/B` с 1–4 hex-цифрами на канал (обычно 4 —
121
+ * `rgb:ffff/8080/0000`) и устаревший `#RGB`/`#RRGGBB`/`#RRRGGGBBB`/`#RRRRGGGGBBBB`.
122
+ * Канал масштабируется к 8 битам по своей разрядности. Непонятная строка —
123
+ * `undefined`: ответ терминала — внешние данные, бросать на них нельзя.
124
+ */
125
+ export function parseXColor(spec) {
126
+ const rgb = /^rgb:([0-9a-f]{1,4})\/([0-9a-f]{1,4})\/([0-9a-f]{1,4})$/i.exec(spec);
127
+ if (rgb !== null)
128
+ return packRgb(scaleXChannel(rgb[1]), scaleXChannel(rgb[2]), scaleXChannel(rgb[3]));
129
+ const hash = /^#((?:[0-9a-f]{3}){1,4})$/i.exec(spec);
130
+ if (hash === null)
131
+ return undefined;
132
+ const digits = hash[1];
133
+ const width = digits.length / 3;
134
+ const channel = (i) => scaleXChannel(digits.slice(i * width, (i + 1) * width));
135
+ return packRgb(channel(0), channel(1), channel(2));
136
+ }
137
+ /** Канал X11-цвета из `digits.length` hex-цифр → 0..255 (`f` → 255, `ffff` → 255, `8080` → 128). */
138
+ function scaleXChannel(digits) {
139
+ const max = 16 ** digits.length - 1;
140
+ return Math.round((parseInt(digits, 16) * 255) / max);
141
+ }
118
142
  /**
119
143
  * Обратное к {@link parseHexColor}: `#rrggbb` для непрозрачного, `#rrggbbaa`
120
144
  * с альфой, `#00000000` для {@link TRANSPARENT_COLOR}. `DEFAULT_COLOR` hex не
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tuidom/core",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
4
4
  "type": "module",
5
5
  "description": "Experimental terminal UI DOM — core: element tree, flex layout, grid rendering, input parsing. API is unstable.",
6
6
  "license": "MIT",