or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

core-components.mdindex.mdperformance-optimization.mdplugin-system.mdreact-hooks.mdrender-functions.md

plugin-system.mddocs/

0

# Plugin System

1

2

React-specific plugin functionality that integrates Slate with React's lifecycle and event system. The plugin system enables Slate editors to work seamlessly with React components and provides React-specific enhancements.

3

4

## Capabilities

5

6

### withReact Plugin

7

8

The `withReact` function enhances a Slate editor with React-specific behaviors, DOM handling, and integration with React's component lifecycle.

9

10

```typescript { .api }

11

/**

12

* Adds React and DOM specific behaviors to the editor

13

* @param editor - Base editor to enhance

14

* @param clipboardFormatKey - Key for clipboard data format (default: 'x-slate-fragment')

15

* @returns Enhanced editor with React capabilities

16

*/

17

function withReact<T extends BaseEditor>(

18

editor: T,

19

clipboardFormatKey?: string

20

): T & ReactEditor;

21

```

22

23

**Usage Example:**

24

25

```typescript

26

import React, { useMemo } from 'react';

27

import { createEditor } from 'slate';

28

import { withReact } from 'slate-react';

29

30

const MyEditor = () => {

31

// Apply React plugin to base editor

32

const editor = useMemo(() => withReact(createEditor()), []);

33

34

// Editor now has React-specific capabilities

35

return (

36

<Slate editor={editor} initialValue={initialValue}>

37

<Editable />

38

</Slate>

39

);

40

};

41

42

// With custom clipboard format

43

const EditorWithCustomClipboard = () => {

44

const editor = useMemo(() =>

45

withReact(createEditor(), 'my-custom-format'),

46

[]

47

);

48

49

return (

50

<Slate editor={editor} initialValue={initialValue}>

51

<Editable />

52

</Slate>

53

);

54

};

55

```

56

57

### ReactEditor Interface

58

59

The `ReactEditor` interface extends `DOMEditor` from slate-dom and provides React-specific editor methods and capabilities.

60

61

```typescript { .api }

62

/**

63

* React and DOM-specific editor interface

64

* Extends DOMEditor with React-specific functionality

65

*/

66

interface ReactEditor extends DOMEditor {

67

/**

68

* Get the chunk size for performance optimization

69

* @param node - Ancestor node to get chunk size for

70

* @returns Chunk size or null if not chunked

71

*/

72

getChunkSize(node: Ancestor): number | null;

73

}

74

```

75

76

The ReactEditor interface inherits all methods from DOMEditor, including:

77

78

- DOM manipulation methods

79

- Event handling utilities

80

- Selection and range operations

81

- Node-to-DOM mapping functions

82

83

**Usage Example:**

84

85

```typescript

86

import React from 'react';

87

import { ReactEditor } from 'slate-react';

88

import { useSlateStatic } from 'slate-react';

89

90

const CustomComponent = () => {

91

const editor = useSlateStatic() as ReactEditor;

92

93

const handleClick = (element: Element) => {

94

// Use ReactEditor-specific methods

95

const domElement = ReactEditor.toDOMNode(editor, element);

96

const slateNode = ReactEditor.toSlateNode(editor, domElement);

97

98

// Check chunk size for performance optimization

99

const chunkSize = editor.getChunkSize(element);

100

if (chunkSize) {

101

console.log(`Element is chunked with size: ${chunkSize}`);

102

}

103

};

104

105

return (

106

<button onClick={() => handleClick(someElement)}>

107

Process Element

108

</button>

109

);

110

};

111

```

112

113

## Plugin Features

114

115

### React Lifecycle Integration

116

117

The `withReact` plugin integrates Slate with React's component lifecycle:

118

119

- **Component Updates**: Synchronizes editor state with React component updates

120

- **Event Handling**: Integrates DOM events with React's synthetic event system

121

- **Context Propagation**: Ensures proper context propagation throughout the editor tree

122

- **Performance Optimization**: Implements React-specific performance optimizations

123

124

### DOM Integration

125

126

React-specific DOM handling and integration:

127

128

```typescript

129

// DOM element mapping (inherited from DOMEditor)

130

const domElement = ReactEditor.toDOMNode(editor, slateNode);

131

const slateNode = ReactEditor.toSlateNode(editor, domElement);

132

133

// Range operations

134

const domRange = ReactEditor.toDOMRange(editor, slateRange);

135

const slateRange = ReactEditor.toSlateRange(editor, domRange);

136

137

// Selection handling

138

const domSelection = ReactEditor.toDOMSelection(editor, slateSelection);

139

const slateSelection = ReactEditor.toSlateSelection(editor, domSelection);

140

```

141

142

### Clipboard Integration

143

144

Enhanced clipboard functionality with React-specific handling:

145

146

```typescript

147

import { withReact } from 'slate-react';

148

149

// Default clipboard format

150

const editor = withReact(createEditor()); // Uses 'x-slate-fragment'

151

152

// Custom clipboard format

153

const customEditor = withReact(createEditor(), 'my-app-fragment');

154

```

