chat-layout 1.2.0-6 → 1.2.0-8
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 +3 -3
- package/example/chat.ts +16 -5
- package/index.d.mts +53 -32
- package/index.mjs +953 -719
- package/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -67,11 +67,11 @@ list.unshiftAll([olderMessage], {
|
|
|
67
67
|
});
|
|
68
68
|
```
|
|
69
69
|
|
|
70
|
-
To make chat-style inserts automatically follow the latest visible edge, pass `
|
|
70
|
+
To make chat-style inserts automatically follow the latest visible edge, pass `autoFollow: true`. When the corresponding auto-follow latch is armed, the insert behaves like a conditional `jumpToTop()` / `jumpToBottom()` after the items are inserted:
|
|
71
71
|
|
|
72
72
|
```ts
|
|
73
73
|
list.pushAll([nextMessage], {
|
|
74
|
-
|
|
74
|
+
autoFollow: true,
|
|
75
75
|
duration: 220,
|
|
76
76
|
});
|
|
77
77
|
```
|
|
@@ -178,7 +178,7 @@ Notes:
|
|
|
178
178
|
- `FlexItem` exposes `grow`, `shrink`, and `alignSelf`; `basis` is no longer public.
|
|
179
179
|
- `MultilineText` now uses `align` / `physicalAlign` instead of `alignment`.
|
|
180
180
|
- `ListState.position` uses `undefined` for the renderer default anchor.
|
|
181
|
-
- Use `list.
|
|
181
|
+
- Use `list.applyScroll(delta)` for relative scrolling, or renderer `jumpTo()` / `jumpToTop()` / `jumpToBottom()` for absolute navigation.
|
|
182
182
|
|
|
183
183
|
## Development
|
|
184
184
|
|
package/example/chat.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
|
+
Fixed,
|
|
2
3
|
Flex,
|
|
3
4
|
FlexItem,
|
|
4
|
-
Fixed,
|
|
5
5
|
ListRenderer,
|
|
6
6
|
ListState,
|
|
7
7
|
MultilineText,
|
|
@@ -505,6 +505,7 @@ const renderer = new ListRenderer(ctx, {
|
|
|
505
505
|
renderItem,
|
|
506
506
|
list,
|
|
507
507
|
});
|
|
508
|
+
renderer.padding = { top: 32, bottom: 32 };
|
|
508
509
|
let nextMessageId = list.items.length + 1;
|
|
509
510
|
|
|
510
511
|
function drawFrame(): void {
|
|
@@ -519,15 +520,26 @@ function drawFrame(): void {
|
|
|
519
520
|
renderer.render(feedback);
|
|
520
521
|
|
|
521
522
|
ctx.save();
|
|
523
|
+
|
|
524
|
+
ctx.fillStyle = "rgba(255, 0, 255, 0.5)";
|
|
525
|
+
ctx.fillRect(0, 0, canvas.clientWidth, 32);
|
|
526
|
+
ctx.fillRect(0, canvas.clientHeight - 32, canvas.clientWidth, 32);
|
|
527
|
+
|
|
522
528
|
ctx.textBaseline = "top";
|
|
523
529
|
ctx.font = "12px system-ui";
|
|
524
530
|
ctx.fillStyle = "black";
|
|
525
531
|
ctx.strokeStyle = "white";
|
|
526
532
|
ctx.lineWidth = 4;
|
|
527
533
|
ctx.lineJoin = "round";
|
|
528
|
-
const
|
|
529
|
-
|
|
530
|
-
|
|
534
|
+
const lines = Object.entries(feedback).map(
|
|
535
|
+
([key, value]) => `${key}: ${String(value)}`,
|
|
536
|
+
);
|
|
537
|
+
const lineHeight = 14;
|
|
538
|
+
for (const [index, line] of lines.entries()) {
|
|
539
|
+
const y = 10 + index * lineHeight;
|
|
540
|
+
ctx.strokeText(line, 10, y);
|
|
541
|
+
ctx.fillText(line, 10, y);
|
|
542
|
+
}
|
|
531
543
|
ctx.restore();
|
|
532
544
|
|
|
533
545
|
requestAnimationFrame(drawFrame);
|
|
@@ -662,7 +674,6 @@ button("push", () => {
|
|
|
662
674
|
},
|
|
663
675
|
],
|
|
664
676
|
{
|
|
665
|
-
distance: 24,
|
|
666
677
|
autoFollow: true,
|
|
667
678
|
},
|
|
668
679
|
);
|
package/index.d.mts
CHANGED
|
@@ -524,19 +524,24 @@ interface DeleteListItemAnimationOptions {
|
|
|
524
524
|
interface InsertListItemsAnimationOptions {
|
|
525
525
|
/** Animation duration in milliseconds. */
|
|
526
526
|
duration?: number;
|
|
527
|
-
/** Enter offset in pixels measured from the final resting position. */
|
|
528
|
-
distance?: number;
|
|
529
527
|
/** Auto-follow the insertion edge when the viewport was already pinned there. */
|
|
530
528
|
autoFollow?: boolean;
|
|
531
529
|
}
|
|
532
530
|
type PushListItemsAnimationOptions = InsertListItemsAnimationOptions;
|
|
533
531
|
type UnshiftListItemsAnimationOptions = InsertListItemsAnimationOptions;
|
|
532
|
+
type ListScrollMutationSource = "external" | "internal";
|
|
533
|
+
type ListScrollStatePatch = {
|
|
534
|
+
position?: number | undefined;
|
|
535
|
+
offset?: number;
|
|
536
|
+
};
|
|
537
|
+
declare const WRITE_LIST_SCROLL_STATE: unique symbol;
|
|
538
|
+
declare const FINALIZE_LIST_DELETE: unique symbol;
|
|
534
539
|
declare class ListState<T extends {}> {
|
|
535
540
|
#private;
|
|
536
541
|
/** Pixel offset from the anchored item edge. */
|
|
537
|
-
offset: number;
|
|
542
|
+
get offset(): number;
|
|
538
543
|
/** Anchor item index, or `undefined` to use the renderer default. */
|
|
539
|
-
position: number | undefined;
|
|
544
|
+
get position(): number | undefined;
|
|
540
545
|
/** Items currently managed by the renderer. */
|
|
541
546
|
get items(): T[];
|
|
542
547
|
/** Replaces the full item collection while preserving scroll state. */
|
|
@@ -564,19 +569,14 @@ declare class ListState<T extends {}> {
|
|
|
564
569
|
/**
|
|
565
570
|
* Finalizes a pending delete by removing the item from the list.
|
|
566
571
|
*/
|
|
567
|
-
|
|
568
|
-
/**
|
|
569
|
-
* Sets the current anchor item and pixel offset.
|
|
570
|
-
*/
|
|
571
|
-
setAnchor(position: number, offset?: number): void;
|
|
572
|
+
[FINALIZE_LIST_DELETE](item: T): void;
|
|
572
573
|
/**
|
|
573
574
|
* Replaces all items and clears scroll state.
|
|
574
575
|
*/
|
|
575
576
|
reset(items?: T[]): void;
|
|
576
|
-
/** Clears the current scroll anchor while keeping the items. */
|
|
577
|
-
resetScroll(): void;
|
|
578
577
|
/** Applies a relative pixel scroll delta. */
|
|
579
578
|
applyScroll(delta: number): void;
|
|
579
|
+
[WRITE_LIST_SCROLL_STATE](patch: ListScrollStatePatch, source: ListScrollMutationSource): void;
|
|
580
580
|
}
|
|
581
581
|
//#endregion
|
|
582
582
|
//#region src/renderer/memo.d.ts
|
|
@@ -596,27 +596,34 @@ declare function memoRenderItemBy<C extends CanvasRenderingContext2D, T, K>(keyO
|
|
|
596
596
|
resetKey: (key: K) => boolean;
|
|
597
597
|
};
|
|
598
598
|
//#endregion
|
|
599
|
-
//#region src/renderer/virtualized/base-types.d.ts
|
|
600
|
-
type AutoFollowCapabilities = {
|
|
601
|
-
top: boolean;
|
|
602
|
-
bottom: boolean;
|
|
603
|
-
};
|
|
604
|
-
/** Per-item draw/hittest callbacks produced by the resolver. */
|
|
605
|
-
type VirtualizedResolvedItem = {
|
|
606
|
-
draw: (y: number) => boolean;
|
|
607
|
-
hittest: (test: HitTest, y: number) => boolean;
|
|
608
|
-
};
|
|
609
|
-
//#endregion
|
|
610
599
|
//#region src/renderer/virtualized/solver.d.ts
|
|
611
600
|
type ListAnchorMode = "top" | "bottom";
|
|
612
601
|
type ListUnderflowAlign = "top" | "bottom";
|
|
602
|
+
interface ListPadding {
|
|
603
|
+
top?: number;
|
|
604
|
+
bottom?: number;
|
|
605
|
+
}
|
|
606
|
+
interface ResolvedListPadding {
|
|
607
|
+
top: number;
|
|
608
|
+
bottom: number;
|
|
609
|
+
}
|
|
613
610
|
interface ListLayoutOptions {
|
|
614
611
|
anchorMode?: ListAnchorMode;
|
|
615
612
|
underflowAlign?: ListUnderflowAlign;
|
|
613
|
+
padding?: ListPadding;
|
|
616
614
|
}
|
|
617
615
|
interface ResolvedListLayoutOptions {
|
|
618
616
|
anchorMode: ListAnchorMode;
|
|
619
617
|
underflowAlign: ListUnderflowAlign;
|
|
618
|
+
padding: ResolvedListPadding;
|
|
619
|
+
}
|
|
620
|
+
interface ListViewportMetrics {
|
|
621
|
+
outerHeight: number;
|
|
622
|
+
contentTop: number;
|
|
623
|
+
contentBottom: number;
|
|
624
|
+
contentHeight: number;
|
|
625
|
+
outerContentTop: number;
|
|
626
|
+
outerContentBottom: number;
|
|
620
627
|
}
|
|
621
628
|
interface VisibleListState {
|
|
622
629
|
position?: number;
|
|
@@ -627,7 +634,7 @@ interface NormalizedListState {
|
|
|
627
634
|
offset: number;
|
|
628
635
|
}
|
|
629
636
|
interface VisibleWindowEntry<T> {
|
|
630
|
-
|
|
637
|
+
index: number;
|
|
631
638
|
value: T;
|
|
632
639
|
offset: number;
|
|
633
640
|
height: number;
|
|
@@ -642,6 +649,17 @@ interface VisibleWindowResult<T> {
|
|
|
642
649
|
window: VisibleWindow<T>;
|
|
643
650
|
}
|
|
644
651
|
//#endregion
|
|
652
|
+
//#region src/renderer/virtualized/virtualized-types.d.ts
|
|
653
|
+
type AutoFollowCapabilities = {
|
|
654
|
+
top: boolean;
|
|
655
|
+
bottom: boolean;
|
|
656
|
+
};
|
|
657
|
+
/** Per-item draw/hittest callbacks produced by the resolver. */
|
|
658
|
+
type VirtualizedResolvedItem = {
|
|
659
|
+
draw: (y: number) => boolean;
|
|
660
|
+
hittest: (test: HitTest, y: number) => boolean;
|
|
661
|
+
};
|
|
662
|
+
//#endregion
|
|
645
663
|
//#region src/renderer/virtualized/base.d.ts
|
|
646
664
|
/**
|
|
647
665
|
* Options for programmatic scrolling to a target item.
|
|
@@ -673,12 +691,8 @@ declare abstract class VirtualizedRenderer<C extends CanvasRenderingContext2D, T
|
|
|
673
691
|
});
|
|
674
692
|
/** Current anchor item index. */
|
|
675
693
|
get position(): number | undefined;
|
|
676
|
-
/** Updates the current anchor item index. */
|
|
677
|
-
set position(value: number | undefined);
|
|
678
694
|
/** Pixel offset from the anchored item edge. */
|
|
679
695
|
get offset(): number;
|
|
680
|
-
/** Updates the pixel offset from the anchored item edge. */
|
|
681
|
-
set offset(value: number);
|
|
682
696
|
/** Items currently available to the renderer. */
|
|
683
697
|
get items(): T[];
|
|
684
698
|
/** Replaces the current item collection. */
|
|
@@ -709,15 +723,19 @@ declare abstract class VirtualizedRenderer<C extends CanvasRenderingContext2D, T
|
|
|
709
723
|
protected _resetRenderFeedback(feedback?: RenderFeedback): void;
|
|
710
724
|
protected _accumulateRenderFeedback(feedback: RenderFeedback, idx: number, top: number, height: number): void;
|
|
711
725
|
protected _renderDrawList(list: VisibleWindow<VirtualizedResolvedItem>["drawList"], shift: number, feedback?: RenderFeedback): boolean;
|
|
712
|
-
protected _renderVisibleWindow(window: VisibleWindow<VirtualizedResolvedItem>, feedback?: RenderFeedback
|
|
713
|
-
protected _readAutoFollowCapabilities(window: VisibleWindow<VirtualizedResolvedItem
|
|
726
|
+
protected _renderVisibleWindow(window: VisibleWindow<VirtualizedResolvedItem>, feedback?: RenderFeedback): boolean;
|
|
727
|
+
protected _readAutoFollowCapabilities(window: VisibleWindow<VirtualizedResolvedItem>): AutoFollowCapabilities;
|
|
714
728
|
protected _readVisibleRange(top: number, height: number): {
|
|
715
729
|
top: number;
|
|
716
730
|
bottom: number;
|
|
717
731
|
} | undefined;
|
|
732
|
+
protected _readOuterVisibleRange(top: number, height: number): {
|
|
733
|
+
top: number;
|
|
734
|
+
bottom: number;
|
|
735
|
+
} | undefined;
|
|
718
736
|
protected _pruneTransitionAnimations(_window: VisibleWindow<unknown>, now: number): boolean;
|
|
719
|
-
protected _hittestVisibleWindow(window: VisibleWindow<VirtualizedResolvedItem>, test: HitTest
|
|
720
|
-
protected _captureVisibleItemSnapshot(solution: VisibleWindowResult<unknown
|
|
737
|
+
protected _hittestVisibleWindow(window: VisibleWindow<VirtualizedResolvedItem>, test: HitTest): boolean;
|
|
738
|
+
protected _captureVisibleItemSnapshot(solution: VisibleWindowResult<unknown>): void;
|
|
721
739
|
protected _prepareRender(now: number): boolean;
|
|
722
740
|
protected _finishRender(requestRedraw: boolean): boolean;
|
|
723
741
|
protected _clampItemIndex(index: number): number;
|
|
@@ -736,6 +754,7 @@ declare abstract class VirtualizedRenderer<C extends CanvasRenderingContext2D, T
|
|
|
736
754
|
protected abstract _applyAnchor(anchor: number): void;
|
|
737
755
|
protected abstract _getDefaultJumpBlock(): NonNullable<JumpToOptions["block"]>;
|
|
738
756
|
protected abstract _getTargetAnchor(index: number, block: NonNullable<JumpToOptions["block"]>): number;
|
|
757
|
+
protected _getViewportMetrics(): ListViewportMetrics;
|
|
739
758
|
}
|
|
740
759
|
//#endregion
|
|
741
760
|
//#region src/renderer/virtualized/list.d.ts
|
|
@@ -749,6 +768,8 @@ interface ListRendererOptions<C extends CanvasRenderingContext2D, T extends {}>
|
|
|
749
768
|
declare class ListRenderer<C extends CanvasRenderingContext2D, T extends {}> extends VirtualizedRenderer<C, T> {
|
|
750
769
|
#private;
|
|
751
770
|
constructor(graphics: C, options: ListRendererOptions<C, T>);
|
|
771
|
+
get padding(): ListPadding;
|
|
772
|
+
set padding(value: ListPadding);
|
|
752
773
|
protected _getLayoutOptions(): ResolvedListLayoutOptions;
|
|
753
774
|
protected _resolveVisibleWindowForState(state: VisibleListState, now: number): VisibleWindowResult<VirtualizedResolvedItem>;
|
|
754
775
|
protected _getDefaultJumpBlock(): NonNullable<JumpToOptions["block"]>;
|
|
@@ -758,5 +779,5 @@ declare class ListRenderer<C extends CanvasRenderingContext2D, T extends {}> ext
|
|
|
758
779
|
protected _getTargetAnchor(index: number, block: NonNullable<JumpToOptions["block"]>): number;
|
|
759
780
|
}
|
|
760
781
|
//#endregion
|
|
761
|
-
export { Axis, BaseRenderer, Box, ChildLayoutResult, Context, CrossAxisAlignment, DebugRenderer, DeleteListItemAnimationOptions, DynValue, Fixed, Flex, FlexContainerOptions, FlexItem, FlexItemOptions, FlexLayoutResult, Group, HitTest, InlineSpan, InsertListItemsAnimationOptions, JumpToOptions, LayoutConstraints, LayoutRect, ListAnchorMode, ListLayoutOptions, ListRenderer, ListRendererOptions, ListState, ListUnderflowAlign, MainAxisAlignment, MainAxisSize, MultilineText, MultilineTextOptions, Node, PaddingBox, PhysicalTextAlign, Place, PushListItemsAnimationOptions, RenderFeedback, RendererOptions, ShrinkWrap, Text, TextAlign, TextEllipsisPosition, TextJustifyMode, TextJustifyOptions, TextOptions, TextOverflowMode, TextOverflowWrapMode, TextStyleOptions, TextWhiteSpaceMode, TextWordBreakMode, UnshiftListItemsAnimationOptions, UpdateListItemAnimationOptions, VirtualizedRenderer, Wrapper, memoRenderItem, memoRenderItemBy };
|
|
782
|
+
export { Axis, BaseRenderer, Box, ChildLayoutResult, Context, CrossAxisAlignment, DebugRenderer, DeleteListItemAnimationOptions, DynValue, Fixed, Flex, FlexContainerOptions, FlexItem, FlexItemOptions, FlexLayoutResult, Group, HitTest, InlineSpan, InsertListItemsAnimationOptions, JumpToOptions, LayoutConstraints, LayoutRect, ListAnchorMode, ListLayoutOptions, ListPadding, ListRenderer, ListRendererOptions, ListState, ListUnderflowAlign, MainAxisAlignment, MainAxisSize, MultilineText, MultilineTextOptions, Node, PaddingBox, PhysicalTextAlign, Place, PushListItemsAnimationOptions, RenderFeedback, RendererOptions, ShrinkWrap, Text, TextAlign, TextEllipsisPosition, TextJustifyMode, TextJustifyOptions, TextOptions, TextOverflowMode, TextOverflowWrapMode, TextStyleOptions, TextWhiteSpaceMode, TextWordBreakMode, UnshiftListItemsAnimationOptions, UpdateListItemAnimationOptions, VirtualizedRenderer, Wrapper, memoRenderItem, memoRenderItemBy };
|
|
762
783
|
//# sourceMappingURL=index.d.mts.map
|