chat-layout 0.1.2 → 0.1.4

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/index.d.mts CHANGED
@@ -197,10 +197,19 @@ type DrawItem<C extends CanvasRenderingContext2D> = {
197
197
  offset: number;
198
198
  height: number;
199
199
  };
200
+ interface JumpToOptions {
201
+ animated?: boolean;
202
+ duration?: number;
203
+ onComplete?: () => void;
204
+ }
200
205
  declare abstract class VirtualizedRenderer<C extends CanvasRenderingContext2D, T extends {}> extends BaseRenderer<C, {
201
206
  renderItem: (item: T) => Node<C>;
202
207
  list: ListState<T>;
203
208
  }> {
209
+ #private;
210
+ static readonly MIN_JUMP_DURATION = 160;
211
+ static readonly MAX_JUMP_DURATION = 420;
212
+ static readonly JUMP_DURATION_PER_ITEM = 28;
204
213
  get position(): number;
205
214
  set position(value: number);
206
215
  get offset(): number;
@@ -209,15 +218,32 @@ declare abstract class VirtualizedRenderer<C extends CanvasRenderingContext2D, T
209
218
  set items(value: T[]);
210
219
  abstract render(feedback?: RenderFeedback): boolean;
211
220
  abstract hittest(test: HitTest): boolean;
221
+ jumpTo(index: number, options?: JumpToOptions): void;
212
222
  protected _resetRenderFeedback(feedback?: RenderFeedback): void;
213
223
  protected _accumulateRenderFeedback(feedback: RenderFeedback, idx: number, top: number, height: number): void;
214
224
  protected _renderDrawList(list: DrawItem<C>[], shift: number, feedback?: RenderFeedback): boolean;
225
+ protected _prepareRender(): boolean;
226
+ protected _finishRender(requestRedraw: boolean): boolean;
227
+ protected _clampItemIndex(index: number): number;
228
+ protected _getItemHeight(index: number): number;
229
+ protected abstract _prepareAnchorState(): void;
230
+ protected abstract _readAnchor(): number;
231
+ protected abstract _applyAnchor(anchor: number): void;
232
+ protected abstract _getTargetAnchor(index: number): number;
215
233
  }
216
234
  declare class TimelineRenderer<C extends CanvasRenderingContext2D, T extends {}> extends VirtualizedRenderer<C, T> {
235
+ protected _prepareAnchorState(): void;
236
+ protected _readAnchor(): number;
237
+ protected _applyAnchor(anchor: number): void;
238
+ protected _getTargetAnchor(index: number): number;
217
239
  render(feedback?: RenderFeedback): boolean;
218
240
  hittest(test: HitTest): boolean;
219
241
  }
220
242
  declare class ChatRenderer<C extends CanvasRenderingContext2D, T extends {}> extends VirtualizedRenderer<C, T> {
243
+ protected _prepareAnchorState(): void;
244
+ protected _readAnchor(): number;
245
+ protected _applyAnchor(anchor: number): void;
246
+ protected _getTargetAnchor(index: number): number;
221
247
  render(feedback?: RenderFeedback): boolean;
222
248
  hittest(test: HitTest): boolean;
223
249
  }
@@ -227,5 +253,5 @@ declare function registerNodeParent<C extends CanvasRenderingContext2D>(node: No
227
253
  declare function unregisterNodeParent<C extends CanvasRenderingContext2D>(node: Node<C>): void;
228
254
  declare function getNodeParent<C extends CanvasRenderingContext2D>(node: Node<C>): Node<C> | undefined;
229
255
  //#endregion
230
- export { AlignBox, Alignment, BaseRenderer, Box, ChatRenderer, Context, DebugRenderer, DynValue, Fixed, Group, HStack, HitTest, ListState, MultilineText, Node, PaddingBox, RenderFeedback, RendererOptions, Text, TimelineRenderer, VStack, VirtualizedRenderer, Wrapper, getNodeParent, memoRenderItem, registerNodeParent, unregisterNodeParent };
256
+ export { AlignBox, Alignment, BaseRenderer, Box, ChatRenderer, Context, DebugRenderer, DynValue, Fixed, Group, HStack, HitTest, JumpToOptions, ListState, MultilineText, Node, PaddingBox, RenderFeedback, RendererOptions, Text, TimelineRenderer, VStack, VirtualizedRenderer, Wrapper, getNodeParent, memoRenderItem, registerNodeParent, unregisterNodeParent };
231
257
  //# sourceMappingURL=index.d.mts.map
package/index.mjs CHANGED
@@ -596,7 +596,21 @@ var ListState = class {
596
596
  function clamp(value, min, max) {
597
597
  return Math.min(Math.max(value, min), max);
598
598
  }
599
- var VirtualizedRenderer = class extends BaseRenderer {
599
+ function sameState(state, position, offset) {
600
+ return Object.is(state.position, position) && Object.is(state.offset, offset);
601
+ }
602
+ function smoothstep(value) {
603
+ return value * value * (3 - 2 * value);
604
+ }
605
+ function getNow() {
606
+ return globalThis.performance?.now() ?? Date.now();
607
+ }
608
+ var VirtualizedRenderer = class VirtualizedRenderer extends BaseRenderer {
609
+ static MIN_JUMP_DURATION = 160;
610
+ static MAX_JUMP_DURATION = 420;
611
+ static JUMP_DURATION_PER_ITEM = 28;
612
+ #controlledState;
613
+ #jumpAnimation;
600
614
  get position() {
601
615
  return this.options.list.position;
602
616
  }
@@ -615,6 +629,47 @@ var VirtualizedRenderer = class extends BaseRenderer {
615
629
  set items(value) {
616
630
  this.options.list.items = value;
617
631
  }
632
+ jumpTo(index, options = {}) {
633
+ if (this.items.length === 0) {
634
+ this.#cancelJumpAnimation();
635
+ return;
636
+ }
637
+ const targetIndex = this._clampItemIndex(index);
638
+ this._prepareAnchorState();
639
+ const targetAnchor = this._getTargetAnchor(targetIndex);
640
+ if (!(options.animated ?? true)) {
641
+ this.#cancelJumpAnimation();
642
+ this._applyAnchor(targetAnchor);
643
+ options.onComplete?.();
644
+ return;
645
+ }
646
+ const startAnchor = this._readAnchor();
647
+ if (!Number.isFinite(startAnchor)) {
648
+ this.#cancelJumpAnimation();
649
+ this._applyAnchor(targetAnchor);
650
+ options.onComplete?.();
651
+ return;
652
+ }
653
+ const duration = clamp(options.duration ?? VirtualizedRenderer.MIN_JUMP_DURATION + Math.abs(targetAnchor - startAnchor) * VirtualizedRenderer.JUMP_DURATION_PER_ITEM, 0, VirtualizedRenderer.MAX_JUMP_DURATION);
654
+ if (duration <= 0 || Math.abs(targetAnchor - startAnchor) <= Number.EPSILON) {
655
+ this.#cancelJumpAnimation();
656
+ this._applyAnchor(targetAnchor);
657
+ options.onComplete?.();
658
+ return;
659
+ }
660
+ this.#jumpAnimation = {
661
+ startAnchor,
662
+ targetAnchor,
663
+ startTime: getNow(),
664
+ duration,
665
+ needsMoreFrames: true,
666
+ onComplete: options.onComplete
667
+ };
668
+ this.#controlledState = {
669
+ position: this.position,
670
+ offset: this.offset
671
+ };
672
+ }
618
673
  _resetRenderFeedback(feedback) {
619
674
  if (feedback == null) return;
620
675
  feedback.minIdx = NaN;
@@ -646,9 +701,83 @@ var VirtualizedRenderer = class extends BaseRenderer {
646
701
  }
647
702
  return result;
648
703
  }
704
+ _prepareRender() {
705
+ const animation = this.#jumpAnimation;
706
+ if (animation == null) return false;
707
+ if (this.items.length === 0) {
708
+ this.#cancelJumpAnimation();
709
+ return false;
710
+ }
711
+ if (this.#controlledState != null && !sameState(this.#controlledState, this.position, this.offset)) {
712
+ this.#cancelJumpAnimation();
713
+ return false;
714
+ }
715
+ const progress = clamp((getNow() - animation.startTime) / animation.duration, 0, 1);
716
+ const eased = progress >= 1 ? 1 : smoothstep(progress);
717
+ const anchor = animation.startAnchor + (animation.targetAnchor - animation.startAnchor) * eased;
718
+ this._applyAnchor(anchor);
719
+ animation.needsMoreFrames = progress < 1;
720
+ return animation.needsMoreFrames;
721
+ }
722
+ _finishRender(requestRedraw) {
723
+ const animation = this.#jumpAnimation;
724
+ if (animation == null) return requestRedraw;
725
+ if (animation.needsMoreFrames) {
726
+ this.#controlledState = {
727
+ position: this.position,
728
+ offset: this.offset
729
+ };
730
+ return true;
731
+ }
732
+ const onComplete = animation.onComplete;
733
+ this.#cancelJumpAnimation();
734
+ onComplete?.();
735
+ return requestRedraw || this.#jumpAnimation != null;
736
+ }
737
+ _clampItemIndex(index) {
738
+ return clamp(Number.isFinite(index) ? Math.trunc(index) : 0, 0, this.items.length - 1);
739
+ }
740
+ _getItemHeight(index) {
741
+ const item = this.items[index];
742
+ const node = this.options.renderItem(item);
743
+ return this.measureNode(node).height;
744
+ }
745
+ #cancelJumpAnimation() {
746
+ this.#jumpAnimation = void 0;
747
+ this.#controlledState = void 0;
748
+ }
649
749
  };
