chat-layout 1.2.0-2 → 1.2.0-3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +22 -18
- package/example/chat.ts +24 -11
- package/example/test.ts +4 -2
- package/index.d.mts +5 -5
- package/index.mjs +71 -39
- package/index.mjs.map +1 -1
- package/package.json +4 -1
package/README.md
CHANGED
|
@@ -28,10 +28,11 @@ const bubble = new RoundedBox(
|
|
|
28
28
|
);
|
|
29
29
|
|
|
30
30
|
const body = new ShrinkWrap(
|
|
31
|
-
new Flex(
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
31
|
+
new Flex([senderLine, bubble], {
|
|
32
|
+
direction: "column",
|
|
33
|
+
gap: 4,
|
|
34
|
+
alignItems: item.sender === "A" ? "end" : "start",
|
|
35
|
+
}),
|
|
35
36
|
);
|
|
36
37
|
|
|
37
38
|
const row = new Flex(
|
|
@@ -74,17 +75,20 @@ See [example/chat.ts](./example/chat.ts) for a full chat example.
|
|
|
74
75
|
Single-line `Text` can ellipsize at the start, end, or middle when a finite width constraint is present:
|
|
75
76
|
|
|
76
77
|
```ts
|
|
77
|
-
const title = new Text(
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
78
|
+
const title = new Text(
|
|
79
|
+
[
|
|
80
|
+
{ text: "Extremely long " },
|
|
81
|
+
{ text: "thread title", font: "700 16px system-ui", color: "#0f766e" },
|
|
82
|
+
{ text: " that should not blow out the row" },
|
|
83
|
+
],
|
|
84
|
+
{
|
|
85
|
+
lineHeight: 20,
|
|
86
|
+
font: "16px system-ui",
|
|
87
|
+
color: "#111",
|
|
88
|
+
overflow: "ellipsis",
|
|
89
|
+
ellipsisPosition: "middle",
|
|
90
|
+
},
|
|
91
|
+
);
|
|
88
92
|
```
|
|
89
93
|
|
|
90
94
|
Multi-line `MultilineText` can cap the visible line count and convert the last visible line to an end ellipsis:
|
|
@@ -119,9 +123,9 @@ const justified = new MultilineText(paragraph, {
|
|
|
119
123
|
font: "16px system-ui",
|
|
120
124
|
color: "#111",
|
|
121
125
|
align: "start",
|
|
122
|
-
justify: true,
|
|
123
|
-
justifyLastLine: false,
|
|
124
|
-
justifyGapThreshold: 2.0,
|
|
126
|
+
justify: true, // or "inter-word" | "inter-character"
|
|
127
|
+
justifyLastLine: false, // default: last line uses normal alignment
|
|
128
|
+
justifyGapThreshold: 2.0, // max gap ratio before fallback
|
|
125
129
|
});
|
|
126
130
|
```
|
|
127
131
|
|
package/example/chat.ts
CHANGED
|
@@ -195,7 +195,11 @@ const richTextMessage: InlineSpan<C>[] = [
|
|
|
195
195
|
{ text: "、" },
|
|
196
196
|
{ text: "粗体", font: "700 16px system-ui", color: "#b91c1c" },
|
|
197
197
|
{ text: ",以及 " },
|
|
198
|
-
{
|
|
198
|
+
{
|
|
199
|
+
text: "inline code",
|
|
200
|
+
font: "15px ui-monospace, SFMono-Regular, Consolas, monospace",
|
|
201
|
+
color: "#7c3aed",
|
|
202
|
+
},
|
|
199
203
|
{ text: " 这样的片段混排。" },
|
|
200
204
|
];
|
|
201
205
|
|
|
@@ -205,7 +209,11 @@ const richReplyPreview: InlineSpan<C>[] = [
|
|
|
205
209
|
{ text: ",比如 " },
|
|
206
210
|
{ text: "关键词高亮", color: "#2563eb" },
|
|
207
211
|
{ text: " 和 " },
|
|
208
|
-
{
|
|
212
|
+
{
|
|
213
|
+
text: "code()",
|
|
214
|
+
font: "12px ui-monospace, SFMono-Regular, Consolas, monospace",
|
|
215
|
+
color: "#7c3aed",
|
|
216
|
+
},
|
|
209
217
|
{
|
|
210
218
|
text: ",超长内容仍然会按原来的两行省略规则收起,不需要额外处理。",
|
|
211
219
|
},
|
|
@@ -234,13 +242,15 @@ class ItemDetector extends Wrapper<C> {
|
|
|
234
242
|
hittest(_ctx: Context<C>, test: HitTest): boolean {
|
|
235
243
|
currentHover = this.item;
|
|
236
244
|
if (test.type === "click") {
|
|
237
|
-
|
|
238
|
-
if (index < 0) {
|
|
245
|
+
if (!list.items.includes(this.item)) {
|
|
239
246
|
return true;
|
|
240
247
|
}
|
|
241
|
-
const nextItem =
|
|
248
|
+
const nextItem =
|
|
249
|
+
this.item.kind === "revoked"
|
|
250
|
+
? this.item.original
|
|
251
|
+
: revokeMessage(this.item);
|
|
242
252
|
currentHover = nextItem;
|
|
243
|
-
list.
|
|
253
|
+
list.update(this.item, nextItem, {
|
|
244
254
|
duration: REPLACE_ANIMATION_DURATION,
|
|
245
255
|
});
|
|
246
256
|
}
|
|
@@ -266,8 +276,10 @@ const renderItem = memoRenderItem((item: ChatItem): Node<C> => {
|
|
|
266
276
|
left: 12,
|
|
267
277
|
right: 12,
|
|
268
278
|
radii: 999,
|
|
269
|
-
fill: () =>
|
|
270
|
-
|
|
279
|
+
fill: () =>
|
|
280
|
+
currentHover?.id === item.id ? "#d9d9d9" : "#ececec",
|
|
281
|
+
stroke: () =>
|
|
282
|
+
currentHover?.id === item.id ? "#bcbcbc" : "#d3d3d3",
|
|
271
283
|
},
|
|
272
284
|
),
|
|
273
285
|
{
|
|
@@ -632,12 +644,13 @@ button("jump latest (no anim)", () => {
|
|
|
632
644
|
});
|
|
633
645
|
|
|
634
646
|
button("revoke first", () => {
|
|
635
|
-
const item = list.items.find(
|
|
647
|
+
const item = list.items.find(
|
|
648
|
+
(entry): entry is MessageItem => entry.kind === "message",
|
|
649
|
+
);
|
|
636
650
|
if (item == null) {
|
|
637
651
|
return;
|
|
638
652
|
}
|
|
639
|
-
|
|
640
|
-
list.replace(index, revokeMessage(item), {
|
|
653
|
+
list.update(item, revokeMessage(item), {
|
|
641
654
|
duration: REPLACE_ANIMATION_DURATION,
|
|
642
655
|
});
|
|
643
656
|
});
|
package/example/test.ts
CHANGED
|
@@ -47,8 +47,10 @@ class RoundedBox extends PaddingBox<C> {
|
|
|
47
47
|
// Reuse the current layout constraints so the background matches wrapped text.
|
|
48
48
|
const { width, height } = ctx.measureNode(this, ctx.constraints);
|
|
49
49
|
ctx.with((g) => {
|
|
50
|
-
const fill =
|
|
51
|
-
|
|
50
|
+
const fill =
|
|
51
|
+
this.fill == null ? undefined : ctx.resolveDynValue(this.fill);
|
|
52
|
+
const stroke =
|
|
53
|
+
this.stroke == null ? undefined : ctx.resolveDynValue(this.stroke);
|
|
52
54
|
g.beginPath();
|
|
53
55
|
g.roundRect(x, y, width, height, this.radii);
|
|
54
56
|
if (fill != null) {
|
package/index.d.mts
CHANGED
|
@@ -509,7 +509,7 @@ declare class DebugRenderer<C extends CanvasRenderingContext2D> extends BaseRend
|
|
|
509
509
|
/**
|
|
510
510
|
* Mutable list state shared with virtualized renderers.
|
|
511
511
|
*/
|
|
512
|
-
interface
|
|
512
|
+
interface UpdateListItemAnimationOptions {
|
|
513
513
|
/** Animation duration in milliseconds. */
|
|
514
514
|
duration?: number;
|
|
515
515
|
}
|
|
@@ -536,9 +536,9 @@ declare class ListState<T extends {}> {
|
|
|
536
536
|
/** Appends an array of items. */
|
|
537
537
|
pushAll(items: T[]): void;
|
|
538
538
|
/**
|
|
539
|
-
*
|
|
539
|
+
* Updates an existing item by object identity.
|
|
540
540
|
*/
|
|
541
|
-
|
|
541
|
+
update(targetItem: T, nextItem: T, animation?: UpdateListItemAnimationOptions): void;
|
|
542
542
|
/**
|
|
543
543
|
* Sets the current anchor item and pixel offset.
|
|
544
544
|
*/
|
|
@@ -658,7 +658,7 @@ declare abstract class VirtualizedRenderer<C extends CanvasRenderingContext2D, T
|
|
|
658
658
|
protected _finishRender(requestRedraw: boolean): boolean;
|
|
659
659
|
protected _clampItemIndex(index: number): number;
|
|
660
660
|
protected _getItemHeight(index: number): number;
|
|
661
|
-
protected _resolveItem(item: T,
|
|
661
|
+
protected _resolveItem(item: T, _index: number, now: number): {
|
|
662
662
|
value: VirtualizedResolvedItem<C>;
|
|
663
663
|
height: number;
|
|
664
664
|
};
|
|
@@ -703,5 +703,5 @@ declare class TimelineRenderer<C extends CanvasRenderingContext2D, T extends {}>
|
|
|
703
703
|
hittest(test: HitTest): boolean;
|
|
704
704
|
}
|
|
705
705
|
//#endregion
|
|
706
|
-
export { Axis, BaseRenderer, Box, ChatRenderer, ChildLayoutResult, Context, CrossAxisAlignment, DebugRenderer, DynValue, Fixed, Flex, FlexContainerOptions, FlexItem, FlexItemOptions, FlexLayoutResult, Group, HitTest, InlineSpan, JumpToOptions, LayoutConstraints, LayoutRect, ListState, MainAxisAlignment, MainAxisSize, MultilineText, MultilineTextOptions, Node, PaddingBox, PhysicalTextAlign, Place, RenderFeedback, RendererOptions,
|
|
706
|
+
export { Axis, BaseRenderer, Box, ChatRenderer, ChildLayoutResult, Context, CrossAxisAlignment, DebugRenderer, DynValue, Fixed, Flex, FlexContainerOptions, FlexItem, FlexItemOptions, FlexLayoutResult, Group, HitTest, InlineSpan, JumpToOptions, LayoutConstraints, LayoutRect, ListState, MainAxisAlignment, MainAxisSize, MultilineText, MultilineTextOptions, Node, PaddingBox, PhysicalTextAlign, Place, RenderFeedback, RendererOptions, ShrinkWrap, Text, TextAlign, TextEllipsisPosition, TextJustifyMode, TextJustifyOptions, TextOptions, TextOverflowMode, TextOverflowWrapMode, TextStyleOptions, TextWhiteSpaceMode, TextWordBreakMode, TimelineRenderer, UpdateListItemAnimationOptions, VirtualizedRenderer, Wrapper, memoRenderItem, memoRenderItemBy };
|
|
707
707
|
//# sourceMappingURL=index.d.mts.map
|
package/index.mjs
CHANGED
|
@@ -3625,6 +3625,24 @@ function subscribeListState(list, owner, listener) {
|
|
|
3625
3625
|
token
|
|
3626
3626
|
});
|
|
3627
3627
|
}
|
|
3628
|
+
function isObjectIdentityCandidate(value) {
|
|
3629
|
+
return typeof value === "object" && value !== null || typeof value === "function";
|
|
3630
|
+
}
|
|
3631
|
+
function assertUniqueItemReferences(items, existingItems) {
|
|
3632
|
+
const seen = /* @__PURE__ */ new Set();
|
|
3633
|
+
if (existingItems != null) {
|
|
3634
|
+
for (const item of existingItems) if (isObjectIdentityCandidate(item)) seen.add(item);
|
|
3635
|
+
}
|
|
3636
|
+
for (const item of items) {
|
|
3637
|
+
if (!isObjectIdentityCandidate(item)) continue;
|
|
3638
|
+
if (seen.has(item)) throw new Error("ListState items must use unique object references.");
|
|
3639
|
+
seen.add(item);
|
|
3640
|
+
}
|
|
3641
|
+
}
|
|
3642
|
+
function normalizeUpdateAnimation(animation) {
|
|
3643
|
+
if (animation == null) return;
|
|
3644
|
+
return Number.isFinite(animation.duration) ? { duration: animation.duration } : {};
|
|
3645
|
+
}
|
|
3628
3646
|
var ListState = class {
|
|
3629
3647
|
#items;
|
|
3630
3648
|
/** Pixel offset from the anchored item edge. */
|
|
@@ -3637,14 +3655,18 @@ var ListState = class {
|
|
|
3637
3655
|
}
|
|
3638
3656
|
/** Replaces the full item collection while preserving scroll state. */
|
|
3639
3657
|
set items(value) {
|
|
3640
|
-
|
|
3658
|
+
const nextItems = [...value];
|
|
3659
|
+
assertUniqueItemReferences(nextItems);
|
|
3660
|
+
this.#items = nextItems;
|
|
3641
3661
|
emitListStateChange(this, { type: "set" });
|
|
3642
3662
|
}
|
|
3643
3663
|
/**
|
|
3644
3664
|
* @param items Initial list items.
|
|
3645
3665
|
*/
|
|
3646
3666
|
constructor(items = []) {
|
|
3647
|
-
|
|
3667
|
+
const nextItems = [...items];
|
|
3668
|
+
assertUniqueItemReferences(nextItems);
|
|
3669
|
+
this.#items = nextItems;
|
|
3648
3670
|
}
|
|
3649
3671
|
/** Prepends one or more items. */
|
|
3650
3672
|
unshift(...items) {
|
|
@@ -3653,6 +3675,7 @@ var ListState = class {
|
|
|
3653
3675
|
/** Prepends an array of items. */
|
|
3654
3676
|
unshiftAll(items) {
|
|
3655
3677
|
if (items.length === 0) return;
|
|
3678
|
+
assertUniqueItemReferences(items, this.#items);
|
|
3656
3679
|
if (this.position != null) this.position += items.length;
|
|
3657
3680
|
this.#items = items.concat(this.#items);
|
|
3658
3681
|
emitListStateChange(this, {
|
|
@@ -3667,6 +3690,7 @@ var ListState = class {
|
|
|
3667
3690
|
/** Appends an array of items. */
|
|
3668
3691
|
pushAll(items) {
|
|
3669
3692
|
if (items.length === 0) return;
|
|
3693
|
+
assertUniqueItemReferences(items, this.#items);
|
|
3670
3694
|
this.#items.push(...items);
|
|
3671
3695
|
emitListStateChange(this, {
|
|
3672
3696
|
type: "push",
|
|
@@ -3674,19 +3698,21 @@ var ListState = class {
|
|
|
3674
3698
|
});
|
|
3675
3699
|
}
|
|
3676
3700
|
/**
|
|
3677
|
-
*
|
|
3701
|
+
* Updates an existing item by object identity.
|
|
3678
3702
|
*/
|
|
3679
|
-
|
|
3680
|
-
|
|
3681
|
-
if (
|
|
3682
|
-
const
|
|
3683
|
-
|
|
3703
|
+
update(targetItem, nextItem, animation) {
|
|
3704
|
+
if (!isObjectIdentityCandidate(targetItem) || !isObjectIdentityCandidate(nextItem)) throw new TypeError("update() only supports object items.");
|
|
3705
|
+
if (targetItem === nextItem) throw new Error("update() requires nextItem to be a new object reference.");
|
|
3706
|
+
const index = this.#items.indexOf(targetItem);
|
|
3707
|
+
if (index < 0) throw new Error("update() targetItem is not present in the list.");
|
|
3708
|
+
if (this.#items.includes(nextItem)) throw new Error("update() nextItem is already present in the list.");
|
|
3709
|
+
const prevItem = this.#items[index];
|
|
3710
|
+
this.#items[index] = nextItem;
|
|
3684
3711
|
emitListStateChange(this, {
|
|
3685
|
-
type: "
|
|
3686
|
-
index: normalizedIndex,
|
|
3712
|
+
type: "update",
|
|
3687
3713
|
prevItem,
|
|
3688
|
-
nextItem
|
|
3689
|
-
animation:
|
|
3714
|
+
nextItem,
|
|
3715
|
+
animation: normalizeUpdateAnimation(animation)
|
|
3690
3716
|
});
|
|
3691
3717
|
}
|
|
3692
3718
|
/**
|
|
@@ -3700,7 +3726,9 @@ var ListState = class {
|
|
|
3700
3726
|
* Replaces all items and clears scroll state.
|
|
3701
3727
|
*/
|
|
3702
3728
|
reset(items = []) {
|
|
3703
|
-
|
|
3729
|
+
const nextItems = [...items];
|
|
3730
|
+
assertUniqueItemReferences(nextItems);
|
|
3731
|
+
this.#items = nextItems;
|
|
3704
3732
|
this.offset = 0;
|
|
3705
3733
|
this.position = void 0;
|
|
3706
3734
|
emitListStateChange(this, { type: "reset" });
|
|
@@ -3808,7 +3836,8 @@ var VirtualizedRenderer = class VirtualizedRenderer extends BaseRenderer {
|
|
|
3808
3836
|
static JUMP_DURATION_PER_ITEM = 28;
|
|
3809
3837
|
#controlledState;
|
|
3810
3838
|
#jumpAnimation;
|
|
3811
|
-
#replacementAnimations = /* @__PURE__ */ new
|
|
3839
|
+
#replacementAnimations = /* @__PURE__ */ new WeakMap();
|
|
3840
|
+
#activeReplacementItems = /* @__PURE__ */ new Set();
|
|
3812
3841
|
#nextReplacementLayerKey = 0;
|
|
3813
3842
|
constructor(graphics, options) {
|
|
3814
3843
|
super(graphics, options);
|
|
@@ -3971,14 +4000,14 @@ var VirtualizedRenderer = class VirtualizedRenderer extends BaseRenderer {
|
|
|
3971
4000
|
}
|
|
3972
4001
|
_getItemHeight(index) {
|
|
3973
4002
|
const now = getNow();
|
|
3974
|
-
const replacement = this.#readReplacementAnimation(index, now);
|
|
3975
|
-
if (replacement != null) return this.#sampleReplacementHeight(replacement, now);
|
|
3976
4003
|
const item = this.items[index];
|
|
4004
|
+
const replacement = this.#readReplacementAnimation(item, now);
|
|
4005
|
+
if (replacement != null) return this.#sampleReplacementHeight(replacement, now);
|
|
3977
4006
|
const node = this.options.renderItem(item);
|
|
3978
4007
|
return this.measureRootNode(node).height;
|
|
3979
4008
|
}
|
|
3980
|
-
_resolveItem(item,
|
|
3981
|
-
const replacement = this.#readReplacementAnimation(
|
|
4009
|
+
_resolveItem(item, _index, now) {
|
|
4010
|
+
const replacement = this.#readReplacementAnimation(item, now);
|
|
3982
4011
|
if (replacement == null) {
|
|
3983
4012
|
const node = this.options.renderItem(item);
|
|
3984
4013
|
return {
|
|
@@ -4050,24 +4079,26 @@ var VirtualizedRenderer = class VirtualizedRenderer extends BaseRenderer {
|
|
|
4050
4079
|
#isLayerComplete(layer, now) {
|
|
4051
4080
|
return getProgress(layer.startTime, layer.duration, now) >= 1 && Math.abs(layer.toAlpha - this.#sampleLayerAlpha(layer, now)) <= ALPHA_EPSILON;
|
|
4052
4081
|
}
|
|
4053
|
-
#readReplacementAnimation(
|
|
4054
|
-
const animation = this.#replacementAnimations.get(
|
|
4082
|
+
#readReplacementAnimation(item, now) {
|
|
4083
|
+
const animation = this.#replacementAnimations.get(item);
|
|
4055
4084
|
if (animation == null) return;
|
|
4056
4085
|
const currentLayer = animation.layers.find((layer) => layer.key === animation.currentLayerKey);
|
|
4057
4086
|
if (currentLayer == null) {
|
|
4058
|
-
this.#replacementAnimations.delete(
|
|
4087
|
+
this.#replacementAnimations.delete(item);
|
|
4088
|
+
this.#activeReplacementItems.delete(item);
|
|
4059
4089
|
return;
|
|
4060
4090
|
}
|
|
4061
4091
|
animation.layers = animation.layers.filter((layer) => layer.key === animation.currentLayerKey || !this.#isLayerComplete(layer, now));
|
|
4062
4092
|
if (getProgress(animation.startTime, animation.duration, now) >= 1 && this.#isLayerComplete(currentLayer, now) && animation.layers.length === 1) {
|
|
4063
|
-
this.#replacementAnimations.delete(
|
|
4093
|
+
this.#replacementAnimations.delete(item);
|
|
4094
|
+
this.#activeReplacementItems.delete(item);
|
|
4064
4095
|
return;
|
|
4065
4096
|
}
|
|
4066
4097
|
return animation;
|
|
4067
4098
|
}
|
|
4068
4099
|
#prepareReplacementAnimations(now) {
|
|
4069
4100
|
let keepAnimating = false;
|
|
4070
|
-
for (const
|
|
4101
|
+
for (const item of [...this.#activeReplacementItems]) if (this.#readReplacementAnimation(item, now) != null) keepAnimating = true;
|
|
4071
4102
|
return keepAnimating;
|
|
4072
4103
|
}
|
|
4073
4104
|
#drawReplacementLayers(layers, slotHeight, y) {
|
|
@@ -4093,38 +4124,34 @@ var VirtualizedRenderer = class VirtualizedRenderer extends BaseRenderer {
|
|
|
4093
4124
|
}
|
|
4094
4125
|
#handleListStateChange(change) {
|
|
4095
4126
|
switch (change.type) {
|
|
4096
|
-
case "
|
|
4097
|
-
this.#
|
|
4127
|
+
case "update":
|
|
4128
|
+
this.#handleUpdate(change.prevItem, change.nextItem, change.animation?.duration);
|
|
4098
4129
|
break;
|
|
4099
|
-
case "unshift":
|
|
4100
|
-
if (change.count <= 0 || this.#replacementAnimations.size === 0) return;
|
|
4101
|
-
const shifted = /* @__PURE__ */ new Map();
|
|
4102
|
-
for (const [index, animation] of this.#replacementAnimations) shifted.set(index + change.count, animation);
|
|
4103
|
-
this.#replacementAnimations = shifted;
|
|
4104
|
-
break;
|
|
4105
|
-
}
|
|
4130
|
+
case "unshift":
|
|
4106
4131
|
case "push": break;
|
|
4107
4132
|
case "reset":
|
|
4108
4133
|
case "set":
|
|
4109
|
-
this.#replacementAnimations
|
|
4134
|
+
this.#replacementAnimations = /* @__PURE__ */ new WeakMap();
|
|
4135
|
+
this.#activeReplacementItems.clear();
|
|
4110
4136
|
break;
|
|
4111
4137
|
}
|
|
4112
4138
|
}
|
|
4113
|
-
#
|
|
4114
|
-
const normalizedDuration = Number.isFinite(duration) ?
|
|
4139
|
+
#handleUpdate(prevItem, nextItem, duration) {
|
|
4140
|
+
const normalizedDuration = Math.max(0, typeof duration === "number" && Number.isFinite(duration) ? duration : 0);
|
|
4115
4141
|
if (normalizedDuration <= 0) {
|
|
4116
|
-
this.#replacementAnimations.delete(
|
|
4142
|
+
this.#replacementAnimations.delete(prevItem);
|
|
4143
|
+
this.#activeReplacementItems.delete(prevItem);
|
|
4117
4144
|
return;
|
|
4118
4145
|
}
|
|
4119
4146
|
const now = getNow();
|
|
4120
4147
|
const nextNode = this.options.renderItem(nextItem);
|
|
4121
4148
|
const nextHeight = this.measureRootNode(nextNode).height;
|
|
4122
|
-
const animation = this.#readReplacementAnimation(
|
|
4149
|
+
const animation = this.#readReplacementAnimation(prevItem, now);
|
|
4123
4150
|
if (animation == null) {
|
|
4124
4151
|
const prevNode = this.options.renderItem(prevItem);
|
|
4125
4152
|
const outgoing = this.#createReplacementLayer(prevNode, 1, 0, now, normalizedDuration);
|
|
4126
4153
|
const incoming = this.#createReplacementLayer(nextNode, 0, 1, now, normalizedDuration);
|
|
4127
|
-
this.#replacementAnimations.set(
|
|
4154
|
+
this.#replacementAnimations.set(nextItem, {
|
|
4128
4155
|
currentLayerKey: incoming.key,
|
|
4129
4156
|
layers: [outgoing, incoming],
|
|
4130
4157
|
fromHeight: this.measureRootNode(prevNode).height,
|
|
@@ -4132,6 +4159,8 @@ var VirtualizedRenderer = class VirtualizedRenderer extends BaseRenderer {
|
|
|
4132
4159
|
startTime: now,
|
|
4133
4160
|
duration: normalizedDuration
|
|
4134
4161
|
});
|
|
4162
|
+
this.#activeReplacementItems.delete(prevItem);
|
|
4163
|
+
this.#activeReplacementItems.add(nextItem);
|
|
4135
4164
|
return;
|
|
4136
4165
|
}
|
|
4137
4166
|
const currentLayer = animation.layers.find((layer) => layer.key === animation.currentLayerKey);
|
|
@@ -4141,7 +4170,8 @@ var VirtualizedRenderer = class VirtualizedRenderer extends BaseRenderer {
|
|
|
4141
4170
|
if (currentAlpha > ALPHA_EPSILON) layers.push(this.#createReplacementLayer(currentNode, currentAlpha, 0, now, normalizedDuration));
|
|
4142
4171
|
const incoming = this.#createReplacementLayer(nextNode, 0, 1, now, normalizedDuration);
|
|
4143
4172
|
layers.push(incoming);
|
|
4144
|
-
this.#replacementAnimations.
|
|
4173
|
+
this.#replacementAnimations.delete(prevItem);
|
|
4174
|
+
this.#replacementAnimations.set(nextItem, {
|
|
4145
4175
|
currentLayerKey: incoming.key,
|
|
4146
4176
|
layers,
|
|
4147
4177
|
fromHeight: this.#sampleReplacementHeight(animation, now),
|
|
@@ -4149,6 +4179,8 @@ var VirtualizedRenderer = class VirtualizedRenderer extends BaseRenderer {
|
|
|
4149
4179
|
startTime: now,
|
|
4150
4180
|
duration: normalizedDuration
|
|
4151
4181
|
});
|
|
4182
|
+
this.#activeReplacementItems.delete(prevItem);
|
|
4183
|
+
this.#activeReplacementItems.add(nextItem);
|
|
4152
4184
|
}
|
|
4153
4185
|
};
|
|
4154
4186
|
//#endregion
|