chat-layout 0.1.2 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.d.mts +27 -1
- package/index.mjs +163 -3
- package/index.mjs.map +1 -1
- package/package.json +1 -1
package/index.d.mts
CHANGED
|
@@ -197,10 +197,19 @@ type DrawItem<C extends CanvasRenderingContext2D> = {
|
|
|
197
197
|
offset: number;
|
|
198
198
|
height: number;
|
|
199
199
|
};
|
|
200
|
+
interface JumpToOptions {
|
|
201
|
+
animated?: boolean;
|
|
202
|
+
duration?: number;
|
|
203
|
+
onComplete?: () => void;
|
|
204
|
+
}
|
|
200
205
|
declare abstract class VirtualizedRenderer<C extends CanvasRenderingContext2D, T extends {}> extends BaseRenderer<C, {
|
|
201
206
|
renderItem: (item: T) => Node<C>;
|
|
202
207
|
list: ListState<T>;
|
|
203
208
|
}> {
|
|
209
|
+
#private;
|
|
210
|
+
static readonly MIN_JUMP_DURATION = 160;
|
|
211
|
+
static readonly MAX_JUMP_DURATION = 420;
|
|
212
|
+
static readonly JUMP_DURATION_PER_ITEM = 28;
|
|
204
213
|
get position(): number;
|
|
205
214
|
set position(value: number);
|
|
206
215
|
get offset(): number;
|
|
@@ -209,15 +218,32 @@ declare abstract class VirtualizedRenderer<C extends CanvasRenderingContext2D, T
|
|
|
209
218
|
set items(value: T[]);
|
|
210
219
|
abstract render(feedback?: RenderFeedback): boolean;
|
|
211
220
|
abstract hittest(test: HitTest): boolean;
|
|
221
|
+
jumpTo(index: number, options?: JumpToOptions): void;
|
|
212
222
|
protected _resetRenderFeedback(feedback?: RenderFeedback): void;
|
|
213
223
|
protected _accumulateRenderFeedback(feedback: RenderFeedback, idx: number, top: number, height: number): void;
|
|
214
224
|
protected _renderDrawList(list: DrawItem<C>[], shift: number, feedback?: RenderFeedback): boolean;
|
|
225
|
+
protected _prepareRender(): boolean;
|
|
226
|
+
protected _finishRender(requestRedraw: boolean): boolean;
|
|
227
|
+
protected _clampItemIndex(index: number): number;
|
|
228
|
+
protected _getItemHeight(index: number): number;
|
|
229
|
+
protected abstract _prepareAnchorState(): void;
|
|
230
|
+
protected abstract _readAnchor(): number;
|
|
231
|
+
protected abstract _applyAnchor(anchor: number): void;
|
|
232
|
+
protected abstract _getTargetAnchor(index: number): number;
|
|
215
233
|
}
|
|
216
234
|
declare class TimelineRenderer<C extends CanvasRenderingContext2D, T extends {}> extends VirtualizedRenderer<C, T> {
|
|
235
|
+
protected _prepareAnchorState(): void;
|
|
236
|
+
protected _readAnchor(): number;
|
|
237
|
+
protected _applyAnchor(anchor: number): void;
|
|
238
|
+
protected _getTargetAnchor(index: number): number;
|
|
217
239
|
render(feedback?: RenderFeedback): boolean;
|
|
218
240
|
hittest(test: HitTest): boolean;
|
|
219
241
|
}
|
|
220
242
|
declare class ChatRenderer<C extends CanvasRenderingContext2D, T extends {}> extends VirtualizedRenderer<C, T> {
|
|
243
|
+
protected _prepareAnchorState(): void;
|
|
244
|
+
protected _readAnchor(): number;
|
|
245
|
+
protected _applyAnchor(anchor: number): void;
|
|
246
|
+
protected _getTargetAnchor(index: number): number;
|
|
221
247
|
render(feedback?: RenderFeedback): boolean;
|
|
222
248
|
hittest(test: HitTest): boolean;
|
|
223
249
|
}
|
|
@@ -227,5 +253,5 @@ declare function registerNodeParent<C extends CanvasRenderingContext2D>(node: No
|
|
|
227
253
|
declare function unregisterNodeParent<C extends CanvasRenderingContext2D>(node: Node<C>): void;
|
|
228
254
|
declare function getNodeParent<C extends CanvasRenderingContext2D>(node: Node<C>): Node<C> | undefined;
|
|
229
255
|
//#endregion
|
|
230
|
-
export { AlignBox, Alignment, BaseRenderer, Box, ChatRenderer, Context, DebugRenderer, DynValue, Fixed, Group, HStack, HitTest, ListState, MultilineText, Node, PaddingBox, RenderFeedback, RendererOptions, Text, TimelineRenderer, VStack, VirtualizedRenderer, Wrapper, getNodeParent, memoRenderItem, registerNodeParent, unregisterNodeParent };
|
|
256
|
+
export { AlignBox, Alignment, BaseRenderer, Box, ChatRenderer, Context, DebugRenderer, DynValue, Fixed, Group, HStack, HitTest, JumpToOptions, ListState, MultilineText, Node, PaddingBox, RenderFeedback, RendererOptions, Text, TimelineRenderer, VStack, VirtualizedRenderer, Wrapper, getNodeParent, memoRenderItem, registerNodeParent, unregisterNodeParent };
|
|
231
257
|
//# sourceMappingURL=index.d.mts.map
|
package/index.mjs
CHANGED
|
@@ -596,7 +596,21 @@ var ListState = class {
|
|
|
596
596
|
function clamp(value, min, max) {
|
|
597
597
|
return Math.min(Math.max(value, min), max);
|
|
598
598
|
}
|
|
599
|
-
|
|
599
|
+
function sameState(state, position, offset) {
|
|
600
|
+
return Object.is(state.position, position) && Object.is(state.offset, offset);
|
|
601
|
+
}
|
|
602
|
+
function smoothstep(value) {
|
|
603
|
+
return value * value * (3 - 2 * value);
|
|
604
|
+
}
|
|
605
|
+
function getNow() {
|
|
606
|
+
return globalThis.performance?.now() ?? Date.now();
|
|
607
|
+
}
|
|
608
|
+
var VirtualizedRenderer = class VirtualizedRenderer extends BaseRenderer {
|
|
609
|
+
static MIN_JUMP_DURATION = 160;
|
|
610
|
+
static MAX_JUMP_DURATION = 420;
|
|
611
|
+
static JUMP_DURATION_PER_ITEM = 28;
|
|
612
|
+
#controlledState;
|
|
613
|
+
#jumpAnimation;
|
|
600
614
|
get position() {
|
|
601
615
|
return this.options.list.position;
|
|
602
616
|
}
|
|
@@ -615,6 +629,47 @@ var VirtualizedRenderer = class extends BaseRenderer {
|
|
|
615
629
|
set items(value) {
|
|
616
630
|
this.options.list.items = value;
|
|
617
631
|
}
|
|
632
|
+
jumpTo(index, options = {}) {
|
|
633
|
+
if (this.items.length === 0) {
|
|
634
|
+
this.#cancelJumpAnimation();
|
|
635
|
+
return;
|
|
636
|
+
}
|
|
637
|
+
const targetIndex = this._clampItemIndex(index);
|
|
638
|
+
this._prepareAnchorState();
|
|
639
|
+
const targetAnchor = this._getTargetAnchor(targetIndex);
|
|
640
|
+
if (!(options.animated ?? true)) {
|
|
641
|
+
this.#cancelJumpAnimation();
|
|
642
|
+
this._applyAnchor(targetAnchor);
|
|
643
|
+
options.onComplete?.();
|
|
644
|
+
return;
|
|
645
|
+
}
|
|
646
|
+
const startAnchor = this._readAnchor();
|
|
647
|
+
if (!Number.isFinite(startAnchor)) {
|
|
648
|
+
this.#cancelJumpAnimation();
|
|
649
|
+
this._applyAnchor(targetAnchor);
|
|
650
|
+
options.onComplete?.();
|
|
651
|
+
return;
|
|
652
|
+
}
|
|
653
|
+
const duration = clamp(options.duration ?? VirtualizedRenderer.MIN_JUMP_DURATION + Math.abs(targetAnchor - startAnchor) * VirtualizedRenderer.JUMP_DURATION_PER_ITEM, 0, VirtualizedRenderer.MAX_JUMP_DURATION);
|
|
654
|
+
if (duration <= 0 || Math.abs(targetAnchor - startAnchor) <= Number.EPSILON) {
|
|
655
|
+
this.#cancelJumpAnimation();
|
|
656
|
+
this._applyAnchor(targetAnchor);
|
|
657
|
+
options.onComplete?.();
|
|
658
|
+
return;
|
|
659
|
+
}
|
|
660
|
+
this.#jumpAnimation = {
|
|
661
|
+
startAnchor,
|
|
662
|
+
targetAnchor,
|
|
663
|
+
startTime: getNow(),
|
|
664
|
+
duration,
|
|
665
|
+
needsMoreFrames: true,
|
|
666
|
+
onComplete: options.onComplete
|
|
667
|
+
};
|
|
668
|
+
this.#controlledState = {
|
|
669
|
+
position: this.position,
|
|
670
|
+
offset: this.offset
|
|
671
|
+
};
|
|
672
|
+
}
|
|
618
673
|
_resetRenderFeedback(feedback) {
|
|
619
674
|
if (feedback == null) return;
|
|
620
675
|
feedback.minIdx = NaN;
|
|
@@ -646,9 +701,83 @@ var VirtualizedRenderer = class extends BaseRenderer {
|
|
|
646
701
|
}
|
|
647
702
|
return result;
|
|
648
703
|
}
|
|
704
|
+
_prepareRender() {
|
|
705
|
+
const animation = this.#jumpAnimation;
|
|
706
|
+
if (animation == null) return false;
|
|
707
|
+
if (this.items.length === 0) {
|
|
708
|
+
this.#cancelJumpAnimation();
|
|
709
|
+
return false;
|
|
710
|
+
}
|
|
711
|
+
if (this.#controlledState != null && !sameState(this.#controlledState, this.position, this.offset)) {
|
|
712
|
+
this.#cancelJumpAnimation();
|
|
713
|
+
return false;
|
|
714
|
+
}
|
|
715
|
+
const progress = clamp((getNow() - animation.startTime) / animation.duration, 0, 1);
|
|
716
|
+
const eased = progress >= 1 ? 1 : smoothstep(progress);
|
|
717
|
+
const anchor = animation.startAnchor + (animation.targetAnchor - animation.startAnchor) * eased;
|
|
718
|
+
this._applyAnchor(anchor);
|
|
719
|
+
animation.needsMoreFrames = progress < 1;
|
|
720
|
+
return animation.needsMoreFrames;
|
|
721
|
+
}
|
|
722
|
+
_finishRender(requestRedraw) {
|
|
723
|
+
const animation = this.#jumpAnimation;
|
|
724
|
+
if (animation == null) return requestRedraw;
|
|
725
|
+
if (animation.needsMoreFrames) {
|
|
726
|
+
this.#controlledState = {
|
|
727
|
+
position: this.position,
|
|
728
|
+
offset: this.offset
|
|
729
|
+
};
|
|
730
|
+
return true;
|
|
731
|
+
}
|
|
732
|
+
const onComplete = animation.onComplete;
|
|
733
|
+
this.#cancelJumpAnimation();
|
|
734
|
+
onComplete?.();
|
|
735
|
+
return requestRedraw || this.#jumpAnimation != null;
|
|
736
|
+
}
|
|
737
|
+
_clampItemIndex(index) {
|
|
738
|
+
return clamp(Number.isFinite(index) ? Math.trunc(index) : 0, 0, this.items.length - 1);
|
|
739
|
+
}
|
|
740
|
+
_getItemHeight(index) {
|
|
741
|
+
const item = this.items[index];
|
|
742
|
+
const node = this.options.renderItem(item);
|
|
743
|
+
return this.measureNode(node).height;
|
|
744
|
+
}
|
|
745
|
+
#cancelJumpAnimation() {
|
|
746
|
+
this.#jumpAnimation = void 0;
|
|
747
|
+
this.#controlledState = void 0;
|
|
748
|
+
}
|
|
649
749
|
};
|
|
650
750
|
var TimelineRenderer = class extends VirtualizedRenderer {
|
|
751
|
+
_prepareAnchorState() {
|
|
752
|
+
if (this.items.length === 0) return;
|
|
753
|
+
if (!Number.isFinite(this.position)) {
|
|
754
|
+
this.position = 0;
|
|
755
|
+
this.offset = 0;
|
|
756
|
+
return;
|
|
757
|
+
}
|
|
758
|
+
this.position = this._clampItemIndex(this.position);
|
|
759
|
+
if (!Number.isFinite(this.offset)) this.offset = 0;
|
|
760
|
+
}
|
|
761
|
+
_readAnchor() {
|
|
762
|
+
this._prepareAnchorState();
|
|
763
|
+
if (this.items.length === 0) return 0;
|
|
764
|
+
const height = this._getItemHeight(this.position);
|
|
765
|
+
return height > 0 ? this.position - this.offset / height : this.position;
|
|
766
|
+
}
|
|
767
|
+
_applyAnchor(anchor) {
|
|
768
|
+
if (this.items.length === 0) return;
|
|
769
|
+
const clampedAnchor = clamp(anchor, 0, this.items.length);
|
|
770
|
+
const position = clamp(Math.floor(clampedAnchor), 0, this.items.length - 1);
|
|
771
|
+
const height = this._getItemHeight(position);
|
|
772
|
+
this.position = position;
|
|
773
|
+
const offset = height > 0 ? -(clampedAnchor - position) * height : 0;
|
|
774
|
+
this.offset = Object.is(offset, -0) ? 0 : offset;
|
|
775
|
+
}
|
|
776
|
+
_getTargetAnchor(index) {
|
|
777
|
+
return index;
|
|
778
|
+
}
|
|
651
779
|
render(feedback) {
|
|
780
|
+
const keepAnimating = this._prepareRender();
|
|
652
781
|
const { clientWidth: viewportWidth, clientHeight: viewportHeight } = this.graphics.canvas;
|
|
653
782
|
this.graphics.clearRect(0, 0, viewportWidth, viewportHeight);
|
|
654
783
|
this._resetRenderFeedback(feedback);
|
|
@@ -715,7 +844,8 @@ var TimelineRenderer = class extends VirtualizedRenderer {
|
|
|
715
844
|
this.offset = 0;
|
|
716
845
|
}
|
|
717
846
|
}
|
|
718
|
-
|
|
847
|
+
const requestRedraw = this._renderDrawList(drawList, shift, feedback);
|
|
848
|
+
return this._finishRender(keepAnimating || requestRedraw);
|
|
719
849
|
}
|
|
720
850
|
hittest(test) {
|
|
721
851
|
const viewportHeight = this.graphics.canvas.clientHeight;
|
|
@@ -732,7 +862,36 @@ var TimelineRenderer = class extends VirtualizedRenderer {
|
|
|
732
862
|
}
|
|
733
863
|
};
|
|
734
864
|
var ChatRenderer = class extends VirtualizedRenderer {
|
|
865
|
+
_prepareAnchorState() {
|
|
866
|
+
if (this.items.length === 0) return;
|
|
867
|
+
if (!Number.isFinite(this.position)) {
|
|
868
|
+
this.position = this.items.length - 1;
|
|
869
|
+
this.offset = 0;
|
|
870
|
+
return;
|
|
871
|
+
}
|
|
872
|
+
this.position = this._clampItemIndex(this.position);
|
|
873
|
+
if (!Number.isFinite(this.offset)) this.offset = 0;
|
|
874
|
+
}
|
|
875
|
+
_readAnchor() {
|
|
876
|
+
this._prepareAnchorState();
|
|
877
|
+
if (this.items.length === 0) return 0;
|
|
878
|
+
const height = this._getItemHeight(this.position);
|
|
879
|
+
return height > 0 ? this.position + 1 - this.offset / height : this.position + 1;
|
|
880
|
+
}
|
|
881
|
+
_applyAnchor(anchor) {
|
|
882
|
+
if (this.items.length === 0) return;
|
|
883
|
+
const clampedAnchor = clamp(anchor, 0, this.items.length);
|
|
884
|
+
const position = clamp(Math.ceil(clampedAnchor) - 1, 0, this.items.length - 1);
|
|
885
|
+
const height = this._getItemHeight(position);
|
|
886
|
+
this.position = position;
|
|
887
|
+
const offset = height > 0 ? (position + 1 - clampedAnchor) * height : 0;
|
|
888
|
+
this.offset = Object.is(offset, -0) ? 0 : offset;
|
|
889
|
+
}
|
|
890
|
+
_getTargetAnchor(index) {
|
|
891
|
+
return index + 1;
|
|
892
|
+
}
|
|
735
893
|
render(feedback) {
|
|
894
|
+
const keepAnimating = this._prepareRender();
|
|
736
895
|
const { clientWidth: viewportWidth, clientHeight: viewportHeight } = this.graphics.canvas;
|
|
737
896
|
this.graphics.clearRect(0, 0, viewportWidth, viewportHeight);
|
|
738
897
|
this._resetRenderFeedback(feedback);
|
|
@@ -791,7 +950,8 @@ var ChatRenderer = class extends VirtualizedRenderer {
|
|
|
791
950
|
else this.offset = drawLength - viewportHeight;
|
|
792
951
|
} else this.offset = drawLength - viewportHeight;
|
|
793
952
|
}
|
|
794
|
-
|
|
953
|
+
const requestRedraw = this._renderDrawList(drawList, shift, feedback);
|
|
954
|
+
return this._finishRender(keepAnimating || requestRedraw);
|
|
795
955
|
}
|
|
796
956
|
hittest(test) {
|
|
797
957
|
const viewportHeight = this.graphics.canvas.clientHeight;
|
package/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["#inner","#top","#bottom","#left","#right","#shift","#width","#lines","#text","#ctx","#lastWidth","#cache"],"sources":["../src/text.ts","../src/utils.ts","../src/registry.ts","../src/nodes.ts","../src/renderer.ts"],"sourcesContent":["import { layoutWithLines, prepareWithSegments } from \"@chenglou/pretext\";\nimport type { Context } from \"./types\";\n\nexport interface TextLayout {\n width: number;\n text: string;\n shift: number;\n}\n\nfunction preprocessSegments(text: string): string[] {\n return text\n .split(\"\\n\")\n .map((line) => line.trim())\n .filter(Boolean);\n}\n\nexport function layoutFirstLine<C extends CanvasRenderingContext2D>(\n ctx: Context<C>,\n text: string,\n maxWidth: number,\n): TextLayout {\n if (maxWidth < 0) {\n maxWidth = 0;\n }\n const segments = preprocessSegments(text);\n const segment = segments[0];\n if (!segment) {\n return { width: 0, text: \"\", shift: 0 };\n }\n const {\n fontBoundingBoxAscent: ascent = 0,\n fontBoundingBoxDescent: descent = 0,\n } = ctx.graphics.measureText(segment);\n const shift = ascent - descent;\n if (maxWidth === 0) {\n return { width: 0, text: \"\", shift };\n }\n const prepared = prepareWithSegments(segment, ctx.graphics.font);\n const { lines } = layoutWithLines(prepared, maxWidth, 0);\n if (lines.length === 0) {\n return { width: 0, text: \"\", shift };\n }\n return { width: lines[0].width, text: lines[0].text, shift };\n}\n\nexport function layoutText<C extends CanvasRenderingContext2D>(\n ctx: Context<C>,\n text: string,\n maxWidth: number,\n): { width: number; lines: TextLayout[] } {\n if (maxWidth < 0) {\n maxWidth = 0;\n }\n\n const segments = preprocessSegments(text);\n if (segments.length === 0 || maxWidth === 0) {\n return { width: 0, lines: [] };\n }\n\n const font = ctx.graphics.font;\n let width = 0;\n const lines: TextLayout[] = [];\n\n for (const segment of segments) {\n const {\n fontBoundingBoxAscent: ascent = 0,\n fontBoundingBoxDescent: descent = 0,\n } = ctx.graphics.measureText(segment);\n const shift = ascent - descent;\n const prepared = prepareWithSegments(segment, font);\n const { lines: segLines } = layoutWithLines(prepared, maxWidth, 0);\n for (const segLine of segLines) {\n width = Math.max(width, segLine.width);\n lines.push({ width: segLine.width, text: segLine.text, shift });\n }\n }\n\n return { width, lines };\n}\n","export function shallow<T extends object>(object: T): T {\n return Object.create(object) as T;\n}\n\nexport function shallowMerge<T extends object, R extends object>(object: T, other: R): T & R {\n return { __proto__: object, ...other } as unknown as T & R;\n}\n","import type { Node } from \"./types\";\n\nconst registry = new WeakMap<Node<any>, Node<any>>();\n\nexport function registerNodeParent<C extends CanvasRenderingContext2D>(\n node: Node<C>,\n parent: Node<C>,\n): void {\n registry.set(node, parent);\n}\n\nexport function unregisterNodeParent<C extends CanvasRenderingContext2D>(node: Node<C>): void {\n registry.delete(node);\n}\n\nexport function getNodeParent<C extends CanvasRenderingContext2D>(node: Node<C>): Node<C> | undefined {\n return registry.get(node);\n}\n","import type { Alignment, Box, Context, DynValue, HitTest, Node } from \"./types\";\nimport { layoutFirstLine, layoutText, type TextLayout } from \"./text\";\nimport { shallow, shallowMerge } from \"./utils\";\nimport { registerNodeParent, unregisterNodeParent } from \"./registry\";\n\nexport abstract class Group<C extends CanvasRenderingContext2D> implements Node<C> {\n constructor(readonly children: Node<C>[]) {\n for (const child of children) {\n registerNodeParent(child, this);\n }\n }\n\n abstract measure(ctx: Context<C>): Box;\n abstract draw(ctx: Context<C>, x: number, y: number): boolean;\n abstract hittest(ctx: Context<C>, test: HitTest): boolean;\n\n get flex(): boolean {\n return this.children.some((item) => item.flex);\n }\n}\n\nexport class VStack<C extends CanvasRenderingContext2D> extends Group<C> {\n constructor(\n children: Node<C>[],\n readonly options: { gap?: number; alignment?: \"left\" | \"center\" | \"right\" } = {},\n ) {\n super(children);\n }\n\n measure(ctx: Context<C>): Box {\n let width = 0;\n let height = 0;\n if (this.options.alignment != null) {\n ctx.alignment = this.options.alignment;\n }\n\n for (const [index, child] of this.children.entries()) {\n if (this.options.gap != null && index !== 0) {\n height += this.options.gap;\n }\n const result = shallow(ctx).measureNode(child);\n height += result.height;\n width = Math.max(width, result.width);\n }\n ctx.remainingWidth -= width;\n return { width, height };\n }\n\n draw(ctx: Context<C>, x: number, y: number): boolean {\n let result = false;\n const fullWidth = ctx.measureNode(this).width;\n const alignment = this.options.alignment ?? ctx.alignment;\n if (this.options.alignment != null) {\n ctx.alignment = this.options.alignment;\n }\n\n for (const [index, child] of this.children.entries()) {\n if (this.options.gap != null && index !== 0) {\n y += this.options.gap;\n }\n const { width, height } = shallow(ctx).measureNode(child);\n const curCtx = shallow(ctx);\n let requestRedraw: boolean;\n if (alignment === \"right\") {\n requestRedraw = child.draw(curCtx, x + fullWidth - width, y);\n } else if (alignment === \"center\") {\n requestRedraw = child.draw(curCtx, x + (fullWidth - width) / 2, y);\n } else {\n requestRedraw = child.draw(curCtx, x, y);\n }\n result ||= requestRedraw;\n y += height;\n }\n return result;\n }\n\n hittest(ctx: Context<C>, test: HitTest): boolean {\n let y = 0;\n const fullWidth = ctx.measureNode(this).width;\n const alignment = this.options.alignment ?? ctx.alignment;\n if (this.options.alignment != null) {\n ctx.alignment = this.options.alignment;\n }\n\n for (const [index, child] of this.children.entries()) {\n if (this.options.gap != null && index !== 0) {\n y += this.options.gap;\n }\n\n const { width, height } = shallow(ctx).measureNode(child);\n const curCtx = shallow(ctx);\n if (test.y >= y && test.y < y + height) {\n let x: number;\n if (alignment === \"right\") {\n x = test.x - fullWidth + width;\n } else if (alignment === \"center\") {\n x = test.x - (fullWidth - width) / 2;\n } else {\n x = test.x;\n }\n if (x < 0 || x >= width) {\n return false;\n }\n return child.hittest(\n curCtx,\n shallowMerge(test, {\n x,\n y: test.y - y,\n }),\n );\n }\n y += height;\n }\n return false;\n }\n}\n\nexport class HStack<C extends CanvasRenderingContext2D> extends Group<C> {\n constructor(\n readonly children: Node<C>[],\n readonly options: { reverse?: boolean; gap?: number } = {},\n ) {\n super(children);\n }\n\n measure(ctx: Context<C>): Box {\n let width = 0;\n let height = 0;\n let firstFlex: Node<C> | undefined;\n\n for (const [index, child] of this.children.entries()) {\n if (this.options.gap != null && index !== 0) {\n width += this.options.gap;\n }\n if (firstFlex == null && child.flex) {\n firstFlex = child;\n continue;\n }\n const curCtx = shallow(ctx);\n curCtx.remainingWidth = ctx.remainingWidth - width;\n const result = curCtx.measureNode(child);\n width += result.width;\n height = Math.max(height, result.height);\n }\n\n if (firstFlex != null) {\n const curCtx = shallow(ctx);\n curCtx.remainingWidth = ctx.remainingWidth - width;\n const result = curCtx.measureNode(firstFlex);\n width += result.width;\n height = Math.max(height, result.height);\n }\n\n return { width, height };\n }\n\n draw(ctx: Context<C>, x: number, y: number): boolean {\n let result = false;\n const reverse = this.options.reverse ?? ctx.reverse;\n if (this.options.reverse) {\n ctx.reverse = this.options.reverse;\n }\n\n if (reverse) {\n x += ctx.measureNode(this).width;\n for (const [index, child] of this.children.entries()) {\n const gap = this.options.gap != null && index !== 0 ? this.options.gap : undefined;\n if (gap) {\n x -= gap;\n ctx.remainingWidth -= gap;\n }\n const { width } = shallow(ctx).measureNode(child);\n x -= width;\n const requestRedraw = child.draw(shallow(ctx), x, y);\n result ||= requestRedraw;\n ctx.remainingWidth -= width;\n }\n } else {\n for (const [index, child] of this.children.entries()) {\n const gap = this.options.gap != null && index !== 0 ? this.options.gap : undefined;\n if (gap) {\n x += gap;\n ctx.remainingWidth -= gap;\n }\n const requestRedraw = child.draw(shallow(ctx), x, y);\n result ||= requestRedraw;\n const { width } = shallow(ctx).measureNode(child);\n ctx.remainingWidth -= width;\n x += width;\n }\n }\n\n return result;\n }\n\n hittest(ctx: Context<C>, test: HitTest): boolean {\n const reverse = this.options.reverse ?? ctx.reverse;\n if (this.options.reverse) {\n ctx.reverse = this.options.reverse;\n }\n\n if (reverse) {\n let x = ctx.measureNode(this).width;\n for (const [index, child] of this.children.entries()) {\n const gap = this.options.gap != null && index !== 0 ? this.options.gap : undefined;\n if (gap) {\n x -= gap;\n ctx.remainingWidth -= gap;\n }\n const { width, height } = shallow(ctx).measureNode(child);\n x -= width;\n if (x <= test.x && test.x < x + width) {\n if (test.y >= height) {\n return false;\n }\n return child.hittest(\n shallow(ctx),\n shallowMerge(test, {\n x: test.x - x,\n }),\n );\n }\n ctx.remainingWidth -= width;\n }\n } else {\n let x = 0;\n for (const [index, child] of this.children.entries()) {\n const gap = this.options.gap != null && index !== 0 ? this.options.gap : undefined;\n if (gap) {\n x += gap;\n ctx.remainingWidth -= gap;\n }\n const { width, height } = shallow(ctx).measureNode(child);\n if (x <= test.x && test.x < x + width) {\n if (test.y >= height) {\n return false;\n }\n return child.hittest(\n shallow(ctx),\n shallowMerge(test, {\n x: test.x - x,\n }),\n );\n }\n x += width;\n ctx.remainingWidth -= width;\n }\n }\n\n return false;\n }\n}\n\nexport class Wrapper<C extends CanvasRenderingContext2D> implements Node<C> {\n #inner: Node<C>;\n\n constructor(inner: Node<C>) {\n this.#inner = inner;\n registerNodeParent(this.#inner, this);\n }\n\n get inner(): Node<C> {\n return this.#inner;\n }\n\n set inner(newNode: Node<C>) {\n if (newNode === this.#inner) {\n return;\n }\n unregisterNodeParent(this.#inner);\n this.#inner = newNode;\n registerNodeParent(newNode, this);\n }\n\n get flex(): boolean {\n return this.inner.flex;\n }\n\n measure(ctx: Context<C>): Box {\n return this.inner.measure(ctx);\n }\n\n draw(ctx: Context<C>, x: number, y: number): boolean {\n return this.inner.draw(ctx, x, y);\n }\n\n hittest(ctx: Context<C>, test: HitTest): boolean {\n return this.inner.hittest(ctx, test);\n }\n}\n\nexport class PaddingBox<C extends CanvasRenderingContext2D> extends Wrapper<C> {\n constructor(\n inner: Node<C>,\n readonly padding: {\n top?: number;\n bottom?: number;\n left?: number;\n right?: number;\n } = {},\n ) {\n super(inner);\n }\n\n get #top(): number {\n return this.padding.top ?? 0;\n }\n\n get #bottom(): number {\n return this.padding.bottom ?? 0;\n }\n\n get #left(): number {\n return this.padding.left ?? 0;\n }\n\n get #right(): number {\n return this.padding.right ?? 0;\n }\n\n measure(ctx: Context<C>): Box {\n ctx.remainingWidth -= this.#left + this.#right;\n const { width, height } = ctx.measureNode(this.inner);\n return {\n width: width + this.#left + this.#right,\n height: height + this.#top + this.#bottom,\n };\n }\n\n draw(ctx: Context<C>, x: number, y: number): boolean {\n ctx.remainingWidth -= this.#left + this.#right;\n return this.inner.draw(ctx, x + this.#left, y + this.#top);\n }\n\n hittest(ctx: Context<C>, test: HitTest): boolean {\n ctx.remainingWidth -= this.#left + this.#right;\n const { width, height } = shallow(ctx).measureNode(this.inner);\n if (0 <= test.x - this.#left && test.x - this.#left < width && 0 <= test.y - this.#top && test.y - this.#top < height) {\n return this.inner.hittest(\n shallow(ctx),\n shallowMerge(test, {\n x: test.x - this.#left,\n y: test.y - this.#top,\n }),\n );\n }\n return false;\n }\n}\n\nexport class AlignBox<C extends CanvasRenderingContext2D> extends Wrapper<C> {\n #shift = 0;\n\n constructor(\n inner: Node<C>,\n readonly options: {\n alignment: Alignment;\n },\n ) {\n super(inner);\n }\n\n measure(ctx: Context<C>): Box {\n ctx.alignment = this.options.alignment;\n const { width, height } = ctx.measureNode(this.inner);\n switch (this.options.alignment) {\n case \"center\":\n this.#shift = (ctx.remainingWidth - width) / 2;\n break;\n case \"right\":\n this.#shift = ctx.remainingWidth - width;\n break;\n default:\n this.#shift = 0;\n }\n return {\n width: ctx.remainingWidth,\n height,\n };\n }\n\n draw(ctx: Context<C>, x: number, y: number): boolean {\n ctx.alignment = this.options.alignment;\n return this.inner.draw(ctx, x + this.#shift, y);\n }\n\n hittest(ctx: Context<C>, test: HitTest): boolean {\n ctx.alignment = this.options.alignment;\n const { width } = shallow(ctx).measureNode(this.inner);\n if (0 <= test.x - this.#shift && test.x - this.#shift < width) {\n return this.inner.hittest(\n shallow(ctx),\n shallowMerge(test, {\n x: test.x - this.#shift,\n }),\n );\n }\n return false;\n }\n}\n\nexport class MultilineText<C extends CanvasRenderingContext2D> implements Node<C> {\n #width = 0;\n #lines: TextLayout[] = [];\n\n constructor(\n readonly text: string,\n readonly options: {\n lineHeight: number;\n font: string;\n alignment: \"left\" | \"center\" | \"right\";\n style: DynValue<C, string>;\n },\n ) {}\n\n get flex(): boolean {\n return true;\n }\n\n measure(ctx: Context<C>): Box {\n return ctx.with((g) => {\n g.font = this.options.font;\n const { width, lines } = layoutText(ctx, this.text, ctx.remainingWidth);\n this.#width = width;\n this.#lines = lines;\n return { width: this.#width, height: this.#lines.length * this.options.lineHeight };\n });\n }\n\n draw(ctx: Context<C>, x: number, y: number): boolean {\n return ctx.with((g) => {\n g.font = this.options.font;\n g.fillStyle = ctx.resolveDynValue(this.options.style);\n switch (this.options.alignment) {\n case \"left\":\n for (const { text, shift } of this.#lines) {\n g.fillText(text, x, y + (this.options.lineHeight + shift) / 2);\n y += this.options.lineHeight;\n }\n break;\n case \"right\":\n x += this.#width;\n g.textAlign = \"right\";\n for (const { text, shift } of this.#lines) {\n g.fillText(text, x, y + (this.options.lineHeight + shift) / 2);\n y += this.options.lineHeight;\n }\n break;\n case \"center\":\n x += this.#width / 2;\n g.textAlign = \"center\";\n for (const { text, shift } of this.#lines) {\n g.fillText(text, x, y + (this.options.lineHeight + shift) / 2);\n y += this.options.lineHeight;\n }\n break;\n }\n return false;\n });\n }\n\n hittest(_ctx: Context<C>, _test: HitTest): boolean {\n return false;\n }\n}\n\nexport class Text<C extends CanvasRenderingContext2D> implements Node<C> {\n #width = 0;\n #text = \"\";\n #shift = 0;\n\n constructor(\n readonly text: string,\n readonly options: {\n lineHeight: number;\n font: string;\n style: DynValue<C, string>;\n },\n ) {}\n\n get flex(): boolean {\n return false;\n }\n\n measure(ctx: Context<C>): Box {\n return ctx.with((g) => {\n g.font = this.options.font;\n const { width, text, shift } = layoutFirstLine(ctx, this.text, ctx.remainingWidth);\n this.#width = width;\n this.#text = text;\n this.#shift = shift;\n return { width: this.#width, height: this.options.lineHeight };\n });\n }\n\n draw(ctx: Context<C>, x: number, y: number): boolean {\n return ctx.with((g) => {\n g.font = this.options.font;\n g.fillStyle = ctx.resolveDynValue(this.options.style);\n g.fillText(this.#text, x, y + (this.options.lineHeight + this.#shift) / 2);\n return false;\n });\n }\n\n hittest(_ctx: Context<C>, _test: HitTest): boolean {\n return false;\n }\n}\n\nexport class Fixed<C extends CanvasRenderingContext2D> implements Node<C> {\n constructor(\n readonly width: number,\n readonly height: number,\n ) {}\n\n get flex(): boolean {\n return false;\n }\n\n measure(_ctx: Context<C>): Box {\n return { width: this.width, height: this.height };\n }\n\n draw(_ctx: Context<C>, _x: number, _y: number): boolean {\n return false;\n }\n\n hittest(_ctx: Context<C>, _test: HitTest): boolean {\n return false;\n }\n}\n","import type { Box, Context, DynValue, HitTest, Node, RenderFeedback, RendererOptions } from \"./types\";\nimport { shallow, shallowMerge } from \"./utils\";\nimport { getNodeParent } from \"./registry\";\n\nexport class BaseRenderer<C extends CanvasRenderingContext2D, O extends {} = {}> {\n graphics: C;\n #ctx: Context<C>;\n #lastWidth: number;\n #cache = new WeakMap<Node<C>, Box>();\n\n protected get context(): Context<C> {\n return shallow(this.#ctx);\n }\n\n constructor(\n graphics: C,\n readonly options: RendererOptions & O,\n ) {\n this.graphics = graphics;\n this.graphics.textRendering = \"optimizeLegibility\";\n const self = this;\n this.#ctx = {\n graphics: this.graphics,\n get remainingWidth() {\n return this.graphics.canvas.clientWidth;\n },\n set remainingWidth(value: number) {\n Object.defineProperty(this, \"remainingWidth\", { value, writable: true });\n },\n alignment: \"left\",\n reverse: false,\n measureNode(node: Node<C>) {\n return self.measureNode(node, this);\n },\n invalidateNode: this.invalidateNode.bind(this),\n resolveDynValue<T>(value: DynValue<C, T>): T {\n if (typeof value === \"function\") {\n return value(this.graphics);\n }\n return value as T;\n },\n with<T>(cb: (g: C) => T): T {\n this.graphics.save();\n try {\n return cb(this.graphics);\n } finally {\n this.graphics.restore();\n }\n },\n };\n this.#lastWidth = this.graphics.canvas.clientWidth;\n }\n\n invalidateNode(node: Node<C>): void {\n this.#cache.delete(node);\n let it: Node<C> | undefined = node;\n while ((it = getNodeParent(it))) {\n this.#cache.delete(it);\n }\n }\n\n measureNode(node: Node<C>, ctx?: Context<C>): Box {\n if (this.#lastWidth !== this.graphics.canvas.clientWidth) {\n this.#cache = new WeakMap<Node<C>, Box>();\n this.#lastWidth = this.graphics.canvas.clientWidth;\n } else {\n const result = this.#cache.get(node);\n if (result != null) {\n return result;\n }\n }\n const result = node.measure(ctx ?? this.context);\n this.#cache.set(node, result);\n return result;\n }\n}\n\nexport class DebugRenderer<C extends CanvasRenderingContext2D> extends BaseRenderer<C> {\n draw(node: Node<C>): boolean {\n const { clientWidth: viewportWidth, clientHeight: viewportHeight } = this.graphics.canvas;\n this.graphics.clearRect(0, 0, viewportWidth, viewportHeight);\n return node.draw(this.context, 0, 0);\n }\n\n hittest(node: Node<C>, test: HitTest): boolean {\n return node.hittest(this.context, test);\n }\n}\n\nexport function memoRenderItem<C extends CanvasRenderingContext2D, T extends {}>(\n renderItem: (item: T) => Node<C>,\n): ((item: T) => Node<C>) & { reset: (key: T) => boolean } {\n const cache = new WeakMap<object, Node<C>>();\n\n function fn(item: T): Node<C> {\n const key = item as unknown as object;\n const cached = cache.get(key);\n if (cached != null) {\n return cached;\n }\n const result = renderItem(item);\n cache.set(key, result);\n return result;\n }\n\n return Object.assign(fn, {\n reset: (key: T) => cache.delete(key as unknown as object),\n });\n}\n\nexport class ListState<T extends {}> {\n offset = 0;\n position = Number.NaN;\n items: T[] = [];\n\n unshift(...items: T[]): void {\n this.unshiftAll(items);\n }\n\n unshiftAll(items: T[]): void {\n this.position += items.length;\n this.items = items.concat(this.items);\n }\n\n push(...items: T[]): void {\n this.pushAll(items);\n }\n\n pushAll(items: T[]): void {\n this.items.push(...items);\n }\n\n reset(): void {\n this.items = [];\n this.offset = 0;\n this.position = Number.NaN;\n }\n\n resetScroll(): void {\n this.offset = 0;\n this.position = Number.NaN;\n }\n\n applyScroll(delta: number): void {\n this.offset += delta;\n }\n}\n\ntype DrawItem<C extends CanvasRenderingContext2D> = {\n idx: number;\n node: Node<C>;\n offset: number;\n height: number;\n};\n\nfunction clamp(value: number, min: number, max: number): number {\n return Math.min(Math.max(value, min), max);\n}\n\nexport abstract class VirtualizedRenderer<C extends CanvasRenderingContext2D, T extends {}> extends BaseRenderer<\n C,\n {\n renderItem: (item: T) => Node<C>;\n list: ListState<T>;\n }\n> {\n get position(): number {\n return this.options.list.position;\n }\n\n set position(value: number) {\n this.options.list.position = value;\n }\n\n get offset(): number {\n return this.options.list.offset;\n }\n\n set offset(value: number) {\n this.options.list.offset = value;\n }\n\n get items(): T[] {\n return this.options.list.items;\n }\n\n set items(value: T[]) {\n this.options.list.items = value;\n }\n\n abstract render(feedback?: RenderFeedback): boolean;\n abstract hittest(test: HitTest): boolean;\n\n protected _resetRenderFeedback(feedback?: RenderFeedback): void {\n if (feedback == null) {\n return;\n }\n feedback.minIdx = Number.NaN;\n feedback.maxIdx = Number.NaN;\n feedback.min = Number.NaN;\n feedback.max = Number.NaN;\n }\n\n protected _accumulateRenderFeedback(feedback: RenderFeedback, idx: number, top: number, height: number): void {\n if (!Number.isFinite(top) || !Number.isFinite(height) || height <= 0) {\n return;\n }\n\n const viewportHeight = this.graphics.canvas.clientHeight;\n const visibleTop = clamp(-top, 0, height);\n const visibleBottom = clamp(viewportHeight - top, 0, height);\n if (visibleBottom <= visibleTop) {\n return;\n }\n\n const itemMin = idx + visibleTop / height;\n const itemMax = idx + visibleBottom / height;\n feedback.minIdx = Number.isNaN(feedback.minIdx) ? idx : Math.min(idx, feedback.minIdx);\n feedback.maxIdx = Number.isNaN(feedback.maxIdx) ? idx : Math.max(idx, feedback.maxIdx);\n feedback.min = Number.isNaN(feedback.min) ? itemMin : Math.min(itemMin, feedback.min);\n feedback.max = Number.isNaN(feedback.max) ? itemMax : Math.max(itemMax, feedback.max);\n }\n\n protected _renderDrawList(list: DrawItem<C>[], shift: number, feedback?: RenderFeedback): boolean {\n let result = false;\n const viewportHeight = this.graphics.canvas.clientHeight;\n\n for (const { idx, node, offset, height } of list) {\n const y = offset + shift;\n if (feedback != null) {\n this._accumulateRenderFeedback(feedback, idx, y, height);\n }\n if (y + height < 0 || y > viewportHeight) {\n continue;\n }\n if (node.draw(this.context, 0, y)) {\n result = true;\n }\n }\n\n return result;\n }\n}\n\nexport class TimelineRenderer<C extends CanvasRenderingContext2D, T extends {}> extends VirtualizedRenderer<C, T> {\n render(feedback?: RenderFeedback): boolean {\n const { clientWidth: viewportWidth, clientHeight: viewportHeight } = this.graphics.canvas;\n this.graphics.clearRect(0, 0, viewportWidth, viewportHeight);\n this._resetRenderFeedback(feedback);\n\n let drawLength = 0;\n if (Number.isNaN(this.position)) {\n this.position = 0;\n }\n\n if (this.offset > 0) {\n if (this.position === 0) {\n this.offset = 0;\n } else {\n for (let i = this.position - 1; i >= 0; i -= 1) {\n const item = this.items[i];\n const node = this.options.renderItem(item);\n const { height } = this.measureNode(node);\n this.position = i;\n this.offset -= height;\n if (this.offset <= 0) {\n break;\n }\n }\n if (this.position === 0 && this.offset > 0) {\n this.offset = 0;\n }\n }\n }\n\n let y = this.offset;\n const drawList: DrawItem<C>[] = [];\n for (let i = this.position; i < this.items.length; i += 1) {\n const item = this.items[i];\n const node = this.options.renderItem(item);\n const { height } = this.measureNode(node);\n if (y + height > 0) {\n drawList.push({ idx: i, node, offset: y, height });\n drawLength += height;\n } else {\n this.offset += height;\n this.position = i + 1;\n }\n y += height;\n if (y >= viewportHeight) {\n break;\n }\n }\n\n let shift = 0;\n if (y < viewportHeight) {\n if (this.position === 0 && drawLength < viewportHeight) {\n shift = -this.offset;\n this.offset = 0;\n } else {\n shift = viewportHeight - y;\n y = (this.offset += shift);\n let lastIdx = -1;\n for (let i = this.position - 1; i >= 0; i -= 1) {\n const item = this.items[(lastIdx = i)];\n const node = this.options.renderItem(item);\n const { height } = this.measureNode(node);\n drawLength += height;\n y -= height;\n drawList.push({ idx: i, node, offset: y - shift, height });\n if (y < 0) {\n break;\n }\n }\n if (lastIdx === 0 && drawLength < viewportHeight) {\n shift = -drawList[drawList.length - 1].offset;\n this.position = 0;\n this.offset = 0;\n }\n }\n }\n\n return this._renderDrawList(drawList, shift, feedback);\n }\n\n hittest(test: HitTest): boolean {\n const viewportHeight = this.graphics.canvas.clientHeight;\n let y = this.offset;\n\n for (let i = this.position; i < this.items.length; i += 1) {\n const item = this.items[i];\n const node = this.options.renderItem(item);\n const { height } = this.measureNode(node);\n if (test.y < y + height) {\n return node.hittest(\n this.context,\n shallowMerge(test, {\n y: test.y - y,\n }),\n );\n }\n y += height;\n if (y >= viewportHeight) {\n break;\n }\n }\n return false;\n }\n}\n\nexport class ChatRenderer<C extends CanvasRenderingContext2D, T extends {}> extends VirtualizedRenderer<C, T> {\n render(feedback?: RenderFeedback): boolean {\n const { clientWidth: viewportWidth, clientHeight: viewportHeight } = this.graphics.canvas;\n this.graphics.clearRect(0, 0, viewportWidth, viewportHeight);\n this._resetRenderFeedback(feedback);\n\n let drawLength = 0;\n if (Number.isNaN(this.position)) {\n this.position = this.items.length - 1;\n }\n\n if (this.offset < 0) {\n if (this.position === this.items.length - 1) {\n this.offset = 0;\n } else {\n for (let i = this.position + 1; i < this.items.length; i += 1) {\n const item = this.items[i];\n const node = this.options.renderItem(item);\n const { height } = this.measureNode(node);\n this.position = i;\n this.offset += height;\n if (this.offset > 0) {\n break;\n }\n }\n }\n }\n\n let y = viewportHeight + this.offset;\n const drawList: DrawItem<C>[] = [];\n for (let i = this.position; i >= 0; i -= 1) {\n const item = this.items[i];\n const node = this.options.renderItem(item);\n const { height } = this.measureNode(node);\n y -= height;\n if (y <= viewportHeight) {\n drawList.push({ idx: i, node, offset: y, height });\n drawLength += height;\n } else {\n this.offset -= height;\n this.position = i - 1;\n }\n if (y < 0) {\n break;\n }\n }\n\n let shift = 0;\n if (y > 0) {\n shift = -y;\n if (drawLength < viewportHeight) {\n y = drawLength;\n for (let i = this.position + 1; i < this.items.length; i += 1) {\n const item = this.items[i];\n const node = this.options.renderItem(item);\n const { height } = this.measureNode(node);\n drawList.push({ idx: i, node, offset: y - shift, height });\n y = (drawLength += height);\n this.position = i;\n if (y >= viewportHeight) {\n break;\n }\n }\n if (drawLength < viewportHeight) {\n this.offset = 0;\n } else {\n this.offset = drawLength - viewportHeight;\n }\n } else {\n this.offset = drawLength - viewportHeight;\n }\n }\n\n return this._renderDrawList(drawList, shift, feedback);\n }\n\n hittest(test: HitTest): boolean {\n const viewportHeight = this.graphics.canvas.clientHeight;\n\n let drawLength = 0;\n const heights: Array<readonly [Node<C>, number]> = [];\n for (let i = this.position; i >= 0; i -= 1) {\n const item = this.items[i];\n const node = this.options.renderItem(item);\n const { height } = this.measureNode(node);\n drawLength += height;\n heights.push([node, height]);\n }\n\n let y = drawLength < viewportHeight ? drawLength : viewportHeight + this.offset;\n if (test.y > y) {\n return false;\n }\n\n for (const [node, height] of heights) {\n y -= height;\n if (test.y > y) {\n return node.hittest(\n this.context,\n shallowMerge(test, {\n y: test.y - y,\n }),\n );\n }\n }\n return false;\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["#inner","#top","#bottom","#left","#right","#shift","#width","#lines","#text","#ctx","#lastWidth","#cache","#cancelJumpAnimation","#jumpAnimation","#controlledState"],"sources":["../src/text.ts","../src/utils.ts","../src/registry.ts","../src/nodes.ts","../src/renderer.ts"],"sourcesContent":["import { layoutWithLines, prepareWithSegments } from \"@chenglou/pretext\";\nimport type { Context } from \"./types\";\n\nexport interface TextLayout {\n width: number;\n text: string;\n shift: number;\n}\n\nfunction preprocessSegments(text: string): string[] {\n return text\n .split(\"\\n\")\n .map((line) => line.trim())\n .filter(Boolean);\n}\n\nexport function layoutFirstLine<C extends CanvasRenderingContext2D>(\n ctx: Context<C>,\n text: string,\n maxWidth: number,\n): TextLayout {\n if (maxWidth < 0) {\n maxWidth = 0;\n }\n const segments = preprocessSegments(text);\n const segment = segments[0];\n if (!segment) {\n return { width: 0, text: \"\", shift: 0 };\n }\n const {\n fontBoundingBoxAscent: ascent = 0,\n fontBoundingBoxDescent: descent = 0,\n } = ctx.graphics.measureText(segment);\n const shift = ascent - descent;\n if (maxWidth === 0) {\n return { width: 0, text: \"\", shift };\n }\n const prepared = prepareWithSegments(segment, ctx.graphics.font);\n const { lines } = layoutWithLines(prepared, maxWidth, 0);\n if (lines.length === 0) {\n return { width: 0, text: \"\", shift };\n }\n return { width: lines[0].width, text: lines[0].text, shift };\n}\n\nexport function layoutText<C extends CanvasRenderingContext2D>(\n ctx: Context<C>,\n text: string,\n maxWidth: number,\n): { width: number; lines: TextLayout[] } {\n if (maxWidth < 0) {\n maxWidth = 0;\n }\n\n const segments = preprocessSegments(text);\n if (segments.length === 0 || maxWidth === 0) {\n return { width: 0, lines: [] };\n }\n\n const font = ctx.graphics.font;\n let width = 0;\n const lines: TextLayout[] = [];\n\n for (const segment of segments) {\n const {\n fontBoundingBoxAscent: ascent = 0,\n fontBoundingBoxDescent: descent = 0,\n } = ctx.graphics.measureText(segment);\n const shift = ascent - descent;\n const prepared = prepareWithSegments(segment, font);\n const { lines: segLines } = layoutWithLines(prepared, maxWidth, 0);\n for (const segLine of segLines) {\n width = Math.max(width, segLine.width);\n lines.push({ width: segLine.width, text: segLine.text, shift });\n }\n }\n\n return { width, lines };\n}\n","export function shallow<T extends object>(object: T): T {\n return Object.create(object) as T;\n}\n\nexport function shallowMerge<T extends object, R extends object>(object: T, other: R): T & R {\n return { __proto__: object, ...other } as unknown as T & R;\n}\n","import type { Node } from \"./types\";\n\nconst registry = new WeakMap<Node<any>, Node<any>>();\n\nexport function registerNodeParent<C extends CanvasRenderingContext2D>(\n node: Node<C>,\n parent: Node<C>,\n): void {\n registry.set(node, parent);\n}\n\nexport function unregisterNodeParent<C extends CanvasRenderingContext2D>(node: Node<C>): void {\n registry.delete(node);\n}\n\nexport function getNodeParent<C extends CanvasRenderingContext2D>(node: Node<C>): Node<C> | undefined {\n return registry.get(node);\n}\n","import type { Alignment, Box, Context, DynValue, HitTest, Node } from \"./types\";\nimport { layoutFirstLine, layoutText, type TextLayout } from \"./text\";\nimport { shallow, shallowMerge } from \"./utils\";\nimport { registerNodeParent, unregisterNodeParent } from \"./registry\";\n\nexport abstract class Group<C extends CanvasRenderingContext2D> implements Node<C> {\n constructor(readonly children: Node<C>[]) {\n for (const child of children) {\n registerNodeParent(child, this);\n }\n }\n\n abstract measure(ctx: Context<C>): Box;\n abstract draw(ctx: Context<C>, x: number, y: number): boolean;\n abstract hittest(ctx: Context<C>, test: HitTest): boolean;\n\n get flex(): boolean {\n return this.children.some((item) => item.flex);\n }\n}\n\nexport class VStack<C extends CanvasRenderingContext2D> extends Group<C> {\n constructor(\n children: Node<C>[],\n readonly options: { gap?: number; alignment?: \"left\" | \"center\" | \"right\" } = {},\n ) {\n super(children);\n }\n\n measure(ctx: Context<C>): Box {\n let width = 0;\n let height = 0;\n if (this.options.alignment != null) {\n ctx.alignment = this.options.alignment;\n }\n\n for (const [index, child] of this.children.entries()) {\n if (this.options.gap != null && index !== 0) {\n height += this.options.gap;\n }\n const result = shallow(ctx).measureNode(child);\n height += result.height;\n width = Math.max(width, result.width);\n }\n ctx.remainingWidth -= width;\n return { width, height };\n }\n\n draw(ctx: Context<C>, x: number, y: number): boolean {\n let result = false;\n const fullWidth = ctx.measureNode(this).width;\n const alignment = this.options.alignment ?? ctx.alignment;\n if (this.options.alignment != null) {\n ctx.alignment = this.options.alignment;\n }\n\n for (const [index, child] of this.children.entries()) {\n if (this.options.gap != null && index !== 0) {\n y += this.options.gap;\n }\n const { width, height } = shallow(ctx).measureNode(child);\n const curCtx = shallow(ctx);\n let requestRedraw: boolean;\n if (alignment === \"right\") {\n requestRedraw = child.draw(curCtx, x + fullWidth - width, y);\n } else if (alignment === \"center\") {\n requestRedraw = child.draw(curCtx, x + (fullWidth - width) / 2, y);\n } else {\n requestRedraw = child.draw(curCtx, x, y);\n }\n result ||= requestRedraw;\n y += height;\n }\n return result;\n }\n\n hittest(ctx: Context<C>, test: HitTest): boolean {\n let y = 0;\n const fullWidth = ctx.measureNode(this).width;\n const alignment = this.options.alignment ?? ctx.alignment;\n if (this.options.alignment != null) {\n ctx.alignment = this.options.alignment;\n }\n\n for (const [index, child] of this.children.entries()) {\n if (this.options.gap != null && index !== 0) {\n y += this.options.gap;\n }\n\n const { width, height } = shallow(ctx).measureNode(child);\n const curCtx = shallow(ctx);\n if (test.y >= y && test.y < y + height) {\n let x: number;\n if (alignment === \"right\") {\n x = test.x - fullWidth + width;\n } else if (alignment === \"center\") {\n x = test.x - (fullWidth - width) / 2;\n } else {\n x = test.x;\n }\n if (x < 0 || x >= width) {\n return false;\n }\n return child.hittest(\n curCtx,\n shallowMerge(test, {\n x,\n y: test.y - y,\n }),\n );\n }\n y += height;\n }\n return false;\n }\n}\n\nexport class HStack<C extends CanvasRenderingContext2D> extends Group<C> {\n constructor(\n readonly children: Node<C>[],\n readonly options: { reverse?: boolean; gap?: number } = {},\n ) {\n super(children);\n }\n\n measure(ctx: Context<C>): Box {\n let width = 0;\n let height = 0;\n let firstFlex: Node<C> | undefined;\n\n for (const [index, child] of this.children.entries()) {\n if (this.options.gap != null && index !== 0) {\n width += this.options.gap;\n }\n if (firstFlex == null && child.flex) {\n firstFlex = child;\n continue;\n }\n const curCtx = shallow(ctx);\n curCtx.remainingWidth = ctx.remainingWidth - width;\n const result = curCtx.measureNode(child);\n width += result.width;\n height = Math.max(height, result.height);\n }\n\n if (firstFlex != null) {\n const curCtx = shallow(ctx);\n curCtx.remainingWidth = ctx.remainingWidth - width;\n const result = curCtx.measureNode(firstFlex);\n width += result.width;\n height = Math.max(height, result.height);\n }\n\n return { width, height };\n }\n\n draw(ctx: Context<C>, x: number, y: number): boolean {\n let result = false;\n const reverse = this.options.reverse ?? ctx.reverse;\n if (this.options.reverse) {\n ctx.reverse = this.options.reverse;\n }\n\n if (reverse) {\n x += ctx.measureNode(this).width;\n for (const [index, child] of this.children.entries()) {\n const gap = this.options.gap != null && index !== 0 ? this.options.gap : undefined;\n if (gap) {\n x -= gap;\n ctx.remainingWidth -= gap;\n }\n const { width } = shallow(ctx).measureNode(child);\n x -= width;\n const requestRedraw = child.draw(shallow(ctx), x, y);\n result ||= requestRedraw;\n ctx.remainingWidth -= width;\n }\n } else {\n for (const [index, child] of this.children.entries()) {\n const gap = this.options.gap != null && index !== 0 ? this.options.gap : undefined;\n if (gap) {\n x += gap;\n ctx.remainingWidth -= gap;\n }\n const requestRedraw = child.draw(shallow(ctx), x, y);\n result ||= requestRedraw;\n const { width } = shallow(ctx).measureNode(child);\n ctx.remainingWidth -= width;\n x += width;\n }\n }\n\n return result;\n }\n\n hittest(ctx: Context<C>, test: HitTest): boolean {\n const reverse = this.options.reverse ?? ctx.reverse;\n if (this.options.reverse) {\n ctx.reverse = this.options.reverse;\n }\n\n if (reverse) {\n let x = ctx.measureNode(this).width;\n for (const [index, child] of this.children.entries()) {\n const gap = this.options.gap != null && index !== 0 ? this.options.gap : undefined;\n if (gap) {\n x -= gap;\n ctx.remainingWidth -= gap;\n }\n const { width, height } = shallow(ctx).measureNode(child);\n x -= width;\n if (x <= test.x && test.x < x + width) {\n if (test.y >= height) {\n return false;\n }\n return child.hittest(\n shallow(ctx),\n shallowMerge(test, {\n x: test.x - x,\n }),\n );\n }\n ctx.remainingWidth -= width;\n }\n } else {\n let x = 0;\n for (const [index, child] of this.children.entries()) {\n const gap = this.options.gap != null && index !== 0 ? this.options.gap : undefined;\n if (gap) {\n x += gap;\n ctx.remainingWidth -= gap;\n }\n const { width, height } = shallow(ctx).measureNode(child);\n if (x <= test.x && test.x < x + width) {\n if (test.y >= height) {\n return false;\n }\n return child.hittest(\n shallow(ctx),\n shallowMerge(test, {\n x: test.x - x,\n }),\n );\n }\n x += width;\n ctx.remainingWidth -= width;\n }\n }\n\n return false;\n }\n}\n\nexport class Wrapper<C extends CanvasRenderingContext2D> implements Node<C> {\n #inner: Node<C>;\n\n constructor(inner: Node<C>) {\n this.#inner = inner;\n registerNodeParent(this.#inner, this);\n }\n\n get inner(): Node<C> {\n return this.#inner;\n }\n\n set inner(newNode: Node<C>) {\n if (newNode === this.#inner) {\n return;\n }\n unregisterNodeParent(this.#inner);\n this.#inner = newNode;\n registerNodeParent(newNode, this);\n }\n\n get flex(): boolean {\n return this.inner.flex;\n }\n\n measure(ctx: Context<C>): Box {\n return this.inner.measure(ctx);\n }\n\n draw(ctx: Context<C>, x: number, y: number): boolean {\n return this.inner.draw(ctx, x, y);\n }\n\n hittest(ctx: Context<C>, test: HitTest): boolean {\n return this.inner.hittest(ctx, test);\n }\n}\n\nexport class PaddingBox<C extends CanvasRenderingContext2D> extends Wrapper<C> {\n constructor(\n inner: Node<C>,\n readonly padding: {\n top?: number;\n bottom?: number;\n left?: number;\n right?: number;\n } = {},\n ) {\n super(inner);\n }\n\n get #top(): number {\n return this.padding.top ?? 0;\n }\n\n get #bottom(): number {\n return this.padding.bottom ?? 0;\n }\n\n get #left(): number {\n return this.padding.left ?? 0;\n }\n\n get #right(): number {\n return this.padding.right ?? 0;\n }\n\n measure(ctx: Context<C>): Box {\n ctx.remainingWidth -= this.#left + this.#right;\n const { width, height } = ctx.measureNode(this.inner);\n return {\n width: width + this.#left + this.#right,\n height: height + this.#top + this.#bottom,\n };\n }\n\n draw(ctx: Context<C>, x: number, y: number): boolean {\n ctx.remainingWidth -= this.#left + this.#right;\n return this.inner.draw(ctx, x + this.#left, y + this.#top);\n }\n\n hittest(ctx: Context<C>, test: HitTest): boolean {\n ctx.remainingWidth -= this.#left + this.#right;\n const { width, height } = shallow(ctx).measureNode(this.inner);\n if (0 <= test.x - this.#left && test.x - this.#left < width && 0 <= test.y - this.#top && test.y - this.#top < height) {\n return this.inner.hittest(\n shallow(ctx),\n shallowMerge(test, {\n x: test.x - this.#left,\n y: test.y - this.#top,\n }),\n );\n }\n return false;\n }\n}\n\nexport class AlignBox<C extends CanvasRenderingContext2D> extends Wrapper<C> {\n #shift = 0;\n\n constructor(\n inner: Node<C>,\n readonly options: {\n alignment: Alignment;\n },\n ) {\n super(inner);\n }\n\n measure(ctx: Context<C>): Box {\n ctx.alignment = this.options.alignment;\n const { width, height } = ctx.measureNode(this.inner);\n switch (this.options.alignment) {\n case \"center\":\n this.#shift = (ctx.remainingWidth - width) / 2;\n break;\n case \"right\":\n this.#shift = ctx.remainingWidth - width;\n break;\n default:\n this.#shift = 0;\n }\n return {\n width: ctx.remainingWidth,\n height,\n };\n }\n\n draw(ctx: Context<C>, x: number, y: number): boolean {\n ctx.alignment = this.options.alignment;\n return this.inner.draw(ctx, x + this.#shift, y);\n }\n\n hittest(ctx: Context<C>, test: HitTest): boolean {\n ctx.alignment = this.options.alignment;\n const { width } = shallow(ctx).measureNode(this.inner);\n if (0 <= test.x - this.#shift && test.x - this.#shift < width) {\n return this.inner.hittest(\n shallow(ctx),\n shallowMerge(test, {\n x: test.x - this.#shift,\n }),\n );\n }\n return false;\n }\n}\n\nexport class MultilineText<C extends CanvasRenderingContext2D> implements Node<C> {\n #width = 0;\n #lines: TextLayout[] = [];\n\n constructor(\n readonly text: string,\n readonly options: {\n lineHeight: number;\n font: string;\n alignment: \"left\" | \"center\" | \"right\";\n style: DynValue<C, string>;\n },\n ) {}\n\n get flex(): boolean {\n return true;\n }\n\n measure(ctx: Context<C>): Box {\n return ctx.with((g) => {\n g.font = this.options.font;\n const { width, lines } = layoutText(ctx, this.text, ctx.remainingWidth);\n this.#width = width;\n this.#lines = lines;\n return { width: this.#width, height: this.#lines.length * this.options.lineHeight };\n });\n }\n\n draw(ctx: Context<C>, x: number, y: number): boolean {\n return ctx.with((g) => {\n g.font = this.options.font;\n g.fillStyle = ctx.resolveDynValue(this.options.style);\n switch (this.options.alignment) {\n case \"left\":\n for (const { text, shift } of this.#lines) {\n g.fillText(text, x, y + (this.options.lineHeight + shift) / 2);\n y += this.options.lineHeight;\n }\n break;\n case \"right\":\n x += this.#width;\n g.textAlign = \"right\";\n for (const { text, shift } of this.#lines) {\n g.fillText(text, x, y + (this.options.lineHeight + shift) / 2);\n y += this.options.lineHeight;\n }\n break;\n case \"center\":\n x += this.#width / 2;\n g.textAlign = \"center\";\n for (const { text, shift } of this.#lines) {\n g.fillText(text, x, y + (this.options.lineHeight + shift) / 2);\n y += this.options.lineHeight;\n }\n break;\n }\n return false;\n });\n }\n\n hittest(_ctx: Context<C>, _test: HitTest): boolean {\n return false;\n }\n}\n\nexport class Text<C extends CanvasRenderingContext2D> implements Node<C> {\n #width = 0;\n #text = \"\";\n #shift = 0;\n\n constructor(\n readonly text: string,\n readonly options: {\n lineHeight: number;\n font: string;\n style: DynValue<C, string>;\n },\n ) {}\n\n get flex(): boolean {\n return false;\n }\n\n measure(ctx: Context<C>): Box {\n return ctx.with((g) => {\n g.font = this.options.font;\n const { width, text, shift } = layoutFirstLine(ctx, this.text, ctx.remainingWidth);\n this.#width = width;\n this.#text = text;\n this.#shift = shift;\n return { width: this.#width, height: this.options.lineHeight };\n });\n }\n\n draw(ctx: Context<C>, x: number, y: number): boolean {\n return ctx.with((g) => {\n g.font = this.options.font;\n g.fillStyle = ctx.resolveDynValue(this.options.style);\n g.fillText(this.#text, x, y + (this.options.lineHeight + this.#shift) / 2);\n return false;\n });\n }\n\n hittest(_ctx: Context<C>, _test: HitTest): boolean {\n return false;\n }\n}\n\nexport class Fixed<C extends CanvasRenderingContext2D> implements Node<C> {\n constructor(\n readonly width: number,\n readonly height: number,\n ) {}\n\n get flex(): boolean {\n return false;\n }\n\n measure(_ctx: Context<C>): Box {\n return { width: this.width, height: this.height };\n }\n\n draw(_ctx: Context<C>, _x: number, _y: number): boolean {\n return false;\n }\n\n hittest(_ctx: Context<C>, _test: HitTest): boolean {\n return false;\n }\n}\n","import type { Box, Context, DynValue, HitTest, Node, RenderFeedback, RendererOptions } from \"./types\";\nimport { shallow, shallowMerge } from \"./utils\";\nimport { getNodeParent } from \"./registry\";\n\nexport class BaseRenderer<C extends CanvasRenderingContext2D, O extends {} = {}> {\n graphics: C;\n #ctx: Context<C>;\n #lastWidth: number;\n #cache = new WeakMap<Node<C>, Box>();\n\n protected get context(): Context<C> {\n return shallow(this.#ctx);\n }\n\n constructor(\n graphics: C,\n readonly options: RendererOptions & O,\n ) {\n this.graphics = graphics;\n this.graphics.textRendering = \"optimizeLegibility\";\n const self = this;\n this.#ctx = {\n graphics: this.graphics,\n get remainingWidth() {\n return this.graphics.canvas.clientWidth;\n },\n set remainingWidth(value: number) {\n Object.defineProperty(this, \"remainingWidth\", { value, writable: true });\n },\n alignment: \"left\",\n reverse: false,\n measureNode(node: Node<C>) {\n return self.measureNode(node, this);\n },\n invalidateNode: this.invalidateNode.bind(this),\n resolveDynValue<T>(value: DynValue<C, T>): T {\n if (typeof value === \"function\") {\n return value(this.graphics);\n }\n return value as T;\n },\n with<T>(cb: (g: C) => T): T {\n this.graphics.save();\n try {\n return cb(this.graphics);\n } finally {\n this.graphics.restore();\n }\n },\n };\n this.#lastWidth = this.graphics.canvas.clientWidth;\n }\n\n invalidateNode(node: Node<C>): void {\n this.#cache.delete(node);\n let it: Node<C> | undefined = node;\n while ((it = getNodeParent(it))) {\n this.#cache.delete(it);\n }\n }\n\n measureNode(node: Node<C>, ctx?: Context<C>): Box {\n if (this.#lastWidth !== this.graphics.canvas.clientWidth) {\n this.#cache = new WeakMap<Node<C>, Box>();\n this.#lastWidth = this.graphics.canvas.clientWidth;\n } else {\n const result = this.#cache.get(node);\n if (result != null) {\n return result;\n }\n }\n const result = node.measure(ctx ?? this.context);\n this.#cache.set(node, result);\n return result;\n }\n}\n\nexport class DebugRenderer<C extends CanvasRenderingContext2D> extends BaseRenderer<C> {\n draw(node: Node<C>): boolean {\n const { clientWidth: viewportWidth, clientHeight: viewportHeight } = this.graphics.canvas;\n this.graphics.clearRect(0, 0, viewportWidth, viewportHeight);\n return node.draw(this.context, 0, 0);\n }\n\n hittest(node: Node<C>, test: HitTest): boolean {\n return node.hittest(this.context, test);\n }\n}\n\nexport function memoRenderItem<C extends CanvasRenderingContext2D, T extends {}>(\n renderItem: (item: T) => Node<C>,\n): ((item: T) => Node<C>) & { reset: (key: T) => boolean } {\n const cache = new WeakMap<object, Node<C>>();\n\n function fn(item: T): Node<C> {\n const key = item as unknown as object;\n const cached = cache.get(key);\n if (cached != null) {\n return cached;\n }\n const result = renderItem(item);\n cache.set(key, result);\n return result;\n }\n\n return Object.assign(fn, {\n reset: (key: T) => cache.delete(key as unknown as object),\n });\n}\n\nexport class ListState<T extends {}> {\n offset = 0;\n position = Number.NaN;\n items: T[] = [];\n\n unshift(...items: T[]): void {\n this.unshiftAll(items);\n }\n\n unshiftAll(items: T[]): void {\n this.position += items.length;\n this.items = items.concat(this.items);\n }\n\n push(...items: T[]): void {\n this.pushAll(items);\n }\n\n pushAll(items: T[]): void {\n this.items.push(...items);\n }\n\n reset(): void {\n this.items = [];\n this.offset = 0;\n this.position = Number.NaN;\n }\n\n resetScroll(): void {\n this.offset = 0;\n this.position = Number.NaN;\n }\n\n applyScroll(delta: number): void {\n this.offset += delta;\n }\n}\n\ntype DrawItem<C extends CanvasRenderingContext2D> = {\n idx: number;\n node: Node<C>;\n offset: number;\n height: number;\n};\n\nexport interface JumpToOptions {\n animated?: boolean;\n duration?: number;\n onComplete?: () => void;\n}\n\ntype ControlledState = {\n position: number;\n offset: number;\n};\n\ntype JumpAnimation = {\n startAnchor: number;\n targetAnchor: number;\n startTime: number;\n duration: number;\n needsMoreFrames: boolean;\n onComplete: (() => void) | undefined;\n};\n\nfunction clamp(value: number, min: number, max: number): number {\n return Math.min(Math.max(value, min), max);\n}\n\nfunction sameState(state: ControlledState, position: number, offset: number): boolean {\n return Object.is(state.position, position) && Object.is(state.offset, offset);\n}\n\nfunction smoothstep(value: number): number {\n return value * value * (3 - 2 * value);\n}\n\nfunction getNow(): number {\n return globalThis.performance?.now() ?? Date.now();\n}\n\nexport abstract class VirtualizedRenderer<C extends CanvasRenderingContext2D, T extends {}> extends BaseRenderer<\n C,\n {\n renderItem: (item: T) => Node<C>;\n list: ListState<T>;\n }\n> {\n static readonly MIN_JUMP_DURATION = 160;\n static readonly MAX_JUMP_DURATION = 420;\n static readonly JUMP_DURATION_PER_ITEM = 28;\n\n #controlledState: ControlledState | undefined;\n #jumpAnimation: JumpAnimation | undefined;\n\n get position(): number {\n return this.options.list.position;\n }\n\n set position(value: number) {\n this.options.list.position = value;\n }\n\n get offset(): number {\n return this.options.list.offset;\n }\n\n set offset(value: number) {\n this.options.list.offset = value;\n }\n\n get items(): T[] {\n return this.options.list.items;\n }\n\n set items(value: T[]) {\n this.options.list.items = value;\n }\n\n abstract render(feedback?: RenderFeedback): boolean;\n abstract hittest(test: HitTest): boolean;\n\n jumpTo(index: number, options: JumpToOptions = {}): void {\n if (this.items.length === 0) {\n this.#cancelJumpAnimation();\n return;\n }\n\n const targetIndex = this._clampItemIndex(index);\n this._prepareAnchorState();\n const targetAnchor = this._getTargetAnchor(targetIndex);\n\n const animated = options.animated ?? true;\n if (!animated) {\n this.#cancelJumpAnimation();\n this._applyAnchor(targetAnchor);\n options.onComplete?.();\n return;\n }\n\n const startAnchor = this._readAnchor();\n if (!Number.isFinite(startAnchor)) {\n this.#cancelJumpAnimation();\n this._applyAnchor(targetAnchor);\n options.onComplete?.();\n return;\n }\n\n const duration = clamp(\n options.duration ??\n VirtualizedRenderer.MIN_JUMP_DURATION +\n Math.abs(targetAnchor - startAnchor) * VirtualizedRenderer.JUMP_DURATION_PER_ITEM,\n 0,\n VirtualizedRenderer.MAX_JUMP_DURATION,\n );\n\n if (duration <= 0 || Math.abs(targetAnchor - startAnchor) <= Number.EPSILON) {\n this.#cancelJumpAnimation();\n this._applyAnchor(targetAnchor);\n options.onComplete?.();\n return;\n }\n\n this.#jumpAnimation = {\n startAnchor,\n targetAnchor,\n startTime: getNow(),\n duration,\n needsMoreFrames: true,\n onComplete: options.onComplete,\n };\n this.#controlledState = {\n position: this.position,\n offset: this.offset,\n };\n }\n\n protected _resetRenderFeedback(feedback?: RenderFeedback): void {\n if (feedback == null) {\n return;\n }\n feedback.minIdx = Number.NaN;\n feedback.maxIdx = Number.NaN;\n feedback.min = Number.NaN;\n feedback.max = Number.NaN;\n }\n\n protected _accumulateRenderFeedback(feedback: RenderFeedback, idx: number, top: number, height: number): void {\n if (!Number.isFinite(top) || !Number.isFinite(height) || height <= 0) {\n return;\n }\n\n const viewportHeight = this.graphics.canvas.clientHeight;\n const visibleTop = clamp(-top, 0, height);\n const visibleBottom = clamp(viewportHeight - top, 0, height);\n if (visibleBottom <= visibleTop) {\n return;\n }\n\n const itemMin = idx + visibleTop / height;\n const itemMax = idx + visibleBottom / height;\n feedback.minIdx = Number.isNaN(feedback.minIdx) ? idx : Math.min(idx, feedback.minIdx);\n feedback.maxIdx = Number.isNaN(feedback.maxIdx) ? idx : Math.max(idx, feedback.maxIdx);\n feedback.min = Number.isNaN(feedback.min) ? itemMin : Math.min(itemMin, feedback.min);\n feedback.max = Number.isNaN(feedback.max) ? itemMax : Math.max(itemMax, feedback.max);\n }\n\n protected _renderDrawList(list: DrawItem<C>[], shift: number, feedback?: RenderFeedback): boolean {\n let result = false;\n const viewportHeight = this.graphics.canvas.clientHeight;\n\n for (const { idx, node, offset, height } of list) {\n const y = offset + shift;\n if (feedback != null) {\n this._accumulateRenderFeedback(feedback, idx, y, height);\n }\n if (y + height < 0 || y > viewportHeight) {\n continue;\n }\n if (node.draw(this.context, 0, y)) {\n result = true;\n }\n }\n\n return result;\n }\n\n protected _prepareRender(): boolean {\n const animation = this.#jumpAnimation;\n if (animation == null) {\n return false;\n }\n if (this.items.length === 0) {\n this.#cancelJumpAnimation();\n return false;\n }\n if (this.#controlledState != null && !sameState(this.#controlledState, this.position, this.offset)) {\n this.#cancelJumpAnimation();\n return false;\n }\n\n const progress = clamp((getNow() - animation.startTime) / animation.duration, 0, 1);\n const eased = progress >= 1 ? 1 : smoothstep(progress);\n const anchor = animation.startAnchor + (animation.targetAnchor - animation.startAnchor) * eased;\n this._applyAnchor(anchor);\n animation.needsMoreFrames = progress < 1;\n return animation.needsMoreFrames;\n }\n\n protected _finishRender(requestRedraw: boolean): boolean {\n const animation = this.#jumpAnimation;\n if (animation == null) {\n return requestRedraw;\n }\n\n if (animation.needsMoreFrames) {\n this.#controlledState = {\n position: this.position,\n offset: this.offset,\n };\n return true;\n }\n\n const onComplete = animation.onComplete;\n this.#cancelJumpAnimation();\n onComplete?.();\n return requestRedraw || this.#jumpAnimation != null;\n }\n\n protected _clampItemIndex(index: number): number {\n return clamp(Number.isFinite(index) ? Math.trunc(index) : 0, 0, this.items.length - 1);\n }\n\n protected _getItemHeight(index: number): number {\n const item = this.items[index];\n const node = this.options.renderItem(item);\n return this.measureNode(node).height;\n }\n\n protected abstract _prepareAnchorState(): void;\n protected abstract _readAnchor(): number;\n protected abstract _applyAnchor(anchor: number): void;\n protected abstract _getTargetAnchor(index: number): number;\n\n #cancelJumpAnimation(): void {\n this.#jumpAnimation = undefined;\n this.#controlledState = undefined;\n }\n}\n\nexport class TimelineRenderer<C extends CanvasRenderingContext2D, T extends {}> extends VirtualizedRenderer<C, T> {\n protected _prepareAnchorState(): void {\n if (this.items.length === 0) {\n return;\n }\n if (!Number.isFinite(this.position)) {\n this.position = 0;\n this.offset = 0;\n return;\n }\n this.position = this._clampItemIndex(this.position);\n if (!Number.isFinite(this.offset)) {\n this.offset = 0;\n }\n }\n\n protected _readAnchor(): number {\n this._prepareAnchorState();\n if (this.items.length === 0) {\n return 0;\n }\n const height = this._getItemHeight(this.position);\n return height > 0 ? this.position - this.offset / height : this.position;\n }\n\n protected _applyAnchor(anchor: number): void {\n if (this.items.length === 0) {\n return;\n }\n const clampedAnchor = clamp(anchor, 0, this.items.length);\n const position = clamp(Math.floor(clampedAnchor), 0, this.items.length - 1);\n const height = this._getItemHeight(position);\n this.position = position;\n const offset = height > 0 ? -(clampedAnchor - position) * height : 0;\n this.offset = Object.is(offset, -0) ? 0 : offset;\n }\n\n protected _getTargetAnchor(index: number): number {\n return index;\n }\n\n render(feedback?: RenderFeedback): boolean {\n const keepAnimating = this._prepareRender();\n const { clientWidth: viewportWidth, clientHeight: viewportHeight } = this.graphics.canvas;\n this.graphics.clearRect(0, 0, viewportWidth, viewportHeight);\n this._resetRenderFeedback(feedback);\n\n let drawLength = 0;\n if (Number.isNaN(this.position)) {\n this.position = 0;\n }\n\n if (this.offset > 0) {\n if (this.position === 0) {\n this.offset = 0;\n } else {\n for (let i = this.position - 1; i >= 0; i -= 1) {\n const item = this.items[i];\n const node = this.options.renderItem(item);\n const { height } = this.measureNode(node);\n this.position = i;\n this.offset -= height;\n if (this.offset <= 0) {\n break;\n }\n }\n if (this.position === 0 && this.offset > 0) {\n this.offset = 0;\n }\n }\n }\n\n let y = this.offset;\n const drawList: DrawItem<C>[] = [];\n for (let i = this.position; i < this.items.length; i += 1) {\n const item = this.items[i];\n const node = this.options.renderItem(item);\n const { height } = this.measureNode(node);\n if (y + height > 0) {\n drawList.push({ idx: i, node, offset: y, height });\n drawLength += height;\n } else {\n this.offset += height;\n this.position = i + 1;\n }\n y += height;\n if (y >= viewportHeight) {\n break;\n }\n }\n\n let shift = 0;\n if (y < viewportHeight) {\n if (this.position === 0 && drawLength < viewportHeight) {\n shift = -this.offset;\n this.offset = 0;\n } else {\n shift = viewportHeight - y;\n y = (this.offset += shift);\n let lastIdx = -1;\n for (let i = this.position - 1; i >= 0; i -= 1) {\n const item = this.items[(lastIdx = i)];\n const node = this.options.renderItem(item);\n const { height } = this.measureNode(node);\n drawLength += height;\n y -= height;\n drawList.push({ idx: i, node, offset: y - shift, height });\n if (y < 0) {\n break;\n }\n }\n if (lastIdx === 0 && drawLength < viewportHeight) {\n shift = -drawList[drawList.length - 1].offset;\n this.position = 0;\n this.offset = 0;\n }\n }\n }\n\n const requestRedraw = this._renderDrawList(drawList, shift, feedback);\n return this._finishRender(keepAnimating || requestRedraw);\n }\n\n hittest(test: HitTest): boolean {\n const viewportHeight = this.graphics.canvas.clientHeight;\n let y = this.offset;\n\n for (let i = this.position; i < this.items.length; i += 1) {\n const item = this.items[i];\n const node = this.options.renderItem(item);\n const { height } = this.measureNode(node);\n if (test.y < y + height) {\n return node.hittest(\n this.context,\n shallowMerge(test, {\n y: test.y - y,\n }),\n );\n }\n y += height;\n if (y >= viewportHeight) {\n break;\n }\n }\n return false;\n }\n}\n\nexport class ChatRenderer<C extends CanvasRenderingContext2D, T extends {}> extends VirtualizedRenderer<C, T> {\n protected _prepareAnchorState(): void {\n if (this.items.length === 0) {\n return;\n }\n if (!Number.isFinite(this.position)) {\n this.position = this.items.length - 1;\n this.offset = 0;\n return;\n }\n this.position = this._clampItemIndex(this.position);\n if (!Number.isFinite(this.offset)) {\n this.offset = 0;\n }\n }\n\n protected _readAnchor(): number {\n this._prepareAnchorState();\n if (this.items.length === 0) {\n return 0;\n }\n const height = this._getItemHeight(this.position);\n return height > 0 ? this.position + 1 - this.offset / height : this.position + 1;\n }\n\n protected _applyAnchor(anchor: number): void {\n if (this.items.length === 0) {\n return;\n }\n const clampedAnchor = clamp(anchor, 0, this.items.length);\n const position = clamp(Math.ceil(clampedAnchor) - 1, 0, this.items.length - 1);\n const height = this._getItemHeight(position);\n this.position = position;\n const offset = height > 0 ? (position + 1 - clampedAnchor) * height : 0;\n this.offset = Object.is(offset, -0) ? 0 : offset;\n }\n\n protected _getTargetAnchor(index: number): number {\n return index + 1;\n }\n\n render(feedback?: RenderFeedback): boolean {\n const keepAnimating = this._prepareRender();\n const { clientWidth: viewportWidth, clientHeight: viewportHeight } = this.graphics.canvas;\n this.graphics.clearRect(0, 0, viewportWidth, viewportHeight);\n this._resetRenderFeedback(feedback);\n\n let drawLength = 0;\n if (Number.isNaN(this.position)) {\n this.position = this.items.length - 1;\n }\n\n if (this.offset < 0) {\n if (this.position === this.items.length - 1) {\n this.offset = 0;\n } else {\n for (let i = this.position + 1; i < this.items.length; i += 1) {\n const item = this.items[i];\n const node = this.options.renderItem(item);\n const { height } = this.measureNode(node);\n this.position = i;\n this.offset += height;\n if (this.offset > 0) {\n break;\n }\n }\n }\n }\n\n let y = viewportHeight + this.offset;\n const drawList: DrawItem<C>[] = [];\n for (let i = this.position; i >= 0; i -= 1) {\n const item = this.items[i];\n const node = this.options.renderItem(item);\n const { height } = this.measureNode(node);\n y -= height;\n if (y <= viewportHeight) {\n drawList.push({ idx: i, node, offset: y, height });\n drawLength += height;\n } else {\n this.offset -= height;\n this.position = i - 1;\n }\n if (y < 0) {\n break;\n }\n }\n\n let shift = 0;\n if (y > 0) {\n shift = -y;\n if (drawLength < viewportHeight) {\n y = drawLength;\n for (let i = this.position + 1; i < this.items.length; i += 1) {\n const item = this.items[i];\n const node = this.options.renderItem(item);\n const { height } = this.measureNode(node);\n drawList.push({ idx: i, node, offset: y - shift, height });\n y = (drawLength += height);\n this.position = i;\n if (y >= viewportHeight) {\n break;\n }\n }\n if (drawLength < viewportHeight) {\n this.offset = 0;\n } else {\n this.offset = drawLength - viewportHeight;\n }\n } else {\n this.offset = drawLength - viewportHeight;\n }\n }\n\n const requestRedraw = this._renderDrawList(drawList, shift, feedback);\n return this._finishRender(keepAnimating || requestRedraw);\n }\n\n hittest(test: HitTest): boolean {\n const viewportHeight = this.graphics.canvas.clientHeight;\n\n let drawLength = 0;\n const heights: Array<readonly [Node<C>, number]> = [];\n for (let i = this.position; i >= 0; i -= 1) {\n const item = this.items[i];\n const node = this.options.renderItem(item);\n const { height } = this.measureNode(node);\n drawLength += height;\n heights.push([node, height]);\n }\n\n let y = drawLength < viewportHeight ? drawLength : viewportHeight + this.offset;\n if (test.y > y) {\n return false;\n }\n\n for (const [node, height] of heights) {\n y -= height;\n if (test.y > y) {\n return node.hittest(\n this.context,\n shallowMerge(test, {\n y: test.y - y,\n }),\n );\n }\n }\n return false;\n }\n}\n"],"mappings":";;AASA,SAAS,mBAAmB,MAAwB;AAClD,QAAO,KACJ,MAAM,KAAK,CACX,KAAK,SAAS,KAAK,MAAM,CAAC,CAC1B,OAAO,QAAQ;;AAGpB,SAAgB,gBACd,KACA,MACA,UACY;AACZ,KAAI,WAAW,EACb,YAAW;CAGb,MAAM,UADW,mBAAmB,KAAK,CAChB;AACzB,KAAI,CAAC,QACH,QAAO;EAAE,OAAO;EAAG,MAAM;EAAI,OAAO;EAAG;CAEzC,MAAM,EACJ,uBAAuB,SAAS,GAChC,wBAAwB,UAAU,MAChC,IAAI,SAAS,YAAY,QAAQ;CACrC,MAAM,QAAQ,SAAS;AACvB,KAAI,aAAa,EACf,QAAO;EAAE,OAAO;EAAG,MAAM;EAAI;EAAO;CAGtC,MAAM,EAAE,UAAU,gBADD,oBAAoB,SAAS,IAAI,SAAS,KAAK,EACpB,UAAU,EAAE;AACxD,KAAI,MAAM,WAAW,EACnB,QAAO;EAAE,OAAO;EAAG,MAAM;EAAI;EAAO;AAEtC,QAAO;EAAE,OAAO,MAAM,GAAG;EAAO,MAAM,MAAM,GAAG;EAAM;EAAO;;AAG9D,SAAgB,WACd,KACA,MACA,UACwC;AACxC,KAAI,WAAW,EACb,YAAW;CAGb,MAAM,WAAW,mBAAmB,KAAK;AACzC,KAAI,SAAS,WAAW,KAAK,aAAa,EACxC,QAAO;EAAE,OAAO;EAAG,OAAO,EAAE;EAAE;CAGhC,MAAM,OAAO,IAAI,SAAS;CAC1B,IAAI,QAAQ;CACZ,MAAM,QAAsB,EAAE;AAE9B,MAAK,MAAM,WAAW,UAAU;EAC9B,MAAM,EACJ,uBAAuB,SAAS,GAChC,wBAAwB,UAAU,MAChC,IAAI,SAAS,YAAY,QAAQ;EACrC,MAAM,QAAQ,SAAS;EAEvB,MAAM,EAAE,OAAO,aAAa,gBADX,oBAAoB,SAAS,KAAK,EACG,UAAU,EAAE;AAClE,OAAK,MAAM,WAAW,UAAU;AAC9B,WAAQ,KAAK,IAAI,OAAO,QAAQ,MAAM;AACtC,SAAM,KAAK;IAAE,OAAO,QAAQ;IAAO,MAAM,QAAQ;IAAM;IAAO,CAAC;;;AAInE,QAAO;EAAE;EAAO;EAAO;;;;AC7EzB,SAAgB,QAA0B,QAAc;AACtD,QAAO,OAAO,OAAO,OAAO;;AAG9B,SAAgB,aAAiD,QAAW,OAAiB;AAC3F,QAAO;EAAE,WAAW;EAAQ,GAAG;EAAO;;;;ACHxC,MAAM,2BAAW,IAAI,SAA+B;AAEpD,SAAgB,mBACd,MACA,QACM;AACN,UAAS,IAAI,MAAM,OAAO;;AAG5B,SAAgB,qBAAyD,MAAqB;AAC5F,UAAS,OAAO,KAAK;;AAGvB,SAAgB,cAAkD,MAAoC;AACpG,QAAO,SAAS,IAAI,KAAK;;;;ACX3B,IAAsB,QAAtB,MAAmF;CACjF,YAAY,UAA8B;AAArB,OAAA,WAAA;AACnB,OAAK,MAAM,SAAS,SAClB,oBAAmB,OAAO,KAAK;;CAQnC,IAAI,OAAgB;AAClB,SAAO,KAAK,SAAS,MAAM,SAAS,KAAK,KAAK;;;AAIlD,IAAa,SAAb,cAAgE,MAAS;CACvE,YACE,UACA,UAA8E,EAAE,EAChF;AACA,QAAM,SAAS;AAFN,OAAA,UAAA;;CAKX,QAAQ,KAAsB;EAC5B,IAAI,QAAQ;EACZ,IAAI,SAAS;AACb,MAAI,KAAK,QAAQ,aAAa,KAC5B,KAAI,YAAY,KAAK,QAAQ;AAG/B,OAAK,MAAM,CAAC,OAAO,UAAU,KAAK,SAAS,SAAS,EAAE;AACpD,OAAI,KAAK,QAAQ,OAAO,QAAQ,UAAU,EACxC,WAAU,KAAK,QAAQ;GAEzB,MAAM,SAAS,QAAQ,IAAI,CAAC,YAAY,MAAM;AAC9C,aAAU,OAAO;AACjB,WAAQ,KAAK,IAAI,OAAO,OAAO,MAAM;;AAEvC,MAAI,kBAAkB;AACtB,SAAO;GAAE;GAAO;GAAQ;;CAG1B,KAAK,KAAiB,GAAW,GAAoB;EACnD,IAAI,SAAS;EACb,MAAM,YAAY,IAAI,YAAY,KAAK,CAAC;EACxC,MAAM,YAAY,KAAK,QAAQ,aAAa,IAAI;AAChD,MAAI,KAAK,QAAQ,aAAa,KAC5B,KAAI,YAAY,KAAK,QAAQ;AAG/B,OAAK,MAAM,CAAC,OAAO,UAAU,KAAK,SAAS,SAAS,EAAE;AACpD,OAAI,KAAK,QAAQ,OAAO,QAAQ,UAAU,EACxC,MAAK,KAAK,QAAQ;GAEpB,MAAM,EAAE,OAAO,WAAW,QAAQ,IAAI,CAAC,YAAY,MAAM;GACzD,MAAM,SAAS,QAAQ,IAAI;GAC3B,IAAI;AACJ,OAAI,cAAc,QAChB,iBAAgB,MAAM,KAAK,QAAQ,IAAI,YAAY,OAAO,EAAE;YACnD,cAAc,SACvB,iBAAgB,MAAM,KAAK,QAAQ,KAAK,YAAY,SAAS,GAAG,EAAE;OAElE,iBAAgB,MAAM,KAAK,QAAQ,GAAG,EAAE;AAE1C,cAAW;AACX,QAAK;;AAEP,SAAO;;CAGT,QAAQ,KAAiB,MAAwB;EAC/C,IAAI,IAAI;EACR,MAAM,YAAY,IAAI,YAAY,KAAK,CAAC;EACxC,MAAM,YAAY,KAAK,QAAQ,aAAa,IAAI;AAChD,MAAI,KAAK,QAAQ,aAAa,KAC5B,KAAI,YAAY,KAAK,QAAQ;AAG/B,OAAK,MAAM,CAAC,OAAO,UAAU,KAAK,SAAS,SAAS,EAAE;AACpD,OAAI,KAAK,QAAQ,OAAO,QAAQ,UAAU,EACxC,MAAK,KAAK,QAAQ;GAGpB,MAAM,EAAE,OAAO,WAAW,QAAQ,IAAI,CAAC,YAAY,MAAM;GACzD,MAAM,SAAS,QAAQ,IAAI;AAC3B,OAAI,KAAK,KAAK,KAAK,KAAK,IAAI,IAAI,QAAQ;IACtC,IAAI;AACJ,QAAI,cAAc,QAChB,KAAI,KAAK,IAAI,YAAY;aAChB,cAAc,SACvB,KAAI,KAAK,KAAK,YAAY,SAAS;QAEnC,KAAI,KAAK;AAEX,QAAI,IAAI,KAAK,KAAK,MAChB,QAAO;AAET,WAAO,MAAM,QACX,QACA,aAAa,MAAM;KACjB;KACA,GAAG,KAAK,IAAI;KACb,CAAC,CACH;;AAEH,QAAK;;AAEP,SAAO;;;AAIX,IAAa,SAAb,cAAgE,MAAS;CACvE,YACE,UACA,UAAwD,EAAE,EAC1D;AACA,QAAM,SAAS;AAHN,OAAA,WAAA;AACA,OAAA,UAAA;;CAKX,QAAQ,KAAsB;EAC5B,IAAI,QAAQ;EACZ,IAAI,SAAS;EACb,IAAI;AAEJ,OAAK,MAAM,CAAC,OAAO,UAAU,KAAK,SAAS,SAAS,EAAE;AACpD,OAAI,KAAK,QAAQ,OAAO,QAAQ,UAAU,EACxC,UAAS,KAAK,QAAQ;AAExB,OAAI,aAAa,QAAQ,MAAM,MAAM;AACnC,gBAAY;AACZ;;GAEF,MAAM,SAAS,QAAQ,IAAI;AAC3B,UAAO,iBAAiB,IAAI,iBAAiB;GAC7C,MAAM,SAAS,OAAO,YAAY,MAAM;AACxC,YAAS,OAAO;AAChB,YAAS,KAAK,IAAI,QAAQ,OAAO,OAAO;;AAG1C,MAAI,aAAa,MAAM;GACrB,MAAM,SAAS,QAAQ,IAAI;AAC3B,UAAO,iBAAiB,IAAI,iBAAiB;GAC7C,MAAM,SAAS,OAAO,YAAY,UAAU;AAC5C,YAAS,OAAO;AAChB,YAAS,KAAK,IAAI,QAAQ,OAAO,OAAO;;AAG1C,SAAO;GAAE;GAAO;GAAQ;;CAG1B,KAAK,KAAiB,GAAW,GAAoB;EACnD,IAAI,SAAS;EACb,MAAM,UAAU,KAAK,QAAQ,WAAW,IAAI;AAC5C,MAAI,KAAK,QAAQ,QACf,KAAI,UAAU,KAAK,QAAQ;AAG7B,MAAI,SAAS;AACX,QAAK,IAAI,YAAY,KAAK,CAAC;AAC3B,QAAK,MAAM,CAAC,OAAO,UAAU,KAAK,SAAS,SAAS,EAAE;IACpD,MAAM,MAAM,KAAK,QAAQ,OAAO,QAAQ,UAAU,IAAI,KAAK,QAAQ,MAAM,KAAA;AACzE,QAAI,KAAK;AACP,UAAK;AACL,SAAI,kBAAkB;;IAExB,MAAM,EAAE,UAAU,QAAQ,IAAI,CAAC,YAAY,MAAM;AACjD,SAAK;IACL,MAAM,gBAAgB,MAAM,KAAK,QAAQ,IAAI,EAAE,GAAG,EAAE;AACpD,eAAW;AACX,QAAI,kBAAkB;;QAGxB,MAAK,MAAM,CAAC,OAAO,UAAU,KAAK,SAAS,SAAS,EAAE;GACpD,MAAM,MAAM,KAAK,QAAQ,OAAO,QAAQ,UAAU,IAAI,KAAK,QAAQ,MAAM,KAAA;AACzE,OAAI,KAAK;AACP,SAAK;AACL,QAAI,kBAAkB;;GAExB,MAAM,gBAAgB,MAAM,KAAK,QAAQ,IAAI,EAAE,GAAG,EAAE;AACpD,cAAW;GACX,MAAM,EAAE,UAAU,QAAQ,IAAI,CAAC,YAAY,MAAM;AACjD,OAAI,kBAAkB;AACtB,QAAK;;AAIT,SAAO;;CAGT,QAAQ,KAAiB,MAAwB;EAC/C,MAAM,UAAU,KAAK,QAAQ,WAAW,IAAI;AAC5C,MAAI,KAAK,QAAQ,QACf,KAAI,UAAU,KAAK,QAAQ;AAG7B,MAAI,SAAS;GACX,IAAI,IAAI,IAAI,YAAY,KAAK,CAAC;AAC9B,QAAK,MAAM,CAAC,OAAO,UAAU,KAAK,SAAS,SAAS,EAAE;IACpD,MAAM,MAAM,KAAK,QAAQ,OAAO,QAAQ,UAAU,IAAI,KAAK,QAAQ,MAAM,KAAA;AACzE,QAAI,KAAK;AACP,UAAK;AACL,SAAI,kBAAkB;;IAExB,MAAM,EAAE,OAAO,WAAW,QAAQ,IAAI,CAAC,YAAY,MAAM;AACzD,SAAK;AACL,QAAI,KAAK,KAAK,KAAK,KAAK,IAAI,IAAI,OAAO;AACrC,SAAI,KAAK,KAAK,OACZ,QAAO;AAET,YAAO,MAAM,QACX,QAAQ,IAAI,EACZ,aAAa,MAAM,EACjB,GAAG,KAAK,IAAI,GACb,CAAC,CACH;;AAEH,QAAI,kBAAkB;;SAEnB;GACL,IAAI,IAAI;AACR,QAAK,MAAM,CAAC,OAAO,UAAU,KAAK,SAAS,SAAS,EAAE;IACpD,MAAM,MAAM,KAAK,QAAQ,OAAO,QAAQ,UAAU,IAAI,KAAK,QAAQ,MAAM,KAAA;AACzE,QAAI,KAAK;AACP,UAAK;AACL,SAAI,kBAAkB;;IAExB,MAAM,EAAE,OAAO,WAAW,QAAQ,IAAI,CAAC,YAAY,MAAM;AACzD,QAAI,KAAK,KAAK,KAAK,KAAK,IAAI,IAAI,OAAO;AACrC,SAAI,KAAK,KAAK,OACZ,QAAO;AAET,YAAO,MAAM,QACX,QAAQ,IAAI,EACZ,aAAa,MAAM,EACjB,GAAG,KAAK,IAAI,GACb,CAAC,CACH;;AAEH,SAAK;AACL,QAAI,kBAAkB;;;AAI1B,SAAO;;;AAIX,IAAa,UAAb,MAA4E;CAC1E;CAEA,YAAY,OAAgB;AAC1B,QAAA,QAAc;AACd,qBAAmB,MAAA,OAAa,KAAK;;CAGvC,IAAI,QAAiB;AACnB,SAAO,MAAA;;CAGT,IAAI,MAAM,SAAkB;AAC1B,MAAI,YAAY,MAAA,MACd;AAEF,uBAAqB,MAAA,MAAY;AACjC,QAAA,QAAc;AACd,qBAAmB,SAAS,KAAK;;CAGnC,IAAI,OAAgB;AAClB,SAAO,KAAK,MAAM;;CAGpB,QAAQ,KAAsB;AAC5B,SAAO,KAAK,MAAM,QAAQ,IAAI;;CAGhC,KAAK,KAAiB,GAAW,GAAoB;AACnD,SAAO,KAAK,MAAM,KAAK,KAAK,GAAG,EAAE;;CAGnC,QAAQ,KAAiB,MAAwB;AAC/C,SAAO,KAAK,MAAM,QAAQ,KAAK,KAAK;;;AAIxC,IAAa,aAAb,cAAoE,QAAW;CAC7E,YACE,OACA,UAKI,EAAE,EACN;AACA,QAAM,MAAM;AAPH,OAAA,UAAA;;CAUX,KAAA,MAAmB;AACjB,SAAO,KAAK,QAAQ,OAAO;;CAG7B,KAAA,SAAsB;AACpB,SAAO,KAAK,QAAQ,UAAU;;CAGhC,KAAA,OAAoB;AAClB,SAAO,KAAK,QAAQ,QAAQ;;CAG9B,KAAA,QAAqB;AACnB,SAAO,KAAK,QAAQ,SAAS;;CAG/B,QAAQ,KAAsB;AAC5B,MAAI,kBAAkB,MAAA,OAAa,MAAA;EACnC,MAAM,EAAE,OAAO,WAAW,IAAI,YAAY,KAAK,MAAM;AACrD,SAAO;GACL,OAAO,QAAQ,MAAA,OAAa,MAAA;GAC5B,QAAQ,SAAS,MAAA,MAAY,MAAA;GAC9B;;CAGH,KAAK,KAAiB,GAAW,GAAoB;AACnD,MAAI,kBAAkB,MAAA,OAAa,MAAA;AACnC,SAAO,KAAK,MAAM,KAAK,KAAK,IAAI,MAAA,MAAY,IAAI,MAAA,IAAU;;CAG5D,QAAQ,KAAiB,MAAwB;AAC/C,MAAI,kBAAkB,MAAA,OAAa,MAAA;EACnC,MAAM,EAAE,OAAO,WAAW,QAAQ,IAAI,CAAC,YAAY,KAAK,MAAM;AAC9D,MAAI,KAAK,KAAK,IAAI,MAAA,QAAc,KAAK,IAAI,MAAA,OAAa,SAAS,KAAK,KAAK,IAAI,MAAA,OAAa,KAAK,IAAI,MAAA,MAAY,OAC7G,QAAO,KAAK,MAAM,QAChB,QAAQ,IAAI,EACZ,aAAa,MAAM;GACjB,GAAG,KAAK,IAAI,MAAA;GACZ,GAAG,KAAK,IAAI,MAAA;GACb,CAAC,CACH;AAEH,SAAO;;;AAIX,IAAa,WAAb,cAAkE,QAAW;CAC3E,SAAS;CAET,YACE,OACA,SAGA;AACA,QAAM,MAAM;AAJH,OAAA,UAAA;;CAOX,QAAQ,KAAsB;AAC5B,MAAI,YAAY,KAAK,QAAQ;EAC7B,MAAM,EAAE,OAAO,WAAW,IAAI,YAAY,KAAK,MAAM;AACrD,UAAQ,KAAK,QAAQ,WAArB;GACE,KAAK;AACH,UAAA,SAAe,IAAI,iBAAiB,SAAS;AAC7C;GACF,KAAK;AACH,UAAA,QAAc,IAAI,iBAAiB;AACnC;GACF,QACE,OAAA,QAAc;;AAElB,SAAO;GACL,OAAO,IAAI;GACX;GACD;;CAGH,KAAK,KAAiB,GAAW,GAAoB;AACnD,MAAI,YAAY,KAAK,QAAQ;AAC7B,SAAO,KAAK,MAAM,KAAK,KAAK,IAAI,MAAA,OAAa,EAAE;;CAGjD,QAAQ,KAAiB,MAAwB;AAC/C,MAAI,YAAY,KAAK,QAAQ;EAC7B,MAAM,EAAE,UAAU,QAAQ,IAAI,CAAC,YAAY,KAAK,MAAM;AACtD,MAAI,KAAK,KAAK,IAAI,MAAA,SAAe,KAAK,IAAI,MAAA,QAAc,MACtD,QAAO,KAAK,MAAM,QAChB,QAAQ,IAAI,EACZ,aAAa,MAAM,EACjB,GAAG,KAAK,IAAI,MAAA,OACb,CAAC,CACH;AAEH,SAAO;;;AAIX,IAAa,gBAAb,MAAkF;CAChF,SAAS;CACT,SAAuB,EAAE;CAEzB,YACE,MACA,SAMA;AAPS,OAAA,OAAA;AACA,OAAA,UAAA;;CAQX,IAAI,OAAgB;AAClB,SAAO;;CAGT,QAAQ,KAAsB;AAC5B,SAAO,IAAI,MAAM,MAAM;AACrB,KAAE,OAAO,KAAK,QAAQ;GACtB,MAAM,EAAE,OAAO,UAAU,WAAW,KAAK,KAAK,MAAM,IAAI,eAAe;AACvE,SAAA,QAAc;AACd,SAAA,QAAc;AACd,UAAO;IAAE,OAAO,MAAA;IAAa,QAAQ,MAAA,MAAY,SAAS,KAAK,QAAQ;IAAY;IACnF;;CAGJ,KAAK,KAAiB,GAAW,GAAoB;AACnD,SAAO,IAAI,MAAM,MAAM;AACrB,KAAE,OAAO,KAAK,QAAQ;AACtB,KAAE,YAAY,IAAI,gBAAgB,KAAK,QAAQ,MAAM;AACrD,WAAQ,KAAK,QAAQ,WAArB;IACE,KAAK;AACH,UAAK,MAAM,EAAE,MAAM,WAAW,MAAA,OAAa;AACzC,QAAE,SAAS,MAAM,GAAG,KAAK,KAAK,QAAQ,aAAa,SAAS,EAAE;AAC9D,WAAK,KAAK,QAAQ;;AAEpB;IACF,KAAK;AACH,UAAK,MAAA;AACL,OAAE,YAAY;AACd,UAAK,MAAM,EAAE,MAAM,WAAW,MAAA,OAAa;AACzC,QAAE,SAAS,MAAM,GAAG,KAAK,KAAK,QAAQ,aAAa,SAAS,EAAE;AAC9D,WAAK,KAAK,QAAQ;;AAEpB;IACF,KAAK;AACH,UAAK,MAAA,QAAc;AACnB,OAAE,YAAY;AACd,UAAK,MAAM,EAAE,MAAM,WAAW,MAAA,OAAa;AACzC,QAAE,SAAS,MAAM,GAAG,KAAK,KAAK,QAAQ,aAAa,SAAS,EAAE;AAC9D,WAAK,KAAK,QAAQ;;AAEpB;;AAEJ,UAAO;IACP;;CAGJ,QAAQ,MAAkB,OAAyB;AACjD,SAAO;;;AAIX,IAAa,OAAb,MAAyE;CACvE,SAAS;CACT,QAAQ;CACR,SAAS;CAET,YACE,MACA,SAKA;AANS,OAAA,OAAA;AACA,OAAA,UAAA;;CAOX,IAAI,OAAgB;AAClB,SAAO;;CAGT,QAAQ,KAAsB;AAC5B,SAAO,IAAI,MAAM,MAAM;AACrB,KAAE,OAAO,KAAK,QAAQ;GACtB,MAAM,EAAE,OAAO,MAAM,UAAU,gBAAgB,KAAK,KAAK,MAAM,IAAI,eAAe;AAClF,SAAA,QAAc;AACd,SAAA,OAAa;AACb,SAAA,QAAc;AACd,UAAO;IAAE,OAAO,MAAA;IAAa,QAAQ,KAAK,QAAQ;IAAY;IAC9D;;CAGJ,KAAK,KAAiB,GAAW,GAAoB;AACnD,SAAO,IAAI,MAAM,MAAM;AACrB,KAAE,OAAO,KAAK,QAAQ;AACtB,KAAE,YAAY,IAAI,gBAAgB,KAAK,QAAQ,MAAM;AACrD,KAAE,SAAS,MAAA,MAAY,GAAG,KAAK,KAAK,QAAQ,aAAa,MAAA,SAAe,EAAE;AAC1E,UAAO;IACP;;CAGJ,QAAQ,MAAkB,OAAyB;AACjD,SAAO;;;AAIX,IAAa,QAAb,MAA0E;CACxE,YACE,OACA,QACA;AAFS,OAAA,QAAA;AACA,OAAA,SAAA;;CAGX,IAAI,OAAgB;AAClB,SAAO;;CAGT,QAAQ,MAAuB;AAC7B,SAAO;GAAE,OAAO,KAAK;GAAO,QAAQ,KAAK;GAAQ;;CAGnD,KAAK,MAAkB,IAAY,IAAqB;AACtD,SAAO;;CAGT,QAAQ,MAAkB,OAAyB;AACjD,SAAO;;;;;AC5gBX,IAAa,eAAb,MAAiF;CAC/E;CACA;CACA;CACA,yBAAS,IAAI,SAAuB;CAEpC,IAAc,UAAsB;AAClC,SAAO,QAAQ,MAAA,IAAU;;CAG3B,YACE,UACA,SACA;AADS,OAAA,UAAA;AAET,OAAK,WAAW;AAChB,OAAK,SAAS,gBAAgB;EAC9B,MAAM,OAAO;AACb,QAAA,MAAY;GACV,UAAU,KAAK;GACf,IAAI,iBAAiB;AACnB,WAAO,KAAK,SAAS,OAAO;;GAE9B,IAAI,eAAe,OAAe;AAChC,WAAO,eAAe,MAAM,kBAAkB;KAAE;KAAO,UAAU;KAAM,CAAC;;GAE1E,WAAW;GACX,SAAS;GACT,YAAY,MAAe;AACzB,WAAO,KAAK,YAAY,MAAM,KAAK;;GAErC,gBAAgB,KAAK,eAAe,KAAK,KAAK;GAC9C,gBAAmB,OAA0B;AAC3C,QAAI,OAAO,UAAU,WACnB,QAAO,MAAM,KAAK,SAAS;AAE7B,WAAO;;GAET,KAAQ,IAAoB;AAC1B,SAAK,SAAS,MAAM;AACpB,QAAI;AACF,YAAO,GAAG,KAAK,SAAS;cAChB;AACR,UAAK,SAAS,SAAS;;;GAG5B;AACD,QAAA,YAAkB,KAAK,SAAS,OAAO;;CAGzC,eAAe,MAAqB;AAClC,QAAA,MAAY,OAAO,KAAK;EACxB,IAAI,KAA0B;AAC9B,SAAQ,KAAK,cAAc,GAAG,CAC5B,OAAA,MAAY,OAAO,GAAG;;CAI1B,YAAY,MAAe,KAAuB;AAChD,MAAI,MAAA,cAAoB,KAAK,SAAS,OAAO,aAAa;AACxD,SAAA,wBAAc,IAAI,SAAuB;AACzC,SAAA,YAAkB,KAAK,SAAS,OAAO;SAClC;GACL,MAAM,SAAS,MAAA,MAAY,IAAI,KAAK;AACpC,OAAI,UAAU,KACZ,QAAO;;EAGX,MAAM,SAAS,KAAK,QAAQ,OAAO,KAAK,QAAQ;AAChD,QAAA,MAAY,IAAI,MAAM,OAAO;AAC7B,SAAO;;;AAIX,IAAa,gBAAb,cAAuE,aAAgB;CACrF,KAAK,MAAwB;EAC3B,MAAM,EAAE,aAAa,eAAe,cAAc,mBAAmB,KAAK,SAAS;AACnF,OAAK,SAAS,UAAU,GAAG,GAAG,eAAe,eAAe;AAC5D,SAAO,KAAK,KAAK,KAAK,SAAS,GAAG,EAAE;;CAGtC,QAAQ,MAAe,MAAwB;AAC7C,SAAO,KAAK,QAAQ,KAAK,SAAS,KAAK;;;AAI3C,SAAgB,eACd,YACyD;CACzD,MAAM,wBAAQ,IAAI,SAA0B;CAE5C,SAAS,GAAG,MAAkB;EAC5B,MAAM,MAAM;EACZ,MAAM,SAAS,MAAM,IAAI,IAAI;AAC7B,MAAI,UAAU,KACZ,QAAO;EAET,MAAM,SAAS,WAAW,KAAK;AAC/B,QAAM,IAAI,KAAK,OAAO;AACtB,SAAO;;AAGT,QAAO,OAAO,OAAO,IAAI,EACvB,QAAQ,QAAW,MAAM,OAAO,IAAyB,EAC1D,CAAC;;AAGJ,IAAa,YAAb,MAAqC;CACnC,SAAS;CACT,WAAW;CACX,QAAa,EAAE;CAEf,QAAQ,GAAG,OAAkB;AAC3B,OAAK,WAAW,MAAM;;CAGxB,WAAW,OAAkB;AAC3B,OAAK,YAAY,MAAM;AACvB,OAAK,QAAQ,MAAM,OAAO,KAAK,MAAM;;CAGvC,KAAK,GAAG,OAAkB;AACxB,OAAK,QAAQ,MAAM;;CAGrB,QAAQ,OAAkB;AACxB,OAAK,MAAM,KAAK,GAAG,MAAM;;CAG3B,QAAc;AACZ,OAAK,QAAQ,EAAE;AACf,OAAK,SAAS;AACd,OAAK,WAAW;;CAGlB,cAAoB;AAClB,OAAK,SAAS;AACd,OAAK,WAAW;;CAGlB,YAAY,OAAqB;AAC/B,OAAK,UAAU;;;AA+BnB,SAAS,MAAM,OAAe,KAAa,KAAqB;AAC9D,QAAO,KAAK,IAAI,KAAK,IAAI,OAAO,IAAI,EAAE,IAAI;;AAG5C,SAAS,UAAU,OAAwB,UAAkB,QAAyB;AACpF,QAAO,OAAO,GAAG,MAAM,UAAU,SAAS,IAAI,OAAO,GAAG,MAAM,QAAQ,OAAO;;AAG/E,SAAS,WAAW,OAAuB;AACzC,QAAO,QAAQ,SAAS,IAAI,IAAI;;AAGlC,SAAS,SAAiB;AACxB,QAAO,WAAW,aAAa,KAAK,IAAI,KAAK,KAAK;;AAGpD,IAAsB,sBAAtB,MAAsB,4BAA8E,aAMlG;CACA,OAAgB,oBAAoB;CACpC,OAAgB,oBAAoB;CACpC,OAAgB,yBAAyB;CAEzC;CACA;CAEA,IAAI,WAAmB;AACrB,SAAO,KAAK,QAAQ,KAAK;;CAG3B,IAAI,SAAS,OAAe;AAC1B,OAAK,QAAQ,KAAK,WAAW;;CAG/B,IAAI,SAAiB;AACnB,SAAO,KAAK,QAAQ,KAAK;;CAG3B,IAAI,OAAO,OAAe;AACxB,OAAK,QAAQ,KAAK,SAAS;;CAG7B,IAAI,QAAa;AACf,SAAO,KAAK,QAAQ,KAAK;;CAG3B,IAAI,MAAM,OAAY;AACpB,OAAK,QAAQ,KAAK,QAAQ;;CAM5B,OAAO,OAAe,UAAyB,EAAE,EAAQ;AACvD,MAAI,KAAK,MAAM,WAAW,GAAG;AAC3B,SAAA,qBAA2B;AAC3B;;EAGF,MAAM,cAAc,KAAK,gBAAgB,MAAM;AAC/C,OAAK,qBAAqB;EAC1B,MAAM,eAAe,KAAK,iBAAiB,YAAY;AAGvD,MAAI,EADa,QAAQ,YAAY,OACtB;AACb,SAAA,qBAA2B;AAC3B,QAAK,aAAa,aAAa;AAC/B,WAAQ,cAAc;AACtB;;EAGF,MAAM,cAAc,KAAK,aAAa;AACtC,MAAI,CAAC,OAAO,SAAS,YAAY,EAAE;AACjC,SAAA,qBAA2B;AAC3B,QAAK,aAAa,aAAa;AAC/B,WAAQ,cAAc;AACtB;;EAGF,MAAM,WAAW,MACf,QAAQ,YACN,oBAAoB,oBAClB,KAAK,IAAI,eAAe,YAAY,GAAG,oBAAoB,wBAC/D,GACA,oBAAoB,kBACrB;AAED,MAAI,YAAY,KAAK,KAAK,IAAI,eAAe,YAAY,IAAI,OAAO,SAAS;AAC3E,SAAA,qBAA2B;AAC3B,QAAK,aAAa,aAAa;AAC/B,WAAQ,cAAc;AACtB;;AAGF,QAAA,gBAAsB;GACpB;GACA;GACA,WAAW,QAAQ;GACnB;GACA,iBAAiB;GACjB,YAAY,QAAQ;GACrB;AACD,QAAA,kBAAwB;GACtB,UAAU,KAAK;GACf,QAAQ,KAAK;GACd;;CAGH,qBAA+B,UAAiC;AAC9D,MAAI,YAAY,KACd;AAEF,WAAS,SAAS;AAClB,WAAS,SAAS;AAClB,WAAS,MAAM;AACf,WAAS,MAAM;;CAGjB,0BAAoC,UAA0B,KAAa,KAAa,QAAsB;AAC5G,MAAI,CAAC,OAAO,SAAS,IAAI,IAAI,CAAC,OAAO,SAAS,OAAO,IAAI,UAAU,EACjE;EAGF,MAAM,iBAAiB,KAAK,SAAS,OAAO;EAC5C,MAAM,aAAa,MAAM,CAAC,KAAK,GAAG,OAAO;EACzC,MAAM,gBAAgB,MAAM,iBAAiB,KAAK,GAAG,OAAO;AAC5D,MAAI,iBAAiB,WACnB;EAGF,MAAM,UAAU,MAAM,aAAa;EACnC,MAAM,UAAU,MAAM,gBAAgB;AACtC,WAAS,SAAS,OAAO,MAAM,SAAS,OAAO,GAAG,MAAM,KAAK,IAAI,KAAK,SAAS,OAAO;AACtF,WAAS,SAAS,OAAO,MAAM,SAAS,OAAO,GAAG,MAAM,KAAK,IAAI,KAAK,SAAS,OAAO;AACtF,WAAS,MAAM,OAAO,MAAM,SAAS,IAAI,GAAG,UAAU,KAAK,IAAI,SAAS,SAAS,IAAI;AACrF,WAAS,MAAM,OAAO,MAAM,SAAS,IAAI,GAAG,UAAU,KAAK,IAAI,SAAS,SAAS,IAAI;;CAGvF,gBAA0B,MAAqB,OAAe,UAAoC;EAChG,IAAI,SAAS;EACb,MAAM,iBAAiB,KAAK,SAAS,OAAO;AAE5C,OAAK,MAAM,EAAE,KAAK,MAAM,QAAQ,YAAY,MAAM;GAChD,MAAM,IAAI,SAAS;AACnB,OAAI,YAAY,KACd,MAAK,0BAA0B,UAAU,KAAK,GAAG,OAAO;AAE1D,OAAI,IAAI,SAAS,KAAK,IAAI,eACxB;AAEF,OAAI,KAAK,KAAK,KAAK,SAAS,GAAG,EAAE,CAC/B,UAAS;;AAIb,SAAO;;CAGT,iBAAoC;EAClC,MAAM,YAAY,MAAA;AAClB,MAAI,aAAa,KACf,QAAO;AAET,MAAI,KAAK,MAAM,WAAW,GAAG;AAC3B,SAAA,qBAA2B;AAC3B,UAAO;;AAET,MAAI,MAAA,mBAAyB,QAAQ,CAAC,UAAU,MAAA,iBAAuB,KAAK,UAAU,KAAK,OAAO,EAAE;AAClG,SAAA,qBAA2B;AAC3B,UAAO;;EAGT,MAAM,WAAW,OAAO,QAAQ,GAAG,UAAU,aAAa,UAAU,UAAU,GAAG,EAAE;EACnF,MAAM,QAAQ,YAAY,IAAI,IAAI,WAAW,SAAS;EACtD,MAAM,SAAS,UAAU,eAAe,UAAU,eAAe,UAAU,eAAe;AAC1F,OAAK,aAAa,OAAO;AACzB,YAAU,kBAAkB,WAAW;AACvC,SAAO,UAAU;;CAGnB,cAAwB,eAAiC;EACvD,MAAM,YAAY,MAAA;AAClB,MAAI,aAAa,KACf,QAAO;AAGT,MAAI,UAAU,iBAAiB;AAC7B,SAAA,kBAAwB;IACtB,UAAU,KAAK;IACf,QAAQ,KAAK;IACd;AACD,UAAO;;EAGT,MAAM,aAAa,UAAU;AAC7B,QAAA,qBAA2B;AAC3B,gBAAc;AACd,SAAO,iBAAiB,MAAA,iBAAuB;;CAGjD,gBAA0B,OAAuB;AAC/C,SAAO,MAAM,OAAO,SAAS,MAAM,GAAG,KAAK,MAAM,MAAM,GAAG,GAAG,GAAG,KAAK,MAAM,SAAS,EAAE;;CAGxF,eAAyB,OAAuB;EAC9C,MAAM,OAAO,KAAK,MAAM;EACxB,MAAM,OAAO,KAAK,QAAQ,WAAW,KAAK;AAC1C,SAAO,KAAK,YAAY,KAAK,CAAC;;CAQhC,uBAA6B;AAC3B,QAAA,gBAAsB,KAAA;AACtB,QAAA,kBAAwB,KAAA;;;AAI5B,IAAa,mBAAb,cAAwF,oBAA0B;CAChH,sBAAsC;AACpC,MAAI,KAAK,MAAM,WAAW,EACxB;AAEF,MAAI,CAAC,OAAO,SAAS,KAAK,SAAS,EAAE;AACnC,QAAK,WAAW;AAChB,QAAK,SAAS;AACd;;AAEF,OAAK,WAAW,KAAK,gBAAgB,KAAK,SAAS;AACnD,MAAI,CAAC,OAAO,SAAS,KAAK,OAAO,CAC/B,MAAK,SAAS;;CAIlB,cAAgC;AAC9B,OAAK,qBAAqB;AAC1B,MAAI,KAAK,MAAM,WAAW,EACxB,QAAO;EAET,MAAM,SAAS,KAAK,eAAe,KAAK,SAAS;AACjD,SAAO,SAAS,IAAI,KAAK,WAAW,KAAK,SAAS,SAAS,KAAK;;CAGlE,aAAuB,QAAsB;AAC3C,MAAI,KAAK,MAAM,WAAW,EACxB;EAEF,MAAM,gBAAgB,MAAM,QAAQ,GAAG,KAAK,MAAM,OAAO;EACzD,MAAM,WAAW,MAAM,KAAK,MAAM,cAAc,EAAE,GAAG,KAAK,MAAM,SAAS,EAAE;EAC3E,MAAM,SAAS,KAAK,eAAe,SAAS;AAC5C,OAAK,WAAW;EAChB,MAAM,SAAS,SAAS,IAAI,EAAE,gBAAgB,YAAY,SAAS;AACnE,OAAK,SAAS,OAAO,GAAG,QAAQ,GAAG,GAAG,IAAI;;CAG5C,iBAA2B,OAAuB;AAChD,SAAO;;CAGT,OAAO,UAAoC;EACzC,MAAM,gBAAgB,KAAK,gBAAgB;EAC3C,MAAM,EAAE,aAAa,eAAe,cAAc,mBAAmB,KAAK,SAAS;AACnF,OAAK,SAAS,UAAU,GAAG,GAAG,eAAe,eAAe;AAC5D,OAAK,qBAAqB,SAAS;EAEnC,IAAI,aAAa;AACjB,MAAI,OAAO,MAAM,KAAK,SAAS,CAC7B,MAAK,WAAW;AAGlB,MAAI,KAAK,SAAS,EAChB,KAAI,KAAK,aAAa,EACpB,MAAK,SAAS;OACT;AACL,QAAK,IAAI,IAAI,KAAK,WAAW,GAAG,KAAK,GAAG,KAAK,GAAG;IAC9C,MAAM,OAAO,KAAK,MAAM;IACxB,MAAM,OAAO,KAAK,QAAQ,WAAW,KAAK;IAC1C,MAAM,EAAE,WAAW,KAAK,YAAY,KAAK;AACzC,SAAK,WAAW;AAChB,SAAK,UAAU;AACf,QAAI,KAAK,UAAU,EACjB;;AAGJ,OAAI,KAAK,aAAa,KAAK,KAAK,SAAS,EACvC,MAAK,SAAS;;EAKpB,IAAI,IAAI,KAAK;EACb,MAAM,WAA0B,EAAE;AAClC,OAAK,IAAI,IAAI,KAAK,UAAU,IAAI,KAAK,MAAM,QAAQ,KAAK,GAAG;GACzD,MAAM,OAAO,KAAK,MAAM;GACxB,MAAM,OAAO,KAAK,QAAQ,WAAW,KAAK;GAC1C,MAAM,EAAE,WAAW,KAAK,YAAY,KAAK;AACzC,OAAI,IAAI,SAAS,GAAG;AAClB,aAAS,KAAK;KAAE,KAAK;KAAG;KAAM,QAAQ;KAAG;KAAQ,CAAC;AAClD,kBAAc;UACT;AACL,SAAK,UAAU;AACf,SAAK,WAAW,IAAI;;AAEtB,QAAK;AACL,OAAI,KAAK,eACP;;EAIJ,IAAI,QAAQ;AACZ,MAAI,IAAI,eACN,KAAI,KAAK,aAAa,KAAK,aAAa,gBAAgB;AACtD,WAAQ,CAAC,KAAK;AACd,QAAK,SAAS;SACT;AACL,WAAQ,iBAAiB;AACzB,OAAK,KAAK,UAAU;GACpB,IAAI,UAAU;AACd,QAAK,IAAI,IAAI,KAAK,WAAW,GAAG,KAAK,GAAG,KAAK,GAAG;IAC9C,MAAM,OAAO,KAAK,MAAO,UAAU;IACnC,MAAM,OAAO,KAAK,QAAQ,WAAW,KAAK;IAC1C,MAAM,EAAE,WAAW,KAAK,YAAY,KAAK;AACzC,kBAAc;AACd,SAAK;AACL,aAAS,KAAK;KAAE,KAAK;KAAG;KAAM,QAAQ,IAAI;KAAO;KAAQ,CAAC;AAC1D,QAAI,IAAI,EACN;;AAGJ,OAAI,YAAY,KAAK,aAAa,gBAAgB;AAChD,YAAQ,CAAC,SAAS,SAAS,SAAS,GAAG;AACvC,SAAK,WAAW;AAChB,SAAK,SAAS;;;EAKpB,MAAM,gBAAgB,KAAK,gBAAgB,UAAU,OAAO,SAAS;AACrE,SAAO,KAAK,cAAc,iBAAiB,cAAc;;CAG3D,QAAQ,MAAwB;EAC9B,MAAM,iBAAiB,KAAK,SAAS,OAAO;EAC5C,IAAI,IAAI,KAAK;AAEb,OAAK,IAAI,IAAI,KAAK,UAAU,IAAI,KAAK,MAAM,QAAQ,KAAK,GAAG;GACzD,MAAM,OAAO,KAAK,MAAM;GACxB,MAAM,OAAO,KAAK,QAAQ,WAAW,KAAK;GAC1C,MAAM,EAAE,WAAW,KAAK,YAAY,KAAK;AACzC,OAAI,KAAK,IAAI,IAAI,OACf,QAAO,KAAK,QACV,KAAK,SACL,aAAa,MAAM,EACjB,GAAG,KAAK,IAAI,GACb,CAAC,CACH;AAEH,QAAK;AACL,OAAI,KAAK,eACP;;AAGJ,SAAO;;;AAIX,IAAa,eAAb,cAAoF,oBAA0B;CAC5G,sBAAsC;AACpC,MAAI,KAAK,MAAM,WAAW,EACxB;AAEF,MAAI,CAAC,OAAO,SAAS,KAAK,SAAS,EAAE;AACnC,QAAK,WAAW,KAAK,MAAM,SAAS;AACpC,QAAK,SAAS;AACd;;AAEF,OAAK,WAAW,KAAK,gBAAgB,KAAK,SAAS;AACnD,MAAI,CAAC,OAAO,SAAS,KAAK,OAAO,CAC/B,MAAK,SAAS;;CAIlB,cAAgC;AAC9B,OAAK,qBAAqB;AAC1B,MAAI,KAAK,MAAM,WAAW,EACxB,QAAO;EAET,MAAM,SAAS,KAAK,eAAe,KAAK,SAAS;AACjD,SAAO,SAAS,IAAI,KAAK,WAAW,IAAI,KAAK,SAAS,SAAS,KAAK,WAAW;;CAGjF,aAAuB,QAAsB;AAC3C,MAAI,KAAK,MAAM,WAAW,EACxB;EAEF,MAAM,gBAAgB,MAAM,QAAQ,GAAG,KAAK,MAAM,OAAO;EACzD,MAAM,WAAW,MAAM,KAAK,KAAK,cAAc,GAAG,GAAG,GAAG,KAAK,MAAM,SAAS,EAAE;EAC9E,MAAM,SAAS,KAAK,eAAe,SAAS;AAC5C,OAAK,WAAW;EAChB,MAAM,SAAS,SAAS,KAAK,WAAW,IAAI,iBAAiB,SAAS;AACtE,OAAK,SAAS,OAAO,GAAG,QAAQ,GAAG,GAAG,IAAI;;CAG5C,iBAA2B,OAAuB;AAChD,SAAO,QAAQ;;CAGjB,OAAO,UAAoC;EACzC,MAAM,gBAAgB,KAAK,gBAAgB;EAC3C,MAAM,EAAE,aAAa,eAAe,cAAc,mBAAmB,KAAK,SAAS;AACnF,OAAK,SAAS,UAAU,GAAG,GAAG,eAAe,eAAe;AAC5D,OAAK,qBAAqB,SAAS;EAEnC,IAAI,aAAa;AACjB,MAAI,OAAO,MAAM,KAAK,SAAS,CAC7B,MAAK,WAAW,KAAK,MAAM,SAAS;AAGtC,MAAI,KAAK,SAAS,EAChB,KAAI,KAAK,aAAa,KAAK,MAAM,SAAS,EACxC,MAAK,SAAS;MAEd,MAAK,IAAI,IAAI,KAAK,WAAW,GAAG,IAAI,KAAK,MAAM,QAAQ,KAAK,GAAG;GAC7D,MAAM,OAAO,KAAK,MAAM;GACxB,MAAM,OAAO,KAAK,QAAQ,WAAW,KAAK;GAC1C,MAAM,EAAE,WAAW,KAAK,YAAY,KAAK;AACzC,QAAK,WAAW;AAChB,QAAK,UAAU;AACf,OAAI,KAAK,SAAS,EAChB;;EAMR,IAAI,IAAI,iBAAiB,KAAK;EAC9B,MAAM,WAA0B,EAAE;AAClC,OAAK,IAAI,IAAI,KAAK,UAAU,KAAK,GAAG,KAAK,GAAG;GAC1C,MAAM,OAAO,KAAK,MAAM;GACxB,MAAM,OAAO,KAAK,QAAQ,WAAW,KAAK;GAC1C,MAAM,EAAE,WAAW,KAAK,YAAY,KAAK;AACzC,QAAK;AACL,OAAI,KAAK,gBAAgB;AACvB,aAAS,KAAK;KAAE,KAAK;KAAG;KAAM,QAAQ;KAAG;KAAQ,CAAC;AAClD,kBAAc;UACT;AACL,SAAK,UAAU;AACf,SAAK,WAAW,IAAI;;AAEtB,OAAI,IAAI,EACN;;EAIJ,IAAI,QAAQ;AACZ,MAAI,IAAI,GAAG;AACT,WAAQ,CAAC;AACT,OAAI,aAAa,gBAAgB;AAC/B,QAAI;AACJ,SAAK,IAAI,IAAI,KAAK,WAAW,GAAG,IAAI,KAAK,MAAM,QAAQ,KAAK,GAAG;KAC7D,MAAM,OAAO,KAAK,MAAM;KACxB,MAAM,OAAO,KAAK,QAAQ,WAAW,KAAK;KAC1C,MAAM,EAAE,WAAW,KAAK,YAAY,KAAK;AACzC,cAAS,KAAK;MAAE,KAAK;MAAG;MAAM,QAAQ,IAAI;MAAO;MAAQ,CAAC;AAC1D,SAAK,cAAc;AACnB,UAAK,WAAW;AAChB,SAAI,KAAK,eACP;;AAGJ,QAAI,aAAa,eACf,MAAK,SAAS;QAEd,MAAK,SAAS,aAAa;SAG7B,MAAK,SAAS,aAAa;;EAI/B,MAAM,gBAAgB,KAAK,gBAAgB,UAAU,OAAO,SAAS;AACrE,SAAO,KAAK,cAAc,iBAAiB,cAAc;;CAG3D,QAAQ,MAAwB;EAC9B,MAAM,iBAAiB,KAAK,SAAS,OAAO;EAE5C,IAAI,aAAa;EACjB,MAAM,UAA6C,EAAE;AACrD,OAAK,IAAI,IAAI,KAAK,UAAU,KAAK,GAAG,KAAK,GAAG;GAC1C,MAAM,OAAO,KAAK,MAAM;GACxB,MAAM,OAAO,KAAK,QAAQ,WAAW,KAAK;GAC1C,MAAM,EAAE,WAAW,KAAK,YAAY,KAAK;AACzC,iBAAc;AACd,WAAQ,KAAK,CAAC,MAAM,OAAO,CAAC;;EAG9B,IAAI,IAAI,aAAa,iBAAiB,aAAa,iBAAiB,KAAK;AACzE,MAAI,KAAK,IAAI,EACX,QAAO;AAGT,OAAK,MAAM,CAAC,MAAM,WAAW,SAAS;AACpC,QAAK;AACL,OAAI,KAAK,IAAI,EACX,QAAO,KAAK,QACV,KAAK,SACL,aAAa,MAAM,EACjB,GAAG,KAAK,IAAI,GACb,CAAC,CACH;;AAGL,SAAO"}
|