650
750
  var TimelineRenderer = class extends VirtualizedRenderer {
751
+ _prepareAnchorState() {
752
+ if (this.items.length === 0) return;
753
+ if (!Number.isFinite(this.position)) {
754
+ this.position = 0;
755
+ this.offset = 0;
756
+ return;
757
+ }
758
+ this.position = this._clampItemIndex(this.position);
759
+ if (!Number.isFinite(this.offset)) this.offset = 0;
760
+ }
761
+ _readAnchor() {
762
+ this._prepareAnchorState();
763
+ if (this.items.length === 0) return 0;
764
+ const height = this._getItemHeight(this.position);
765
+ return height > 0 ? this.position - this.offset / height : this.position;
766
+ }
767
+ _applyAnchor(anchor) {
768
+ if (this.items.length === 0) return;
769
+ const clampedAnchor = clamp(anchor, 0, this.items.length);
770
+ const position = clamp(Math.floor(clampedAnchor), 0, this.items.length - 1);
771
+ const height = this._getItemHeight(position);
772
+ this.position = position;
773
+ const offset = height > 0 ? -(clampedAnchor - position) * height : 0;
774
+ this.offset = Object.is(offset, -0) ? 0 : offset;
775
+ }
776
+ _getTargetAnchor(index) {
777
+ return index;
778
+ }
651
779
  render(feedback) {
780
+ const keepAnimating = this._prepareRender();
652
781
  const { clientWidth: viewportWidth, clientHeight: viewportHeight } = this.graphics.canvas;
653
782
  this.graphics.clearRect(0, 0, viewportWidth, viewportHeight);
654
783
  this._resetRenderFeedback(feedback);
@@ -715,7 +844,8 @@ var TimelineRenderer = class extends VirtualizedRenderer {
715
844
  this.offset = 0;
716
845
  }
717
846
  }
718
- return this._renderDrawList(drawList, shift, feedback);
847
+ const requestRedraw = this._renderDrawList(drawList, shift, feedback);
848
+ return this._finishRender(keepAnimating || requestRedraw);
719
849
  }
720
850
  hittest(test) {
721
851
  const viewportHeight = this.graphics.canvas.clientHeight;
@@ -732,7 +862,36 @@ var TimelineRenderer = class extends VirtualizedRenderer {
732
862
  }
733
863
  };
734
864
  var ChatRenderer = class extends VirtualizedRenderer {
865
+ _prepareAnchorState() {
866
+ if (this.items.length === 0) return;
867
+ if (!Number.isFinite(this.position)) {
868
+ this.position = this.items.length - 1;
869
+ this.offset = 0;
870
+ return;
871
+ }
872
+ this.position = this._clampItemIndex(this.position);
873
+ if (!Number.isFinite(this.offset)) this.offset = 0;
874
+ }
875
+ _readAnchor() {
876
+ this._prepareAnchorState();
877
+ if (this.items.length === 0) return 0;
878
+ const height = this._getItemHeight(this.position);
879
+ return height > 0 ? this.position + 1 - this.offset / height : this.position + 1;
880
+ }
881
+ _applyAnchor(anchor) {
882
+ if (this.items.length === 0) return;
883
+ const clampedAnchor = clamp(anchor, 0, this.items.length);
884
+ const position = clamp(Math.ceil(clampedAnchor) - 1, 0, this.items.length - 1);
885
+ const height = this._getItemHeight(position);
886
+ this.position = position;
887
+ const offset = height > 0 ? (position + 1 - clampedAnchor) * height : 0;
888
+ this.offset = Object.is(offset, -0) ? 0 : offset;
889
+ }
890
+ _getTargetAnchor(index) {
891
+ return index + 1;
892
+ }
735
893
  render(feedback) {
894
+ const keepAnimating = this._prepareRender();
736
895
  const { clientWidth: viewportWidth, clientHeight: viewportHeight } = this.graphics.canvas;
737
896
  this.graphics.clearRect(0, 0, viewportWidth, viewportHeight);
738
897
  this._resetRenderFeedback(feedback);
@@ -791,7 +950,8 @@ var ChatRenderer = class extends VirtualizedRenderer {
791
950
  else this.offset = drawLength - viewportHeight;
792
951
  } else this.offset = drawLength - viewportHeight;
793
952
  }
794
- return this._renderDrawList(drawList, shift, feedback);
953
+ const requestRedraw = this._renderDrawList(drawList, shift, feedback);
954
+ return this._finishRender(keepAnimating || requestRedraw);
795
955
  }
