Skip to content

Commit 8a19fee

Browse files
committed
v2
1 parent ce2bd6c commit 8a19fee

105 files changed

Lines changed: 6367 additions & 542 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"slate": minor
3+
---
4+
5+
Add concrete operation type guards and reject unknown operation replay records.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
---
2+
"slate-react": patch
3+
---
4+
5+
Rename React annotation and void helper props for clearer v2 authoring.
6+
7+
**Migration:**
8+
9+
- Use `<Slate annotationStore={store}>` instead of `annotationStores={[store]}`.
10+
- Use `useSlateAnnotations()` and `useSlateAnnotation(id)` inside `Slate` when reading the provider store.
11+
- Use `renderVoid={({ element, path }) => ...}` instead of `target` for void paths.

‎docs/api/operations/README.md‎

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
- [Operation](./operation.md)
77
- Operation subtypes
88
- [Node Operations](README.md#node-operations)
9+
- [Fragment Operations](README.md#fragment-operations)
910
- [Text Operations](README.md#text-operations)
1011
- [Selection Operation](README.md#selection-operation)
1112
- [Base Operation](README.md#base-operation)
@@ -69,6 +70,29 @@ export type NodeOperation =
6970
| SplitNodeOperation
7071
```
7172
73+
### Fragment Operations
74+
75+
Fragment operations replace a child slice under a path and carry the model
76+
selection before and after the replacement. Slate uses this shape for bulk
77+
edits such as paste, where one user action should stay one history and
78+
collaboration operation.
79+
80+
```typescript
81+
type ReplaceFragmentOperation = {
82+
type: 'replace_fragment'
83+
path: Path
84+
children: Node[]
85+
newChildren: Node[]
86+
selection: Range | null
87+
newSelection: Range | null
88+
}
89+
```
90+
91+
Collaboration adapters can replay this operation directly through
92+
`tx.operations.replay(...)`. CRDT adapters that cannot represent subtree
93+
replacement atomically should lower it to their own CRDT edits at the adapter
94+
boundary.
95+
7296
### Text Operations
7397
7498
Text operations operate on `Text` objects only.
@@ -125,5 +149,9 @@ export type SelectionOperation = SetSelectionOperation
125149
The combination of all operation types.
126150
127151
```typescript
128-
export type BaseOperation = NodeOperation | SelectionOperation | TextOperation
152+
export type BaseOperation =
153+
| NodeOperation
154+
| ReplaceFragmentOperation
155+
| SelectionOperation
156+
| TextOperation
129157
```

‎docs/concepts/05-operations.md‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,4 +35,10 @@ editor.update(tx => {
3535

3636
Under the covers Slate converts editor method calls into low-level operations and applies them automatically. You usually think about operations only when implementing collaborative editing, history, or import/export tooling.
3737

38+
Bulk edits can still be one operation. For example, paste can produce a
39+
`replace_fragment` operation that replaces a child slice and moves the model
40+
selection to the end of the inserted fragment. Collaboration adapters can replay
41+
that operation directly, or translate it into their own CRDT representation at
42+
the adapter boundary.
43+
3844
> 🤖 Slate's editing behaviors being defined as operations is what makes things like collaborative editing possible, because each change is easily define-able, apply-able, compose-able and even undo-able!

‎docs/general/docs-proof-map.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ or one-off manual checks.
4545
Use the focused source and docs gates during docs work.
4646

4747
```bash
48-
rg -n "createEditor<|initialValue|renderVoid|useElementSelected|decorationSources|annotationStores|operations\\.replay|editor\\.update|editor\\.read" docs packages
48+
rg -n "createEditor<|initialValue|renderVoid|useElementSelected|decorationSources|annotationStore|operations\\.replay|editor\\.update|editor\\.read" docs packages
4949
```
5050

5151
Use the browser contract registry when a browser-sensitive claim changes.

‎docs/libraries/slate-react/annotations.md‎

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,27 @@ const annotationStore = useSlateAnnotationStore(editor, [
7070
])
7171
```
7272

73+
Pass the store to `Slate` when editor-local annotation UI lives under that
74+
provider. `useSlateAnnotations()` and `useSlateAnnotation(id)` read that store
75+
by default.
76+
77+
```tsx
78+
<Slate annotationStore={annotationStore} editor={editor}>
79+
<Editable renderSegment={renderCommentSegment} />
80+
<CommentsSidebar />
81+
</Slate>
82+
83+
function CommentsSidebar() {
84+
const snapshot = useSlateAnnotations()
85+
86+
return snapshot.allIds.map((id) => {
87+
const comment = snapshot.byId.get(id)
88+
89+
return <CommentThread key={id} comment={comment} />
90+
})
91+
}
92+
```
93+
7394
Release bookmarks when the app removes the annotation.
7495

7596
```tsx

‎docs/libraries/slate-react/editable.md‎

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -69,10 +69,10 @@ Always spread `attributes` on the top-level DOM element and render `children`.
6969
Use `renderVoid` for void elements. A void renderer returns visible content only.
7070

7171
```tsx
72-
const renderVoid = ({ element, target }) => {
72+
const renderVoid = ({ element, path }) => {
7373
switch (element.type) {
7474
case 'image':
75-
return <ImageElement element={element} target={target} />
75+
return <ImageElement element={element} path={path} />
7676
default:
7777
return null
7878
}
@@ -81,11 +81,11 @@ const renderVoid = ({ element, target }) => {
8181

8282
Do not render `children`, hidden text anchors, or shell wrappers in normal void renderers. Slate renders the shell and model anchor for you.
8383

84-
If a void needs selected UI, subscribe by target.
84+
If a void needs selected UI, subscribe by path.
8585

8686
```tsx
87-
const ImageElement = ({ element, target }) => {
88-
const selected = useElementSelected(target)
87+
const ImageElement = ({ element, path }) => {
88+
const selected = useElementSelected(path)
8989

9090
return <img data-selected={selected || undefined} src={element.url} />
9191
}
@@ -137,7 +137,7 @@ const renderText = ({ attributes, children, text }) => {
137137
/>
138138
```
139139

140-
Normal apps should pass `decorationSources` and `annotationStores` to `Slate`, then render projected text through `renderSegment`.
140+
Normal apps should pass `decorationSources` and `annotationStore` to `Slate`, then render projected text through `renderSegment`.
141141

142142
## `placeholder` And `renderPlaceholder`
143143

@@ -181,11 +181,11 @@ Use `onDOMBeforeInput` only when you need the native `InputEvent`. Keep model wr
181181

182182
## Projection Sources
183183

184-
Put decoration sources and annotation stores on `Slate`, not `Editable`. The provider owns editor-level projection sources so the editor surface, toolbar, and overlay UI read the same committed projection.
184+
Put decoration sources and the annotation store on `Slate`, not `Editable`. The provider owns editor-level projection sources so the editor surface, toolbar, and overlay UI read the same committed projection.
185185

186186
```tsx
187187
<Slate
188-
annotationStores={[commentStore]}
188+
annotationStore={commentStore}
189189
decorationSources={[searchSource]}
190190
editor={editor}
191191
>

‎docs/libraries/slate-react/hooks.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,9 @@ Get the current element object inside an element renderer.
7676
Get the current element object, or `null` when the component is not inside an
7777
element renderer.
7878

79-
#### `useElementSelected(target?: Path): boolean`
79+
#### `useElementSelected(path?: Path): boolean`
8080

81-
Subscribe to whether a specific element target intersects the current
81+
Subscribe to whether a specific element path intersects the current
8282
selection. Use this only when the component actually draws selected UI.
8383

8484
#### `useNodeSelector<T>(selector, equalityFn?, options?): T`

‎docs/libraries/slate-react/react-editor.md‎

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,12 @@ Find a Slate range from a DOM range or selection.
103103

104104
#### `editor.dom.clipboard.insertData(data: DataTransfer): void`
105105

106-
Insert data from a `DataTransfer` into the editor. This tries Slate fragment
107-
data first, then plain text.
106+
Insert data from a `DataTransfer` into the editor.
107+
108+
Slate runs `dom.clipboard.insertData` capability handlers first. A handler that
109+
returns `true` stops the default import path. When no handler claims the data,
110+
Slate tries an internal Slate fragment for the editor's configured
111+
`clipboardFormatKey`, then plain text.
108112

109113
#### `editor.dom.clipboard.insertFragmentData(data: DataTransfer): boolean`
110114

@@ -119,3 +123,8 @@ was inserted.
119123
#### `editor.dom.clipboard.writeSelection(data: Pick<DataTransfer, 'getData' | 'setData'>): void`
120124

121125
Write the current selection to a `DataTransfer`.
126+
127+
Slate writes plain text, HTML, and an internal Slate fragment payload. The
128+
fragment payload uses `application/${clipboardFormatKey}` and the HTML fallback
129+
is tagged with the same key, so differently configured editors do not blindly
130+
import each other's internal JSON.

‎docs/libraries/slate-react/slate.md‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
```typescript
1515
type SlateProps = {
16-
annotationStores?: readonly SlateAnnotationStore[] | null
16+
annotationStore?: SlateAnnotationStore | null
1717
children: React.ReactNode
1818
decorationSources?: readonly SlateDecorationSource[] | null
1919
editor: ReactEditor
@@ -146,9 +146,9 @@ const searchSource = useMemo(
146146

147147
Prefer provider-owned `decorationSources` so every `Editable` and overlay UI reads from the same projection source.
148148

149-
### `annotationStores`
149+
### `annotationStore`
150150

151-
Annotation stores publish anchor-backed annotations to text rendering and annotation UI hooks.
151+
The annotation store publishes anchor-backed annotations to text rendering and annotation UI hooks.
152152

153153
```tsx
154154
const annotations = comments.map((comment) => ({
@@ -163,8 +163,8 @@ const annotations = comments.map((comment) => ({
163163

164164
const annotationStore = useSlateAnnotationStore(editor, annotations)
165165

166-
<Slate annotationStores={[annotationStore]} editor={editor}>
166+
<Slate annotationStore={annotationStore} editor={editor}>
167167
<Editable renderSegment={renderCommentSegment} />
168-
<CommentsSidebar store={annotationStore} />
168+
<CommentsSidebar />
169169
</Slate>
170170
```

0 commit comments

Comments
 (0)