equation editor를 만들며, mathlive라는 라이브러리 사용 방법을 알아보면서, 라이브러리 사용 방식에 2가지가 있다는 사실을 알았다.
그것을 간단하게 정리해보려고 한다.
또, 이어서, mathlive 라이브러리 사용 방법을 알아보려고 한다.
: Content Delivery Network 에 있는 파일 (즉, 웹 주소)을 브라우저가 직접 불러옴
-> index.html 안에 script 태그로 넣어줌
: npm install로 프로젝트에 직접 설치 (node_modules)
--> 즉, 직접 배포할 프로젝트에는 당연히 npm 방식으로 라이브러리 불러오는 게 맞음!!!!!
<math-field
// onInput={(e) => setValue((e.target as any).value)}
ref={mathfieldRef}
virtual-keyboard-mode="onfocus"
>
log
</math-field>
-> 그런데, Property 'math-field' does not exist on type 'JSX.IntrinsicElements' 라는 오류 발생
WHY?
: math-field 는 커스톰 웹 컴포넌트라서, typescript에서는 인식하지 못함. 따라서 해당 코드도 인식할 수 있게 아래 코드 글로벌에 추가
import 'react';
declare module 'react' {
namespace JSX {
interface IntrinsicElements {
'math-field': React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement> & {
value?: string;
readonly?: boolean;
disabled?: boolean;
onInput?: (event: any) => void;
virtualKeyboardMode?: string;
};
}
}
}
-> typescript에서 math-field 태그 인식할 수 있게 추가
ResizeObserver loop completed with undelivered notifications.
at handleError (webpack-internal:///./node_modules/webpack-dev-server/client/overlay.js:589:58)
at eval (webpack-internal:///./node_modules/webpack-dev-server/client/overlay.js:613:7)
: 개발 서버에서 브라우저에서 DOM 크기 변화 감시하는 ResizeObserver가 과도하게 처리되어서 뜨는 오류이다. 프로덕션에서는 나타나지 않으므로 해결하지 않아도 되는 문제인데, overlay가 되는 것이 문제였으므로 (빨간 화면)
-> webpack.config.js 를 수정해서 해결하였다.
devServer: {
historyApiFallback: true,
client: {
overlay: {
runtimeErrors: (error) => {
if(error?.message === "ResizeObserver loop completed with undelivered notifications.")
{
console.error(error)
return false;
}
return true;
},
},
},
},
-> devServer 즉, 로컬 개발할 때의 동작들을 제어하는 부분에 설정을 추가해준 것. 그 중에서도 client, 브라우저에서 보여주는 부분에 대한 설정 추가
-> 해당 메시지가 뜨면, overlay는 안되지만, 콘솔에는 남게끔 수정해두었다.
keyboard.layouts = {
rows: [
["1","2","3","4","5","x","y",""],
["6","7","8","9","0","+","-","\\sqrt{#0}"],
["\\%","-",".","\\frac{#0}{#0}","{#0}\\frac{#0}{#0}","\\cdot","\\div","\\sqrt[#0]{#0}"],
["","{#0}^{#0}","({#0})","\\le","\\lt","=","\\ge","\\gt"],
["\\pi","","","","","","","\\lvert{#@}\\rvert"],
]
};
const style = document.createElement("style");
style.innerHTML = `
.digitalSHSATModule__eeContainer { position: relative; }
math-field::part(menu-toggle),
math-field::part(virtual-keyboard-toggle) { display: none !important; }
.digitalSHSATModule__eeContainer .ML__virtual-keyboard {
position: absolute !important;
top: calc(100% + 8px) !important;
left: 0 !important;
width: 620px !important;
z-index: 999 !important;
}
`;
document.head.appendChild(style);
-> style을 추가해준다. display: none이 되도록!
math-field::part(menu-toggle),
math-field::part(virtual-keyboard-toggle) { display: none !important; }
const container = document.querySelector(".digitalSHSATModule__eeContainer");
if (container) keyboard.container = container;
setTimeout(() => {
const vk = container?.querySelector(".ML__keyboard") as HTMLElement;
if (vk) {
vk.style.height = "260px";
vk.style.pointerEvents = "auto";
vk.style.opacity = "1";
vk.style.visibility = "visible";
}
}, 50);
--> 기준이 되는 컨테이너를 바꿔주었다. 그 안에 담기도록 위치를 조절해주었다.
const preventHide = (e: FocusEvent) => {
setTimeout(() => {
if (mf && document.activeElement !== mf) { // refocus
mf.focus();
}
keyboard.show();
if (vk) {
vk.style.display = "block";
vk.style.visibility = "visible";
vk.style.opacity = "1";
vk.style.pointerEvents = "auto";
}
}, 10); // delay after hide keyboard
};
mf.addEventListener("blur", preventHide, true);
mf.addEventListener("focusout", preventHide, true);
-> focus가 사라지면, 키보드가 사라지는 것이다. 이거를 해결하는데, 가장 오랜 시간이 걸렸다. ㅋㅋ 그래서, 포커스 아웃이 되면, refocus 되도록 만들었다.