Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 32 additions & 5 deletions apps/docs/app/(diffs)/docs/ReactAPI/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,34 @@ const cleanupByNode = new WeakMap<HTMLElement, () => void>();
options={{
onPostRender(node, _instance, phase) {
if (phase === 'mount') {
const observer = new ResizeObserver(() => {
console.log(node.getBoundingClientRect().height);
const selectionRoot = node.shadowRoot ?? node;

const handleSelectStart = () => {
console.log('selection started in diff');
};

const handleSelectionChange = () => {
const selection = document.getSelection();
if (selection == null || selection.isCollapsed) {
return;
}

if (
!containsSelectionNode(selectionRoot, selection.anchorNode) &&
!containsSelectionNode(selectionRoot, selection.focusNode)
) {
return;
}

console.log('selected text', selection.toString());
};

selectionRoot.addEventListener('selectstart', handleSelectStart);
document.addEventListener('selectionchange', handleSelectionChange);
cleanupByNode.set(node, () => {
selectionRoot.removeEventListener('selectstart', handleSelectStart);
document.removeEventListener('selectionchange', handleSelectionChange);
});
observer.observe(node);
cleanupByNode.set(node, () => observer.disconnect());
return;
}

Expand All @@ -34,7 +57,11 @@ const cleanupByNode = new WeakMap<HTMLElement, () => void>();
}
},
}}
/>`,
/>

function containsSelectionNode(root: Node, node: Node | null) {
return node != null && root.contains(node);
}`,
},
options,
};
Expand Down
8 changes: 4 additions & 4 deletions apps/docs/app/(diffs)/docs/ReactAPI/content.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,10 @@ a container node, `phase: 'update'` after later DOM-committing renders, and
`phase: 'unmount'` before a mounted container node is removed, replaced, cleaned
up, or recycled.

Use this callback for DOM-node-associated work such as observers, measurements,
or imperative integrations. Treat `unmount` as node-centric: if you need
teardown state, capture it by `node` when the node mounts instead of depending
on mutable instance fields.
Use this callback when native DOM selection listeners need access to the
rendered diff node or its shadow DOM. Attach listeners such as `selectstart` and
`selectionchange` during `mount`, and remove them during `unmount` with teardown
state captured by `node`.

<DocsCodeExample {...postRenderLifecycleExample} />

Expand Down
37 changes: 32 additions & 5 deletions apps/docs/app/(diffs)/docs/VanillaAPI/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,34 @@ const cleanupByNode = new WeakMap<HTMLElement, () => void>();
const instance = new FileDiff({
onPostRender(node, _instance, phase) {
if (phase === 'mount') {
const observer = new ResizeObserver(() => {
console.log(node.getBoundingClientRect().height);
const selectionRoot = node.shadowRoot ?? node;

const handleSelectStart = () => {
console.log('selection started in diff');
};

const handleSelectionChange = () => {
const selection = document.getSelection();
if (selection == null || selection.isCollapsed) {
return;
}

if (
!containsSelectionNode(selectionRoot, selection.anchorNode) &&
!containsSelectionNode(selectionRoot, selection.focusNode)
) {
return;
}

console.log('selected text', selection.toString());
};

selectionRoot.addEventListener('selectstart', handleSelectStart);
document.addEventListener('selectionchange', handleSelectionChange);
cleanupByNode.set(node, () => {
selectionRoot.removeEventListener('selectstart', handleSelectStart);
document.removeEventListener('selectionchange', handleSelectionChange);
});
observer.observe(node);
cleanupByNode.set(node, () => observer.disconnect());
return;
}

Expand All @@ -32,7 +55,11 @@ const instance = new FileDiff({
cleanupByNode.delete(node);
}
},
});`,
});

function containsSelectionNode(root: Node, node: Node | null) {
return node != null && root.contains(node);
}`,
},
options,
};
Expand Down
8 changes: 4 additions & 4 deletions apps/docs/app/(diffs)/docs/VanillaAPI/content.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,10 @@ container node, `phase: 'update'` after later DOM-committing renders, and
`phase: 'unmount'` before a mounted container node is removed, replaced, cleaned
up, or recycled.

Use this callback for DOM-node-associated work such as observers, measurements,
or imperative integrations. Treat `unmount` as node-centric: if you need
teardown state, capture it by `node` when the node mounts instead of depending
on mutable instance fields.
Use this callback when native DOM selection listeners need access to the
rendered diff node or its shadow DOM. Attach listeners such as `selectstart` and
`selectionchange` during `mount`, and remove them during `unmount` with teardown
state captured by `node`.

<DocsCodeExample {...postRenderLifecycleExample} />

Expand Down
Loading