mirror of
https://github.com/ianstormtaylor/slate.git
synced 2025-08-31 19:01:54 +02:00
remove keyboard data.*
properties (#1235)
* update examples and walkthroughs * deprecate data keyboard properties * update examples * add is-hotkey to resources doc * udpate docs * update docs * fix split-block test
This commit is contained in:
@@ -49,9 +49,9 @@ class App extends React.Component {
|
||||
this.setState({ state })
|
||||
}
|
||||
|
||||
// Define a new handler which prints the key code that was pressed.
|
||||
// Define a new handler which prints the key that was pressed.
|
||||
onKeyDown = (event, data, change) => {
|
||||
console.log(event.which)
|
||||
console.log(event.key)
|
||||
}
|
||||
|
||||
render() {
|
||||
@@ -85,8 +85,8 @@ class App extends React.Component {
|
||||
}
|
||||
|
||||
onKeyDown = (event, data, change) => {
|
||||
// Return with no changes if it's not the "7" key with shift pressed.
|
||||
if (event.which != 55 || !event.shiftKey) return
|
||||
// Return with no changes if it's not the "&" key.
|
||||
if (event.key != '&') return
|
||||
|
||||
// Prevent the ampersand character from being inserted.
|
||||
event.preventDefault()
|
||||
|
@@ -28,7 +28,7 @@ class App extends React.Component {
|
||||
}
|
||||
|
||||
onKeyDown = (event, data, change) => {
|
||||
if (event.which != 67 || !event.metaKey || !event.altKey) return
|
||||
if (event.key != '`' || !event.metaKey) return
|
||||
event.preventDefault()
|
||||
const isCode = change.state.blocks.some(block => block.type == 'code')
|
||||
|
||||
@@ -72,16 +72,15 @@ class App extends React.Component {
|
||||
if (!event.metaKey) return
|
||||
|
||||
// Decide what to do based on the key code...
|
||||
switch (event.which) {
|
||||
switch (event.key) {
|
||||
// When "B" is pressed, add a "bold" mark to the text.
|
||||
case 66: {
|
||||
case 'b': {
|
||||
event.preventDefault()
|
||||
change.addMark('bold')
|
||||
return true
|
||||
}
|
||||
// When "`" is pressed, keep our existing code block logic.
|
||||
case 67: {
|
||||
if (!event.altKey) return
|
||||
case '`': {
|
||||
const isCode = change.state.blocks.some(block => block.type == 'code')
|
||||
event.preventDefault()
|
||||
change.setBlock(isCode ? 'paragraph' : 'code')
|
||||
@@ -148,14 +147,13 @@ class App extends React.Component {
|
||||
onKeyDown = (event, data, change) => {
|
||||
if (!event.metaKey) return
|
||||
|
||||
switch (event.which) {
|
||||
case 66: {
|
||||
switch (event.key) {
|
||||
case 'b': {
|
||||
event.preventDefault()
|
||||
change.toggleMark('bold')
|
||||
return true
|
||||
}
|
||||
case 67: {
|
||||
if (!event.altKey) return
|
||||
case '`': {
|
||||
const isCode = change.state.blocks.some(block => block.type == 'code')
|
||||
event.preventDefault()
|
||||
state.setBlock(isCode ? 'paragraph' : 'code')
|
||||
|
@@ -23,10 +23,8 @@ class App extends React.Component {
|
||||
}
|
||||
|
||||
onKeyDown = (event, data, change) => {
|
||||
if (event.which != 55 || !event.shiftKey) return
|
||||
|
||||
if (event.key != '&') return
|
||||
event.preventDefault()
|
||||
|
||||
change.insertText('and');
|
||||
return true
|
||||
}
|
||||
@@ -87,10 +85,8 @@ class App extends React.Component {
|
||||
}
|
||||
|
||||
onKeyDown = (event, data, change) => {
|
||||
if (event.which != 55 || !event.shiftKey) return
|
||||
|
||||
if (event.key != '&') return
|
||||
event.preventDefault()
|
||||
|
||||
change.insertText('and')
|
||||
return true
|
||||
}
|
||||
@@ -110,7 +106,7 @@ class App extends React.Component {
|
||||
}
|
||||
```
|
||||
|
||||
Okay, but now we'll need a way for the user to actually turn a block into a code block. So let's change our `onKeyDown` function to add a `⌘-Alt-C` shortcut that does just that:
|
||||
Okay, but now we'll need a way for the user to actually turn a block into a code block. So let's change our `onKeyDown` function to add a `⌘-\`` shortcut that does just that:
|
||||
|
||||
```js
|
||||
function CodeNode(props) {
|
||||
@@ -134,7 +130,7 @@ class App extends React.Component {
|
||||
|
||||
onKeyDown = (event, data, change) => {
|
||||
// Return with no changes if it's not the "`" key with cmd/ctrl pressed.
|
||||
if (event.which != 67 || !event.metaKey || !event.altKey) return
|
||||
if (event.key != '`' || !event.metaKey) return
|
||||
|
||||
// Prevent the "`" from being inserted by default.
|
||||
event.preventDefault()
|
||||
@@ -158,9 +154,9 @@ class App extends React.Component {
|
||||
}
|
||||
```
|
||||
|
||||
Now, if you press `⌘-Alt-C`, the block your cursor is in should turn into a code block! Magic!
|
||||
Now, if you press `⌘-\`` the block your cursor is in should turn into a code block! Magic!
|
||||
|
||||
But we forgot one thing. When you hit `⌘-Alt-C` again, it should change the code block back into a paragraph. To do that, we'll need to add a bit of logic to change the type we set based on whether any of the currently selected blocks are already a code block:
|
||||
But we forgot one thing. When you hit `⌘-\`` again, it should change the code block back into a paragraph. To do that, we'll need to add a bit of logic to change the type we set based on whether any of the currently selected blocks are already a code block:
|
||||
|
||||
```js
|
||||
function CodeNode(props) {
|
||||
@@ -183,7 +179,7 @@ class App extends React.Component {
|
||||
}
|
||||
|
||||
onKeyDown = (event, data, change) => {
|
||||
if (event.which != 67 || !event.metaKey || !event.altKey) return
|
||||
if (event.key != '`' || !event.metaKey) return
|
||||
|
||||
event.preventDefault()
|
||||
|
||||
@@ -209,7 +205,7 @@ class App extends React.Component {
|
||||
}
|
||||
```
|
||||
|
||||
And there you have it! If you press `⌘-Alt-C` while inside a code block, it should turn back into a paragraph!
|
||||
And there you have it! If you press `⌘-\`` while inside a code block, it should turn back into a paragraph!
|
||||
|
||||
<br/>
|
||||
<p align="center"><strong>Next:</strong><br/><a href="./applying-custom-formatting.md">Applying Custom Formatting</a></p>
|
||||
|
@@ -30,7 +30,7 @@ class App extends React.Component {
|
||||
}
|
||||
|
||||
onKeyDown = (event, data, change) => {
|
||||
if (!event.metaKey || event.which != 66) return
|
||||
if (event.key != 'b' || !event.metaKey) return
|
||||
event.preventDefault()
|
||||
change.toggleMark('bold')
|
||||
return true
|
||||
@@ -50,12 +50,12 @@ class App extends React.Component {
|
||||
}
|
||||
```
|
||||
|
||||
Let's write a new function, that takes a set of options: the mark `type` to toggle and the key `code` to press.
|
||||
Let's write a new function, that takes a set of options: the mark `type` to toggle and the `key` to press.
|
||||
|
||||
```js
|
||||
function MarkHotkey(options) {
|
||||
// Grab our options from the ones passed in.
|
||||
const { type, code, isAltKey = false } = options
|
||||
const { type, key } = options
|
||||
}
|
||||
```
|
||||
|
||||
@@ -67,13 +67,13 @@ In this case our plugin object will have one property: a `onKeyDown` handler, wi
|
||||
|
||||
```js
|
||||
function MarkHotkey(options) {
|
||||
const { type, code, isAltKey = false } = options
|
||||
const { type, key } = options
|
||||
|
||||
// Return our "plugin" object, containing the `onKeyDown` handler.
|
||||
return {
|
||||
onKeyDown(event, data, change) {
|
||||
// Check that the key pressed matches our `code` option.
|
||||
if (!event.metaKey || event.which != code || event.altKey != isAltKey) return
|
||||
// Check that the key pressed matches our `key` option.
|
||||
if (!event.metaKey || event.key != key) return
|
||||
|
||||
// Prevent the default characters from being inserted.
|
||||
event.preventDefault()
|
||||
@@ -94,7 +94,7 @@ Now that we have our plugin, let's remove the hard-coded logic from our app, and
|
||||
// Initialize our bold-mark-adding plugin.
|
||||
const boldPlugin = MarkHotkey({
|
||||
type: 'bold',
|
||||
code: 66
|
||||
key: 'b'
|
||||
})
|
||||
|
||||
// Create an array of plugins.
|
||||
@@ -139,11 +139,11 @@ Let's add _italic_, `code`, ~~strikethrough~~ and underline marks:
|
||||
```js
|
||||
// Initialize a plugin for each mark...
|
||||
const plugins = [
|
||||
MarkHotkey({ code: 66, type: 'bold' }),
|
||||
MarkHotkey({ code: 67, type: 'code', isAltKey: true }),
|
||||
MarkHotkey({ code: 73, type: 'italic' }),
|
||||
MarkHotkey({ code: 68, type: 'strikethrough' }),
|
||||
MarkHotkey({ code: 85, type: 'underline' })
|
||||
MarkHotkey({ key: 'b', type: 'bold' }),
|
||||
MarkHotkey({ key: '`', type: 'code' }),
|
||||
MarkHotkey({ key: 'i', type: 'italic' }),
|
||||
MarkHotkey({ key: '~', type: 'strikethrough' }),
|
||||
MarkHotkey({ key: 'u', type: 'underline' })
|
||||
]
|
||||
|
||||
class App extends React.Component {
|
||||
@@ -182,87 +182,6 @@ class App extends React.Component {
|
||||
|
||||
And there you have it! We just added a ton of functionality to the editor with very little work. And we can keep all of our mark hotkey logic tested and isolated in a single place, making maintaining the code easier.
|
||||
|
||||
Of course... now that it's reusable, we could actually make our `MarkHotkey` plugin a little easier to use. What if instead of a `code` argument it took the text of the `key` itself? That would make the calling code a lot clearer, since key codes are really obtuse.
|
||||
|
||||
In fact, unless you have weirdly good keycode knowledge, you probably have no idea what our current hotkeys actually are.
|
||||
|
||||
Let's fix that.
|
||||
|
||||
Using the `keycode` module in npm makes this dead simple.
|
||||
|
||||
First install it:
|
||||
|
||||
```
|
||||
npm install keycode
|
||||
```
|
||||
|
||||
And then we can add it our plugin:
|
||||
|
||||
```js
|
||||
// Import the keycode module.
|
||||
import keycode from `keycode`
|
||||
|
||||
function MarkHotkey(options) {
|
||||
// Change the options to take a `key`.
|
||||
const { type, key, isAltKey = false } = options
|
||||
|
||||
return {
|
||||
onKeyDown(event, data, change) {
|
||||
// Change the comparison to use the key name.
|
||||
if (!event.metaKey || keycode(event.which) != key || event.altKey != isAltKey) return
|
||||
event.preventDefault()
|
||||
change.toggleMark(type)
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
And now we can make our app code much clearer for the next person who reads it:
|
||||
|
||||
```js
|
||||
// Use the much clearer key names instead of key codes!
|
||||
const plugins = [
|
||||
MarkHotkey({ key: 'b', type: 'bold' }),
|
||||
MarkHotkey({ key: 'c', type: 'code', isAltKey: true }),
|
||||
MarkHotkey({ key: 'i', type: 'italic' }),
|
||||
MarkHotkey({ key: 'd', type: 'strikethrough' }),
|
||||
MarkHotkey({ key: 'u', type: 'underline' })
|
||||
]
|
||||
|
||||
class App extends React.Component {
|
||||
|
||||
state = {
|
||||
state: initialState,
|
||||
schema: {
|
||||
marks: {
|
||||
bold: props => <strong>{props.children}</strong>,
|
||||
code: props => <code>{props.children}</code>,
|
||||
italic: props => <em>{props.children}</em>,
|
||||
strikethrough: props => <del>{props.children}</del>,
|
||||
underline: props => <u>{props.children}</u>,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onChange = ({ state }) => {
|
||||
this.setState({ state })
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Editor
|
||||
plugins={plugins}
|
||||
schema={this.state.schema}
|
||||
state={this.state.state}
|
||||
onChange={this.onChange}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
That's why plugins are awesome. They let you get really expressive while also making your codebase easier to manage. And since Slate is built with plugins as a primary consideration, using them is dead simple!
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user