155

156

### Event System Integration

157

158

The plugin integrates with React's event system for:

159

160

- **Keyboard Events**: Handles keyboard shortcuts and input

161

- **Mouse Events**: Manages selection and interaction

162

- **Focus Events**: Tracks editor focus state

163

- **Composition Events**: Handles IME input and composition

164

165

**Usage Example:**

166

167

```typescript

168

import React from 'react';

169

import { Editable } from 'slate-react';

170

171

const EditorWithEvents = () => {

172

return (

173

<Editable

174

onKeyDown={(event) => {

175

// React synthetic event integration

176

if (event.key === 'Enter') {

177

event.preventDefault();

178

// Handle custom enter behavior

179

}

180

}}

181

onDOMBeforeInput={(event) => {

182

// Native DOM event integration

183

console.log('Native input event:', event);

184

}}

185

/>

186

);

187

};

188

```

189

190

## Advanced Plugin Patterns

191

192

### Combining Multiple Plugins

193

194

The `withReact` plugin can be combined with other Slate plugins:

195

196

```typescript

197

import React, { useMemo } from 'react';

198

import { createEditor } from 'slate';

199

import { withReact } from 'slate-react';

200

import { withHistory } from 'slate-history';

201

202

const EditorWithPlugins = () => {

203

const editor = useMemo(() => {

204

// Apply plugins in correct order

205

return withReact(withHistory(createEditor()));

206

}, []);

207

208

return (

209

<Slate editor={editor} initialValue={initialValue}>

210

<Editable />

211

</Slate>

212

);

213

};

214

```

215

216

### Custom Plugin Creation

217

218

You can create custom plugins that work with the React plugin:

219

220

```typescript

221

import { Editor, Transforms } from 'slate';

222

import { ReactEditor } from 'slate-react';

223

224

// Custom plugin that adds React-aware functionality

225

const withCustomReactFeature = <T extends ReactEditor>(editor: T): T => {

226

const { insertText } = editor;

227

228

editor.insertText = (text: string) => {

229

// Custom logic that works with React

230

if (text === '@') {

231

// Trigger React component for mentions

232

Transforms.insertNodes(editor, {

233

type: 'mention',

234

character: '@',

235

children: [{ text: '' }]

236

});

237

return;

238

}

239

240

insertText(text);

241

};

242

243

return editor;

244

};

245

246

// Usage with React plugin

247

const editor = useMemo(() =>

248

withCustomReactFeature(withReact(createEditor())),

249

[]

250

);

251

```

252

253

### TypeScript Integration

254

255

Proper TypeScript integration with custom editor types:

256

257

```typescript

258

import { BaseEditor } from 'slate';

259

import { ReactEditor } from 'slate-react';

260

import { HistoryEditor } from 'slate-history';

261

262

// Extend editor type for TypeScript

263

type CustomEditor = BaseEditor & ReactEditor & HistoryEditor & {

264

customMethod(): void;

265

};

266

267

// Declare module for Slate TypeScript integration

268

declare module 'slate' {

269

interface CustomTypes {

270

Editor: CustomEditor;

271

Element: CustomElement;

272

Text: CustomText;

273

}

274

}

275

276

const withCustom = <T extends ReactEditor>(editor: T): T & { customMethod(): void } => {

277

editor.customMethod = () => {

278

console.log('Custom method called');

279

};

280

281

return editor as T & { customMethod(): void };

282

};

283

```

284

285

## Plugin System Best Practices

286

287

### Plugin Order

288

289

Apply plugins in the correct order for optimal functionality:

290

291

```typescript

292

// Recommended plugin order:

293

// 1. Core functionality plugins (history, etc.)

294

// 2. Custom business logic plugins

295

// 3. React plugin last

296

const editor = withReact(

297

withCustomLogic(

298

withHistory(

299

createEditor()

300

)

301

)

302

);

303

```

304

305

### Error Handling

306

307

Implement proper error handling in custom plugins:

308

309

```typescript

310

const withErrorHandling = <T extends ReactEditor>(editor: T): T => {

311

const { insertNode } = editor;

312

313

editor.insertNode = (node) => {

314

try {

315

insertNode(node);

316

} catch (error) {

317

console.error('Error inserting node:', error);

318

// Fallback behavior

319

}

320

};

321

322

return editor;

323

};

324

```

325

326

### Performance Considerations

327

328

Consider performance implications when creating custom plugins:

329

330

```typescript

331

const withPerformantPlugin = <T extends ReactEditor>(editor: T): T => {

332

// Cache expensive operations

333

const cache = new WeakMap();

334

335

editor.customOperation = (node) => {

336

if (cache.has(node)) {

337

return cache.get(node);

338

}

339

340

const result = expensiveOperation(node);

341

cache.set(node, result);

342

return result;

343

};

344

345

return editor;

346

};

347

```