simian 0.2.0

A command-line tool for exploring and implementing Machine Learning algorithms in Rust.
import clsx from 'clsx'
import { useMemo } from 'react'
import { Editor, Node, Transforms } from 'slate'
import { ReactEditor } from 'slate-react'

import {
  ghDarkDimmed,
  ghDarkHighContrast,
} from '@/ui/editor/addon/code-block/utils/highlighter'
import { contextualize } from '@/ui/editor/context'
import { ElementProps } from '@/ui/editor/types'
import { useTheme } from 'next-themes'

import { useEquationNumber } from './context'
import { renderKaTeX } from './utils'
import { Block } from '../../block'

export const LatexBlockElement = contextualize<ElementProps<'latex-block'>>()(
  ['editor', 'mode'],
  ({ attributes, children, editor, element, mode }) => {
    const num = useEquationNumber(element.id)
    const { resolvedTheme: themeMode } = useTheme()
    const text = Node.string(element)

    const [fgColor, bgColor] = useMemo(() => {
      if (themeMode === 'dark') {
        return [
          ghDarkDimmed.colors?.['editor.foreground'],
          ghDarkDimmed.colors?.['editor.background'],
        ]
      }

      return [
        ghDarkHighContrast.colors?.['editor.foreground'],
        ghDarkHighContrast.colors?.['editor.background'],
      ]
    }, [themeMode])

    const handleMouseDown = (e: React.MouseEvent) => {
      if (mode === 'read') return
      // detail === 2 means this is the second click in a short duration (Double Click)
      if (e.detail === 2) {
        e.preventDefault() // Prevent Slate from handling the double-click selection

        const path = ReactEditor.findPath(editor, element)

        Transforms.setNodes(editor, { mode: 'write' }, { at: path })

        // We need a slight delay to ensure the DOM has switched to edit mode
        // before we try to focus the end of the text.
        setTimeout(() => {
          ReactEditor.focus(editor)
          Transforms.select(editor, Editor.end(editor, path))
        }, 0)
      }
    }

    return (
      <Block element={element} {...attributes}>
        {element.mode == 'write' ? (
          <div
            className={clsx(['p-3 mb-6 rounded font-mono text-sm'])}
            style={{
              color: fgColor,
              backgroundColor: bgColor,
            }}
          >
            {children}
          </div>
        ) : (
          <div
            className="rounded p-3 overflow-x-scroll"
            onMouseDown={handleMouseDown}
            contentEditable={false}
          >
            <div
              dangerouslySetInnerHTML={{
                __html: renderKaTeX(text, num),
              }}
            />

            {/* 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>
          </div>
        )}
      </Block>
    )
  },
)