@teaui/core 1.1.4

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 (203) hide show
  1. package/.dist/Buffer.d.ts +21 -0
  2. package/.dist/Buffer.js +140 -0
  3. package/.dist/Buffer.js.map +1 -0
  4. package/.dist/Color.d.ts +7 -0
  5. package/.dist/Color.js +39 -0
  6. package/.dist/Color.js.map +1 -0
  7. package/.dist/Container.d.ts +21 -0
  8. package/.dist/Container.js +138 -0
  9. package/.dist/Container.js.map +1 -0
  10. package/.dist/Screen.d.ts +54 -0
  11. package/.dist/Screen.js +278 -0
  12. package/.dist/Screen.js.map +1 -0
  13. package/.dist/Style.d.ts +46 -0
  14. package/.dist/Style.js +433 -0
  15. package/.dist/Style.js.map +1 -0
  16. package/.dist/System.d.ts +13 -0
  17. package/.dist/System.js +26 -0
  18. package/.dist/System.js.map +1 -0
  19. package/.dist/Theme.d.ts +56 -0
  20. package/.dist/Theme.js +157 -0
  21. package/.dist/Theme.js.map +1 -0
  22. package/.dist/UI.d.ts +2 -0
  23. package/.dist/UI.js +28 -0
  24. package/.dist/UI.js.map +1 -0
  25. package/.dist/View.d.ts +99 -0
  26. package/.dist/View.js +374 -0
  27. package/.dist/View.js.map +1 -0
  28. package/.dist/Viewport.d.ts +89 -0
  29. package/.dist/Viewport.js +295 -0
  30. package/.dist/Viewport.js.map +1 -0
  31. package/.dist/ansi.d.ts +31 -0
  32. package/.dist/ansi.js +139 -0
  33. package/.dist/ansi.js.map +1 -0
  34. package/.dist/components/Accordion.d.ts +47 -0
  35. package/.dist/components/Accordion.js +294 -0
  36. package/.dist/components/Accordion.js.map +1 -0
  37. package/.dist/components/Box.d.ts +67 -0
  38. package/.dist/components/Box.js +211 -0
  39. package/.dist/components/Box.js.map +1 -0
  40. package/.dist/components/Button.d.ts +28 -0
  41. package/.dist/components/Button.js +118 -0
  42. package/.dist/components/Button.js.map +1 -0
  43. package/.dist/components/Checkbox.d.ts +31 -0
  44. package/.dist/components/Checkbox.js +106 -0
  45. package/.dist/components/Checkbox.js.map +1 -0
  46. package/.dist/components/Collapsible.d.ts +32 -0
  47. package/.dist/components/Collapsible.js +109 -0
  48. package/.dist/components/Collapsible.js.map +1 -0
  49. package/.dist/components/CollapsibleText.d.ts +21 -0
  50. package/.dist/components/CollapsibleText.js +113 -0
  51. package/.dist/components/CollapsibleText.js.map +1 -0
  52. package/.dist/components/Digits.d.ts +20 -0
  53. package/.dist/components/Digits.js +843 -0
  54. package/.dist/components/Digits.js.map +1 -0
  55. package/.dist/components/Drawer.d.ts +44 -0
  56. package/.dist/components/Drawer.js +473 -0
  57. package/.dist/components/Drawer.js.map +1 -0
  58. package/.dist/components/Dropdown.d.ts +61 -0
  59. package/.dist/components/Dropdown.js +367 -0
  60. package/.dist/components/Dropdown.js.map +1 -0
  61. package/.dist/components/Header.d.ts +25 -0
  62. package/.dist/components/Header.js +106 -0
  63. package/.dist/components/Header.js.map +1 -0
  64. package/.dist/components/HotKey.d.ts +14 -0
  65. package/.dist/components/HotKey.js +31 -0
  66. package/.dist/components/HotKey.js.map +1 -0
  67. package/.dist/components/Input.d.ts +45 -0
  68. package/.dist/components/Input.js +1109 -0
  69. package/.dist/components/Input.js.map +1 -0
  70. package/.dist/components/Log.d.ts +16 -0
  71. package/.dist/components/Log.js +122 -0
  72. package/.dist/components/Log.js.map +1 -0
  73. package/.dist/components/Progress.d.ts +21 -0
  74. package/.dist/components/Progress.js +200 -0
  75. package/.dist/components/Progress.js.map +1 -0
  76. package/.dist/components/Scrollable.d.ts +50 -0
  77. package/.dist/components/Scrollable.js +226 -0
  78. package/.dist/components/Scrollable.js.map +1 -0
  79. package/.dist/components/ScrollableList.d.ts +70 -0
  80. package/.dist/components/ScrollableList.js +354 -0
  81. package/.dist/components/ScrollableList.js.map +1 -0
  82. package/.dist/components/Separator.d.ts +21 -0
  83. package/.dist/components/Separator.js +67 -0
  84. package/.dist/components/Separator.js.map +1 -0
  85. package/.dist/components/Slider.d.ts +60 -0
  86. package/.dist/components/Slider.js +341 -0
  87. package/.dist/components/Slider.js.map +1 -0
  88. package/.dist/components/Space.d.ts +19 -0
  89. package/.dist/components/Space.js +45 -0
  90. package/.dist/components/Space.js.map +1 -0
  91. package/.dist/components/Spinner.d.ts +16 -0
  92. package/.dist/components/Spinner.js +48 -0
  93. package/.dist/components/Spinner.js.map +1 -0
  94. package/.dist/components/Stack.d.ts +33 -0
  95. package/.dist/components/Stack.js +285 -0
  96. package/.dist/components/Stack.js.map +1 -0
  97. package/.dist/components/Tabs.d.ts +52 -0
  98. package/.dist/components/Tabs.js +312 -0
  99. package/.dist/components/Tabs.js.map +1 -0
  100. package/.dist/components/Text.d.ts +35 -0
  101. package/.dist/components/Text.js +242 -0
  102. package/.dist/components/Text.js.map +1 -0
  103. package/.dist/components/ToggleGroup.d.ts +26 -0
  104. package/.dist/components/ToggleGroup.js +279 -0
  105. package/.dist/components/ToggleGroup.js.map +1 -0
  106. package/.dist/components/Tree.d.ts +21 -0
  107. package/.dist/components/Tree.js +233 -0
  108. package/.dist/components/Tree.js.map +1 -0
  109. package/.dist/components/Window.d.ts +6 -0
  110. package/.dist/components/Window.js +17 -0
  111. package/.dist/components/Window.js.map +1 -0
  112. package/.dist/components/fonts.d.ts +2 -0
  113. package/.dist/components/fonts.js +39 -0
  114. package/.dist/components/fonts.js.map +1 -0
  115. package/.dist/components/index.d.ts +27 -0
  116. package/.dist/components/index.js +48 -0
  117. package/.dist/components/index.js.map +1 -0
  118. package/.dist/components/types.d.ts +6 -0
  119. package/.dist/components/types.js +20 -0
  120. package/.dist/components/types.js.map +1 -0
  121. package/.dist/components/utility/TrackMouse.d.ts +16 -0
  122. package/.dist/components/utility/TrackMouse.js +53 -0
  123. package/.dist/components/utility/TrackMouse.js.map +1 -0
  124. package/.dist/components/utility/index.d.ts +1 -0
  125. package/.dist/components/utility/index.js +6 -0
  126. package/.dist/components/utility/index.js.map +1 -0
  127. package/.dist/events/index.d.ts +12 -0
  128. package/.dist/events/index.js +20 -0
  129. package/.dist/events/index.js.map +1 -0
  130. package/.dist/events/key.d.ts +15 -0
  131. package/.dist/events/key.js +105 -0
  132. package/.dist/events/key.js.map +1 -0
  133. package/.dist/events/mouse.d.ts +65 -0
  134. package/.dist/events/mouse.js +68 -0
  135. package/.dist/events/mouse.js.map +1 -0
  136. package/.dist/events/window.d.ts +6 -0
  137. package/.dist/events/window.js +3 -0
  138. package/.dist/events/window.js.map +1 -0
  139. package/.dist/geometry.d.ts +178 -0
  140. package/.dist/geometry.js +315 -0
  141. package/.dist/geometry.js.map +1 -0
  142. package/.dist/iTerm2.d.ts +20 -0
  143. package/.dist/iTerm2.js +60 -0
  144. package/.dist/iTerm2.js.map +1 -0
  145. package/.dist/index.d.ts +18 -0
  146. package/.dist/index.js +37 -0
  147. package/.dist/index.js.map +1 -0
  148. package/.dist/inspect.d.ts +2 -0
  149. package/.dist/inspect.js +118 -0
  150. package/.dist/inspect.js.map +1 -0
  151. package/.dist/log.d.ts +12 -0
  152. package/.dist/log.js +56 -0
  153. package/.dist/log.js.map +1 -0
  154. package/.dist/managers/FocusManager.d.ts +28 -0
  155. package/.dist/managers/FocusManager.js +143 -0
  156. package/.dist/managers/FocusManager.js.map +1 -0
  157. package/.dist/managers/ModalManager.d.ts +10 -0
  158. package/.dist/managers/ModalManager.js +67 -0
  159. package/.dist/managers/ModalManager.js.map +1 -0
  160. package/.dist/managers/MouseManager.d.ts +21 -0
  161. package/.dist/managers/MouseManager.js +313 -0
  162. package/.dist/managers/MouseManager.js.map +1 -0
  163. package/.dist/managers/TickManager.d.ts +11 -0
  164. package/.dist/managers/TickManager.js +63 -0
  165. package/.dist/managers/TickManager.js.map +1 -0
  166. package/.dist/sys/alias.d.ts +470 -0
  167. package/.dist/sys/alias.js +487 -0
  168. package/.dist/sys/alias.js.map +1 -0
  169. package/.dist/sys/colors.d.ts +10 -0
  170. package/.dist/sys/colors.js +285 -0
  171. package/.dist/sys/colors.js.map +1 -0
  172. package/.dist/sys/gpmclient.d.ts +11 -0
  173. package/.dist/sys/gpmclient.js +193 -0
  174. package/.dist/sys/gpmclient.js.map +1 -0
  175. package/.dist/sys/index.d.ts +4 -0
  176. package/.dist/sys/index.js +41 -0
  177. package/.dist/sys/index.js.map +1 -0
  178. package/.dist/sys/keys.d.ts +4 -0
  179. package/.dist/sys/keys.js +531 -0
  180. package/.dist/sys/keys.js.map +1 -0
  181. package/.dist/sys/program.d.ts +356 -0
  182. package/.dist/sys/program.js +3739 -0
  183. package/.dist/sys/program.js.map +1 -0
  184. package/.dist/sys/tput.d.ts +297 -0
  185. package/.dist/sys/tput.js +2708 -0
  186. package/.dist/sys/tput.js.map +1 -0
  187. package/.dist/sys/unicode.d.ts +11 -0
  188. package/.dist/sys/unicode.js +619 -0
  189. package/.dist/sys/unicode.js.map +1 -0
  190. package/.dist/sys/usr/linux +0 -0
  191. package/.dist/sys/usr/windows-ansi +0 -0
  192. package/.dist/sys/usr/xterm +0 -0
  193. package/.dist/sys/usr/xterm-256color +0 -0
  194. package/.dist/sys/usr/xterm.termcap +243 -0
  195. package/.dist/sys/usr/xterm.terminfo +1977 -0
  196. package/.dist/terminal.d.ts +7 -0
  197. package/.dist/terminal.js +3 -0
  198. package/.dist/terminal.js.map +1 -0
  199. package/.dist/util.d.ts +22 -0
  200. package/.dist/util.js +79 -0
  201. package/.dist/util.js.map +1 -0
  202. package/LICENSE +24 -0
  203. package/package.json +49 -0
