uiwjs / react-codemirror

CodeMirror 6 component for React. @codemirror https://uiwjs.github.io/react-codemirror/
https://uiwjs.github.io/react-codemirror/
MIT License
1.63k stars 129 forks source link

onDeletion event ? #625

Open Jules-Pinsard opened 8 months ago

Jules-Pinsard commented 8 months ago

Hi !

I'm trying to create a "bookmark" feature for my app but i'm stuck with event handling. The feature should work this way : -When the user type "#" in the beginning of the line it implement the useReducer state with an object (with the content of this line and the position in the editor) -A button is created by rerendering with an action of focus on the specific line when the user click on it -The position stored in the object should evolve as the editor is modified -The object should be deleted if the line is deleted

I'm struggling to find an event to listen for deletion of content (in order to update the position if it's affected)

Thanks for your help 😄

import "./App.css";
import CodeMirror from "@uiw/react-codemirror";
import { useReducer, useRef } from "react";
import SceneList from "./components/SceneList";
import CharacterList from "./components/CharacterList";

const initalState = {
  title: "En attendant Godot",
  value:
    "#Scène 1\n@Monsieur A\nBonjour madame.\n@Madame B\nBonjour à vous monsieur !",
  scenes: [{ name: "Scène 1", position: "0" }],
  characters: ["@Monsieur A"],
};

function App() {
  const CodeMirrorRef = useRef();

  function reducer(state, action) {
    const view = CodeMirrorRef.current.view;
    const currPostion = view.state.selection.main.head;
    state = {...state, scenes: state.scenes.map((scene) => {
       scene.position = scene.position > currPostion ? scene.position + 1 : scene.position
       return scene
    })}
    switch (action.type) {
      case "newEntry":
        if (action.payload[action.payload.length - 1] === "\n") {
          const array = action.payload.split("\n");
          const lastValue = array[array.length - 2];
          if (lastValue[0] === "#") {
            return {
              ...state,
              scenes: [
                ...state.scenes,
                { name: lastValue, position: currPostion - 1 },
              ],
            };
          }
          if (lastValue[0] === "@") {
            return { ...state, characters: [...state.characters, lastValue] };
          }
        }
        return state;

      case "focusPosition":
        view.dispatch({ selection: { anchor: action.payload } });
        view.focus();
        return state;

      case "insertCharacter":
        view.dispatch({
          changes: { from: currPostion, insert: action.payload },
          selection: { anchor: currPostion + action.payload.length + 1 },
          scrollIntoView: true,
        });
        return state;

      default:
        throw new Error("Undefined action");
    }
  }
  const [{ title, value, scenes, characters }, dispatch] = useReducer(
    reducer,
    initalState
  );

  return (
    <>
      <h1>{title}</h1>
      <CodeMirror
        ref={CodeMirrorRef}
        value={value}
        height="200px"
        onChange={(e, data) => {
          console.log(data);
          dispatch({ type: "newEntry", payload: e})}
        }
      />
      <SceneList scenes={scenes} dispatch={dispatch} />
      <CharacterList characters={characters} dispatch={dispatch} />
    </>
  );
}

export default App;
jaywcjlove commented 8 months ago

@Jules-Pinsard Maybe this plugin can solve your problem

https://uiwjs.github.io/react-codemirror/#/extensions/events

const extension = events.content({
  input: (evn) => {
    console.log('input');
  }
});

<CodeMirror value="console.log('hello world!');" height="200px" extensions={[extension]} />
Jules-Pinsard commented 8 months ago

Thanks for your answer 😃 That's interesting! Is there a list of events handled by this extensions ? In the documentation I only found "blur" "focus" and "scroll"

jaywcjlove commented 7 months ago
image

@Jules-Pinsard This is a dom event, which supports a lot of event bindings. Welcome to help update the documentation.