@cplieger/web-terminal-ui 5.4.2 → 5.4.3
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 +1 -1
- package/src/features/tabs/index.ts +49 -20
- package/src/features/tabs/strip.ts +26 -15
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cplieger/web-terminal-ui",
|
|
3
|
-
"version": "5.4.
|
|
3
|
+
"version": "5.4.3",
|
|
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",
|
|
@@ -45,6 +45,7 @@ import { browserNotifierEnv, createNotifier } from "./notify.js";
|
|
|
45
45
|
import {
|
|
46
46
|
REORDER_MOVE_EPS_PX,
|
|
47
47
|
REORDER_REST_MS,
|
|
48
|
+
REORDER_STILL_MS,
|
|
48
49
|
REORDER_SETTLE_MS,
|
|
49
50
|
REORDER_SHIFT_TRANS,
|
|
50
51
|
REORDER_SLOT_FADE_MS,
|
|
@@ -679,6 +680,9 @@ export function tabs(opts: TabsOptions = {}): TerminalFeature<TabsApi> {
|
|
|
679
680
|
let restTimer: ReturnType<typeof setTimeout> | null = null;
|
|
680
681
|
let restBefore: HTMLElement | null = null;
|
|
681
682
|
let restX: number | null = null;
|
|
683
|
+
// When the pointer last actually MOVED. A stationary dragover this long after it
|
|
684
|
+
// is believed as a stop (see trackRest).
|
|
685
|
+
let restMovedAt = 0;
|
|
682
686
|
// Whether a `drop` fired for the drag in flight. It is the exact signal for
|
|
683
687
|
// "the user released deliberately" as opposed to "the drag was abandoned":
|
|
684
688
|
// Escape and a refused release fire dragend with no drop at all. dragend
|
|
@@ -1943,12 +1947,19 @@ export function tabs(opts: TabsOptions = {}): TerminalFeature<TabsApi> {
|
|
|
1943
1947
|
// travelling pointer rearranges nothing at all; the moment it comes to REST the
|
|
1944
1948
|
// slot opens.
|
|
1945
1949
|
//
|
|
1946
|
-
// Rest is detected
|
|
1947
|
-
//
|
|
1948
|
-
//
|
|
1949
|
-
//
|
|
1950
|
-
//
|
|
1951
|
-
//
|
|
1950
|
+
// Rest is detected from TWO signals, and separating them is what lets the slot
|
|
1951
|
+
// open promptly without a fast sweep committing every slot it crosses:
|
|
1952
|
+
//
|
|
1953
|
+
// - a `dragover` at an unchanged position is POSITIVE evidence of a stop, so it
|
|
1954
|
+
// commits after a short REORDER_STILL_MS confirmation. This is the signal that
|
|
1955
|
+
// normally decides, and the reason the delay is short.
|
|
1956
|
+
// - the absence of events is only a FALLBACK (armRestNet), for a browser that
|
|
1957
|
+
// stops delivering dragover entirely. That one has to out-wait the drag loop's
|
|
1958
|
+
// 350ms cadence, so it is long — and it is rarely what decides.
|
|
1959
|
+
//
|
|
1960
|
+
// One quiet window had to serve both jobs before this, which is why it could not be
|
|
1961
|
+
// shortened: the timer deciding responsiveness was the same one that had to survive
|
|
1962
|
+
// the cadence.
|
|
1952
1963
|
function trackRest(clientX: number): void {
|
|
1953
1964
|
const dragged = draggingEl;
|
|
1954
1965
|
if (!dragged) {
|
|
@@ -1964,21 +1975,39 @@ export function tabs(opts: TabsOptions = {}): TerminalFeature<TabsApi> {
|
|
|
1964
1975
|
return;
|
|
1965
1976
|
}
|
|
1966
1977
|
restBefore = before;
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1978
|
+
const now = Date.now();
|
|
1979
|
+
if (moved) {
|
|
1980
|
+
// Still travelling. Push the net out and wait.
|
|
1981
|
+
restMovedAt = now;
|
|
1982
|
+
armRestNet();
|
|
1983
|
+
return;
|
|
1984
|
+
}
|
|
1985
|
+
// A dragover at an UNCHANGED position is positive evidence that the pointer has
|
|
1986
|
+
// stopped, which is a far stronger signal than the absence of events — and it is
|
|
1987
|
+
// what lets the slot open promptly instead of out-waiting the drag loop's 350ms
|
|
1988
|
+
// cadence. The elapsed check filters the coincidence where one event of a sweep
|
|
1989
|
+
// lands within REORDER_MOVE_EPS_PX of the previous (a reversal, or a frame whose
|
|
1990
|
+
// motion was almost all vertical); a real stop clears it on the next event.
|
|
1991
|
+
if (now - restMovedAt >= REORDER_STILL_MS) {
|
|
1992
|
+
flushRest();
|
|
1993
|
+
return;
|
|
1981
1994
|
}
|
|
1995
|
+
armRestNet(); // too soon to believe; keep the net alive
|
|
1996
|
+
}
|
|
1997
|
+
// armRestNet is the no-events fallback: if dragover stops arriving altogether, no
|
|
1998
|
+
// stationary event will ever confirm the stop, so this commits anyway. Sized to
|
|
1999
|
+
// out-wait the cadence (see REORDER_REST_MS) because it is the one timer that a
|
|
2000
|
+
// fast sweep could otherwise expire between two of its own events.
|
|
2001
|
+
function armRestNet(): void {
|
|
2002
|
+
if (restTimer !== null) {
|
|
2003
|
+
clearTimeout(restTimer);
|
|
2004
|
+
}
|
|
2005
|
+
restTimer = setTimeout(() => {
|
|
2006
|
+
restTimer = null;
|
|
2007
|
+
const target = restBefore;
|
|
2008
|
+
restBefore = null;
|
|
2009
|
+
commitSlot(target);
|
|
2010
|
+
}, REORDER_REST_MS);
|
|
1982
2011
|
}
|
|
1983
2012
|
function cancelRest(): void {
|
|
1984
2013
|
if (restTimer === null) {
|
|
@@ -21,24 +21,35 @@ import { statusPhrase, statusRevealsDot } from "./model.js";
|
|
|
21
21
|
// motion is spelled in — index.ts owns the mechanism, strip.ts owns the values,
|
|
22
22
|
// the same split switcher.ts keeps for the mobile swipe.
|
|
23
23
|
|
|
24
|
-
/**
|
|
25
|
-
*
|
|
24
|
+
/** How long (ms) the pointer must have been un-moved before a stationary `dragover` is
|
|
25
|
+
* believed as "stopped".
|
|
26
26
|
*
|
|
27
|
-
* This is
|
|
28
|
-
*
|
|
29
|
-
*
|
|
27
|
+
* This is the number that decides how fast the slot opens, and it is small because a
|
|
28
|
+
* `dragover` at an UNCHANGED position is positive evidence of rest — far better
|
|
29
|
+
* evidence than the absence of events, which is all the fallback below has. The drag
|
|
30
|
+
* loop keeps delivering events while the pointer is held still, so a genuinely stopped
|
|
31
|
+
* pointer announces itself; this only filters the coincidence where one event of a
|
|
32
|
+
* sweep happens to land within REORDER_MOVE_EPS_PX of the previous one (a direction
|
|
33
|
+
* reversal, or a frame where the motion was almost entirely vertical). */
|
|
34
|
+
export const REORDER_STILL_MS = 90;
|
|
35
|
+
|
|
36
|
+
/** Fallback guard (ms): commit the pending slot this long after the last MOVEMENT, for
|
|
37
|
+
* the case where `dragover` stops arriving altogether and no stationary event ever
|
|
38
|
+
* confirms the stop.
|
|
30
39
|
*
|
|
31
|
-
* **
|
|
32
|
-
* guarantees a `dragover` every 350ms — the
|
|
33
|
-
* not per mouse movement — so
|
|
34
|
-
* of a fast sweep, and the strip commits every slot the
|
|
35
|
-
*
|
|
36
|
-
*
|
|
40
|
+
* **Its floor is set by the platform, not by taste, and this is the timer that floor
|
|
41
|
+
* applies to.** HTML5 drag-and-drop only guarantees a `dragover` every 350ms — the drag
|
|
42
|
+
* loop runs on that cadence, not per mouse movement — so a guard at or below it can
|
|
43
|
+
* expire BETWEEN two events of a fast sweep, and the strip then commits every slot the
|
|
44
|
+
* pointer crosses. Measured in production: at 120ms a quick pass over five tabs moved
|
|
45
|
+
* all five.
|
|
37
46
|
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
|
|
47
|
+
* A pure quiet-window design has to make this ONE number carry both jobs, which is why
|
|
48
|
+
* it could not be shortened — the same timer that decides responsiveness was the one
|
|
49
|
+
* that had to out-wait the cadence, so 500ms was safe and felt slow. Splitting rest
|
|
50
|
+
* DETECTION (the stationary event above) from the no-events NET (here) lets each be
|
|
51
|
+
* sized for its own job. This one is rarely the deciding signal at all. */
|
|
52
|
+
export const REORDER_REST_MS = 450;
|
|
42
53
|
|
|
43
54
|
/** Movement (px) between two dragover events below which the pointer counts as still.
|
|
44
55
|
* A hand resting on a mouse is never perfectly still, and treating a 1px tremor as a
|