@sanity/visual-editing
Version:
[](https://npm-stat.com/charts.html?package=@sanity/visual-editing) [](https://
73 lines (67 loc) • 2.28 kB
text/typescript
import type {ClientPerspective, ContentSourceMapDocuments} from '@sanity/client'
import {useCallback, useEffect, useRef} from 'react'
import type {ElementState, SanityNode, VisualEditingNode} from '../types'
function isEqualSets(a: Set<string>, b: Set<string>) {
if (a === b) return true
if (a.size !== b.size) return false
for (const value of a) if (!b.has(value)) return false
return true
}
/**
* Hook for reporting in use documents to Presentation
* @internal
*/
export function useReportDocuments(
comlink: VisualEditingNode | undefined,
elements: ElementState[],
perspective: ClientPerspective,
): void {
const lastReported = useRef<
| {
nodeIds: Set<string>
perspective: ClientPerspective
}
| undefined
>(undefined)
const reportDocuments = useCallback(
(documents: ContentSourceMapDocuments, perspective: ClientPerspective) => {
comlink?.post('visual-editing/documents', {
documents,
perspective,
})
},
[comlink],
)
useEffect(() => {
// Report only nodes of type `SanityNode`. Untransformed `SanityStegaNode`
// nodes without an `id`, are not reported as they will not contain the
// necessary document data.
const nodes = elements
.map((e) => {
const {sanity} = e
if (!sanity || !('id' in sanity)) return null
return sanity
})
.filter((s) => !!s) as SanityNode[]
const nodeIds = new Set<string>(nodes.map((e) => e.id))
// Report if:
// - Documents not yet reported
// - Document IDs changed
// - Perspective changed
if (
!lastReported.current ||
!isEqualSets(nodeIds, lastReported.current.nodeIds) ||
perspective !== lastReported.current.perspective
) {
const documentsOnPage: ContentSourceMapDocuments = Array.from(nodeIds).map((_id) => {
const node = nodes.find((node) => node.id === _id)!
const {type, projectId: _projectId, dataset: _dataset} = node
return _projectId && _dataset
? {_id, _type: type!, _projectId, _dataset}
: {_id, _type: type!}
})
lastReported.current = {nodeIds, perspective}
reportDocuments(documentsOnPage, perspective)
}
}, [elements, perspective, reportDocuments])
}