take4-console 0.15.0 → 0.25.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 (64) hide show
  1. package/CHANGELOG.md +365 -0
  2. package/README.md +1 -1
  3. package/dist/Screen/InterfaceBuilder.d.mts +15 -4
  4. package/dist/Screen/InterfaceBuilder.d.mts.map +1 -1
  5. package/dist/Screen/InterfaceBuilder.mjs +104 -8
  6. package/dist/Screen/InterfaceBuilder.mjs.map +1 -1
  7. package/dist/Screen/Pos.d.mts +12 -0
  8. package/dist/Screen/Pos.d.mts.map +1 -1
  9. package/dist/Screen/Pos.mjs +23 -1
  10. package/dist/Screen/Pos.mjs.map +1 -1
  11. package/dist/Screen/Screen.d.mts +77 -3
  12. package/dist/Screen/Screen.d.mts.map +1 -1
  13. package/dist/Screen/Screen.mjs +168 -3
  14. package/dist/Screen/Screen.mjs.map +1 -1
  15. package/dist/Screen/Size.d.mts +49 -6
  16. package/dist/Screen/Size.d.mts.map +1 -1
  17. package/dist/Screen/Size.mjs +81 -7
  18. package/dist/Screen/Size.mjs.map +1 -1
  19. package/dist/Screen/Window.d.mts +131 -20
  20. package/dist/Screen/Window.d.mts.map +1 -1
  21. package/dist/Screen/Window.mjs +474 -57
  22. package/dist/Screen/Window.mjs.map +1 -1
  23. package/dist/Screen/WindowManager.d.mts +85 -5
  24. package/dist/Screen/WindowManager.d.mts.map +1 -1
  25. package/dist/Screen/WindowManager.mjs +279 -26
  26. package/dist/Screen/WindowManager.mjs.map +1 -1
  27. package/dist/Screen/controls/ListBox.d.mts +34 -12
  28. package/dist/Screen/controls/ListBox.d.mts.map +1 -1
  29. package/dist/Screen/controls/ListBox.mjs +127 -25
  30. package/dist/Screen/controls/ListBox.mjs.map +1 -1
  31. package/dist/Screen/controls/TextArea.d.mts +15 -1
  32. package/dist/Screen/controls/TextArea.d.mts.map +1 -1
  33. package/dist/Screen/controls/TextArea.mjs +74 -1
  34. package/dist/Screen/controls/TextArea.mjs.map +1 -1
  35. package/dist/Screen/controls/TextBox.d.mts +13 -1
  36. package/dist/Screen/controls/TextBox.d.mts.map +1 -1
  37. package/dist/Screen/controls/TextBox.mjs +36 -1
  38. package/dist/Screen/controls/TextBox.mjs.map +1 -1
  39. package/dist/Screen/textWidth.d.mts +13 -0
  40. package/dist/Screen/textWidth.d.mts.map +1 -0
  41. package/dist/Screen/textWidth.mjs +188 -0
  42. package/dist/Screen/textWidth.mjs.map +1 -0
  43. package/dist/Screen/types.d.mts +336 -20
  44. package/dist/Screen/types.d.mts.map +1 -1
  45. package/dist/Screen/types.mjs.map +1 -1
  46. package/dist/index.d.mts +3 -2
  47. package/dist/index.d.mts.map +1 -1
  48. package/dist/index.mjs +3 -1
  49. package/dist/index.mjs.map +1 -1
  50. package/package.json +4 -4
  51. package/src/Screen/InterfaceBuilder.mts +116 -20
  52. package/src/Screen/Pos.mts +24 -1
  53. package/src/Screen/Screen.mts +192 -4
  54. package/src/Screen/Size.mts +97 -12
  55. package/src/Screen/Window.mts +463 -63
  56. package/src/Screen/WindowManager.mts +301 -29
  57. package/src/Screen/controls/ListBox.mts +151 -32
  58. package/src/Screen/controls/TextArea.mts +82 -1
  59. package/src/Screen/controls/TextBox.mts +40 -1
  60. package/src/Screen/textWidth.mts +186 -0
  61. package/src/Screen/types.mts +328 -23
  62. package/src/demo.mts +232 -20
  63. package/src/index.mts +23 -3
  64. package/src/layout.yaml +56 -24
@@ -1,22 +1,74 @@
1
1
  import { Pct } from './Pos.mjs';
2
+ /** Value object describing a flex dimension — `grow` shares positive leftover
3
+ * space between siblings, `shrink` soaks up negative leftover, `basis` is the
4
+ * starting main-axis size before distribution. Produced via the `flex()`
5
+ * factory and accepted anywhere a `Size` constructor expects a dimension. */
6
+ export class FlexDim {
7
+ grow;
8
+ shrink;
9
+ basis;
10
+ constructor(grow = 1, shrink = 1, basis = 0) {
11
+ this.grow = grow;
12
+ this.shrink = shrink;
13
+ this.basis = basis;
14
+ }
15
+ }
16
+ /** Singleton marker for content-sized dimensions. Produced via the `content()`
17
+ * factory; the layout engine measures the child's natural size (current
18
+ * Region dimensions) at layout time. */
19
+ export class ContentDim {
20
+ static INSTANCE = new ContentDim();
21
+ constructor() { }
22
+ }
23
+ /** Factory for a flex dimension — shorthand for `new FlexDim(grow, shrink, basis)`. */
24
+ export function flex(grow = 1, shrink = 1, basis = 0) {
25
+ return new FlexDim(grow, shrink, basis);
26
+ }
27
+ /** Factory for a content-sized dimension. Always returns the singleton. */
28
+ export function content() {
29
+ return ContentDim.INSTANCE;
30
+ }
31
+ /** Converts a basis literal to the internal FlexBasis representation. */
32
+ function toFlexBasis(v) {
33
+ if (v instanceof Pct)
34
+ return { kind: 'pct', value: v.value };
35
+ return { kind: 'abs', value: v };
36
+ }
2
37
  /** Converts a user-supplied dimension value to an internal DimSpec. */
3
38
  function toDimSpec(v) {
4
39
  if (v instanceof Pct)
5
40
  return { mode: 'pct', value: v.value };
41
+ if (v instanceof FlexDim)
42
+ return { mode: 'flex', grow: v.grow, shrink: v.shrink, basis: toFlexBasis(v.basis) };
43
+ if (v instanceof ContentDim)
44
+ return { mode: 'content' };
6
45
  return { mode: 'abs', value: v };
7
46
  }
8
- /** Resolves a single dimension spec to a pixel value. */
47
+ /** Resolves a single dimension spec to a pixel value. For modes whose final
48
+ * size is determined by the parent's layout engine (`flex`, `content`) this
49
+ * returns a safe fallback that keeps the region non-empty until the layout
50
+ * pass overwrites it — `flex` falls back to its basis, `content` to 1. */
9
51
  function resolveDim(spec, parentSize) {
10
- if (spec.mode === 'pct')
11
- return Math.floor(parentSize * spec.value / 100);
12
- return spec.value;
52
+ switch (spec.mode) {
53
+ case 'abs': return spec.value;
54
+ case 'pct': return Math.floor(parentSize * spec.value / 100);
55
+ case 'flex': return spec.basis.kind === 'pct'
56
+ ? Math.floor(parentSize * spec.basis.value / 100)
57
+ : spec.basis.value;
58
+ case 'content': return 1;
59
+ }
13
60
  }
