take4-console 0.15.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 (131) hide show
  1. package/CHANGELOG.md +287 -0
  2. package/LICENSE +21 -0
  3. package/README.md +986 -0
  4. package/dist/Screen/InterfaceBuilder.d.mts +43 -0
  5. package/dist/Screen/InterfaceBuilder.d.mts.map +1 -0
  6. package/dist/Screen/InterfaceBuilder.mjs +355 -0
  7. package/dist/Screen/InterfaceBuilder.mjs.map +1 -0
  8. package/dist/Screen/Pos.d.mts +52 -0
  9. package/dist/Screen/Pos.d.mts.map +1 -0
  10. package/dist/Screen/Pos.mjs +105 -0
  11. package/dist/Screen/Pos.mjs.map +1 -0
  12. package/dist/Screen/Region.d.mts +31 -0
  13. package/dist/Screen/Region.d.mts.map +1 -0
  14. package/dist/Screen/Region.mjs +73 -0
  15. package/dist/Screen/Region.mjs.map +1 -0
  16. package/dist/Screen/RegistryHolder.d.mts +6 -0
  17. package/dist/Screen/RegistryHolder.d.mts.map +1 -0
  18. package/dist/Screen/RegistryHolder.mjs +14 -0
  19. package/dist/Screen/RegistryHolder.mjs.map +1 -0
  20. package/dist/Screen/Screen.d.mts +25 -0
  21. package/dist/Screen/Screen.d.mts.map +1 -0
  22. package/dist/Screen/Screen.mjs +100 -0
  23. package/dist/Screen/Screen.mjs.map +1 -0
  24. package/dist/Screen/Size.d.mts +23 -0
  25. package/dist/Screen/Size.d.mts.map +1 -0
  26. package/dist/Screen/Size.mjs +48 -0
  27. package/dist/Screen/Size.mjs.map +1 -0
  28. package/dist/Screen/StyleRegistry.d.mts +32 -0
  29. package/dist/Screen/StyleRegistry.d.mts.map +1 -0
  30. package/dist/Screen/StyleRegistry.mjs +80 -0
  31. package/dist/Screen/StyleRegistry.mjs.map +1 -0
  32. package/dist/Screen/Window.d.mts +121 -0
  33. package/dist/Screen/Window.d.mts.map +1 -0
  34. package/dist/Screen/Window.mjs +407 -0
  35. package/dist/Screen/Window.mjs.map +1 -0
  36. package/dist/Screen/WindowManager.d.mts +86 -0
  37. package/dist/Screen/WindowManager.d.mts.map +1 -0
  38. package/dist/Screen/WindowManager.mjs +399 -0
  39. package/dist/Screen/WindowManager.mjs.map +1 -0
  40. package/dist/Screen/controls/BarChart.d.mts +29 -0
  41. package/dist/Screen/controls/BarChart.d.mts.map +1 -0
  42. package/dist/Screen/controls/BarChart.mjs +90 -0
  43. package/dist/Screen/controls/BarChart.mjs.map +1 -0
  44. package/dist/Screen/controls/Button.d.mts +16 -0
  45. package/dist/Screen/controls/Button.d.mts.map +1 -0
  46. package/dist/Screen/controls/Button.mjs +34 -0
  47. package/dist/Screen/controls/Button.mjs.map +1 -0
  48. package/dist/Screen/controls/Checkbox.d.mts +23 -0
  49. package/dist/Screen/controls/Checkbox.d.mts.map +1 -0
  50. package/dist/Screen/controls/Checkbox.mjs +55 -0
  51. package/dist/Screen/controls/Checkbox.mjs.map +1 -0
  52. package/dist/Screen/controls/LineChart.d.mts +29 -0
  53. package/dist/Screen/controls/LineChart.d.mts.map +1 -0
  54. package/dist/Screen/controls/LineChart.mjs +172 -0
  55. package/dist/Screen/controls/LineChart.mjs.map +1 -0
  56. package/dist/Screen/controls/ListBox.d.mts +34 -0
  57. package/dist/Screen/controls/ListBox.d.mts.map +1 -0
  58. package/dist/Screen/controls/ListBox.mjs +138 -0
  59. package/dist/Screen/controls/ListBox.mjs.map +1 -0
  60. package/dist/Screen/controls/ProgressBar.d.mts +26 -0
  61. package/dist/Screen/controls/ProgressBar.d.mts.map +1 -0
  62. package/dist/Screen/controls/ProgressBar.mjs +70 -0
  63. package/dist/Screen/controls/ProgressBar.mjs.map +1 -0
  64. package/dist/Screen/controls/ProgressBarV.d.mts +22 -0
  65. package/dist/Screen/controls/ProgressBarV.d.mts.map +1 -0
  66. package/dist/Screen/controls/ProgressBarV.mjs +61 -0
  67. package/dist/Screen/controls/ProgressBarV.mjs.map +1 -0
  68. package/dist/Screen/controls/Radio.d.mts +23 -0
  69. package/dist/Screen/controls/Radio.d.mts.map +1 -0
  70. package/dist/Screen/controls/Radio.mjs +55 -0
  71. package/dist/Screen/controls/Radio.mjs.map +1 -0
  72. package/dist/Screen/controls/Sparkline.d.mts +29 -0
  73. package/dist/Screen/controls/Sparkline.d.mts.map +1 -0
  74. package/dist/Screen/controls/Sparkline.mjs +82 -0
  75. package/dist/Screen/controls/Sparkline.mjs.map +1 -0
  76. package/dist/Screen/controls/Spinner.d.mts +37 -0
  77. package/dist/Screen/controls/Spinner.d.mts.map +1 -0
  78. package/dist/Screen/controls/Spinner.mjs +87 -0
  79. package/dist/Screen/controls/Spinner.mjs.map +1 -0
  80. package/dist/Screen/controls/StatusLED.d.mts +22 -0
  81. package/dist/Screen/controls/StatusLED.d.mts.map +1 -0
  82. package/dist/Screen/controls/StatusLED.mjs +51 -0
  83. package/dist/Screen/controls/StatusLED.mjs.map +1 -0
  84. package/dist/Screen/controls/Tabs.d.mts +42 -0
  85. package/dist/Screen/controls/Tabs.d.mts.map +1 -0
  86. package/dist/Screen/controls/Tabs.mjs +126 -0
  87. package/dist/Screen/controls/Tabs.mjs.map +1 -0
  88. package/dist/Screen/controls/TextArea.d.mts +41 -0
  89. package/dist/Screen/controls/TextArea.d.mts.map +1 -0
  90. package/dist/Screen/controls/TextArea.mjs +197 -0
  91. package/dist/Screen/controls/TextArea.mjs.map +1 -0
  92. package/dist/Screen/controls/TextBox.d.mts +35 -0
  93. package/dist/Screen/controls/TextBox.d.mts.map +1 -0
  94. package/dist/Screen/controls/TextBox.mjs +135 -0
  95. package/dist/Screen/controls/TextBox.mjs.map +1 -0
  96. package/dist/Screen/types.d.mts +399 -0
  97. package/dist/Screen/types.d.mts.map +1 -0
  98. package/dist/Screen/types.mjs +22 -0
  99. package/dist/Screen/types.mjs.map +1 -0
  100. package/dist/index.d.mts +26 -0
  101. package/dist/index.d.mts.map +1 -0
  102. package/dist/index.mjs +41 -0
  103. package/dist/index.mjs.map +1 -0
  104. package/package.json +72 -0
  105. package/src/Screen/InterfaceBuilder.mts +403 -0
  106. package/src/Screen/Pos.mts +119 -0
  107. package/src/Screen/Region.mts +88 -0
  108. package/src/Screen/RegistryHolder.mts +16 -0
  109. package/src/Screen/Screen.mts +103 -0
  110. package/src/Screen/Size.mts +55 -0
  111. package/src/Screen/StyleRegistry.mts +95 -0
  112. package/src/Screen/Window.mts +439 -0
  113. package/src/Screen/WindowManager.mts +472 -0
  114. package/src/Screen/controls/BarChart.mts +109 -0
  115. package/src/Screen/controls/Button.mts +40 -0
  116. package/src/Screen/controls/Checkbox.mts +66 -0
  117. package/src/Screen/controls/LineChart.mts +202 -0
  118. package/src/Screen/controls/ListBox.mts +154 -0
  119. package/src/Screen/controls/ProgressBar.mts +88 -0
  120. package/src/Screen/controls/ProgressBarV.mts +77 -0
  121. package/src/Screen/controls/Radio.mts +66 -0
  122. package/src/Screen/controls/Sparkline.mts +101 -0
  123. package/src/Screen/controls/Spinner.mts +102 -0
  124. package/src/Screen/controls/StatusLED.mts +65 -0
  125. package/src/Screen/controls/Tabs.mts +140 -0
  126. package/src/Screen/controls/TextArea.mts +194 -0
  127. package/src/Screen/controls/TextBox.mts +139 -0
  128. package/src/Screen/types.mts +416 -0
  129. package/src/demo.mts +171 -0
  130. package/src/index.mts +105 -0
  131. package/src/layout.yaml +236 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,287 @@
