@portabletext/editor 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +3 -0
- package/lib/index.d.mts +911 -0
- package/lib/index.d.ts +911 -0
- package/lib/index.esm.js +4896 -0
- package/lib/index.esm.js.map +1 -0
- package/lib/index.js +4874 -0
- package/lib/index.js.map +1 -0
- package/lib/index.mjs +4896 -0
- package/lib/index.mjs.map +1 -0
- package/package.json +119 -0
- package/src/editor/Editable.tsx +683 -0
- package/src/editor/PortableTextEditor.tsx +308 -0
- package/src/editor/__tests__/PortableTextEditor.test.tsx +386 -0
- package/src/editor/__tests__/PortableTextEditorTester.tsx +116 -0
- package/src/editor/__tests__/RangeDecorations.test.tsx +115 -0
- package/src/editor/__tests__/handleClick.test.tsx +218 -0
- package/src/editor/__tests__/pteWarningsSelfSolving.test.tsx +389 -0
- package/src/editor/__tests__/utils.ts +39 -0
- package/src/editor/components/DraggableBlock.tsx +287 -0
- package/src/editor/components/Element.tsx +279 -0
- package/src/editor/components/Leaf.tsx +288 -0
- package/src/editor/components/SlateContainer.tsx +81 -0
- package/src/editor/components/Synchronizer.tsx +190 -0
- package/src/editor/hooks/usePortableTextEditor.ts +23 -0
- package/src/editor/hooks/usePortableTextEditorKeyGenerator.ts +24 -0
- package/src/editor/hooks/usePortableTextEditorSelection.ts +22 -0
- package/src/editor/hooks/usePortableTextEditorValue.ts +16 -0
- package/src/editor/hooks/usePortableTextReadOnly.ts +20 -0
- package/src/editor/hooks/useSyncValue.test.tsx +125 -0
- package/src/editor/hooks/useSyncValue.ts +372 -0
- package/src/editor/nodes/DefaultAnnotation.tsx +16 -0
- package/src/editor/nodes/DefaultObject.tsx +15 -0
- package/src/editor/nodes/index.ts +189 -0
- package/src/editor/plugins/__tests__/withEditableAPIDelete.test.tsx +244 -0
- package/src/editor/plugins/__tests__/withEditableAPIGetFragment.test.tsx +142 -0
- package/src/editor/plugins/__tests__/withEditableAPIInsert.test.tsx +346 -0
- package/src/editor/plugins/__tests__/withEditableAPISelectionsOverlapping.test.tsx +162 -0
- package/src/editor/plugins/__tests__/withHotkeys.test.tsx +212 -0
- package/src/editor/plugins/__tests__/withInsertBreak.test.tsx +204 -0
- package/src/editor/plugins/__tests__/withPlaceholderBlock.test.tsx +133 -0
- package/src/editor/plugins/__tests__/withPortableTextLists.test.tsx +65 -0
- package/src/editor/plugins/__tests__/withPortableTextMarkModel.test.tsx +1377 -0
- package/src/editor/plugins/__tests__/withPortableTextSelections.test.tsx +91 -0
- package/src/editor/plugins/__tests__/withUndoRedo.test.tsx +115 -0
- package/src/editor/plugins/createWithEditableAPI.ts +573 -0
- package/src/editor/plugins/createWithHotKeys.ts +304 -0
- package/src/editor/plugins/createWithInsertBreak.ts +45 -0
- package/src/editor/plugins/createWithInsertData.ts +359 -0
- package/src/editor/plugins/createWithMaxBlocks.ts +24 -0
- package/src/editor/plugins/createWithObjectKeys.ts +63 -0
- package/src/editor/plugins/createWithPatches.ts +274 -0
- package/src/editor/plugins/createWithPlaceholderBlock.ts +36 -0
- package/src/editor/plugins/createWithPortableTextBlockStyle.ts +91 -0
- package/src/editor/plugins/createWithPortableTextLists.ts +160 -0
- package/src/editor/plugins/createWithPortableTextMarkModel.ts +441 -0
- package/src/editor/plugins/createWithPortableTextSelections.ts +65 -0
- package/src/editor/plugins/createWithSchemaTypes.ts +76 -0
- package/src/editor/plugins/createWithUndoRedo.ts +494 -0
- package/src/editor/plugins/createWithUtils.ts +81 -0
- package/src/editor/plugins/index.ts +155 -0
- package/src/index.ts +11 -0
- package/src/patch/PatchEvent.ts +33 -0
- package/src/patch/applyPatch.ts +29 -0
- package/src/patch/array.ts +89 -0
- package/src/patch/arrayInsert.ts +27 -0
- package/src/patch/object.ts +39 -0
- package/src/patch/patches.ts +53 -0
- package/src/patch/primitive.ts +43 -0
- package/src/patch/string.ts +51 -0
- package/src/types/editor.ts +576 -0
- package/src/types/options.ts +17 -0
- package/src/types/patch.ts +65 -0
- package/src/types/slate.ts +25 -0
- package/src/utils/__tests__/dmpToOperations.test.ts +181 -0
- package/src/utils/__tests__/operationToPatches.test.ts +421 -0
- package/src/utils/__tests__/patchToOperations.test.ts +293 -0
- package/src/utils/__tests__/ranges.test.ts +18 -0
- package/src/utils/__tests__/valueNormalization.test.tsx +62 -0
- package/src/utils/__tests__/values.test.ts +253 -0
- package/src/utils/applyPatch.ts +407 -0
- package/src/utils/bufferUntil.ts +15 -0
- package/src/utils/debug.ts +12 -0
- package/src/utils/getPortableTextMemberSchemaTypes.ts +100 -0
- package/src/utils/operationToPatches.ts +357 -0
- package/src/utils/patches.ts +36 -0
- package/src/utils/paths.ts +60 -0
- package/src/utils/ranges.ts +77 -0
- package/src/utils/schema.ts +8 -0
- package/src/utils/selection.ts +65 -0
- package/src/utils/ucs2Indices.ts +67 -0
- package/src/utils/validateValue.ts +394 -0
- package/src/utils/values.ts +208 -0
- package/src/utils/weakMaps.ts +24 -0
- package/src/utils/withChanges.ts +25 -0
- package/src/utils/withPreserveKeys.ts +14 -0
- package/src/utils/withoutPatching.ts +14 -0
|
@@ -0,0 +1,576 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type ArraySchemaType,
|
|
3
|
+
type BlockDecoratorDefinition,
|
|
4
|
+
type BlockListDefinition,
|
|
5
|
+
type BlockSchemaType,
|
|
6
|
+
type BlockStyleDefinition,
|
|
7
|
+
type ObjectSchemaType,
|
|
8
|
+
type Path,
|
|
9
|
+
type PortableTextBlock,
|
|
10
|
+
type PortableTextChild,
|
|
11
|
+
type PortableTextListBlock,
|
|
12
|
+
type PortableTextObject,
|
|
13
|
+
type PortableTextSpan,
|
|
14
|
+
type PortableTextTextBlock,
|
|
15
|
+
type SpanSchemaType,
|
|
16
|
+
type TypedObject,
|
|
17
|
+
} from '@sanity/types'
|
|
18
|
+
import {
|
|
19
|
+
type ClipboardEvent,
|
|
20
|
+
type FocusEvent,
|
|
21
|
+
type KeyboardEvent,
|
|
22
|
+
type PropsWithChildren,
|
|
23
|
+
type ReactElement,
|
|
24
|
+
type RefObject,
|
|
25
|
+
} from 'react'
|
|
26
|
+
import {type Observable, type Subject} from 'rxjs'
|
|
27
|
+
import {type Descendant, type Node as SlateNode, type Operation as SlateOperation} from 'slate'
|
|
28
|
+
import {type ReactEditor} from 'slate-react'
|
|
29
|
+
import {type DOMNode} from 'slate-react/dist/utils/dom'
|
|
30
|
+
|
|
31
|
+
import {type PortableTextEditableProps} from '../editor/Editable'
|
|
32
|
+
import {type PortableTextEditor} from '../editor/PortableTextEditor'
|
|
33
|
+
import {type Patch} from '../types/patch'
|
|
34
|
+
|
|
35
|
+
/** @beta */
|
|
36
|
+
export interface EditableAPIDeleteOptions {
|
|
37
|
+
mode?: 'blocks' | 'children' | 'selected'
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** @beta */
|
|
41
|
+
export interface EditableAPI {
|
|
42
|
+
activeAnnotations: () => PortableTextObject[]
|
|
43
|
+
isAnnotationActive: (annotationType: PortableTextObject['_type']) => boolean
|
|
44
|
+
addAnnotation: (
|
|
45
|
+
type: ObjectSchemaType,
|
|
46
|
+
value?: {[prop: string]: unknown},
|
|
47
|
+
) => {spanPath: Path; markDefPath: Path} | undefined
|
|
48
|
+
blur: () => void
|
|
49
|
+
delete: (selection: EditorSelection, options?: EditableAPIDeleteOptions) => void
|
|
50
|
+
findByPath: (path: Path) => [PortableTextBlock | PortableTextChild | undefined, Path | undefined]
|
|
51
|
+
findDOMNode: (element: PortableTextBlock | PortableTextChild) => DOMNode | undefined
|
|
52
|
+
focus: () => void
|
|
53
|
+
focusBlock: () => PortableTextBlock | undefined
|
|
54
|
+
focusChild: () => PortableTextChild | undefined
|
|
55
|
+
getSelection: () => EditorSelection
|
|
56
|
+
getFragment: () => PortableTextBlock[] | undefined
|
|
57
|
+
getValue: () => PortableTextBlock[] | undefined
|
|
58
|
+
hasBlockStyle: (style: string) => boolean
|
|
59
|
+
hasListStyle: (listStyle: string) => boolean
|
|
60
|
+
insertBlock: (type: BlockSchemaType | ObjectSchemaType, value?: {[prop: string]: unknown}) => Path
|
|
61
|
+
insertChild: (type: SpanSchemaType | ObjectSchemaType, value?: {[prop: string]: unknown}) => Path
|
|
62
|
+
insertBreak: () => void
|
|
63
|
+
isCollapsedSelection: () => boolean
|
|
64
|
+
isExpandedSelection: () => boolean
|
|
65
|
+
isMarkActive: (mark: string) => boolean
|
|
66
|
+
isSelectionsOverlapping: (selectionA: EditorSelection, selectionB: EditorSelection) => boolean
|
|
67
|
+
isVoid: (element: PortableTextBlock | PortableTextChild) => boolean
|
|
68
|
+
marks: () => string[]
|
|
69
|
+
redo: () => void
|
|
70
|
+
removeAnnotation: (type: ObjectSchemaType) => void
|
|
71
|
+
select: (selection: EditorSelection) => void
|
|
72
|
+
toggleBlockStyle: (blockStyle: string) => void
|
|
73
|
+
toggleList: (listStyle: string) => void
|
|
74
|
+
toggleMark: (mark: string) => void
|
|
75
|
+
undo: () => void
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/** @internal */
|
|
79
|
+
export type EditorNode = SlateNode & {
|
|
80
|
+
_key: string
|
|
81
|
+
_type: string
|
|
82
|
+
}
|
|
83
|
+
/** @internal */
|
|
84
|
+
export type HistoryItem = {
|
|
85
|
+
operations: SlateOperation[]
|
|
86
|
+
timestamp: Date
|
|
87
|
+
}
|
|
88
|
+
/** @internal */
|
|
89
|
+
export interface History {
|
|
90
|
+
redos: HistoryItem[]
|
|
91
|
+
undos: HistoryItem[]
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/** @beta */
|
|
95
|
+
export type EditorSelectionPoint = {path: Path; offset: number}
|
|
96
|
+
/** @beta */
|
|
97
|
+
export type EditorSelection = {
|
|
98
|
+
anchor: EditorSelectionPoint
|
|
99
|
+
focus: EditorSelectionPoint
|
|
100
|
+
backward?: boolean
|
|
101
|
+
} | null
|
|
102
|
+
/** @internal */
|
|
103
|
+
export interface PortableTextSlateEditor extends ReactEditor {
|
|
104
|
+
_key: 'editor'
|
|
105
|
+
_type: 'editor'
|
|
106
|
+
destroy: () => void
|
|
107
|
+
createPlaceholderBlock: () => Descendant
|
|
108
|
+
editable: EditableAPI
|
|
109
|
+
history: History
|
|
110
|
+
insertPortableTextData: (data: DataTransfer) => boolean
|
|
111
|
+
insertTextOrHTMLData: (data: DataTransfer) => boolean
|
|
112
|
+
isTextBlock: (value: unknown) => value is PortableTextTextBlock
|
|
113
|
+
isTextSpan: (value: unknown) => value is PortableTextSpan
|
|
114
|
+
isListBlock: (value: unknown) => value is PortableTextListBlock
|
|
115
|
+
subscriptions: (() => () => void)[]
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Increments selected list items levels, or decrements them if `reverse` is true.
|
|
119
|
+
*
|
|
120
|
+
* @param reverse - if true, decrement instead of incrementing
|
|
121
|
+
* @returns True if anything was incremented in the selection
|
|
122
|
+
*/
|
|
123
|
+
pteIncrementBlockLevels: (reverse?: boolean) => boolean
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Toggle selected blocks as listItem
|
|
127
|
+
*
|
|
128
|
+
* @param listStyle - Style of list item to toggle on/off
|
|
129
|
+
*/
|
|
130
|
+
pteToggleListItem: (listStyle: string) => void
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Set selected block as listItem
|
|
134
|
+
*
|
|
135
|
+
* @param listStyle - Style of list item to set
|
|
136
|
+
*/
|
|
137
|
+
pteSetListItem: (listStyle: string) => void
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Unset selected block as listItem
|
|
141
|
+
*
|
|
142
|
+
* @param listStyle - Style of list item to unset
|
|
143
|
+
*/
|
|
144
|
+
pteUnsetListItem: (listStyle: string) => void
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Ends a list
|
|
148
|
+
*
|
|
149
|
+
* @returns True if a list was ended in the selection
|
|
150
|
+
*/
|
|
151
|
+
pteEndList: () => boolean
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Toggle marks in the selection
|
|
155
|
+
*
|
|
156
|
+
* @param mark - Mark to toggle on/off
|
|
157
|
+
*/
|
|
158
|
+
pteToggleMark: (mark: string) => void
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Test if a mark is active in the current selection
|
|
162
|
+
*
|
|
163
|
+
* @param mark - Mark to check whether or not is active
|
|
164
|
+
*/
|
|
165
|
+
pteIsMarkActive: (mark: string) => boolean
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Toggle the selected block style
|
|
169
|
+
*
|
|
170
|
+
* @param style - The style name
|
|
171
|
+
*
|
|
172
|
+
*/
|
|
173
|
+
pteToggleBlockStyle: (style: string) => void
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Test if the current selection has a certain block style
|
|
177
|
+
*
|
|
178
|
+
* @param style - The style name
|
|
179
|
+
*
|
|
180
|
+
*/
|
|
181
|
+
pteHasBlockStyle: (style: string) => boolean
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Test if the current selection has a certain list style
|
|
185
|
+
*
|
|
186
|
+
* @param listStyle - Style name to check whether or not the selection has
|
|
187
|
+
*
|
|
188
|
+
*/
|
|
189
|
+
pteHasListStyle: (style: string) => boolean
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Try to expand the current selection to a word
|
|
193
|
+
*/
|
|
194
|
+
pteExpandToWord: () => void
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Use hotkeys
|
|
198
|
+
*/
|
|
199
|
+
pteWithHotKeys: (event: KeyboardEvent<HTMLDivElement>) => void
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Helper function that creates an empty text block
|
|
203
|
+
*/
|
|
204
|
+
pteCreateEmptyBlock: () => Descendant
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Undo
|
|
208
|
+
*/
|
|
209
|
+
undo: () => void
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Redo
|
|
213
|
+
*/
|
|
214
|
+
redo: () => void
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* The editor has mutated it's content.
|
|
219
|
+
* @beta */
|
|
220
|
+
export type MutationChange = {
|
|
221
|
+
type: 'mutation'
|
|
222
|
+
patches: Patch[]
|
|
223
|
+
snapshot: PortableTextBlock[] | undefined
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* The editor has produced a patch
|
|
228
|
+
* @beta */
|
|
229
|
+
export type PatchChange = {
|
|
230
|
+
type: 'patch'
|
|
231
|
+
patch: Patch
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* The editor has received a new (props) value
|
|
236
|
+
* @beta */
|
|
237
|
+
export type ValueChange = {
|
|
238
|
+
type: 'value'
|
|
239
|
+
value: PortableTextBlock[] | undefined
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* The editor has a new selection
|
|
244
|
+
* @beta */
|
|
245
|
+
export type SelectionChange = {
|
|
246
|
+
type: 'selection'
|
|
247
|
+
selection: EditorSelection
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* The editor received focus
|
|
252
|
+
* @beta */
|
|
253
|
+
export type FocusChange = {
|
|
254
|
+
type: 'focus'
|
|
255
|
+
event: FocusEvent<HTMLDivElement, Element>
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/** @beta */
|
|
259
|
+
export type UnsetChange = {
|
|
260
|
+
type: 'unset'
|
|
261
|
+
previousValue: PortableTextBlock[]
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* The editor blurred
|
|
266
|
+
* @beta */
|
|
267
|
+
export type BlurChange = {
|
|
268
|
+
type: 'blur'
|
|
269
|
+
event: FocusEvent<HTMLDivElement, Element>
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* The editor is currently loading something
|
|
274
|
+
* Could be used to show a spinner etc.
|
|
275
|
+
* @beta */
|
|
276
|
+
export type LoadingChange = {
|
|
277
|
+
type: 'loading'
|
|
278
|
+
isLoading: boolean
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* The editor content is ready to be edited by the user
|
|
283
|
+
* @beta */
|
|
284
|
+
export type ReadyChange = {
|
|
285
|
+
type: 'ready'
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* The editor produced an error
|
|
290
|
+
* @beta */
|
|
291
|
+
export type ErrorChange = {
|
|
292
|
+
type: 'error'
|
|
293
|
+
name: string // short computer readable name
|
|
294
|
+
level: 'warning' | 'error'
|
|
295
|
+
description: string
|
|
296
|
+
data?: unknown
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
/**
|
|
300
|
+
* The editor has invalid data in the value that can be resolved by the user
|
|
301
|
+
* @beta */
|
|
302
|
+
export type InvalidValueResolution = {
|
|
303
|
+
autoResolve?: boolean
|
|
304
|
+
patches: Patch[]
|
|
305
|
+
description: string
|
|
306
|
+
action: string
|
|
307
|
+
item: PortableTextBlock[] | PortableTextBlock | PortableTextChild | undefined
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* i18n keys for the description and action
|
|
311
|
+
*
|
|
312
|
+
* These are in addition to the description and action properties, to decouple the editor from
|
|
313
|
+
* the i18n system, and allow usage without it. The i18n keys take precedence over the
|
|
314
|
+
* description and action properties, if i18n framework is available.
|
|
315
|
+
*/
|
|
316
|
+
i18n: {
|
|
317
|
+
description: `inputs.portable-text.invalid-value.${Lowercase<string>}.description`
|
|
318
|
+
action: `inputs.portable-text.invalid-value.${Lowercase<string>}.action`
|
|
319
|
+
values?: Record<string, string | number | string[]>
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
/**
|
|
324
|
+
* The editor has an invalid value
|
|
325
|
+
* @beta */
|
|
326
|
+
export type InvalidValue = {
|
|
327
|
+
type: 'invalidValue'
|
|
328
|
+
resolution: InvalidValueResolution | null
|
|
329
|
+
value: PortableTextBlock[] | undefined
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
/**
|
|
333
|
+
* The editor performed a undo history step
|
|
334
|
+
* @beta */
|
|
335
|
+
export type UndoChange = {
|
|
336
|
+
type: 'undo'
|
|
337
|
+
patches: Patch[]
|
|
338
|
+
timestamp: Date
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
/**
|
|
342
|
+
* The editor performed redo history step
|
|
343
|
+
* @beta */
|
|
344
|
+
export type RedoChange = {
|
|
345
|
+
type: 'redo'
|
|
346
|
+
patches: Patch[]
|
|
347
|
+
timestamp: Date
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
/**
|
|
351
|
+
* The editor was either connected or disconnected to the network
|
|
352
|
+
* To show out of sync warnings etc when in collaborative mode.
|
|
353
|
+
* @beta */
|
|
354
|
+
export type ConnectionChange = {
|
|
355
|
+
type: 'connection'
|
|
356
|
+
value: 'online' | 'offline'
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
/**
|
|
360
|
+
* When the editor changes, it will emit a change item describing the change
|
|
361
|
+
* @beta */
|
|
362
|
+
export type EditorChange =
|
|
363
|
+
| BlurChange
|
|
364
|
+
| ConnectionChange
|
|
365
|
+
| ErrorChange
|
|
366
|
+
| FocusChange
|
|
367
|
+
| InvalidValue
|
|
368
|
+
| LoadingChange
|
|
369
|
+
| MutationChange
|
|
370
|
+
| PatchChange
|
|
371
|
+
| ReadyChange
|
|
372
|
+
| RedoChange
|
|
373
|
+
| SelectionChange
|
|
374
|
+
| UndoChange
|
|
375
|
+
| UnsetChange
|
|
376
|
+
| ValueChange
|
|
377
|
+
|
|
378
|
+
export type EditorChanges = Subject<EditorChange>
|
|
379
|
+
|
|
380
|
+
/** @beta */
|
|
381
|
+
export type OnPasteResult =
|
|
382
|
+
| {
|
|
383
|
+
insert?: TypedObject[]
|
|
384
|
+
path?: Path
|
|
385
|
+
}
|
|
386
|
+
| undefined
|
|
387
|
+
export type OnPasteResultOrPromise = OnPasteResult | Promise<OnPasteResult>
|
|
388
|
+
|
|
389
|
+
/** @beta */
|
|
390
|
+
export interface PasteData {
|
|
391
|
+
event: ClipboardEvent
|
|
392
|
+
path: Path
|
|
393
|
+
schemaTypes: PortableTextMemberSchemaTypes
|
|
394
|
+
value: PortableTextBlock[] | undefined
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
/** @beta */
|
|
398
|
+
export type OnPasteFn = (data: PasteData) => OnPasteResultOrPromise
|
|
399
|
+
|
|
400
|
+
/** @beta */
|
|
401
|
+
export type OnBeforeInputFn = (event: InputEvent) => void
|
|
402
|
+
|
|
403
|
+
/** @beta */
|
|
404
|
+
export type OnCopyFn = (
|
|
405
|
+
event: ClipboardEvent<HTMLDivElement | HTMLSpanElement>,
|
|
406
|
+
) => undefined | unknown
|
|
407
|
+
|
|
408
|
+
/** @beta */
|
|
409
|
+
export type PatchObservable = Observable<{
|
|
410
|
+
patches: Patch[]
|
|
411
|
+
snapshot: PortableTextBlock[] | undefined
|
|
412
|
+
}>
|
|
413
|
+
|
|
414
|
+
/** @beta */
|
|
415
|
+
export interface BlockRenderProps {
|
|
416
|
+
children: ReactElement
|
|
417
|
+
editorElementRef: RefObject<HTMLElement>
|
|
418
|
+
focused: boolean
|
|
419
|
+
level?: number
|
|
420
|
+
listItem?: string
|
|
421
|
+
path: Path
|
|
422
|
+
selected: boolean
|
|
423
|
+
style?: string
|
|
424
|
+
schemaType: ObjectSchemaType
|
|
425
|
+
/** @deprecated Use `schemaType` instead */
|
|
426
|
+
type: ObjectSchemaType
|
|
427
|
+
value: PortableTextBlock
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
/** @beta */
|
|
431
|
+
export interface BlockChildRenderProps {
|
|
432
|
+
annotations: PortableTextObject[]
|
|
433
|
+
children: ReactElement
|
|
434
|
+
editorElementRef: RefObject<HTMLElement>
|
|
435
|
+
focused: boolean
|
|
436
|
+
path: Path
|
|
437
|
+
selected: boolean
|
|
438
|
+
schemaType: ObjectSchemaType
|
|
439
|
+
/** @deprecated Use `schemaType` instead */
|
|
440
|
+
type: ObjectSchemaType
|
|
441
|
+
value: PortableTextChild
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
/** @beta */
|
|
445
|
+
export interface BlockAnnotationRenderProps {
|
|
446
|
+
block: PortableTextBlock
|
|
447
|
+
children: ReactElement
|
|
448
|
+
editorElementRef: RefObject<HTMLElement>
|
|
449
|
+
focused: boolean
|
|
450
|
+
path: Path
|
|
451
|
+
schemaType: ObjectSchemaType
|
|
452
|
+
selected: boolean
|
|
453
|
+
/** @deprecated Use `schemaType` instead */
|
|
454
|
+
type: ObjectSchemaType
|
|
455
|
+
value: PortableTextObject
|
|
456
|
+
}
|
|
457
|
+
/** @beta */
|
|
458
|
+
export interface BlockDecoratorRenderProps {
|
|
459
|
+
children: ReactElement
|
|
460
|
+
editorElementRef: RefObject<HTMLElement>
|
|
461
|
+
focused: boolean
|
|
462
|
+
path: Path
|
|
463
|
+
schemaType: BlockDecoratorDefinition
|
|
464
|
+
selected: boolean
|
|
465
|
+
/** @deprecated Use `schemaType` instead */
|
|
466
|
+
type: BlockDecoratorDefinition
|
|
467
|
+
value: string
|
|
468
|
+
}
|
|
469
|
+
/** @beta */
|
|
470
|
+
|
|
471
|
+
export interface BlockListItemRenderProps {
|
|
472
|
+
block: PortableTextTextBlock
|
|
473
|
+
children: ReactElement
|
|
474
|
+
editorElementRef: RefObject<HTMLElement>
|
|
475
|
+
focused: boolean
|
|
476
|
+
level: number
|
|
477
|
+
path: Path
|
|
478
|
+
schemaType: BlockListDefinition
|
|
479
|
+
selected: boolean
|
|
480
|
+
value: string
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
/** @beta */
|
|
484
|
+
export type RenderBlockFunction = (props: BlockRenderProps) => JSX.Element
|
|
485
|
+
|
|
486
|
+
/** @beta */
|
|
487
|
+
export type RenderChildFunction = (props: BlockChildRenderProps) => JSX.Element
|
|
488
|
+
|
|
489
|
+
/** @beta */
|
|
490
|
+
export type RenderEditableFunction = (props: PortableTextEditableProps) => JSX.Element
|
|
491
|
+
|
|
492
|
+
/** @beta */
|
|
493
|
+
export type RenderAnnotationFunction = (props: BlockAnnotationRenderProps) => JSX.Element
|
|
494
|
+
|
|
495
|
+
/** @beta */
|
|
496
|
+
export type RenderStyleFunction = (props: BlockStyleRenderProps) => JSX.Element
|
|
497
|
+
|
|
498
|
+
/** @beta */
|
|
499
|
+
|
|
500
|
+
export interface BlockStyleRenderProps {
|
|
501
|
+
block: PortableTextTextBlock
|
|
502
|
+
children: ReactElement
|
|
503
|
+
editorElementRef: RefObject<HTMLElement>
|
|
504
|
+
focused: boolean
|
|
505
|
+
path: Path
|
|
506
|
+
selected: boolean
|
|
507
|
+
schemaType: BlockStyleDefinition
|
|
508
|
+
value: string
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
/** @beta */
|
|
512
|
+
export type RenderListItemFunction = (props: BlockListItemRenderProps) => JSX.Element
|
|
513
|
+
|
|
514
|
+
/** @beta */
|
|
515
|
+
export type RenderDecoratorFunction = (props: BlockDecoratorRenderProps) => JSX.Element
|
|
516
|
+
|
|
517
|
+
/** @beta */
|
|
518
|
+
export type ScrollSelectionIntoViewFunction = (
|
|
519
|
+
editor: PortableTextEditor,
|
|
520
|
+
domRange: globalThis.Range,
|
|
521
|
+
) => void
|
|
522
|
+
|
|
523
|
+
/**
|
|
524
|
+
* Parameters for the callback that will be called for a RangeDecoration's onMoved.
|
|
525
|
+
* @alpha */
|
|
526
|
+
export interface RangeDecorationOnMovedDetails {
|
|
527
|
+
rangeDecoration: RangeDecoration
|
|
528
|
+
newSelection: EditorSelection
|
|
529
|
+
origin: 'remote' | 'local'
|
|
530
|
+
}
|
|
531
|
+
/**
|
|
532
|
+
* A range decoration is a UI affordance that wraps a given selection range in the editor
|
|
533
|
+
* with a custom component. This can be used to highlight search results,
|
|
534
|
+
* mark validation errors on specific words, draw user presence and similar.
|
|
535
|
+
* @alpha */
|
|
536
|
+
export interface RangeDecoration {
|
|
537
|
+
/**
|
|
538
|
+
* A component for rendering the range decoration.
|
|
539
|
+
* The component will receive the children (text) of the range decoration as its children.
|
|
540
|
+
*
|
|
541
|
+
* @example
|
|
542
|
+
* ```ts
|
|
543
|
+
* (rangeComponentProps: PropsWithChildren) => (
|
|
544
|
+
* <SearchResultHighlight>
|
|
545
|
+
* {rangeComponentProps.children}
|
|
546
|
+
* </SearchResultHighlight>
|
|
547
|
+
* )
|
|
548
|
+
* ```
|
|
549
|
+
*/
|
|
550
|
+
component: (props: PropsWithChildren) => ReactElement
|
|
551
|
+
/**
|
|
552
|
+
* The editor content selection range
|
|
553
|
+
*/
|
|
554
|
+
selection: EditorSelection
|
|
555
|
+
/**
|
|
556
|
+
* A optional callback that will be called when the range decoration potentially moves according to user edits.
|
|
557
|
+
*/
|
|
558
|
+
onMoved?: (details: RangeDecorationOnMovedDetails) => void
|
|
559
|
+
/**
|
|
560
|
+
* A custom payload that can be set on the range decoration
|
|
561
|
+
*/
|
|
562
|
+
payload?: Record<string, unknown>
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
/** @internal */
|
|
566
|
+
export type PortableTextMemberSchemaTypes = {
|
|
567
|
+
annotations: (ObjectSchemaType & {i18nTitleKey?: string})[]
|
|
568
|
+
block: ObjectSchemaType
|
|
569
|
+
blockObjects: ObjectSchemaType[]
|
|
570
|
+
decorators: BlockDecoratorDefinition[]
|
|
571
|
+
inlineObjects: ObjectSchemaType[]
|
|
572
|
+
portableText: ArraySchemaType<PortableTextBlock>
|
|
573
|
+
span: ObjectSchemaType
|
|
574
|
+
styles: BlockStyleDefinition[]
|
|
575
|
+
lists: BlockListDefinition[]
|
|
576
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import {type BaseSyntheticEvent} from 'react'
|
|
2
|
+
|
|
3
|
+
import {type PortableTextEditor} from '../editor/PortableTextEditor'
|
|
4
|
+
import {type PatchObservable} from './editor'
|
|
5
|
+
|
|
6
|
+
export type createEditorOptions = {
|
|
7
|
+
keyGenerator: () => string
|
|
8
|
+
patches$?: PatchObservable
|
|
9
|
+
portableTextEditor: PortableTextEditor
|
|
10
|
+
readOnly: boolean
|
|
11
|
+
maxBlocks?: number
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export type HotkeyOptions = {
|
|
15
|
+
marks?: Record<string, string>
|
|
16
|
+
custom?: Record<string, (event: BaseSyntheticEvent, editor: PortableTextEditor) => void>
|
|
17
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import {type Path} from '@sanity/types'
|
|
2
|
+
|
|
3
|
+
export type JSONValue = number | string | boolean | {[key: string]: JSONValue} | JSONValue[]
|
|
4
|
+
|
|
5
|
+
export type Origin = 'remote' | 'local' | 'internal'
|
|
6
|
+
|
|
7
|
+
export type IncPatch = {
|
|
8
|
+
path: Path
|
|
9
|
+
origin?: Origin
|
|
10
|
+
type: 'inc'
|
|
11
|
+
value: JSONValue
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export type DecPatch = {
|
|
15
|
+
path: Path
|
|
16
|
+
origin?: Origin
|
|
17
|
+
type: 'dec'
|
|
18
|
+
value: JSONValue
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export type SetPatch = {
|
|
22
|
+
path: Path
|
|
23
|
+
type: 'set'
|
|
24
|
+
origin?: Origin
|
|
25
|
+
value: JSONValue
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export type SetIfMissingPatch = {
|
|
29
|
+
path: Path
|
|
30
|
+
origin?: Origin
|
|
31
|
+
type: 'setIfMissing'
|
|
32
|
+
value: JSONValue
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export type UnsetPatch = {
|
|
36
|
+
path: Path
|
|
37
|
+
origin?: Origin
|
|
38
|
+
type: 'unset'
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export type InsertPosition = 'before' | 'after' | 'replace'
|
|
42
|
+
|
|
43
|
+
export type InsertPatch = {
|
|
44
|
+
path: Path
|
|
45
|
+
origin?: Origin
|
|
46
|
+
type: 'insert'
|
|
47
|
+
position: InsertPosition
|
|
48
|
+
items: JSONValue[]
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export type DiffMatchPatch = {
|
|
52
|
+
path: Path
|
|
53
|
+
type: 'diffMatchPatch'
|
|
54
|
+
origin?: Origin
|
|
55
|
+
value: string
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export type Patch =
|
|
59
|
+
| SetPatch
|
|
60
|
+
| SetIfMissingPatch
|
|
61
|
+
| UnsetPatch
|
|
62
|
+
| InsertPatch
|
|
63
|
+
| DiffMatchPatch
|
|
64
|
+
| IncPatch
|
|
65
|
+
| DecPatch
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import {type PortableTextSpan, type PortableTextTextBlock} from '@sanity/types'
|
|
2
|
+
import {type BaseEditor, type Descendant} from 'slate'
|
|
3
|
+
import {type ReactEditor} from 'slate-react'
|
|
4
|
+
|
|
5
|
+
import {type PortableTextSlateEditor} from '..'
|
|
6
|
+
|
|
7
|
+
export interface VoidElement {
|
|
8
|
+
_type: string
|
|
9
|
+
_key: string
|
|
10
|
+
children: Descendant[]
|
|
11
|
+
__inline: boolean
|
|
12
|
+
value: Record<string, unknown>
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface SlateTextBlock extends Omit<PortableTextTextBlock, 'children'> {
|
|
16
|
+
children: Descendant[]
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
declare module 'slate' {
|
|
20
|
+
interface CustomTypes {
|
|
21
|
+
Editor: BaseEditor & ReactEditor & PortableTextSlateEditor
|
|
22
|
+
Element: SlateTextBlock | VoidElement
|
|
23
|
+
Text: PortableTextSpan
|
|
24
|
+
}
|
|
25
|
+
}
|