@moyarich/console-addon-process-state 0.0.0-stage → 0.2.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 +38 -2
- package/dist/ProgressIndicator.d.cts +19 -0
- package/dist/ProgressIndicator.d.ts +19 -0
- package/dist/console-addon-process-state.css +66 -0
- package/dist/index.cjs +326 -0
- package/dist/index.d.cts +58 -0
- package/dist/index.d.ts +58 -0
- package/dist/index.js +326 -0
- package/dist/locales/en.json +7 -0
- package/dist/locales/es.json +7 -0
- package/dist/locales/fr.json +7 -0
- package/dist/locales/pt.json +7 -0
- package/dist/localization.d.cts +3 -0
- package/dist/localization.d.ts +3 -0
- package/dist/styles.css +67 -0
- package/package.json +70 -4
package/README.md
CHANGED
|
@@ -1,3 +1,39 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @moyarich/console-addon-process-state
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Track terminal process progress. Interpret OSC progress, working directory, command lifecycle, and notifications without requiring xterm.js.
|
|
4
|
+
|
|
5
|
+
[Documentation and live examples](https://moyarich.github.io/console/)
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install @moyarich/console @moyarich/console-addon-process-state react
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Configure the `@moyarich` scope and authenticate with GitHub Packages as described in the [installation guide](../../../README.md#installation).
|
|
14
|
+
|
|
15
|
+
Required peer dependencies: `@moyarich/console-core@^0.2.0`, `react@>=18`.
|
|
16
|
+
|
|
17
|
+
## Quick start
|
|
18
|
+
|
|
19
|
+
```tsx
|
|
20
|
+
import { Console } from "@moyarich/console";
|
|
21
|
+
import { createConsoleProcessStateAddon } from "@moyarich/console-addon-process-state";
|
|
22
|
+
|
|
23
|
+
const addons = [createConsoleProcessStateAddon()];
|
|
24
|
+
|
|
25
|
+
// Pass your application's terminal output entries to Console.
|
|
26
|
+
<Console mode="terminal" messages={messages} addons={addons} />;
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
The addon is optional and can be combined with other Console addons. Use terminal mode when passing process output.
|
|
30
|
+
|
|
31
|
+
## Learn more
|
|
32
|
+
|
|
33
|
+
Explore [runnable package examples](./examples) and the [Console documentation](https://moyarich.github.io/console/) for available settings and integration patterns.
|
|
34
|
+
|
|
35
|
+
Review the [changelog](./CHANGELOG.md) for changes by version and [package metadata](./package.json) for dependency requirements.
|
|
36
|
+
|
|
37
|
+
## License
|
|
38
|
+
|
|
39
|
+
MIT
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type ProcessStateTranslations } from "./localization.cjs";
|
|
2
|
+
import { type CSSProperties } from "react";
|
|
3
|
+
import type { ProcessStateController } from "./index.cjs";
|
|
4
|
+
|
|
5
|
+
export interface ConsoleProgressIndicatorOptions {
|
|
6
|
+
locale?: string;
|
|
7
|
+
translations?: ProcessStateTranslations;
|
|
8
|
+
className?: string;
|
|
9
|
+
style?: CSSProperties;
|
|
10
|
+
/** Custom label for the determinate progress mode. */
|
|
11
|
+
format?: (percentage: number, state: number) => string;
|
|
12
|
+
/** Keep the progress strip visible after a clear command. */
|
|
13
|
+
showCleared?: boolean;
|
|
14
|
+
}
|
|
15
|
+
export interface ConsoleProgressIndicatorProps extends ConsoleProgressIndicatorOptions {
|
|
16
|
+
controller: ProcessStateController;
|
|
17
|
+
}
|
|
18
|
+
/** Read-only, optional status strip; it never modifies terminal output or scroll position. */
|
|
19
|
+
export declare function ConsoleProgressIndicator({ controller, className, style, format, showCleared, locale, translations, }: ConsoleProgressIndicatorProps): import("react").JSX.Element | null;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type ProcessStateTranslations } from "./localization.js";
|
|
2
|
+
import { type CSSProperties } from "react";
|
|
3
|
+
import type { ProcessStateController } from "./index.js";
|
|
4
|
+
|
|
5
|
+
export interface ConsoleProgressIndicatorOptions {
|
|
6
|
+
locale?: string;
|
|
7
|
+
translations?: ProcessStateTranslations;
|
|
8
|
+
className?: string;
|
|
9
|
+
style?: CSSProperties;
|
|
10
|
+
/** Custom label for the determinate progress mode. */
|
|
11
|
+
format?: (percentage: number, state: number) => string;
|
|
12
|
+
/** Keep the progress strip visible after a clear command. */
|
|
13
|
+
showCleared?: boolean;
|
|
14
|
+
}
|
|
15
|
+
export interface ConsoleProgressIndicatorProps extends ConsoleProgressIndicatorOptions {
|
|
16
|
+
controller: ProcessStateController;
|
|
17
|
+
}
|
|
18
|
+
/** Read-only, optional status strip; it never modifies terminal output or scroll position. */
|
|
19
|
+
export declare function ConsoleProgressIndicator({ controller, className, style, format, showCleared, locale, translations, }: ConsoleProgressIndicatorProps): import("react").JSX.Element | null;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
.console-progress-indicator {
|
|
2
|
+
--_progress-fg: var(
|
|
3
|
+
--console-progress-color,
|
|
4
|
+
var(--console-color-accent, currentColor)
|
|
5
|
+
);
|
|
6
|
+
--_progress-track: var(
|
|
7
|
+
--console-progress-track,
|
|
8
|
+
color-mix(in srgb, currentColor 12%, transparent)
|
|
9
|
+
);
|
|
10
|
+
--_progress-text: var(--console-progress-text, inherit);
|
|
11
|
+
/* This overlay has no layout height: updates cannot resize or scroll the terminal. */
|
|
12
|
+
position: sticky;
|
|
13
|
+
top: 0;
|
|
14
|
+
z-index: 2;
|
|
15
|
+
display: flex;
|
|
16
|
+
justify-content: flex-end;
|
|
17
|
+
align-items: center;
|
|
18
|
+
gap: var(--console-progress-gap, 0.75rem);
|
|
19
|
+
box-sizing: border-box;
|
|
20
|
+
height: 0;
|
|
21
|
+
min-height: 0;
|
|
22
|
+
padding: 0 var(--console-progress-inline-padding, 0.75rem);
|
|
23
|
+
pointer-events: none;
|
|
24
|
+
color: var(--_progress-text);
|
|
25
|
+
font: inherit;
|
|
26
|
+
transform: translateY(var(--console-progress-offset, 0.25rem));
|
|
27
|
+
}
|
|
28
|
+
.console-progress-indicator__label {
|
|
29
|
+
flex: none;
|
|
30
|
+
font-size: 0.8em;
|
|
31
|
+
}
|
|
32
|
+
.console-progress-indicator__track {
|
|
33
|
+
flex: 1;
|
|
34
|
+
height: 0.35rem;
|
|
35
|
+
border-radius: 999px;
|
|
36
|
+
background: var(--_progress-track);
|
|
37
|
+
overflow: hidden;
|
|
38
|
+
}
|
|
39
|
+
.console-progress-indicator__fill {
|
|
40
|
+
height: 100%;
|
|
41
|
+
background: var(--_progress-fg);
|
|
42
|
+
transition: width 120ms linear;
|
|
43
|
+
}
|
|
44
|
+
.console-progress-indicator[data-state="2"] .console-progress-indicator__fill {
|
|
45
|
+
background: var(--console-progress-error, #b42318);
|
|
46
|
+
}
|
|
47
|
+
.console-progress-indicator[data-state="4"] .console-progress-indicator__fill {
|
|
48
|
+
background: var(--console-progress-paused, #a46b00);
|
|
49
|
+
}
|
|
50
|
+
.console-progress-indicator[data-state="3"] .console-progress-indicator__fill {
|
|
51
|
+
animation: console-progress-motion 1.5s ease-in-out infinite alternate;
|
|
52
|
+
}
|
|
53
|
+
@keyframes console-progress-motion {
|
|
54
|
+
from {
|
|
55
|
+
transform: translateX(0);
|
|
56
|
+
}
|
|
57
|
+
to {
|
|
58
|
+
transform: translateX(230%);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
@media (prefers-reduced-motion: reduce) {
|
|
62
|
+
.console-progress-indicator__fill {
|
|
63
|
+
transition: none;
|
|
64
|
+
animation: none !important;
|
|
65
|
+
}
|
|
66
|
+
}
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const react = require("react");
|
|
4
|
+
const jsxRuntime = require("react/jsx-runtime");
|
|
5
|
+
const consoleCore = require("@moyarich/console-core");
|
|
6
|
+
const cleared$3 = "Progress cleared";
|
|
7
|
+
const working$3 = "Working";
|
|
8
|
+
const error$3 = "Process error";
|
|
9
|
+
const paused$3 = "Paused";
|
|
10
|
+
const progress$3 = "In progress";
|
|
11
|
+
const en = {
|
|
12
|
+
cleared: cleared$3,
|
|
13
|
+
working: working$3,
|
|
14
|
+
error: error$3,
|
|
15
|
+
paused: paused$3,
|
|
16
|
+
progress: progress$3
|
|
17
|
+
};
|
|
18
|
+
const cleared$2 = "Progreso borrado";
|
|
19
|
+
const working$2 = "Trabajando";
|
|
20
|
+
const error$2 = "Error del proceso";
|
|
21
|
+
const paused$2 = "En pausa";
|
|
22
|
+
const progress$2 = "En curso";
|
|
23
|
+
const es = {
|
|
24
|
+
cleared: cleared$2,
|
|
25
|
+
working: working$2,
|
|
26
|
+
error: error$2,
|
|
27
|
+
paused: paused$2,
|
|
28
|
+
progress: progress$2
|
|
29
|
+
};
|
|
30
|
+
const cleared$1 = "Progression effacée";
|
|
31
|
+
const working$1 = "En cours";
|
|
32
|
+
const error$1 = "Erreur du processus";
|
|
33
|
+
const paused$1 = "En pause";
|
|
34
|
+
const progress$1 = "En progression";
|
|
35
|
+
const fr = {
|
|
36
|
+
cleared: cleared$1,
|
|
37
|
+
working: working$1,
|
|
38
|
+
error: error$1,
|
|
39
|
+
paused: paused$1,
|
|
40
|
+
progress: progress$1
|
|
41
|
+
};
|
|
42
|
+
const cleared = "Progresso limpo";
|
|
43
|
+
const working = "Trabalhando";
|
|
44
|
+
const error = "Erro do processo";
|
|
45
|
+
const paused = "Pausado";
|
|
46
|
+
const progress = "Em andamento";
|
|
47
|
+
const pt = {
|
|
48
|
+
cleared,
|
|
49
|
+
working,
|
|
50
|
+
error,
|
|
51
|
+
paused,
|
|
52
|
+
progress
|
|
53
|
+
};
|
|
54
|
+
const locales = { en, es, fr, pt };
|
|
55
|
+
function resolveProcessStateMessages(locale = "en", overrides) {
|
|
56
|
+
const tag = locale.replace(/_/g, "-").toLowerCase();
|
|
57
|
+
return {
|
|
58
|
+
...en,
|
|
59
|
+
...locales[tag] ?? locales[tag.split("-")[0]] ?? {},
|
|
60
|
+
...overrides
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
function ConsoleProgressIndicator({
|
|
64
|
+
controller,
|
|
65
|
+
className,
|
|
66
|
+
style,
|
|
67
|
+
format,
|
|
68
|
+
showCleared = false,
|
|
69
|
+
locale = "en",
|
|
70
|
+
translations
|
|
71
|
+
}) {
|
|
72
|
+
const state = react.useSyncExternalStore(
|
|
73
|
+
controller.subscribe,
|
|
74
|
+
controller.getState,
|
|
75
|
+
controller.getState
|
|
76
|
+
);
|
|
77
|
+
const progress2 = state.progress;
|
|
78
|
+
const labels = resolveProcessStateMessages(locale, translations);
|
|
79
|
+
if (!progress2 || progress2.state === 0 && !showCleared) return null;
|
|
80
|
+
const value = progress2.value ?? 0;
|
|
81
|
+
const label = progress2.state === 0 ? labels.cleared : progress2.state === 3 ? labels.working : progress2.state === 2 ? labels.error : progress2.state === 4 ? labels.paused : labels.progress;
|
|
82
|
+
const description = progress2.state === 0 ? label : progress2.state === 3 ? label : format?.(value, progress2.state) ?? `${label}: ${value}%`;
|
|
83
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
84
|
+
"div",
|
|
85
|
+
{
|
|
86
|
+
className: ["console-progress-indicator", className].filter(Boolean).join(" "),
|
|
87
|
+
"data-state": progress2.state,
|
|
88
|
+
style,
|
|
89
|
+
role: "status",
|
|
90
|
+
"aria-live": "polite",
|
|
91
|
+
"aria-label": description,
|
|
92
|
+
children: [
|
|
93
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "console-progress-indicator__label", children: description }),
|
|
94
|
+
progress2.state !== 0 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
95
|
+
"div",
|
|
96
|
+
{
|
|
97
|
+
className: "console-progress-indicator__track",
|
|
98
|
+
role: "progressbar",
|
|
99
|
+
"aria-label": label,
|
|
100
|
+
"aria-valuemin": 0,
|
|
101
|
+
"aria-valuemax": 100,
|
|
102
|
+
"aria-valuenow": progress2.state === 3 ? void 0 : value,
|
|
103
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
104
|
+
"div",
|
|
105
|
+
{
|
|
106
|
+
className: "console-progress-indicator__fill",
|
|
107
|
+
style: { width: `${progress2.state === 3 ? 30 : value}%` }
|
|
108
|
+
}
|
|
109
|
+
)
|
|
110
|
+
}
|
|
111
|
+
)
|
|
112
|
+
]
|
|
113
|
+
}
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
const CONSOLE_PROCESS_STATE_ADDON_ID = "@moyarich/console-addon-process-state";
|
|
117
|
+
const consoleProcessStateService = consoleCore.createConsoleServiceToken(
|
|
118
|
+
CONSOLE_PROCESS_STATE_ADDON_ID + ".controller"
|
|
119
|
+
);
|
|
120
|
+
function createProcessStateController() {
|
|
121
|
+
let state = { notifications: [] };
|
|
122
|
+
let events = [];
|
|
123
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
124
|
+
const emit = () => {
|
|
125
|
+
for (const listener of listeners) listener();
|
|
126
|
+
};
|
|
127
|
+
return {
|
|
128
|
+
getState: () => state,
|
|
129
|
+
getEvents: () => events,
|
|
130
|
+
subscribe(listener) {
|
|
131
|
+
listeners.add(listener);
|
|
132
|
+
return () => {
|
|
133
|
+
listeners.delete(listener);
|
|
134
|
+
};
|
|
135
|
+
},
|
|
136
|
+
reset() {
|
|
137
|
+
state = { notifications: [] };
|
|
138
|
+
events = [];
|
|
139
|
+
emit();
|
|
140
|
+
},
|
|
141
|
+
apply(event) {
|
|
142
|
+
events = [...events, event];
|
|
143
|
+
switch (event.type) {
|
|
144
|
+
case "progress": {
|
|
145
|
+
const previous = state.progress?.value ?? 0;
|
|
146
|
+
const value = event.state === 0 ? 0 : event.state === 3 ? previous : (event.state === 2 || event.state === 4) && !event.value ? previous : event.value ?? previous;
|
|
147
|
+
state = {
|
|
148
|
+
...state,
|
|
149
|
+
progress: {
|
|
150
|
+
state: event.state,
|
|
151
|
+
value: Math.max(0, Math.min(100, value))
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
break;
|
|
155
|
+
}
|
|
156
|
+
case "cwd":
|
|
157
|
+
state = { ...state, cwd: event.cwd };
|
|
158
|
+
break;
|
|
159
|
+
case "command":
|
|
160
|
+
state = {
|
|
161
|
+
...state,
|
|
162
|
+
command: {
|
|
163
|
+
phase: event.phase,
|
|
164
|
+
...event.exitCode === void 0 ? {} : { exitCode: event.exitCode }
|
|
165
|
+
}
|
|
166
|
+
};
|
|
167
|
+
break;
|
|
168
|
+
case "notification":
|
|
169
|
+
state = {
|
|
170
|
+
...state,
|
|
171
|
+
notifications: [
|
|
172
|
+
...state.notifications,
|
|
173
|
+
{ title: event.title, message: event.message }
|
|
174
|
+
]
|
|
175
|
+
};
|
|
176
|
+
break;
|
|
177
|
+
}
|
|
178
|
+
emit();
|
|
179
|
+
}
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
const sanitize = (value) => Array.from(value).filter((character) => {
|
|
183
|
+
const code = character.charCodeAt(0);
|
|
184
|
+
return code >= 32 && code !== 127 && code !== 155;
|
|
185
|
+
}).join("").slice(0, 1024);
|
|
186
|
+
function interpret(payload) {
|
|
187
|
+
const parts = payload.split(";");
|
|
188
|
+
if (parts[0] === "9" && parts[1] === "4") {
|
|
189
|
+
if (!/^[0-4]$/.test(parts[2] ?? "")) return void 0;
|
|
190
|
+
if (parts.length > 4) return void 0;
|
|
191
|
+
const numeric = parts[3] === void 0 || parts[3] === "" ? void 0 : parts[3];
|
|
192
|
+
if (numeric !== void 0 && !/^\d+$/.test(numeric)) return void 0;
|
|
193
|
+
if (parts[2] === "1" && numeric === void 0) return void 0;
|
|
194
|
+
const value = numeric === void 0 ? void 0 : Math.min(100, Number(numeric));
|
|
195
|
+
return {
|
|
196
|
+
type: "progress",
|
|
197
|
+
state: Number(parts[2]),
|
|
198
|
+
...value === void 0 ? {} : { value }
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
if (parts[0] === "9" && parts[1] === "9") {
|
|
202
|
+
const cwd = sanitize(parts.slice(2).join(";"));
|
|
203
|
+
return cwd ? { type: "cwd", cwd } : void 0;
|
|
204
|
+
}
|
|
205
|
+
if (parts[0] === "133") {
|
|
206
|
+
const phases = {
|
|
207
|
+
A: { type: "command", phase: "prompt" },
|
|
208
|
+
B: { type: "command", phase: "started" },
|
|
209
|
+
C: { type: "command", phase: "executing" }
|
|
210
|
+
};
|
|
211
|
+
if (parts[1] === "D") {
|
|
212
|
+
if (parts.length > 3 || parts[2] !== void 0 && !/^-?\d{1,8}$/.test(parts[2]))
|
|
213
|
+
return void 0;
|
|
214
|
+
return {
|
|
215
|
+
type: "command",
|
|
216
|
+
phase: "finished",
|
|
217
|
+
...parts[2] === void 0 ? {} : { exitCode: Number(parts[2]) }
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
return parts.length === 2 ? phases[parts[1] ?? ""] : void 0;
|
|
221
|
+
}
|
|
222
|
+
if (parts[0] === "777" && parts[1] === "notify") {
|
|
223
|
+
const title = sanitize(parts[2] ?? "");
|
|
224
|
+
const message = sanitize(parts.slice(3).join(";"));
|
|
225
|
+
return title || message ? { type: "notification", title, message } : void 0;
|
|
226
|
+
}
|
|
227
|
+
return void 0;
|
|
228
|
+
}
|
|
229
|
+
function createProcessStateParser(controller) {
|
|
230
|
+
let pending = "";
|
|
231
|
+
return {
|
|
232
|
+
id: CONSOLE_PROCESS_STATE_ADDON_ID,
|
|
233
|
+
reset() {
|
|
234
|
+
pending = "";
|
|
235
|
+
controller.reset();
|
|
236
|
+
},
|
|
237
|
+
parse({ output }) {
|
|
238
|
+
const input = pending + output.data;
|
|
239
|
+
pending = "";
|
|
240
|
+
let visible = "";
|
|
241
|
+
const events = [];
|
|
242
|
+
let pos = 0;
|
|
243
|
+
while (pos < input.length) {
|
|
244
|
+
const begin = input.indexOf("\x1B", pos);
|
|
245
|
+
if (begin < 0) {
|
|
246
|
+
visible += input.slice(pos);
|
|
247
|
+
break;
|
|
248
|
+
}
|
|
249
|
+
visible += input.slice(pos, begin);
|
|
250
|
+
if (begin === input.length - 1) {
|
|
251
|
+
pending = input.slice(begin);
|
|
252
|
+
break;
|
|
253
|
+
}
|
|
254
|
+
if (input[begin + 1] !== "]") {
|
|
255
|
+
visible += "\x1B";
|
|
256
|
+
pos = begin + 1;
|
|
257
|
+
continue;
|
|
258
|
+
}
|
|
259
|
+
let end = begin + 2;
|
|
260
|
+
while (end < input.length && input[end] !== "\x07" && !(input[end] === "\x1B" && input[end + 1] === "\\"))
|
|
261
|
+
end++;
|
|
262
|
+
if (end >= input.length || input[end] === "\x1B" && end + 1 >= input.length) {
|
|
263
|
+
pending = input.slice(begin).slice(0, 8192);
|
|
264
|
+
break;
|
|
265
|
+
}
|
|
266
|
+
const payload = input.slice(begin + 2, end);
|
|
267
|
+
const event = payload.length <= 4096 ? interpret(payload) : void 0;
|
|
268
|
+
if (event) {
|
|
269
|
+
events.push(event);
|
|
270
|
+
controller.apply(event);
|
|
271
|
+
} else {
|
|
272
|
+
visible += input.slice(begin, end + (input[end] === "\x07" ? 1 : 2));
|
|
273
|
+
}
|
|
274
|
+
pos = end + (input[end] === "\x07" ? 1 : 2);
|
|
275
|
+
}
|
|
276
|
+
return {
|
|
277
|
+
data: visible,
|
|
278
|
+
events: events.map((event) => ({
|
|
279
|
+
type: event.type,
|
|
280
|
+
data: { ...event }
|
|
281
|
+
})),
|
|
282
|
+
omit: visible.length === 0
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
function createConsoleProcessStateAddon(options = {}) {
|
|
288
|
+
const isController = "apply" in options;
|
|
289
|
+
const controller = isController ? options : options.controller ?? createProcessStateController();
|
|
290
|
+
const indicator = isController ? false : options.indicator;
|
|
291
|
+
return {
|
|
292
|
+
id: CONSOLE_PROCESS_STATE_ADDON_ID,
|
|
293
|
+
controller,
|
|
294
|
+
activate(host) {
|
|
295
|
+
host.services.provide(consoleProcessStateService, controller);
|
|
296
|
+
host.extensions.register(
|
|
297
|
+
consoleCore.consoleExtensionPoints.processControlParser,
|
|
298
|
+
createProcessStateParser(controller),
|
|
299
|
+
{
|
|
300
|
+
id: CONSOLE_PROCESS_STATE_ADDON_ID + ":parser"
|
|
301
|
+
}
|
|
302
|
+
);
|
|
303
|
+
if (indicator) {
|
|
304
|
+
host.extensions.register(
|
|
305
|
+
consoleCore.consoleExtensionPoints.panelElement,
|
|
306
|
+
{
|
|
307
|
+
id: CONSOLE_PROCESS_STATE_ADDON_ID + ":indicator",
|
|
308
|
+
placement: "before-output",
|
|
309
|
+
render: () => react.createElement(ConsoleProgressIndicator, {
|
|
310
|
+
controller,
|
|
311
|
+
...typeof indicator === "object" ? indicator : {}
|
|
312
|
+
})
|
|
313
|
+
},
|
|
314
|
+
{ id: CONSOLE_PROCESS_STATE_ADDON_ID + ":indicator" }
|
|
315
|
+
);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
};
|
|
319
|
+
}
|
|
320
|
+
exports.CONSOLE_PROCESS_STATE_ADDON_ID = CONSOLE_PROCESS_STATE_ADDON_ID;
|
|
321
|
+
exports.ConsoleProgressIndicator = ConsoleProgressIndicator;
|
|
322
|
+
exports.consoleProcessStateService = consoleProcessStateService;
|
|
323
|
+
exports.createConsoleProcessStateAddon = createConsoleProcessStateAddon;
|
|
324
|
+
exports.createProcessStateController = createProcessStateController;
|
|
325
|
+
exports.createProcessStateParser = createProcessStateParser;
|
|
326
|
+
exports.resolveProcessStateMessages = resolveProcessStateMessages;
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { type ConsoleProgressIndicatorOptions } from "./ProgressIndicator.cjs";
|
|
2
|
+
export { ConsoleProgressIndicator } from "./ProgressIndicator.cjs";
|
|
3
|
+
export { resolveProcessStateMessages } from "./localization.cjs";
|
|
4
|
+
export type { ProcessStateTranslations } from "./localization.cjs";
|
|
5
|
+
export type { ConsoleProgressIndicatorOptions } from "./ProgressIndicator.cjs";
|
|
6
|
+
import { type ConsoleAddon, type ConsoleProcessControlParser } from "@moyarich/console-core";
|
|
7
|
+
export declare const CONSOLE_PROCESS_STATE_ADDON_ID = "@moyarich/console-addon-process-state";
|
|
8
|
+
export interface ProcessState {
|
|
9
|
+
readonly progress?: {
|
|
10
|
+
readonly state: number;
|
|
11
|
+
readonly value?: number;
|
|
12
|
+
};
|
|
13
|
+
readonly cwd?: string;
|
|
14
|
+
readonly command?: {
|
|
15
|
+
readonly phase: "prompt" | "started" | "executing" | "finished";
|
|
16
|
+
readonly exitCode?: number;
|
|
17
|
+
};
|
|
18
|
+
readonly notifications: readonly {
|
|
19
|
+
readonly title: string;
|
|
20
|
+
readonly message: string;
|
|
21
|
+
}[];
|
|
22
|
+
}
|
|
23
|
+
export type ProcessStateEvent = {
|
|
24
|
+
readonly type: "progress";
|
|
25
|
+
readonly state: number;
|
|
26
|
+
readonly value?: number;
|
|
27
|
+
} | {
|
|
28
|
+
readonly type: "cwd";
|
|
29
|
+
readonly cwd: string;
|
|
30
|
+
} | {
|
|
31
|
+
readonly type: "command";
|
|
32
|
+
readonly phase: "prompt" | "started" | "executing" | "finished";
|
|
33
|
+
readonly exitCode?: number;
|
|
34
|
+
} | {
|
|
35
|
+
readonly type: "notification";
|
|
36
|
+
readonly title: string;
|
|
37
|
+
readonly message: string;
|
|
38
|
+
};
|
|
39
|
+
export interface ProcessStateController {
|
|
40
|
+
getState(): ProcessState;
|
|
41
|
+
getEvents(): readonly ProcessStateEvent[];
|
|
42
|
+
subscribe(listener: () => void): () => void;
|
|
43
|
+
reset(): void;
|
|
44
|
+
apply(event: ProcessStateEvent): void;
|
|
45
|
+
}
|
|
46
|
+
export declare const consoleProcessStateService: import("@moyarich/console-core").ConsoleServiceToken<ProcessStateController>;
|
|
47
|
+
export declare function createProcessStateController(): ProcessStateController;
|
|
48
|
+
/** Stateful OSC decoder; parsed sequences are removed while printable text is preserved. */
|
|
49
|
+
export declare function createProcessStateParser(controller: ProcessStateController): ConsoleProcessControlParser;
|
|
50
|
+
export interface ProcessStateAddon extends ConsoleAddon {
|
|
51
|
+
readonly controller: ProcessStateController;
|
|
52
|
+
}
|
|
53
|
+
export interface ProcessStateAddonOptions {
|
|
54
|
+
controller?: ProcessStateController;
|
|
55
|
+
/** Set to true or provide options to display a compact status strip. Default: headless. */
|
|
56
|
+
indicator?: boolean | ConsoleProgressIndicatorOptions;
|
|
57
|
+
}
|
|
58
|
+
export declare function createConsoleProcessStateAddon(options?: ProcessStateController | ProcessStateAddonOptions): ProcessStateAddon;
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { type ConsoleProgressIndicatorOptions } from "./ProgressIndicator.js";
|
|
2
|
+
export { ConsoleProgressIndicator } from "./ProgressIndicator.js";
|
|
3
|
+
export { resolveProcessStateMessages } from "./localization.js";
|
|
4
|
+
export type { ProcessStateTranslations } from "./localization.js";
|
|
5
|
+
export type { ConsoleProgressIndicatorOptions } from "./ProgressIndicator.js";
|
|
6
|
+
import { type ConsoleAddon, type ConsoleProcessControlParser } from "@moyarich/console-core";
|
|
7
|
+
export declare const CONSOLE_PROCESS_STATE_ADDON_ID = "@moyarich/console-addon-process-state";
|
|
8
|
+
export interface ProcessState {
|
|
9
|
+
readonly progress?: {
|
|
10
|
+
readonly state: number;
|
|
11
|
+
readonly value?: number;
|
|
12
|
+
};
|
|
13
|
+
readonly cwd?: string;
|
|
14
|
+
readonly command?: {
|
|
15
|
+
readonly phase: "prompt" | "started" | "executing" | "finished";
|
|
16
|
+
readonly exitCode?: number;
|
|
17
|
+
};
|
|
18
|
+
readonly notifications: readonly {
|
|
19
|
+
readonly title: string;
|
|
20
|
+
readonly message: string;
|
|
21
|
+
}[];
|
|
22
|
+
}
|
|
23
|
+
export type ProcessStateEvent = {
|
|
24
|
+
readonly type: "progress";
|
|
25
|
+
readonly state: number;
|
|
26
|
+
readonly value?: number;
|
|
27
|
+
} | {
|
|
28
|
+
readonly type: "cwd";
|
|
29
|
+
readonly cwd: string;
|
|
30
|
+
} | {
|
|
31
|
+
readonly type: "command";
|
|
32
|
+
readonly phase: "prompt" | "started" | "executing" | "finished";
|
|
33
|
+
readonly exitCode?: number;
|
|
34
|
+
} | {
|
|
35
|
+
readonly type: "notification";
|
|
36
|
+
readonly title: string;
|
|
37
|
+
readonly message: string;
|
|
38
|
+
};
|
|
39
|
+
export interface ProcessStateController {
|
|
40
|
+
getState(): ProcessState;
|
|
41
|
+
getEvents(): readonly ProcessStateEvent[];
|
|
42
|
+
subscribe(listener: () => void): () => void;
|
|
43
|
+
reset(): void;
|
|
44
|
+
apply(event: ProcessStateEvent): void;
|
|
45
|
+
}
|
|
46
|
+
export declare const consoleProcessStateService: import("@moyarich/console-core").ConsoleServiceToken<ProcessStateController>;
|
|
47
|
+
export declare function createProcessStateController(): ProcessStateController;
|
|
48
|
+
/** Stateful OSC decoder; parsed sequences are removed while printable text is preserved. */
|
|
49
|
+
export declare function createProcessStateParser(controller: ProcessStateController): ConsoleProcessControlParser;
|
|
50
|
+
export interface ProcessStateAddon extends ConsoleAddon {
|
|
51
|
+
readonly controller: ProcessStateController;
|
|
52
|
+
}
|
|
53
|
+
export interface ProcessStateAddonOptions {
|
|
54
|
+
controller?: ProcessStateController;
|
|
55
|
+
/** Set to true or provide options to display a compact status strip. Default: headless. */
|
|
56
|
+
indicator?: boolean | ConsoleProgressIndicatorOptions;
|
|
57
|
+
}
|
|
58
|
+
export declare function createConsoleProcessStateAddon(options?: ProcessStateController | ProcessStateAddonOptions): ProcessStateAddon;
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
import { useSyncExternalStore, createElement } from "react";
|
|
2
|
+
import { jsxs, jsx } from "react/jsx-runtime";
|
|
3
|
+
import { createConsoleServiceToken, consoleExtensionPoints } from "@moyarich/console-core";
|
|
4
|
+
const cleared$3 = "Progress cleared";
|
|
5
|
+
const working$3 = "Working";
|
|
6
|
+
const error$3 = "Process error";
|
|
7
|
+
const paused$3 = "Paused";
|
|
8
|
+
const progress$3 = "In progress";
|
|
9
|
+
const en = {
|
|
10
|
+
cleared: cleared$3,
|
|
11
|
+
working: working$3,
|
|
12
|
+
error: error$3,
|
|
13
|
+
paused: paused$3,
|
|
14
|
+
progress: progress$3
|
|
15
|
+
};
|
|
16
|
+
const cleared$2 = "Progreso borrado";
|
|
17
|
+
const working$2 = "Trabajando";
|
|
18
|
+
const error$2 = "Error del proceso";
|
|
19
|
+
const paused$2 = "En pausa";
|
|
20
|
+
const progress$2 = "En curso";
|
|
21
|
+
const es = {
|
|
22
|
+
cleared: cleared$2,
|
|
23
|
+
working: working$2,
|
|
24
|
+
error: error$2,
|
|
25
|
+
paused: paused$2,
|
|
26
|
+
progress: progress$2
|
|
27
|
+
};
|
|
28
|
+
const cleared$1 = "Progression effacée";
|
|
29
|
+
const working$1 = "En cours";
|
|
30
|
+
const error$1 = "Erreur du processus";
|
|
31
|
+
const paused$1 = "En pause";
|
|
32
|
+
const progress$1 = "En progression";
|
|
33
|
+
const fr = {
|
|
34
|
+
cleared: cleared$1,
|
|
35
|
+
working: working$1,
|
|
36
|
+
error: error$1,
|
|
37
|
+
paused: paused$1,
|
|
38
|
+
progress: progress$1
|
|
39
|
+
};
|
|
40
|
+
const cleared = "Progresso limpo";
|
|
41
|
+
const working = "Trabalhando";
|
|
42
|
+
const error = "Erro do processo";
|
|
43
|
+
const paused = "Pausado";
|
|
44
|
+
const progress = "Em andamento";
|
|
45
|
+
const pt = {
|
|
46
|
+
cleared,
|
|
47
|
+
working,
|
|
48
|
+
error,
|
|
49
|
+
paused,
|
|
50
|
+
progress
|
|
51
|
+
};
|
|
52
|
+
const locales = { en, es, fr, pt };
|
|
53
|
+
function resolveProcessStateMessages(locale = "en", overrides) {
|
|
54
|
+
const tag = locale.replace(/_/g, "-").toLowerCase();
|
|
55
|
+
return {
|
|
56
|
+
...en,
|
|
57
|
+
...locales[tag] ?? locales[tag.split("-")[0]] ?? {},
|
|
58
|
+
...overrides
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
function ConsoleProgressIndicator({
|
|
62
|
+
controller,
|
|
63
|
+
className,
|
|
64
|
+
style,
|
|
65
|
+
format,
|
|
66
|
+
showCleared = false,
|
|
67
|
+
locale = "en",
|
|
68
|
+
translations
|
|
69
|
+
}) {
|
|
70
|
+
const state = useSyncExternalStore(
|
|
71
|
+
controller.subscribe,
|
|
72
|
+
controller.getState,
|
|
73
|
+
controller.getState
|
|
74
|
+
);
|
|
75
|
+
const progress2 = state.progress;
|
|
76
|
+
const labels = resolveProcessStateMessages(locale, translations);
|
|
77
|
+
if (!progress2 || progress2.state === 0 && !showCleared) return null;
|
|
78
|
+
const value = progress2.value ?? 0;
|
|
79
|
+
const label = progress2.state === 0 ? labels.cleared : progress2.state === 3 ? labels.working : progress2.state === 2 ? labels.error : progress2.state === 4 ? labels.paused : labels.progress;
|
|
80
|
+
const description = progress2.state === 0 ? label : progress2.state === 3 ? label : format?.(value, progress2.state) ?? `${label}: ${value}%`;
|
|
81
|
+
return /* @__PURE__ */ jsxs(
|
|
82
|
+
"div",
|
|
83
|
+
{
|
|
84
|
+
className: ["console-progress-indicator", className].filter(Boolean).join(" "),
|
|
85
|
+
"data-state": progress2.state,
|
|
86
|
+
style,
|
|
87
|
+
role: "status",
|
|
88
|
+
"aria-live": "polite",
|
|
89
|
+
"aria-label": description,
|
|
90
|
+
children: [
|
|
91
|
+
/* @__PURE__ */ jsx("span", { className: "console-progress-indicator__label", children: description }),
|
|
92
|
+
progress2.state !== 0 && /* @__PURE__ */ jsx(
|
|
93
|
+
"div",
|
|
94
|
+
{
|
|
95
|
+
className: "console-progress-indicator__track",
|
|
96
|
+
role: "progressbar",
|
|
97
|
+
"aria-label": label,
|
|
98
|
+
"aria-valuemin": 0,
|
|
99
|
+
"aria-valuemax": 100,
|
|
100
|
+
"aria-valuenow": progress2.state === 3 ? void 0 : value,
|
|
101
|
+
children: /* @__PURE__ */ jsx(
|
|
102
|
+
"div",
|
|
103
|
+
{
|
|
104
|
+
className: "console-progress-indicator__fill",
|
|
105
|
+
style: { width: `${progress2.state === 3 ? 30 : value}%` }
|
|
106
|
+
}
|
|
107
|
+
)
|
|
108
|
+
}
|
|
109
|
+
)
|
|
110
|
+
]
|
|
111
|
+
}
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
const CONSOLE_PROCESS_STATE_ADDON_ID = "@moyarich/console-addon-process-state";
|
|
115
|
+
const consoleProcessStateService = createConsoleServiceToken(
|
|
116
|
+
CONSOLE_PROCESS_STATE_ADDON_ID + ".controller"
|
|
117
|
+
);
|
|
118
|
+
function createProcessStateController() {
|
|
119
|
+
let state = { notifications: [] };
|
|
120
|
+
let events = [];
|
|
121
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
122
|
+
const emit = () => {
|
|
123
|
+
for (const listener of listeners) listener();
|
|
124
|
+
};
|
|
125
|
+
return {
|
|
126
|
+
getState: () => state,
|
|
127
|
+
getEvents: () => events,
|
|
128
|
+
subscribe(listener) {
|
|
129
|
+
listeners.add(listener);
|
|
130
|
+
return () => {
|
|
131
|
+
listeners.delete(listener);
|
|
132
|
+
};
|
|
133
|
+
},
|
|
134
|
+
reset() {
|
|
135
|
+
state = { notifications: [] };
|
|
136
|
+
events = [];
|
|
137
|
+
emit();
|
|
138
|
+
},
|
|
139
|
+
apply(event) {
|
|
140
|
+
events = [...events, event];
|
|
141
|
+
switch (event.type) {
|
|
142
|
+
case "progress": {
|
|
143
|
+
const previous = state.progress?.value ?? 0;
|
|
144
|
+
const value = event.state === 0 ? 0 : event.state === 3 ? previous : (event.state === 2 || event.state === 4) && !event.value ? previous : event.value ?? previous;
|
|
145
|
+
state = {
|
|
146
|
+
...state,
|
|
147
|
+
progress: {
|
|
148
|
+
state: event.state,
|
|
149
|
+
value: Math.max(0, Math.min(100, value))
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
break;
|
|
153
|
+
}
|
|
154
|
+
case "cwd":
|
|
155
|
+
state = { ...state, cwd: event.cwd };
|
|
156
|
+
break;
|
|
157
|
+
case "command":
|
|
158
|
+
state = {
|
|
159
|
+
...state,
|
|
160
|
+
command: {
|
|
161
|
+
phase: event.phase,
|
|
162
|
+
...event.exitCode === void 0 ? {} : { exitCode: event.exitCode }
|
|
163
|
+
}
|
|
164
|
+
};
|
|
165
|
+
break;
|
|
166
|
+
case "notification":
|
|
167
|
+
state = {
|
|
168
|
+
...state,
|
|
169
|
+
notifications: [
|
|
170
|
+
...state.notifications,
|
|
171
|
+
{ title: event.title, message: event.message }
|
|
172
|
+
]
|
|
173
|
+
};
|
|
174
|
+
break;
|
|
175
|
+
}
|
|
176
|
+
emit();
|
|
177
|
+
}
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
const sanitize = (value) => Array.from(value).filter((character) => {
|
|
181
|
+
const code = character.charCodeAt(0);
|
|
182
|
+
return code >= 32 && code !== 127 && code !== 155;
|
|
183
|
+
}).join("").slice(0, 1024);
|
|
184
|
+
function interpret(payload) {
|
|
185
|
+
const parts = payload.split(";");
|
|
186
|
+
if (parts[0] === "9" && parts[1] === "4") {
|
|
187
|
+
if (!/^[0-4]$/.test(parts[2] ?? "")) return void 0;
|
|
188
|
+
if (parts.length > 4) return void 0;
|
|
189
|
+
const numeric = parts[3] === void 0 || parts[3] === "" ? void 0 : parts[3];
|
|
190
|
+
if (numeric !== void 0 && !/^\d+$/.test(numeric)) return void 0;
|
|
191
|
+
if (parts[2] === "1" && numeric === void 0) return void 0;
|
|
192
|
+
const value = numeric === void 0 ? void 0 : Math.min(100, Number(numeric));
|
|
193
|
+
return {
|
|
194
|
+
type: "progress",
|
|
195
|
+
state: Number(parts[2]),
|
|
196
|
+
...value === void 0 ? {} : { value }
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
if (parts[0] === "9" && parts[1] === "9") {
|
|
200
|
+
const cwd = sanitize(parts.slice(2).join(";"));
|
|
201
|
+
return cwd ? { type: "cwd", cwd } : void 0;
|
|
202
|
+
}
|
|
203
|
+
if (parts[0] === "133") {
|
|
204
|
+
const phases = {
|
|
205
|
+
A: { type: "command", phase: "prompt" },
|
|
206
|
+
B: { type: "command", phase: "started" },
|
|
207
|
+
C: { type: "command", phase: "executing" }
|
|
208
|
+
};
|
|
209
|
+
if (parts[1] === "D") {
|
|
210
|
+
if (parts.length > 3 || parts[2] !== void 0 && !/^-?\d{1,8}$/.test(parts[2]))
|
|
211
|
+
return void 0;
|
|
212
|
+
return {
|
|
213
|
+
type: "command",
|
|
214
|
+
phase: "finished",
|
|
215
|
+
...parts[2] === void 0 ? {} : { exitCode: Number(parts[2]) }
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
return parts.length === 2 ? phases[parts[1] ?? ""] : void 0;
|
|
219
|
+
}
|
|
220
|
+
if (parts[0] === "777" && parts[1] === "notify") {
|
|
221
|
+
const title = sanitize(parts[2] ?? "");
|
|
222
|
+
const message = sanitize(parts.slice(3).join(";"));
|
|
223
|
+
return title || message ? { type: "notification", title, message } : void 0;
|
|
224
|
+
}
|
|
225
|
+
return void 0;
|
|
226
|
+
}
|
|
227
|
+
function createProcessStateParser(controller) {
|
|
228
|
+
let pending = "";
|
|
229
|
+
return {
|
|
230
|
+
id: CONSOLE_PROCESS_STATE_ADDON_ID,
|
|
231
|
+
reset() {
|
|
232
|
+
pending = "";
|
|
233
|
+
controller.reset();
|
|
234
|
+
},
|
|
235
|
+
parse({ output }) {
|
|
236
|
+
const input = pending + output.data;
|
|
237
|
+
pending = "";
|
|
238
|
+
let visible = "";
|
|
239
|
+
const events = [];
|
|
240
|
+
let pos = 0;
|
|
241
|
+
while (pos < input.length) {
|
|
242
|
+
const begin = input.indexOf("\x1B", pos);
|
|
243
|
+
if (begin < 0) {
|
|
244
|
+
visible += input.slice(pos);
|
|
245
|
+
break;
|
|
246
|
+
}
|
|
247
|
+
visible += input.slice(pos, begin);
|
|
248
|
+
if (begin === input.length - 1) {
|
|
249
|
+
pending = input.slice(begin);
|
|
250
|
+
break;
|
|
251
|
+
}
|
|
252
|
+
if (input[begin + 1] !== "]") {
|
|
253
|
+
visible += "\x1B";
|
|
254
|
+
pos = begin + 1;
|
|
255
|
+
continue;
|
|
256
|
+
}
|
|
257
|
+
let end = begin + 2;
|
|
258
|
+
while (end < input.length && input[end] !== "\x07" && !(input[end] === "\x1B" && input[end + 1] === "\\"))
|
|
259
|
+
end++;
|
|
260
|
+
if (end >= input.length || input[end] === "\x1B" && end + 1 >= input.length) {
|
|
261
|
+
pending = input.slice(begin).slice(0, 8192);
|
|
262
|
+
break;
|
|
263
|
+
}
|
|
264
|
+
const payload = input.slice(begin + 2, end);
|
|
265
|
+
const event = payload.length <= 4096 ? interpret(payload) : void 0;
|
|
266
|
+
if (event) {
|
|
267
|
+
events.push(event);
|
|
268
|
+
controller.apply(event);
|
|
269
|
+
} else {
|
|
270
|
+
visible += input.slice(begin, end + (input[end] === "\x07" ? 1 : 2));
|
|
271
|
+
}
|
|
272
|
+
pos = end + (input[end] === "\x07" ? 1 : 2);
|
|
273
|
+
}
|
|
274
|
+
return {
|
|
275
|
+
data: visible,
|
|
276
|
+
events: events.map((event) => ({
|
|
277
|
+
type: event.type,
|
|
278
|
+
data: { ...event }
|
|
279
|
+
})),
|
|
280
|
+
omit: visible.length === 0
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
function createConsoleProcessStateAddon(options = {}) {
|
|
286
|
+
const isController = "apply" in options;
|
|
287
|
+
const controller = isController ? options : options.controller ?? createProcessStateController();
|
|
288
|
+
const indicator = isController ? false : options.indicator;
|
|
289
|
+
return {
|
|
290
|
+
id: CONSOLE_PROCESS_STATE_ADDON_ID,
|
|
291
|
+
controller,
|
|
292
|
+
activate(host) {
|
|
293
|
+
host.services.provide(consoleProcessStateService, controller);
|
|
294
|
+
host.extensions.register(
|
|
295
|
+
consoleExtensionPoints.processControlParser,
|
|
296
|
+
createProcessStateParser(controller),
|
|
297
|
+
{
|
|
298
|
+
id: CONSOLE_PROCESS_STATE_ADDON_ID + ":parser"
|
|
299
|
+
}
|
|
300
|
+
);
|
|
301
|
+
if (indicator) {
|
|
302
|
+
host.extensions.register(
|
|
303
|
+
consoleExtensionPoints.panelElement,
|
|
304
|
+
{
|
|
305
|
+
id: CONSOLE_PROCESS_STATE_ADDON_ID + ":indicator",
|
|
306
|
+
placement: "before-output",
|
|
307
|
+
render: () => createElement(ConsoleProgressIndicator, {
|
|
308
|
+
controller,
|
|
309
|
+
...typeof indicator === "object" ? indicator : {}
|
|
310
|
+
})
|
|
311
|
+
},
|
|
312
|
+
{ id: CONSOLE_PROCESS_STATE_ADDON_ID + ":indicator" }
|
|
313
|
+
);
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
export {
|
|
319
|
+
CONSOLE_PROCESS_STATE_ADDON_ID,
|
|
320
|
+
ConsoleProgressIndicator,
|
|
321
|
+
consoleProcessStateService,
|
|
322
|
+
createConsoleProcessStateAddon,
|
|
323
|
+
createProcessStateController,
|
|
324
|
+
createProcessStateParser,
|
|
325
|
+
resolveProcessStateMessages
|
|
326
|
+
};
|
package/dist/styles.css
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/* src/ProgressIndicator.css */
|
|
2
|
+
.console-progress-indicator {
|
|
3
|
+
--_progress-fg: var(
|
|
4
|
+
--console-progress-color,
|
|
5
|
+
var(--console-color-accent, currentColor)
|
|
6
|
+
);
|
|
7
|
+
--_progress-track: var(
|
|
8
|
+
--console-progress-track,
|
|
9
|
+
color-mix(in srgb, currentColor 12%, transparent)
|
|
10
|
+
);
|
|
11
|
+
--_progress-text: var(--console-progress-text, inherit);
|
|
12
|
+
/* This overlay has no layout height: updates cannot resize or scroll the terminal. */
|
|
13
|
+
position: sticky;
|
|
14
|
+
top: 0;
|
|
15
|
+
z-index: 2;
|
|
16
|
+
display: flex;
|
|
17
|
+
justify-content: flex-end;
|
|
18
|
+
align-items: center;
|
|
19
|
+
gap: var(--console-progress-gap, 0.75rem);
|
|
20
|
+
box-sizing: border-box;
|
|
21
|
+
height: 0;
|
|
22
|
+
min-height: 0;
|
|
23
|
+
padding: 0 var(--console-progress-inline-padding, 0.75rem);
|
|
24
|
+
pointer-events: none;
|
|
25
|
+
color: var(--_progress-text);
|
|
26
|
+
font: inherit;
|
|
27
|
+
transform: translateY(var(--console-progress-offset, 0.25rem));
|
|
28
|
+
}
|
|
29
|
+
.console-progress-indicator__label {
|
|
30
|
+
flex: none;
|
|
31
|
+
font-size: 0.8em;
|
|
32
|
+
}
|
|
33
|
+
.console-progress-indicator__track {
|
|
34
|
+
flex: 1;
|
|
35
|
+
height: 0.35rem;
|
|
36
|
+
border-radius: 999px;
|
|
37
|
+
background: var(--_progress-track);
|
|
38
|
+
overflow: hidden;
|
|
39
|
+
}
|
|
40
|
+
.console-progress-indicator__fill {
|
|
41
|
+
height: 100%;
|
|
42
|
+
background: var(--_progress-fg);
|
|
43
|
+
transition: width 120ms linear;
|
|
44
|
+
}
|
|
45
|
+
.console-progress-indicator[data-state="2"] .console-progress-indicator__fill {
|
|
46
|
+
background: var(--console-progress-error, #b42318);
|
|
47
|
+
}
|
|
48
|
+
.console-progress-indicator[data-state="4"] .console-progress-indicator__fill {
|
|
49
|
+
background: var(--console-progress-paused, #a46b00);
|
|
50
|
+
}
|
|
51
|
+
.console-progress-indicator[data-state="3"] .console-progress-indicator__fill {
|
|
52
|
+
animation: console-progress-motion 1.5s ease-in-out infinite alternate;
|
|
53
|
+
}
|
|
54
|
+
@keyframes console-progress-motion {
|
|
55
|
+
from {
|
|
56
|
+
transform: translateX(0);
|
|
57
|
+
}
|
|
58
|
+
to {
|
|
59
|
+
transform: translateX(230%);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
@media (prefers-reduced-motion: reduce) {
|
|
63
|
+
.console-progress-indicator__fill {
|
|
64
|
+
transition: none;
|
|
65
|
+
animation: none !important;
|
|
66
|
+
}
|
|
67
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,72 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@moyarich/console-addon-process-state",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Observable process state from OSC terminal control sequences",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "./dist/index.cjs",
|
|
8
|
+
"module": "./dist/index.js",
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"import": {
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"default": "./dist/index.js"
|
|
15
|
+
},
|
|
16
|
+
"require": {
|
|
17
|
+
"types": "./dist/index.d.cts",
|
|
18
|
+
"default": "./dist/index.cjs"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"./styles.css": "./dist/styles.css"
|
|
22
|
+
},
|
|
23
|
+
"files": [
|
|
24
|
+
"dist"
|
|
25
|
+
],
|
|
26
|
+
"publishConfig": {
|
|
27
|
+
"registry": "https://npm.pkg.github.com"
|
|
28
|
+
},
|
|
29
|
+
"scripts": {
|
|
30
|
+
"build": "vite build && tsc -p tsconfig.build.json && node ../../../scripts/prepare-cjs-types.mjs && node ../../../scripts/prepare-addon-styles.mjs",
|
|
31
|
+
"typecheck": "tsc --noEmit"
|
|
32
|
+
},
|
|
33
|
+
"peerDependencies": {
|
|
34
|
+
"@moyarich/console-core": "^0.2.0",
|
|
35
|
+
"react": ">=18"
|
|
36
|
+
},
|
|
37
|
+
"devDependencies": {
|
|
38
|
+
"@moyarich/console-core": "0.2.0",
|
|
39
|
+
"typescript": "^5.9.2",
|
|
40
|
+
"vite": "^7.1.5",
|
|
41
|
+
"react": "^19.2.7",
|
|
42
|
+
"@types/react": "^19.1.12"
|
|
43
|
+
},
|
|
44
|
+
"repository": {
|
|
45
|
+
"type": "git",
|
|
46
|
+
"url": "git+https://github.com/moyarich/console.git",
|
|
47
|
+
"directory": "packages/addons/process-state"
|
|
48
|
+
},
|
|
49
|
+
"bugs": {
|
|
50
|
+
"url": "https://github.com/moyarich/console/issues"
|
|
51
|
+
},
|
|
52
|
+
"homepage": "https://github.com/moyarich/console#readme",
|
|
53
|
+
"keywords": [
|
|
54
|
+
"console",
|
|
55
|
+
"addon",
|
|
56
|
+
"osc",
|
|
57
|
+
"terminal",
|
|
58
|
+
"process-state"
|
|
59
|
+
],
|
|
60
|
+
"sideEffects": [
|
|
61
|
+
"./src/ProgressIndicator.css",
|
|
62
|
+
"./dist/index.js",
|
|
63
|
+
"./dist/index.cjs",
|
|
64
|
+
"./dist/styles.css"
|
|
65
|
+
],
|
|
66
|
+
"publisher": "moyarich",
|
|
67
|
+
"author": "Moya Richards",
|
|
68
|
+
"engines": {
|
|
69
|
+
"node": ">=24"
|
|
70
|
+
},
|
|
71
|
+
"private": false
|
|
72
|
+
}
|