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 +6 -0
- package/index.mjs +26 -6
- package/index.mjs.map +1 -1
- package/package.json +1 -1
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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"}
|