chat-layout 1.2.0-6 → 1.2.0-7

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 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 `followIfAtBoundary: true`. When the viewport was already pinned to that edge, the insert behaves like a conditional `jumpTo()` instead of combining with the enter animation:
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
- followIfAtBoundary: true,
74
+ autoFollow: true,
75
75
  duration: 220,
76
76
  });
77
77
  ```
package/example/chat.ts CHANGED
@@ -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 text = JSON.stringify(feedback);
529
- ctx.strokeText(text, 10, 10);
530
- ctx.fillText(text, 10, 10);
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,25 @@ 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;
534
538
  declare class ListState<T extends {}> {
535
539
  #private;
536
540
  /** Pixel offset from the anchored item edge. */
537
- offset: number;
541
+ get offset(): number;
542
+ set offset(value: number);
538
543
  /** Anchor item index, or `undefined` to use the renderer default. */
539
- position: number | undefined;
544
+ get position(): number | undefined;
545
+ set position(value: number | undefined);
540
546
  /** Items currently managed by the renderer. */
541
547
  get items(): T[];
542
548
  /** Replaces the full item collection while preserving scroll state. */
@@ -577,6 +583,7 @@ declare class ListState<T extends {}> {
577
583
  resetScroll(): void;
578
584
  /** Applies a relative pixel scroll delta. */
579
585
  applyScroll(delta: number): void;
586
+ [WRITE_LIST_SCROLL_STATE](patch: ListScrollStatePatch, source: ListScrollMutationSource): void;
580
587
  }
581
588
  //#endregion
582
589
  //#region src/renderer/memo.d.ts
@@ -610,13 +617,31 @@ type VirtualizedResolvedItem = {
610
617
  //#region src/renderer/virtualized/solver.d.ts
611
618
  type ListAnchorMode = "top" | "bottom";
612
619
  type ListUnderflowAlign = "top" | "bottom";
620
+ interface ListPadding {
621
+ top?: number;
622
+ bottom?: number;
623
+ }
624
+ interface ResolvedListPadding {
625
+ top: number;
626
+ bottom: number;
627
+ }
613
628
  interface ListLayoutOptions {
614
629
  anchorMode?: ListAnchorMode;
615
630
  underflowAlign?: ListUnderflowAlign;
631
+ padding?: ListPadding;
616
632
  }
617
633
  interface ResolvedListLayoutOptions {
618
634
  anchorMode: ListAnchorMode;
619
635
  underflowAlign: ListUnderflowAlign;
636
+ padding: ResolvedListPadding;
637
+ }
638
+ interface ListViewportMetrics {
639
+ outerHeight: number;
640
+ contentTop: number;
641
+ contentBottom: number;
642
+ contentHeight: number;
643
+ outerContentTop: number;
644
+ outerContentBottom: number;
620
645
  }
621
646
  interface VisibleListState {
622
647
  position?: number;
@@ -709,15 +734,19 @@ declare abstract class VirtualizedRenderer<C extends CanvasRenderingContext2D, T
709
734
  protected _resetRenderFeedback(feedback?: RenderFeedback): void;
710
735
  protected _accumulateRenderFeedback(feedback: RenderFeedback, idx: number, top: number, height: number): void;
711
736
  protected _renderDrawList(list: VisibleWindow<VirtualizedResolvedItem>["drawList"], shift: number, feedback?: RenderFeedback): boolean;
712
- protected _renderVisibleWindow(window: VisibleWindow<VirtualizedResolvedItem>, feedback?: RenderFeedback, extraShift?: number): boolean;
713
- protected _readAutoFollowCapabilities(window: VisibleWindow<VirtualizedResolvedItem>, extraShift?: number): AutoFollowCapabilities;
737
+ protected _renderVisibleWindow(window: VisibleWindow<VirtualizedResolvedItem>, feedback?: RenderFeedback): boolean;
738
+ protected _readAutoFollowCapabilities(window: VisibleWindow<VirtualizedResolvedItem>): AutoFollowCapabilities;
714
739
  protected _readVisibleRange(top: number, height: number): {
715
740
  top: number;
716
741
  bottom: number;
717
742
  } | undefined;
743
+ protected _readOuterVisibleRange(top: number, height: number): {
744
+ top: number;
745
+ bottom: number;
746
+ } | undefined;
718
747
  protected _pruneTransitionAnimations(_window: VisibleWindow<unknown>, now: number): boolean;
719
- protected _hittestVisibleWindow(window: VisibleWindow<VirtualizedResolvedItem>, test: HitTest, extraShift?: number): boolean;
720
- protected _captureVisibleItemSnapshot(solution: VisibleWindowResult<unknown>, extraShift?: number): void;
748
+ protected _hittestVisibleWindow(window: VisibleWindow<VirtualizedResolvedItem>, test: HitTest): boolean;
749
+ protected _captureVisibleItemSnapshot(solution: VisibleWindowResult<unknown>): void;
721
750
  protected _prepareRender(now: number): boolean;
722
751
  protected _finishRender(requestRedraw: boolean): boolean;
723
752
  protected _clampItemIndex(index: number): number;
@@ -736,6 +765,7 @@ declare abstract class VirtualizedRenderer<C extends CanvasRenderingContext2D, T
736
765
  protected abstract _applyAnchor(anchor: number): void;
737
766
  protected abstract _getDefaultJumpBlock(): NonNullable<JumpToOptions["block"]>;
738
767
  protected abstract _getTargetAnchor(index: number, block: NonNullable<JumpToOptions["block"]>): number;
768
+ protected _getViewportMetrics(): ListViewportMetrics;
739
769
  }
740
770
  //#endregion
741
771
  //#region src/renderer/virtualized/list.d.ts
@@ -749,6 +779,8 @@ interface ListRendererOptions<C extends CanvasRenderingContext2D, T extends {}>
749
779
  declare class ListRenderer<C extends CanvasRenderingContext2D, T extends {}> extends VirtualizedRenderer<C, T> {
750
780
  #private;
751
781
  constructor(graphics: C, options: ListRendererOptions<C, T>);
782
+ get padding(): ListPadding;
783
+ set padding(value: ListPadding);
752
784
  protected _getLayoutOptions(): ResolvedListLayoutOptions;
753
785
  protected _resolveVisibleWindowForState(state: VisibleListState, now: number): VisibleWindowResult<VirtualizedResolvedItem>;
754
786
  protected _getDefaultJumpBlock(): NonNullable<JumpToOptions["block"]>;
@@ -758,5 +790,5 @@ declare class ListRenderer<C extends CanvasRenderingContext2D, T extends {}> ext
758
790
  protected _getTargetAnchor(index: number, block: NonNullable<JumpToOptions["block"]>): number;
759
791
  }
760
792
  //#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 };
793
+ 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
794
  //# sourceMappingURL=index.d.mts.map