14
- /** Encodes window dimensions. Supports absolute pixel values and percentage of parent size. */
61
+ /** Encodes window dimensions. Supports absolute pixel values, percentages of
62
+ * the parent, flex slots (`flex(grow, shrink, basis)`), and content-sized
63
+ * dimensions (`content()`). Flex and content modes only take effect inside a
64
+ * flex-layout parent (`WindowProperties.layout` set to 'row', 'column', or
65
+ * 'grid'); in 'absolute' layout they degrade to the fallback resolution. */
15
66
  export class Size {
16
67
  wSpec;
17
68
  hSpec;
18
69
  /** Creates a size from width and height values.
19
- * Pass a plain number for absolute pixels, or a Pct instance for a percentage of the parent. */
70
+ * Accepts plain numbers (absolute pixels), `Pct` (percentage of parent),
71
+ * `FlexDim` (via `flex()` factory), or `ContentDim` (via `content()`). */
20
72
  constructor(w, h) {
21
73
  this.wSpec = toDimSpec(w);
22
74
  this.hSpec = toDimSpec(h);
@@ -33,16 +85,38 @@ export class Size {
33
85
  static fillHeight(w) {
34
86
  return new Size(w, new Pct(100));
35
87
  }
88
+ /** Creates a size that flexes on both axes — shorthand for
89
+ * `new Size(flex(grow, shrink, basis), flex(grow, shrink, basis))`. The
90
+ * parent's layout engine decides which axis is main vs cross. */
91
+ static flex(grow = 1, shrink = 1, basis = 0) {
92
+ return new Size(flex(grow, shrink, basis), flex(grow, shrink, basis));
93
+ }
94
+ /** Creates a size where both axes are content-sized. The layout engine
95
+ * measures the child's current Region dimensions and uses those. */
96
+ static content() {
97
+ return new Size(content(), content());
98
+ }
36
99
  /** Returns true when both dimensions are absolute pixel values (no parent size needed). */
37
100
  isAbsolute() {
38
101
  return this.wSpec.mode === 'abs' && this.hSpec.mode === 'abs';
39
102
  }
40
- /** Resolves this size to pixel dimensions given the parent's dimensions. */
103
+ /** Resolves this size to pixel dimensions given the parent's dimensions.
104
+ * Flex/content modes fall back to safe defaults; the layout engine takes
105
+ * over when the parent uses a non-'absolute' `layout`. */
41
106
  resolve(parentW, parentH) {
42
107
  return {
43
108
  w: resolveDim(this.wSpec, parentW),
44
109
  h: resolveDim(this.hSpec, parentH),
45
110
  };
46
111
  }
112
+ /** Returns the raw width spec so the layout engine can inspect the mode
113
+ * (abs/pct/flex/content) and route each child accordingly. */
114
+ getWidthSpec() {
115
+ return this.wSpec;
116
+ }
117
+ /** Returns the raw height spec — companion to getWidthSpec(). */
118
+ getHeightSpec() {
119
+ return this.hSpec;
120
+ }
47
121
  }
48
122
  //# sourceMappingURL=Size.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"Size.mjs","sourceRoot":"","sources":["../../src/Screen/Size.mts"],"names":[],"mappings":"AACA,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAEhC,uEAAuE;AACvE,SAAS,SAAS,CAAC,CAAe;IACjC,IAAI,CAAC,YAAY,GAAG;QAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC;IAC7D,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;AAClC,CAAC;AAED,yDAAyD;AACzD,SAAS,UAAU,CAAC,IAAa,EAAE,UAAkB;IACpD,IAAI,IAAI,CAAC,IAAI,KAAK,KAAK;QAAE,OAAO,IAAI,CAAC,KAAK,CAAC,UAAU,GAAG,IAAI,CAAC,KAAK,GAAG,GAAG,CAAC,CAAC;IAC1E,OAAO,IAAI,CAAC,KAAK,CAAC;AACnB,CAAC;AAED,+FAA+F;AAC/F,MAAM,OAAO,IAAI;IACR,KAAK,CAAU;IACf,KAAK,CAAU;IAEvB;qGACiG;IACjG,YAAmB,CAAe,EAAE,CAAe;QAClD,IAAI,CAAC,KAAK,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;QAC1B,IAAI,CAAC,KAAK,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;IAC3B,CAAC;IAED,uEAAuE;IAChE,MAAM,CAAC,IAAI;QACjB,OAAO,IAAI,IAAI,CAAC,IAAI,GAAG,CAAC,GAAG,CAAC,EAAE,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;IAC7C,CAAC;IAED,8FAA8F;IACvF,MAAM,CAAC,SAAS,CAAC,CAAe;QACtC,OAAO,IAAI,IAAI,CAAC,IAAI,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;IAClC,CAAC;IAED,8FAA8F;IACvF,MAAM,CAAC,UAAU,CAAC,CAAe;QACvC,OAAO,IAAI,IAAI,CAAC,CAAC,EAAE,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;IAClC,CAAC;IAED,2FAA2F;IACpF,UAAU;QAChB,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,KAAK,KAAK,CAAC;IAC/D,CAAC;IAED,4EAA4E;IACrE,OAAO,CAAC,OAAe,EAAE,OAAe;QAC9C,OAAO;YACN,CAAC,EAAE,UAAU,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC;YAClC,CAAC,EAAE,UAAU,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC;SAClC,CAAC;IACH,CAAC;CACD"}
1
+ {"version":3,"file":"Size.mjs","sourceRoot":"","sources":["../../src/Screen/Size.mts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import type { Cell, StyleId, WindowBorder, WindowProperties, WriteTextOptions, TerminalSize } from './types.mjs';
1
+ import type { Cell, StyleId, WindowBorder, WindowProperties, WriteTextOptions, WriteTextInput, TerminalSize } from './types.mjs';
2
2
  import { Region } from './Region.mjs';
3
3
  import { StyleRegistry } from './StyleRegistry.mjs';
4
4
  export declare class Window {
@@ -30,20 +30,45 @@ export declare class Window {
30
30
  private active;
31
31
  private posSpec;
32
32
  private sizeSpec;
33
+ /** Whether this window participates in rendering. When false, the window's own
34
+ * render() is a no-op, its region is not blitted onto the parent, and
35
+ * `getCell()` throws. Focus-cycle in WindowManager skips invisible focusable
36
+ * controls. Default: true. */
37
+ private visible;
38
+ /** Layout algorithm applied to direct children. 'absolute' keeps the pre-flex
39
+ * behaviour; 'row' / 'column' / 'grid' activate the flex engine. */
40
+ private layoutMode;
41
+ /** Spacing (in cells) between adjacent children for flex / grid layouts. */
42
+ private gap;
43
+ /** Padding applied inside the border (in addition to the border inset).
44
+ * Influences `getInnerSize()` / `getInnerOffset()`. */
45
+ private padding;
46
+ /** Number of columns for `layout: 'grid'`. */
47
+ private gridColumns;
48
+ /** Cross-axis alignment for row/column layouts. */
49
+ private alignItems;
50
+ /** Main-axis distribution of leftover space when no flex-grow child consumes it. */
51
+ private justifyContent;
33
52
  /** Creates a window from the given properties.
34
53
  * For percentage-based sizes, call addChild() before writing content to the window.
35
54
  * Uses the global StyleRegistry set by the Screen constructor. */
36
55
  constructor(wp: WindowProperties);
37
56
  /** Returns the window dimensions (columns × rows). */
38
57
  getSize(): TerminalSize;
39
- /** Returns the number of cells consumed by decorations on each edge. */
58
+ /** Returns the number of cells consumed by decorations on each edge.
59
+ * The explicit 'none' border style is treated as no border (no insets). */
40
60
  private borderInset;
41
- /** Returns the top-left offset of the content area, accounting for decorations such as borders. */
61
+ /** Returns the combined per-side inset (border + padding) that defines the
62
+ * inner content area. Padding stacks on top of the border inset. */
63
+ private innerInset;
64
+ /** Returns the top-left offset of the content area, accounting for
65
+ * decorations (border) and layout insets (padding). */
42
66
  getInnerOffset(): {
43
67
  x: number;
44
68
  y: number;
45
69
  };
46
- /** Returns the dimensions of the content area, accounting for decorations such as borders. */
70
+ /** Returns the dimensions of the content area, accounting for decorations
71
+ * (border) and layout insets (padding). */
47
72
  getInnerSize(): TerminalSize;
48
73
  /** Sets the active state. Affects border and background appearance on next render(). */
49
74
  setActive(active: boolean): void;
@@ -55,6 +80,14 @@ export declare class Window {
55
80
  setDisabled(disabled: boolean): void;
56
81
  /** Returns whether this window is currently disabled. */
57
82
  isDisabled(): boolean;
83
+ /** Shows or hides the window. A hidden window does not paint itself, is not
84
+ * blitted onto its parent, and its focusable descendants are skipped by
85
+ * `WindowManager.moveFocus / setFocus`. Toggling visibility does not mutate
86
+ * the content buffer — previously written cells reappear verbatim on the
87
+ * next render after the window is shown again. */
88
+ setVisible(visible: boolean): void;
89
+ /** Returns whether this window is currently visible. Default: true. */
90
+ isVisible(): boolean;
58
91
  /** Sets the label text displayed by the control. */
59
92
  setLabel(label: string): void;
60
93
  /** Returns the current label text. */
@@ -66,12 +99,17 @@ export declare class Window {
66
99
  * Called automatically at the start of render() so subclasses never need to do it manually.
67
100
  * Only updates the color when no explicit color was provided in the original border config. */
68
101
  private syncBorderColor;
69
- /** Adds a child window. If the child uses percentage-based sizes they are resolved immediately
70
- * against this window's inner dimensions (excluding decorations such as borders).
71
- * Position is resolved relative to the inner area and stored on child.x/y. */
102
+ /** Adds a child window. The final position and (for non-absolute sizes) the
103
+ * final dimensions are computed by the parent's layout engine: in
104
+ * 'absolute' layout each child resolves its own Pos/Size; in 'row',
105
+ * 'column', or 'grid' layouts the engine distributes the inner area
106
+ * across every visible child. Re-laying out on addChild keeps sibling
107
+ * geometry consistent when more children join the stack. */
72
108
  addChild(child: Window): void;
73
109
  /** Returns a resolved Cell (char + CellAttributes) at (x, y) from the display buffer.
74
- * Throws RangeError if out of bounds. */
110
+ * Throws RangeError if out of bounds. Throws Error when the window is
111
+ * currently hidden (setVisible(false)) — callers should check isVisible()
112
+ * first when the visibility state is uncertain. */
75
113
  getCell(x: number, y: number): Cell;
76
114
  /** Sets only the character at (x, y) without modifying the style ID. Throws RangeError if out of bounds. */
77
115
  setChar(x: number, y: number, char: string): void;
@@ -86,14 +124,47 @@ export declare class Window {
86
124
  fill(char: string, styleId?: StyleId): void;
87
125
  /** Writes text into the window's content area starting at (x, y) (default 0, 0).
88
126
  * Coordinates are relative to the inner content area (i.e. decorations such as borders are excluded).
89
- * Newline characters move to the next row, resetting x to startX.
90
- * Characters outside the inner bounds are silently clipped.
91
- * When no style is provided, automatically picks disabledStyleId, focusedStyleId, or normalStyleId
92
- * based on the current disabled/focused state. */
93
- writeText(text: string, options?: WriteTextOptions): void;
127
+ *
128
+ * Accepts either a plain string (one base style for the whole text) or an array of
129
+ * `WriteTextSegment`s so inline rich text can be laid out without separate writeText()
130
+ * calls — the cursor flows from one segment into the next on the same row. Each segment
131
+ * may pin its own style either as a pre-registered `style: StyleId` or as inline
132
+ * `attrs: CellAttributes` (registered on the fly). The segment style is merged on top
133
+ * of the base style so global defaults (e.g. foreground) keep applying unless overridden.
134
+ *
135
+ * Behaviour shared with the single-string form:
136
+ * - Newline characters move to the next row, resetting x to startX.
137
+ * - Characters outside the inner bounds are silently clipped.
138
+ * - Wide characters (CJK, emoji, double-width NerdFonts) occupy two consecutive cells;
139
+ * the second cell stores '' as a continuation sentinel so terminal cursor advancement
140
+ * during render() stays aligned with the buffer indices. Wide chars whose right half
141
+ * would overflow the inner area are skipped entirely.
142
+ * - Zero-width codepoints (combining marks, format chars, control chars) are skipped.
143
+ * - When no style is provided, the base style is auto-picked from disabled / focused /
144
+ * normal state. Pass `options.style = 0` to suppress the state-based base style. */
145
+ writeText(input: WriteTextInput, options?: WriteTextOptions): void;
146
+ /** Writes a template that embeds named styles from the StyleRegistry.
147
+ * Syntax is a mini-markup: `{name}…{/}` wraps an inline region in the style
148
+ * registered under `name` (e.g. a built-in name like `builtin:text-focused` or a
149
+ * user-registered custom name). Nested tags inherit attributes from their parent
150
+ * — the inner style is merged on top of the outer one, so `{red}a{bold}b{/}c{/}`
151
+ * renders `a` in red, `b` in red+bold, `c` in red. `{/}` closes the most recently
152
+ * opened tag. Unknown names keep the surrounding style unchanged. `{{` and `}}`
153
+ * escape literal braces. The template is compiled to an array of
154
+ * `WriteTextSegment`s and written via writeText(), so line-wrap, width, and
155
+ * clipping rules are inherited. */
156
+ writeMarkup(template: string, options?: WriteTextOptions): void;
157
+ /** Returns the display width (in terminal cells) of a string,
158
+ * honouring wide characters (CJK, emoji, double-width NerdFonts) and
159
+ * ignoring zero-width codepoints. Useful for sizing labels or aligning
160
+ * text in custom controls. */
161
+ getTextWidth(text: string): number;
94
162
  /**
95
163
  * Builds the display buffer: background → user content → border → children.
96
164
  * The result is stored in region and used by blitChild / Screen.render().
165
+ * A hidden window (setVisible(false)) returns immediately so neither its
166
+ * own paint stages nor its children contribute to the frame; hidden
167
+ * children are also skipped in the loop below.
97
168
  */
98
169
  render(): void;
99
170
  /** Fills the display buffer with the background style. When inactive, adds dim to every cell.
@@ -101,20 +172,60 @@ export declare class Window {
101
172
  private paintBackground;
102
173
  /** Overlays user-written content onto the display buffer, merging with any background already set. */
103
174
  private blitContent;
104
- /** Draws border characters on the display buffer edges. When inactive, adds dim to border cells. */
175
+ /** Draws border characters on the display buffer edges. When inactive, adds dim to border cells.
176
+ * Uses the glyph table for `border.style`, with optional per-character overrides
177
+ * via `border.chars`. The 'none' style is a no-op placeholder. */
105
178
  private paintBorder;
106
- /** Copies a child's display buffer onto this window's display buffer, clipping to this window's bounds.
107
- * Styles are transferred from the child's registry into this window's registry.
108
- * Position is re-resolved from the child's Pos spec relative to the inner content area on every render. */
179
+ /** Copies a child's display buffer onto this window's display buffer,
180
+ * clipping to this window's bounds. Styles are transferred from the child's
181
+ * registry into this window's registry. The child's (x, y) was computed by
182
+ * the layout engine on addChild / reflowChildren / setSize, so blit can
183
+ * read it directly — this keeps absolute and flex paths on the same code. */
109
184
  private blitChild;
110
185
  /** Removes a previously added child window. No-op if the child is not found. */
111
186
  removeChild(child: Window): void;
112
187
  /** Replaces both internal regions with new ones of the given dimensions,
113
188
  * then re-resolves sizes and positions of all direct children against the updated inner area. */
114
- private resizeRegions;
115
- /** Re-resolves sizes and absolute positions for every direct child against the current inner area.
116
- * Called after this window is resized so that percentage-based children get correct dimensions. */
189
+ protected resizeRegions(w: number, h: number): void;
190
+ /** Resizes this window to the given absolute dimensions and reflows every
191
+ * descendant whose size or position is percentage-based against the new
192
+ * inner area. Existing absolute children keep their declared geometry but
193
+ * have their stored x/y refreshed by reflowChildren() so the parent's
194
+ * border insets still apply. The previously written content is discarded
195
+ * — callers that need to preserve it must redraw after setSize(). */
196
+ setSize(width: number, height: number): void;
197
+ /** Re-resolves sizes and absolute positions for every direct child against
198
+ * the current inner area. Delegates to the layout engine so percentage
199
+ * children, flex children, and grid cells are all updated from the same
200
+ * code path. Called after this window is resized or a new child is added. */
117
201
  private reflowChildren;
202
+ /** Runs the layout engine against the current inner area. Dispatches to
203
+ * absolute / row / column / grid implementations based on `layoutMode`. */
204
+ private runLayout;
205
+ /** Absolute layout: each child independently resolves its Pos/Size against
206
+ * the parent's inner area — the pre-flex behaviour. */
207
+ private layoutAbsolute;
208
+ /** Row / column flex layout. The main axis (width for 'row', height for
209
+ * 'column') is distributed across children: each child starts with its
210
+ * basis (abs → value, pct → fraction of parent, flex → flex basis,
211
+ * content → measured natural size), then remaining slack is distributed
212
+ * pro rata by `grow`, and negative slack by `shrink`. The cross axis is
213
+ * aligned via `alignItems` — 'stretch' expands flex/content children to
214
+ * the full inner cross dimension. `justifyContent` governs leftover
215
+ * distribution only when no child consumes slack via flex-grow. Invisible
216
+ * children are skipped so `setVisible(false)` effectively removes them
217
+ * from the stack. Children are ordered by `Pos.flex(order)` first, then
218
+ * by addChild insertion (stable). */
219
+ private layoutFlex;
220
+ /** Grid layout: children are placed row-major into equally sized cells.
221
+ * Each cell's width is `(innerWidth - gap * (cols - 1)) / cols` (floored);
222
+ * heights use the same formula with the derived row count. Children are
223
+ * resized to the cell dimensions and positioned at the cell's top-left.
224
+ * Invisible children are skipped. */
225
+ private layoutGrid;
226
+ /** Returns visible children sorted by Pos.flex(order) ascending; children
227
+ * without Pos.flex default to order 0. Stable w.r.t. addChild insertion. */
228
+ private orderedVisibleChildren;
118
229
  /** Returns the flat index for (x, y) in the region buffer (used by getCell). */
119
230
  private flatIndex;
120
231
  }
@@ -1 +1 @@
1
- {"version":3,"file":"Window.d.mts","sourceRoot":"","sources":["../../src/Screen/Window.mts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Window.d.mts","sourceRoot":"","sources":["../../src/Screen/Window.mts"],"names":[],"mappings":"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"}