Last active
August 23, 2023 09:12
-
-
Save gerryfletch/09d9995725027fcbf060d0149441c3a8 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import * as React from "react"; | |
import { CSSProperties, useEffect, useMemo } from "react"; | |
import { MathfieldElement, MathfieldOptions } from "mathlive"; | |
import { create } from "jss"; | |
import camelCase from "jss-plugin-camel-case"; | |
export type MathEditorProps = { | |
options?: Partial<MathfieldOptions>; | |
value: string; | |
onChange: (latex: string) => void; | |
onPlaceholderChange?: (placeholderId: string, latex: string) => void; | |
className?: string; | |
containerStyle?: CSSProperties; | |
placeholderStyle?: CSSProperties; | |
}; | |
/** | |
* @returns a styled math-editor as a non-controlled React component with placeholder support. | |
*/ | |
export const MathEditor = (props: MathEditorProps) => { | |
const containerRef = React.useRef<HTMLDivElement>(null); | |
const mfe = useMemo(() => new MathfieldElement(props.options), []); | |
useEffect(() => { | |
const container = containerRef.current!!; | |
container.innerHTML = ""; | |
container.appendChild(mfe); | |
mfe.className = props.className || ""; | |
// Listen to changes to main mathfield | |
mfe.addEventListener("input", ({ target }) => | |
props.onChange((target as HTMLInputElement).value || "") | |
); | |
// Listen to placeholders, firing if onPlaceholderChange present | |
mfe.addEventListener("placeholder-change", ({ detail }) => { | |
const { placeholderId } = detail; | |
const value = mfe.getPlaceholderField(placeholderId)?.getValue() || ""; | |
if (props.onPlaceholderChange) { | |
props.onPlaceholderChange(placeholderId, value); | |
} | |
}); | |
// Add custom styles to placeholder mathfield elements | |
Object.values(mfe.placeholders).forEach((placeholder) => | |
addStyleEl(placeholder, props.placeholderStyle ?? {}) | |
); | |
}, []); | |
useEffect(() => { | |
mfe.value = props.value; | |
}, [props.value]); | |
return <div ref={containerRef} style={props.containerStyle} />; | |
}; | |
/** | |
* Mathlive uses shadow DOMs which don't inherit global styles. | |
* We patch this by creating <style> tags for nested mathlive | |
* elements. `jss` is used to translate React CSSProperties into | |
* a stylesheet string which is inserted in a new style node. | |
* @param el Mathfield element to create styles for | |
* @param st CSS Properties | |
*/ | |
const addStyleEl = (el: MathfieldElement, css: CSSProperties) => { | |
const node = document.createElement("style"); | |
node.innerHTML = stylesheet("placeholder-mathfield", css); | |
el.appendChild(node); | |
el.classList.add("placeholder-mathfield"); | |
}; | |
const jss = create({ plugins: [camelCase()] }); | |
const stylesheet = (className: string, styles?: CSSProperties): string => | |
jss | |
.createStyleSheet({ [className]: styles }, { generateId: ({ key }) => key }) | |
.toString(); |
Hey @enzomarin I haven't used or updated mathlive in months, but I don't recall seeing that floating window before so it may be something new. I'd advise raising a discussion on the main repository or on Gitter if the community is still active on there.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hello again, sorry to bother you but I need your help again. It turns out that when I use the virtual keyboard, that floating element appears on the screen that, in addition to being annoying, allows you to modify the mathematical expression (it shouldn't since it is defined as static). I've tried looking in the documentation but I can't find what it is or how to disable it.