ianstormtaylor / slate

A completely customizable framework for building rich text editors. (Currently in beta.)
http://slatejs.org
MIT License
30.01k stars 3.26k forks source link

How to get a "normally" working editor? #5671

Open ecosta1020 opened 5 months ago

ecosta1020 commented 5 months ago

Hi, I'm new to slate (know some JS, and a bit of TS), and I've been struggling to get it to behave as the regular editor I think we're all used to.

Whenever I press enter, say in the rich-text example, a new paragraph is created. But I'd normally expect that to simply insert a line-break instead, though, and only if enter is pressed twice such that there are two in a row, should the interface be allowed to transform these nodes by means of actually removing both line-breaks and letting me enter into a fresh <p>. Or is it that I'm missing something really obvious here?

By perusing the source code, the closest I could see is ZeroWidthString from within packages/slate-react/src/components/string.tsx, but this module is not reachable from user space. Before that, I saw Editor.insertSoftBreak and Editor.insertBreak, but both have the same effect of inserting a paragraph, so I'm a bit lost.

Can somebody give me a clue? maybe even including some pseudo-code at least, on how to intercept the enter key in a non-hacky way (i.e: if (event.keyCode == 13) ...) from within the rich-text examples onKeyDown hook? Though I'm tempted to think there's something I'm not understanding properly and that my approach might be wrong altogether, so setting me on track would be same as appreciated.

And as I'm here, would also like to take the opportunity to ask where do deleteWordBackward, deleteWordForward, insertLineBreak, etc. come from?

These are in a big switch on export const Editable = (props: EditableProps) at packages/slate-react/src/components/editable.tsx, but I could only trace these back to the type variable, which appears for the first time at the line 540:

const isCompositionChange =
  type === 'insertCompositionText' || type === 'deleteCompositionText'

So even if these are React constants, the line above got me puzzled because type seems to come from nowhere.

Thanks,

mitchellbusby commented 4 months ago

Hi @ecosta1020 I can't answer all of your questions, but I can help with hopefully making sense of the Slate APIs for you. The functions like Editor.insertSoftBreak and Editor.insertBreak as you mentioned are what Slate calls "commands". If you look at the definition of insertBreak in packages/slate/src/interfaces/editor.ts, you'll see that under the hood it actually delegates out to editor.insertBreak (emphasis here on lowercase editor).

You are able to override the functions on your instance of editor that you get from createEditor to match your expectations of what should happen given particular actions.

You can alternatively, as you said, use the onKeyDown React event handler and check for the enter key being pressed - in that case be sure to event.preventDefault() from your event handler so Slate doesn't run Editor.insertBreak for you. This is the approach recommended in "adding event handlers" in the Slate docs.

One note I'd make is that there's no "normally" working editor and so there will be things you have to override to make intuitive for your use cases 😅 Slate's built in behaviours are inspired by the editors listed in the intro doc. There is no "soft break" built in to Slate, you need to define what it is and how it's represented yourself.

Finally, on your question about the type variable - I believe that is event.inputType and comes from the beforeinput event which Slate also listens to as well as keydown events. As I mentioned above - beforeinput events will be discarded if you event.preventDefault in your keydown hook. They're just "richer" events than keydown events (they indicate more about the user's intent) so Slate uses them to determine which command to call by default.

ecosta1020 commented 4 months ago

Hi Mitchell,

Thanks a lot for taking the time to answer. Unfortunately as I posted my question decided to spend some time looking at the issues just to notice several open bugs nobody seems to be taking care of.

It's a shame slate feels so abandoware because I really liked it and was getting used to it's internals. I also ditched react for this same project I was using the editor with, as it was creating much heavier pages than I was willing to accept, so I just moved to lexical which I can use with vanilla/ts.

Thanks a lot again.