@cplieger/web-terminal-ui 2.1.1 → 2.1.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/css/02-app.css +13 -9
- package/package.json +1 -1
- package/src/composition.ts +6 -2
- package/src/viewport.ts +21 -8
package/css/02-app.css
CHANGED
|
@@ -57,15 +57,19 @@
|
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
.term-input {
|
|
60
|
-
/*
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
60
|
+
/* The hidden keyboard target. position:absolute (NOT fixed) so it lives in
|
|
61
|
+
the terminal's scroll/content coordinate space alongside .composition-view
|
|
62
|
+
and .pred-cursor: composition.positionCompositionView() moves it to the
|
|
63
|
+
cursor row, and because .term is pinned to the visual viewport (viewport.ts)
|
|
64
|
+
the textarea always sits at the VISIBLE cursor, above the keyboard, which is
|
|
65
|
+
where iOS wants the focused input so it does not scroll the page. As
|
|
66
|
+
position:fixed it was placed at the cursor's content offset in viewport
|
|
67
|
+
space, so once output had scrolled it landed off-screen / behind the
|
|
68
|
+
keyboard, and focusing it made iOS scroll the page up to reveal it (the
|
|
69
|
+
content jump). Kept on-screen and 1x1 / opacity:0 so iOS still opens the
|
|
70
|
+
keyboard for it; pointer-events:none so taps fall through to the scroll
|
|
71
|
+
surface (programmatic focus() still works). */
|
|
72
|
+
position: absolute;
|
|
69
73
|
inset-block-end: 0;
|
|
70
74
|
inset-inline-start: 0;
|
|
71
75
|
width: 1px;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cplieger/web-terminal-ui",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.3",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Reference touch-first browser UI for @cplieger/web-terminal-engine: textarea input model, mobile key toolbar, context menu, IME, predictive echo, viewport/keyboard-inset handling, and CSS. One mount() call.",
|
|
6
6
|
"license": "GPL-3.0-or-later",
|
package/src/composition.ts
CHANGED
|
@@ -141,8 +141,12 @@ export function positionCompositionView(): void {
|
|
|
141
141
|
compositionView.style.top = `${top}px`;
|
|
142
142
|
compositionView.style.height = `${cellH}px`;
|
|
143
143
|
compositionView.style.lineHeight = `${cellH}px`;
|
|
144
|
-
//
|
|
145
|
-
// view
|
|
144
|
+
// The textarea is position:absolute in the same scroll/content space as the
|
|
145
|
+
// composition view (see the .term-input CSS note), so the cursor's content
|
|
146
|
+
// coordinates place it at the cursor row directly. Because .term is pinned to
|
|
147
|
+
// the visual viewport (viewport.ts), that keeps the textarea at the VISIBLE
|
|
148
|
+
// cursor, above the keyboard — where iOS wants the focused input so it doesn't
|
|
149
|
+
// scroll the page to reveal it.
|
|
146
150
|
textarea.style.left = `${left}px`;
|
|
147
151
|
textarea.style.top = `${top}px`;
|
|
148
152
|
textarea.style.height = `${cellH}px`;
|
package/src/viewport.ts
CHANGED
|
@@ -61,15 +61,28 @@ export function init(opts: {
|
|
|
61
61
|
if (window.visualViewport) {
|
|
62
62
|
const vv = window.visualViewport;
|
|
63
63
|
const onChange = (): void => {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
//
|
|
67
|
-
//
|
|
68
|
-
//
|
|
69
|
-
//
|
|
64
|
+
// Pin the terminal's fixed box to the exact region the VISUAL viewport
|
|
65
|
+
// occupies inside the layout viewport. On iOS the soft keyboard shrinks
|
|
66
|
+
// (and can offset) the visual viewport WITHOUT resizing the layout
|
|
67
|
+
// viewport — interactive-widget=resizes-content is not honored on iOS
|
|
68
|
+
// Safari — so a `position: fixed; inset: 0` terminal keeps the full-screen
|
|
69
|
+
// height (keyboard overlaying the bottom) while iOS scrolls the focused
|
|
70
|
+
// input into view and shifts the fixed box up, sliding the output and
|
|
71
|
+
// prompt behind the keyboard (the "content jumps up, hidden until I
|
|
72
|
+
// scroll" symptom). Driving top AND bottom from visualViewport keeps the
|
|
73
|
+
// terminal exactly over the visible area in every browser, so nothing is
|
|
74
|
+
// left behind the keyboard for iOS to scroll to.
|
|
75
|
+
const offsetTop = Math.max(0, Math.round(vv.offsetTop));
|
|
76
|
+
const bottomInset = Math.max(0, Math.round(window.innerHeight - vv.offsetTop - vv.height));
|
|
77
|
+
termWrap.style.top = offsetTop > 0 ? `${offsetTop}px` : "";
|
|
78
|
+
termWrap.style.bottom = bottomInset > 0 ? `${bottomInset}px` : "";
|
|
79
|
+
// Expose the same geometry as CSS vars for the sibling fixed chrome:
|
|
80
|
+
// --kb-inset lifts the bottom banner above the keyboard; --vv-top lets the
|
|
81
|
+
// top key toolbar follow the visual viewport's offset (otherwise it
|
|
82
|
+
// scrolls off the top when iOS shifts the layout up).
|
|
70
83
|
const root = document.documentElement.style;
|
|
71
|
-
root.setProperty("--kb-inset", `${
|
|
72
|
-
root.setProperty("--vv-top", `${
|
|
84
|
+
root.setProperty("--kb-inset", `${bottomInset}px`);
|
|
85
|
+
root.setProperty("--vv-top", `${offsetTop}px`);
|
|
73
86
|
startTransition();
|
|
74
87
|
};
|
|
75
88
|
vv.addEventListener("resize", onChange);
|