{options.enableClustering ? (
<>
{fadeNodes.map(({ node, phase }) => {
let content: ReactNode
const stackGroup = node.count > 1 ? stackGroupOf(node) : null
if (node.count === 1) {
const markerId = fadeNodeMarkerThreadId(node, null, openId)
const thread = markerId ? threadsById.get(markerId) : undefined
if (!thread) return null
content = renderThreadPin(thread)
} else if (stackGroup) {
// Routed through the stack's owner so the open/orphan/held slots stay deduped:
// when the owner is one of them, that slot draws the stack and this draws nothing.
const owner = stackGroup.find((id) => renderedThreadIds.has(id)) ?? null
const markerId = fadeNodeMarkerThreadId(node, owner, openId)
content = markerId ? renderThreadPin(threadsById.get(markerId)!) : null
} else {
content = (
)
}
return (
{content}
)
})}
{orphanThreads.map((thread) => (
{renderThreadPin(thread)}
))}
{heldThreads.map((thread) => (
{renderThreadPin(thread)}
))}
>
) : (
// Clustering off: every thread renders its own pin. The open thread is excluded and
// rendered once below, or it would mount a second, stacked pin.
threads
.filter((thread) => thread.id !== openId)
.map((thread) =>
{renderThreadPin(thread)})
)}
{openThread && (
{renderThreadPin(openThread)}
)}
{/* Keep the region visible while composing — the drag draft is gone by now, and no thread
exists yet, so the pending anchor is what shows the area under the open composer. */}
{pending?.anchor.type === 'region' && showPendingComposer && (
)}
{pending && showPendingComposer && (
)}