796
956
  hittest(test) {
797
957
  const viewportHeight = this.graphics.canvas.clientHeight;
package/index.mjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["#inner","#top","#bottom","#left","#right","#shift","#width","#lines","#text","#ctx","#lastWidth","#cache"],"sources":["../src/text.ts","../src/utils.ts","../src/registry.ts","../src/nodes.ts","../src/renderer.ts"],"sourcesContent":["import { layoutWithLines, prepareWithSegments } from \"@chenglou/pretext\";\nimport type { Context } from \"./types\";\n\nexport interface TextLayout {\n width: number;\n text: string;\n shift: number;\n}\n\nfunction preprocessSegments(text: string): string[] {\n return text\n .split(\"\\n\")\n .map((line) => line.trim())\n .filter(Boolean);\n}\n\nexport function layoutFirstLine<C extends CanvasRenderingContext2D>(\n ctx: Context<C>,\n text: string,\n maxWidth: number,\n): TextLayout {\n if (maxWidth < 0) {\n maxWidth = 0;\n }\n const segments = preprocessSegments(text);\n const segment = segments[0];\n if (!segment) {\n return { width: 0, text: \"\", shift: 0 };\n }\n const {\n fontBoundingBoxAscent: ascent = 0,\n fontBoundingBoxDescent: descent = 0,\n } = ctx.graphics.measureText(segment);\n const shift = ascent - descent;\n if (maxWidth === 0) {\n return { width: 0, text: \"\", shift };\n }\n const prepared = prepareWithSegments(segment, ctx.graphics.font);\n const { lines } = layoutWithLines(prepared, maxWidth, 0);\n if (lines.length === 0) {\n return { width: 0, text: \"\", shift };\n }\n return { width: lines[0].width, text: lines[0].text, shift };\n}\n\nexport function layoutText<C extends CanvasRenderingContext2D>(\n ctx: Context<C>,\n text: string,\n maxWidth: number,\n): { width: number; lines: TextLayout[] } {\n if (maxWidth < 0) {\n maxWidth = 0;\n }\n\n const segments = preprocessSegments(text);\n if (segments.length === 0 || maxWidth === 0) {\n return { width: 0, lines: [] };\n }\n\n const font = ctx.graphics.font;\n let width = 0;\n const lines: TextLayout[] = [];\n\n for (const segment of segments) {\n const {\n fontBoundingBoxAscent: ascent = 0,\n fontBoundingBoxDescent: descent = 0,\n } = ctx.graphics.measureText(segment);\n const shift = ascent - descent;\n const prepared = prepareWithSegments(segment, font);\n const { lines: segLines } = layoutWithLines(prepared, maxWidth, 0);\n for (const segLine of segLines) {\n width = Math.max(width, segLine.width);\n lines.push({ width: segLine.width, text: segLine.text, shift });\n }\n }\n\n return { width, lines };\n}\n","export function shallow<T extends object>(object: T): T {\n return Object.create(object) as T;\n}\n\nexport function shallowMerge<T extends object, R extends object>(object: T, other: R): T & R {\n return { __proto__: object, ...other } as unknown as T & R;\n}\n","import type { Node } from \"./types\";\n\nconst registry = new WeakMap<Node<any>, Node<any>>();\n\nexport function registerNodeParent<C extends CanvasRenderingContext2D>(\n node: Node<C>,\n parent: Node<C>,\n): void {\n registry.set(node, parent);\n}\n\nexport function unregisterNodeParent<C extends CanvasRenderingContext2D>(node: Node<C>): void {\n registry.delete(node);\n}\n\nexport function getNodeParent<C extends CanvasRenderingContext2D>(node: Node<C>): Node<C> | undefined {\n return registry.get(node);\n}\n","import type { Alignment, Box, Context, DynValue, HitTest, Node } from \"./types\";\nimport { layoutFirstLine, layoutText, type TextLayout } from \"./text\";\nimport { shallow, shallowMerge } from \"./utils\";\nimport { registerNodeParent, unregisterNodeParent } from \"./registry\";\n\nexport abstract class Group<C extends CanvasRenderingContext2D> implements Node<C> {\n constructor(readonly children: Node<C>[]) {\n for (const child of children) {\n registerNodeParent(child, this);\n }\n }\n\n abstract measure(ctx: Context<C>): Box;\n abstract draw(ctx: Context<C>, x: number, y: number): boolean;\n abstract hittest(ctx: Context<C>, test: HitTest): boolean;\n\n get flex(): boolean {\n return this.children.some((item) => item.flex);\n }\n}\n\nexport class VStack<C extends CanvasRenderingContext2D> extends Group<C> {\n constructor(\n children: Node<C>[],\n readonly options: { gap?: number; alignment?: \"left\" | \"center\" | \"right\" } = {},\n ) {\n super(children);\n }\n\n measure(ctx: Context<C>): Box {\n let width = 0;\n let height = 0;\n if (this.options.alignment != null) {\n ctx.alignment = this.options.alignment;\n }\n\n for (const [index, child] of this.children.entries()) {\n if (this.options.gap != null && index !== 0) {\n height += this.options.gap;\n }\n const result = shallow(ctx).measureNode(child);\n height += result.height;\n width = Math.max(width, result.width);\n }\n ctx.remainingWidth -= width;\n return { width, height };\n }\n\n draw(ctx: Context<C>, x: number, y: number): boolean {\n let result = false;\n const fullWidth = ctx.measureNode(this).width;\n const alignment = this.options.alignment ?? ctx.alignment;\n if (this.options.alignment != null) {\n ctx.alignment = this.options.alignment;\n }\n\n for (const [index, child] of this.children.entries()) {\n if (this.options.gap != null && index !== 0) {\n y += this.options.gap;\n }\n const { width, height } = shallow(ctx).measureNode(child);\n const curCtx = shallow(ctx);\n let requestRedraw: boolean;\n if (alignment === \"right\") {\n requestRedraw = child.draw(curCtx, x + fullWidth - width, y);\n } else if (alignment === \"center\") {\n requestRedraw = child.draw(curCtx, x + (fullWidth - width) / 2, y);\n } else {\n requestRedraw = child.draw(curCtx, x, y);\n }\n result ||= requestRedraw;\n y += height;\n }\n return result;\n }\n\n hittest(ctx: Context<C>, test: HitTest): boolean {\n let y = 0;\n const fullWidth = ctx.measureNode(this).width;\n const alignment = this.options.alignment ?? ctx.alignment;\n if (this.options.alignment != null) {\n ctx.alignment = this.options.alignment;\n }\n\n for (const [index, child] of this.children.entries()) {\n if (this.options.gap != null && index !== 0) {\n y += this.options.gap;\n }\n\n const { width, height } = shallow(ctx).measureNode(child);\n const curCtx = shallow(ctx);\n if (test.y >= y && test.y < y + height) {\n let x: number;\n if (alignment === \"right\") {\n x = test.x - fullWidth + width;\n } else if (alignment === \"center\") {\n x = test.x - (fullWidth - width) / 2;\n } else {\n x = test.x;\n }\n if (x < 0 || x >= width) {\n return false;\n }\n return child.hittest(\n curCtx,\n shallowMerge(test, {\n x,\n y: test.y - y,\n }),\n );\n }\n y += height;\n }\n return false;\n }\n}\n\nexport class HStack<C extends CanvasRenderingContext2D> extends Group<C> {\n constructor(\n readonly children: Node<C>[],\n readonly options: { reverse?: boolean; gap?: number } = {},\n ) {\n super(children);\n }\n\n measure(ctx: Context<C>): Box {\n let width = 0;\n let height = 0;\n let firstFlex: Node<C> | undefined;\n\n for (const [index, child] of this.children.entries()) {\n if (this.options.gap != null && index !== 0) {\n width += this.options.gap;\n }\n if (firstFlex == null && child.flex) {\n firstFlex = child;\n continue;\n }\n const curCtx = shallow(ctx);\n curCtx.remainingWidth = ctx.remainingWidth - width;\n const result = curCtx.measureNode(child);\n width += result.width;\n height = Math.max(height, result.height);\n }\n\n if (firstFlex != null) {\n const curCtx = shallow(ctx);\n curCtx.remainingWidth = ctx.remainingWidth - width;\n const result = curCtx.measureNode(firstFlex);\n width += result.width;\n height = Math.max(height, result.height);\n }\n\n return { width, height };\n }\n\n draw(ctx: Context<C>, x: number, y: number): boolean {\n let result = false;\n const reverse = this.options.reverse ?? ctx.reverse;\n if (this.options.reverse) {\n ctx.reverse = this.options.reverse;\n }\n\n if (reverse) {\n x += ctx.measureNode(this).width;\n for (const [index, child] of this.children.entries()) {\n const gap = this.options.gap != null && index !== 0 ? this.options.gap : undefined;\n if (gap) {\n x -= gap;\n ctx.remainingWidth -= gap;\n }\n const { width } = shallow(ctx).measureNode(child);\n x -= width;\n const requestRedraw = child.draw(shallow(ctx), x, y);\n result ||= requestRedraw;\n ctx.remainingWidth -= width;\n }\n } else {\n for (const [index, child] of this.children.entries()) {\n const gap = this.options.gap != null && index !== 0 ? this.options.gap : undefined;\n if (gap) {\n x += gap;\n ctx.remainingWidth -= gap;\n }\n const requestRedraw = child.draw(shallow(ctx), x, y);\n result ||= requestRedraw;\n const { width } = shallow(ctx).measureNode(child);\n ctx.remainingWidth -= width;\n x += width;\n }\n }\n\n return result;\n }\n\n hittest(ctx: Context<C>, test: HitTest): boolean {\n const reverse = this.options.reverse ?? ctx.reverse;\n if (this.options.reverse) {\n ctx.reverse = this.options.reverse;\n }\n\n if (reverse) {\n let x = ctx.measureNode(this).width;\n for (const [index, child] of this.children.entries()) {\n const gap = this.options.gap != null && index !== 0 ? this.options.gap : undefined;\n if (gap) {\n x -= gap;\n ctx.remainingWidth -= gap;\n }\n const { width, height } = shallow(ctx).measureNode(child);\n x -= width;\n if (x <= test.x && test.x < x + width) {\n if (test.y >= height) {\n return false;\n }\n return child.hittest(\n shallow(ctx),\n shallowMerge(test, {\n x: test.x - x,\n }),\n );\n }\n ctx.remainingWidth -= width;\n }\n } else {\n let x = 0;\n for (const [index, child] of this.children.entries()) {\n const gap = this.options.gap != null && index !== 0 ? this.options.gap : undefined;\n if (gap) {\n x += gap;\n ctx.remainingWidth -= gap;\n }\n const { width, height } = shallow(ctx).measureNode(child);\n if (x <= test.x && test.x < x + width) {\n if (test.y >= height) {\n return false;\n }\n return child.hittest(\n shallow(ctx),\n shallowMerge(test, {\n x: test.x - x,\n }),\n );\n }\n x += width;\n ctx.remainingWidth -= width;\n }\n }\n\n return false;\n }\n}\n\nexport class Wrapper<C extends CanvasRenderingContext2D> implements Node<C> {\n #inner: Node<C>;\n\n constructor(inner: Node<C>) {\n this.#inner = inner;\n registerNodeParent(this.#inner, this);\n }\n\n get inner(): Node<C> {\n return this.#inner;\n }\n\n set inner(newNode: Node<C>) {\n if (newNode === this.#inner) {\n return;\n }\n unregisterNodeParent(this.#inner);\n this.#inner = newNode;\n registerNodeParent(newNode, this);\n }\n\n get flex(): boolean {\n return this.inner.flex;\n }\n\n measure(ctx: Context<C>): Box {\n return this.inner.measure(ctx);\n }\n\n draw(ctx: Context<C>, x: number, y: number): boolean {\n return this.inner.draw(ctx, x, y);\n }\n\n hittest(ctx: Context<C>, test: HitTest): boolean {\n return this.inner.hittest(ctx, test);\n }\n}\n\nexport class PaddingBox<C extends CanvasRenderingContext2D> extends Wrapper<C> {\n constructor(\n inner: Node<C>,\n readonly padding: {\n top?: number;\n bottom?: number;\n left?: number;\n right?: number;\n } = {},\n ) {\n super(inner);\n }\n\n get #top(): number {\n return this.padding.top ?? 0;\n }\n\n get #bottom(): number {\n return this.padding.bottom ?? 0;\n }\n\n get #left(): number {\n return this.padding.left ?? 0;\n }\n\n get #right(): number {\n return this.padding.right ?? 0;\n }\n\n measure(ctx: Context<C>): Box {\n ctx.remainingWidth -= this.#left + this.#right;\n const { width, height } = ctx.measureNode(this.inner);\n return {\n width: width + this.#left + this.#right,\n height: height + this.#top + this.#bottom,\n };\n }\n\n draw(ctx: Context<C>, x: number, y: number): boolean {\n ctx.remainingWidth -= this.#left + this.#right;\n return this.inner.draw(ctx, x + this.#left, y + this.#top);\n }\n\n hittest(ctx: Context<C>, test: HitTest): boolean {\n ctx.remainingWidth -= this.#left + this.#right;\n const { width, height } = shallow(ctx).measureNode(this.inner);\n if (0 <= test.x - this.#left && test.x - this.#left < width && 0 <= test.y - this.#top && test.y - this.#top < height) {\n return this.inner.hittest(\n shallow(ctx),\n shallowMerge(test, {\n x: test.x - this.#left,\n y: test.y - this.#top,\n }),\n );\n }\n return false;\n }\n}\n\nexport class AlignBox<C extends CanvasRenderingContext2D> extends Wrapper<C> {\n #shift = 0;\n\n constructor(\n inner: Node<C>,\n readonly options: {\n alignment: Alignment;\n },\n ) {\n super(inner);\n }\n\n measure(ctx: Context<C>): Box {\n ctx.alignment = this.options.alignment;\n const { width, height } = ctx.measureNode(this.inner);\n switch (this.options.alignment) {\n case \"center\":\n this.#shift = (ctx.remainingWidth - width) / 2;\n break;\n case \"right\":\n this.#shift = ctx.remainingWidth - width;\n break;\n default:\n this.#shift = 0;\n }\n return {\n width: ctx.remainingWidth,\n height,\n };\n }\n\n draw(ctx: Context<C>, x: number, y: number): boolean {\n ctx.alignment = this.options.alignment;\n return this.inner.draw(ctx, x + this.#shift, y);\n }\n\n hittest(ctx: Context<C>, test: HitTest): boolean {\n ctx.alignment = this.options.alignment;\n const { width } = shallow(ctx).measureNode(this.inner);\n if (0 <= test.x - this.#shift && test.x - this.#shift < width) {\n return this.inner.hittest(\n shallow(ctx),\n shallowMerge(test, {\n x: test.x - this.#shift,\n }),\n );\n }\n return false;\n }\n}\n\nexport class MultilineText<C extends CanvasRenderingContext2D> implements Node<C> {\n #width = 0;\n #lines: TextLayout[] = [];\n\n constructor(\n readonly text: string,\n readonly options: {\n lineHeight: number;\n font: string;\n alignment: \"left\" | \"center\" | \"right\";\n style: DynValue<C, string>;\n },\n ) {}\n\n get flex(): boolean {\n return true;\n }\n\n measure(ctx: Context<C>): Box {\n return ctx.with((g) => {\n g.font = this.options.font;\n const { width, lines } = layoutText(ctx, this.text, ctx.remainingWidth);\n this.#width = width;\n this.#lines = lines;\n return { width: this.#width, height: this.#lines.length * this.options.lineHeight };\n });\n }\n\n draw(ctx: Context<C>, x: number, y: number): boolean {\n return ctx.with((g) => {\n g.font = this.options.font;\n g.fillStyle = ctx.resolveDynValue(this.options.style);\n switch (this.options.alignment) {\n case \"left\":\n for (const { text, shift } of this.#lines) {\n g.fillText(text, x, y + (this.options.lineHeight + shift) / 2);\n y += this.options.lineHeight;\n }\n break;\n case \"right\":\n x += this.#width;\n g.textAlign = \"right\";\n for (const { text, shift } of this.#lines) {\n g.fillText(text, x, y + (this.options.lineHeight + shift) / 2);\n y += this.options.lineHeight;\n }\n break;\n case \"center\":\n x += this.#width / 2;\n g.textAlign = \"center\";\n for (const { text, shift } of this.#lines) {\n g.fillText(text, x, y + (this.options.lineHeight + shift) / 2);\n y += this.options.lineHeight;\n }\n break;\n }\n return false;\n });\n }\n\n hittest(_ctx: Context<C>, _test: HitTest): boolean {\n return false;\n }\n}\n\nexport class Text<C extends CanvasRenderingContext2D> implements Node<C> {\n #width = 0;\n #text = \"\";\n #shift = 0;\n\n constructor(\n readonly text: string,\n readonly options: {\n lineHeight: number;\n font: string;\n style: DynValue<C, string>;\n },\n ) {}\n\n get flex(): boolean {\n return false;\n }\n\n measure(ctx: Context<C>): Box {\n return ctx.with((g) => {\n g.font = this.options.font;\n const { width, text, shift } = layoutFirstLine(ctx, this.text, ctx.remainingWidth);\n this.#width = width;\n this.#text = text;\n this.#shift = shift;\n return { width: this.#width, height: this.options.lineHeight };\n });\n }\n\n draw(ctx: Context<C>, x: number, y: number): boolean {\n return ctx.with((g) => {\n g.font = this.options.font;\n g.fillStyle = ctx.resolveDynValue(this.options.style);\n g.fillText(this.#text, x, y + (this.options.lineHeight + this.#shift) / 2);\n return false;\n });\n }\n\n hittest(_ctx: Context<C>, _test: HitTest): boolean {\n return false;\n }\n}\n\nexport class Fixed<C extends CanvasRenderingContext2D> implements Node<C> {\n constructor(\n readonly width: number,\n readonly height: number,\n ) {}\n\n get flex(): boolean {\n return false;\n }\n\n measure(_ctx: Context<C>): Box {\n return { width: this.width, height: this.height };\n }\n\n draw(_ctx: Context<C>, _x: number, _y: number): boolean {\n return false;\n }\n\n hittest(_ctx: Context<C>, _test: HitTest): boolean {\n return false;\n }\n}\n","import type { Box, Context, DynValue, HitTest, Node, RenderFeedback, RendererOptions } from \"./types\";\nimport { shallow, shallowMerge } from \"./utils\";\nimport { getNodeParent } from \"./registry\";\n\nexport class BaseRenderer<C extends CanvasRenderingContext2D, O extends {} = {}> {\n graphics: C;\n #ctx: Context<C>;\n #lastWidth: number;\n #cache = new WeakMap<Node<C>, Box>();\n\n protected get context(): Context<C> {\n return shallow(this.#ctx);\n }\n\n constructor(\n graphics: C,\n readonly options: RendererOptions & O,\n ) {\n this.graphics = graphics;\n this.graphics.textRendering = \"optimizeLegibility\";\n const self = this;\n this.#ctx = {\n graphics: this.graphics,\n get remainingWidth() {\n return this.graphics.canvas.clientWidth;\n },\n set remainingWidth(value: number) {\n Object.defineProperty(this, \"remainingWidth\", { value, writable: true });\n },\n alignment: \"left\",\n reverse: false,\n measureNode(node: Node<C>) {\n return self.measureNode(node, this);\n },\n invalidateNode: this.invalidateNode.bind(this),\n resolveDynValue<T>(value: DynValue<C, T>): T {\n if (typeof value === \"function\") {\n return value(this.graphics);\n }\n return value as T;\n },\n with<T>(cb: (g: C) => T): T {\n this.graphics.save();\n try {\n return cb(this.graphics);\n } finally {\n this.graphics.restore();\n }\n },\n };\n this.#lastWidth = this.graphics.canvas.clientWidth;\n }\n\n invalidateNode(node: Node<C>): void {\n this.#cache.delete(node);\n let it: Node<C> | undefined = node;\n while ((it = getNodeParent(it))) {\n this.#cache.delete(it);\n }\n }\n\n measureNode(node: Node<C>, ctx?: Context<C>): Box {\n if (this.#lastWidth !== this.graphics.canvas.clientWidth) {\n this.#cache = new WeakMap<Node<C>, Box>();\n this.#lastWidth = this.graphics.canvas.clientWidth;\n } else {\n const result = this.#cache.get(node);\n if (result != null) {\n return result;\n }\n }\n const result = node.measure(ctx ?? this.context);\n this.#cache.set(node, result);\n return result;\n }\n}\n\nexport class DebugRenderer<C extends CanvasRenderingContext2D> extends BaseRenderer<C> {\n draw(node: Node<C>): boolean {\n const { clientWidth: viewportWidth, clientHeight: viewportHeight } = this.graphics.canvas;\n this.graphics.clearRect(0, 0, viewportWidth, viewportHeight);\n return node.draw(this.context, 0, 0);\n }\n\n hittest(node: Node<C>, test: HitTest): boolean {\n return node.hittest(this.context, test);\n }\n}\n\nexport function memoRenderItem<C extends CanvasRenderingContext2D, T extends {}>(\n renderItem: (item: T) => Node<C>,\n): ((item: T) => Node<C>) & { reset: (key: T) => boolean } {\n const cache = new WeakMap<object, Node<C>>();\n\n function fn(item: T): Node<C> {\n const key = item as unknown as object;\n const cached = cache.get(key);\n if (cached != null) {\n return cached;\n }\n const result = renderItem(item);\n cache.set(key, result);\n return result;\n }\n\n return Object.assign(fn, {\n reset: (key: T) => cache.delete(key as unknown as object),\n });\n}\n\nexport class ListState<T extends {}> {\n offset = 0;\n position = Number.NaN;\n items: T[] = [];\n\n unshift(...items: T[]): void {\n this.unshiftAll(items);\n }\n\n unshiftAll(items: T[]): void {\n this.position += items.length;\n this.items = items.concat(this.items);\n }\n\n push(...items: T[]): void {\n this.pushAll(items);\n }\n\n pushAll(items: T[]): void {\n this.items.push(...items);\n }\n\n reset(): void {\n this.items = [];\n this.offset = 0;\n this.position = Number.NaN;\n }\n\n resetScroll(): void {\n this.offset = 0;\n this.position = Number.NaN;\n }\n\n applyScroll(delta: number): void {\n this.offset += delta;\n }\n}\n\ntype DrawItem<C extends CanvasRenderingContext2D> = {\n idx: number;\n node: Node<C>;\n offset: number;\n height: number;\n};\n\nfunction clamp(value: number, min: number, max: number): number {\n return Math.min(Math.max(value, min), max);\n}\n\nexport abstract class VirtualizedRenderer<C extends CanvasRenderingContext2D, T extends {}> extends BaseRenderer<\n C,\n {\n renderItem: (item: T) => Node<C>;\n list: ListState<T>;\n }\n> {\n get position(): number {\n return this.options.list.position;\n }\n\n set position(value: number) {\n this.options.list.position = value;\n }\n\n get offset(): number {\n return this.options.list.offset;\n }\n\n set offset(value: number) {\n this.options.list.offset = value;\n }\n\n get items(): T[] {\n return this.options.list.items;\n }\n\n set items(value: T[]) {\n this.options.list.items = value;\n }\n\n abstract render(feedback?: RenderFeedback): boolean;\n abstract hittest(test: HitTest): boolean;\n\n protected _resetRenderFeedback(feedback?: RenderFeedback): void {\n if (feedback == null) {\n return;\n }\n feedback.minIdx = Number.NaN;\n feedback.maxIdx = Number.NaN;\n feedback.min = Number.NaN;\n feedback.max = Number.NaN;\n }\n\n protected _accumulateRenderFeedback(feedback: RenderFeedback, idx: number, top: number, height: number): void {\n if (!Number.isFinite(top) || !Number.isFinite(height) || height <= 0) {\n return;\n }\n\n const viewportHeight = this.graphics.canvas.clientHeight;\n const visibleTop = clamp(-top, 0, height);\n const visibleBottom = clamp(viewportHeight - top, 0, height);\n if (visibleBottom <= visibleTop) {\n return;\n }\n\n const itemMin = idx + visibleTop / height;\n const itemMax = idx + visibleBottom / height;\n feedback.minIdx = Number.isNaN(feedback.minIdx) ? idx : Math.min(idx, feedback.minIdx);\n feedback.maxIdx = Number.isNaN(feedback.maxIdx) ? idx : Math.max(idx, feedback.maxIdx);\n feedback.min = Number.isNaN(feedback.min) ? itemMin : Math.min(itemMin, feedback.min);\n feedback.max = Number.isNaN(feedback.max) ? itemMax : Math.max(itemMax, feedback.max);\n }\n\n protected _renderDrawList(list: DrawItem<C>[], shift: number, feedback?: RenderFeedback): boolean {\n let result = false;\n const viewportHeight = this.graphics.canvas.clientHeight;\n\n for (const { idx, node, offset, height } of list) {\n const y = offset + shift;\n if (feedback != null) {\n this._accumulateRenderFeedback(feedback, idx, y, height);\n }\n if (y + height < 0 || y > viewportHeight) {\n continue;\n }\n if (node.draw(this.context, 0, y)) {\n result = true;\n }\n }\n\n return result;\n }\n}\n\nexport class TimelineRenderer<C extends CanvasRenderingContext2D, T extends {}> extends VirtualizedRenderer<C, T> {\n render(feedback?: RenderFeedback): boolean {\n const { clientWidth: viewportWidth, clientHeight: viewportHeight } = this.graphics.canvas;\n this.graphics.clearRect(0, 0, viewportWidth, viewportHeight);\n this._resetRenderFeedback(feedback);\n\n let drawLength = 0;\n if (Number.isNaN(this.position)) {\n this.position = 0;\n }\n\n if (this.offset > 0) {\n if (this.position === 0) {\n this.offset = 0;\n } else {\n for (let i = this.position - 1; i >= 0; i -= 1) {\n const item = this.items[i];\n const node = this.options.renderItem(item);\n const { height } = this.measureNode(node);\n this.position = i;\n this.offset -= height;\n if (this.offset <= 0) {\n break;\n }\n }\n if (this.position === 0 && this.offset > 0) {\n this.offset = 0;\n }\n }\n }\n\n let y = this.offset;\n const drawList: DrawItem<C>[] = [];\n for (let i = this.position; i < this.items.length; i += 1) {\n const item = this.items[i];\n const node = this.options.renderItem(item);\n const { height } = this.measureNode(node);\n if (y + height > 0) {\n drawList.push({ idx: i, node, offset: y, height });\n drawLength += height;\n } else {\n this.offset += height;\n this.position = i + 1;\n }\n y += height;\n if (y >= viewportHeight) {\n break;\n }\n }\n\n let shift = 0;\n if (y < viewportHeight) {\n if (this.position === 0 && drawLength < viewportHeight) {\n shift = -this.offset;\n this.offset = 0;\n } else {\n shift = viewportHeight - y;\n y = (this.offset += shift);\n let lastIdx = -1;\n for (let i = this.position - 1; i >= 0; i -= 1) {\n const item = this.items[(lastIdx = i)];\n const node = this.options.renderItem(item);\n const { height } = this.measureNode(node);\n drawLength += height;\n y -= height;\n drawList.push({ idx: i, node, offset: y - shift, height });\n if (y < 0) {\n break;\n }\n }\n if (lastIdx === 0 && drawLength < viewportHeight) {\n shift = -drawList[drawList.length - 1].offset;\n this.position = 0;\n this.offset = 0;\n }\n }\n }\n\n return this._renderDrawList(drawList, shift, feedback);\n }\n\n hittest(test: HitTest): boolean {\n const viewportHeight = this.graphics.canvas.clientHeight;\n let y = this.offset;\n\n for (let i = this.position; i < this.items.length; i += 1) {\n const item = this.items[i];\n const node = this.options.renderItem(item);\n const { height } = this.measureNode(node);\n if (test.y < y + height) {\n return node.hittest(\n this.context,\n shallowMerge(test, {\n y: test.y - y,\n }),\n );\n }\n y += height;\n if (y >= viewportHeight) {\n break;\n }\n }\n return false;\n }\n}\n\nexport class ChatRenderer<C extends CanvasRenderingContext2D, T extends {}> extends VirtualizedRenderer<C, T> {\n render(feedback?: RenderFeedback): boolean {\n const { clientWidth: viewportWidth, clientHeight: viewportHeight } = this.graphics.canvas;\n this.graphics.clearRect(0, 0, viewportWidth, viewportHeight);\n this._resetRenderFeedback(feedback);\n\n let drawLength = 0;\n if (Number.isNaN(this.position)) {\n this.position = this.items.length - 1;\n }\n\n if (this.offset < 0) {\n if (this.position === this.items.length - 1) {\n this.offset = 0;\n } else {\n for (let i = this.position + 1; i < this.items.length; i += 1) {\n const item = this.items[i];\n const node = this.options.renderItem(item);\n const { height } = this.measureNode(node);\n this.position = i;\n this.offset += height;\n if (this.offset > 0) {\n break;\n }\n }\n }\n }\n\n let y = viewportHeight + this.offset;\n const drawList: DrawItem<C>[] = [];\n for (let i = this.position; i >= 0; i -= 1) {\n const item = this.items[i];\n const node = this.options.renderItem(item);\n const { height } = this.measureNode(node);\n y -= height;\n if (y <= viewportHeight) {\n drawList.push({ idx: i, node, offset: y, height });\n drawLength += height;\n } else {\n this.offset -= height;\n this.position = i - 1;\n }\n if (y < 0) {\n break;\n }\n }\n\n let shift = 0;\n if (y > 0) {\n shift = -y;\n if (drawLength < viewportHeight) {\n y = drawLength;\n for (let i = this.position + 1; i < this.items.length; i += 1) {\n const item = this.items[i];\n const node = this.options.renderItem(item);\n const { height } = this.measureNode(node);\n drawList.push({ idx: i, node, offset: y - shift, height });\n y = (drawLength += height);\n this.position = i;\n if (y >= viewportHeight) {\n break;\n }\n }\n if (drawLength < viewportHeight) {\n this.offset = 0;\n } else {\n this.offset = drawLength - viewportHeight;\n }\n } else {\n this.offset = drawLength - viewportHeight;\n }\n }\n\n return this._renderDrawList(drawList, shift, feedback);\n }\n\n hittest(test: HitTest): boolean {\n const viewportHeight = this.graphics.canvas.clientHeight;\n\n let drawLength = 0;\n const heights: Array<readonly [Node<C>, number]> = [];\n for (let i = this.position; i >= 0; i -= 1) {\n const item = this.items[i];\n const node = this.options.renderItem(item);\n const { height } = this.measureNode(node);\n drawLength += height;\n heights.push([node, height]);\n }\n\n let y = drawLength < viewportHeight ? drawLength : viewportHeight + this.offset;\n if (test.y > y) {\n return false;\n }\n\n for (const [node, height] of heights) {\n y -= height;\n if (test.y > y) {\n return node.hittest(\n this.context,\n shallowMerge(test, {\n y: test.y - y,\n }),\n );\n }\n }\n return false;\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":["#inner","#top","#bottom","#left","#right","#shift","#width","#lines","#text","#ctx","#lastWidth","#cache","#cancelJumpAnimation","#jumpAnimation","#controlledState"],"sources":["../src/text.ts","../src/utils.ts","../src/registry.ts","../src/nodes.ts","../src/renderer.ts"],"sourcesContent":["import { layoutWithLines, prepareWithSegments } from \"@chenglou/pretext\";\nimport type { Context } from \"./types\";\n\nexport interface TextLayout {\n width: number;\n text: string;\n shift: number;\n}\n\nfunction preprocessSegments(text: string): string[] {\n return text\n .split(\"\\n\")\n .map((line) => line.trim())\n .filter(Boolean);\n}\n\nexport function layoutFirstLine<C extends CanvasRenderingContext2D>(\n ctx: Context<C>,\n text: string,\n maxWidth: number,\n): TextLayout {\n if (maxWidth < 0) {\n maxWidth = 0;\n }\n const segments = preprocessSegments(text);\n const segment = segments[0];\n if (!segment) {\n return { width: 0, text: \"\", shift: 0 };\n }\n const {\n fontBoundingBoxAscent: ascent = 0,\n fontBoundingBoxDescent: descent = 0,\n } = ctx.graphics.measureText(segment);\n const shift = ascent - descent;\n if (maxWidth === 0) {\n return { width: 0, text: \"\", shift };\n }\n const prepared = prepareWithSegments(segment, ctx.graphics.font);\n const { lines } = layoutWithLines(prepared, maxWidth, 0);\n if (lines.length === 0) {\n return { width: 0, text: \"\", shift };\n }\n return { width: lines[0].width, text: lines[0].text, shift };\n}\n\nexport function layoutText<C extends CanvasRenderingContext2D>(\n ctx: Context<C>,\n text: string,\n maxWidth: number,\n): { width: number; lines: TextLayout[] } {\n if (maxWidth < 0) {\n maxWidth = 0;\n }\n\n const segments = preprocessSegments(text);\n if (segments.length === 0 || maxWidth === 0) {\n return { width: 0, lines: [] };\n }\n\n const font = ctx.graphics.font;\n let width = 0;\n const lines: TextLayout[] = [];\n\n for (const segment of segments) {\n const {\n fontBoundingBoxAscent: ascent = 0,\n fontBoundingBoxDescent: descent = 0,\n } = ctx.graphics.measureText(segment);\n const shift = ascent - descent;\n const prepared = prepareWithSegments(segment, font);\n const { lines: segLines } = layoutWithLines(prepared, maxWidth, 0);\n for (const segLine of segLines) {\n width = Math.max(width, segLine.width);\n lines.push({ width: segLine.width, text: segLine.text, shift });\n }\n }\n\n return { width, lines };\n}\n","export function shallow<T extends object>(object: T): T {\n return Object.create(object) as T;\n}\n\nexport function shallowMerge<T extends object, R extends object>(object: T, other: R): T & R {\n return { __proto__: object, ...other } as unknown as T & R;\n}\n","import type { Node } from \"./types\";\n\nconst registry = new WeakMap<Node<any>, Node<any>>();\n\nexport function registerNodeParent<C extends CanvasRenderingContext2D>(\n node: Node<C>,\n parent: Node<C>,\n): void {\n registry.set(node, parent);\n}\n\nexport function unregisterNodeParent<C extends CanvasRenderingContext2D>(node: Node<C>): void {\n registry.delete(node);\n}\n\nexport function getNodeParent<C extends CanvasRenderingContext2D>(node: Node<C>): Node<C> | undefined {\n return registry.get(node);\n}\n","import type { Alignment, Box, Context, DynValue, HitTest, Node } from \"./types\";\nimport { layoutFirstLine, layoutText, type TextLayout } from \"./text\";\nimport { shallow, shallowMerge } from \"./utils\";\nimport { registerNodeParent, unregisterNodeParent } from \"./registry\";\n\nexport abstract class Group<C extends CanvasRenderingContext2D> implements Node<C> {\n constructor(readonly children: Node<C>[]) {\n for (const child of children) {\n registerNodeParent(child, this);\n }\n }\n\n abstract measure(ctx: Context<C>): Box;\n abstract draw(ctx: Context<C>, x: number, y: number): boolean;\n abstract hittest(ctx: Context<C>, test: HitTest): boolean;\n\n get flex(): boolean {\n return this.children.some((item) => item.flex);\n }\n}\n\nexport class VStack<C extends CanvasRenderingContext2D> extends Group<C> {\n constructor(\n children: Node<C>[],\n readonly options: { gap?: number; alignment?: \"left\" | \"center\" | \"right\" } = {},\n ) {\n super(children);\n }\n\n measure(ctx: Context<C>): Box {\n let width = 0;\n let height = 0;\n if (this.options.alignment != null) {\n ctx.alignment = this.options.alignment;\n }\n\n for (const [index, child] of this.children.entries()) {\n if (this.options.gap != null && index !== 0) {\n height += this.options.gap;\n }\n const result = shallow(ctx).measureNode(child);\n height += result.height;\n width = Math.max(width, result.width);\n }\n ctx.remainingWidth -= width;\n return { width, height };\n }\n\n draw(ctx: Context<C>, x: number, y: number): boolean {\n let result = false;\n const fullWidth = ctx.measureNode(this).width;\n const alignment = this.options.alignment ?? ctx.alignment;\n if (this.options.alignment != null) {\n ctx.alignment = this.options.alignment;\n }\n\n for (const [index, child] of this.children.entries()) {\n if (this.options.gap != null && index !== 0) {\n y += this.options.gap;\n }\n const { width, height } = shallow(ctx).measureNode(child);\n const curCtx = shallow(ctx);\n let requestRedraw: boolean;\n if (alignment === \"right\") {\n requestRedraw = child.draw(curCtx, x + fullWidth - width, y);\n } else if (alignment === \"center\") {\n requestRedraw = child.draw(curCtx, x + (fullWidth - width) / 2, y);\n } else {\n requestRedraw = child.draw(curCtx, x, y);\n }\n result ||= requestRedraw;\n y += height;\n }\n return result;\n }\n\n hittest(ctx: Context<C>, test: HitTest): boolean {\n let y = 0;\n const fullWidth = ctx.measureNode(this).width;\n const alignment = this.options.alignment ?? ctx.alignment;\n if (this.options.alignment != null) {\n ctx.alignment = this.options.alignment;\n }\n\n for (const [index, child] of this.children.entries()) {\n if (this.options.gap != null && index !== 0) {\n y += this.options.gap;\n }\n\n const { width, height } = shallow(ctx).measureNode(child);\n const curCtx = shallow(ctx);\n if (test.y >= y && test.y < y + height) {\n let x: number;\n if (alignment === \"right\") {\n x = test.x - fullWidth + width;\n } else if (alignment === \"center\") {\n x = test.x - (fullWidth - width) / 2;\n } else {\n x = test.x;\n }\n if (x < 0 || x >= width) {\n return false;\n }\n return child.hittest(\n curCtx,\n shallowMerge(test, {\n x,\n y: test.y - y,\n }),\n );\n }\n y += height;\n }\n return false;\n }\n}\n\nexport class HStack<C extends CanvasRenderingContext2D> extends Group<C> {\n constructor(\n readonly children: Node<C>[],\n readonly options: { reverse?: boolean; gap?: number } = {},\n ) {\n super(children);\n }\n\n measure(ctx: Context<C>): Box {\n let width = 0;\n let height = 0;\n let firstFlex: Node<C> | undefined;\n\n for (const [index, child] of this.children.entries()) {\n if (this.options.gap != null && index !== 0) {\n width += this.options.gap;\n }\n if (firstFlex == null && child.flex) {\n firstFlex = child;\n continue;\n }\n const curCtx = shallow(ctx);\n curCtx.remainingWidth = ctx.remainingWidth - width;\n const result = curCtx.measureNode(child);\n width += result.width;\n height = Math.max(height, result.height);\n }\n\n if (firstFlex != null) {\n const curCtx = shallow(ctx);\n curCtx.remainingWidth = ctx.remainingWidth - width;\n const result = curCtx.measureNode(firstFlex);\n width += result.width;\n height = Math.max(height, result.height);\n }\n\n return { width, height };\n }\n\n draw(ctx: Context<C>, x: number, y: number): boolean {\n let result = false;\n const reverse = this.options.reverse ?? ctx.reverse;\n if (this.options.reverse) {\n ctx.reverse = this.options.reverse;\n }\n\n if (reverse) {\n x += ctx.measureNode(this).width;\n for (const [index, child] of this.children.entries()) {\n const gap = this.options.gap != null && index !== 0 ? this.options.gap : undefined;\n if (gap) {\n x -= gap;\n ctx.remainingWidth -= gap;\n }\n const { width } = shallow(ctx).measureNode(child);\n x -= width;\n const requestRedraw = child.draw(shallow(ctx), x, y);\n result ||= requestRedraw;\n ctx.remainingWidth -= width;\n }\n } else {\n for (const [index, child] of this.children.entries()) {\n const gap = this.options.gap != null && index !== 0 ? this.options.gap : undefined;\n if (gap) {\n x += gap;\n ctx.remainingWidth -= gap;\n }\n const requestRedraw = child.draw(shallow(ctx), x, y);\n result ||= requestRedraw;\n const { width } = shallow(ctx).measureNode(child);\n ctx.remainingWidth -= width;\n x += width;\n }\n }\n\n return result;\n }\n\n hittest(ctx: Context<C>, test: HitTest): boolean {\n const reverse = this.options.reverse ?? ctx.reverse;\n if (this.options.reverse) {\n ctx.reverse = this.options.reverse;\n }\n\n if (reverse) {\n let x = ctx.measureNode(this).width;\n for (const [index, child] of this.children.entries()) {\n const gap = this.options.gap != null && index !== 0 ? this.options.gap : undefined;\n if (gap) {\n x -= gap;\n ctx.remainingWidth -= gap;\n }\n const { width, height } = shallow(ctx).measureNode(child);\n x -= width;\n if (x <= test.x && test.x < x + width) {\n if (test.y >= height) {\n return false;\n }\n return child.hittest(\n shallow(ctx),\n shallowMerge(test, {\n x: test.x - x,\n }),\n );\n }\n ctx.remainingWidth -= width;\n }\n } else {\n let x = 0;\n for (const [index, child] of this.children.entries()) {\n const gap = this.options.gap != null && index !== 0 ? this.options.gap : undefined;\n if (gap) {\n x += gap;\n ctx.remainingWidth -= gap;\n }\n const { width, height } = shallow(ctx).measureNode(child);\n if (x <= test.x && test.x < x + width) {\n if (test.y >= height) {\n return false;\n }\n return child.hittest(\n shallow(ctx),\n shallowMerge(test, {\n x: test.x - x,\n }),\n );\n }\n x += width;\n ctx.remainingWidth -= width;\n }\n }\n\n return false;\n }\n}\n\nexport class Wrapper<C extends CanvasRenderingContext2D> implements Node<C> {\n #inner: Node<C>;\n\n constructor(inner: Node<C>) {\n this.#inner = inner;\n registerNodeParent(this.#inner, this);\n }\n\n get inner(): Node<C> {\n return this.#inner;\n }\n\n set inner(newNode: Node<C>) {\n if (newNode === this.#inner) {\n return;\n }\n unregisterNodeParent(this.#inner);\n this.#inner = newNode;\n registerNodeParent(newNode, this);\n }\n\n get flex(): boolean {\n return this.inner.flex;\n }\n\n measure(ctx: Context<C>): Box {\n return this.inner.measure(ctx);\n }\n\n draw(ctx: Context<C>, x: number, y: number): boolean {\n return this.inner.draw(ctx, x, y);\n }\n\n hittest(ctx: Context<C>, test: HitTest): boolean {\n return this.inner.hittest(ctx, test);\n }\n}\n\nexport class PaddingBox<C extends CanvasRenderingContext2D> extends Wrapper<C> {\n constructor(\n inner: Node<C>,\n readonly padding: {\n top?: number;\n bottom?: number;\n left?: number;\n right?: number;\n } = {},\n ) {\n super(inner);\n }\n\n get #top(): number {\n return this.padding.top ?? 0;\n }\n\n get #bottom(): number {\n return this.padding.bottom ?? 0;\n }\n\n get #left(): number {\n return this.padding.left ?? 0;\n }\n\n get #right(): number {\n return this.padding.right ?? 0;\n }\n\n measure(ctx: Context<C>): Box {\n ctx.remainingWidth -= this.#left + this.#right;\n const { width, height } = ctx.measureNode(this.inner);\n return {\n width: width + this.#left + this.#right,\n height: height + this.#top + this.#bottom,\n };\n }\n\n draw(ctx: Context<C>, x: number, y: number): boolean {\n ctx.remainingWidth -= this.#left + this.#right;\n return this.inner.draw(ctx, x + this.#left, y + this.#top);\n }\n\n hittest(ctx: Context<C>, test: HitTest): boolean {\n ctx.remainingWidth -= this.#left + this.#right;\n const { width, height } = shallow(ctx).measureNode(this.inner);\n if (0 <= test.x - this.#left && test.x - this.#left < width && 0 <= test.y - this.#top && test.y - this.#top < height) {\n return this.inner.hittest(\n shallow(ctx),\n shallowMerge(test, {\n x: test.x - this.#left,\n y: test.y - this.#top,\n }),\n );\n }\n return false;\n }\n}\n\nexport class AlignBox<C extends CanvasRenderingContext2D> extends Wrapper<C> {\n #shift = 0;\n\n constructor(\n inner: Node<C>,\n readonly options: {\n alignment: Alignment;\n },\n ) {\n super(inner);\n }\n\n measure(ctx: Context<C>): Box {\n ctx.alignment = this.options.alignment;\n const { width, height } = ctx.measureNode(this.inner);\n switch (this.options.alignment) {\n case \"center\":\n this.#shift = (ctx.remainingWidth - width) / 2;\n break;\n case \"right\":\n this.#shift = ctx.remainingWidth - width;\n break;\n default:\n this.#shift = 0;\n }\n return {\n width: ctx.remainingWidth,\n height,\n };\n }\n\n draw(ctx: Context<C>, x: number, y: number): boolean {\n ctx.alignment = this.options.alignment;\n return this.inner.draw(ctx, x + this.#shift, y);\n }\n\n hittest(ctx: Context<C>, test: HitTest): boolean {\n ctx.alignment = this.options.alignment;\n const { width } = shallow(ctx).measureNode(this.inner);\n if (0 <= test.x - this.#shift && test.x - this.#shift < width) {\n return this.inner.hittest(\n shallow(ctx),\n shallowMerge(test, {\n x: test.x - this.#shift,\n }),\n );\n }\n return false;\n }\n}\n\nexport class MultilineText<C extends CanvasRenderingContext2D> implements Node<C> {\n #width = 0;\n #lines: TextLayout[] = [];\n\n constructor(\n readonly text: string,\n readonly options: {\n lineHeight: number;\n font: string;\n alignment: \"left\" | \"center\" | \"right\";\n style: DynValue<C, string>;\n },\n ) {}\n\n get flex(): boolean {\n return true;\n }\n\n measure(ctx: Context<C>): Box {\n return ctx.with((g) => {\n g.font = this.options.font;\n const { width, lines } = layoutText(ctx, this.text, ctx.remainingWidth);\n this.#width = width;\n this.#lines = lines;\n return { width: this.#width, height: this.#lines.length * this.options.lineHeight };\n });\n }\n\n draw(ctx: Context<C>, x: number, y: number): boolean {\n return ctx.with((g) => {\n g.font = this.options.font;\n g.fillStyle = ctx.resolveDynValue(this.options.style);\n switch (this.options.alignment) {\n case \"left\":\n for (const { text, shift } of this.#lines) {\n g.fillText(text, x, y + (this.options.lineHeight + shift) / 2);\n y += this.options.lineHeight;\n }\n break;\n case \"right\":\n x += this.#width;\n g.textAlign = \"right\";\n for (const { text, shift } of this.#lines) {\n g.fillText(text, x, y + (this.options.lineHeight + shift) / 2);\n y += this.options.lineHeight;\n }\n break;\n case \"center\":\n x += this.#width / 2;\n g.textAlign = \"center\";\n for (const { text, shift } of this.#lines) {\n g.fillText(text, x, y + (this.options.lineHeight + shift) / 2);\n y += this.options.lineHeight;\n }\n break;\n }\n return false;\n });\n }\n\n hittest(_ctx: Context<C>, _test: HitTest): boolean {\n return false;\n }\n}\n\nexport class Text<C extends CanvasRenderingContext2D> implements Node<C> {\n #width = 0;\n #text = \"\";\n #shift = 0;\n\n constructor(\n readonly text: string,\n readonly options: {\n lineHeight: number;\n font: string;\n style: DynValue<C, string>;\n },\n ) {}\n\n get flex(): boolean {\n return false;\n }\n\n measure(ctx: Context<C>): Box {\n return ctx.with((g) => {\n g.font = this.options.font;\n const { width, text, shift } = layoutFirstLine(ctx, this.text, ctx.remainingWidth);\n this.#width = width;\n this.#text = text;\n this.#shift = shift;\n return { width: this.#width, height: this.options.lineHeight };\n });\n }\n\n draw(ctx: Context<C>, x: number, y: number): boolean {\n return ctx.with((g) => {\n g.font = this.options.font;\n g.fillStyle = ctx.resolveDynValue(this.options.style);\n g.fillText(this.#text, x, y + (this.options.lineHeight + this.#shift) / 2);\n return false;\n });\n }\n\n hittest(_ctx: Context<C>, _test: HitTest): boolean {\n return false;\n }\n}\n\nexport class Fixed<C extends CanvasRenderingContext2D> implements Node<C> {\n constructor(\n readonly width: number,\n readonly height: number,\n ) {}\n\n get flex(): boolean {\n return false;\n }\n\n measure(_ctx: Context<C>): Box {\n return { width: this.width, height: this.height };\n }\n\n draw(_ctx: Context<C>, _x: number, _y: number): boolean {\n return false;\n }\n\n hittest(_ctx: Context<C>, _test: HitTest): boolean {\n return false;\n }\n}\n","import type { Box, Context, DynValue, HitTest, Node, RenderFeedback, RendererOptions } from \"./types\";\nimport { shallow, shallowMerge } from \"./utils\";\nimport { getNodeParent } from \"./registry\";\n\nexport class BaseRenderer<C extends CanvasRenderingContext2D, O extends {} = {}> {\n graphics: C;\n #ctx: Context<C>;\n #lastWidth: number;\n #cache = new WeakMap<Node<C>, Box>();\n\n protected get context(): Context<C> {\n return shallow(this.#ctx);\n }\n\n constructor(\n graphics: C,\n readonly options: RendererOptions & O,\n ) {\n this.graphics = graphics;\n this.graphics.textRendering = \"optimizeLegibility\";\n const self = this;\n this.#ctx = {\n graphics: this.graphics,\n get remainingWidth() {\n return this.graphics.canvas.clientWidth;\n },\n set remainingWidth(value: number) {\n Object.defineProperty(this, \"remainingWidth\", { value, writable: true });\n },\n alignment: \"left\",\n reverse: false,\n measureNode(node: Node<C>) {\n return self.measureNode(node, this);\n },\n invalidateNode: this.invalidateNode.bind(this),\n resolveDynValue<T>(value: DynValue<C, T>): T {\n if (typeof value === \"function\") {\n return value(this.graphics);\n }\n return value as T;\n },\n with<T>(cb: (g: C) => T): T {\n this.graphics.save();\n try {\n return cb(this.graphics);\n } finally {\n this.graphics.restore();\n }\n },\n };\n this.#lastWidth = this.graphics.canvas.clientWidth;\n }\n\n invalidateNode(node: Node<C>): void {\n this.#cache.delete(node);\n let it: Node<C> | undefined = node;\n while ((it = getNodeParent(it))) {\n this.#cache.delete(it);\n }\n }\n\n measureNode(node: Node<C>, ctx?: Context<C>): Box {\n if (this.#lastWidth !== this.graphics.canvas.clientWidth) {\n this.#cache = new WeakMap<Node<C>, Box>();\n this.#lastWidth = this.graphics.canvas.clientWidth;\n } else {\n const result = this.#cache.get(node);\n if (result != null) {\n return result;\n }\n }\n const result = node.measure(ctx ?? this.context);\n this.#cache.set(node, result);\n return result;\n }\n}\n\nexport class DebugRenderer<C extends CanvasRenderingContext2D> extends BaseRenderer<C> {\n draw(node: Node<C>): boolean {\n const { clientWidth: viewportWidth, clientHeight: viewportHeight } = this.graphics.canvas;\n this.graphics.clearRect(0, 0, viewportWidth, viewportHeight);\n return node.draw(this.context, 0, 0);\n }\n\n hittest(node: Node<C>, test: HitTest): boolean {\n return node.hittest(this.context, test);\n }\n}\n\nexport function memoRenderItem<C extends CanvasRenderingContext2D, T extends {}>(\n renderItem: (item: T) => Node<C>,\n): ((item: T) => Node<C>) & { reset: (key: T) => boolean } {\n const cache = new WeakMap<object, Node<C>>();\n\n function fn(item: T): Node<C> {\n const key = item as unknown as object;\n const cached = cache.get(key);\n if (cached != null) {\n return cached;\n }\n const result = renderItem(item);\n cache.set(key, result);\n return result;\n }\n\n return Object.assign(fn, {\n reset: (key: T) => cache.delete(key as unknown as object),\n });\n}\n\nexport class ListState<T extends {}> {\n offset = 0;\n position = Number.NaN;\n items: T[] = [];\n\n unshift(...items: T[]): void {\n this.unshiftAll(items);\n }\n\n unshiftAll(items: T[]): void {\n this.position += items.length;\n this.items = items.concat(this.items);\n }\n\n push(...items: T[]): void {\n this.pushAll(items);\n }\n\n pushAll(items: T[]): void {\n this.items.push(...items);\n }\n\n reset(): void {\n this.items = [];\n this.offset = 0;\n this.position = Number.NaN;\n }\n\n resetScroll(): void {\n this.offset = 0;\n this.position = Number.NaN;\n }\n\n applyScroll(delta: number): void {\n this.offset += delta;\n }\n}\n\ntype DrawItem<C extends CanvasRenderingContext2D> = {\n idx: number;\n node: Node<C>;\n offset: number;\n height: number;\n};\n\nexport interface JumpToOptions {\n animated?: boolean;\n duration?: number;\n onComplete?: () => void;\n}\n\ntype ControlledState = {\n position: number;\n offset: number;\n};\n\ntype JumpAnimation = {\n startAnchor: number;\n targetAnchor: number;\n startTime: number;\n duration: number;\n needsMoreFrames: boolean;\n onComplete: (() => void) | undefined;\n};\n\nfunction clamp(value: number, min: number, max: number): number {\n return Math.min(Math.max(value, min), max);\n}\n\nfunction sameState(state: ControlledState, position: number, offset: number): boolean {\n return Object.is(state.position, position) && Object.is(state.offset, offset);\n}\n\nfunction smoothstep(value: number): number {\n return value * value * (3 - 2 * value);\n}\n\nfunction getNow(): number {\n return globalThis.performance?.now() ?? Date.now();\n}\n\nexport abstract class VirtualizedRenderer<C extends CanvasRenderingContext2D, T extends {}> extends BaseRenderer<\n C,\n {\n renderItem: (item: T) => Node<C>;\n list: ListState<T>;\n }\n> {\n static readonly MIN_JUMP_DURATION = 160;\n static readonly MAX_JUMP_DURATION = 420;\n static readonly JUMP_DURATION_PER_ITEM = 28;\n\n #controlledState: ControlledState | undefined;\n #jumpAnimation: JumpAnimation | undefined;\n\n get position(): number {\n return this.options.list.position;\n }\n\n set position(value: number) {\n this.options.list.position = value;\n }\n\n get offset(): number {\n return this.options.list.offset;\n }\n\n set offset(value: number) {\n this.options.list.offset = value;\n }\n\n get items(): T[] {\n return this.options.list.items;\n }\n\n set items(value: T[]) {\n this.options.list.items = value;\n }\n\n abstract render(feedback?: RenderFeedback): boolean;\n abstract hittest(test: HitTest): boolean;\n\n jumpTo(index: number, options: JumpToOptions = {}): void {\n if (this.items.length === 0) {\n this.#cancelJumpAnimation();\n return;\n }\n\n const targetIndex = this._clampItemIndex(index);\n this._prepareAnchorState();\n const targetAnchor = this._getTargetAnchor(targetIndex);\n\n const animated = options.animated ?? true;\n if (!animated) {\n this.#cancelJumpAnimation();\n this._applyAnchor(targetAnchor);\n options.onComplete?.();\n return;\n }\n\n const startAnchor = this._readAnchor();\n if (!Number.isFinite(startAnchor)) {\n this.#cancelJumpAnimation();\n this._applyAnchor(targetAnchor);\n options.onComplete?.();\n return;\n }\n\n const duration = clamp(\n options.duration ??\n VirtualizedRenderer.MIN_JUMP_DURATION +\n Math.abs(targetAnchor - startAnchor) * VirtualizedRenderer.JUMP_DURATION_PER_ITEM,\n 0,\n VirtualizedRenderer.MAX_JUMP_DURATION,\n );\n\n if (duration <= 0 || Math.abs(targetAnchor - startAnchor) <= Number.EPSILON) {\n this.#cancelJumpAnimation();\n this._applyAnchor(targetAnchor);\n options.onComplete?.();\n return;\n }\n\n this.#jumpAnimation = {\n startAnchor,\n targetAnchor,\n startTime: getNow(),\n duration,\n needsMoreFrames: true,\n onComplete: options.onComplete,\n };\n this.#controlledState = {\n position: this.position,\n offset: this.offset,\n };\n }\n\n protected _resetRenderFeedback(feedback?: RenderFeedback): void {\n if (feedback == null) {\n return;\n }\n feedback.minIdx = Number.NaN;\n feedback.maxIdx = Number.NaN;\n feedback.min = Number.NaN;\n feedback.max = Number.NaN;\n }\n\n protected _accumulateRenderFeedback(feedback: RenderFeedback, idx: number, top: number, height: number): void {\n if (!Number.isFinite(top) || !Number.isFinite(height) || height <= 0) {\n return;\n }\n\n const viewportHeight = this.graphics.canvas.clientHeight;\n const visibleTop = clamp(-top, 0, height);\n const visibleBottom = clamp(viewportHeight - top, 0, height);\n if (visibleBottom <= visibleTop) {\n return;\n }\n\n const itemMin = idx + visibleTop / height;\n const itemMax = idx + visibleBottom / height;\n feedback.minIdx = Number.isNaN(feedback.minIdx) ? idx : Math.min(idx, feedback.minIdx);\n feedback.maxIdx = Number.isNaN(feedback.maxIdx) ? idx : Math.max(idx, feedback.maxIdx);\n feedback.min = Number.isNaN(feedback.min) ? itemMin : Math.min(itemMin, feedback.min);\n feedback.max = Number.isNaN(feedback.max) ? itemMax : Math.max(itemMax, feedback.max);\n }\n\n protected _renderDrawList(list: DrawItem<C>[], shift: number, feedback?: RenderFeedback): boolean {\n let result = false;\n const viewportHeight = this.graphics.canvas.clientHeight;\n\n for (const { idx, node, offset, height } of list) {\n const y = offset + shift;\n if (feedback != null) {\n this._accumulateRenderFeedback(feedback, idx, y, height);\n }\n if (y + height < 0 || y > viewportHeight) {\n continue;\n }\n if (node.draw(this.context, 0, y)) {\n result = true;\n }\n }\n\n return result;\n }\n\n protected _prepareRender(): boolean {\n const animation = this.#jumpAnimation;\n if (animation == null) {\n return false;\n }\n if (this.items.length === 0) {\n this.#cancelJumpAnimation();\n return false;\n }\n if (this.#controlledState != null && !sameState(this.#controlledState, this.position, this.offset)) {\n this.#cancelJumpAnimation();\n return false;\n }\n\n const progress = clamp((getNow() - animation.startTime) / animation.duration, 0, 1);\n const eased = progress >= 1 ? 1 : smoothstep(progress);\n const anchor = animation.startAnchor + (animation.targetAnchor - animation.startAnchor) * eased;\n this._applyAnchor(anchor);\n animation.needsMoreFrames = progress < 1;\n return animation.needsMoreFrames;\n }\n\n protected _finishRender(requestRedraw: boolean): boolean {\n const animation = this.#jumpAnimation;\n if (animation == null) {\n return requestRedraw;\n }\n\n if (animation.needsMoreFrames) {\n this.#controlledState = {\n position: this.position,\n offset: this.offset,\n };\n return true;\n }\n\n const onComplete = animation.onComplete;\n this.#cancelJumpAnimation();\n onComplete?.();\n return requestRedraw || this.#jumpAnimation != null;\n }\n\n protected _clampItemIndex(index: number): number {\n return clamp(Number.isFinite(index) ? Math.trunc(index) : 0, 0, this.items.length - 1);\n }\n\n protected _getItemHeight(index: number): number {\n const item = this.items[index];\n const node = this.options.renderItem(item);\n return this.measureNode(node).height;\n }\n\n protected abstract _prepareAnchorState(): void;\n protected abstract _readAnchor(): number;\n protected abstract _applyAnchor(anchor: number): void;\n protected abstract _getTargetAnchor(index: number): number;\n\n #cancelJumpAnimation(): void {\n this.#jumpAnimation = undefined;\n this.#controlledState = undefined;\n }\n}\n\nexport class TimelineRenderer<C extends CanvasRenderingContext2D, T extends {}> extends VirtualizedRenderer<C, T> {\n protected _prepareAnchorState(): void {\n if (this.items.length === 0) {\n return;\n }\n if (!Number.isFinite(this.position)) {\n this.position = 0;\n this.offset = 0;\n return;\n }\n this.position = this._clampItemIndex(this.position);\n if (!Number.isFinite(this.offset)) {\n this.offset = 0;\n }\n }\n\n protected _readAnchor(): number {\n this._prepareAnchorState();\n if (this.items.length === 0) {\n return 0;\n }\n const height = this._getItemHeight(this.position);\n return height > 0 ? this.position - this.offset / height : this.position;\n }\n\n protected _applyAnchor(anchor: number): void {\n if (this.items.length === 0) {\n return;\n }\n const clampedAnchor = clamp(anchor, 0, this.items.length);\n const position = clamp(Math.floor(clampedAnchor), 0, this.items.length - 1);\n const height = this._getItemHeight(position);\n this.position = position;\n const offset = height > 0 ? -(clampedAnchor - position) * height : 0;\n this.offset = Object.is(offset, -0) ? 0 : offset;\n }\n\n protected _getTargetAnchor(index: number): number {\n return index;\n }\n\n render(feedback?: RenderFeedback): boolean {\n const keepAnimating = this._prepareRender();\n const { clientWidth: viewportWidth, clientHeight: viewportHeight } = this.graphics.canvas;\n this.graphics.clearRect(0, 0, viewportWidth, viewportHeight);\n this._resetRenderFeedback(feedback);\n\n let drawLength = 0;\n if (Number.isNaN(this.position)) {\n this.position = 0;\n }\n\n if (this.offset > 0) {\n if (this.position === 0) {\n this.offset = 0;\n } else {\n for (let i = this.position - 1; i >= 0; i -= 1) {\n const item = this.items[i];\n const node = this.options.renderItem(item);\n const { height } = this.measureNode(node);\n this.position = i;\n this.offset -= height;\n if (this.offset <= 0) {\n break;\n }\n }\n if (this.position === 0 && this.offset > 0) {\n this.offset = 0;\n }\n }\n }\n\n let y = this.offset;\n const drawList: DrawItem<C>[] = [];\n for (let i = this.position; i < this.items.length; i += 1) {\n const item = this.items[i];\n const node = this.options.renderItem(item);\n const { height } = this.measureNode(node);\n if (y + height > 0) {\n drawList.push({ idx: i, node, offset: y, height });\n drawLength += height;\n } else {\n this.offset += height;\n this.position = i + 1;\n }\n y += height;\n if (y >= viewportHeight) {\n break;\n }\n }\n\n let shift = 0;\n if (y < viewportHeight) {\n if (this.position === 0 && drawLength < viewportHeight) {\n shift = -this.offset;\n this.offset = 0;\n } else {\n shift = viewportHeight - y;\n y = (this.offset += shift);\n let lastIdx = -1;\n for (let i = this.position - 1; i >= 0; i -= 1) {\n const item = this.items[(lastIdx = i)];\n const node = this.options.renderItem(item);\n const { height } = this.measureNode(node);\n drawLength += height;\n y -= height;\n drawList.push({ idx: i, node, offset: y - shift, height });\n if (y < 0) {\n break;\n }\n }\n if (lastIdx === 0 && drawLength < viewportHeight) {\n shift = -drawList[drawList.length - 1].offset;\n this.position = 0;\n this.offset = 0;\n }\n }\n }\n\n const requestRedraw = this._renderDrawList(drawList, shift, feedback);\n return this._finishRender(keepAnimating || requestRedraw);\n }\n\n hittest(test: HitTest): boolean {\n const viewportHeight = this.graphics.canvas.clientHeight;\n let y = this.offset;\n\n for (let i = this.position; i < this.items.length; i += 1) {\n const item = this.items[i];\n const node = this.options.renderItem(item);\n const { height } = this.measureNode(node);\n if (test.y < y + height) {\n return node.hittest(\n this.context,\n shallowMerge(test, {\n y: test.y - y,\n }),\n );\n }\n y += height;\n if (y >= viewportHeight) {\n break;\n }\n }\n return false;\n }\n}\n\nexport class ChatRenderer<C extends CanvasRenderingContext2D, T extends {}> extends VirtualizedRenderer<C, T> {\n protected _prepareAnchorState(): void {\n if (this.items.length === 0) {\n return;\n }\n if (!Number.isFinite(this.position)) {\n this.position = this.items.length - 1;\n this.offset = 0;\n return;\n }\n this.position = this._clampItemIndex(this.position);\n if (!Number.isFinite(this.offset)) {\n this.offset = 0;\n }\n }\n\n protected _readAnchor(): number {\n this._prepareAnchorState();\n if (this.items.length === 0) {\n return 0;\n }\n const height = this._getItemHeight(this.position);\n return height > 0 ? this.position + 1 - this.offset / height : this.position + 1;\n }\n\n protected _applyAnchor(anchor: number): void {\n if (this.items.length === 0) {\n return;\n }\n const clampedAnchor = clamp(anchor, 0, this.items.length);\n const position = clamp(Math.ceil(clampedAnchor) - 1, 0, this.items.length - 1);\n const height = this._getItemHeight(position);\n this.position = position;\n const offset = height > 0 ? (position + 1 - clampedAnchor) * height : 0;\n this.offset = Object.is(offset, -0) ? 0 : offset;\n }\n\n protected _getTargetAnchor(index: number): number {\n return index + 1;\n }\n\n render(feedback?: RenderFeedback): boolean {\n const keepAnimating = this._prepareRender();\n const { clientWidth: viewportWidth, clientHeight: viewportHeight } = this.graphics.canvas;\n this.graphics.clearRect(0, 0, viewportWidth, viewportHeight);\n this._resetRenderFeedback(feedback);\n\n let drawLength = 0;\n if (Number.isNaN(this.position)) {\n this.position = this.items.length - 1;\n }\n\n if (this.offset < 0) {\n if (this.position === this.items.length - 1) {\n this.offset = 0;\n } else {\n for (let i = this.position + 1; i < this.items.length; i += 1) {\n const item = this.items[i];\n const node = this.options.renderItem(item);\n const { height } = this.measureNode(node);\n this.position = i;\n this.offset += height;\n if (this.offset > 0) {\n break;\n }\n }\n }\n }\n\n let y = viewportHeight + this.offset;\n const drawList: DrawItem<C>[] = [];\n for (let i = this.position; i >= 0; i -= 1) {\n const item = this.items[i];\n const node = this.options.renderItem(item);\n const { height } = this.measureNode(node);\n y -= height;\n if (y <= viewportHeight) {\n drawList.push({ idx: i, node, offset: y, height });\n drawLength += height;\n } else {\n this.offset -= height;\n this.position = i - 1;\n }\n if (y < 0) {\n break;\n }\n }\n\n let shift = 0;\n if (y > 0) {\n shift = -y;\n if (drawLength < viewportHeight) {\n y = drawLength;\n for (let i = this.position + 1; i < this.items.length; i += 1) {\n const item = this.items[i];\n const node = this.options.renderItem(item);\n const { height } = this.measureNode(node);\n drawList.push({ idx: i, node, offset: y - shift, height });\n y = (drawLength += height);\n this.position = i;\n if (y >= viewportHeight) {\n break;\n }\n }\n if (drawLength < viewportHeight) {\n this.offset = 0;\n } else {\n this.offset = drawLength - viewportHeight;\n }\n } else {\n this.offset = drawLength - viewportHeight;\n }\n }\n\n const requestRedraw = this._renderDrawList(drawList, shift, feedback);\n return this._finishRender(keepAnimating || requestRedraw);\n }\n\n hittest(test: HitTest): boolean {\n const viewportHeight = this.graphics.canvas.clientHeight;\n\n let drawLength = 0;\n const heights: Array<readonly [Node<C>, number]> = [];\n for (let i = this.position; i >= 0; i -= 1) {\n const item = this.items[i];\n const node = this.options.renderItem(item);\n const { height } = this.measureNode(node);\n drawLength += height;\n heights.push([node, height]);\n }\n\n let y = drawLength < viewportHeight ? drawLength : viewportHeight + this.offset;\n if (test.y > y) {\n return false;\n }\n\n for (const [node, height] of heights) {\n y -= height;\n if (test.y > y) {\n return node.hittest(\n this.context,\n shallowMerge(test, {\n y: test.y - y,\n }),\n );\n }\n }\n return false;\n }\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -8,7 +8,7 @@
8
8
  "repository": {
9
9
  "url": "https://github.com/codehz/chat-layout.git"
10
10
  },
11
- "version": "0.1.2",
11
+ "version": "0.1.4",
12
12
  "main": "./index.mjs",
13
13
  "types": "./index.d.mts",
14
14
  "exports": {