diff options
Diffstat (limited to 'modules')
| -rw-r--r-- | modules/core/core-bundle.js | 31 | ||||
| -rw-r--r-- | modules/core/module-uishell.js | 31 |
2 files changed, 52 insertions, 10 deletions
diff --git a/modules/core/core-bundle.js b/modules/core/core-bundle.js index 36f6e7a..924ab14 100644 --- a/modules/core/core-bundle.js +++ b/modules/core/core-bundle.js @@ -23267,13 +23267,31 @@ class UIShellModule { const st = document.createElement('style'); st.id = 'wx11-ui-base-css'; st.textContent = [ - '#ui-root{position:fixed;inset:0;display:none;overflow:hidden;z-index:40;background:var(--bg-color);color:var(--text-color)}', - 'body[data-ui-mode]:not([data-ui-mode="classic"]) #ui-root{display:block}', + // clip, not hidden: `overflow:hidden` still creates a scroll container, and the terminal's + // scrollIntoView() on new output scrolled #ui-root by 464px — the title, the action cards + // and the composer all left the screen (measured 2026-11-07). `clip` cannot be scrolled. + '#ui-root{position:fixed;inset:0;display:none;overflow:clip;z-index:40;background:var(--bg-color);color:var(--text-color)}', + // flex column, not block: every mode is a vertical stack (chrome / content / composer / + // footer) and a block container makes each child's `flex:1 1 auto` inert — the terminal + // collapsed to 0px and the composer sat at the very bottom of a 4 600px flow. + 'body[data-ui-mode]:not([data-ui-mode="classic"]) #ui-root{display:flex;flex-direction:column;height:100%}', + '#ui-root > *{min-width:0;min-height:0}', + // A non-classic mode owns the viewport: the page itself must not scroll, or terminal + // output drags the action cards off-screen and the composer never comes back. + 'body[data-ui-mode]:not([data-ui-mode="classic"]){overflow:clip}', + 'body[data-ui-mode]:not([data-ui-mode="classic"]) #ui-root{overflow:clip}', 'body[data-ui-mode]:not([data-ui-mode="classic"]) #cmd-cards{display:none!important}', + // A mode IS the onboarding: six cards behind the classic "Let's Get Started" modal is two + // competing first-run prompts, and the modal covered the easy mode's action cards. + 'body[data-ui-mode]:not([data-ui-mode="classic"]) #welcome-modal{display:none!important}', 'body[data-ui-mode]:not([data-ui-mode="classic"]) #ui-root{padding-bottom:34px}', // The stock containers are flex children of <body>; inside a pane they must be able to // shrink, or every mode overflows vertically and the input scrolls off-screen. - '#ui-root #terminal-container{flex:1 1 auto;min-height:0;height:auto;overflow-y:auto;padding:0}', + // basis 0, not auto: with `auto` the terminal takes its 4 600px content height and pushes + // every sibling out of the viewport instead of scrolling inside its own pane. + // min-height 100px, not 0: in the tabbed/panel modes the terminal sits inside a grid cell + // that is not a flex parent, so `flex:1 1 0` resolves to 0 and the output strip vanished. + '#ui-root #terminal-container{flex:1 1 0;min-height:100px;height:0;overflow-y:auto;padding:0}', '#ui-root #input-area{flex:0 0 auto}', '#ui-root #status-bar{flex:0 0 auto}', '#ui-foot{position:absolute;left:0;right:0;bottom:0;height:34px;display:flex;align-items:center;', @@ -23331,10 +23349,13 @@ class UIShellModule { exec: (line) => term.executeCommand(String(line)), // shell-authored fixed strings only → capturePipeOutput (no security gate) capture: (line) => { - const parts = term._parseArgs(String(line).trim()); + // Do NOT use terminal._parseArgs — it does not exist on the terminal instance; every + // panel rendered "unavailable: term._parseArgs is not a function" (measured 2026-11-07). + const raw = String(line).trim(); + const parts = raw.match(/(?:[^\s"']+|"[^"]*"|'[^']*')+/g) || []; const cmd = parts[0]; if (!cmd) return Promise.resolve(''); - return term.capturePipeOutput(cmd, parts.slice(1), String(line)); + return term.capturePipeOutput(cmd, parts.slice(1), raw); }, fs: term.fs, el: (tag, props, kids) => { diff --git a/modules/core/module-uishell.js b/modules/core/module-uishell.js index 63a1437..ac14b20 100644 --- a/modules/core/module-uishell.js +++ b/modules/core/module-uishell.js @@ -306,13 +306,31 @@ class UIShellModule { const st = document.createElement('style'); st.id = 'wx11-ui-base-css'; st.textContent = [ - '#ui-root{position:fixed;inset:0;display:none;overflow:hidden;z-index:40;background:var(--bg-color);color:var(--text-color)}', - 'body[data-ui-mode]:not([data-ui-mode="classic"]) #ui-root{display:block}', + // clip, not hidden: `overflow:hidden` still creates a scroll container, and the terminal's + // scrollIntoView() on new output scrolled #ui-root by 464px — the title, the action cards + // and the composer all left the screen (measured 2026-11-07). `clip` cannot be scrolled. + '#ui-root{position:fixed;inset:0;display:none;overflow:clip;z-index:40;background:var(--bg-color);color:var(--text-color)}', + // flex column, not block: every mode is a vertical stack (chrome / content / composer / + // footer) and a block container makes each child's `flex:1 1 auto` inert — the terminal + // collapsed to 0px and the composer sat at the very bottom of a 4 600px flow. + 'body[data-ui-mode]:not([data-ui-mode="classic"]) #ui-root{display:flex;flex-direction:column;height:100%}', + '#ui-root > *{min-width:0;min-height:0}', + // A non-classic mode owns the viewport: the page itself must not scroll, or terminal + // output drags the action cards off-screen and the composer never comes back. + 'body[data-ui-mode]:not([data-ui-mode="classic"]){overflow:clip}', + 'body[data-ui-mode]:not([data-ui-mode="classic"]) #ui-root{overflow:clip}', 'body[data-ui-mode]:not([data-ui-mode="classic"]) #cmd-cards{display:none!important}', + // A mode IS the onboarding: six cards behind the classic "Let's Get Started" modal is two + // competing first-run prompts, and the modal covered the easy mode's action cards. + 'body[data-ui-mode]:not([data-ui-mode="classic"]) #welcome-modal{display:none!important}', 'body[data-ui-mode]:not([data-ui-mode="classic"]) #ui-root{padding-bottom:34px}', // The stock containers are flex children of <body>; inside a pane they must be able to // shrink, or every mode overflows vertically and the input scrolls off-screen. - '#ui-root #terminal-container{flex:1 1 auto;min-height:0;height:auto;overflow-y:auto;padding:0}', + // basis 0, not auto: with `auto` the terminal takes its 4 600px content height and pushes + // every sibling out of the viewport instead of scrolling inside its own pane. + // min-height 100px, not 0: in the tabbed/panel modes the terminal sits inside a grid cell + // that is not a flex parent, so `flex:1 1 0` resolves to 0 and the output strip vanished. + '#ui-root #terminal-container{flex:1 1 0;min-height:100px;height:0;overflow-y:auto;padding:0}', '#ui-root #input-area{flex:0 0 auto}', '#ui-root #status-bar{flex:0 0 auto}', '#ui-foot{position:absolute;left:0;right:0;bottom:0;height:34px;display:flex;align-items:center;', @@ -370,10 +388,13 @@ class UIShellModule { exec: (line) => term.executeCommand(String(line)), // shell-authored fixed strings only → capturePipeOutput (no security gate) capture: (line) => { - const parts = term._parseArgs(String(line).trim()); + // Do NOT use terminal._parseArgs — it does not exist on the terminal instance; every + // panel rendered "unavailable: term._parseArgs is not a function" (measured 2026-11-07). + const raw = String(line).trim(); + const parts = raw.match(/(?:[^\s"']+|"[^"]*"|'[^']*')+/g) || []; const cmd = parts[0]; if (!cmd) return Promise.resolve(''); - return term.capturePipeOutput(cmd, parts.slice(1), String(line)); + return term.capturePipeOutput(cmd, parts.slice(1), raw); }, fs: term.fs, el: (tag, props, kids) => { |