chat-layout 0.1.0 → 0.1.2

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
@@ -2,9 +2,13 @@
2
2
  type DynValue<C extends CanvasRenderingContext2D, T> = T extends Function ? never : T | ((context: C) => T);
3
3
  interface RendererOptions {}
4
4
  interface RenderFeedback {
5
+ /** Smallest visible item index that contributes a positive visible height. */
5
6
  minIdx: number;
7
+ /** Largest visible item index that contributes a positive visible height. */
6
8
  maxIdx: number;
9
+ /** Smallest visible continuous item position, expressed in item coordinates rather than pixels. */
7
10
  min: number;
11
+ /** Largest visible continuous item position, expressed in item coordinates rather than pixels. */
8
12
  max: number;
9
13
  }
10
14
  type Alignment = "left" | "center" | "right";
@@ -205,6 +209,8 @@ declare abstract class VirtualizedRenderer<C extends CanvasRenderingContext2D, T
205
209
  set items(value: T[]);
206
210
  abstract render(feedback?: RenderFeedback): boolean;
207
211
  abstract hittest(test: HitTest): boolean;
212
+ protected _resetRenderFeedback(feedback?: RenderFeedback): void;
213
+ protected _accumulateRenderFeedback(feedback: RenderFeedback, idx: number, top: number, height: number): void;
208
214
  protected _renderDrawList(list: DrawItem<C>[], shift: number, feedback?: RenderFeedback): boolean;
209
215
  }
210
216
  declare class TimelineRenderer<C extends CanvasRenderingContext2D, T extends {}> extends VirtualizedRenderer<C, T> {
package/index.mjs CHANGED
@@ -593,6 +593,9 @@ var ListState = class {
593
593
  this.offset += delta;
594
594
  }
595
595
  };
596
+ function clamp(value, min, max) {
597
+ return Math.min(Math.max(value, min), max);
598
+ }
596
599
  var VirtualizedRenderer = class extends BaseRenderer {
597
600
  get position() {
598
601
  return this.options.list.position;
@@ -612,18 +615,33 @@ var VirtualizedRenderer = class extends BaseRenderer {
612
615
  set items(value) {
613
616
  this.options.list.items = value;
614
617
  }
618
+ _resetRenderFeedback(feedback) {
619
+ if (feedback == null) return;
620
+ feedback.minIdx = NaN;
621
+ feedback.maxIdx = NaN;
622
+ feedback.min = NaN;
623
+ feedback.max = NaN;
624
+ }
625
+ _accumulateRenderFeedback(feedback, idx, top, height) {
626
+ if (!Number.isFinite(top) || !Number.isFinite(height) || height <= 0) return;
627
+ const viewportHeight = this.graphics.canvas.clientHeight;
628
+ const visibleTop = clamp(-top, 0, height);
629
+ const visibleBottom = clamp(viewportHeight - top, 0, height);
630
+ if (visibleBottom <= visibleTop) return;
631
+ const itemMin = idx + visibleTop / height;
632
+ const itemMax = idx + visibleBottom / height;
633
+ feedback.minIdx = Number.isNaN(feedback.minIdx) ? idx : Math.min(idx, feedback.minIdx);
634
+ feedback.maxIdx = Number.isNaN(feedback.maxIdx) ? idx : Math.max(idx, feedback.maxIdx);
635
+ feedback.min = Number.isNaN(feedback.min) ? itemMin : Math.min(itemMin, feedback.min);
636
+ feedback.max = Number.isNaN(feedback.max) ? itemMax : Math.max(itemMax, feedback.max);
637
+ }
615
638
  _renderDrawList(list, shift, feedback) {
616
639
  let result = false;
617
640
  const viewportHeight = this.graphics.canvas.clientHeight;
618
641
  for (const { idx, node, offset, height } of list) {
619
642
  const y = offset + shift;
643
+ if (feedback != null) this._accumulateRenderFeedback(feedback, idx, y, height);
620
644
  if (y + height < 0 || y > viewportHeight) continue;
621
- if (feedback != null) {
622
- feedback.minIdx = Number.isNaN(feedback.minIdx) ? idx : Math.min(idx, feedback.minIdx);
623
- feedback.maxIdx = Number.isNaN(feedback.maxIdx) ? idx : Math.max(idx, feedback.maxIdx);
624
- if (feedback.minIdx === idx) feedback.min = idx - Math.min(0, y) / height;
625
- if (feedback.maxIdx === idx) feedback.max = idx - Math.max(0, y + height - viewportHeight) / height;
626
- }
627
645
  if (node.draw(this.context, 0, y)) result = true;
628
646
  }
629
647
  return result;
@@ -633,6 +651,7 @@ var TimelineRenderer = class extends VirtualizedRenderer {
633
651
  render(feedback) {
634
652
  const { clientWidth: viewportWidth, clientHeight: viewportHeight } = this.graphics.canvas;
635
653
  this.graphics.clearRect(0, 0, viewportWidth, viewportHeight);
654
+ this._resetRenderFeedback(feedback);
636
655
  let drawLength = 0;
637
656
  if (Number.isNaN(this.position)) this.position = 0;
638
657
  if (this.offset > 0) if (this.position === 0) this.offset = 0;
@@ -716,6 +735,7 @@ var ChatRenderer = class extends VirtualizedRenderer {
716
735
  render(feedback) {
717
736
  const { clientWidth: viewportWidth, clientHeight: viewportHeight } = this.graphics.canvas;
718
737
  this.graphics.clearRect(0, 0, viewportWidth, viewportHeight);
738
+ this._resetRenderFeedback(feedback);
719
739
  let drawLength = 0;
720
740
  if (Number.isNaN(this.position)) this.position = this.items.length - 1;
721
741
  if (this.offset < 0) if (this.position === this.items.length - 1) this.offset = 0;
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\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 _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 (y + height < 0 || y > viewportHeight) {\n continue;\n }\n if (feedback != null) {\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 if (feedback.minIdx === idx) {\n feedback.min = idx - Math.min(0, y) / height;\n }\n if (feedback.maxIdx === idx) {\n feedback.max = idx - Math.max(0, y + height - viewportHeight) / height;\n }\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\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\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"],"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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"}
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.0",
11
+ "version": "0.1.2",
12
12
  "main": "./index.mjs",
13
13
  "types": "./index.d.mts",
14
14
  "exports": {