DeltaComponent
Description
A component that animates changes
DeltaComponent updates its DOM tree to match a new component's DOM tree using a diff algorithm. It detects text appends and adds them as new spans to avoid full re-rendering.
This DeltaComponent renders its content inside a Shadow DOM root.
Samples
Basic Delta Animation
Shadow DOM
API reference
public class DeltaComponent : IComponentA small inline metric showing the change between two values (with up/down arrow and tone for positive / negative / neutral deltas).
- Namespace
- Tesserae
- Implements
- IComponent
Constructors
| Name | Description |
|---|---|
| DeltaComponent | Initializes a new instance of this class. |
Methods
| Name | Description |
|---|---|
| Animated | Configures the component to animated. |
| ReplaceContent | Reconciles what is on screen with newContent, in place: the nodes that match are kept and patched, and only what genuinely differs is swapped. That is the point of this component - a streamed reply re-rendered per frame keeps its scroll position, its selection and its text nodes instead of flickering - but it also means a node that stays keeps the event listeners its component gave it, so nodes are only ever reconciled with nodes of the same component (see CanReconcile). |
| DiffAndPatch | Patches current into next, or swaps it out when the two cannot be reconciled. Returns the node that is on screen afterwards, which is current for a patch and next for a swap. |
| CanReconcile | Whether two nodes may be reconciled with each other rather than swapped: the same kind of node, and the same component. A node carries the event listeners its component attached to it and no patch can move those, so re-purposing a node from one component to another leaves it answering to a component nobody can reach any more: the symptom is a control that looks right and does what its predecessor did - a tool call that became a "tools used" group mid-stream opening the chip it used to be instead of the group it is now. |
| RootClassOf | The first class on element that its component put there, skipping the ones the toolkit adds from outside. |
| MarkAsReapplying | Puts this component on the element it currently renders, so that the fluent helpers can tell in one property read whether what they are applying needs remembering. |
| RememberStyling | Records something just applied to this component, so it can be applied again to the element the component renders next. Ignored while a replay is in progress, so a replayed call does not record itself a second time. |
| ReapplyStyling | Applies everything recorded through RememberStyling to the element this component renders now, in the order it was originally applied. |
| Render | Renders the component's root HTML element. |
public void ReplaceContent(IComponent newContent)Reconciles what is on screen with newContent, in place: the nodes that match are kept and patched, and only what genuinely differs is swapped. That is the point of this component - a streamed reply re-rendered per frame keeps its scroll position, its selection and its text nodes instead of flickering - but it also means a node that stays keeps the event listeners its component gave it, so nodes are only ever reconciled with nodes of the same component (see CanReconcile).
private Node DiffAndPatch(Node current, Node next)Patches current into next, or swaps it out when the two cannot be reconciled. Returns the node that is on screen afterwards, which is current for a patch and next for a swap.
private static bool CanReconcile(Node current, Node next)Whether two nodes may be reconciled with each other rather than swapped: the same kind of node, and the same component. A node carries the event listeners its component attached to it and no patch can move those, so re-purposing a node from one component to another leaves it answering to a component nobody can reach any more: the symptom is a control that looks right and does what its predecessor did - a tool call that became a "tools used" group mid-stream opening the chip it used to be instead of the group it is now.
private static string RootClassOf(HTMLElement element)The first class on element that its component put there, skipping the ones the toolkit adds from outside.
Remarks
tss-fade-in is added by this component to every node it inserts, and tss-stack-item by the container that took the element in. Both go on the node that is on screen and never on the freshly rendered one it is compared with, and on an element with no class of its own they are the first class. Counting them made the two sides of every classless element disagree: each <strong>, <code>, <p> and <table> of a streamed Markdown reply was swapped - and faded in again - on every chunk after the one that inserted it.
private void MarkAsReapplying()Puts this component on the element it currently renders, so that the fluent helpers can tell in one property read whether what they are applying needs remembering.
Remarks
The alternative, testing the component's type in each helper, was measured at a fifth of the cost of .Class() itself - which a page calls thousands of times, virtually never on a DeltaComponent. A missing property on an element is a plain read.
internal void RememberStyling(Action reapply, bool replayAfterPatch)Records something just applied to this component, so it can be applied again to the element the component renders next. Ignored while a replay is in progress, so a replayed call does not record itself a second time.
Parameters
- reapply
- Applies the same thing again to whatever the component renders.
- replayAfterPatch
- Whether replaying it after a patch - which happens on every content change, not only on the rarer swap - is free of side effects. True for a call that writes an attribute and nothing else, which is exactly what a patch overwrites. False for anything that also attaches something the patch leaves alone: a tooltip's listener and tippy instance survive a patch, and calling for another one per frame would stack them up.
private void ReapplyStyling(bool afterPatch)Applies everything recorded through RememberStyling to the element this component renders now, in the order it was originally applied.