@tuidom/core 0.1.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.
Files changed (91) hide show
  1. package/dist/backend/iTerminalBackend.d.ts +41 -0
  2. package/dist/backend/iTerminalBackend.js +1 -0
  3. package/dist/common/colorUtils.d.ts +19 -0
  4. package/dist/common/colorUtils.js +30 -0
  5. package/dist/common/displayLine.d.ts +72 -0
  6. package/dist/common/displayLine.js +190 -0
  7. package/dist/common/disposable.d.ts +9 -0
  8. package/dist/common/disposable.js +18 -0
  9. package/dist/common/geometryPromitives.d.ts +47 -0
  10. package/dist/common/geometryPromitives.js +115 -0
  11. package/dist/common/iTerminalSurface.d.ts +68 -0
  12. package/dist/common/iTerminalSurface.js +8 -0
  13. package/dist/common/measureTextWidth.d.ts +21 -0
  14. package/dist/common/measureTextWidth.js +43 -0
  15. package/dist/common/styleFlags.d.ts +17 -0
  16. package/dist/common/styleFlags.js +16 -0
  17. package/dist/common/textTruncation.d.ts +30 -0
  18. package/dist/common/textTruncation.js +124 -0
  19. package/dist/common/typingUtils.d.ts +1 -0
  20. package/dist/common/typingUtils.js +3 -0
  21. package/dist/common/unicodeWidth.d.ts +18 -0
  22. package/dist/common/unicodeWidth.js +339 -0
  23. package/dist/dom/borderStyle.d.ts +31 -0
  24. package/dist/dom/borderStyle.js +40 -0
  25. package/dist/dom/compositeElement.d.ts +20 -0
  26. package/dist/dom/compositeElement.js +44 -0
  27. package/dist/dom/events/contextMenuEventSource.d.ts +17 -0
  28. package/dist/dom/events/contextMenuEventSource.js +44 -0
  29. package/dist/dom/events/focusManager.d.ts +13 -0
  30. package/dist/dom/events/focusManager.js +56 -0
  31. package/dist/dom/events/mouseEventDispatcher.d.ts +24 -0
  32. package/dist/dom/events/mouseEventDispatcher.js +177 -0
  33. package/dist/dom/events/tuiEventBase.d.ts +25 -0
  34. package/dist/dom/events/tuiEventBase.js +39 -0
  35. package/dist/dom/events/tuiFocusEvent.d.ts +6 -0
  36. package/dist/dom/events/tuiFocusEvent.js +8 -0
  37. package/dist/dom/events/tuiKeyboardEvent.d.ts +21 -0
  38. package/dist/dom/events/tuiKeyboardEvent.js +20 -0
  39. package/dist/dom/events/tuiMouseEvent.d.ts +40 -0
  40. package/dist/dom/events/tuiMouseEvent.js +32 -0
  41. package/dist/dom/events/tuiPasteEvent.d.ts +10 -0
  42. package/dist/dom/events/tuiPasteEvent.js +13 -0
  43. package/dist/dom/overlayLayer.d.ts +92 -0
  44. package/dist/dom/overlayLayer.js +343 -0
  45. package/dist/dom/styles/index.d.ts +4 -0
  46. package/dist/dom/styles/index.js +2 -0
  47. package/dist/dom/styles/styleTokens.d.ts +114 -0
  48. package/dist/dom/styles/styleTokens.js +122 -0
  49. package/dist/dom/styles/tuiStyle.d.ts +75 -0
  50. package/dist/dom/styles/tuiStyle.js +121 -0
  51. package/dist/dom/tuiApplication.d.ts +57 -0
  52. package/dist/dom/tuiApplication.js +231 -0
  53. package/dist/dom/tuiElement.d.ts +528 -0
  54. package/dist/dom/tuiElement.js +1168 -0
  55. package/dist/dom/tuiSelector.d.ts +9 -0
  56. package/dist/dom/tuiSelector.js +82 -0
  57. package/dist/dom/validateTree.d.ts +42 -0
  58. package/dist/dom/validateTree.js +125 -0
  59. package/dist/input/convertToken.d.ts +3 -0
  60. package/dist/input/convertToken.js +114 -0
  61. package/dist/input/keyEvent.d.ts +46 -0
  62. package/dist/input/keyEvent.js +26 -0
  63. package/dist/input/keyInputParser.d.ts +72 -0
  64. package/dist/input/keyInputParser.js +249 -0
  65. package/dist/input/mouseTracking.d.ts +18 -0
  66. package/dist/input/mouseTracking.js +18 -0
  67. package/dist/input/parseInput.d.ts +13 -0
  68. package/dist/input/parseInput.js +17 -0
  69. package/dist/input/rawTerminalToken.d.ts +142 -0
  70. package/dist/input/rawTerminalToken.js +2 -0
  71. package/dist/input/serializeKey.d.ts +14 -0
  72. package/dist/input/serializeKey.js +179 -0
  73. package/dist/input/serializeMouse.d.ts +26 -0
  74. package/dist/input/serializeMouse.js +38 -0
  75. package/dist/input/tokenize.d.ts +59 -0
  76. package/dist/input/tokenize.js +681 -0
  77. package/dist/rendering/cell.d.ts +24 -0
  78. package/dist/rendering/cell.js +46 -0
  79. package/dist/rendering/damage.d.ts +35 -0
  80. package/dist/rendering/damage.js +99 -0
  81. package/dist/rendering/grid.d.ts +49 -0
  82. package/dist/rendering/grid.js +216 -0
  83. package/dist/rendering/gridSnapshot.d.ts +33 -0
  84. package/dist/rendering/gridSnapshot.js +32 -0
  85. package/dist/rendering/gridToSvg.d.ts +29 -0
  86. package/dist/rendering/gridToSvg.js +145 -0
  87. package/dist/rendering/terminalRenderer.d.ts +28 -0
  88. package/dist/rendering/terminalRenderer.js +161 -0
  89. package/dist/rendering/terminalScreen.d.ts +25 -0
  90. package/dist/rendering/terminalScreen.js +50 -0
  91. package/package.json +29 -0
