@cplieger/web-terminal-ui 5.3.1 → 5.4.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/LICENSE +371 -690
- package/README.md +1 -1
- package/css/01-scope.css +10 -0
- package/css/30-tabs.css +75 -3
- package/css/40-animations.css +34 -1
- package/package.json +3 -3
- package/src/features/tabs/index.ts +806 -123
- package/src/features/tabs/model.ts +116 -90
- package/src/features/tabs/strip.ts +75 -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,81 @@
|
|
|
495
495
|
}
|
|
496
496
|
}
|
|
497
497
|
|
|
498
|
-
/*
|
|
499
|
-
|
|
500
|
-
|
|
498
|
+
/* ===== Pending drop edge (tabs feature, desktop drag) =====
|
|
499
|
+
The exact boundary the dragged tab will be inserted at, marked while the hold runs
|
|
500
|
+
and filling from nothing to full over the hold's own duration (the tabs feature
|
|
501
|
+
sets the duration inline from REORDER_DWELL_MS, so the bar and the timer cannot
|
|
502
|
+
drift apart).
|
|
503
|
+
|
|
504
|
+
It rides the neighbouring chip: the leading edge of the chip being pushed aside,
|
|
505
|
+
or the trailing edge of the last chip when the tab is heading past the end of the
|
|
506
|
+
strip (.wt-tab-dwell-end). The chip is already position: relative for its progress
|
|
507
|
+
bar, and its overflow clip keeps the rail inside the same rounded padding box.
|
|
508
|
+
|
|
509
|
+
3px of solid accent rather than a dashed treatment: the dashed vocabulary belongs
|
|
510
|
+
to the SLOT, which is a destination that has been decided. This is a boundary
|
|
511
|
+
still being chosen, so it reads as a caret. inset-block keeps it clear of the
|
|
512
|
+
chip's rounded corners without needing its own radius arithmetic. */
|
|
513
|
+
:where(.wt-root) .wt-tab-dwell {
|
|
514
|
+
position: absolute;
|
|
515
|
+
inset-block: var(--sp-1);
|
|
516
|
+
inset-inline-start: 0;
|
|
517
|
+
width: 3px;
|
|
518
|
+
border-radius: var(--radius-sm);
|
|
519
|
+
background: var(--accent);
|
|
520
|
+
/* Grows upward like a gauge. The feature writes scaleY inline; a transform on this
|
|
521
|
+
element cannot collide with the chip's own animations because it is a separate
|
|
522
|
+
element, which is the whole reason the rail is not a pseudo-element on the chip. */
|
|
523
|
+
transform-origin: bottom;
|
|
524
|
+
pointer-events: none;
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
:where(.wt-root) .wt-tab-dwell-end {
|
|
528
|
+
inset-inline: auto 0;
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
/* ===== Reorder drop slot (tabs feature, desktop drag) =====
|
|
532
|
+
The dragged chip stays in the strip's flow for the whole gesture and renders as
|
|
533
|
+
the SLOT it will land in: an empty dashed outline in the accent over a faint
|
|
534
|
+
accent wash. It used to be a dimmed copy of the tab, and with a solid drag
|
|
535
|
+
image already following the pointer that put three tab-shaped things on screen
|
|
536
|
+
at once — the slot it left, the chip it hovered, and the copy under the
|
|
537
|
+
pointer — none of which read as the answer to "where will this land". One
|
|
538
|
+
solid thing under the pointer, one hollow thing where it will land.
|
|
539
|
+
|
|
540
|
+
Staying in the flow is what keeps the geometry honest: the slot IS the gap,
|
|
541
|
+
exactly one chip wide, so nothing has to synthesise a placeholder box or agree
|
|
542
|
+
with the chip about how wide a tab is. It is also what lets the reorder animate
|
|
543
|
+
at all — the strip's other chips slide around a real box (index.ts, commitSlot).
|
|
544
|
+
|
|
545
|
+
The outline is the chip's OWN reserved border switched to `dashed`: every tab
|
|
546
|
+
carries a transparent 1px border for exactly this kind of toggle (see .wt-tab),
|
|
547
|
+
so the treatment costs no layout and lands on the same --radius-inner corners
|
|
548
|
+
as every other chip state.
|
|
549
|
+
|
|
550
|
+
Scoped through .wt-tab-scroll on purpose, and it is not decoration. A drag
|
|
551
|
+
reorder exists only inside the desktop scroller, and the extra compound is what
|
|
552
|
+
carries the rule past the two rungs it has to out-rank without any of the usual
|
|
553
|
+
tricks: the press rung (.wt-tab:not(.wt-tab-active):active, which a mousedown
|
|
554
|
+
that starts a drag leaves applied for the whole gesture in Blink, so the slot
|
|
555
|
+
would otherwise paint as a pressed tab under the dashes), and the per-status
|
|
556
|
+
dot rules far below, which would otherwise keep the status dot lit inside an
|
|
557
|
+
outline that is meant to be empty. */
|
|
558
|
+
:where(.wt-root) .wt-tab-scroll .wt-tab.wt-tab-dragging {
|
|
559
|
+
background: color-mix(in oklch, var(--accent) 12%, transparent);
|
|
560
|
+
border-color: color-mix(in oklch, var(--accent) 60%, transparent);
|
|
561
|
+
border-style: dashed;
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
/* Nothing inside the slot: the outline is the whole message, and the tab's
|
|
565
|
+
identity is already in the drag image under the pointer. Fading the CONTENT
|
|
566
|
+
rather than the chip is what keeps the dashes at full strength — an opacity on
|
|
567
|
+
the chip dimmed the outline along with everything else, which is exactly how
|
|
568
|
+
the old treatment ended up reading as a faded tab rather than as a gap. The dot
|
|
569
|
+
is included by inheritance: opacity multiplies onto its glow and ripple
|
|
570
|
+
pseudo-elements, so one declaration silences the whole dot. */
|
|
571
|
+
:where(.wt-root) .wt-tab-scroll .wt-tab.wt-tab-dragging > * {
|
|
572
|
+
opacity: 0;
|
|
501
573
|
}
|
|
502
574
|
|
|
503
575
|
/* ===== 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.0",
|
|
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"
|