@@ -0,0 +1,226 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Scrollable = void 0;
4
+ const Container_1 = require("../Container");
5
+ const geometry_1 = require("../geometry");
6
+ const events_1 = require("../events");
7
+ const Style_1 = require("../Style");
8
+ /**
9
+ * Scrollable is meant to scroll _a single view_, ie a Stack view. But all the
10
+ * container views are optimized to check their _visibleRect_, and won't render
11
+ * children that are not in view, saving some CPU cycles.
12
+ */
13
+ class Scrollable extends Container_1.Container {
14
+ #showScrollbars = true;
15
+ #scrollHeight = 1;
16
+ #scrollWidth = 2;
17
+ #contentOffset;
18
+ #contentSize = geometry_1.Size.zero;
19
+ #visibleSize = geometry_1.Size.zero;
20
+ #prevMouseDown = undefined;
21
+ constructor(props) {
22
+ super(props);
23
+ this.#contentOffset = { x: 0, y: 0 };
24
+ this.#update(props);
25
+ }
26
+ update(props) {
27
+ this.#update(props);
28
+ super.update(props);
29
+ }
30
+ #update({ scrollHeight, scrollWidth, showScrollbars }) {
31
+ this.#showScrollbars = showScrollbars ?? true;
32
+ this.#scrollHeight = scrollHeight ?? 1;
33
+ this.#scrollWidth = scrollWidth ?? 2;
34
+ }
35
+ naturalSize(available) {
36
+ const size = super.naturalSize(available).mutableCopy();
37
+ size.width = Math.min(size.width, available.width);
38
+ size.height = Math.min(size.height, available.height);
39
+ return size;
40
+ }
41
+ #maxOffsetX() {
42
+ const tooTall = this.#contentSize.height > this.contentSize.height;
43
+ return this.#visibleSize.width - this.#contentSize.width + (tooTall ? 0 : 1);
44
+ }
45
+ #maxOffsetY() {
46
+ const tooWide = this.#contentSize.width > this.contentSize.width;
47
+ return (this.#visibleSize.height - this.#contentSize.height + (tooWide ? 0 : 1));
48
+ }
49
+ receiveMouse(event) {
50
+ if ((0, events_1.isMouseWheel)(event)) {
51
+ this.receiveWheel(event);
52
+ return;
53
+ }
54
+ if (event.name === 'mouse.button.up') {
55
+ this.#prevMouseDown = undefined;
56
+ return;
57
+ }
58
+ const tooWide = this.#contentSize.width > this.contentSize.width;
59
+ const tooTall = this.#contentSize.height > this.contentSize.height;
60
+ if (tooWide &&
61
+ tooTall &&
62
+ event.position.y === this.contentSize.height - 1 &&
63
+ event.position.x === this.contentSize.width - 1) {
64
+ // bottom-right corner click
65
+ return;
66
+ }
67
+ if (this.#prevMouseDown === undefined) {
68
+ if (tooWide && event.position.y === this.contentSize.height) {
69
+ this.#prevMouseDown = 'horizontal';
70
+ }
71
+ else if (tooTall && event.position.x === this.contentSize.width) {
72
+ this.#prevMouseDown = 'vertical';
73
+ }
74
+ else {
75
+ return;
76
+ }
77
+ }
78
+ this.receiveMouseDown(event);
79
+ }
80
+ receiveMouseDown(event) {
81
+ const tooWide = this.#contentSize.width > this.contentSize.width;
82
+ const tooTall = this.#contentSize.height > this.contentSize.height;
83
+ if (tooWide && this.#prevMouseDown === 'horizontal') {
84
+ const maxX = this.#maxOffsetX();
85
+ const offsetX = Math.round((0, geometry_1.interpolate)(event.position.x, [0, this.contentSize.width - (tooTall ? 1 : 0)], [0, maxX]));
86
+ this.#contentOffset = {
87
+ x: Math.max(maxX, Math.min(0, offsetX)),
88
+ y: this.#contentOffset.y,
89
+ };
90
+ }
91
+ else if (tooTall && this.#prevMouseDown === 'vertical') {
92
+ const maxY = this.#maxOffsetY();
93
+ const offsetY = Math.round((0, geometry_1.interpolate)(event.position.y, [0, this.contentSize.height - (tooWide ? 1 : 0)], [0, maxY]));
94
+ this.#contentOffset = {
95
+ x: this.#contentOffset.x,
96
+ y: Math.max(maxY, Math.min(0, offsetY)),
97
+ };
98
+ }
99
+ }
100
+ receiveWheel(event) {
101
+ let deltaY = 0, deltaX = 0;
102
+ if (event.name === 'mouse.wheel.up') {
103
+ deltaY = this.#scrollHeight * -1;
104
+ }
105
+ else if (event.name === 'mouse.wheel.down') {
106
+ deltaY = this.#scrollHeight;
107
+ }
108
+ else if (event.name === 'mouse.wheel.left') {
109
+ deltaX = this.#scrollWidth;
110
+ }
111
+ else if (event.name === 'mouse.wheel.right') {
112
+ deltaX = this.#scrollWidth * -1;
113
+ }
114
+ if (event.ctrl) {
115
+ deltaY *= 5;
116
+ deltaX *= 5;
117
+ }
118
+ const tooTall = (this.#contentSize?.height ?? 0) > this.contentSize.height;
119
+ if (!tooTall && deltaX === 0) {
120
+ deltaX = deltaY;
121
+ }
122
+ this.scrollBy(deltaX, deltaY);
123
+ }
124
+ /**
125
+ * Moves the visible region. The visible region is stored as a pointer to the
126
+ * top-most row and an offset from the top of that row (see `interface ContentOffset`)
127
+ *
128
+ * Positive offset scrolls *down* (currentOffset goes more negative)
129
+ *
130
+ * When current cell is entirely above the top, we set the `contentOffset` to the
131
+ * row that is at the top of the screen and still visible, similarly if the current
132
+ * cell is below the top, we fetch enough rows about and update the `contentOffset`
133
+ * to point to the top-most row.
134
+ */
135
+ scrollBy(offsetX, offsetY) {
136
+ if (offsetX === 0 && offsetY === 0) {
137
+ return;
138
+ }
139
+ const tooWide = this.#contentSize.width > this.contentSize.width;
140
+ const tooTall = this.#contentSize.height > this.contentSize.height;
141
+ let { x, y } = this.#contentOffset;
142
+ const maxX = this.#maxOffsetX();
143
+ const maxY = this.#maxOffsetY();
144
+ x = Math.min(0, Math.max(maxX, x - offsetX));
145
+ y = Math.min(0, Math.max(maxY, y - offsetY));
146
+ this.#contentOffset = { x, y };
147
+ }
148
+ get contentSize() {
149
+ const delta = this.#showScrollbars ? 1 : 0;
150
+ return super.contentSize.shrink(delta, delta);
151
+ }
152
+ render(viewport) {
153
+ if (viewport.isEmpty) {
154
+ return super.render(viewport);
155
+ }
156
+ viewport.registerMouse('mouse.wheel');
157
+ let contentSize = geometry_1.Size.zero.mutableCopy();
158
+ for (const child of this.children) {
159
+ const childSize = child.naturalSize(viewport.contentSize);
160
+ contentSize.width = Math.max(contentSize.width, childSize.width);
161
+ contentSize.height = Math.max(contentSize.height, childSize.height);
162
+ }
163
+ this.#contentSize = contentSize;
164
+ const tooWide = contentSize.width > viewport.contentSize.width;
165
+ const tooTall = contentSize.height > viewport.contentSize.height;
166
+ // #contentOffset is _negative_ (indicates the amount to move the view away
167
+ // from the origin, which will always be up/left of 0,0)
168
+ const outside = new geometry_1.Rect([this.#contentOffset.x, this.#contentOffset.y], viewport.contentSize
169
+ .shrink(this.#contentOffset.x, this.#contentOffset.y)
170
+ .shrink(this.#showScrollbars && tooTall ? 1 : 0, this.#showScrollbars && tooWide ? 1 : 0));
171
+ viewport.clipped(outside, inside => {
172
+ for (const child of this.children) {
173
+ child.render(inside);
174
+ }
175
+ });
176
+ this.#visibleSize = viewport.visibleRect.size.shrink(tooWide ? 1 : 0, tooTall ? 1 : 0);
177
+ if (this.#showScrollbars && (tooWide || tooTall)) {
178
+ const scrollBar = new Style_1.Style({
179
+ foreground: this.theme.darkenColor,
180
+ background: this.theme.darkenColor,
181
+ });
182
+ const scrollControl = new Style_1.Style({
183
+ foreground: this.theme.highlightColor,
184
+ background: this.theme.highlightColor,
185
+ });
186
+ // scrollMaxX: x of the last column of the view
187
+ // scrollMaxY: y of the last row of the view
188
+ // scrollMaxHorizX: horizontal scroll bar is drawn from 0 to scrollMaxHorizX
189
+ // scrollMaxHorizY: vertical scroll bar is drawn from 0 to scrollMaxHorizY
190
+ const scrollMaxX = viewport.contentSize.width - 1, scrollMaxY = viewport.contentSize.height - 1, scrollMaxHorizX = scrollMaxX - (tooTall ? 1 : 0), scrollMaxVertY = scrollMaxY - (tooWide ? 1 : 0);
191
+ if (tooWide && tooTall) {
192
+ viewport.write('█', new geometry_1.Point(scrollMaxX, scrollMaxY), scrollBar);
193
+ }
194
+ if (tooWide) {
195
+ viewport.registerMouse('mouse.button.left', new geometry_1.Rect(new geometry_1.Point(0, scrollMaxY), new geometry_1.Size(scrollMaxHorizX + 1, 1)));
196
+ const contentOffsetX = -this.#contentOffset.x;
197
+ const viewX = Math.round((0, geometry_1.interpolate)(contentOffsetX, [
198
+ 0,
199
+ contentSize.width -
200
+ viewport.contentSize.width +
201
+ (tooTall ? 1 : 0),
202
+ ], [0, scrollMaxHorizX]));
203
+ for (let x = 0; x <= scrollMaxHorizX; x++) {
204
+ const inRange = x === viewX;
205
+ viewport.write(inRange ? '█' : ' ', new geometry_1.Point(x, scrollMaxY), inRange ? scrollControl : scrollBar);
206
+ }
207
+ }
208
+ if (tooTall) {
209
+ viewport.registerMouse('mouse.button.left', new geometry_1.Rect(new geometry_1.Point(scrollMaxX, 0), new geometry_1.Size(1, scrollMaxVertY + 1)));
210
+ const contentOffsetY = -this.#contentOffset.y;
211
+ const viewY = Math.round((0, geometry_1.interpolate)(contentOffsetY, [
212
+ 0,
213
+ contentSize.height -
214
+ viewport.contentSize.height +
215
+ (tooWide ? 1 : 0),
216
+ ], [0, scrollMaxVertY]));
217
+ for (let y = 0; y <= scrollMaxVertY; y++) {
218
+ const inRange = y === viewY;
219
+ viewport.write(inRange ? '█' : ' ', new geometry_1.Point(scrollMaxX, y), inRange ? scrollControl : scrollBar);
220
+ }
221
+ }
222
+ }
223
+ }
224
+ }
225
+ exports.Scrollable = Scrollable;
226
+ //# sourceMappingURL=Scrollable.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Scrollable.js","sourceRoot":"","sources":["../../lib/components/Scrollable.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,70 @@
1
+ import type { Viewport } from '../Viewport';
2
+ import { type Props as ViewProps, View } from '../View';
3
+ import { Container } from '../Container';
4
+ import { Size } from '../geometry';
5
+ import { type MouseEvent } from '../events';
6
+ interface Props<T> extends ViewProps {
7
+ items: T[];
8
+ cellForItem: (item: T, row: number) => View;
9
+ /**
10
+ * Show/hide the scrollbars
11
+ * @default true
12
+ */
13
+ showScrollbars?: boolean;
14
+ /**
15
+ * How many rows to scroll by when using the mouse wheel.
16
+ * @default 1
17
+ */
18
+ scrollHeight?: number;
19
+ /**
20
+ * Useful for log views
21
+ */
22
+ keepAtBottom?: boolean;
23
+ }
24
+ interface ContentOffset {
25
+ row: number;
26
+ offset: number;
27
+ }
28
+ export declare class ScrollableList<T> extends Container {
29
+ #private;
30
+ constructor({ cellForItem, items, keepAtBottom, scrollHeight, showScrollbars, ...viewProps }: Props<T>);
31
+ update(props: Props<T>): void;
32
+ naturalSize(available: Size): Size;
33
+ /**
34
+ * Tells ScrollableList to re-fetch all rows.
35
+ */
36
+ invalidate(): void;
37
+ /**
38
+ * Tells ScrollableList to re-fetch the visible rows.
39
+ * @param forCache: 'size' | 'view' representing which cache to invalidate
40
+ */
41
+ invalidateAllRows(forCache: 'size' | 'view'): void;
42
+ /**
43
+ * Tells ScrollableList to refetch a specific row
44
+ * @param row: the row to invalidate
45
+ * @param forCache: 'size' | 'view' representing which cache to invalidate
46
+ */
47
+ invalidateItem(item: T, forCache: 'size' | 'view'): void;
48
+ invalidateSize(): void;
49
+ receiveMouse(event: MouseEvent): void;
50
+ /**
51
+ * Moves the visible region. The visible region is stored as a pointer to the
52
+ * top-most row and an offset from the top of that row (see `interface ContentOffset`)
53
+ *
54
+ * Positive offset scrolls *down* (currentOffset goes more negative)
55
+ *
56
+ * When current cell is entirely above the top, we set the `contentOffset` to the
57
+ * row that is at the top of the screen and still visible, similarly if the current
58
+ * cell is below the top, we fetch enough rows about and update the `contentOffset`
59
+ * to point to the top-most row.
60
+ */
61
+ scrollBy(offset: number): void;
62
+ updateItems(items: T[]): void;
63
+ viewForRow(row: number): View | undefined;
64
+ sizeForRow(row: number, contentWidth: number, view: View): Size;
65
+ sizeForRow(row: number, contentWidth: number): Size | undefined;
66
+ get contentSize(): Size;
67
+ lastOffset(): ContentOffset;
68
+ render(viewport: Viewport): void;
69
+ }
70
+ export {};
@@ -0,0 +1,354 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ScrollableList = void 0;
4
+ const Container_1 = require("../Container");
5
+ const Style_1 = require("../Style");
6
+ const geometry_1 = require("../geometry");
7
+ const events_1 = require("../events");
8
+ class ScrollableList extends Container_1.Container {
9
+ /**
10
+ * Your function here need not return "stable" views; the views returned by this
11
+ * function will be cached until you call `scrollableList.invalidateCache()` or
12
+ * `scrollableList.invalidateRow(row)`.
13
+ */
14
+ #items;
15
+ #cellForItem;
16
+ #keepAtBottom;
17
+ #isAtBottom = true;
18
+ #showScrollbars;
19
+ #scrollHeight;
20
+ #contentOffset;
21
+ #maxWidth = 0;
22
+ #viewCache = new Map();
23
+ #sizeCache = new Map();
24
+ #totalHeight;
25
+ constructor({ cellForItem, items, keepAtBottom, scrollHeight, showScrollbars, ...viewProps }) {
26
+ super(viewProps);
27
+ this.#showScrollbars = showScrollbars ?? true;
28
+ this.#contentOffset = { row: 0, offset: 0 };
29
+ this.#cellForItem = cellForItem;
30
+ this.#scrollHeight = scrollHeight ?? 1;
31
+ this.#items = items;
32
+ this.#keepAtBottom = keepAtBottom ?? false;
33
+ }
34
+ update(props) {
35
+ this.#update(props);
36
+ super.update(props);
37
+ }
38
+ #update({}) { }
39
+ naturalSize(available) {
40
+ let { row, offset: y } = this.#contentOffset;
41
+ const scrollWidth = this.#showScrollbars ? 1 : 0;
42
+ while (y < available.height) {
43
+ const view = this.viewForRow(row);
44
+ if (!view) {
45
+ break;
46
+ }
47
+ const rowSize = this.sizeForRow(row, available.width - scrollWidth, view);
48
+ // persist #maxWidth so that the largest row _remains_ the largest row even
49
+ // after it scrolls out of the visible window
50
+ this.#maxWidth = Math.max(this.#maxWidth, rowSize.width);
51
+ y += rowSize.height;
52
+ row += 1;
53
+ }
54
+ return new geometry_1.Size(this.#maxWidth + scrollWidth, available.height);
55
+ }
56
+ /**
57
+ * Tells ScrollableList to re-fetch all rows.
58
+ */
59
+ invalidate() {
60
+ this.#maxWidth = 0;
61
+ this.invalidateAllRows('view');
62
+ super.invalidateSize();
63
+ }
64
+ /**
65
+ * Tells ScrollableList to re-fetch the visible rows.
66
+ * @param forCache: 'size' | 'view' representing which cache to invalidate
67
+ */
68
+ invalidateAllRows(forCache) {
69
+ if (forCache === 'view') {
70
+ this.#viewCache = new Map();
71
+ }
72
+ this.#sizeCache = new Map();
73
+ }
74
+ /**
75
+ * Tells ScrollableList to refetch a specific row
76
+ * @param row: the row to invalidate
77
+ * @param forCache: 'size' | 'view' representing which cache to invalidate
78
+ */
79
+ invalidateItem(item, forCache) {
80
+ if (forCache === 'view') {
81
+ this.#viewCache.delete(item);
82
+ }
83
+ this.#sizeCache.delete(item);
84
+ }
85
+ invalidateSize() {
86
+ this.#maxWidth = 0;
87
+ this.invalidateAllRows('size');
88
+ super.invalidateSize();
89
+ }
90
+ receiveMouse(event) {
91
+ if (event.name === 'mouse.wheel.up') {
92
+ this.scrollBy(this.#scrollHeight * -1);
93
+ }
94
+ else if (event.name === 'mouse.wheel.down') {
95
+ this.scrollBy(this.#scrollHeight);
96
+ }
97
+ else if ((0, events_1.isMouseDragging)(event) && this.#totalHeight) {
98
+ if (this.#totalHeight <= this.contentSize.height) {
99
+ this.#contentOffset = { row: 0, offset: 0 };
100
+ return;
101
+ }
102
+ const maxY = this.#totalHeight - this.contentSize.height;
103
+ const heightY = Math.round((0, geometry_1.interpolate)(Math.max(0, Math.min(this.contentSize.height - 1, event.position.y)), [0, this.contentSize.height - 1], [0, maxY]));
104
+ this.#isAtBottom = heightY === maxY;
105
+ const cellWidth = this.contentSize.width;
106
+ for (let row = 0, y = 0; row < this.#items.length; row++) {
107
+ const rowHeight = this.sizeForRow(row, cellWidth)?.height;
108
+ if (rowHeight === undefined) {
109
+ break;
110
+ }
111
+ if (y + rowHeight >= heightY) {
112
+ this.#contentOffset = { row, offset: y - heightY };
113
+ return;
114
+ }
115
+ y += rowHeight;
116
+ }
117
+ }
118
+ }
119
+ /**
120
+ * Moves the visible region. The visible region is stored as a pointer to the
121
+ * top-most row and an offset from the top of that row (see `interface ContentOffset`)
122
+ *
123
+ * Positive offset scrolls *down* (currentOffset goes more negative)
124
+ *
125
+ * When current cell is entirely above the top, we set the `contentOffset` to the
126
+ * row that is at the top of the screen and still visible, similarly if the current
127
+ * cell is below the top, we fetch enough rows about and update the `contentOffset`
128
+ * to point to the top-most row.
129
+ */
130
+ scrollBy(offset) {
131
+ if (offset === 0) {
132
+ return;
133
+ }
134
+ this.invalidateSize();
135
+ const { row, offset: currentOffset } = this.#contentOffset;
136
+ let height = this.sizeForRow(row, this.contentSize.width)?.height;
137
+ if (height === undefined) {
138
+ this.#contentOffset = { row: 0, offset: 0 };
139
+ return;
140
+ }
141
+ // prevent scrolling if there is no more content
142
+ if (offset > 0) {
143
+ const doScroll = this.#checkScrollDown(row, currentOffset, height);
144
+ if (!doScroll) {
145
+ this.#isAtBottom = true;
146
+ return;
147
+ }
148
+ }
149
+ else if (row === 0 && currentOffset >= 0) {
150
+ // no helper function necessary here - if offset < 0, do not scroll if we are
151
+ // already at the top
152
+ return;
153
+ }
154
+ this.#isAtBottom = false;
155
+ let nextOffset = currentOffset - offset;
156
+ if (nextOffset <= -height) {
157
+ this.#contentOffset = this.#scrollDownToNextRow(row, nextOffset, height);
158
+ }
159
+ else if (nextOffset > 0) {
160
+ this.#contentOffset = this.#scrollUpToPrevRow(row, nextOffset, height);
161
+ }
162
+ else {
163
+ this.#contentOffset = { row: row, offset: nextOffset };
164
+ }
165
+ }
166
+ updateItems(items) {
167
+ this.#items = items;
168
+ this.invalidateAllRows('view');
169
+ this.invalidateSize();
170
+ }
171
+ viewForRow(row) {
172
+ if (row < 0 || row >= this.#items.length) {
173
+ return;
174
+ }
175
+ const item = this.#items[row];
176
+ let view = this.#viewCache.get(item);
177
+ if (!view) {
178
+ view = this.#cellForItem(item, row);
179
+ if (view) {
180
+ this.#viewCache.set(item, view);
181
+ }
182
+ }
183
+ return view;
184
+ }
185
+ sizeForRow(row, contentWidth, view) {
186
+ const item = this.#items[row];
187
+ if (contentWidth === this.contentSize.width && item) {
188
+ const size = this.#sizeCache.get(item);
189
+ if (size !== undefined) {
190
+ return size;
191
+ }
192
+ }
193
+ view = view ?? this.viewForRow(row);
194
+ if (view === undefined) {
195
+ return undefined;
196
+ }
197
+ const size = view.naturalSize(new geometry_1.Size(contentWidth, 0));
198
+ if (contentWidth === this.contentSize.width && item) {
199
+ this.#sizeCache.set(item, size);
200
+ }
201
+ return size;
202
+ }
203
+ get contentSize() {
204
+ return super.contentSize.shrink(this.#showScrollbars ? 1 : 0, 0);
205
+ }
206
+ lastOffset() {
207
+ const cellCount = this.#items.length;
208
+ const cellWidth = this.contentSize.width;
209
+ let row = cellCount - 1;
210
+ let y = 0;
211
+ while (y < this.contentSize.height) {
212
+ const height = this.sizeForRow(row, cellWidth)?.height;
213
+ if (height === undefined) {
214
+ return { row: 0, offset: 0 };
215
+ }
216
+ y += height;
217
+ if (y >= this.contentSize.height) {
218
+ break;
219
+ }
220
+ row -= 1;
221
+ }
222
+ return { row, offset: this.contentSize.height - y };
223
+ }
224
+ render(viewport) {
225
+ if (viewport.isEmpty) {
226
+ return super.render(viewport);
227
+ }
228
+ viewport.registerMouse('mouse.wheel');
229
+ if (this.#contentOffset.row >= this.#items.length ||
230
+ (this.#keepAtBottom && this.#isAtBottom)) {
231
+ const offset = this.lastOffset();
232
+ this.#contentOffset = offset;
233
+ }
234
+ const cellWidth = this.contentSize.width;
235
+ const prevRows = new Set(this.children);
236
+ const visibleRows = new Set();
237
+ let { row, offset: y } = this.#contentOffset;
238
+ let heights = [0, 0, 0];
239
+ if (this.#showScrollbars) {
240
+ for (let i = 0; i < row; i++) {
241
+ heights[0] += this.sizeForRow(i, cellWidth)?.height ?? 0;
242
+ }
243
+ heights[1] = heights[0];
244
+ }
245
+ while (y < viewport.contentSize.height) {
246
+ const view = this.viewForRow(row);
247
+ if (!view) {
248
+ break;
249
+ }
250
+ const height = this.sizeForRow(row, cellWidth, view)?.height;
251
+ if (y === this.#contentOffset.offset && y + height <= 0) {
252
+ y = this.#contentOffset.offset = 0;
253
+ }
254
+ row += 1;
255
+ heights[1] += height;
256
+ if (view.parent !== this) {
257
+ this.add(view);
258
+ }
259
+ visibleRows.add(view);
260
+ if (y < viewport.visibleRect.maxY() &&
261
+ y + height >= viewport.visibleRect.minY()) {
262
+ const rect = new geometry_1.Rect(new geometry_1.Point(0, y), new geometry_1.Size(cellWidth, height));
263
+ viewport.clipped(rect, inside => {
264
+ view.render(inside);
265
+ });
266
+ }
267
+ y += height;
268
+ if (y >= viewport.contentSize.height) {
269
+ break;
270
+ }
271
+ }
272
+ for (const prevRow of prevRows) {
273
+ if (!visibleRows.has(prevRow)) {
274
+ this.removeChild(prevRow);
275
+ }
276
+ }
277
+ if (this.#showScrollbars) {
278
+ viewport.registerMouse('mouse.button.left', new geometry_1.Rect(new geometry_1.Point(cellWidth, 0), new geometry_1.Size(1, viewport.contentSize.height)));
279
+ heights[2] = heights[1];
280
+ for (let i = row; i < this.#items.length; i++) {
281
+ const rowHeight = this.sizeForRow(i, cellWidth)?.height;
282
+ if (rowHeight === undefined) {
283
+ break;
284
+ }
285
+ heights[2] += rowHeight;
286
+ }
287
+ this.#totalHeight = heights[2];
288
+ for (let y = 0; y < viewport.contentSize.height; y++) {
289
+ const h = (0, geometry_1.interpolate)(y, [0, viewport.contentSize.height - 1], [0, heights[2]]);
290
+ const inRange = ~~h >= heights[0] && ~~h <= heights[1] + 1;
291
+ viewport.write(inRange ? '█' : ' ', new geometry_1.Point(cellWidth, y), new Style_1.Style(inRange
292
+ ? {
293
+ foreground: this.theme.highlightColor,
294
+ background: this.theme.highlightColor,
295
+ }
296
+ : {
297
+ foreground: this.theme.darkenColor,
298
+ background: this.theme.darkenColor,
299
+ }));
300
+ }
301
+ }
302
+ }
303
+ /**
304
+ * Returns 'true' if the scroll should be allowed, returns 'false' if there
305
+ * is no more content to be shown (do not scroll down)
306
+ */
307
+ #checkScrollDown(row, currentOffset, height) {
308
+ // add heights of visible cells – if we run out of cells before
309
+ // y > this.contentSize, exit. Otherwise, scroll.
310
+ let y = currentOffset;
311
+ let nextRow = row;
312
+ let nextHeight = height;
313
+ while (nextHeight !== undefined) {
314
+ y += nextHeight;
315
+ if (y > this.contentSize.height) {
316
+ return true;
317
+ }
318
+ nextHeight = this.sizeForRow(++nextRow, this.contentSize.width)?.height;
319
+ if (nextHeight === undefined) {
320
+ return false;
321
+ }
322
+ }
323
+ }
324
+ #scrollDownToNextRow(row, nextOffset, height) {
325
+ let nextRow = row;
326
+ while (nextOffset <= -height) {
327
+ const nextHeight = this.sizeForRow(nextRow + 1, this.contentSize.width)?.height;
328
+ if (nextHeight === undefined) {
329
+ nextOffset = -height;
330
+ break;
331
+ }
332
+ nextOffset += height;
333
+ height = nextHeight;
334
+ nextRow += 1;
335
+ }
336
+ return { row: nextRow, offset: nextOffset };
337
+ }
338
+ #scrollUpToPrevRow(row, nextOffset, height) {
339
+ let nextRow = row;
340
+ while (nextOffset > 0) {
341
+ const nextHeight = this.sizeForRow(nextRow - 1, this.contentSize.width)?.height;
342
+ if (nextHeight === undefined) {
343
+ nextOffset = 0;
344
+ break;
345
+ }
346
+ height = nextHeight;
347
+ nextOffset -= height;
348
+ nextRow -= 1;
349
+ }
350
+ return { row: nextRow, offset: nextOffset };
351
+ }
352
+ }
353
+ exports.ScrollableList = ScrollableList;
354
+ //# sourceMappingURL=ScrollableList.js.map