@cplieger/web-terminal-ui 7.0.1 → 7.0.2
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/package.json +2 -2
- package/src/features/tabs/index.ts +24 -9
- package/src/kernel/kernel.ts +9 -5
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cplieger/web-terminal-ui",
|
|
3
|
-
"version": "7.0.
|
|
3
|
+
"version": "7.0.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Reference touch-first browser UI for @cplieger/web-terminal-engine: a composable kernel + feature modules (tabs, activity monitor, mobile toolbar, context menu, IME, predictive echo, viewport handling) and CSS. One createTerminal() call.",
|
|
6
6
|
"license": "MPL-2.0",
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
"@vitest/coverage-v8": "4.1.11",
|
|
56
56
|
"eslint": "10.8.1",
|
|
57
57
|
"fast-check": "4.9.0",
|
|
58
|
-
"happy-dom": "20.11.
|
|
58
|
+
"happy-dom": "20.11.6",
|
|
59
59
|
"html-validate": "11.8.0",
|
|
60
60
|
"knip": "6.32.2",
|
|
61
61
|
"prettier": "3.9.6",
|
|
@@ -2873,13 +2873,20 @@ export function tabs(opts: TabsOptions = {}): TerminalFeature<TabsApi> {
|
|
|
2873
2873
|
// still be), to the terminal otherwise. Recorded at entry because the exit
|
|
2874
2874
|
// paths cannot tell them apart.
|
|
2875
2875
|
let editFrom: "keyboard" | "pointer" = "pointer";
|
|
2876
|
-
// Tab ids with
|
|
2877
|
-
// record carrying a DIFFERENT value is applied for display
|
|
2878
|
-
// supersede the request: SSE delivery order and REST mutation
|
|
2879
|
-
// one total order, so a record sampled BEFORE our PUT can
|
|
2880
|
-
// and treating it as newer authority would suppress the
|
|
2881
|
-
// rollback and its failure toast.
|
|
2882
|
-
|
|
2876
|
+
// Tab ids with pinned-name requests in flight, COUNTED per id. While a count
|
|
2877
|
+
// is held, a status record carrying a DIFFERENT value is applied for display
|
|
2878
|
+
// but does not supersede the request: SSE delivery order and REST mutation
|
|
2879
|
+
// order are not one total order, so a record sampled BEFORE our PUT can
|
|
2880
|
+
// arrive after it, and treating it as newer authority would suppress the
|
|
2881
|
+
// request's own rollback and its failure toast.
|
|
2882
|
+
// Counted rather than a Set of ids, because two renames of one tab can be out
|
|
2883
|
+
// at once and the invariant is "no request of OURS is in flight", not "no id
|
|
2884
|
+
// is marked": a bare Set let the first request's completion clear the marker
|
|
2885
|
+
// while the second's PUT was still open, and the second rename then failed
|
|
2886
|
+
// silently. A per-request token would carry more information, but the only
|
|
2887
|
+
// reader asks whether ANY request is out for this id, and the failure handler
|
|
2888
|
+
// already distinguishes its own supersession by (born, nameSeq).
|
|
2889
|
+
const namesInFlight = new Map<string, number>();
|
|
2883
2890
|
|
|
2884
2891
|
/** restoreFocusAfterEdit sends focus where the entry path implies. The
|
|
2885
2892
|
* terminal branch is gated exactly like switchTo's focus-on-switch: on a
|
|
@@ -2949,8 +2956,11 @@ export function tabs(opts: TabsOptions = {}): TerminalFeature<TabsApi> {
|
|
|
2949
2956
|
const { text, fallback } = baseLabel(t);
|
|
2950
2957
|
ctx.announce(fallback ? "Custom name removed" : `Using automatic name: ${text}`);
|
|
2951
2958
|
}
|
|
2952
|
-
namesInFlight.add(id);
|
|
2953
2959
|
const request = name === "" ? api.clearPinnedTitle(id) : api.setPinnedTitle(id, name);
|
|
2960
|
+
// Counted only once the request exists: an api implementation that throws
|
|
2961
|
+
// instead of rejecting would otherwise leave a count behind that no
|
|
2962
|
+
// .finally ever releases, and the id would read as in flight forever.
|
|
2963
|
+
namesInFlight.set(id, (namesInFlight.get(id) ?? 0) + 1);
|
|
2954
2964
|
void request
|
|
2955
2965
|
.catch(() => {
|
|
2956
2966
|
const cur = tabList.find((x) => x.id === id);
|
|
@@ -2962,7 +2972,12 @@ export function tabs(opts: TabsOptions = {}): TerminalFeature<TabsApi> {
|
|
|
2962
2972
|
ctx.toast("Couldn't save the terminal name");
|
|
2963
2973
|
})
|
|
2964
2974
|
.finally(() => {
|
|
2965
|
-
namesInFlight.
|
|
2975
|
+
const left = (namesInFlight.get(id) ?? 0) - 1;
|
|
2976
|
+
if (left > 0) {
|
|
2977
|
+
namesInFlight.set(id, left);
|
|
2978
|
+
} else {
|
|
2979
|
+
namesInFlight.delete(id);
|
|
2980
|
+
}
|
|
2966
2981
|
});
|
|
2967
2982
|
return true;
|
|
2968
2983
|
}
|
package/src/kernel/kernel.ts
CHANGED
|
@@ -274,17 +274,21 @@ function buildTerminal(
|
|
|
274
274
|
// Narrow = compact in EITHER dimension: skinny (a phone in portrait, a
|
|
275
275
|
// narrow embedded panel) or short (a phone in landscape). The one
|
|
276
276
|
// ResizeObserver below fires on both width and height changes.
|
|
277
|
+
//
|
|
278
|
+
// Constructed unconditionally: ResizeObserver is a hard requirement of this
|
|
279
|
+
// library, not an enhancement. viewport.init() and the tabs strip both
|
|
280
|
+
// construct one with no guard, and the same buildTerminal builds a WeakRef
|
|
281
|
+
// (whose browser floor is strictly higher), so a `typeof ResizeObserver ===
|
|
282
|
+
// "function"` guard here could only ever protect a browser that crashes
|
|
283
|
+
// moments later. It used to be here, and it was measured dead.
|
|
277
284
|
const isNarrow = (): boolean =>
|
|
278
285
|
root.clientWidth <= NARROW_MAX_PX || root.clientHeight <= SHORT_MAX_PX;
|
|
279
286
|
function updateNarrow(): void {
|
|
280
287
|
root.classList.toggle("wt-narrow", isNarrow());
|
|
281
288
|
}
|
|
282
289
|
updateNarrow();
|
|
283
|
-
let narrowObserver: ResizeObserver | null =
|
|
284
|
-
|
|
285
|
-
narrowObserver = new ResizeObserver(updateNarrow);
|
|
286
|
-
narrowObserver.observe(root);
|
|
287
|
-
}
|
|
290
|
+
let narrowObserver: ResizeObserver | null = new ResizeObserver(updateNarrow);
|
|
291
|
+
narrowObserver.observe(root);
|
|
288
292
|
|
|
289
293
|
// --- Document title (kernel-owned, composed from two inputs) ---
|
|
290
294
|
//
|