simian 0.2.0

A command-line tool for exploring and implementing Machine Learning algorithms in Rust.
import 'katex/dist/katex.min.css'
import katex from 'katex'
import { FC, useCallback, useEffect } from 'react'
import { Editor, Node, Transforms } from 'slate'
import { ReactEditor, useFocused, useSelected } from 'slate-react'

import { useEditor } from '@/ui/editor/context'
import { ElementProps } from '@/ui/editor/types'
import clsx from 'clsx'

export const LatexInline: FC<ElementProps<'latex-inline'>> = ({
  attributes,
  children,
  element,
}) => {
  const { editor, mode } = useEditor()
  const expression = Node.string(element)
  const selected = useSelected()
  const focused = useFocused()

  // Get the first child (which is the Text node) to check for notes
  // const {
  //   activateNotes,
  //   noteIds,
  //   className: noteClassName
  // } = useNotes(element);

  const setMode = useCallback(
    (newMode: 'read' | 'write') => {
      if (mode === 'read') return

      const path = ReactEditor.findPath(editor, element)
      Transforms.setNodes(editor, { mode: newMode }, { at: path })

      // When switching to edit mode, focus the editor and place the cursor inside the node
      if (newMode === 'write') {
        ReactEditor.focus(editor)
        const nodeEnd = Editor.end(editor, path)
        Transforms.select(editor, nodeEnd)
        // Collapse to the end to place cursor at the end of the content
        Transforms.collapse(editor, { edge: 'end' })
      }
    },
    [editor, element, mode],
  )

  // Watch for "Click Out" events
  useEffect(() => {
    // If we are currently in view mode, do nothing.
    if (element.mode === 'read') return

    // Logic: If the node is currently editing, but:
    // A) The user selected something else (selected === false)
    // B) The user clicked outside the editor (focused === false)
    // Then switch back to view mode.
    if (!selected || !focused) {
      setMode('read')
    }
  }, [selected, focused, element.mode, setMode])

  if (element.mode === 'write' && mode === 'read') {
    return (
      <span
        {...attributes}
        className="
          rounded-md px-1.5 py-0.5 text-sm font-mono 
          dark:bg-zinc-100 dark:text-zinc-800 
          bg-zinc-800 text-zinc-100
          border dark:border-zinc-200 border-zinc-700
        "
      >
        {children}
      </span>
    )
  }

  return (
    <span
      {...attributes}
      // data-note-ids={noteIds?.join(",")}
      contentEditable={false}
      // onClick={() => {
      //   activateNotes();
      // }}
      onDoubleClick={() => setMode('write')}
      className={clsx([
        'inline-block relative',
        //noteClassName,
      ])}
    >
      <span
        dangerouslySetInnerHTML={{
          __html: katex.renderToString(expression, {
            throwOnError: false,
            displayMode: false,
          }),
        }}
      />

      {/* Hidden children are CRUCIAL because
          Slate needs the text in the DOM to maintain the model. */}
      <span className="sr-only pointer-events-none opacity-0">{children}</span>
    </span>
  )
}