@promptctl/rich-js 0.18.0 → 0.18.1

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 (221) hide show
  1. package/dist/core/anchor.d.ts +45 -0
  2. package/dist/core/anchor.js +39 -0
  3. package/dist/core/ansi.d.ts +65 -0
  4. package/dist/core/ansi.js +231 -0
  5. package/dist/core/box.d.ts +143 -0
  6. package/dist/core/box.js +379 -0
  7. package/dist/core/cells.d.ts +159 -0
  8. package/dist/core/cells.js +287 -0
  9. package/dist/core/color.d.ts +246 -0
  10. package/dist/core/color.js +1038 -0
  11. package/dist/core/console.d.ts +165 -0
  12. package/dist/core/console.js +527 -0
  13. package/dist/core/emoji.d.ts +24 -0
  14. package/dist/core/emoji.js +391 -0
  15. package/dist/core/export-html.d.ts +59 -0
  16. package/dist/core/export-html.js +200 -0
  17. package/dist/core/export-lines.d.ts +121 -0
  18. package/dist/core/export-lines.js +141 -0
  19. package/dist/core/highlighter.d.ts +33 -0
  20. package/dist/core/highlighter.js +124 -0
  21. package/dist/core/json.d.ts +27 -0
  22. package/dist/core/json.js +53 -0
  23. package/dist/core/markup.d.ts +119 -0
  24. package/dist/core/markup.js +731 -0
  25. package/dist/core/measure.d.ts +27 -0
  26. package/dist/core/measure.js +62 -0
  27. package/dist/core/oklch.d.ts +161 -0
  28. package/dist/core/oklch.js +312 -0
  29. package/dist/core/osc8.d.ts +68 -0
  30. package/dist/core/osc8.js +90 -0
  31. package/dist/core/place.d.ts +30 -0
  32. package/dist/core/place.js +51 -0
  33. package/dist/core/pretty.d.ts +144 -0
  34. package/dist/core/pretty.js +476 -0
  35. package/dist/core/protocol.d.ts +267 -0
  36. package/dist/core/protocol.js +163 -0
  37. package/dist/core/render.d.ts +84 -0
  38. package/dist/core/render.js +145 -0
  39. package/dist/core/segment.d.ts +161 -0
  40. package/dist/core/segment.js +492 -0
  41. package/dist/core/spinnerData.d.ts +12 -0
  42. package/dist/core/spinnerData.js +117 -0
  43. package/dist/core/strip.d.ts +141 -0
  44. package/dist/core/strip.js +305 -0
  45. package/dist/core/style.d.ts +169 -0
  46. package/dist/core/style.js +695 -0
  47. package/dist/core/subscription.d.ts +12 -0
  48. package/dist/core/subscription.js +12 -0
  49. package/dist/core/text.d.ts +256 -0
  50. package/dist/core/text.js +976 -0
  51. package/dist/core/wrap.d.ts +41 -0
  52. package/dist/core/wrap.js +127 -0
  53. package/dist/host/app.d.ts +121 -0
  54. package/dist/host/app.js +255 -0
  55. package/dist/host/host-environment.d.ts +26 -0
  56. package/dist/host/host-environment.js +44 -0
  57. package/dist/host/index.d.ts +5 -0
  58. package/dist/host/index.js +3 -0
  59. package/dist/host/terminal-host.d.ts +179 -0
  60. package/dist/host/terminal-host.js +186 -0
  61. package/dist/index.d.ts +91 -0
  62. package/dist/index.js +107 -0
  63. package/dist/node/prompt.d.ts +21 -0
  64. package/dist/node/prompt.js +30 -0
  65. package/dist/node/save.d.ts +17 -0
  66. package/dist/node/save.js +21 -0
  67. package/dist/node/terminal-host.d.ts +113 -0
  68. package/dist/node/terminal-host.js +227 -0
  69. package/dist/node/traceback.d.ts +37 -0
  70. package/dist/node/traceback.js +134 -0
  71. package/dist/renderables/align.d.ts +16 -0
  72. package/dist/renderables/align.js +33 -0
  73. package/dist/renderables/columns.d.ts +61 -0
  74. package/dist/renderables/columns.js +152 -0
  75. package/dist/renderables/constrain.d.ts +15 -0
  76. package/dist/renderables/constrain.js +37 -0
  77. package/dist/renderables/embed.d.ts +50 -0
  78. package/dist/renderables/embed.js +71 -0
  79. package/dist/renderables/flexStrip.d.ts +41 -0
  80. package/dist/renderables/flexStrip.js +200 -0
  81. package/dist/renderables/group.d.ts +11 -0
  82. package/dist/renderables/group.js +17 -0
  83. package/dist/renderables/layout.d.ts +92 -0
  84. package/dist/renderables/layout.js +312 -0
  85. package/dist/renderables/live.d.ts +50 -0
  86. package/dist/renderables/live.js +175 -0
  87. package/dist/renderables/markdown.d.ts +24 -0
  88. package/dist/renderables/markdown.js +184 -0
  89. package/dist/renderables/padding.d.ts +38 -0
  90. package/dist/renderables/padding.js +141 -0
  91. package/dist/renderables/panel.d.ts +116 -0
  92. package/dist/renderables/panel.js +307 -0
  93. package/dist/renderables/progress.d.ts +90 -0
  94. package/dist/renderables/progress.js +238 -0
  95. package/dist/renderables/progressBar.d.ts +31 -0
  96. package/dist/renderables/progressBar.js +53 -0
  97. package/dist/renderables/prompt.d.ts +49 -0
  98. package/dist/renderables/prompt.js +125 -0
  99. package/dist/renderables/rule.d.ts +25 -0
  100. package/dist/renderables/rule.js +90 -0
  101. package/dist/renderables/spinner.d.ts +31 -0
  102. package/dist/renderables/spinner.js +70 -0
  103. package/dist/renderables/status.d.ts +23 -0
  104. package/dist/renderables/status.js +60 -0
  105. package/dist/renderables/syntax.d.ts +35 -0
  106. package/dist/renderables/syntax.js +115 -0
  107. package/dist/renderables/table.d.ts +194 -0
  108. package/dist/renderables/table.js +795 -0
  109. package/dist/renderables/traceback.d.ts +31 -0
  110. package/dist/renderables/traceback.js +108 -0
  111. package/dist/renderables/tree.d.ts +68 -0
  112. package/dist/renderables/tree.js +150 -0
  113. package/dist/renderables/viewport.d.ts +114 -0
  114. package/dist/renderables/viewport.js +198 -0
  115. package/dist/template-bindings/color-funcs.d.ts +87 -0
  116. package/dist/template-bindings/color-funcs.js +217 -0
  117. package/dist/template-bindings/helpers.d.ts +24 -0
  118. package/dist/template-bindings/helpers.js +48 -0
  119. package/dist/template-bindings/index.d.ts +107 -0
  120. package/dist/template-bindings/index.js +146 -0
  121. package/dist/template-bindings/palette-funcs.d.ts +94 -0
  122. package/dist/template-bindings/palette-funcs.js +141 -0
  123. package/dist/template-bindings/style-funcs.d.ts +28 -0
  124. package/dist/template-bindings/style-funcs.js +155 -0
  125. package/dist/themes/buildPalette.d.ts +36 -0
  126. package/dist/themes/buildPalette.js +56 -0
  127. package/dist/themes/colorMath.d.ts +82 -0
  128. package/dist/themes/colorMath.js +254 -0
  129. package/dist/themes/colorRef.d.ts +51 -0
  130. package/dist/themes/colorRef.js +96 -0
  131. package/dist/themes/data/ansi-tables.d.ts +14 -0
  132. package/dist/themes/data/ansi-tables.js +49 -0
  133. package/dist/themes/data/atom-one-dark.d.ts +3 -0
  134. package/dist/themes/data/atom-one-dark.js +177 -0
  135. package/dist/themes/data/atom-one-light.d.ts +3 -0
  136. package/dist/themes/data/atom-one-light.js +177 -0
  137. package/dist/themes/data/catppuccin-frappe.d.ts +3 -0
  138. package/dist/themes/data/catppuccin-frappe.js +177 -0
  139. package/dist/themes/data/catppuccin-latte.d.ts +3 -0
  140. package/dist/themes/data/catppuccin-latte.js +177 -0
  141. package/dist/themes/data/catppuccin-macchiato.d.ts +3 -0
  142. package/dist/themes/data/catppuccin-macchiato.js +177 -0
  143. package/dist/themes/data/catppuccin-mocha.d.ts +3 -0
  144. package/dist/themes/data/catppuccin-mocha.js +177 -0
  145. package/dist/themes/data/cyberpunk.d.ts +17 -0
  146. package/dist/themes/data/cyberpunk.js +193 -0
  147. package/dist/themes/data/default.d.ts +3 -0
  148. package/dist/themes/data/default.js +160 -0
  149. package/dist/themes/data/dracula.d.ts +3 -0
  150. package/dist/themes/data/dracula.js +177 -0
  151. package/dist/themes/data/flexoki.d.ts +3 -0
  152. package/dist/themes/data/flexoki.js +177 -0
  153. package/dist/themes/data/gruvbox.d.ts +3 -0
  154. package/dist/themes/data/gruvbox.js +177 -0
  155. package/dist/themes/data/index.d.ts +35 -0
  156. package/dist/themes/data/index.js +64 -0
  157. package/dist/themes/data/monokai.d.ts +3 -0
  158. package/dist/themes/data/monokai.js +177 -0
  159. package/dist/themes/data/nord.d.ts +3 -0
  160. package/dist/themes/data/nord.js +177 -0
  161. package/dist/themes/data/rose-pine-dawn.d.ts +3 -0
  162. package/dist/themes/data/rose-pine-dawn.js +177 -0
  163. package/dist/themes/data/rose-pine-moon.d.ts +3 -0
  164. package/dist/themes/data/rose-pine-moon.js +177 -0
  165. package/dist/themes/data/rose-pine.d.ts +3 -0
  166. package/dist/themes/data/rose-pine.js +177 -0
  167. package/dist/themes/data/solarized-dark.d.ts +3 -0
  168. package/dist/themes/data/solarized-dark.js +177 -0
  169. package/dist/themes/data/solarized-light.d.ts +3 -0
  170. package/dist/themes/data/solarized-light.js +177 -0
  171. package/dist/themes/data/svg-export.d.ts +3 -0
  172. package/dist/themes/data/svg-export.js +177 -0
  173. package/dist/themes/data/textual-ansi.d.ts +3 -0
  174. package/dist/themes/data/textual-ansi.js +160 -0
  175. package/dist/themes/data/textual-dark.d.ts +3 -0
  176. package/dist/themes/data/textual-dark.js +160 -0
  177. package/dist/themes/data/textual-light.d.ts +3 -0
  178. package/dist/themes/data/textual-light.js +160 -0
  179. package/dist/themes/data/tokyo-night.d.ts +3 -0
  180. package/dist/themes/data/tokyo-night.js +177 -0
  181. package/dist/themes/data/types.d.ts +31 -0
  182. package/dist/themes/data/types.js +10 -0
  183. package/dist/themes/palette.d.ts +21 -0
  184. package/dist/themes/palette.js +28 -0
  185. package/dist/themes/ramp.d.ts +83 -0
  186. package/dist/themes/ramp.js +122 -0
  187. package/dist/themes/registry.d.ts +44 -0
  188. package/dist/themes/registry.js +94 -0
  189. package/dist/themes/terminalThemes.d.ts +49 -0
  190. package/dist/themes/terminalThemes.js +63 -0
  191. package/dist/themes/transpose.d.ts +87 -0
  192. package/dist/themes/transpose.js +138 -0
  193. package/dist/widgets/button.d.ts +49 -0
  194. package/dist/widgets/button.js +208 -0
  195. package/dist/widgets/checkbox.d.ts +41 -0
  196. package/dist/widgets/checkbox.js +157 -0
  197. package/dist/widgets/dropdown.d.ts +67 -0
  198. package/dist/widgets/dropdown.js +450 -0
  199. package/dist/widgets/event-router.d.ts +71 -0
  200. package/dist/widgets/event-router.js +629 -0
  201. package/dist/widgets/focus-manager.d.ts +45 -0
  202. package/dist/widgets/focus-manager.js +191 -0
  203. package/dist/widgets/hit.d.ts +64 -0
  204. package/dist/widgets/hit.js +113 -0
  205. package/dist/widgets/index.d.ts +20 -0
  206. package/dist/widgets/index.js +14 -0
  207. package/dist/widgets/slider.d.ts +57 -0
  208. package/dist/widgets/slider.js +270 -0
  209. package/dist/widgets/static-item.d.ts +34 -0
  210. package/dist/widgets/static-item.js +54 -0
  211. package/dist/widgets/text-input.d.ts +274 -0
  212. package/dist/widgets/text-input.js +1165 -0
  213. package/dist/widgets/toggle.d.ts +44 -0
  214. package/dist/widgets/toggle.js +180 -0
  215. package/dist/widgets/types.d.ts +87 -0
  216. package/dist/widgets/types.js +30 -0
  217. package/dist/widgets/widget-app.d.ts +63 -0
  218. package/dist/widgets/widget-app.js +199 -0
  219. package/dist/widgets/widget-base.d.ts +40 -0
  220. package/dist/widgets/widget-base.js +165 -0
  221. package/package.json +6 -2
