Skip to content

Instantly share code, notes, and snippets.

@sritchie
Created November 7, 2022 02:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sritchie/aabc0895ac6c831f379a0212265cc9d8 to your computer and use it in GitHub Desktop.
Save sritchie/aabc0895ac6c831f379a0212265cc9d8 to your computer and use it in GitHub Desktop.
(def ^{:doc "Docstring."}
Mathfield
(r/adapt-react-class
(react/forwardRef
(fn [props ref]
(let [[mf set-mf] (react/useState nil)
{:strs [children value options defaultValue onChange
soundsDirectory fontsDirectory] :as props}
(js->clj props)]
;; These effects run once on initial load (note the empty dependency array).
(react/useEffect
(fn mount []
(when children
(js/console.error "don't set children!"))
(when (and defaultValue value)
(js/console.error "don't both value and defaultValue!")))
#js [])
;; NOTE this tricky thing, don't use "options" since that changes every
;; time! This effect notes if any properties change; this matters if you
;; allow the user to provide a map.
(let [opt-ref (react/useRef options)]
(when (not= opt-ref.current options)
(set! (.-current opt-ref) options))
(react/useEffect
(fn mount []
(when (and mf options)
(update-options! mf options)))
#js [(.-current opt-ref) mf]))
;; This triggers whenever the value changes; if someone else has changed
;; the value this keeps the Mathfield in sync.
(react/useEffect
(fn mount []
(when (and mf value (not= (.getValue mf) value))
(.setValue mf value)))
#js [value])
;; For whatever reason, when the component is controlled, the component
;; can't move its own cursor position well. So this handles the odd case
;; at the very beginning...
(react/useEffect
(fn []
(when (and mf
(.endsWith (.getValue mf) "?")
(= 2 (.-position mf)))
(.executeCommand ^js mf "moveToPreviousWord"))))
(react/useImperativeHandle ref (fn [] mf))
(r/as-element
[:math-field
(assoc (dissoc props "onChange" "defaultValue" "value")
"children" (or value defaultValue "")
"ref" set-mf
"onInput" onChange
"sounds-directory" (or soundsDirectory default-sounds-directory)
"fonts-directory" (or fontsDirectory default-fonts-directory))]))))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment