@cplieger/web-terminal-ui 5.3.1 → 5.4.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.
- package/LICENSE +371 -690
- package/README.md +1 -1
- package/css/01-scope.css +10 -0
- package/css/30-tabs.css +42 -3
- package/css/40-animations.css +34 -1
- package/package.json +6 -6
- package/src/features/tabs/index.ts +798 -123
- package/src/features/tabs/model.ts +116 -90
- package/src/features/tabs/strip.ts +82 -7
- package/src/features/tabs/switch-anim.ts +29 -0
- package/src/kernel/kernel.ts +6 -3
package/README.md
CHANGED
package/css/01-scope.css
CHANGED
|
@@ -15,6 +15,16 @@
|
|
|
15
15
|
.wt-root.wt-viewport {
|
|
16
16
|
position: fixed;
|
|
17
17
|
inset: 0;
|
|
18
|
+
/* Clip like the container mode below, so the two layout modes agree. Inert
|
|
19
|
+
today: the root's box IS the viewport here and page.css already hides
|
|
20
|
+
document overflow, so nothing can currently paint outside it, and
|
|
21
|
+
position:fixed descendants escape a clip regardless. It exists so the
|
|
22
|
+
asymmetry cannot be mistaken for a deliberate difference, and so a future
|
|
23
|
+
transform on .term (see docs/tab-switch-repaint.md) is bounded by a
|
|
24
|
+
declaration rather than by the viewport happening to coincide with the box.
|
|
25
|
+
overflow:clip specifically, not hidden: no scroll container, no block
|
|
26
|
+
formatting context, nothing programmatically scrollable. */
|
|
27
|
+
overflow: clip;
|
|
18
28
|
}
|
|
19
29
|
|
|
20
30
|
.wt-root.wt-container {
|
package/css/30-tabs.css
CHANGED
|
@@ -495,9 +495,48 @@
|
|
|
495
495
|
}
|
|
496
496
|
}
|
|
497
497
|
|
|
498
|
-
/*
|
|
499
|
-
|
|
500
|
-
|
|
498
|
+
/* ===== Reorder drop slot (tabs feature, desktop drag) =====
|
|
499
|
+
The dragged chip stays in the strip's flow for the whole gesture and renders as
|
|
500
|
+
the SLOT it will land in: an empty dashed outline in the accent over a faint
|
|
501
|
+
accent wash. It used to be a dimmed copy of the tab, and with a solid drag
|
|
502
|
+
image already following the pointer that put three tab-shaped things on screen
|
|
503
|
+
at once — the slot it left, the chip it hovered, and the copy under the
|
|
504
|
+
pointer — none of which read as the answer to "where will this land". One
|
|
505
|
+
solid thing under the pointer, one hollow thing where it will land.
|
|
506
|
+
|
|
507
|
+
Staying in the flow is what keeps the geometry honest: the slot IS the gap,
|
|
508
|
+
exactly one chip wide, so nothing has to synthesise a placeholder box or agree
|
|
509
|
+
with the chip about how wide a tab is. It is also what lets the reorder animate
|
|
510
|
+
at all — the strip's other chips slide around a real box (index.ts, commitSlot).
|
|
511
|
+
|
|
512
|
+
The outline is the chip's OWN reserved border switched to `dashed`: every tab
|
|
513
|
+
carries a transparent 1px border for exactly this kind of toggle (see .wt-tab),
|
|
514
|
+
so the treatment costs no layout and lands on the same --radius-inner corners
|
|
515
|
+
as every other chip state.
|
|
516
|
+
|
|
517
|
+
Scoped through .wt-tab-scroll on purpose, and it is not decoration. A drag
|
|
518
|
+
reorder exists only inside the desktop scroller, and the extra compound is what
|
|
519
|
+
carries the rule past the two rungs it has to out-rank without any of the usual
|
|
520
|
+
tricks: the press rung (.wt-tab:not(.wt-tab-active):active, which a mousedown
|
|
521
|
+
that starts a drag leaves applied for the whole gesture in Blink, so the slot
|
|
522
|
+
would otherwise paint as a pressed tab under the dashes), and the per-status
|
|
523
|
+
dot rules far below, which would otherwise keep the status dot lit inside an
|
|
524
|
+
outline that is meant to be empty. */
|
|
525
|
+
:where(.wt-root) .wt-tab-scroll .wt-tab.wt-tab-dragging {
|
|
526
|
+
background: color-mix(in oklch, var(--accent) 12%, transparent);
|
|
527
|
+
border-color: color-mix(in oklch, var(--accent) 60%, transparent);
|
|
528
|
+
border-style: dashed;
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
/* Nothing inside the slot: the outline is the whole message, and the tab's
|
|
532
|
+
identity is already in the drag image under the pointer. Fading the CONTENT
|
|
533
|
+
rather than the chip is what keeps the dashes at full strength — an opacity on
|
|
534
|
+
the chip dimmed the outline along with everything else, which is exactly how
|
|
535
|
+
the old treatment ended up reading as a faded tab rather than as a gap. The dot
|
|
536
|
+
is included by inheritance: opacity multiplies onto its glow and ripple
|
|
537
|
+
pseudo-elements, so one declaration silences the whole dot. */
|
|
538
|
+
:where(.wt-root) .wt-tab-scroll .wt-tab.wt-tab-dragging > * {
|
|
539
|
+
opacity: 0;
|
|
501
540
|
}
|
|
502
541
|
|
|
503
542
|
/* ===== Inline rename (tabs feature) =====
|
package/css/40-animations.css
CHANGED
|
@@ -27,15 +27,48 @@
|
|
|
27
27
|
display var(--dur-standard) allow-discrete;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
/* Tab chrome micro-transitions (hover/active
|
|
30
|
+
/* Tab chrome micro-transitions (hover/active colour shifts, and a chip's hand-off
|
|
31
|
+
into the reorder drop slot). border-color rides along because the slot IS a
|
|
32
|
+
border-colour change plus a dashed style (30-tabs.css): without it the chip
|
|
33
|
+
snapped from tab to outline in a single frame, which is the same instant
|
|
34
|
+
rearrangement the reorder preview exists to remove. The dash pattern itself still
|
|
35
|
+
appears at once — border-style does not interpolate — so the slot reads as an
|
|
36
|
+
outline drawing itself in rather than as a tab bleaching out. */
|
|
31
37
|
:where(.wt-root.wt-animate) .wt-tab,
|
|
32
38
|
:where(.wt-root.wt-animate) .wt-tab-close,
|
|
33
39
|
:where(.wt-root.wt-animate) .wt-tab-new {
|
|
34
40
|
transition:
|
|
35
41
|
background-color var(--dur-micro) var(--ease-standard),
|
|
42
|
+
border-color var(--dur-micro) var(--ease-standard),
|
|
36
43
|
color var(--dur-micro) var(--ease-standard);
|
|
37
44
|
}
|
|
38
45
|
|
|
46
|
+
/* The chip's content dissolves as it becomes the drop slot, and comes back when the
|
|
47
|
+
drag ends (30-tabs.css fades every child to nothing). One rule on the children,
|
|
48
|
+
not four per-part rules: the label, the status dot, the progress bar and the close
|
|
49
|
+
all leave together, because they leave for one reason. */
|
|
50
|
+
:where(.wt-root.wt-animate) .wt-tab > * {
|
|
51
|
+
transition: opacity var(--dur-micro) var(--ease-standard);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/* The drop slot fades in at each position the reorder preview commits it to
|
|
55
|
+
(index.ts, flashSlot). The chips it displaces SLIDE there — a JS FLIP, because the
|
|
56
|
+
distance is only known at commit time — while the slot itself deliberately does
|
|
57
|
+
not travel: a hole crossing the strip alongside the solid drag image the pointer
|
|
58
|
+
is already carrying is two things moving at once, which is what made the old
|
|
59
|
+
instant reorder unreadable. It appears where the strip has just opened, which is
|
|
60
|
+
the frame that says the reorder took. */
|
|
61
|
+
:where(.wt-root.wt-animate) .wt-tab-slotted {
|
|
62
|
+
animation: wt-slot-in var(--dur-enter) var(--ease-enter);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
@keyframes wt-slot-in {
|
|
66
|
+
from {
|
|
67
|
+
opacity: 0;
|
|
68
|
+
transform: scale(0.97);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
39
72
|
/* New tab enters with a fade + scale-in. Only runtime-added tabs get
|
|
40
73
|
.wt-tab-enter (the tabs feature's `started` gate). A closing tab is removed
|
|
41
74
|
immediately with no exit animation, so the strip reflows in one frame (a
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cplieger/web-terminal-ui",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.4.1",
|
|
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
|
-
"license": "
|
|
6
|
+
"license": "MPL-2.0",
|
|
7
7
|
"exports": {
|
|
8
8
|
".": "./src/index.ts",
|
|
9
9
|
"./startup-copy": "./src/kernel/startup-copy.ts",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"verify": "bash scripts/verify.sh"
|
|
41
41
|
},
|
|
42
42
|
"peerDependencies": {
|
|
43
|
-
"@cplieger/web-terminal-engine": "^3.
|
|
43
|
+
"@cplieger/web-terminal-engine": "^3.10.0"
|
|
44
44
|
},
|
|
45
45
|
"overrides": {
|
|
46
46
|
"qs": "^6.15.2"
|
|
@@ -50,19 +50,19 @@
|
|
|
50
50
|
"@stryker-mutator/core": "9.6.1",
|
|
51
51
|
"@stryker-mutator/typescript-checker": "9.6.1",
|
|
52
52
|
"@stryker-mutator/vitest-runner": "9.6.1",
|
|
53
|
-
"@types/node": "
|
|
53
|
+
"@types/node": "26.2.0",
|
|
54
54
|
"@typescript/native": "npm:typescript@7.0.2",
|
|
55
55
|
"@vitest/coverage-v8": "4.1.10",
|
|
56
56
|
"eslint": "10.8.1",
|
|
57
57
|
"fast-check": "4.9.0",
|
|
58
58
|
"happy-dom": "20.11.2",
|
|
59
59
|
"html-validate": "11.6.2",
|
|
60
|
-
"knip": "6.32.
|
|
60
|
+
"knip": "6.32.1",
|
|
61
61
|
"prettier": "3.9.6",
|
|
62
62
|
"stylelint": "17.14.1",
|
|
63
63
|
"stylelint-config-standard": "40.0.0",
|
|
64
64
|
"typescript": "npm:@typescript/typescript6@6.0.2",
|
|
65
|
-
"typescript-eslint": "8.
|
|
65
|
+
"typescript-eslint": "8.67.0",
|
|
66
66
|
"vitest": "4.1.10"
|
|
67
67
|
},
|
|
68
68
|
"publishConfig": {
|