@@ -0,0 +1,191 @@
1
+ /**
2
+ * FocusManager — which widget has focus, over the widgets on the frame.
3
+ * [LAW:one-source-of-truth] single authority for which widget has focus.
4
+ * [LAW:dataflow-not-control-flow] focus transitions are observable state;
5
+ * widgets react to focus/blur events, the manager never skips dispatch.
6
+ */
7
+ var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
8
+ var useValue = arguments.length > 2;
9
+ for (var i = 0; i < initializers.length; i++) {
10
+ value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
11
+ }
12
+ return useValue ? value : void 0;
13
+ };
14
+ var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
15
+ function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
16
+ var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
17
+ var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
18
+ var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
19
+ var _, done = false;
20
+ for (var i = decorators.length - 1; i >= 0; i--) {
21
+ var context = {};
22
+ for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
23
+ for (var p in contextIn.access) context.access[p] = contextIn.access[p];
24
+ context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
25
+ var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
26
+ if (kind === "accessor") {
27
+ if (result === void 0) continue;
28
+ if (result === null || typeof result !== "object") throw new TypeError("Object expected");
29
+ if (_ = accept(result.get)) descriptor.get = _;
30
+ if (_ = accept(result.set)) descriptor.set = _;
31
+ if (_ = accept(result.init)) initializers.unshift(_);
32
+ }
33
+ else if (_ = accept(result)) {
34
+ if (kind === "field") initializers.unshift(_);
35
+ else descriptor[key] = _;
36
+ }
37
+ }
38
+ if (target) Object.defineProperty(target, contextIn.name, descriptor);
39
+ done = true;
40
+ };
41
+ import { action, observableRef } from "mobx";
42
+ let DefaultFocusManager = (() => {
43
+ let _instanceExtraInitializers = [];
44
+ let _currentWidget_decorators;
45
+ let _currentWidget_initializers = [];
46
+ let _currentWidget_extraInitializers = [];
47
+ let _next_decorators;
48
+ let _prev_decorators;
49
+ let _focus_decorators;
50
+ let _settle_decorators;
51
+ let _clear_decorators;
52
+ let _setFocus_decorators;
53
+ return class DefaultFocusManager {
54
+ static {
55
+ const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
56
+ _currentWidget_decorators = [observableRef];
57
+ _next_decorators = [action];
58
+ _prev_decorators = [action];
59
+ _focus_decorators = [action];
60
+ _settle_decorators = [action];
61
+ _clear_decorators = [action];
62
+ _setFocus_decorators = [action];
63
+ __esDecorate(this, null, _currentWidget_decorators, { kind: "accessor", name: "currentWidget", static: false, private: false, access: { has: obj => "currentWidget" in obj, get: obj => obj.currentWidget, set: (obj, value) => { obj.currentWidget = value; } }, metadata: _metadata }, _currentWidget_initializers, _currentWidget_extraInitializers);
64
+ __esDecorate(this, null, _next_decorators, { kind: "method", name: "next", static: false, private: false, access: { has: obj => "next" in obj, get: obj => obj.next }, metadata: _metadata }, null, _instanceExtraInitializers);
65
+ __esDecorate(this, null, _prev_decorators, { kind: "method", name: "prev", static: false, private: false, access: { has: obj => "prev" in obj, get: obj => obj.prev }, metadata: _metadata }, null, _instanceExtraInitializers);
66
+ __esDecorate(this, null, _focus_decorators, { kind: "method", name: "focus", static: false, private: false, access: { has: obj => "focus" in obj, get: obj => obj.focus }, metadata: _metadata }, null, _instanceExtraInitializers);
67
+ __esDecorate(this, null, _settle_decorators, { kind: "method", name: "settle", static: false, private: false, access: { has: obj => "settle" in obj, get: obj => obj.settle }, metadata: _metadata }, null, _instanceExtraInitializers);
68
+ __esDecorate(this, null, _clear_decorators, { kind: "method", name: "clear", static: false, private: false, access: { has: obj => "clear" in obj, get: obj => obj.clear }, metadata: _metadata }, null, _instanceExtraInitializers);
69
+ __esDecorate(this, null, _setFocus_decorators, { kind: "method", name: "setFocus", static: false, private: false, access: { has: obj => "setFocus" in obj, get: obj => obj.setFocus }, metadata: _metadata }, null, _instanceExtraInitializers);
70
+ if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
71
+ }
72
+ onScreen = __runInitializers(this, _instanceExtraInitializers);
73
+ #currentWidget_accessor_storage = __runInitializers(this, _currentWidget_initializers, null);
74
+ get currentWidget() { return this.#currentWidget_accessor_storage; }
75
+ set currentWidget(value) { this.#currentWidget_accessor_storage = value; }
76
+ changeHandlers = (__runInitializers(this, _currentWidget_extraInitializers), new Set());
77
+ /**
78
+ * `onScreen` is the widgets on the frame on screen, in document order.
79
+ *
80
+ * [LAW:one-source-of-truth] It is asked every time rather than kept: a list
81
+ * of the widgets held here would be a second picture of the frame, and
82
+ * wrong from the next paint.
83
+ */
84
+ constructor(onScreen) {
85
+ this.onScreen = onScreen;
86
+ }
87
+ get current() {
88
+ return this.currentWidget;
89
+ }
90
+ get widgets() {
91
+ return this.onScreen().filter(takesFocus);
92
+ }
93
+ next() {
94
+ const focusable = this.widgets;
95
+ if (focusable.length === 0)
96
+ return;
97
+ const currentIdx = this.currentWidget ? focusable.indexOf(this.currentWidget) : -1;
98
+ const nextIdx = (currentIdx + 1) % focusable.length;
99
+ this.setFocus(focusable[nextIdx]);
100
+ }
101
+ prev() {
102
+ const focusable = this.widgets;
103
+ if (focusable.length === 0)
104
+ return;
105
+ const currentIdx = this.currentWidget ? focusable.indexOf(this.currentWidget) : -1;
106
+ const prevIdx = currentIdx <= 0 ? focusable.length - 1 : currentIdx - 1;
107
+ this.setFocus(focusable[prevIdx]);
108
+ }
109
+ // A widget not on screen yet can take focus: an app that is about to show
110
+ // it focuses it first, and the frame that shows it keeps it (`settle`).
111
+ focus(widget) {
112
+ if (!takesFocus(widget))
113
+ return;
114
+ this.setFocus(widget);
115
+ }
116
+ /**
117
+ * Put focus where the frame just painted lets it rest: it stays on a widget
118
+ * the view drew (`drawn`) that can take it, and otherwise moves to the first
119
+ * one on screen that can, or to none.
120
+ *
121
+ * Drawn, not on screen: a widget cropped for the moment — the terminal
122
+ * shrank, a viewport scrolled, an overlay covers it — is still in the view,
123
+ * and keeps focus and whatever focus holds, like a half-typed filter.
124
+ *
125
+ * [LAW:single-enforcer] The one place focus follows the frame — onto the
126
+ * first widget when the app starts, off a widget that stopped being drawn
127
+ * or was disabled.
128
+ */
129
+ settle(drawn) {
130
+ const current = this.currentWidget;
131
+ if (current && takesFocus(current) && drawn.includes(current))
132
+ return;
133
+ const first = this.widgets[0];
134
+ if (first)
135
+ this.setFocus(first);
136
+ else
137
+ this.clear();
138
+ }
139
+ onChange(handler) {
140
+ this.changeHandlers.add(handler);
141
+ return () => this.changeHandlers.delete(handler);
142
+ }
143
+ // [LAW:single-enforcer] FocusManager owns Tab/Shift+Tab semantics. The
144
+ // router registers this as a normal-priority handler at construction —
145
+ // it runs after the focused widget, so a widget can `event.stop()`
146
+ // to suppress traversal (e.g. Dropdown when its overlay is open).
147
+ handleKey(event) {
148
+ if (event.key !== "tab")
149
+ return;
150
+ if (event.shift)
151
+ this.prev();
152
+ else
153
+ this.next();
154
+ event.stop();
155
+ }
156
+ // --- Private ---
157
+ // No focus is where `settle` leaves an app with nothing to focus, and only
158
+ // there: anywhere else the next frame would put focus back on the first
159
+ // widget, so there is no public way in.
160
+ clear() {
161
+ if (!this.currentWidget)
162
+ return;
163
+ // [LAW:single-enforcer] WidgetBase.focus()/blur() route through
164
+ // handleFocus; calling it here as well would dispatch twice and run any
165
+ // subclass side effect (e.g. Dropdown clearing its filter) twice.
166
+ this.currentWidget.blur();
167
+ this.currentWidget = null;
168
+ this.emitChange();
169
+ }
170
+ setFocus(widget) {
171
+ if (this.currentWidget === widget)
172
+ return;
173
+ // [LAW:single-enforcer] focus()/blur() already dispatch handleFocus —
174
+ // see clear() for the rationale.
175
+ if (this.currentWidget)
176
+ this.currentWidget.blur();
177
+ this.currentWidget = widget;
178
+ widget.focus();
179
+ this.emitChange();
180
+ }
181
+ emitChange() {
182
+ for (const handler of this.changeHandlers) {
183
+ handler(this.currentWidget);
184
+ }
185
+ }
186
+ };
187
+ })();
188
+ export { DefaultFocusManager };
189
+ function takesFocus(widget) {
190
+ return widget.focusable && !widget.disabled;
191
+ }
@@ -0,0 +1,64 @@
1
+ /**
2
+ * widgetAt — which widget drew a cell of a painted frame, and where in its
3
+ * own output that cell sits; scrollTargetAt — what the wheel over that cell
4
+ * moves.
5
+ *
6
+ * A widget stamps every cell it draws (`WidgetBase.render`), and a
7
+ * `Scrollable` such as `Viewport` every cell it shows, around its content's
8
+ * stamps. The stamp rides
9
+ * through every container on the cell's `Style`, and the frame a screen paints
10
+ * is therefore its own hit map: nothing lays widgets out a second time to
11
+ * answer "what is under the pointer", so the answer cannot disagree with what
12
+ * the user sees. Z-order is paint order — whoever painted a cell last owns it.
13
+ */
14
+ import { Segment } from "../core/segment.js";
15
+ import type { Scrollable } from "../core/protocol.js";
16
+ import type { InteractiveWidget } from "./types.js";
17
+ /** A pointer position resolved to the widget that drew it. */
18
+ export interface WidgetHit {
19
+ readonly widget: InteractiveWidget;
20
+ /** Column of the cell in the widget's own output. */
21
+ readonly col: number;
22
+ /** Row of the cell in the widget's own output. */
23
+ readonly row: number;
24
+ }
25
+ /**
26
+ * The innermost widget that drew the cell at column `x` of row `y` of
27
+ * `frame`, or `undefined` when no widget drew it. A widget nested inside
28
+ * another widget's output wins over the one containing it.
29
+ */
30
+ export declare function widgetAt(frame: readonly (readonly Segment[])[], x: number, y: number): WidgetHit | undefined;
31
+ /**
32
+ * The innermost `Scrollable` that drew the cell at column `x` of row `y` of
33
+ * `frame` and that `scrollBy(lines)` would move, or `undefined` when none
34
+ * did. A widget drawn inside it does not hide it: the widget's anchor is
35
+ * nested in its. One that cannot move that way — a viewport whose content
36
+ * fits, or that is at that end — passes the wheel to the one around it.
37
+ */
38
+ export declare function scrollTargetAt(frame: readonly (readonly Segment[])[], x: number, y: number, lines: number): Scrollable | undefined;
39
+ /**
40
+ * Where `widget`'s output starts in `frame` — the cell its own row 0, column
41
+ * 0 falls on — read off the first cell it drew, or `undefined` when it drew
42
+ * none.
43
+ */
44
+ export declare function originOf(frame: readonly (readonly Segment[])[], widget: InteractiveWidget): {
45
+ x: number;
46
+ y: number;
47
+ } | undefined;
48
+ /**
49
+ * Whether `widget` drew the cell at column `x` of row `y` of `frame`, itself
50
+ * or through a widget nested in its output.
51
+ */
52
+ export declare function drew(frame: readonly (readonly Segment[])[], widget: InteractiveWidget, x: number, y: number): boolean;
53
+ /**
54
+ * Where `widget`'s footprint sits in `frame`: the cell its row 0, column 0
55
+ * falls on, and how many of its rows the frame shows down to its lowest — or
56
+ * `undefined` when the frame does not show its row 0.
57
+ */
58
+ export declare function footprintOf(frame: readonly (readonly Segment[])[], widget: InteractiveWidget): {
59
+ x: number;
60
+ y: number;
61
+ rows: number;
62
+ } | undefined;
63
+ /** Every owner that drew a cell of `frame`, at every depth of nesting. */
64
+ export declare function ownersOn(frame: readonly (readonly Segment[])[]): Set<object>;
@@ -0,0 +1,113 @@
1
+ /**
2
+ * widgetAt — which widget drew a cell of a painted frame, and where in its
3
+ * own output that cell sits; scrollTargetAt — what the wheel over that cell
4
+ * moves.
5
+ *
6
+ * A widget stamps every cell it draws (`WidgetBase.render`), and a
7
+ * `Scrollable` such as `Viewport` every cell it shows, around its content's
8
+ * stamps. The stamp rides
9
+ * through every container on the cell's `Style`, and the frame a screen paints
10
+ * is therefore its own hit map: nothing lays widgets out a second time to
11
+ * answer "what is under the pointer", so the answer cannot disagree with what
12
+ * the user sees. Z-order is paint order — whoever painted a cell last owns it.
13
+ */
14
+ import { Segment } from "../core/segment.js";
15
+ import { isScrollable } from "../core/protocol.js";
16
+ import { WidgetBase } from "./widget-base.js";
17
+ /**
18
+ * The innermost widget that drew the cell at column `x` of row `y` of
19
+ * `frame`, or `undefined` when no widget drew it. A widget nested inside
20
+ * another widget's output wins over the one containing it.
21
+ */
22
+ export function widgetAt(frame, x, y) {
23
+ const hit = innermost(frame, x, y, (owner) => (owner instanceof WidgetBase ? owner : undefined));
24
+ return hit && { widget: hit.owner, col: hit.col, row: hit.row };
25
+ }
26
+ /**
27
+ * The innermost `Scrollable` that drew the cell at column `x` of row `y` of
28
+ * `frame` and that `scrollBy(lines)` would move, or `undefined` when none
29
+ * did. A widget drawn inside it does not hide it: the widget's anchor is
30
+ * nested in its. One that cannot move that way — a viewport whose content
31
+ * fits, or that is at that end — passes the wheel to the one around it.
32
+ */
33
+ export function scrollTargetAt(frame, x, y, lines) {
34
+ return innermost(frame, x, y, (owner) => isScrollable(owner) && owner.canScrollBy(lines) ? owner : undefined)?.owner;
35
+ }
36
+ /**
37
+ * The innermost owner of the cell at column `x` of row `y` of `frame` that
38
+ * `accept` turns into a `T`, with the cell's place in that owner's output.
39
+ *
40
+ * [LAW:parse-dont-validate] An anchor's owner is any object; `accept` is
41
+ * where it becomes the kind of owner the caller asked for, or nothing.
42
+ */
43
+ function innermost(frame, x, y, accept) {
44
+ let found;
45
+ for (let a = Segment.anchorAt(frame, x, y); a; a = a.inner) {
46
+ const owner = accept(a.owner);
47
+ if (owner)
48
+ found = { owner, col: a.col, row: a.row };
49
+ }
50
+ return found;
51
+ }
52
+ /**
53
+ * Where `widget`'s output starts in `frame` — the cell its own row 0, column
54
+ * 0 falls on — read off the first cell it drew, or `undefined` when it drew
55
+ * none.
56
+ */
57
+ export function originOf(frame, widget) {
58
+ for (let y = 0; y < frame.length; y++) {
59
+ let start = 0;
60
+ for (const segment of frame[y]) {
61
+ for (let a = segment.style?.anchor; a; a = a.inner) {
62
+ if (a.owner === widget)
63
+ return { x: start - a.col, y: y - a.row };
64
+ }
65
+ start += segment.cellLength;
66
+ }
67
+ }
68
+ return undefined;
69
+ }
70
+ /**
71
+ * Whether `widget` drew the cell at column `x` of row `y` of `frame`, itself
72
+ * or through a widget nested in its output.
73
+ */
74
+ export function drew(frame, widget, x, y) {
75
+ for (let a = Segment.anchorAt(frame, x, y); a; a = a.inner)
76
+ if (a.owner === widget)
77
+ return true;
78
+ return false;
79
+ }
80
+ /**
81
+ * Where `widget`'s footprint sits in `frame`: the cell its row 0, column 0
82
+ * falls on, and how many of its rows the frame shows down to its lowest — or
83
+ * `undefined` when the frame does not show its row 0.
84
+ */
85
+ export function footprintOf(frame, widget) {
86
+ let origin;
87
+ let rows = 0;
88
+ for (let y = 0; y < frame.length; y++) {
89
+ let start = 0;
90
+ for (const segment of frame[y]) {
91
+ for (let a = segment.style?.anchor; a; a = a.inner) {
92
+ if (a.owner !== widget)
93
+ continue;
94
+ if (a.row === 0 && !origin)
95
+ origin = { x: start - a.col, y };
96
+ rows = Math.max(rows, a.row + 1);
97
+ }
98
+ start += segment.cellLength;
99
+ }
100
+ }
101
+ return origin && { ...origin, rows };
102
+ }
103
+ /** Every owner that drew a cell of `frame`, at every depth of nesting. */
104
+ export function ownersOn(frame) {
105
+ const owners = new Set();
106
+ for (const line of frame) {
107
+ for (const segment of line) {
108
+ for (let a = segment.style?.anchor; a; a = a.inner)
109
+ owners.add(a.owner);
110
+ }
111
+ }
112
+ return owners;
113
+ }
@@ -0,0 +1,20 @@
1
+ export type { KeyEventInit, KeyHandlerPriority, KeyHandlerOptions, ScreenMouseEvent, WidgetMouseEvent, WidgetFocusEvent, InteractiveWidget, OverlayRenderable, FocusManager, } from "./types.js";
2
+ export { hasOverlay, KeyEvent } from "./types.js";
3
+ export { StaticItem } from "./static-item.js";
4
+ export type { StaticItemOptions } from "./static-item.js";
5
+ export { WidgetBase } from "./widget-base.js";
6
+ export { WidgetApp } from "./widget-app.js";
7
+ export { Button } from "./button.js";
8
+ export type { ButtonVariant, ButtonOptions } from "./button.js";
9
+ export { Checkbox } from "./checkbox.js";
10
+ export type { CheckboxOptions } from "./checkbox.js";
11
+ export { Toggle } from "./toggle.js";
12
+ export type { ToggleVariant, ToggleOptions } from "./toggle.js";
13
+ export { TextInput, charGreedyWrap } from "./text-input.js";
14
+ export type { TextInputOptions, WrapStrategy, WrapRow } from "./text-input.js";
15
+ export { Dropdown } from "./dropdown.js";
16
+ export type { DropdownOptions } from "./dropdown.js";
17
+ export { Slider } from "./slider.js";
18
+ export type { SliderOptions } from "./slider.js";
19
+ export { widgetAt } from "./hit.js";
20
+ export type { WidgetHit } from "./hit.js";
@@ -0,0 +1,14 @@
1
+ export { hasOverlay, KeyEvent } from "./types.js";
2
+ export { StaticItem } from "./static-item.js";
3
+ export { WidgetBase } from "./widget-base.js";
4
+ export { WidgetApp } from "./widget-app.js";
5
+ export { Button } from "./button.js";
6
+ export { Checkbox } from "./checkbox.js";
7
+ export { Toggle } from "./toggle.js";
8
+ export { TextInput, charGreedyWrap } from "./text-input.js";
9
+ export { Dropdown } from "./dropdown.js";
10
+ export { Slider } from "./slider.js";
11
+ export { widgetAt } from "./hit.js";
12
+ // The terminal seam is not re-exported here. It lives on the `host` subpath,
13
+ // and a second path to `TerminalHost` would be the two-clocks problem the
14
+ // subpath split exists to remove.
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Slider widget — numeric value within [min, max] with step increments.
3
+ * [LAW:dataflow-not-control-flow] every render emits exactly `width`
4
+ * track cells; the marker cell index is data, not a branch.
5
+ * [LAW:one-type-per-behavior] shared infrastructure inherited from
6
+ * WidgetBase.
7
+ *
8
+ * Visual:
9
+ * track — `width` cells of "─" (ASCII fallback "-")
10
+ * marker — "●" (ASCII fallback "*") at round((value - min) / range * (width - 1))
11
+ * filled — cells left of and including the marker use primary fg
12
+ * on the default terminal bg
13
+ * unfilled — cells right of the marker use surface fg on the default
14
+ * terminal bg (no explicit bgcolor — the unfilled track
15
+ * should sit transparently against whatever the panel /
16
+ * parent paints underneath)
17
+ * focused — underline on the segments
18
+ * disabled — dim
19
+ */
20
+ import { Segment } from "../core/segment.js";
21
+ import { type RenderOptions } from "../core/protocol.js";
22
+ import type { TerminalTheme } from "../core/color.js";
23
+ import { WidgetBase } from "./widget-base.js";
24
+ import type { KeyEvent, WidgetMouseEvent } from "./types.js";
25
+ export interface SliderOptions {
26
+ value?: number;
27
+ min?: number;
28
+ max?: number;
29
+ step?: number;
30
+ width?: number;
31
+ id?: string;
32
+ disabled?: boolean;
33
+ theme?: TerminalTheme;
34
+ }
35
+ export declare class Slider extends WidgetBase {
36
+ readonly id: string;
37
+ readonly focusable = true;
38
+ accessor value: number;
39
+ accessor min: number;
40
+ accessor max: number;
41
+ accessor step: number;
42
+ accessor width: number;
43
+ private accessor _theme;
44
+ private _dragging;
45
+ constructor(options?: SliderOptions);
46
+ setTheme(theme: TerminalTheme): void;
47
+ handleKey(event: KeyEvent): void;
48
+ handleMouse(event: WidgetMouseEvent): void;
49
+ private setValue;
50
+ private setValueFromMouseX;
51
+ protected draw(options: RenderOptions): Iterable<Segment>;
52
+ measure(_options: RenderOptions): {
53
+ minimum: number;
54
+ maximum: number;
55
+ };
56
+ private resolvePalette;
57
+ }