Socket
Socket
Sign inDemoInstall

@codemirror-toolkit/react

Package Overview
Dependencies
13
Maintainers
1
Versions
11
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

    @codemirror-toolkit/react

A small and flexible solution for binding CodeMirror 6 to React


Version published
Maintainers
1
Created

Readme

Source

@codemirror-toolkit/react

npm (scoped) npm bundle size (scoped) GitHub Workflow Status (with branch) Codecov branch

A small and flexible solution for binding CodeMirror 6 to React.

Instead of providing component with a big amount of props and un-tree-shakable dependencies (like @uiw/react-codemirror), it offers a set of hooks and an optional context provider that can be used to better integrate with your components.

Examples

See codemirror-toolkit#examples.

Installation

# npm
npm install @codemirror-toolkit/react

# Yarn
yarn add @codemirror-toolkit/react

Note that, you also need to install the peer dependencies @codemirror/state and @codemirror/view if you don't use the official all-in-one package codemirror or your package manager doesn't do it automatically.

Usage

First create an instance with configuration as an object or a factory function:

import { createCodeMirror } from '@codemirror-toolkit/react'

const codeMirror = createCodeMirror<HTMLDivElement>((prevState) => ({
  doc: prevState?.doc ?? 'Hello World!',
  // ...otherConfig,
}))

// if you want to use them in other files
export const { useViewEffect, useContainerRef /* ... */ } = codeMirror

Then bind your components with the hooks:

function Editor() {
  const containerRef = useContainerRef()
  return <div ref={containerRef} />
}

function App() {
  const [showEditor, setShowEditor] = useState(true)
  const [lastInput, setLastInput] = useState('')
  useViewEffect((view) => {
    console.log('EditorView is created')
    return () => {
      console.log('EditorView is destroyed')
      // expect(view.dom.parentElement).toBeNull()
      setLastInput(view.state.doc.toString())
    }
  })
  return (
    <>
      <button onClick={() => setShowEditor(!showEditor)}>
        {showEditor ? 'Destroy' : 'Create'} Editor
      </button>
      {showEditor ? (
        <Editor />
      ) : (
        <div>
          <p>Editor destroyed</p>
          <p>Last input: {lastInput}</p>
        </div>
      )}
    </>
  )
}

:warning: An instance of EditorView will be created only when a DOM node is assigned to containerRef.current, and will be destroyed only when containerRef.current is set back to null.

With Context Provider

All the functions and hooks created with createCodeMirror don't require a context provider to use in different components, but in some cases you may want to instantiate EditorView with props from a component. In this case, you can use createCodeMirrorWithContext to create an instance within a context:

import { createCodeMirrorWithContext } from '@codemirror-toolkit/react'

const {
  Provider: CodeMirrorProvider,
  useView,
  useContainerRef,
  // ...
} = createCodeMirrorWithContext<HTMLDivElement>('CodeMirrorContext')

function MenuBar() {
  const view = useView()
  // ...
}

function Editor() {
  const containerRef = useContainerRef()
  return <div ref={containerRef} />
}

function App({ initialInput }: { initialInput: string }) {
  return (
    <CodeMirrorProvider
      config={{
        doc: initialInput,
        // ...otherConfig,
      }}>
      <MenuBar />
      <Editor />
    </CodeMirrorProvider>
  )
}

API

🚧 Documentation is WIP.

There are only two functions exported: createCodeMirror and createCodeMirrorWithContext.

Common Types

import type { EditorState } from '@codemirror/state'
import type { EditorView, EditorViewConfig } from '@codemirror/view'
import type { EffectCallback, MutableRefObject } from 'react'

type EditorViewConfigWithoutParentElement = Omit<EditorViewConfig, 'parent'>
interface CodeMirrorConfig extends EditorViewConfigWithoutParentElement {}

type CodeMirrorConfigCreator = (prevState: EditorState | undefined) => CodeMirrorConfig
type ProvidedCodeMirrorConfig = CodeMirrorConfig | CodeMirrorConfigCreator

type GetView = () => EditorView | null
type UseViewHook = () => EditorView | null

type ViewEffectCleanup = ReturnType<EffectCallback>
type ViewEffectSetup = (view: EditorView) => ViewEffectCleanup
type UseViewEffectHook = (setup: ViewEffectSetup) => void

type ViewDispath = typeof EditorView.prototype.dispatch
type UseViewDispatchHook = () => ViewDispath

type ContainerRef<ContainerElement extends Element = Element> =
  MutableRefObject<ContainerElement | null>
type UseContainerRefHook<ContainerElement extends Element = Element> =
  () => ContainerRef<ContainerElement>

interface CodeMirror<ContainerElement extends Element = Element> {
  getView: GetView
  useView: UseViewHook
  useViewEffect: UseViewEffectHook
  useViewDispatch: UseViewDispatchHook
  useContainerRef: UseContainerRefHook<ContainerElement>
}

createCodeMirror

function createCodeMirror<ContainerElement extends Element>(
  config?: ProvidedCodeMirrorConfig,
): CodeMirror<ContainerElement>

createCodeMirrorWithContext

import type { FunctionComponent, PropsWithChildren } from 'react'

interface CodeMirrorProps {
  config?: ProvidedCodeMirrorConfig
}
interface CodeMirrorProviderProps extends PropsWithChildren<CodeMirrorProps> {}
interface CodeMirrorProvider extends FunctionComponent<CodeMirrorProviderProps> {}

type UseCodeMirrorContextHook<ContainerElement extends Element = Element> =
  () => CodeMirror<ContainerElement>

type UseGetViewHook = () => GetView

interface CodeMirrorWithContext<ContainerElement extends Element = Element> {
  Provider: CodeMirrorProvider
  useContext: UseCodeMirrorContextHook<ContainerElement>
  useGetView: UseGetViewHook
  useView: UseViewHook
  useViewEffect: UseViewEffectHook
  useViewDispatch: UseViewDispatchHook
  useContainerRef: UseContainerRefHook<ContainerElement>
}

function createCodeMirrorWithContext<ContainerElement extends Element>(
  displayName?: string | false,
): CodeMirrorWithContext<ContainerElement>

License

MIT License @ 2022-Present Xuanbo Cheng

Keywords

FAQs

Last updated on 18 Dec 2023

Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc