@promptctl/rich-js 0.19.0 → 0.20.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.
- package/README.md +3 -2
- package/dist/core/color.d.ts +1 -0
- package/dist/core/color.js +3 -2
- package/dist/core/noise.d.ts +31 -0
- package/dist/core/noise.js +94 -0
- package/dist/core/paint.js +13 -2
- package/dist/core/pretty.d.ts +23 -2
- package/dist/core/pretty.js +54 -18
- package/dist/core/protocol.d.ts +2 -0
- package/dist/core/protocol.js +3 -2
- package/dist/core/selection.d.ts +12 -0
- package/dist/core/selection.js +14 -0
- package/dist/core/strip.d.ts +103 -72
- package/dist/core/strip.js +240 -212
- package/dist/core/style.js +9 -7
- package/dist/host/app.d.ts +68 -2
- package/dist/host/app.js +125 -15
- package/dist/host/index.d.ts +3 -1
- package/dist/host/index.js +1 -0
- package/dist/host/input.d.ts +84 -0
- package/dist/host/input.js +498 -0
- package/dist/host/terminal-host.d.ts +12 -0
- package/dist/host/terminal-host.js +2 -0
- package/dist/index.d.ts +9 -4
- package/dist/index.js +6 -3
- package/dist/node/terminal-host.d.ts +7 -0
- package/dist/node/terminal-host.js +7 -0
- package/dist/renderables/effect.d.ts +23 -8
- package/dist/renderables/effect.js +48 -26
- package/dist/renderables/effects.d.ts +252 -0
- package/dist/renderables/effects.js +565 -0
- package/dist/renderables/embed.d.ts +11 -5
- package/dist/renderables/embed.js +13 -6
- package/dist/renderables/list-view.d.ts +42 -0
- package/dist/renderables/list-view.js +78 -0
- package/dist/renderables/progress.d.ts +6 -0
- package/dist/renderables/progress.js +11 -4
- package/dist/renderables/progressBar.d.ts +22 -2
- package/dist/renderables/progressBar.js +51 -7
- package/dist/renderables/rule.d.ts +2 -2
- package/dist/renderables/rule.js +12 -10
- package/dist/renderables/table.js +5 -7
- package/dist/renderables/viewport.d.ts +30 -0
- package/dist/renderables/viewport.js +59 -3
- package/dist/widgets/dropdown.js +3 -3
- package/dist/widgets/event-router.d.ts +31 -40
- package/dist/widgets/event-router.js +52 -483
- package/dist/widgets/index.d.ts +2 -1
- package/dist/widgets/types.d.ts +8 -25
- package/dist/widgets/types.js +8 -0
- package/dist/widgets/widget-app.d.ts +22 -7
- package/dist/widgets/widget-app.js +22 -12
- package/package.json +22 -18
|
@@ -20,12 +20,21 @@
|
|
|
20
20
|
*
|
|
21
21
|
* [LAW:locality-or-seam] `App` knows nothing of widgets — `host/` depends on
|
|
22
22
|
* `core/` alone — and this reaches it only through the seams it already has:
|
|
23
|
-
* the view is a renderable,
|
|
23
|
+
* the view is a renderable, `onPaint` hears the frame, and `onKey`/`onMouse`
|
|
24
|
+
* hear the input.
|
|
24
25
|
*/
|
|
25
26
|
import { Segment } from "../core/segment.js";
|
|
26
27
|
import type { Unsubscribe } from "../core/subscription.js";
|
|
27
|
-
import { type AppOptions, type AppPhase } from "../host/app.js";
|
|
28
|
-
import type { FocusManager, FrameSource, KeyEvent, KeyHandlerOptions
|
|
28
|
+
import { type AppOptions, type AppPhase, type Wheel } from "../host/app.js";
|
|
29
|
+
import type { FocusManager, FrameSource, KeyEvent, KeyHandlerOptions } from "./types.js";
|
|
30
|
+
import type { AppMouseEvent } from "../host/app.js";
|
|
31
|
+
export interface WidgetAppOptions extends AppOptions {
|
|
32
|
+
/**
|
|
33
|
+
* Whether a left-button press focuses the widget under it, before it hears the
|
|
34
|
+
* press. `true` unless given.
|
|
35
|
+
*/
|
|
36
|
+
readonly focusOnClick?: boolean;
|
|
37
|
+
}
|
|
29
38
|
export declare class WidgetApp implements FrameSource {
|
|
30
39
|
readonly focusManager: FocusManager;
|
|
31
40
|
private readonly focus;
|
|
@@ -33,7 +42,7 @@ export declare class WidgetApp implements FrameSource {
|
|
|
33
42
|
private readonly router;
|
|
34
43
|
private readonly reaction;
|
|
35
44
|
private drawn;
|
|
36
|
-
constructor(options:
|
|
45
|
+
constructor(options: WidgetAppOptions);
|
|
37
46
|
get phase(): AppPhase;
|
|
38
47
|
/** The rows on screen now, as painted: what a pointer event lands on. */
|
|
39
48
|
get frame(): readonly (readonly Segment[])[];
|
|
@@ -54,12 +63,18 @@ export declare class WidgetApp implements FrameSource {
|
|
|
54
63
|
/** Paint at the app's rate until the returned function is called, as `App.animate` does. */
|
|
55
64
|
animate(): Unsubscribe;
|
|
56
65
|
/**
|
|
57
|
-
* Hear every key. A `high` handler hears it before the focused widget, a
|
|
66
|
+
* Hear every key the app does not quit on. A `high` handler hears it before the focused widget, a
|
|
58
67
|
* `normal` one after it — and after Tab has moved focus — and a handler
|
|
59
68
|
* that calls `event.stop()` ends the key there.
|
|
60
69
|
*/
|
|
61
70
|
onKey(handler: (event: KeyEvent) => void, options?: KeyHandlerOptions): Unsubscribe;
|
|
62
|
-
/** Hear every pointer event, in terminal cells, before any widget does. */
|
|
63
|
-
onMouse(handler: (event:
|
|
71
|
+
/** Hear every pointer event but the vertical wheel, in terminal cells, before any widget does. */
|
|
72
|
+
onMouse(handler: (event: AppMouseEvent) => void): Unsubscribe;
|
|
73
|
+
/**
|
|
74
|
+
* Offer each wheel turn the viewport under the pointer did not move with to
|
|
75
|
+
* `handler`, as `App.onWheel` does: it returns whether it moved something,
|
|
76
|
+
* and a turn nothing moved with is passed outward.
|
|
77
|
+
*/
|
|
78
|
+
onWheel(handler: (wheel: Wheel) => boolean): Unsubscribe;
|
|
64
79
|
private compose;
|
|
65
80
|
}
|
|
@@ -20,7 +20,8 @@
|
|
|
20
20
|
*
|
|
21
21
|
* [LAW:locality-or-seam] `App` knows nothing of widgets — `host/` depends on
|
|
22
22
|
* `core/` alone — and this reaches it only through the seams it already has:
|
|
23
|
-
* the view is a renderable,
|
|
23
|
+
* the view is a renderable, `onPaint` hears the frame, and `onKey`/`onMouse`
|
|
24
|
+
* hear the input.
|
|
24
25
|
*/
|
|
25
26
|
import { Reaction } from "mobx";
|
|
26
27
|
import { Segment } from "../core/segment.js";
|
|
@@ -40,7 +41,7 @@ export class WidgetApp {
|
|
|
40
41
|
// The widgets the view drew for the frame on screen, in document order.
|
|
41
42
|
drawn = [];
|
|
42
43
|
constructor(options) {
|
|
43
|
-
const { view } = options;
|
|
44
|
+
const { view, focusOnClick = true } = options;
|
|
44
45
|
this.reaction = new Reaction("WidgetApp", () => this.app.refresh());
|
|
45
46
|
this.app = new App({
|
|
46
47
|
...options,
|
|
@@ -51,7 +52,12 @@ export class WidgetApp {
|
|
|
51
52
|
return this.drawn.filter((widget) => owners.has(widget));
|
|
52
53
|
});
|
|
53
54
|
this.focusManager = this.focus;
|
|
54
|
-
this.router = new EventRouter({ source: this,
|
|
55
|
+
this.router = new EventRouter({ source: this, focusOnClick });
|
|
56
|
+
// [LAW:single-enforcer] The app reads the terminal; the router routes
|
|
57
|
+
// what it hears, after the app's quit keys.
|
|
58
|
+
this.app.onKey((press) => this.router.key(press));
|
|
59
|
+
this.app.onMouse((event) => this.router.mouse(event));
|
|
60
|
+
this.app.onWheel((wheel) => this.router.wheel(wheel));
|
|
55
61
|
this.app.onPaint(() => {
|
|
56
62
|
this.focus.settle(this.drawn);
|
|
57
63
|
this.router.framePainted();
|
|
@@ -72,18 +78,14 @@ export class WidgetApp {
|
|
|
72
78
|
* until the app stops — `App.run`, with the input.
|
|
73
79
|
*/
|
|
74
80
|
async run() {
|
|
75
|
-
// App refuses a second run; this one must not end the
|
|
81
|
+
// App refuses a second run; this one must not end the state of the first.
|
|
76
82
|
if (this.app.phase !== "idle")
|
|
77
83
|
return this.app.run();
|
|
78
|
-
// Listening before the app starts, so a first frame that throws — and
|
|
79
|
-
// stops the host — is not followed by a subscription that restarts it.
|
|
80
|
-
this.router.start();
|
|
81
|
-
const running = this.app.run();
|
|
82
84
|
try {
|
|
83
|
-
await
|
|
85
|
+
await this.app.run();
|
|
84
86
|
}
|
|
85
87
|
finally {
|
|
86
|
-
this.router.
|
|
88
|
+
this.router.reset();
|
|
87
89
|
this.reaction.dispose();
|
|
88
90
|
}
|
|
89
91
|
}
|
|
@@ -109,17 +111,25 @@ export class WidgetApp {
|
|
|
109
111
|
return this.app.animate();
|
|
110
112
|
}
|
|
111
113
|
/**
|
|
112
|
-
* Hear every key. A `high` handler hears it before the focused widget, a
|
|
114
|
+
* Hear every key the app does not quit on. A `high` handler hears it before the focused widget, a
|
|
113
115
|
* `normal` one after it — and after Tab has moved focus — and a handler
|
|
114
116
|
* that calls `event.stop()` ends the key there.
|
|
115
117
|
*/
|
|
116
118
|
onKey(handler, options) {
|
|
117
119
|
return this.router.onKey(handler, options);
|
|
118
120
|
}
|
|
119
|
-
/** Hear every pointer event, in terminal cells, before any widget does. */
|
|
121
|
+
/** Hear every pointer event but the vertical wheel, in terminal cells, before any widget does. */
|
|
120
122
|
onMouse(handler) {
|
|
121
123
|
return this.router.onMouse(handler);
|
|
122
124
|
}
|
|
125
|
+
/**
|
|
126
|
+
* Offer each wheel turn the viewport under the pointer did not move with to
|
|
127
|
+
* `handler`, as `App.onWheel` does: it returns whether it moved something,
|
|
128
|
+
* and a turn nothing moved with is passed outward.
|
|
129
|
+
*/
|
|
130
|
+
onWheel(handler) {
|
|
131
|
+
return this.app.onWheel(handler);
|
|
132
|
+
}
|
|
123
133
|
compose(view, options) {
|
|
124
134
|
const drawn = new Set();
|
|
125
135
|
// [LAW:parse-dont-validate] An owner is any object; only a `WidgetBase`
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@promptctl/rich-js",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.20.0",
|
|
4
4
|
"description": "Rich text and beautiful formatting in the terminal — a TypeScript port of Python's Rich",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -61,26 +61,27 @@
|
|
|
61
61
|
"build": "npm run clean && tsc",
|
|
62
62
|
"test": "vitest run",
|
|
63
63
|
"test:watch": "vitest",
|
|
64
|
+
"prelint": "node scripts/stage-repo-files.ts",
|
|
64
65
|
"lint": "tsc --noEmit && tsc -p tsconfig.scripts.json && tsc -p tsconfig.test.json",
|
|
65
66
|
"clean": "rm -rf dist",
|
|
66
|
-
"
|
|
67
|
-
"docs:
|
|
67
|
+
"predocs:dev": "node scripts/stage-repo-files.ts",
|
|
68
|
+
"docs:dev": "vitepress dev docs",
|
|
69
|
+
"predocs:build": "node scripts/stage-repo-files.ts",
|
|
70
|
+
"docs:build": "vitepress build docs",
|
|
68
71
|
"docs:preview": "vitepress preview docs",
|
|
69
|
-
"demo": "
|
|
70
|
-
"demo:build": "
|
|
71
|
-
"sessions": "
|
|
72
|
-
"strip": "
|
|
73
|
-
"effects-feel": "
|
|
74
|
-
"viewport": "
|
|
75
|
-
"markup-plugins": "
|
|
76
|
-
"demo-inputs": "
|
|
77
|
-
"demo:dropdown": "
|
|
78
|
-
"dash": "
|
|
79
|
-
"template-bindings": "
|
|
80
|
-
"themes-and-color-studio": "
|
|
81
|
-
"
|
|
82
|
-
"demos:build": "tsc -p tsconfig.demo.json && vite build --config vite.config.demos.ts",
|
|
83
|
-
"demos:preview": "vite preview --config vite.config.demos.ts",
|
|
72
|
+
"demo": "node scripts/build-demos.ts && node dist-demo/examples/rich-explore/node.js",
|
|
73
|
+
"demo:build": "node scripts/build-demos.ts",
|
|
74
|
+
"sessions": "node scripts/build-demos.ts && node dist-demo/examples/claude-sessions/node.js",
|
|
75
|
+
"strip": "node scripts/build-demos.ts && node dist-demo/examples/rich-strip/main.js",
|
|
76
|
+
"effects-feel": "node scripts/build-demos.ts && node dist-demo/examples/effects-feel/index.js",
|
|
77
|
+
"viewport": "node scripts/build-demos.ts && node dist-demo/examples/rich-viewport/main.js",
|
|
78
|
+
"markup-plugins": "node scripts/build-demos.ts && node dist-demo/examples/rich-markup-plugins/main.js",
|
|
79
|
+
"demo-inputs": "node scripts/build-demos.ts && node dist-demo/examples/rich-config/main.js",
|
|
80
|
+
"demo:dropdown": "node scripts/build-demos.ts && node dist-demo/examples/dropdown-demo/main.js",
|
|
81
|
+
"dash": "node scripts/build-demos.ts && node dist-demo/examples/rich-dash/node.js",
|
|
82
|
+
"template-bindings": "node scripts/build-demos.ts && node dist-demo/examples/rich-template-bindings/main.js",
|
|
83
|
+
"themes-and-color-studio": "node scripts/build-demos.ts && node dist-demo/examples/themes-and-color-studio/node.js",
|
|
84
|
+
"terminal-host": "node scripts/build-demos.ts && node dist-demo/examples/terminal-host/main.js",
|
|
84
85
|
"test:demos": "playwright test"
|
|
85
86
|
},
|
|
86
87
|
"keywords": [
|
|
@@ -97,6 +98,9 @@
|
|
|
97
98
|
"cli"
|
|
98
99
|
],
|
|
99
100
|
"license": "MIT",
|
|
101
|
+
"devEngines": {
|
|
102
|
+
"runtime": { "name": "node", "version": "^22.18.0 || >=23.6.0", "onFail": "error" }
|
|
103
|
+
},
|
|
100
104
|
"engines": {
|
|
101
105
|
"node": ">=20"
|
|
102
106
|
},
|