1
+ # Changelog
2
+
3
+ ## [0.15.0] – 2026-04-12
4
+
5
+ ### Changed
6
+ - **Border defaults moved to `Window`** – each control now declares its default
7
+ border shape via `defaultBorder` in `WindowProperties` instead of overriding
8
+ `border: wp.border ?? { ... }` in the constructor. `Window` resolves the final
9
+ border as `wp.border ?? wp.defaultBorder`.
10
+ - **Border color synced automatically** – `Window.render()` calls a private
11
+ `syncBorderColor()` before painting the border. It updates the border color
12
+ based on the current `disabled`/`focused` state using `BUILTIN_BORDER_DISABLED`,
13
+ `BUILTIN_BORDER_FOCUSED`, and `BUILTIN_BORDER`. Controls no longer call
14
+ `updateBorder({ ..., color })` at the start of every `render()`.
15
+ - **Text style auto-picked in `writeText()`** – when no `style` option is
16
+ provided, `writeText()` automatically selects `disabledStyleId`, `focusedStyleId`,
17
+ or `normalStyleId` based on the current control state. Controls only pass an
18
+ explicit style for non-standard cases (e.g. `checkedStyleId`, `placeholderStyleId`).
19
+ - **`focusedStyleId` promoted to `Window`** – initialized from `BUILTIN_TEXT_FOCUSED`,
20
+ shared by all interactive controls; per-control `focusedStyleId` fields removed.
21
+ - **`Window` background default changed** – background now defaults to 0
22
+ (transparent) when not specified in `WindowProperties`; the BUILTIN_WINDOW_BG
23
+ fallback is the responsibility of each control that needs it.
24
+
25
+ ## [0.14.0] – 2026-04-12
26
+
27
+ ### Changed
28
+ - **Common control properties moved to `Window`** – `focused`, `disabled`,
29
+ `label`, `normalStyleId`, and `disabledStyleId` fields plus their
30
+ getters/setters (`setFocused`/`isFocused`, `setDisabled`/`isDisabled`,
31
+ `setLabel`/`getLabel`) now live in the `Window` base class as protected fields
32
+ with public accessors. All 14 controls no longer duplicate these declarations.
33
+ - `setDisabled()` automatically calls `setActive(!disabled)` to keep the two
34
+ flags in sync.
35
+ - Read-only controls (StatusLED, ProgressBar, ProgressBarV, LineChart, BarChart,
36
+ Sparkline, Spinner) no longer override `isFocused()`/`setFocused()`/`isDisabled()`
37
+ as no-ops — the inherited `Window` implementation is used instead.
38
+ - Renamed internal style fields for consistency: `TextBox`/`TextArea`
39
+ `textStyleId` → `normalStyleId`; `Tabs` `normalTextStyleId` → `normalStyleId`,
40
+ `disabledTextStyleId` → `disabledStyleId`.
41
+
42
+ ## [0.13.0] – 2026-04-12
43
+
44
+ ### Changed
45
+ - **Global StyleRegistry singleton** – eliminated the `registry?: StyleRegistry`
46
+ parameter from every constructor (`Window`, all 14 controls). Instead, a single
47
+ `StyleRegistry` is created by the `Screen` constructor and stored in a new
48
+ module-level singleton (`src/Screen/RegistryHolder.mts`). All windows and
49
+ controls automatically use that shared registry via `getRegistry()` without any
50
+ explicit wiring. `InterfaceBuilder` no longer threads a registry argument through
51
+ its internal `buildNode` helper.
52
+ - `Screen.getStyleRegistry()`, `Screen.registerStyle()`, and
53
+ `Screen.setBuiltinStyle()` are preserved and now delegate to the singleton.
54
+ - New internal module `RegistryHolder.mts` exports `getRegistry()` /
55
+ `setRegistry()` – avoids circular imports between `Screen` and `Window`.
56
+
57
+ ## [0.12.0] – 2026-04-12
58
+
59
+ ### Added
60
+ - **Library packaging** – the project now ships as a reusable npm package:
61
+ - New `src/index.mts` barrel re-exports every public class, type, and
62
+ built-in style constant (`Screen`, `Window`, `WindowManager`, all 15
63
+ controls, `InterfaceBuilder`, `Pos`/`Size`/`Pct`/`pct`, all `*Options`
64
+ interfaces, YAML schema types, `BUILTIN_*` constants)
65
+ - `package.json` fields for publishing: `exports` map (ESM-only with
66
+ type-aware conditional exports), `types`, `module`, `files`,
67
+ `sideEffects: false`, `engines: node >= 18`, `keywords`, `repository`,
68
+ `bugs`, `homepage`, `license`, `author`, and a `prepublishOnly` script
69
+ that runs build + tests
70
+ - `LICENSE` file (MIT)
71
+ - `npm run demo` script – alias for the tsx-based dev command
72
+
73
+ ### Changed
74
+ - **Demo entry point** moved from `src/index.mts` to `src/demo.mts`. The
75
+ library's `main`/`exports` now point at `dist/index.mjs` (the barrel),
76
+ so `import { Screen } from 'take4-console'` no longer accidentally runs
77
+ the demo — **breaking change for anyone importing the old internal
78
+ index.mts path**
79
+ - `tsconfig.json` excludes `src/demo.mts` from the library build (the demo
80
+ is tsx-only so `layout.yaml` keeps resolving from `src/` via
81
+ `import.meta.url`)
82
+ - README rewritten with an **Installation**, **Quick start**, **Public
83
+ API**, and **Running the bundled demo** section at the top; the
84
+ existing architecture / custom-control / YAML reference content is kept
85
+ below with a note that the example imports use relative paths because
86
+ they target in-repo extension
87
+
88
+ ---
89
+
90
+ ## [0.11.0] – 2026-04-12
91
+
92
+ ### Added
93
+ - **`ListBox`** – scrollable, focusable list of single-line items; supports ↑/↓, Home/End, PgUp/PgDn with automatic scrolling; emits `onChange(index, item)` when the selection moves
94
+ - **`Tabs`** – tabbed container that renders a header row and composites only the children tagged to the active tab; focusable with ←/→ to cycle tabs; new `addChildToTab(tabIndex, child)` API tags children without affecting standard `addChild()` semantics
95
+ - **`Sparkline`** – read-only one-row inline chart built from the eight-level block-character ramp (` ▁▂▃▄▅▆▇█`); supports width/data resampling via linear interpolation
96
+ - **`Spinner`** – read-only animated loader with five built-in frame styles (`braille`, `dots`, `line`, `circle`, `arrow`); advances via `step()` driven by an external clock; supports optional label to the right of the glyph
97
+ - New option interfaces: `ListBoxOptions`, `TabsOptions`, `SparklineOptions`, `SpinnerOptions`
98
+ - Extended `YamlWindowType` with `listbox`, `tabs`, `sparkline`, `spinner`
99
+ - New `YamlWindowDef.tab` field – when the parent is a `Tabs` control, children with a `tab:` field are routed through `addChildToTab()` automatically
100
+
101
+ ### Changed
102
+ - **`LineChart.render()`** – rewrote the plotting pipeline: every plot column now receives an interpolated row via linear interpolation between data samples, and vertical transitions are drawn as self-contained steps (`╯│╭` / `╮│╰`) instead of disjoint per-data-point cells. Fixes the "jagged" / disconnected appearance when plot width exceeds the data-point count. The buggy `selectLineChar` enter/exit lookup table (which had `up`/`down` corner characters swapped) has been removed entirely.
103
+ - **Demo (`index.mts` + `layout.yaml`)** – added a `LIVE` braille spinner to the header, replaced the bottom-right charts panel with a three-tab `Tabs` control (Charts / Trends / Events) showing the original `LineChart`+`BarChart` on tab 0, three stacked `Sparkline` histories on tab 1, and a scrolling `ListBox` event log on tab 2. The timer now advances the spinner, shifts rolling sparkline buffers in sync with the progress bars, and prepends timestamped log entries to the event list.
104
+
105
+ ---
106
+
107
+ ## [0.10.0] – 2026-04-12
108
+
109
+ ### Added
110
+ - **`StatusLED`** – read-only coloured status indicator (states: `ok`/`warn`/`error`/`off`; auto-sizes to label width)
111
+ - **`ProgressBar`** – horizontal progress bar using `█`/`░` block characters with optional centred percentage label
112
+ - **`ProgressBarV`** – vertical progress bar filling from the bottom upward
113
+ - **`LineChart`** – line chart using box-drawing characters (`─`, `│`, `╭`, `╮`, `╯`, `╰`) with Y-axis labels and X-axis
114
+ - **`BarChart`** – vertical bar chart with `█` columns and single-character labels in the bottom row
115
+ - All five controls are read-only (`isFocused()` always `false`) and YAML-compatible via `InterfaceBuilder` using types `statusled`, `progressbar`, `progressbarv`, `linechart`, `barchart`
116
+ - New option interfaces in `types.mts`: `StatusLEDOptions`, `ProgressBarOptions`, `ProgressBarVOptions`, `LineChartOptions`, `BarChartOptions`
117
+ - Extended `YamlWindowType` and `YamlWindowDef` to support the new controls
118
+
119
+ ---
120
+
121
+ ## [0.9.0] – 2026-04-12
122
+
123
+ ### Added
124
+ - **Built-in named style system** – `Screen` pre-registers ten default styles under well-known names; controls look them up by name at render time and fall back to hardcoded defaults if the registry is fresh:
125
+ - `BUILTIN_WINDOW_BG` (`builtin:window-bg`) – default background for windows and controls
126
+ - `BUILTIN_BORDER` / `BUILTIN_BORDER_FOCUSED` / `BUILTIN_BORDER_DISABLED` – border foreground colours
127
+ - `BUILTIN_TEXT` / `BUILTIN_TEXT_FOCUSED` / `BUILTIN_TEXT_DISABLED` / `BUILTIN_TEXT_PLACEHOLDER` / `BUILTIN_TEXT_CHECKED` – text colour variants
128
+ - `BUILTIN_CURSOR` (`builtin:cursor`) – cursor inverse-highlight style
129
+ - **`StyleRegistry.registerNamed(name, attrs)`** – registers a style under a string name and returns its stable ID
130
+ - **`StyleRegistry.getNamed(name)`** – returns the StyleId associated with a name, or `undefined`
131
+ - **`StyleRegistry.getNamedForeground(name, fallback)`** – convenience helper that resolves the foreground `Color` of a named style (used by controls for border colours)
132
+ - **`Screen.setBuiltinStyle(name, attrs)`** – overrides any named style (built-in or custom) and returns the new ID; controls pick up the change on their next `render()` call
133
+ - **YAML `styles:` section** – `InterfaceBuilder` now parses an optional `styles:` list at the top of the layout document and registers each entry in `StyleRegistry` before building windows:
134
+ ```yaml
135
+ styles:
136
+ - name: my-panel-bg
137
+ background: 235
138
+ - name: builtin:border-focused # override built-in
139
+ foreground: 214 # amber focused border
140
+ windows:
141
+ - background: my-panel-bg
142
+ ```
143
+
144
+ ### Changed
145
+ - **`WindowOptions.background`** changed from `Color | false` to `StyleId | undefined` — pass a registered StyleId or omit for transparent (0 = no background); **breaking change**
146
+ - **`YamlWindowDef.background`** changed from `Color | false` to `string | number | undefined` — string values are resolved as named style names, numbers are used directly as StyleIds; **breaking change**
147
+ - **`YamlLayout`** now includes an optional `styles?: YamlStyleDef[]` field
148
+ - All controls (`Button`, `TextBox`, `TextArea`, `Checkbox`, `Radio`) now resolve their default colours from the built-in named styles instead of hardcoded ANSI numbers; hardcoded values remain as fallbacks when no Screen registry is present
149
+
150
+ ### Tests
151
+ - `Window.test.mts` — background-option tests updated: register a StyleId via `StyleRegistry` instead of passing a raw color number; added `StyleId 0 background leaves region blank` case
152
+
153
+ ---
154
+
155
+ ## [0.8.0] – 2026-04-11
156
+
157
+ ### Added
158
+ - **`InterfaceBuilder`** (`src/Screen/InterfaceBuilder.mts`) – builds a window hierarchy from a YAML description:
159
+ - `build(yamlText, screen, wm?)` – parses YAML, adds all top-level windows to Screen, returns `Map<string, Window>` keyed by YAML `id`
160
+ - `buildFromFile(path, screen, wm?)` – async variant that reads a file first
161
+ - `registerCallback(id, fn)` – registers a named function for use with `onPress` / `onChange` in YAML
162
+ - Supports all widget types: `window`, `button`, `textbox`, `textarea`, `checkbox`, `radio`
163
+ - Position spec: `{x, y}` (absolute / negative edge-relative / `"N%"` percentage), named presets (`center`, `topLeft`, `topRight`, `bottomLeft`, `bottomRight`), edge presets (`{preset: top|left|right|bottom, offset?}`)
164
+ - Size spec: `{width, height}`, `"fill"`, `{fillWidth: N}`, `{fillHeight: N}`; `checkbox` and `radio` are auto-sized (no `size` needed)
165
+ - Passes shared `StyleRegistry` from Screen to all created windows
166
+ - When `wm` is provided, all focusable controls are automatically registered with `WindowManager` after the full tree is built (position resolution happens before registration)
167
+ - YAML schema types added to `types.mts`: `YamlAxisValue`, `YamlPosSpec`, `YamlSizeSpec`, `YamlWindowType`, `YamlWindowDef`, `YamlLayout`
168
+ - `yaml` package added as a runtime dependency
169
+
170
+ ---
171
+
172
+ ## [0.7.0] – 2026-04-11
173
+
174
+ ### Added
175
+ - **`WindowManager`** (`src/Screen/WindowManager.mts`) – application input manager:
176
+ - Captures raw stdin in TTY raw mode; parses escape sequences and SGR mouse events
177
+ - `register(control, ...parents)` – registers a focusable control for Tab-cycling; parent chain is used to compute absolute screen position for mouse hit-testing
178
+ - `unregister(control)` – removes a control from the focus list
179
+ - `getFocused()` / `setFocus(control)` – read/set current focus
180
+ - `openDialog(dialog, controls)` – pushes a modal dialog level; the dialog Window is added to Screen and its controls capture all focus until `closeDialog()` is called
181
+ - `closeDialog()` – pops the topmost dialog, removes it from Screen, and restores previous focus context
182
+ - `run()` – starts the event loop (raw mode, optional mouse tracking, hides cursor, initial render)
183
+ - `stop()` – restores terminal state and fires `onExit` callback
184
+ - Mouse support (SGR protocol): left-click focuses the clicked registered control (`mouse: true` option)
185
+ - `handleInput(Buffer)` – public method so tests can drive input without a real TTY
186
+ - **`Focusable`** interface (`types.mts`) – `{ isFocused, setFocused, isDisabled, handleKey? }` satisfied by all interactive controls
187
+ - **`TerminalMouseEvent`** interface (`types.mts`) – typed mouse event from the terminal
188
+ - **`WindowManagerOptions`** interface (`types.mts`) – `exitKeys`, `onExit`, `onKey`, `onMouse`, `mouse`
189
+ - **`Button.handleKey(key)`** – Enter or Space activates `onPress` callback
190
+ - **`Checkbox.handleKey(key)`** – Space toggles `checked` and fires `onChange`
191
+ - **`Radio.handleKey(key)`** – Space selects the button and fires `onChange`
192
+ - `onPress?: () => void` added to `ButtonOptions`
193
+ - `onChange?: (checked: boolean) => void` added to `CheckboxOptions` and `RadioOptions`
194
+ - **`Window.removeChild(child)`** – removes a previously added child (used internally by `closeDialog`)
195
+ - Demo (`src/index.mts`) updated to use `WindowManager` with mouse support; press `q` or Ctrl+C to exit
196
+
197
+ ---
198
+
199
+ ## [0.6.0] – 2026-04-11
200
+
201
+ ### Added
202
+ - **`Window.getInnerOffset()`** / **`Window.getInnerSize()`** – public methods returning the content area offset and dimensions after accounting for decorations (borders); used by `writeText`, `addChild`, `blitChild`
203
+ - **`Window.updateBorder()`** – protected method allowing subclasses to change the border config before each `render()` call (e.g. focus-state colour)
204
+ - **`Button`** (`src/Screen/controls/Button.mts`) – clickable button with rounded border, centred label, normal/focused/disabled states
205
+ - **`Checkbox`** (`src/Screen/controls/Checkbox.mts`) – `[✓]/[ ]` toggle; auto-sized to label width; checked/focused/disabled states
206
+ - **`Radio`** (`src/Screen/controls/Radio.mts`) – `(●)/( )` single-selection; auto-sized to label width; checked/focused/disabled states
207
+ - **`TextBox`** (`src/Screen/controls/TextBox.mts`) – single-line text input with scrolling, cursor, placeholder, `handleKey()` for terminal input
208
+ - **`TextArea`** (`src/Screen/controls/TextArea.mts`) – multi-line text input with 2-D cursor, scroll, placeholder, `handleKey()` for terminal input
209
+ - Control option types added to `types.mts`: `ControlOptions`, `ButtonOptions`, `TextBoxOptions`, `TextAreaOptions`, `CheckboxOptions`, `RadioOptions`
210
+
211
+ ### Changed
212
+ - `Window.addChild()` now resolves child sizes and positions relative to the **inner content area** (excludes border cells) — **breaking change** for parents with borders
213
+ - `Window.writeText()` coordinates are now relative to the inner content area; text clips at inner boundaries, not full window edges — **breaking change** for windows with borders
214
+ - `Window.blitChild()` uses inner area dimensions for `Pos.resolve()` and offsets results by inner offset
215
+
216
+ ---
217
+
218
+ ## [0.5.0] – 2026-04-11
219
+
220
+ ### Added
221
+ - **`Pos`** class (`src/Screen/Pos.mts`) – encodes window position with support for:
222
+ - Absolute coordinates: `new Pos(5, 3)`
223
+ - From-right/bottom edge (negative): `new Pos(-5, -3)` — own edge at distance from parent edge
224
+ - Percentage of parent: `new Pos(pct(50), pct(25))`
225
+ - Named edge presets: `Pos.topLeft()`, `Pos.topRight()`, `Pos.bottomLeft()`, `Pos.bottomRight()`, `Pos.center()`, `Pos.left(y?)`, `Pos.right(y?)`, `Pos.top(x?)`, `Pos.bottom(x?)`
226
+ - **`Size`** class (`src/Screen/Size.mts`) – encodes window dimensions with support for:
227
+ - Absolute pixels: `new Size(30, 10)`
228
+ - Percentage of parent: `new Size(pct(50), pct(100))`
229
+ - Fill shortcuts: `Size.fill()`, `Size.fillWidth(h)`, `Size.fillHeight(w)`
230
+ - **`Pct`** class and **`pct(n)`** helper – wrap percentage values for use in `Pos` and `Size`
231
+ - `AxisSpec` and `DimSpec` type aliases added to `types.mts`
232
+
233
+ ### Changed
234
+ - **`Window` constructor** signature changed from `(x, y, width, height, options?, registry?)` to `(pos: Pos, size: Size, options?, registry?)` — **breaking change**
235
+ - `Window.addChild()` now resolves percentage-based child sizes immediately against parent dimensions
236
+ - `Window` internal `blitChild()` re-resolves position via `Pos.resolve()` on every `render()` call
237
+
238
+ ### Notes
239
+ - For windows with percentage-based sizes, call `parent.addChild(child)` before writing content.
240
+
241
+ ---
242
+
243
+ ## [0.4.0] - 2026-04-11
244
+
245
+ ### Added
246
+ - `StyleRegistry` class (`src/Screen/StyleRegistry.mts`) – central style store with integer IDs and deduplication; `register()`, `get()`, `merge()`
247
+ - `StyleId = number` type alias (`src/Screen/types.mts`)
248
+ - `Screen.registerStyle(attrs): StyleId` – public API for registering styles
249
+ - `Screen.getStyleRegistry(): StyleRegistry` – returns the screen's registry for sharing with child Windows
250
+ - `Window.mergeStyle(x, y, styleId)` – replaces `setAttributes`; merges a style ID onto an existing cell
251
+
252
+ ### Changed
253
+ - `Region` now stores `number[]` (style IDs) instead of `CellAttributes[]`; replaced `getAttrs()` with `getStyleIds()`, `setAttributes()` with `setStyleId()`, `getCell()` removed in favour of `getChar()` + `getStyleId()`
254
+ - `Window.setCell(x, y, char, styleId?)`, `fill(char, styleId?)`, `writeText(text, options?)` all accept `StyleId` instead of `CellAttributes`
255
+ - `WriteTextOptions` no longer extends `CellAttributes`; uses `style?: StyleId` field instead
256
+ - `Window` constructor gains optional `registry?: StyleRegistry` parameter for sharing ID spaces
257
+ - `tsconfig.json` – added `"types": ["node"]` to resolve `process` global
258
+
259
+ ### Removed
260
+ - `Window.setAttributes()` (replaced by `mergeStyle()`)
261
+ - `Region.getAttrs()`, `Region.getCell()`, `Region.setAttributes()`
262
+
263
+ ---
264
+
265
+ ## [0.3.0] - 2026-04-11
266
+
267
+ ### Added
268
+ - `Window.writeText(text, options?)` – built-in text utility; position defaults to (0,0), supports `\n`, silently clips out-of-bounds characters (`src/Screen/Window.mts`)
269
+ - `WriteTextOptions` interface extending `CellAttributes` with optional `x`/`y` (`src/Screen/types.mts`)
270
+
271
+ ### Changed
272
+ - `src/index.mts` – removed local `writeText` helper; all calls use `win.writeText()`
273
+
274
+ ---
275
+
276
+ ## [0.2.0] - 2026-04-11
277
+
278
+ ### Added
279
+ - `Screen` class with terminal cell grid (`src/Screen/Screen.mts`)
280
+ - Type declarations: `Color`, `CellAttributes`, `Cell`, `TerminalSize` (`src/Screen/types.mts`)
281
+ - Methods: `getSize`, `getCell`, `setChar`, `setCell`, `setAttributes`, `clear`, `fill`
282
+ - Unit tests for all `Screen` methods (`src/Screen/Screen.test.mts`)
283
+
284
+ ## [0.1.0] - 2026-04-11
285
+
286
+ ### Added
287
+ - Initial project setup (Node.js + TypeScript, ESM, Vitest)
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Jarosław Mężyk
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.