{
  "version": 3,
  "sources": ["../../../src/components/collab-sidebar/hooks.js"],
  "sourcesContent": ["import { speak } from '@wordpress/a11y';\nimport { __ } from '@wordpress/i18n';\nimport {\n\tuseState,\n\tuseEffect,\n\tuseMemo,\n\tuseSyncExternalStore,\n} from '@wordpress/element';\nimport { useEntityRecords, store as coreStore } from '@wordpress/core-data';\nimport { useDispatch, useRegistry, useSelect } from '@wordpress/data';\nimport {\n\tstore as blockEditorStore,\n\tprivateApis as blockEditorPrivateApis,\n} from '@wordpress/block-editor';\nimport { store as noticesStore } from '@wordpress/notices';\nimport { getScrollContainer } from '@wordpress/dom';\nimport { decodeEntities } from '@wordpress/html-entities';\nimport { store as interfaceStore } from '@wordpress/interface';\nimport { RichTextData, create } from '@wordpress/rich-text';\nimport { store as editorStore } from '../../store';\nimport { FLOATING_NOTES_SIDEBAR } from './constants';\nimport { unlock } from '../../lock-unlock';\nimport { createBoardStore } from './board-store';\nimport { NOTE_FORMAT_NAME } from './format';\nimport {\n\tapplyNoteFormat,\n\tcalculateNotePositions,\n\tfindNoteInBlock,\n\tgetInlineMarkerStart,\n\tgetNoteIdsFromMetadata,\n\taddNoteIdToMetadata,\n\tremoveNoteFormat,\n\tremoveNoteIdFromMetadata,\n} from './utils';\n\nconst { cleanEmptyObject } = unlock( blockEditorPrivateApis );\n\nexport function useNoteThreads( postId ) {\n\tconst queryArgs = {\n\t\tpost: postId,\n\t\ttype: 'note',\n\t\tstatus: 'all',\n\t\tper_page: -1,\n\t};\n\n\tconst { records: threads } = useEntityRecords(\n\t\t'root',\n\t\t'comment',\n\t\tqueryArgs,\n\t\t{ enabled: !! postId && typeof postId === 'number' }\n\t);\n\n\tconst { getBlockAttributes } = useSelect( blockEditorStore );\n\tconst { clientIds } = useSelect( ( select ) => {\n\t\tconst { getClientIdsWithDescendants } = select( blockEditorStore );\n\t\treturn {\n\t\t\tclientIds: getClientIdsWithDescendants(),\n\t\t};\n\t}, [] );\n\n\t// Process notes to build the tree structure.\n\tconst { notes, unresolvedNotes } = useMemo( () => {\n\t\tif ( ! threads || threads.length === 0 ) {\n\t\t\treturn { notes: [], unresolvedNotes: [] };\n\t\t}\n\n\t\t/*\n\t\t * Single pass over clientIds builds the forward map and reverse lookup\n\t\t * together. getNoteIdsFromMetadata returns numeric ids, matching the\n\t\t * types returned by the comments REST endpoint.\n\t\t */\n\t\tconst blocksWithNotes = {};\n\t\tconst clientIdByNoteId = new Map();\n\t\tfor ( const clientId of clientIds ) {\n\t\t\tconst metadata = getBlockAttributes( clientId )?.metadata;\n\t\t\tconst noteIds = getNoteIdsFromMetadata( metadata );\n\t\t\tif ( noteIds.length > 0 ) {\n\t\t\t\tblocksWithNotes[ clientId ] = noteIds;\n\t\t\t\tfor ( const noteId of noteIds ) {\n\t\t\t\t\tclientIdByNoteId.set( noteId, clientId );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Materialize threads; collect roots; replies linked in a second pass\n\t\t// via unshift to invert order (matches prior reverse semantics).\n\t\tconst threadsById = new Map();\n\t\tconst rootThreads = [];\n\t\tfor ( const item of threads ) {\n\t\t\tconst thread = {\n\t\t\t\t...item,\n\t\t\t\treply: [],\n\t\t\t\tblockClientId:\n\t\t\t\t\titem.parent === 0\n\t\t\t\t\t\t? clientIdByNoteId.get( item.id ) ?? null\n\t\t\t\t\t\t: null,\n\t\t\t};\n\t\t\tthreadsById.set( item.id, thread );\n\t\t\tif ( item.parent === 0 ) {\n\t\t\t\trootThreads.push( thread );\n\t\t\t}\n\t\t}\n\t\tfor ( const item of threads ) {\n\t\t\tif ( item.parent !== 0 ) {\n\t\t\t\tthreadsById\n\t\t\t\t\t.get( item.parent )\n\t\t\t\t\t?.reply.unshift( threadsById.get( item.id ) );\n\t\t\t}\n\t\t}\n\n\t\tif ( rootThreads.length === 0 ) {\n\t\t\treturn { notes: [], unresolvedNotes: [] };\n\t\t}\n\n\t\t// Order within a block: block-level notes (no inline anchor) come\n\t\t// first as the \"overall comment\", then inline notes ascending by\n\t\t// marker start offset. Ties (rare; two markers at the same offset)\n\t\t// fall back to creation order via thread id. Blocks themselves are\n\t\t// already iterated in document order above.\n\t\tconst unresolved = [];\n\t\tconst resolved = [];\n\t\tfor ( const [ clientId, noteIds ] of Object.entries(\n\t\t\tblocksWithNotes\n\t\t) ) {\n\t\t\tconst attributes = getBlockAttributes( clientId );\n\t\t\tconst orderedThreads = noteIds\n\t\t\t\t.map( ( noteId ) => {\n\t\t\t\t\tconst thread = threadsById.get( noteId );\n\t\t\t\t\tif ( ! thread ) {\n\t\t\t\t\t\treturn null;\n\t\t\t\t\t}\n\t\t\t\t\treturn {\n\t\t\t\t\t\tthread,\n\t\t\t\t\t\tstart: getInlineMarkerStart( thread, attributes ),\n\t\t\t\t\t};\n\t\t\t\t} )\n\t\t\t\t.filter( Boolean )\n\t\t\t\t.sort( ( a, b ) => {\n\t\t\t\t\tif ( a.start !== b.start ) {\n\t\t\t\t\t\treturn a.start - b.start;\n\t\t\t\t\t}\n\t\t\t\t\treturn a.thread.id - b.thread.id;\n\t\t\t\t} );\n\t\t\tfor ( const { thread } of orderedThreads ) {\n\t\t\t\tif ( thread.status === 'hold' ) {\n\t\t\t\t\tunresolved.push( thread );\n\t\t\t\t} else if ( thread.status === 'approved' ) {\n\t\t\t\t\tresolved.push( thread );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Orphans: root threads without a linked block. They stay with the\n\t\t// active notes (above the \"Resolved\" separator) since they may still\n\t\t// need attention even though their associated block is gone.\n\t\tconst orphans = rootThreads.filter(\n\t\t\t( thread ) => ! thread.blockClientId\n\t\t);\n\n\t\treturn {\n\t\t\tnotes: [ ...unresolved, ...orphans, ...resolved ],\n\t\t\tunresolvedNotes: unresolved,\n\t\t};\n\t}, [ clientIds, threads, getBlockAttributes ] );\n\n\treturn {\n\t\tnotes,\n\t\tunresolvedNotes,\n\t};\n}\n\n/**\n * Read an inline selection from block-editor selection state, returning\n * normalized anchor data when a non-collapsed selection sits inside a single\n * rich-text attribute. Returns null for block-level or collapsed selections.\n *\n * @param {Function} getSelectionStart Block-editor selector.\n * @param {Function} getSelectionEnd   Block-editor selector.\n * @return {?Object} { clientId, attributeKey, start, end } or null.\n */\nfunction readInlineSelection( getSelectionStart, getSelectionEnd ) {\n\tconst start = getSelectionStart();\n\tconst end = getSelectionEnd();\n\tif (\n\t\t! start?.clientId ||\n\t\tstart.clientId !== end.clientId ||\n\t\t! start.attributeKey ||\n\t\tstart.offset === undefined ||\n\t\tend.offset === undefined ||\n\t\tstart.offset === end.offset\n\t) {\n\t\treturn null;\n\t}\n\t// Normalize direction so callers don't have to think about reversed ranges.\n\tconst [ startOffset, endOffset ] =\n\t\tstart.offset < end.offset\n\t\t\t? [ start.offset, end.offset ]\n\t\t\t: [ end.offset, start.offset ];\n\treturn {\n\t\tclientId: start.clientId,\n\t\tattributeKey: start.attributeKey,\n\t\tstart: startOffset,\n\t\tend: endOffset,\n\t};\n}\n\n/**\n * Wrap a rich-text range with a core/note marker. Returns a new\n * RichTextData ready to write back into block attributes, or null when the\n * incoming value isn't a rich-text instance (legacy/string attributes).\n *\n * @param {*}      value Existing block attribute value.\n * @param {number} id    New note id to embed as `data-id`.\n * @param {number} start Range start offset.\n * @param {number} end   Range end offset.\n * @return {?RichTextData} Wrapped value or null when the attribute isn't rich text.\n */\nfunction wrapInlineNote( value, id, start, end ) {\n\tif ( ! ( value instanceof RichTextData ) ) {\n\t\treturn null;\n\t}\n\tconst record = applyNoteFormat(\n\t\tcreate( { html: value.toHTMLString() } ),\n\t\t{ type: NOTE_FORMAT_NAME, attributes: { 'data-id': String( id ) } },\n\t\tstart,\n\t\tend\n\t);\n\t// Round-trip through HTML to normalise format references (applyNoteFormat\n\t// leaves them un-normalised) so the stored value matches a fresh reload.\n\treturn RichTextData.fromHTMLString(\n\t\tnew RichTextData( record ).toHTMLString()\n\t);\n}\n\n/**\n * Strip a note's inline `core/note` marker from whichever block holds it, if\n * any, so a deleted or resolved note's highlight does not linger in the content.\n * No-op for block-level notes (those carry no marker). Used by the resolve path,\n * which only knows the note id; the delete path strips the marker inline since\n * it already has the block.\n *\n * @param {number}   noteId                      Note id whose marker to remove.\n * @param {Function} getClientIdsWithDescendants Block-editor selector.\n * @param {Function} getBlockAttributes          Block-editor selector.\n * @param {Function} updateBlockAttributes       Block-editor action.\n */\nfunction clearInlineNoteMarker(\n\tnoteId,\n\tgetClientIdsWithDescendants,\n\tgetBlockAttributes,\n\tupdateBlockAttributes\n) {\n\tfor ( const clientId of getClientIdsWithDescendants() ) {\n\t\tconst attributes = getBlockAttributes( clientId );\n\t\tconst found = findNoteInBlock( attributes, noteId );\n\t\tif ( ! found ) {\n\t\t\tcontinue;\n\t\t}\n\t\tconst next = removeNoteFormat(\n\t\t\tattributes[ found.attributeKey ],\n\t\t\tnoteId\n\t\t);\n\t\tif ( next ) {\n\t\t\tupdateBlockAttributes( clientId, { [ found.attributeKey ]: next } );\n\t\t}\n\t\treturn;\n\t}\n}\n\nexport function useNoteActions() {\n\tconst { createNotice } = useDispatch( noticesStore );\n\tconst { saveEntityRecord, deleteEntityRecord } = useDispatch( coreStore );\n\tconst { getCurrentPostId } = useSelect( editorStore );\n\tconst {\n\t\tgetBlockAttributes,\n\t\tgetClientIdsWithDescendants,\n\t\tgetSelectedBlockClientId,\n\t\tgetSelectionStart,\n\t\tgetSelectionEnd,\n\t} = useSelect( blockEditorStore );\n\tconst { updateBlockAttributes } = useDispatch( blockEditorStore );\n\n\tconst onError = ( error ) => {\n\t\tconst errorMessage =\n\t\t\terror.message && error.code !== 'unknown_error'\n\t\t\t\t? decodeEntities( error.message )\n\t\t\t\t: __( 'An error occurred while performing an update.' );\n\t\tcreateNotice( 'error', errorMessage, {\n\t\t\ttype: 'snackbar',\n\t\t\tisDismissible: true,\n\t\t} );\n\t};\n\n\tconst onCreate = async ( { content, parent } ) => {\n\t\ttry {\n\t\t\t// Capture the target block and inline selection *before* the async\n\t\t\t// save: selection may shift during the round-trip, attaching the\n\t\t\t// note to the wrong block or collapsing its inline anchor.\n\t\t\tconst inlineSelection = ! parent\n\t\t\t\t? readInlineSelection( getSelectionStart, getSelectionEnd )\n\t\t\t\t: null;\n\t\t\tconst clientId = ! parent\n\t\t\t\t? inlineSelection?.clientId || getSelectedBlockClientId()\n\t\t\t\t: null;\n\n\t\t\tconst savedRecord = await saveEntityRecord(\n\t\t\t\t'root',\n\t\t\t\t'comment',\n\t\t\t\t{\n\t\t\t\t\tpost: getCurrentPostId(),\n\t\t\t\t\tcontent,\n\t\t\t\t\tstatus: 'hold',\n\t\t\t\t\ttype: 'note',\n\t\t\t\t\tparent: parent || 0,\n\t\t\t\t},\n\t\t\t\t{ throwOnError: true }\n\t\t\t);\n\n\t\t\t/*\n\t\t\t * If it's a top-level note, update the block attributes with the\n\t\t\t * note id. Read-modify-write on metadata is racy under concurrent\n\t\t\t * edits: two near-simultaneous adds against the same base will each\n\t\t\t * write a 2-element array and the later write wins, dropping the\n\t\t\t * other id. Tracking issue:\n\t\t\t * https://github.com/WordPress/gutenberg/issues/74751.\n\t\t\t */\n\t\t\tif ( ! parent && savedRecord?.id && clientId ) {\n\t\t\t\tconst attributes = getBlockAttributes( clientId );\n\t\t\t\tconst metadata = attributes?.metadata;\n\t\t\t\tconst updatedMetadata = addNoteIdToMetadata(\n\t\t\t\t\tmetadata,\n\t\t\t\t\tsavedRecord.id\n\t\t\t\t);\n\t\t\t\tconst newAttributes = {\n\t\t\t\t\tmetadata: cleanEmptyObject( updatedMetadata ),\n\t\t\t\t};\n\n\t\t\t\t// Inline path: also wrap the selected text with a core/note\n\t\t\t\t// marker so the anchor survives later edits.\n\t\t\t\tif ( inlineSelection ) {\n\t\t\t\t\tconst wrapped = wrapInlineNote(\n\t\t\t\t\t\tattributes?.[ inlineSelection.attributeKey ],\n\t\t\t\t\t\tsavedRecord.id,\n\t\t\t\t\t\tinlineSelection.start,\n\t\t\t\t\t\tinlineSelection.end\n\t\t\t\t\t);\n\t\t\t\t\tif ( wrapped ) {\n\t\t\t\t\t\tnewAttributes[ inlineSelection.attributeKey ] = wrapped;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tupdateBlockAttributes( clientId, newAttributes );\n\t\t\t}\n\n\t\t\tcreateNotice(\n\t\t\t\t'snackbar',\n\t\t\t\tparent ? __( 'Reply added.' ) : __( 'Note added.' ),\n\t\t\t\t{\n\t\t\t\t\ttype: 'snackbar',\n\t\t\t\t\tisDismissible: true,\n\t\t\t\t}\n\t\t\t);\n\t\t\treturn savedRecord;\n\t\t} catch ( error ) {\n\t\t\tonError( error );\n\t\t}\n\t};\n\n\tconst onEdit = async ( { id, content, status } ) => {\n\t\ttry {\n\t\t\t// For resolution or reopen actions, create a new note with metadata.\n\t\t\tif ( status === 'approved' || status === 'hold' ) {\n\t\t\t\t// First, update the thread status.\n\t\t\t\tawait saveEntityRecord(\n\t\t\t\t\t'root',\n\t\t\t\t\t'comment',\n\t\t\t\t\t{\n\t\t\t\t\t\tid,\n\t\t\t\t\t\tstatus,\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tthrowOnError: true,\n\t\t\t\t\t}\n\t\t\t\t);\n\n\t\t\t\t// Then create a new note with the metadata.\n\t\t\t\tconst newNoteData = {\n\t\t\t\t\tpost: getCurrentPostId(),\n\t\t\t\t\tcontent: content || '', // Empty content for resolve, content for reopen.\n\t\t\t\t\ttype: 'note',\n\t\t\t\t\tstatus,\n\t\t\t\t\tparent: id,\n\t\t\t\t\tmeta: {\n\t\t\t\t\t\t_wp_note_status:\n\t\t\t\t\t\t\tstatus === 'approved' ? 'resolved' : 'reopen',\n\t\t\t\t\t},\n\t\t\t\t};\n\n\t\t\t\tconst savedRecord = await saveEntityRecord(\n\t\t\t\t\t'root',\n\t\t\t\t\t'comment',\n\t\t\t\t\tnewNoteData,\n\t\t\t\t\t{\n\t\t\t\t\t\tthrowOnError: true,\n\t\t\t\t\t}\n\t\t\t\t);\n\n\t\t\t\t// Resolving a note drops its inline highlight: strip the marker\n\t\t\t\t// so the note falls back to a block-level note in the content.\n\t\t\t\tif ( status === 'approved' ) {\n\t\t\t\t\tclearInlineNoteMarker(\n\t\t\t\t\t\tid,\n\t\t\t\t\t\tgetClientIdsWithDescendants,\n\t\t\t\t\t\tgetBlockAttributes,\n\t\t\t\t\t\tupdateBlockAttributes\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\t// The note visibly updates in place, so there is no snackbar,\n\t\t\t\t// but screen reader users still need the confirmation.\n\t\t\t\tspeak(\n\t\t\t\t\tstatus === 'approved'\n\t\t\t\t\t\t? __( 'Note marked as resolved.' )\n\t\t\t\t\t\t: __( 'Note reopened.' )\n\t\t\t\t);\n\n\t\t\t\treturn savedRecord;\n\t\t\t}\n\n\t\t\tconst updateData = {\n\t\t\t\tid,\n\t\t\t\tcontent,\n\t\t\t\tstatus,\n\t\t\t};\n\n\t\t\tconst savedRecord = await saveEntityRecord(\n\t\t\t\t'root',\n\t\t\t\t'comment',\n\t\t\t\tupdateData,\n\t\t\t\t{\n\t\t\t\t\tthrowOnError: true,\n\t\t\t\t}\n\t\t\t);\n\n\t\t\tcreateNotice( 'snackbar', __( 'Note updated.' ), {\n\t\t\t\ttype: 'snackbar',\n\t\t\t\tisDismissible: true,\n\t\t\t} );\n\n\t\t\treturn savedRecord;\n\t\t} catch ( error ) {\n\t\t\tonError( error );\n\t\t}\n\t};\n\n\tconst onDelete = async ( note ) => {\n\t\ttry {\n\t\t\t// Capture the target block *before* the async delete: selection may\n\t\t\t// shift during the round-trip, pointing the attribute cleanup at the\n\t\t\t// wrong block.\n\t\t\tconst clientId = ! note.parent\n\t\t\t\t? note.blockClientId || getSelectedBlockClientId()\n\t\t\t\t: null;\n\n\t\t\tawait deleteEntityRecord( 'root', 'comment', note.id, undefined, {\n\t\t\t\tthrowOnError: true,\n\t\t\t} );\n\n\t\t\tif ( clientId ) {\n\t\t\t\tconst attributes = getBlockAttributes( clientId );\n\t\t\t\tconst newAttributes = {\n\t\t\t\t\tmetadata: cleanEmptyObject(\n\t\t\t\t\t\tremoveNoteIdFromMetadata(\n\t\t\t\t\t\t\tattributes?.metadata,\n\t\t\t\t\t\t\tnote.id\n\t\t\t\t\t\t)\n\t\t\t\t\t),\n\t\t\t\t};\n\t\t\t\t// Strip the inline marker too (if any) so the deleted note's\n\t\t\t\t// highlight doesn't linger in the content. Folded into the same\n\t\t\t\t// attribute update so it's a single undo step.\n\t\t\t\tconst found = findNoteInBlock( attributes, note.id );\n\t\t\t\tif ( found ) {\n\t\t\t\t\tconst next = removeNoteFormat(\n\t\t\t\t\t\tattributes[ found.attributeKey ],\n\t\t\t\t\t\tnote.id\n\t\t\t\t\t);\n\t\t\t\t\tif ( next ) {\n\t\t\t\t\t\tnewAttributes[ found.attributeKey ] = next;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tupdateBlockAttributes( clientId, newAttributes );\n\t\t\t}\n\n\t\t\tcreateNotice( 'snackbar', __( 'Note deleted.' ), {\n\t\t\t\ttype: 'snackbar',\n\t\t\t\tisDismissible: true,\n\t\t\t} );\n\n\t\t\treturn true;\n\t\t} catch ( error ) {\n\t\t\tonError( error );\n\t\t}\n\t};\n\n\treturn { onCreate, onEdit, onDelete };\n}\n\nexport function useEnableFloatingSidebar( enabled = false ) {\n\tconst registry = useRegistry();\n\tuseEffect( () => {\n\t\tif ( ! enabled ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst { getActiveComplementaryArea } =\n\t\t\tregistry.select( interfaceStore );\n\t\tconst { disableComplementaryArea, enableComplementaryArea } =\n\t\t\tregistry.dispatch( interfaceStore );\n\n\t\tconst unsubscribe = registry.subscribe( () => {\n\t\t\t// Return `null` to indicate the user hid the complementary area.\n\t\t\tif ( getActiveComplementaryArea( 'core' ) === null ) {\n\t\t\t\tenableComplementaryArea( 'core', FLOATING_NOTES_SIDEBAR );\n\t\t\t}\n\t\t} );\n\n\t\treturn () => {\n\t\t\tunsubscribe();\n\t\t\tif (\n\t\t\t\tgetActiveComplementaryArea( 'core' ) === FLOATING_NOTES_SIDEBAR\n\t\t\t) {\n\t\t\t\tdisableComplementaryArea( 'core', FLOATING_NOTES_SIDEBAR );\n\t\t\t}\n\t\t};\n\t}, [ enabled, registry ] );\n}\n\nexport function useFloatingBoard( {\n\tthreads,\n\tselectedNoteId,\n\tisFloating,\n\tsidebarRef,\n} ) {\n\tconst [ notePositions, setNotePositions ] = useState( {} );\n\tconst [ store ] = useState( createBoardStore );\n\n\tconst heights = useSyncExternalStore( store.subscribe, store.getSnapshot );\n\n\t// Notes are positioned in canvas content-space; CSS inherits\n\t// `--canvas-scroll` to translate each thread in sync with the canvas.\n\tuseEffect( () => {\n\t\tif ( ! isFloating || ! sidebarRef?.current ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst panel = sidebarRef.current;\n\t\tconst blockEl = store.getFirstBlockElement();\n\t\t// Climb to the block-list root so nested scroll containers\n\t\t// (e.g. a Group with overflow:auto) don't shadow the canvas.\n\t\tconst rootEl = blockEl?.closest( '.is-root-container' ) ?? blockEl;\n\t\tconst canvas = rootEl ? getScrollContainer( rootEl ) : null;\n\n\t\tconst applyScroll = () => {\n\t\t\tpanel.style.setProperty(\n\t\t\t\t'--canvas-scroll',\n\t\t\t\t`${ -( canvas?.scrollTop ?? 0 ) }px`\n\t\t\t);\n\t\t};\n\n\t\t// Recalc is deferred to a rAF; back-to-back updates collapse into one paint.\n\t\tlet rafId;\n\t\tconst schedule = () => {\n\t\t\twindow.cancelAnimationFrame( rafId );\n\t\t\trafId = window.requestAnimationFrame( () => {\n\t\t\t\tconst result = calculateNotePositions( {\n\t\t\t\t\tthreads,\n\t\t\t\t\tselectedNoteId,\n\t\t\t\t\tblockRects: store.getAnchorRects(),\n\t\t\t\t\theights,\n\t\t\t\t\tscrollTop: canvas?.scrollTop ?? 0,\n\t\t\t\t} );\n\n\t\t\t\tsetNotePositions( result.positions );\n\t\t\t\tapplyScroll();\n\t\t\t} );\n\t\t};\n\n\t\tschedule();\n\n\t\t// Anchors are read from the DOM, so editing, adding or removing any\n\t\t// block leaves the threads after it stale.\n\t\tconst contentObserver = new window.ResizeObserver( schedule );\n\t\tif ( rootEl ) {\n\t\t\tcontentObserver.observe( rootEl );\n\t\t}\n\n\t\t// Root scrolling elements (documentElement/body) don't fire scroll\n\t\t// on themselves; capture on the window catches them in either canvas.\n\t\tconst view = canvas?.ownerDocument?.defaultView;\n\t\tconst listenerOptions = { passive: true, capture: true };\n\t\tview?.addEventListener( 'scroll', applyScroll, listenerOptions );\n\n\t\treturn () => {\n\t\t\twindow.cancelAnimationFrame( rafId );\n\t\t\tcontentObserver.disconnect();\n\t\t\tview?.removeEventListener( 'scroll', applyScroll, listenerOptions );\n\t\t};\n\t}, [ sidebarRef, heights, isFloating, selectedNoteId, store, threads ] );\n\n\treturn {\n\t\tnotePositions,\n\t\tregisterThread: store.registerThread,\n\t\tunregisterThread: store.unregisterThread,\n\t};\n}\n"],
  "mappings": "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",
  "names": ["blockEditorPrivateApis", "blockEditorStore", "noticesStore", "coreStore", "editorStore", "savedRecord", "interfaceStore"]
}
