@portabletext/editor 1.0.7 → 1.0.9
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/lib/index.d.mts +7 -1
- package/lib/index.d.ts +7 -1
- package/lib/index.esm.js +185 -174
- package/lib/index.esm.js.map +1 -1
- package/lib/index.js +184 -173
- package/lib/index.js.map +1 -1
- package/lib/index.mjs +185 -174
- package/lib/index.mjs.map +1 -1
- package/package.json +2 -3
- package/src/editor/Editable.tsx +8 -8
- package/src/editor/PortableTextEditor.tsx +30 -11
- package/src/editor/__tests__/RangeDecorations.test.tsx +4 -4
- package/src/editor/components/Synchronizer.tsx +15 -46
- package/src/editor/hooks/usePortableTextEditorSelection.tsx +62 -0
- package/src/types/editor.ts +6 -1
- package/src/utils/withChanges.ts +0 -7
- package/src/editor/hooks/usePortableTextEditorSelection.ts +0 -22
- package/src/editor/hooks/usePortableTextEditorValue.ts +0 -16
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@portabletext/editor",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.9",
|
|
4
4
|
"description": "Portable Text Editor made in React",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"sanity",
|
|
@@ -97,7 +97,6 @@
|
|
|
97
97
|
"node-ipc": "npm:@node-ipc/compat@9.2.5",
|
|
98
98
|
"react": "^18.3.1",
|
|
99
99
|
"react-dom": "^18.3.1",
|
|
100
|
-
"rimraf": "^3.0.2",
|
|
101
100
|
"rxjs": "^7.8.1",
|
|
102
101
|
"styled-components": "^6.1.11",
|
|
103
102
|
"tsx": "^4.15.7",
|
|
@@ -123,7 +122,7 @@
|
|
|
123
122
|
"build": "pkg-utils build --strict --check --clean",
|
|
124
123
|
"check:lint": "eslint .",
|
|
125
124
|
"check:types": "tsc --project tsconfig.lib.json",
|
|
126
|
-
"clean": "
|
|
125
|
+
"clean": "del .turbo && del lib && del node_modules",
|
|
127
126
|
"dev": "pkg-utils watch",
|
|
128
127
|
"dev:e2e-server": "cd ./e2e-tests/ && tsx serve",
|
|
129
128
|
"lint:fix": "eslint . --fix",
|
package/src/editor/Editable.tsx
CHANGED
|
@@ -79,8 +79,6 @@ interface BaseRangeWithDecoration extends BaseRange {
|
|
|
79
79
|
rangeDecoration: RangeDecoration
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
-
const EMPTY_DECORATIONS_STATE: BaseRangeWithDecoration[] = []
|
|
83
|
-
|
|
84
82
|
/**
|
|
85
83
|
* @public
|
|
86
84
|
*/
|
|
@@ -142,8 +140,7 @@ export const PortableTextEditable = forwardRef(function PortableTextEditable(
|
|
|
142
140
|
const ref = useRef<HTMLDivElement | null>(null)
|
|
143
141
|
const [editableElement, setEditableElement] = useState<HTMLDivElement | null>(null)
|
|
144
142
|
const [hasInvalidValue, setHasInvalidValue] = useState(false)
|
|
145
|
-
const [rangeDecorationState, setRangeDecorationsState] =
|
|
146
|
-
useState<BaseRangeWithDecoration[]>(EMPTY_DECORATIONS_STATE)
|
|
143
|
+
const [rangeDecorationState, setRangeDecorationsState] = useState<BaseRangeWithDecoration[]>([])
|
|
147
144
|
|
|
148
145
|
// Forward ref to parent component
|
|
149
146
|
useImperativeHandle<HTMLDivElement | null, HTMLDivElement | null>(forwardedRef, () => ref.current)
|
|
@@ -296,7 +293,7 @@ export const PortableTextEditable = forwardRef(function PortableTextEditable(
|
|
|
296
293
|
return
|
|
297
294
|
}
|
|
298
295
|
}
|
|
299
|
-
setRangeDecorationsState(
|
|
296
|
+
setRangeDecorationsState([])
|
|
300
297
|
},
|
|
301
298
|
[portableTextEditor, rangeDecorations, schemaTypes, slateEditor],
|
|
302
299
|
)
|
|
@@ -404,7 +401,10 @@ export const PortableTextEditable = forwardRef(function PortableTextEditable(
|
|
|
404
401
|
Promise.resolve(onPasteResult)
|
|
405
402
|
.then((result) => {
|
|
406
403
|
debug('Custom paste function from client resolved', result)
|
|
407
|
-
if (result
|
|
404
|
+
if (!result || !result.insert) {
|
|
405
|
+
debug('No result from custom paste handler, pasting normally')
|
|
406
|
+
slateEditor.insertData(event.clipboardData)
|
|
407
|
+
} else if (result.insert) {
|
|
408
408
|
slateEditor.insertFragment(
|
|
409
409
|
toSlateValue(result.insert as PortableTextBlock[], {schemaTypes}),
|
|
410
410
|
)
|
|
@@ -616,7 +616,7 @@ export const PortableTextEditable = forwardRef(function PortableTextEditable(
|
|
|
616
616
|
}
|
|
617
617
|
// Editor node has a path length of 0 (should never be decorated)
|
|
618
618
|
if (path.length === 0) {
|
|
619
|
-
return
|
|
619
|
+
return []
|
|
620
620
|
}
|
|
621
621
|
const result = rangeDecorationState.filter((item) => {
|
|
622
622
|
// Special case in order to only return one decoration for collapsed ranges
|
|
@@ -636,7 +636,7 @@ export const PortableTextEditable = forwardRef(function PortableTextEditable(
|
|
|
636
636
|
if (result.length > 0) {
|
|
637
637
|
return result
|
|
638
638
|
}
|
|
639
|
-
return
|
|
639
|
+
return []
|
|
640
640
|
},
|
|
641
641
|
[slateEditor, schemaTypes, rangeDecorationState],
|
|
642
642
|
)
|
|
@@ -26,7 +26,13 @@ import {getPortableTextMemberSchemaTypes} from '../utils/getPortableTextMemberSc
|
|
|
26
26
|
import {compileType} from '../utils/schema'
|
|
27
27
|
import {SlateContainer} from './components/SlateContainer'
|
|
28
28
|
import {Synchronizer} from './components/Synchronizer'
|
|
29
|
-
import {
|
|
29
|
+
import {PortableTextEditorContext} from './hooks/usePortableTextEditor'
|
|
30
|
+
import {
|
|
31
|
+
defaultKeyGenerator,
|
|
32
|
+
PortableTextEditorKeyGeneratorContext,
|
|
33
|
+
} from './hooks/usePortableTextEditorKeyGenerator'
|
|
34
|
+
import {PortableTextEditorSelectionProvider} from './hooks/usePortableTextEditorSelection'
|
|
35
|
+
import {PortableTextEditorReadOnlyContext} from './hooks/usePortableTextReadOnly'
|
|
30
36
|
|
|
31
37
|
const debug = debugWithName('component:PortableTextEditor')
|
|
32
38
|
|
|
@@ -143,6 +149,14 @@ export class PortableTextEditor extends Component<PortableTextEditorProps> {
|
|
|
143
149
|
this.editable = {...this.editable, ...editable}
|
|
144
150
|
}
|
|
145
151
|
|
|
152
|
+
private getValue = () => {
|
|
153
|
+
if (this.editable) {
|
|
154
|
+
return this.editable.getValue()
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
return undefined
|
|
158
|
+
}
|
|
159
|
+
|
|
146
160
|
render() {
|
|
147
161
|
const {onChange, value, children, patches$, incomingPatches$} = this.props
|
|
148
162
|
const {change$} = this
|
|
@@ -163,16 +177,21 @@ export class PortableTextEditor extends Component<PortableTextEditorProps> {
|
|
|
163
177
|
portableTextEditor={this}
|
|
164
178
|
readOnly={readOnly}
|
|
165
179
|
>
|
|
166
|
-
<
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
180
|
+
<PortableTextEditorKeyGeneratorContext.Provider value={keyGenerator}>
|
|
181
|
+
<PortableTextEditorContext.Provider value={this}>
|
|
182
|
+
<PortableTextEditorReadOnlyContext.Provider value={readOnly}>
|
|
183
|
+
<PortableTextEditorSelectionProvider change$={change$}>
|
|
184
|
+
<Synchronizer
|
|
185
|
+
change$={change$}
|
|
186
|
+
getValue={this.getValue}
|
|
187
|
+
onChange={onChange}
|
|
188
|
+
value={value}
|
|
189
|
+
/>
|
|
190
|
+
{children}
|
|
191
|
+
</PortableTextEditorSelectionProvider>
|
|
192
|
+
</PortableTextEditorReadOnlyContext.Provider>
|
|
193
|
+
</PortableTextEditorContext.Provider>
|
|
194
|
+
</PortableTextEditorKeyGeneratorContext.Provider>
|
|
176
195
|
</SlateContainer>
|
|
177
196
|
)
|
|
178
197
|
}
|
|
@@ -46,7 +46,7 @@ describe('RangeDecorations', () => {
|
|
|
46
46
|
/>,
|
|
47
47
|
)
|
|
48
48
|
await waitFor(() => {
|
|
49
|
-
expect([rangeDecorationIteration, 'initial']).toEqual([
|
|
49
|
+
expect([rangeDecorationIteration, 'initial']).toEqual([1, 'initial'])
|
|
50
50
|
})
|
|
51
51
|
// Re-render with the same range decorations
|
|
52
52
|
rerender(
|
|
@@ -59,7 +59,7 @@ describe('RangeDecorations', () => {
|
|
|
59
59
|
/>,
|
|
60
60
|
)
|
|
61
61
|
await waitFor(() => {
|
|
62
|
-
expect([rangeDecorationIteration, 'initial']).toEqual([
|
|
62
|
+
expect([rangeDecorationIteration, 'initial']).toEqual([1, 'initial'])
|
|
63
63
|
})
|
|
64
64
|
// Update the range decorations, a new object with identical values
|
|
65
65
|
rangeDecorations = [
|
|
@@ -82,7 +82,7 @@ describe('RangeDecorations', () => {
|
|
|
82
82
|
)
|
|
83
83
|
await waitFor(() => {
|
|
84
84
|
expect([rangeDecorationIteration, 'updated-with-equal-values']).toEqual([
|
|
85
|
-
|
|
85
|
+
1,
|
|
86
86
|
'updated-with-equal-values',
|
|
87
87
|
])
|
|
88
88
|
})
|
|
@@ -107,7 +107,7 @@ describe('RangeDecorations', () => {
|
|
|
107
107
|
)
|
|
108
108
|
await waitFor(() => {
|
|
109
109
|
expect([rangeDecorationIteration, 'updated-with-different']).toEqual([
|
|
110
|
-
|
|
110
|
+
2,
|
|
111
111
|
'updated-with-different',
|
|
112
112
|
])
|
|
113
113
|
})
|
|
@@ -1,28 +1,17 @@
|
|
|
1
1
|
import {type Patch} from '@portabletext/patches'
|
|
2
2
|
import {type PortableTextBlock} from '@sanity/types'
|
|
3
3
|
import {throttle} from 'lodash'
|
|
4
|
-
import {
|
|
5
|
-
type PropsWithChildren,
|
|
6
|
-
startTransition,
|
|
7
|
-
useCallback,
|
|
8
|
-
useEffect,
|
|
9
|
-
useMemo,
|
|
10
|
-
useRef,
|
|
11
|
-
useState,
|
|
12
|
-
} from 'react'
|
|
4
|
+
import {useCallback, useEffect, useMemo, useRef} from 'react'
|
|
13
5
|
import {Editor} from 'slate'
|
|
14
6
|
import {useSlate} from 'slate-react'
|
|
15
7
|
|
|
16
|
-
import {type EditorChange, type EditorChanges
|
|
8
|
+
import {type EditorChange, type EditorChanges} from '../../types/editor'
|
|
17
9
|
import {debugWithName} from '../../utils/debug'
|
|
18
10
|
import {IS_PROCESSING_LOCAL_CHANGES} from '../../utils/weakMaps'
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
22
|
-
import {PortableTextEditorValueContext} from '../hooks/usePortableTextEditorValue'
|
|
23
|
-
import {PortableTextEditorReadOnlyContext} from '../hooks/usePortableTextReadOnly'
|
|
11
|
+
import {usePortableTextEditor} from '../hooks/usePortableTextEditor'
|
|
12
|
+
import {usePortableTextEditorKeyGenerator} from '../hooks/usePortableTextEditorKeyGenerator'
|
|
13
|
+
import {usePortableTextEditorReadOnlyStatus} from '../hooks/usePortableTextReadOnly'
|
|
24
14
|
import {useSyncValue} from '../hooks/useSyncValue'
|
|
25
|
-
import {PortableTextEditor} from '../PortableTextEditor'
|
|
26
15
|
|
|
27
16
|
const debug = debugWithName('component:PortableTextEditor:Synchronizer')
|
|
28
17
|
const debugVerbose = debug.enabled && false
|
|
@@ -34,13 +23,11 @@ const FLUSH_PATCHES_THROTTLED_MS = process.env.NODE_ENV === 'test' ? 500 : 1000
|
|
|
34
23
|
/**
|
|
35
24
|
* @internal
|
|
36
25
|
*/
|
|
37
|
-
export interface SynchronizerProps
|
|
26
|
+
export interface SynchronizerProps {
|
|
38
27
|
change$: EditorChanges
|
|
39
|
-
|
|
40
|
-
keyGenerator: () => string
|
|
28
|
+
getValue: () => Array<PortableTextBlock> | undefined
|
|
41
29
|
onChange: (change: EditorChange) => void
|
|
42
|
-
|
|
43
|
-
value: PortableTextBlock[] | undefined
|
|
30
|
+
value: Array<PortableTextBlock> | undefined
|
|
44
31
|
}
|
|
45
32
|
|
|
46
33
|
/**
|
|
@@ -48,8 +35,10 @@ export interface SynchronizerProps extends PropsWithChildren {
|
|
|
48
35
|
* @internal
|
|
49
36
|
*/
|
|
50
37
|
export function Synchronizer(props: SynchronizerProps) {
|
|
51
|
-
const
|
|
52
|
-
const
|
|
38
|
+
const portableTextEditor = usePortableTextEditor()
|
|
39
|
+
const keyGenerator = usePortableTextEditorKeyGenerator()
|
|
40
|
+
const readOnly = usePortableTextEditorReadOnlyStatus()
|
|
41
|
+
const {change$, getValue, onChange, value} = props
|
|
53
42
|
const pendingPatches = useRef<Patch[]>([])
|
|
54
43
|
|
|
55
44
|
const syncValue = useSyncValue({
|
|
@@ -71,12 +60,12 @@ export function Synchronizer(props: SynchronizerProps) {
|
|
|
71
60
|
if (debugVerbose) {
|
|
72
61
|
debug(`Patches:\n${JSON.stringify(pendingPatches.current, null, 2)}`)
|
|
73
62
|
}
|
|
74
|
-
const snapshot =
|
|
63
|
+
const snapshot = getValue()
|
|
75
64
|
change$.next({type: 'mutation', patches: pendingPatches.current, snapshot})
|
|
76
65
|
pendingPatches.current = []
|
|
77
66
|
}
|
|
78
67
|
IS_PROCESSING_LOCAL_CHANGES.set(slateEditor, false)
|
|
79
|
-
}, [slateEditor,
|
|
68
|
+
}, [slateEditor, getValue, change$])
|
|
80
69
|
|
|
81
70
|
const onFlushPendingPatchesThrottled = useMemo(() => {
|
|
82
71
|
return throttle(
|
|
@@ -116,14 +105,6 @@ export function Synchronizer(props: SynchronizerProps) {
|
|
|
116
105
|
onFlushPendingPatchesThrottled()
|
|
117
106
|
onChange(next)
|
|
118
107
|
break
|
|
119
|
-
case 'selection':
|
|
120
|
-
// Set the selection state in a transition, we don't need the state immediately.
|
|
121
|
-
startTransition(() => {
|
|
122
|
-
if (debugVerbose) debug('Setting selection')
|
|
123
|
-
setSelection(next.selection)
|
|
124
|
-
})
|
|
125
|
-
onChange(next) // Keep this out of the startTransition!
|
|
126
|
-
break
|
|
127
108
|
default:
|
|
128
109
|
onChange(next)
|
|
129
110
|
}
|
|
@@ -174,17 +155,5 @@ export function Synchronizer(props: SynchronizerProps) {
|
|
|
174
155
|
}
|
|
175
156
|
}, [change$, syncValue, value])
|
|
176
157
|
|
|
177
|
-
return
|
|
178
|
-
<PortableTextEditorKeyGeneratorContext.Provider value={keyGenerator}>
|
|
179
|
-
<PortableTextEditorContext.Provider value={portableTextEditor}>
|
|
180
|
-
<PortableTextEditorValueContext.Provider value={value}>
|
|
181
|
-
<PortableTextEditorReadOnlyContext.Provider value={readOnly}>
|
|
182
|
-
<PortableTextEditorSelectionContext.Provider value={selection}>
|
|
183
|
-
{props.children}
|
|
184
|
-
</PortableTextEditorSelectionContext.Provider>
|
|
185
|
-
</PortableTextEditorReadOnlyContext.Provider>
|
|
186
|
-
</PortableTextEditorValueContext.Provider>
|
|
187
|
-
</PortableTextEditorContext.Provider>
|
|
188
|
-
</PortableTextEditorKeyGeneratorContext.Provider>
|
|
189
|
-
)
|
|
158
|
+
return null
|
|
190
159
|
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import {createContext, startTransition, useContext, useEffect, useState} from 'react'
|
|
2
|
+
|
|
3
|
+
import {type EditorChanges, type EditorSelection} from '../../types/editor'
|
|
4
|
+
import {debugWithName} from '../../utils/debug'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* A React context for sharing the editor selection.
|
|
8
|
+
*/
|
|
9
|
+
const PortableTextEditorSelectionContext = createContext<EditorSelection | null>(null)
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Get the current editor selection from the React context.
|
|
13
|
+
*/
|
|
14
|
+
export const usePortableTextEditorSelection = (): EditorSelection => {
|
|
15
|
+
const selection = useContext(PortableTextEditorSelectionContext)
|
|
16
|
+
|
|
17
|
+
if (selection === undefined) {
|
|
18
|
+
throw new Error(
|
|
19
|
+
`The \`usePortableTextEditorSelection\` hook must be used inside the <PortableTextEditor> component's context.`,
|
|
20
|
+
)
|
|
21
|
+
}
|
|
22
|
+
return selection
|
|
23
|
+
}
|
|
24
|
+
const debug = debugWithName('component:PortableTextEditor:SelectionProvider')
|
|
25
|
+
const debugVerbose = debug.enabled && false
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* @internal
|
|
29
|
+
*/
|
|
30
|
+
export function PortableTextEditorSelectionProvider(
|
|
31
|
+
props: React.PropsWithChildren<{
|
|
32
|
+
change$: EditorChanges
|
|
33
|
+
}>,
|
|
34
|
+
) {
|
|
35
|
+
const {change$} = props
|
|
36
|
+
const [selection, setSelection] = useState<EditorSelection>(null)
|
|
37
|
+
|
|
38
|
+
// Subscribe to, and handle changes from the editor
|
|
39
|
+
useEffect(() => {
|
|
40
|
+
debug('Subscribing to selection changes$')
|
|
41
|
+
const subscription = change$.subscribe((next): void => {
|
|
42
|
+
if (next.type === 'selection') {
|
|
43
|
+
// Set the selection state in a transition, we don't need the state immediately.
|
|
44
|
+
startTransition(() => {
|
|
45
|
+
if (debugVerbose) debug('Setting selection')
|
|
46
|
+
setSelection(next.selection)
|
|
47
|
+
})
|
|
48
|
+
}
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
return () => {
|
|
52
|
+
debug('Unsubscribing to selection changes$')
|
|
53
|
+
subscription.unsubscribe()
|
|
54
|
+
}
|
|
55
|
+
}, [change$])
|
|
56
|
+
|
|
57
|
+
return (
|
|
58
|
+
<PortableTextEditorSelectionContext.Provider value={selection}>
|
|
59
|
+
{props.children}
|
|
60
|
+
</PortableTextEditorSelectionContext.Provider>
|
|
61
|
+
)
|
|
62
|
+
}
|
package/src/types/editor.ts
CHANGED
|
@@ -394,7 +394,12 @@ export interface PasteData {
|
|
|
394
394
|
value: PortableTextBlock[] | undefined
|
|
395
395
|
}
|
|
396
396
|
|
|
397
|
-
/**
|
|
397
|
+
/**
|
|
398
|
+
* @beta
|
|
399
|
+
* It is encouraged not to return `Promise<undefined>` from the `OnPasteFn` as
|
|
400
|
+
* a mechanism to fall back to the native paste behaviour. This doesn't work in
|
|
401
|
+
* all cases. Always return plain `undefined` if possible.
|
|
402
|
+
**/
|
|
398
403
|
export type OnPasteFn = (data: PasteData) => OnPasteResultOrPromise
|
|
399
404
|
|
|
400
405
|
/** @beta */
|
package/src/utils/withChanges.ts
CHANGED
|
@@ -13,13 +13,6 @@ export function isChangingRemotely(editor: Editor): boolean | undefined {
|
|
|
13
13
|
return IS_PROCESSING_REMOTE_CHANGES.get(editor)
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
export function withLocalChanges(editor: Editor, fn: () => void): void {
|
|
17
|
-
const prev = isChangingLocally(editor) || false
|
|
18
|
-
IS_PROCESSING_LOCAL_CHANGES.set(editor, true)
|
|
19
|
-
fn()
|
|
20
|
-
IS_PROCESSING_LOCAL_CHANGES.set(editor, prev)
|
|
21
|
-
}
|
|
22
|
-
|
|
23
16
|
export function isChangingLocally(editor: Editor): boolean | undefined {
|
|
24
17
|
return IS_PROCESSING_LOCAL_CHANGES.get(editor)
|
|
25
18
|
}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import {createContext, useContext} from 'react'
|
|
2
|
-
|
|
3
|
-
import {type EditorSelection} from '../../types/editor'
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* A React context for sharing the editor selection.
|
|
7
|
-
*/
|
|
8
|
-
export const PortableTextEditorSelectionContext = createContext<EditorSelection | null>(null)
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Get the current editor selection from the React context.
|
|
12
|
-
*/
|
|
13
|
-
export const usePortableTextEditorSelection = (): EditorSelection => {
|
|
14
|
-
const selection = useContext(PortableTextEditorSelectionContext)
|
|
15
|
-
|
|
16
|
-
if (selection === undefined) {
|
|
17
|
-
throw new Error(
|
|
18
|
-
`The \`usePortableTextEditorSelection\` hook must be used inside the <PortableTextEditor> component's context.`,
|
|
19
|
-
)
|
|
20
|
-
}
|
|
21
|
-
return selection
|
|
22
|
-
}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import {type PortableTextBlock} from '@sanity/types'
|
|
2
|
-
import {createContext, useContext} from 'react'
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* A React context for sharing the editor value.
|
|
6
|
-
*/
|
|
7
|
-
export const PortableTextEditorValueContext = createContext<PortableTextBlock[] | undefined>(
|
|
8
|
-
undefined,
|
|
9
|
-
)
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Get the current editor value from the React context.
|
|
13
|
-
*/
|
|
14
|
-
export const usePortableTextEditorValue = () => {
|
|
15
|
-
return useContext(PortableTextEditorValueContext)
|
|
16
|
-
}
|