@@ -0,0 +1,92 @@
1
+ import { BoxConstraints, Point, Size } from "../common/geometryPromitives.js";
2
+ import { RenderContext, TUIElement } from "./tuiElement.js";
3
+ export interface OverlayLayerItem {
4
+ element: TUIElement;
5
+ position: Point;
6
+ visible: boolean;
7
+ }
8
+ export interface OverlayAnchorPosition {
9
+ screenX: number;
10
+ screenY: number;
11
+ offsetX?: number;
12
+ offsetY?: number;
13
+ preferBelow?: boolean;
14
+ }
15
+ /**
16
+ * Поведение оверлей-сессии по клику мимо неё. Поле обязательное — каждый оверлей
17
+ * должен явно объявить, что происходит с кликом позади него:
18
+ * - `close-on-outside` — клик снаружи закрывает сессию (попап доходит до элемента позади как раньше);
19
+ * - `modal` — клик снаружи блокируется и НЕ доходит до элементов позади (плюс Tab-фокус заперт внутри);
20
+ * - `passthrough` — клик снаружи проходит насквозь, сессия не закрывается (док-виджеты вроде Find).
21
+ */
22
+ export type PointerPolicy = "close-on-outside" | "modal" | "passthrough";
23
+ export interface OverlaySessionOptions {
24
+ visible?: boolean;
25
+ restoreFocus?: boolean;
26
+ focusOnOpen?: boolean;
27
+ closeOnEscape?: boolean;
28
+ pointerPolicy: PointerPolicy;
29
+ /** Гасит ли оверлей глобальные кейбинды, пока видим. По умолчанию pointerPolicy !== "passthrough". */
30
+ capturesKeyboard?: boolean;
31
+ disposeOnClose?: boolean;
32
+ onClose?: () => void;
33
+ /**
34
+ * Дополнительная принадлежность цели к сессии для close-on-outside: клик по
35
+ * элементу, за который поручился владелец (вложенные попапы-подменю — они
36
+ * отдельные item'ы слоя, не потомки), сессию не закрывает.
37
+ */
38
+ ownsTarget?: (target: TUIElement) => boolean;
39
+ /**
40
+ * Хук перед закрытием по Escape: вернуть false, чтобы слой сессию НЕ закрывал
41
+ * (владелец обработает Escape сам — например закроет только верхнее подменю).
42
+ */
43
+ shouldCloseOnEscape?: () => boolean;
44
+ }
45
+ export interface OverlaySessionHandle {
46
+ readonly element: TUIElement;
47
+ readonly isDisposed: boolean;
48
+ isOpen(): boolean;
49
+ open(): void;
50
+ close(): void;
51
+ setPosition(position: Point): void;
52
+ setAnchor(anchor: OverlayAnchorPosition): void;
53
+ dispose(): void;
54
+ }
55
+ export declare class OverlayLayer extends TUIElement {
56
+ private items;
57
+ private sessions;
58
+ addItem(element: TUIElement, position: Point, visible?: boolean): void;
59
+ removeItem(element: TUIElement): void;
60
+ setVisible(element: TUIElement, visible: boolean): void;
61
+ setPosition(element: TUIElement, position: Point): void;
62
+ createSession(element: TUIElement, position: Point, options: OverlaySessionOptions): OverlaySessionHandle;
63
+ openPopupSession(element: TUIElement, anchor: OverlayAnchorPosition, options: OverlaySessionOptions): OverlaySessionHandle;
64
+ computeAnchorPosition(element: TUIElement, anchor: OverlayAnchorPosition): Point;
65
+ hasVisibleItems(): boolean;
66
+ /**
67
+ * Клавиатурный аналог модальности из elementFromPoint: видимая захватывающая сессия
68
+ * гасит ГЛОБАЛЬНЫЕ кейбинды, чтобы шорткат не увёл фокус на панель за оверлеем.
69
+ * Собственные клавиши оверлея идут мимо глобального реестра, поэтому не задеваются.
70
+ */
71
+ hasKeyboardCapturingOverlay(): boolean;
72
+ clearAll(): void;
73
+ getItems(): readonly OverlayLayerItem[];
74
+ /**
75
+ * Базовый обратный обход детей (скрытые сессии выпадают через hidden) +
76
+ * modal-хвост: модальная сессия проглатывает точку, не взятую элементами
77
+ * над ней, — клик не проваливается под оверлей.
78
+ */
79
+ protected hitTestChildren(point: Point): TUIElement | null;
80
+ /** Слой прозрачен для кликов: мимо попапов точка уходит контенту под ним. */
81
+ protected hitTestSelf(_point: Point): boolean;
82
+ private isModalElement;
83
+ protected performLayout(constraints: BoxConstraints): Size;
84
+ render(context: RenderContext): void;
85
+ private openSession;
86
+ private releaseFocusScope;
87
+ private closeSession;
88
+ private disposeSessionByElement;
89
+ private disposeSession;
90
+ private attachSessionListeners;
91
+ private cleanupSessionListeners;
92
+ }
@@ -0,0 +1,343 @@
1
+ import { BoxConstraints, Offset, Point, Rect, Size } from "../common/geometryPromitives.js";
2
+ import { RenderContext, TUIElement } from "./tuiElement.js";
3
+ export class OverlayLayer extends TUIElement {
4
+ items = [];
5
+ sessions = new Map();
6
+ addItem(element, position, visible = false) {
7
+ this.appendChild(element);
8
+ element.hidden = !visible;
9
+ this.items.push({ element, position, visible });
10
+ this.markDirty();
11
+ }
12
+ removeItem(element) {
13
+ const session = this.sessions.get(element);
14
+ if (session && !session.isDisposed) {
15
+ this.disposeSession(session);
16
+ return;
17
+ }
18
+ const index = this.items.findIndex((item) => item.element === element);
19
+ if (index !== -1) {
20
+ this.removeChild(this.items[index].element);
21
+ this.items.splice(index, 1);
22
+ this.markDirty();
23
+ }
24
+ }
25
+ setVisible(element, visible) {
26
+ const item = this.items.find((item) => item.element === element);
27
+ if (item) {
28
+ item.visible = visible;
29
+ // hidden зеркалит видимость item'а: базовые обходы (Tab, hit-test)
30
+ // пропускают закрытые сессии сами, без override'ов.
31
+ item.element.hidden = !visible;
32
+ this.markDirty();
33
+ }
34
+ }
35
+ setPosition(element, position) {
36
+ const item = this.items.find((item) => item.element === element);
37
+ if (item) {
38
+ item.position = position;
39
+ this.markDirty();
40
+ }
41
+ }
42
+ createSession(element, position, options) {
43
+ this.disposeSessionByElement(element);
44
+ const initialVisible = options.visible ?? false;
45
+ this.addItem(element, position, false);
46
+ const session = {
47
+ element,
48
+ options: {
49
+ restoreFocus: options.restoreFocus ?? false,
50
+ focusOnOpen: options.focusOnOpen ?? false,
51
+ closeOnEscape: options.closeOnEscape ?? false,
52
+ pointerPolicy: options.pointerPolicy,
53
+ capturesKeyboard: options.capturesKeyboard ?? options.pointerPolicy !== "passthrough",
54
+ disposeOnClose: options.disposeOnClose ?? false,
55
+ },
56
+ visible: false,
57
+ isDisposed: false,
58
+ savedFocus: null,
59
+ focusScopePushed: false,
60
+ rootEscapeHandler: null,
61
+ rootOutsideHandler: null,
62
+ onClose: options.onClose ?? null,
63
+ ownsTarget: options.ownsTarget ?? null,
64
+ shouldCloseOnEscape: options.shouldCloseOnEscape ?? null,
65
+ };
66
+ this.sessions.set(element, session);
67
+ if (initialVisible) {
68
+ this.openSession(session);
69
+ }
70
+ const handle = {
71
+ element,
72
+ get isDisposed() {
73
+ return session.isDisposed;
74
+ },
75
+ isOpen: () => {
76
+ return !session.isDisposed && session.visible;
77
+ },
78
+ open: () => {
79
+ if (session.isDisposed)
80
+ return;
81
+ this.openSession(session);
82
+ },
83
+ close: () => {
84
+ if (session.isDisposed)
85
+ return;
86
+ this.closeSession(session);
87
+ },
88
+ setPosition: (nextPosition) => {
89
+ if (session.isDisposed)
90
+ return;
91
+ this.setPosition(session.element, nextPosition);
92
+ },
93
+ setAnchor: (anchor) => {
94
+ if (session.isDisposed)
95
+ return;
96
+ this.setPosition(session.element, this.computeAnchorPosition(session.element, anchor));
97
+ },
98
+ dispose: () => {
99
+ if (session.isDisposed)
100
+ return;
101
+ this.disposeSession(session);
102
+ },
103
+ };
104
+ return handle;
105
+ }
106
+ openPopupSession(element, anchor, options) {
107
+ const position = this.computeAnchorPosition(element, anchor);
108
+ return this.createSession(element, position, options);
109
+ }
110
+ computeAnchorPosition(element, anchor) {
111
+ const menuW = element.getMaxIntrinsicWidth(0);
112
+ const menuH = element.getMaxIntrinsicHeight(menuW);
113
+ const screenW = this.layoutSize.width;
114
+ const screenH = this.layoutSize.height;
115
+ const offsetX = anchor.offsetX ?? 0;
116
+ const offsetY = anchor.offsetY ?? 0;
117
+ const preferBelow = anchor.preferBelow ?? true;
118
+ let px = anchor.screenX + offsetX;
119
+ let py = preferBelow ? anchor.screenY + 1 + offsetY : anchor.screenY + offsetY;
120
+ if (px + menuW > screenW) {
121
+ px = Math.max(0, screenW - menuW);
122
+ }
123
+ if (py + menuH > screenH) {
124
+ py = Math.max(0, anchor.screenY - menuH);
125
+ }
126
+ px = Math.max(0, px);
127
+ py = Math.max(0, py);
128
+ return new Point(px, py);
129
+ }
130
+ hasVisibleItems() {
131
+ return this.items.some((item) => item.visible);
132
+ }
133
+ /**
134
+ * Клавиатурный аналог модальности из elementFromPoint: видимая захватывающая сессия
135
+ * гасит ГЛОБАЛЬНЫЕ кейбинды, чтобы шорткат не увёл фокус на панель за оверлеем.
136
+ * Собственные клавиши оверлея идут мимо глобального реестра, поэтому не задеваются.
137
+ */
138
+ hasKeyboardCapturingOverlay() {
139
+ for (const session of this.sessions.values()) {
140
+ if (session.visible && session.options.capturesKeyboard)
141
+ return true;
142
+ }
143
+ return false;
144
+ }
145
+ clearAll() {
146
+ for (const session of this.sessions.values()) {
147
+ this.cleanupSessionListeners(session);
148
+ this.releaseFocusScope(session);
149
+ session.isDisposed = true;
150
+ }
151
+ this.sessions.clear();
152
+ for (const item of this.items) {
153
+ this.removeChild(item.element);
154
+ }
155
+ this.items = [];
156
+ this.markDirty();
157
+ }
158
+ getItems() {
159
+ return this.items;
160
+ }
161
+ /**
162
+ * Базовый обратный обход детей (скрытые сессии выпадают через hidden) +
163
+ * modal-хвост: модальная сессия проглатывает точку, не взятую элементами
164
+ * над ней, — клик не проваливается под оверлей.
165
+ */
166
+ hitTestChildren(point) {
167
+ const children = this.getChildren();
168
+ for (let i = children.length - 1; i >= 0; i--) {
169
+ const child = children[i];
170
+ const hit = child.elementFromPoint(point);
171
+ if (hit)
172
+ return hit;
173
+ if (this.isModalElement(child))
174
+ return child;
175
+ }
176
+ return null;
177
+ }
178
+ /** Слой прозрачен для кликов: мимо попапов точка уходит контенту под ним. */
179
+ hitTestSelf(_point) {
180
+ return false;
181
+ }
182
+ isModalElement(element) {
183
+ const session = this.sessions.get(element);
184
+ return session?.visible === true && session.options.pointerPolicy === "modal";
185
+ }
186
+ performLayout(constraints) {
187
+ const layerSize = super.performLayout(constraints);
188
+ for (const item of this.items) {
189
+ if (!item.visible)
190
+ continue;
191
+ // Constrain child so it doesn't overflow beyond the layer bounds
192
+ const availableWidth = Math.max(0, layerSize.width - item.position.x);
193
+ const availableHeight = Math.max(0, layerSize.height - item.position.y);
194
+ this.layoutChild(item.element, item.position.x, item.position.y, BoxConstraints.loose(new Size(availableWidth, availableHeight)));
195
+ }
196
+ return layerSize;
197
+ }
198
+ render(context) {
199
+ for (const item of this.items) {
200
+ if (!item.visible)
201
+ continue;
202
+ // Позиция — из localPosition (её выставил layoutChild), не из
203
+ // item.position: после layout авторитетна геометрия элемента (Н5).
204
+ // Клип по границам ребёнка — инвариант отрисовки (Н2): нарисованное
205
+ // не выходит за layoutSize, хит-зона совпадает с видимым.
206
+ const child = item.element;
207
+ const childOffset = new Offset(child.localPosition.dx, child.localPosition.dy);
208
+ const clip = new Rect(child.globalPosition, child.layoutSize);
209
+ const childContext = context.withOffset(childOffset).withClip(clip);
210
+ if (childContext.clipRect.isEmpty)
211
+ continue;
212
+ child.render(childContext);
213
+ }
214
+ }
215
+ openSession(session) {
216
+ if (session.visible || session.isDisposed)
217
+ return;
218
+ const root = this.getRoot();
219
+ const focusManager = root?.focusManager ?? null;
220
+ if (session.options.restoreFocus) {
221
+ session.savedFocus = focusManager?.activeElement ?? null;
222
+ }
223
+ session.visible = true;
224
+ this.setVisible(session.element, true);
225
+ this.attachSessionListeners(session);
226
+ if (focusManager && session.options.pointerPolicy === "modal" && !session.focusScopePushed) {
227
+ focusManager.pushFocusScope(session.element);
228
+ session.focusScopePushed = true;
229
+ }
230
+ if (session.options.focusOnOpen) {
231
+ session.element.focus();
232
+ }
233
+ }
234
+ releaseFocusScope(session) {
235
+ if (!session.focusScopePushed)
236
+ return;
237
+ const focusManager = this.getRoot()?.focusManager ?? null;
238
+ focusManager?.popFocusScope(session.element);
239
+ session.focusScopePushed = false;
240
+ }
241
+ closeSession(session) {
242
+ if (!session.visible || session.isDisposed)
243
+ return;
244
+ const root = this.getRoot();
245
+ const focusManager = root?.focusManager ?? null;
246
+ session.visible = false;
247
+ this.setVisible(session.element, false);
248
+ this.cleanupSessionListeners(session);
249
+ this.releaseFocusScope(session);
250
+ if (session.options.restoreFocus && session.savedFocus) {
251
+ focusManager?.setFocus(session.savedFocus);
252
+ session.savedFocus = null;
253
+ }
254
+ session.onClose?.();
255
+ if (session.options.disposeOnClose) {
256
+ this.disposeSession(session);
257
+ }
258
+ }
259
+ disposeSessionByElement(element) {
260
+ const session = this.sessions.get(element);
261
+ if (!session)
262
+ return;
263
+ this.disposeSession(session);
264
+ }
265
+ disposeSession(session) {
266
+ /* v8 ignore start -- defensive: a disposed session is removed from the map and clearAll sets isDisposed directly, so disposeSession is never re-entered for the same session */
267
+ if (session.isDisposed)
268
+ return;
269
+ /* v8 ignore stop */
270
+ if (session.visible) {
271
+ session.visible = false;
272
+ this.setVisible(session.element, false);
273
+ this.releaseFocusScope(session);
274
+ }
275
+ this.cleanupSessionListeners(session);
276
+ const index = this.items.findIndex((item) => item.element === session.element);
277
+ /* v8 ignore start -- defensive: createSession always adds the element to items, so a live session's element is always found here */
278
+ if (index >= 0) {
279
+ this.removeChild(this.items[index].element);
280
+ this.items.splice(index, 1);
281
+ }
282
+ /* v8 ignore stop */
283
+ session.isDisposed = true;
284
+ session.savedFocus = null;
285
+ this.sessions.delete(session.element);
286
+ this.markDirty();
287
+ }
288
+ attachSessionListeners(session) {
289
+ const root = this.getRoot();
290
+ if (!root)
291
+ return;
292
+ if (session.options.closeOnEscape && !session.rootEscapeHandler) {
293
+ session.rootEscapeHandler = (event) => {
294
+ /* v8 ignore start -- defensive: the handler is registered only for "keydown", so a non-keydown event never reaches it */
295
+ if (event.type !== "keydown")
296
+ return;
297
+ /* v8 ignore stop */
298
+ const keyEvent = event;
299
+ if (keyEvent.key !== "Escape" || event.defaultPrevented)
300
+ return;
301
+ // Владелец может перехватить Escape (закрыть только подменю).
302
+ if (session.shouldCloseOnEscape && !session.shouldCloseOnEscape())
303
+ return;
304
+ this.closeSession(session);
305
+ };
306
+ root.addEventListener("keydown", session.rootEscapeHandler, { capture: true });
307
+ }
308
+ if (session.options.pointerPolicy === "close-on-outside" && !session.rootOutsideHandler) {
309
+ session.rootOutsideHandler = (event) => {
310
+ /* v8 ignore start -- defensive: the handler is registered only for "mousedown", so a non-mousedown event never reaches it */
311
+ if (event.type !== "mousedown")
312
+ return;
313
+ /* v8 ignore stop */
314
+ if (event.target && isInsideElement(event.target, session.element))
315
+ return;
316
+ if (event.target && session.ownsTarget?.(event.target) === true)
317
+ return;
318
+ this.closeSession(session);
319
+ };
320
+ root.addEventListener("mousedown", session.rootOutsideHandler, { capture: true });
321
+ }
322
+ }
323
+ cleanupSessionListeners(session) {
324
+ const root = this.getRoot();
325
+ if (root && session.rootEscapeHandler) {
326
+ root.removeEventListener("keydown", session.rootEscapeHandler, { capture: true });
327
+ }
328
+ if (root && session.rootOutsideHandler) {
329
+ root.removeEventListener("mousedown", session.rootOutsideHandler, { capture: true });
330
+ }
331
+ session.rootEscapeHandler = null;
332
+ session.rootOutsideHandler = null;
333
+ }
334
+ }
335
+ function isInsideElement(element, ancestor) {
336
+ let current = element;
337
+ while (current !== null) {
338
+ if (current === ancestor)
339
+ return true;
340
+ current = current.getParent();
341
+ }
342
+ return false;
343
+ }
@@ -0,0 +1,4 @@
1
+ export type { AnyStyleToken, StyleToken } from "./styleTokens.js";
2
+ export { ROOT_VAR_SCOPE, STYLE_TOKEN_DEFAULTS } from "./styleTokens.js";
3
+ export type { ResolvedTUIStyle, StyleColor, StyleResolutionContext, StyleState, StyleStateSelector, StyleStateVariant, StyleVarScope, TUIStyle, } from "./tuiStyle.js";
4
+ export { extendVarScope, INHERITED_BG, INHERITED_FG, mergeStyleVariants, resolveStyle, resolveStyleColor, ROOT_RESOLVED_STYLE, ROOT_STYLE_CONTEXT, styleEquals, } from "./tuiStyle.js";
@@ -0,0 +1,2 @@
1
+ export { ROOT_VAR_SCOPE, STYLE_TOKEN_DEFAULTS } from "./styleTokens.js";
2
+ export { extendVarScope, INHERITED_BG, INHERITED_FG, mergeStyleVariants, resolveStyle, resolveStyleColor, ROOT_RESOLVED_STYLE, ROOT_STYLE_CONTEXT, styleEquals, } from "./tuiStyle.js";
@@ -0,0 +1,114 @@
1
+ import type { StyleVarScope } from "./tuiStyle.js";
2
+ /**
3
+ * Дефолтные значения цветовых токенов tuidom — единственное место, где у
4
+ * виджетов tuidom/ui есть RGB-литералы. Правило: токен, на который ссылается
5
+ * виджет, ОБЯЗАН иметь строку здесь — иначе резолв без хостовой таблицы
6
+ * (тесты, stories, standalone-использование) упадёт fail-fast'ом.
7
+ *
8
+ * Имена — в конвенции color id VS Code ("list.activeSelectionBackground"),
9
+ * чтобы хост перекрывал дефолты ключами своей темы без функций-мостов;
10
+ * tuidom-специфика без темного эквивалента — под собственным именем
11
+ * ("menu.shortcutForeground", "quickPick.*", "titledPanel.*", "menuBar.*").
12
+ * Значения — только конкретные числа (packed RGB | DEFAULT_COLOR); сентинелы
13
+ * INHERITED_* в таблицах запрещены (проверяется в setStyleVars).
14
+ *
15
+ * Дефолты сохраняют исторический вид unthemed-палитр, которые сюда переехали
16
+ * (Н3): под управлением хоста всё перекрывается активной темой.
17
+ */
18
+ export declare const STYLE_TOKEN_DEFAULTS: {
19
+ "button.foreground": number;
20
+ "button.background": number;
21
+ "button.hoverBackground": number;
22
+ "button.secondaryForeground": number;
23
+ "button.secondaryBackground": number;
24
+ "button.secondaryHoverBackground": number;
25
+ "menu.foreground": number;
26
+ "menu.background": number;
27
+ "menu.selectionForeground": number;
28
+ "menu.selectionBackground": number;
29
+ "menu.border": number;
30
+ "menu.separatorBackground": number;
31
+ "menu.shortcutForeground": number;
32
+ "menuBar.foreground": number;
33
+ "menuBar.background": number;
34
+ "menubar.selectionForeground": number;
35
+ "menubar.selectionBackground": number;
36
+ "list.activeSelectionBackground": number;
37
+ "list.activeSelectionForeground": number;
38
+ "list.inactiveSelectionBackground": number;
39
+ "list.inactiveSelectionForeground": number;
40
+ "list.hoverBackground": number;
41
+ "list.deemphasizedForeground": number;
42
+ "list.highlightForeground": number;
43
+ "scrollbarSlider.background": number;
44
+ "scrollbar.background": number;
45
+ "tab.activeForeground": number;
46
+ "tab.activeBackground": number;
47
+ "tab.inactiveForeground": number;
48
+ "tab.inactiveBackground": number;
49
+ "editorGroupHeader.tabsBackground": number;
50
+ "panel.background": number;
51
+ "panelTitle.inactiveForeground": number;
52
+ "panel.border": number;
53
+ "titledPanel.titleForeground": number;
54
+ "terminal.foreground": number;
55
+ "terminal.background": number;
56
+ "dropdown.foreground": number;
57
+ "dropdown.background": number;
58
+ "dropdown.border": number;
59
+ "dropdown.listBackground": number;
60
+ "input.foreground": number;
61
+ "input.background": number;
62
+ "input.placeholderForeground": number;
63
+ "input.border": number;
64
+ "input.selectionBackground": number;
65
+ focusBorder: number;
66
+ "sash.hoverBorder": number;
67
+ "quickInput.foreground": number;
68
+ "quickInput.background": number;
69
+ "quickPick.border": number;
70
+ "quickPick.badgeForeground": number;
71
+ "quickPick.shortcutForeground": number;
72
+ "quickPick.hintForeground": number;
73
+ "quickPick.titleForeground": number;
74
+ "quickPick.promptForeground": number;
75
+ descriptionForeground: number;
76
+ "editorSuggestWidget.border": number;
77
+ "editorSuggestWidget.background": number;
78
+ "editorSuggestWidget.foreground": number;
79
+ "editorSuggestWidget.selectedBackground": number;
80
+ "editorSuggestWidget.selectedForeground": number;
81
+ "editorSuggestWidget.iconForeground": number;
82
+ "editorSuggestWidget.detailForeground": number;
83
+ "editorWidget.foreground": number;
84
+ "editorWidget.background": number;
85
+ "editorWidget.border": number;
86
+ "textLink.foreground": number;
87
+ "editorLineNumber.foreground": number;
88
+ "editorLineNumber.activeForeground": number;
89
+ "editor.wordHighlightBackground": number;
90
+ "editorGutter.foldingControlForeground": number;
91
+ "editorIndentGuide.background1": number;
92
+ "editorIndentGuide.activeBackground1": number;
93
+ "editorError.foreground": number;
94
+ "editorWarning.foreground": number;
95
+ "editorInfo.foreground": number;
96
+ "editorHint.foreground": number;
97
+ "diffEditor.insertedLineBackground": number;
98
+ "diffEditor.removedLineBackground": number;
99
+ "diffEditor.unchangedRegionForeground": number;
100
+ };
101
+ /** Литеральный union имён токенов tuidom — автокомплит и проверка внутри tuidom/ui. */
102
+ export type StyleToken = keyof typeof STYLE_TOKEN_DEFAULTS;
103
+ /**
104
+ * Публичный тип имени токена: автокомплит по дефолтам сохраняется, но хост
105
+ * может ссылаться на произвольные ключи своей темы — опечатки в них ловит
106
+ * рантайм-fail-fast резолва (в первом же кадре), не компилятор.
107
+ */
108
+ export type AnyStyleToken = StyleToken | (string & {});
109
+ /**
110
+ * Дно прототипной цепочки var-scope'ов: замороженные дефолты с null-прототипом
111
+ * (лукап по цепочке не должен находить ключи Object.prototype). Пользовательские
112
+ * таблицы (setStyleVars) ложатся ПОВЕРХ через Object.create.
113
+ */
114
+ export declare const ROOT_VAR_SCOPE: StyleVarScope;