69 lines
2.1 KiB
TypeScript
69 lines
2.1 KiB
TypeScript
import { THEME, h } from "./dom";
|
|
|
|
/**
|
|
* Generate a build for the output component
|
|
* @param target The parent element in which it is mounted
|
|
* @returns DOM reference to the console box and output container
|
|
*/
|
|
export default function outputBuild(target: HTMLElement) {
|
|
const consoleBox = h<HTMLSpanElement>("span");
|
|
|
|
const outputBox = h<HTMLDivElement>("div", {
|
|
class: THEME.OUTPUT,
|
|
children: [consoleBox]
|
|
});
|
|
|
|
target.appendChild(outputBox);
|
|
|
|
return { outputBox, consoleBox };
|
|
}
|
|
|
|
/**
|
|
* Generate a build for the input component
|
|
* @param target The parent element in which it is mounted
|
|
* @returns DOM reference to the input element
|
|
*/
|
|
export function inputBuild(target: HTMLElement) {
|
|
const inputBox = h<HTMLTextAreaElement>("textarea", {
|
|
props: {
|
|
// 明确声明为普通文本输入,降低移动端将其识别为登录表单的概率。
|
|
spellcheck: false,
|
|
autocorrect: "off",
|
|
autocapitalize: "off",
|
|
autocomplete: "off",
|
|
name: "xterminal_input",
|
|
inputmode: "text",
|
|
enterkeyhint: "enter",
|
|
rows: 1,
|
|
wrap: "off"
|
|
}
|
|
});
|
|
// 部分密码管理器会读取 data-* 做识别,显式标记为非登录用途。
|
|
inputBox.setAttribute("data-form-type", "other");
|
|
inputBox.setAttribute("data-lpignore", "true");
|
|
inputBox.setAttribute("data-1p-ignore", "true");
|
|
inputBox.setAttribute("data-bwignore", "true");
|
|
inputBox.setAttribute("aria-autocomplete", "none");
|
|
inputBox.setAttribute("autocapitalize", "off");
|
|
inputBox.setAttribute("autocorrect", "off");
|
|
// 某些浏览器在首帧点击文本输入框时会误触发凭据弹窗;
|
|
// 先只读,获得焦点后立刻解除,可显著降低“刷新后点一下就弹登录”的概率。
|
|
inputBox.readOnly = true;
|
|
inputBox.addEventListener(
|
|
"focus",
|
|
() => {
|
|
inputBox.readOnly = false;
|
|
},
|
|
{ once: true }
|
|
);
|
|
|
|
const stdin = h<HTMLDivElement>("div", {
|
|
class: THEME.INPUT,
|
|
children: [inputBox]
|
|
});
|
|
|
|
target.appendChild(stdin);
|
|
|
|
return inputBox;
|
|
}
|