@meursyphus/flitter 2.0.3 → 2.2.0

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.cjs CHANGED
@@ -13130,8 +13130,8 @@ var RenderContext = class {
13130
13130
  }
13131
13131
  };
13132
13132
  _resizeHandlers = new WeakMap();
13133
- var _zOrderChanged;
13134
- var RenderPipeline = class {
13133
+ var _zOrderChanged, _RenderPipeline_static, computeMinDescendantZOrder_fn;
13134
+ var _RenderPipeline = class _RenderPipeline {
13135
13135
  constructor({
13136
13136
  onNeedVisualUpdate,
13137
13137
  renderContext,
@@ -13169,6 +13169,7 @@ var RenderPipeline = class {
13169
13169
  this.requestVisualUpdate();
13170
13170
  }
13171
13171
  recalculateZOrder() {
13172
+ var _a;
13172
13173
  if (!__privateGet(this, _zOrderChanged)) return [];
13173
13174
  __privateSet(this, _zOrderChanged, false);
13174
13175
  const visitor = new ZOrderCalculatorVisitor();
@@ -13178,6 +13179,7 @@ var RenderPipeline = class {
13178
13179
  const renderObject = painterRenderObjects[i];
13179
13180
  renderObject.updateZOrder(i);
13180
13181
  }
13182
+ __privateMethod(_a = _RenderPipeline, _RenderPipeline_static, computeMinDescendantZOrder_fn).call(_a, this.renderView);
13181
13183
  return painterRenderObjects;
13182
13184
  }
13183
13185
  flushPaintTransformUpdate() {
@@ -13190,6 +13192,19 @@ var RenderPipeline = class {
13190
13192
  }
13191
13193
  };
13192
13194
  _zOrderChanged = new WeakMap();
13195
+ _RenderPipeline_static = new WeakSet();
13196
+ computeMinDescendantZOrder_fn = function(node) {
13197
+ var _a;
13198
+ let min = node.isPainter ? node.zOrder : Infinity;
13199
+ node.visitChildren((child) => {
13200
+ var _a2;
13201
+ min = Math.min(min, __privateMethod(_a2 = _RenderPipeline, _RenderPipeline_static, computeMinDescendantZOrder_fn).call(_a2, child));
13202
+ });
13203
+ node.minDescendantZOrder = min === Infinity ? (_a = node.zOrder) != null ? _a : 0 : min;
13204
+ return node.minDescendantZOrder;
13205
+ };
13206
+ __privateAdd(_RenderPipeline, _RenderPipeline_static);
13207
+ var RenderPipeline = _RenderPipeline;
13193
13208
  var Painter = class {
13194
13209
  constructor(renderObject) {
13195
13210
  __publicField(this, "renderObject");
@@ -13394,19 +13409,81 @@ function canNotReach(type) {
13394
13409
  }
13395
13410
 
13396
13411
  // src/framework/renderer/canvas/canvas-painting-context.ts
13397
- var _estimateBound, _containerLayer, _currentLayer, _recorder, _ctx2, _CanvasPaintingContext_instances, startRecording_fn, appendLayer_fn;
13412
+ var DRAWING_OPS = /* @__PURE__ */ new Set([
13413
+ "fillRect",
13414
+ "strokeRect",
13415
+ "clearRect",
13416
+ "fill",
13417
+ "stroke",
13418
+ "fillText",
13419
+ "strokeText",
13420
+ "drawImage",
13421
+ "putImageData"
13422
+ ]);
13423
+ var NOOP = () => {
13424
+ };
13425
+ function createCanvasProxy(ctx) {
13426
+ let suppressDepth = 0;
13427
+ let suppressing = false;
13428
+ const proxy = new Proxy(ctx, {
13429
+ get(target, prop, receiver) {
13430
+ if (prop === "__enterSuppress")
13431
+ return () => {
13432
+ suppressing = true;
13433
+ suppressDepth = 0;
13434
+ };
13435
+ if (prop === "__exitSuppress")
13436
+ return () => {
13437
+ suppressing = false;
13438
+ };
13439
+ if (prop === "__raw") return target;
13440
+ if (suppressing) {
13441
+ if (prop === "save") {
13442
+ return () => {
13443
+ suppressDepth++;
13444
+ if (suppressDepth > 1) target.save();
13445
+ };
13446
+ }
13447
+ if (prop === "restore") {
13448
+ return () => {
13449
+ if (suppressDepth > 1) target.restore();
13450
+ suppressDepth--;
13451
+ };
13452
+ }
13453
+ if (DRAWING_OPS.has(prop)) {
13454
+ return NOOP;
13455
+ }
13456
+ }
13457
+ const val = Reflect.get(target, prop, target);
13458
+ return typeof val === "function" ? val.bind(target) : val;
13459
+ },
13460
+ set(target, prop, value) {
13461
+ return Reflect.set(target, prop, value);
13462
+ }
13463
+ });
13464
+ return proxy;
13465
+ }
13466
+ var _estimateBound, _containerLayer, _currentLayer, _skipChildPainting, _CanvasPaintingContext_static, collectPainters_fn, _recorder, _ctx2, _CanvasPaintingContext_instances, startRecording_fn, appendLayer_fn;
13398
13467
  var _CanvasPaintingContext = class _CanvasPaintingContext {
13399
13468
  constructor(containerLayer, estimateBound) {
13400
13469
  __privateAdd(this, _CanvasPaintingContext_instances);
13401
13470
  __privateAdd(this, _estimateBound);
13402
13471
  __privateAdd(this, _containerLayer);
13403
13472
  __privateAdd(this, _currentLayer);
13473
+ /**
13474
+ * When true, paintChild becomes a no-op. Used during z-ordered
13475
+ * painting so that each painter's performPaint only draws itself
13476
+ * without recursing into children (children are painted separately
13477
+ * in z-order).
13478
+ */
13479
+ __privateAdd(this, _skipChildPainting, false);
13404
13480
  __privateAdd(this, _recorder);
13405
13481
  __privateAdd(this, _ctx2);
13406
13482
  __privateSet(this, _containerLayer, containerLayer);
13407
13483
  __privateSet(this, _estimateBound, estimateBound);
13408
13484
  }
13409
13485
  static repaintCompositedChild(node) {
13486
+ var _a;
13410
13487
  assert(
13411
13488
  node.canvasPainter.isRepaintBoundary,
13412
13489
  "isRepaintBoundary must be true on repaintCompositedChild"
@@ -13427,7 +13504,22 @@ var _CanvasPaintingContext = class _CanvasPaintingContext {
13427
13504
  childLayer,
13428
13505
  node.canvasPainter.paintBounds
13429
13506
  );
13430
- node.canvasPainter.paint(childContext, offset_default.Constants.zero);
13507
+ const painters = [];
13508
+ __privateMethod(_a = _CanvasPaintingContext, _CanvasPaintingContext_static, collectPainters_fn).call(_a, node, offset_default.Constants.zero, [], painters);
13509
+ painters.sort((a, b) => a.renderObject.zOrder - b.renderObject.zOrder);
13510
+ const proxyCanvas = childContext.canvas;
13511
+ __privateSet(childContext, _skipChildPainting, true);
13512
+ for (const { renderObject, offset, ancestors } of painters) {
13513
+ proxyCanvas.__raw.save();
13514
+ for (const { node: ancestorNode, offset: ancOffset } of ancestors) {
13515
+ proxyCanvas.__enterSuppress();
13516
+ ancestorNode.canvasPainter.paint(childContext, ancOffset);
13517
+ proxyCanvas.__exitSuppress();
13518
+ }
13519
+ renderObject.canvasPainter.paint(childContext, offset);
13520
+ proxyCanvas.__raw.restore();
13521
+ }
13522
+ __privateSet(childContext, _skipChildPainting, false);
13431
13523
  childContext.stopRecording();
13432
13524
  }
13433
13525
  static updateLayerProperties(_) {
@@ -13450,33 +13542,49 @@ var _CanvasPaintingContext = class _CanvasPaintingContext {
13450
13542
  __privateMethod(this, _CanvasPaintingContext_instances, appendLayer_fn).call(this, layer);
13451
13543
  }
13452
13544
  /**
13453
- *
13454
- * @param child /// Paint a child [RenderObject].
13455
- * @param offset
13456
- ///
13457
- /// @todo: If the child has its own composited layer, the child will be composited
13458
- /// into the layer subtree associated with this painting context. Otherwise,
13459
- /// the child will be painted into the current PictureLayer for this context.
13545
+ * Paint a child RenderObject.
13546
+ *
13547
+ * When #skipChildPainting is true (during z-ordered paint phase),
13548
+ * this is a no-op because each painter is invoked individually
13549
+ * in z-order from repaintCompositedChild.
13460
13550
  */
13461
13551
  paintChild(child, offset) {
13552
+ if (__privateGet(this, _skipChildPainting)) return;
13462
13553
  child.canvasPainter.paint(this, offset);
13463
13554
  }
13464
13555
  };
13465
13556
  _estimateBound = new WeakMap();
13466
13557
  _containerLayer = new WeakMap();
13467
13558
  _currentLayer = new WeakMap();
13559
+ _skipChildPainting = new WeakMap();
13560
+ _CanvasPaintingContext_static = new WeakSet();
13561
+ collectPainters_fn = function(node, offset, ancestorChain, result) {
13562
+ if (node.isPainter) {
13563
+ result.push({
13564
+ renderObject: node,
13565
+ offset,
13566
+ ancestors: [...ancestorChain]
13567
+ });
13568
+ }
13569
+ const childAncestorChain = [...ancestorChain, { node, offset }];
13570
+ node.visitChildren((child) => {
13571
+ var _a;
13572
+ __privateMethod(_a = _CanvasPaintingContext, _CanvasPaintingContext_static, collectPainters_fn).call(_a, child, offset.plus(child.offset), childAncestorChain, result);
13573
+ });
13574
+ };
13468
13575
  _recorder = new WeakMap();
13469
13576
  _ctx2 = new WeakMap();
13470
13577
  _CanvasPaintingContext_instances = new WeakSet();
13471
13578
  startRecording_fn = function() {
13472
13579
  __privateSet(this, _currentLayer, new PictureLayer(__privateGet(this, _estimateBound)));
13473
13580
  __privateSet(this, _recorder, new PictureRecorder(__privateGet(this, _estimateBound)));
13474
- __privateSet(this, _ctx2, __privateGet(this, _recorder).createCanvasContext());
13581
+ __privateSet(this, _ctx2, createCanvasProxy(__privateGet(this, _recorder).createCanvasContext()));
13475
13582
  __privateGet(this, _containerLayer).append(__privateGet(this, _currentLayer));
13476
13583
  };
13477
13584
  appendLayer_fn = function(layer) {
13478
13585
  __privateGet(this, _containerLayer).append(layer);
13479
13586
  };
13587
+ __privateAdd(_CanvasPaintingContext, _CanvasPaintingContext_static);
13480
13588
  var CanvasPaintingContext = _CanvasPaintingContext;
13481
13589
 
13482
13590
  // src/framework/renderer/canvas/canvas-renderer.ts
@@ -13489,13 +13597,15 @@ var CanvasRenderPipeline = class extends RenderPipeline {
13489
13597
  drawFrame() {
13490
13598
  this.flushLayout();
13491
13599
  this.flushPaintTransformUpdate();
13492
- this.flushPaint();
13493
13600
  this.recalculateZOrder();
13601
+ this.flushPaint();
13494
13602
  __privateMethod(this, _CanvasRenderPipeline_instances, compositeFrame_fn).call(this);
13495
13603
  }
13496
13604
  reinitializeFrame() {
13497
13605
  this.renderView.layout(constraints_default.tight(this.renderContext.viewSize));
13498
13606
  this.renderView.updatePaintTransform();
13607
+ this.notifyZOrderChanged();
13608
+ this.recalculateZOrder();
13499
13609
  CanvasPaintingContext.repaintCompositedChild(this.renderView);
13500
13610
  __privateMethod(this, _CanvasRenderPipeline_instances, compositeFrame_fn).call(this);
13501
13611
  }
@@ -13831,23 +13941,95 @@ var Scheduler = class {
13831
13941
  };
13832
13942
  var Scheduler_default = Scheduler;
13833
13943
 
13944
+ // src/framework/Vsync.ts
13945
+ var Vsync = class _Vsync {
13946
+ constructor() {
13947
+ __publicField(this, "callbacks");
13948
+ __publicField(this, "frameRequested");
13949
+ __publicField(this, "rafId");
13950
+ /**
13951
+ * Handles the animation frame by executing all queued callbacks.
13952
+ */
13953
+ __publicField(this, "handleFrame", (time) => {
13954
+ this.frameRequested = false;
13955
+ this.rafId = null;
13956
+ const callbacksToRun = [...this.callbacks];
13957
+ this.callbacks = [];
13958
+ for (const callback of callbacksToRun) {
13959
+ callback(time);
13960
+ }
13961
+ if (this.callbacks.length > 0 && !this.frameRequested) {
13962
+ this.frameRequested = true;
13963
+ this.rafId = requestAnimationFrame(this.handleFrame);
13964
+ }
13965
+ });
13966
+ this.callbacks = [];
13967
+ this.frameRequested = false;
13968
+ this.rafId = null;
13969
+ }
13970
+ static getInstance() {
13971
+ if (typeof window === "undefined") {
13972
+ throw new Error("Vsync requires window object");
13973
+ }
13974
+ if (!window.__flitter_vsync__) {
13975
+ window.__flitter_vsync__ = new _Vsync();
13976
+ }
13977
+ return window.__flitter_vsync__;
13978
+ }
13979
+ /**
13980
+ * Schedules a callback to be executed in the next animation frame.
13981
+ * If there's already a frame requested, the callback will be queued
13982
+ * to run with other callbacks in that frame.
13983
+ */
13984
+ requestCallback(callback) {
13985
+ this.callbacks.push(callback);
13986
+ if (!this.frameRequested) {
13987
+ this.frameRequested = true;
13988
+ this.rafId = requestAnimationFrame(this.handleFrame);
13989
+ }
13990
+ }
13991
+ /**
13992
+ * Removes a previously scheduled callback.
13993
+ */
13994
+ cancelCallback(callback) {
13995
+ const index = this.callbacks.indexOf(callback);
13996
+ if (index !== -1) {
13997
+ this.callbacks.splice(index, 1);
13998
+ }
13999
+ if (this.callbacks.length === 0 && this.rafId !== null) {
14000
+ cancelAnimationFrame(this.rafId);
14001
+ this.frameRequested = false;
14002
+ this.rafId = null;
14003
+ }
14004
+ }
14005
+ };
14006
+
13834
14007
  // src/framework/RenderFrameDispatcher.ts
14008
+ var _vsync;
13835
14009
  var RenderFrameDispatcher = class {
13836
14010
  constructor({ onFrame } = {}) {
13837
14011
  __publicField(this, "onFrame");
14012
+ __privateAdd(this, _vsync, null);
13838
14013
  this.onFrame = onFrame;
13839
14014
  }
14015
+ get vsync() {
14016
+ if (!__privateGet(this, _vsync)) {
14017
+ __privateSet(this, _vsync, Vsync.getInstance());
14018
+ }
14019
+ return __privateGet(this, _vsync);
14020
+ }
13840
14021
  setOnFrame(callback) {
13841
14022
  this.onFrame = () => callback();
13842
14023
  }
13843
14024
  dispatch() {
13844
14025
  if (typeof window === "undefined") return;
13845
- window.requestAnimationFrame(() => {
14026
+ this.vsync.requestCallback(() => {
13846
14027
  var _a;
13847
14028
  (_a = this.onFrame) == null ? void 0 : _a.call(this);
13848
14029
  });
13849
14030
  }
13850
14031
  };
14032
+ _vsync = new WeakMap();
13851
14033
  var RenderFrameDispatcher_default = RenderFrameDispatcher;
13852
14034
 
13853
14035
  // src/framework/Globalkey.ts
@@ -13886,6 +14068,11 @@ var RenderObject = class {
13886
14068
  * Also related to event bubbling on HitTestDispatcher
13887
14069
  */
13888
14070
  __privateAdd(this, _zOrder);
14071
+ /**
14072
+ * The minimum zOrder among all painter descendants (or own zOrder if painter).
14073
+ * Used by canvas renderer to sort children for z-ordered tree walk painting.
14074
+ */
14075
+ __publicField(this, "minDescendantZOrder", 0);
13889
14076
  __privateAdd(this, _svgPainter);
13890
14077
  __privateAdd(this, _canvasPainter);
13891
14078
  __publicField(this, "type", this.constructor.name);
@@ -16970,10 +17157,9 @@ var TransformCanvasPainter = class extends CanvasPainter {
16970
17157
  }
16971
17158
  performPaint(context, offset) {
16972
17159
  const arr = this.effectiveTransform._m4storage;
16973
- const a = arr[0], b = arr[1], c = arr[4], d = arr[5], e = arr[12], f = arr[13];
16974
17160
  context.canvas.save();
16975
17161
  context.canvas.translate(offset.x, offset.y);
16976
- context.canvas.transform(a, b, c, d, e, f);
17162
+ context.canvas.transform(arr[0], arr[1], arr[4], arr[5], arr[12], arr[13]);
16977
17163
  context.canvas.translate(-offset.x, -offset.y);
16978
17164
  this.defaultPaint(context, offset);
16979
17165
  context.canvas.restore();
@@ -18360,10 +18546,10 @@ var CanvasPainterOpacity = class extends CanvasPainter {
18360
18546
  return this.renderObject.opacityProp;
18361
18547
  }
18362
18548
  performPaint(context, offset) {
18363
- const oldAlpha = context.canvas.globalAlpha;
18364
- context.canvas.globalAlpha = oldAlpha * this.opacity;
18549
+ context.canvas.save();
18550
+ context.canvas.globalAlpha *= this.opacity;
18365
18551
  this.defaultPaint(context, offset);
18366
- context.canvas.globalAlpha = oldAlpha;
18552
+ context.canvas.restore();
18367
18553
  }
18368
18554
  };
18369
18555
  var BaseOpacity_default = Opacity;
@@ -19691,7 +19877,6 @@ var ToolTipState = class extends State {
19691
19877
  __publicField(this, "show", false);
19692
19878
  }
19693
19879
  handleMouseEnter() {
19694
- this.show = true;
19695
19880
  this.setState(() => {
19696
19881
  this.show = true;
19697
19882
  });
@@ -20308,7 +20493,9 @@ var CaretState = class extends State {
20308
20493
  if (this.widget.isTyping !== oldWidget.isTyping) {
20309
20494
  if (this.widget.isTyping) {
20310
20495
  this.stopBlinking();
20311
- this.visible = true;
20496
+ this.setState(() => {
20497
+ this.visible = true;
20498
+ });
20312
20499
  } else {
20313
20500
  this.startBlinking();
20314
20501
  }
package/index.d.cts CHANGED
@@ -3570,13 +3570,11 @@ declare class CanvasPaintingContext {
3570
3570
  stopRecording(): void;
3571
3571
  addLayer(layer: Layer): void;
3572
3572
  /**
3573
+ * Paint a child RenderObject.
3573
3574
  *
3574
- * @param child /// Paint a child [RenderObject].
3575
- * @param offset
3576
- ///
3577
- /// @todo: If the child has its own composited layer, the child will be composited
3578
- /// into the layer subtree associated with this painting context. Otherwise,
3579
- /// the child will be painted into the current PictureLayer for this context.
3575
+ * When #skipChildPainting is true (during z-ordered paint phase),
3576
+ * this is a no-op because each painter is invoked individually
3577
+ * in z-order from repaintCompositedChild.
3580
3578
  */
3581
3579
  paintChild(child: RenderObject, offset: Offset$1): void;
3582
3580
  }
@@ -3595,8 +3593,36 @@ declare class CanvasPainter extends Painter$1 {
3595
3593
  skippedPaintingOnLayer(): void;
3596
3594
  }
3597
3595
 
3596
+ /**
3597
+ * Vsync manages requestAnimationFrame calls by queuing callbacks and executing them
3598
+ * in a single animation frame to optimize performance.
3599
+ */
3600
+ declare class Vsync {
3601
+ private callbacks;
3602
+ private frameRequested;
3603
+ private rafId;
3604
+ private constructor();
3605
+ static getInstance(): Vsync;
3606
+ /**
3607
+ * Schedules a callback to be executed in the next animation frame.
3608
+ * If there's already a frame requested, the callback will be queued
3609
+ * to run with other callbacks in that frame.
3610
+ */
3611
+ requestCallback(callback: (time: number) => void): void;
3612
+ /**
3613
+ * Removes a previously scheduled callback.
3614
+ */
3615
+ cancelCallback(callback: (time: number) => void): void;
3616
+ /**
3617
+ * Handles the animation frame by executing all queued callbacks.
3618
+ */
3619
+ private handleFrame;
3620
+ }
3621
+
3598
3622
  declare class RenderFrameDispatcher {
3623
+ #private;
3599
3624
  private onFrame?;
3625
+ get vsync(): Vsync;
3600
3626
  constructor({ onFrame }?: {
3601
3627
  onFrame?: () => void;
3602
3628
  });
@@ -4129,6 +4155,11 @@ declare class RenderObject {
4129
4155
  needsPaintTransformUpdate: boolean;
4130
4156
  depth: number;
4131
4157
  get zOrder(): number;
4158
+ /**
4159
+ * The minimum zOrder among all painter descendants (or own zOrder if painter).
4160
+ * Used by canvas renderer to sort children for z-ordered tree walk painting.
4161
+ */
4162
+ minDescendantZOrder: number;
4132
4163
  updateZOrder(value: number): void;
4133
4164
  get svgPainter(): SvgPainter;
4134
4165
  get canvasPainter(): CanvasPainter;
package/index.d.ts CHANGED
@@ -3570,13 +3570,11 @@ declare class CanvasPaintingContext {
3570
3570
  stopRecording(): void;
3571
3571
  addLayer(layer: Layer): void;
3572
3572
  /**
3573
+ * Paint a child RenderObject.
3573
3574
  *
3574
- * @param child /// Paint a child [RenderObject].
3575
- * @param offset
3576
- ///
3577
- /// @todo: If the child has its own composited layer, the child will be composited
3578
- /// into the layer subtree associated with this painting context. Otherwise,
3579
- /// the child will be painted into the current PictureLayer for this context.
3575
+ * When #skipChildPainting is true (during z-ordered paint phase),
3576
+ * this is a no-op because each painter is invoked individually
3577
+ * in z-order from repaintCompositedChild.
3580
3578
  */
3581
3579
  paintChild(child: RenderObject, offset: Offset$1): void;
3582
3580
  }
@@ -3595,8 +3593,36 @@ declare class CanvasPainter extends Painter$1 {
3595
3593
  skippedPaintingOnLayer(): void;
3596
3594
  }
3597
3595
 
3596
+ /**
3597
+ * Vsync manages requestAnimationFrame calls by queuing callbacks and executing them
3598
+ * in a single animation frame to optimize performance.
3599
+ */
3600
+ declare class Vsync {
3601
+ private callbacks;
3602
+ private frameRequested;
3603
+ private rafId;
3604
+ private constructor();
3605
+ static getInstance(): Vsync;
3606
+ /**
3607
+ * Schedules a callback to be executed in the next animation frame.
3608
+ * If there's already a frame requested, the callback will be queued
3609
+ * to run with other callbacks in that frame.
3610
+ */
3611
+ requestCallback(callback: (time: number) => void): void;
3612
+ /**
3613
+ * Removes a previously scheduled callback.
3614
+ */
3615
+ cancelCallback(callback: (time: number) => void): void;
3616
+ /**
3617
+ * Handles the animation frame by executing all queued callbacks.
3618
+ */
3619
+ private handleFrame;
3620
+ }
3621
+
3598
3622
  declare class RenderFrameDispatcher {
3623
+ #private;
3599
3624
  private onFrame?;
3625
+ get vsync(): Vsync;
3600
3626
  constructor({ onFrame }?: {
3601
3627
  onFrame?: () => void;
3602
3628
  });
@@ -4129,6 +4155,11 @@ declare class RenderObject {
4129
4155
  needsPaintTransformUpdate: boolean;
4130
4156
  depth: number;
4131
4157
  get zOrder(): number;
4158
+ /**
4159
+ * The minimum zOrder among all painter descendants (or own zOrder if painter).
4160
+ * Used by canvas renderer to sort children for z-ordered tree walk painting.
4161
+ */
4162
+ minDescendantZOrder: number;
4132
4163
  updateZOrder(value: number): void;
4133
4164
  get svgPainter(): SvgPainter;
4134
4165
  get canvasPainter(): CanvasPainter;
package/index.global.js CHANGED
@@ -13456,8 +13456,8 @@
13456
13456
  }
13457
13457
  };
13458
13458
  _resizeHandlers = new WeakMap();
13459
- var _zOrderChanged;
13460
- var RenderPipeline = class {
13459
+ var _zOrderChanged, _RenderPipeline_static, computeMinDescendantZOrder_fn;
13460
+ var _RenderPipeline = class _RenderPipeline {
13461
13461
  constructor({
13462
13462
  onNeedVisualUpdate,
13463
13463
  renderContext,
@@ -13495,6 +13495,7 @@
13495
13495
  this.requestVisualUpdate();
13496
13496
  }
13497
13497
  recalculateZOrder() {
13498
+ var _a;
13498
13499
  if (!__privateGet(this, _zOrderChanged)) return [];
13499
13500
  __privateSet(this, _zOrderChanged, false);
13500
13501
  const visitor = new ZOrderCalculatorVisitor();
@@ -13504,6 +13505,7 @@
13504
13505
  const renderObject = painterRenderObjects[i];
13505
13506
  renderObject.updateZOrder(i);
13506
13507
  }
13508
+ __privateMethod(_a = _RenderPipeline, _RenderPipeline_static, computeMinDescendantZOrder_fn).call(_a, this.renderView);
13507
13509
  return painterRenderObjects;
13508
13510
  }
13509
13511
  flushPaintTransformUpdate() {
@@ -13516,6 +13518,19 @@
13516
13518
  }
13517
13519
  };
13518
13520
  _zOrderChanged = new WeakMap();
13521
+ _RenderPipeline_static = new WeakSet();
13522
+ computeMinDescendantZOrder_fn = function(node) {
13523
+ var _a;
13524
+ let min = node.isPainter ? node.zOrder : Infinity;
13525
+ node.visitChildren((child) => {
13526
+ var _a2;
13527
+ min = Math.min(min, __privateMethod(_a2 = _RenderPipeline, _RenderPipeline_static, computeMinDescendantZOrder_fn).call(_a2, child));
13528
+ });
13529
+ node.minDescendantZOrder = min === Infinity ? (_a = node.zOrder) != null ? _a : 0 : min;
13530
+ return node.minDescendantZOrder;
13531
+ };
13532
+ __privateAdd(_RenderPipeline, _RenderPipeline_static);
13533
+ var RenderPipeline = _RenderPipeline;
13519
13534
  var Painter = class {
13520
13535
  constructor(renderObject) {
13521
13536
  __publicField(this, "renderObject");
@@ -13720,19 +13735,81 @@
13720
13735
  }
13721
13736
 
13722
13737
  // src/framework/renderer/canvas/canvas-painting-context.ts
13723
- var _estimateBound, _containerLayer, _currentLayer, _recorder, _ctx2, _CanvasPaintingContext_instances, startRecording_fn, appendLayer_fn;
13738
+ var DRAWING_OPS = /* @__PURE__ */ new Set([
13739
+ "fillRect",
13740
+ "strokeRect",
13741
+ "clearRect",
13742
+ "fill",
13743
+ "stroke",
13744
+ "fillText",
13745
+ "strokeText",
13746
+ "drawImage",
13747
+ "putImageData"
13748
+ ]);
13749
+ var NOOP = () => {
13750
+ };
13751
+ function createCanvasProxy(ctx) {
13752
+ let suppressDepth = 0;
13753
+ let suppressing = false;
13754
+ const proxy = new Proxy(ctx, {
13755
+ get(target, prop, receiver) {
13756
+ if (prop === "__enterSuppress")
13757
+ return () => {
13758
+ suppressing = true;
13759
+ suppressDepth = 0;
13760
+ };
13761
+ if (prop === "__exitSuppress")
13762
+ return () => {
13763
+ suppressing = false;
13764
+ };
13765
+ if (prop === "__raw") return target;
13766
+ if (suppressing) {
13767
+ if (prop === "save") {
13768
+ return () => {
13769
+ suppressDepth++;
13770
+ if (suppressDepth > 1) target.save();
13771
+ };
13772
+ }
13773
+ if (prop === "restore") {
13774
+ return () => {
13775
+ if (suppressDepth > 1) target.restore();
13776
+ suppressDepth--;
13777
+ };
13778
+ }
13779
+ if (DRAWING_OPS.has(prop)) {
13780
+ return NOOP;
13781
+ }
13782
+ }
13783
+ const val = Reflect.get(target, prop, target);
13784
+ return typeof val === "function" ? val.bind(target) : val;
13785
+ },
13786
+ set(target, prop, value) {
13787
+ return Reflect.set(target, prop, value);
13788
+ }
13789
+ });
13790
+ return proxy;
13791
+ }
13792
+ var _estimateBound, _containerLayer, _currentLayer, _skipChildPainting, _CanvasPaintingContext_static, collectPainters_fn, _recorder, _ctx2, _CanvasPaintingContext_instances, startRecording_fn, appendLayer_fn;
13724
13793
  var _CanvasPaintingContext = class _CanvasPaintingContext {
13725
13794
  constructor(containerLayer, estimateBound) {
13726
13795
  __privateAdd(this, _CanvasPaintingContext_instances);
13727
13796
  __privateAdd(this, _estimateBound);
13728
13797
  __privateAdd(this, _containerLayer);
13729
13798
  __privateAdd(this, _currentLayer);
13799
+ /**
13800
+ * When true, paintChild becomes a no-op. Used during z-ordered
13801
+ * painting so that each painter's performPaint only draws itself
13802
+ * without recursing into children (children are painted separately
13803
+ * in z-order).
13804
+ */
13805
+ __privateAdd(this, _skipChildPainting, false);
13730
13806
  __privateAdd(this, _recorder);
13731
13807
  __privateAdd(this, _ctx2);
13732
13808
  __privateSet(this, _containerLayer, containerLayer);
13733
13809
  __privateSet(this, _estimateBound, estimateBound);
13734
13810
  }
13735
13811
  static repaintCompositedChild(node) {
13812
+ var _a;
13736
13813
  assert(
13737
13814
  node.canvasPainter.isRepaintBoundary,
13738
13815
  "isRepaintBoundary must be true on repaintCompositedChild"
@@ -13753,7 +13830,22 @@
13753
13830
  childLayer,
13754
13831
  node.canvasPainter.paintBounds
13755
13832
  );
13756
- node.canvasPainter.paint(childContext, offset_default.Constants.zero);
13833
+ const painters = [];
13834
+ __privateMethod(_a = _CanvasPaintingContext, _CanvasPaintingContext_static, collectPainters_fn).call(_a, node, offset_default.Constants.zero, [], painters);
13835
+ painters.sort((a, b) => a.renderObject.zOrder - b.renderObject.zOrder);
13836
+ const proxyCanvas = childContext.canvas;
13837
+ __privateSet(childContext, _skipChildPainting, true);
13838
+ for (const { renderObject, offset, ancestors } of painters) {
13839
+ proxyCanvas.__raw.save();
13840
+ for (const { node: ancestorNode, offset: ancOffset } of ancestors) {
13841
+ proxyCanvas.__enterSuppress();
13842
+ ancestorNode.canvasPainter.paint(childContext, ancOffset);
13843
+ proxyCanvas.__exitSuppress();
13844
+ }
13845
+ renderObject.canvasPainter.paint(childContext, offset);
13846
+ proxyCanvas.__raw.restore();
13847
+ }
13848
+ __privateSet(childContext, _skipChildPainting, false);
13757
13849
  childContext.stopRecording();
13758
13850
  }
13759
13851
  static updateLayerProperties(_) {
@@ -13776,33 +13868,49 @@
13776
13868
  __privateMethod(this, _CanvasPaintingContext_instances, appendLayer_fn).call(this, layer);
13777
13869
  }
13778
13870
  /**
13779
- *
13780
- * @param child /// Paint a child [RenderObject].
13781
- * @param offset
13782
- ///
13783
- /// @todo: If the child has its own composited layer, the child will be composited
13784
- /// into the layer subtree associated with this painting context. Otherwise,
13785
- /// the child will be painted into the current PictureLayer for this context.
13871
+ * Paint a child RenderObject.
13872
+ *
13873
+ * When #skipChildPainting is true (during z-ordered paint phase),
13874
+ * this is a no-op because each painter is invoked individually
13875
+ * in z-order from repaintCompositedChild.
13786
13876
  */
13787
13877
  paintChild(child, offset) {
13878
+ if (__privateGet(this, _skipChildPainting)) return;
13788
13879
  child.canvasPainter.paint(this, offset);
13789
13880
  }
13790
13881
  };
13791
13882
  _estimateBound = new WeakMap();
13792
13883
  _containerLayer = new WeakMap();
13793
13884
  _currentLayer = new WeakMap();
13885
+ _skipChildPainting = new WeakMap();
13886
+ _CanvasPaintingContext_static = new WeakSet();
13887
+ collectPainters_fn = function(node, offset, ancestorChain, result) {
13888
+ if (node.isPainter) {
13889
+ result.push({
13890
+ renderObject: node,
13891
+ offset,
13892
+ ancestors: [...ancestorChain]
13893
+ });
13894
+ }
13895
+ const childAncestorChain = [...ancestorChain, { node, offset }];
13896
+ node.visitChildren((child) => {
13897
+ var _a;
13898
+ __privateMethod(_a = _CanvasPaintingContext, _CanvasPaintingContext_static, collectPainters_fn).call(_a, child, offset.plus(child.offset), childAncestorChain, result);
13899
+ });
13900
+ };
13794
13901
  _recorder = new WeakMap();
13795
13902
  _ctx2 = new WeakMap();
13796
13903
  _CanvasPaintingContext_instances = new WeakSet();
13797
13904
  startRecording_fn = function() {
13798
13905
  __privateSet(this, _currentLayer, new PictureLayer(__privateGet(this, _estimateBound)));
13799
13906
  __privateSet(this, _recorder, new PictureRecorder(__privateGet(this, _estimateBound)));
13800
- __privateSet(this, _ctx2, __privateGet(this, _recorder).createCanvasContext());
13907
+ __privateSet(this, _ctx2, createCanvasProxy(__privateGet(this, _recorder).createCanvasContext()));
13801
13908
  __privateGet(this, _containerLayer).append(__privateGet(this, _currentLayer));
13802
13909
  };
13803
13910
  appendLayer_fn = function(layer) {
13804
13911
  __privateGet(this, _containerLayer).append(layer);
13805
13912
  };
13913
+ __privateAdd(_CanvasPaintingContext, _CanvasPaintingContext_static);
13806
13914
  var CanvasPaintingContext = _CanvasPaintingContext;
13807
13915
 
13808
13916
  // src/framework/renderer/canvas/canvas-renderer.ts
@@ -13815,13 +13923,15 @@
13815
13923
  drawFrame() {
13816
13924
  this.flushLayout();
13817
13925
  this.flushPaintTransformUpdate();
13818
- this.flushPaint();
13819
13926
  this.recalculateZOrder();
13927
+ this.flushPaint();
13820
13928
  __privateMethod(this, _CanvasRenderPipeline_instances, compositeFrame_fn).call(this);
13821
13929
  }
13822
13930
  reinitializeFrame() {
13823
13931
  this.renderView.layout(constraints_default.tight(this.renderContext.viewSize));
13824
13932
  this.renderView.updatePaintTransform();
13933
+ this.notifyZOrderChanged();
13934
+ this.recalculateZOrder();
13825
13935
  CanvasPaintingContext.repaintCompositedChild(this.renderView);
13826
13936
  __privateMethod(this, _CanvasRenderPipeline_instances, compositeFrame_fn).call(this);
13827
13937
  }
@@ -14157,23 +14267,95 @@
14157
14267
  };
14158
14268
  var Scheduler_default = Scheduler;
14159
14269
 
14270
+ // src/framework/Vsync.ts
14271
+ var Vsync = class _Vsync {
14272
+ constructor() {
14273
+ __publicField(this, "callbacks");
14274
+ __publicField(this, "frameRequested");
14275
+ __publicField(this, "rafId");
14276
+ /**
14277
+ * Handles the animation frame by executing all queued callbacks.
14278
+ */
14279
+ __publicField(this, "handleFrame", (time) => {
14280
+ this.frameRequested = false;
14281
+ this.rafId = null;
14282
+ const callbacksToRun = [...this.callbacks];
14283
+ this.callbacks = [];
14284
+ for (const callback of callbacksToRun) {
14285
+ callback(time);
14286
+ }
14287
+ if (this.callbacks.length > 0 && !this.frameRequested) {
14288
+ this.frameRequested = true;
14289
+ this.rafId = requestAnimationFrame(this.handleFrame);
14290
+ }
14291
+ });
14292
+ this.callbacks = [];
14293
+ this.frameRequested = false;
14294
+ this.rafId = null;
14295
+ }
14296
+ static getInstance() {
14297
+ if (typeof window === "undefined") {
14298
+ throw new Error("Vsync requires window object");
14299
+ }
14300
+ if (!window.__flitter_vsync__) {
14301
+ window.__flitter_vsync__ = new _Vsync();
14302
+ }
14303
+ return window.__flitter_vsync__;
14304
+ }
14305
+ /**
14306
+ * Schedules a callback to be executed in the next animation frame.
14307
+ * If there's already a frame requested, the callback will be queued
14308
+ * to run with other callbacks in that frame.
14309
+ */
14310
+ requestCallback(callback) {
14311
+ this.callbacks.push(callback);
14312
+ if (!this.frameRequested) {
14313
+ this.frameRequested = true;
14314
+ this.rafId = requestAnimationFrame(this.handleFrame);
14315
+ }
14316
+ }
14317
+ /**
14318
+ * Removes a previously scheduled callback.
14319
+ */
14320
+ cancelCallback(callback) {
14321
+ const index = this.callbacks.indexOf(callback);
14322
+ if (index !== -1) {
14323
+ this.callbacks.splice(index, 1);
14324
+ }
14325
+ if (this.callbacks.length === 0 && this.rafId !== null) {
14326
+ cancelAnimationFrame(this.rafId);
14327
+ this.frameRequested = false;
14328
+ this.rafId = null;
14329
+ }
14330
+ }
14331
+ };
14332
+
14160
14333
  // src/framework/RenderFrameDispatcher.ts
14334
+ var _vsync;
14161
14335
  var RenderFrameDispatcher = class {
14162
14336
  constructor({ onFrame } = {}) {
14163
14337
  __publicField(this, "onFrame");
14338
+ __privateAdd(this, _vsync, null);
14164
14339
  this.onFrame = onFrame;
14165
14340
  }
14341
+ get vsync() {
14342
+ if (!__privateGet(this, _vsync)) {
14343
+ __privateSet(this, _vsync, Vsync.getInstance());
14344
+ }
14345
+ return __privateGet(this, _vsync);
14346
+ }
14166
14347
  setOnFrame(callback) {
14167
14348
  this.onFrame = () => callback();
14168
14349
  }
14169
14350
  dispatch() {
14170
14351
  if (typeof window === "undefined") return;
14171
- window.requestAnimationFrame(() => {
14352
+ this.vsync.requestCallback(() => {
14172
14353
  var _a;
14173
14354
  (_a = this.onFrame) == null ? void 0 : _a.call(this);
14174
14355
  });
14175
14356
  }
14176
14357
  };
14358
+ _vsync = new WeakMap();
14177
14359
  var RenderFrameDispatcher_default = RenderFrameDispatcher;
14178
14360
 
14179
14361
  // src/framework/Globalkey.ts
@@ -14212,6 +14394,11 @@
14212
14394
  * Also related to event bubbling on HitTestDispatcher
14213
14395
  */
14214
14396
  __privateAdd(this, _zOrder);
14397
+ /**
14398
+ * The minimum zOrder among all painter descendants (or own zOrder if painter).
14399
+ * Used by canvas renderer to sort children for z-ordered tree walk painting.
14400
+ */
14401
+ __publicField(this, "minDescendantZOrder", 0);
14215
14402
  __privateAdd(this, _svgPainter);
14216
14403
  __privateAdd(this, _canvasPainter);
14217
14404
  __publicField(this, "type", this.constructor.name);
@@ -18174,10 +18361,9 @@
18174
18361
  }
18175
18362
  performPaint(context, offset) {
18176
18363
  const arr = this.effectiveTransform._m4storage;
18177
- const a = arr[0], b = arr[1], c = arr[4], d = arr[5], e = arr[12], f = arr[13];
18178
18364
  context.canvas.save();
18179
18365
  context.canvas.translate(offset.x, offset.y);
18180
- context.canvas.transform(a, b, c, d, e, f);
18366
+ context.canvas.transform(arr[0], arr[1], arr[4], arr[5], arr[12], arr[13]);
18181
18367
  context.canvas.translate(-offset.x, -offset.y);
18182
18368
  this.defaultPaint(context, offset);
18183
18369
  context.canvas.restore();
@@ -19564,10 +19750,10 @@
19564
19750
  return this.renderObject.opacityProp;
19565
19751
  }
19566
19752
  performPaint(context, offset) {
19567
- const oldAlpha = context.canvas.globalAlpha;
19568
- context.canvas.globalAlpha = oldAlpha * this.opacity;
19753
+ context.canvas.save();
19754
+ context.canvas.globalAlpha *= this.opacity;
19569
19755
  this.defaultPaint(context, offset);
19570
- context.canvas.globalAlpha = oldAlpha;
19756
+ context.canvas.restore();
19571
19757
  }
19572
19758
  };
19573
19759
  var BaseOpacity_default = Opacity;
@@ -20895,7 +21081,6 @@
20895
21081
  __publicField(this, "show", false);
20896
21082
  }
20897
21083
  handleMouseEnter() {
20898
- this.show = true;
20899
21084
  this.setState(() => {
20900
21085
  this.show = true;
20901
21086
  });
@@ -21512,7 +21697,9 @@
21512
21697
  if (this.widget.isTyping !== oldWidget.isTyping) {
21513
21698
  if (this.widget.isTyping) {
21514
21699
  this.stopBlinking();
21515
- this.visible = true;
21700
+ this.setState(() => {
21701
+ this.visible = true;
21702
+ });
21516
21703
  } else {
21517
21704
  this.startBlinking();
21518
21705
  }
package/index.js CHANGED
@@ -13130,8 +13130,8 @@ var RenderContext = class {
13130
13130
  }
13131
13131
  };
13132
13132
  _resizeHandlers = new WeakMap();
13133
- var _zOrderChanged;
13134
- var RenderPipeline = class {
13133
+ var _zOrderChanged, _RenderPipeline_static, computeMinDescendantZOrder_fn;
13134
+ var _RenderPipeline = class _RenderPipeline {
13135
13135
  constructor({
13136
13136
  onNeedVisualUpdate,
13137
13137
  renderContext,
@@ -13169,6 +13169,7 @@ var RenderPipeline = class {
13169
13169
  this.requestVisualUpdate();
13170
13170
  }
13171
13171
  recalculateZOrder() {
13172
+ var _a;
13172
13173
  if (!__privateGet(this, _zOrderChanged)) return [];
13173
13174
  __privateSet(this, _zOrderChanged, false);
13174
13175
  const visitor = new ZOrderCalculatorVisitor();
@@ -13178,6 +13179,7 @@ var RenderPipeline = class {
13178
13179
  const renderObject = painterRenderObjects[i];
13179
13180
  renderObject.updateZOrder(i);
13180
13181
  }
13182
+ __privateMethod(_a = _RenderPipeline, _RenderPipeline_static, computeMinDescendantZOrder_fn).call(_a, this.renderView);
13181
13183
  return painterRenderObjects;
13182
13184
  }
13183
13185
  flushPaintTransformUpdate() {
@@ -13190,6 +13192,19 @@ var RenderPipeline = class {
13190
13192
  }
13191
13193
  };
13192
13194
  _zOrderChanged = new WeakMap();
13195
+ _RenderPipeline_static = new WeakSet();
13196
+ computeMinDescendantZOrder_fn = function(node) {
13197
+ var _a;
13198
+ let min = node.isPainter ? node.zOrder : Infinity;
13199
+ node.visitChildren((child) => {
13200
+ var _a2;
13201
+ min = Math.min(min, __privateMethod(_a2 = _RenderPipeline, _RenderPipeline_static, computeMinDescendantZOrder_fn).call(_a2, child));
13202
+ });
13203
+ node.minDescendantZOrder = min === Infinity ? (_a = node.zOrder) != null ? _a : 0 : min;
13204
+ return node.minDescendantZOrder;
13205
+ };
13206
+ __privateAdd(_RenderPipeline, _RenderPipeline_static);
13207
+ var RenderPipeline = _RenderPipeline;
13193
13208
  var Painter = class {
13194
13209
  constructor(renderObject) {
13195
13210
  __publicField(this, "renderObject");
@@ -13394,19 +13409,81 @@ function canNotReach(type) {
13394
13409
  }
13395
13410
 
13396
13411
  // src/framework/renderer/canvas/canvas-painting-context.ts
13397
- var _estimateBound, _containerLayer, _currentLayer, _recorder, _ctx2, _CanvasPaintingContext_instances, startRecording_fn, appendLayer_fn;
13412
+ var DRAWING_OPS = /* @__PURE__ */ new Set([
13413
+ "fillRect",
13414
+ "strokeRect",
13415
+ "clearRect",
13416
+ "fill",
13417
+ "stroke",
13418
+ "fillText",
13419
+ "strokeText",
13420
+ "drawImage",
13421
+ "putImageData"
13422
+ ]);
13423
+ var NOOP = () => {
13424
+ };
13425
+ function createCanvasProxy(ctx) {
13426
+ let suppressDepth = 0;
13427
+ let suppressing = false;
13428
+ const proxy = new Proxy(ctx, {
13429
+ get(target, prop, receiver) {
13430
+ if (prop === "__enterSuppress")
13431
+ return () => {
13432
+ suppressing = true;
13433
+ suppressDepth = 0;
13434
+ };
13435
+ if (prop === "__exitSuppress")
13436
+ return () => {
13437
+ suppressing = false;
13438
+ };
13439
+ if (prop === "__raw") return target;
13440
+ if (suppressing) {
13441
+ if (prop === "save") {
13442
+ return () => {
13443
+ suppressDepth++;
13444
+ if (suppressDepth > 1) target.save();
13445
+ };
13446
+ }
13447
+ if (prop === "restore") {
13448
+ return () => {
13449
+ if (suppressDepth > 1) target.restore();
13450
+ suppressDepth--;
13451
+ };
13452
+ }
13453
+ if (DRAWING_OPS.has(prop)) {
13454
+ return NOOP;
13455
+ }
13456
+ }
13457
+ const val = Reflect.get(target, prop, target);
13458
+ return typeof val === "function" ? val.bind(target) : val;
13459
+ },
13460
+ set(target, prop, value) {
13461
+ return Reflect.set(target, prop, value);
13462
+ }
13463
+ });
13464
+ return proxy;
13465
+ }
13466
+ var _estimateBound, _containerLayer, _currentLayer, _skipChildPainting, _CanvasPaintingContext_static, collectPainters_fn, _recorder, _ctx2, _CanvasPaintingContext_instances, startRecording_fn, appendLayer_fn;
13398
13467
  var _CanvasPaintingContext = class _CanvasPaintingContext {
13399
13468
  constructor(containerLayer, estimateBound) {
13400
13469
  __privateAdd(this, _CanvasPaintingContext_instances);
13401
13470
  __privateAdd(this, _estimateBound);
13402
13471
  __privateAdd(this, _containerLayer);
13403
13472
  __privateAdd(this, _currentLayer);
13473
+ /**
13474
+ * When true, paintChild becomes a no-op. Used during z-ordered
13475
+ * painting so that each painter's performPaint only draws itself
13476
+ * without recursing into children (children are painted separately
13477
+ * in z-order).
13478
+ */
13479
+ __privateAdd(this, _skipChildPainting, false);
13404
13480
  __privateAdd(this, _recorder);
13405
13481
  __privateAdd(this, _ctx2);
13406
13482
  __privateSet(this, _containerLayer, containerLayer);
13407
13483
  __privateSet(this, _estimateBound, estimateBound);
13408
13484
  }
13409
13485
  static repaintCompositedChild(node) {
13486
+ var _a;
13410
13487
  assert(
13411
13488
  node.canvasPainter.isRepaintBoundary,
13412
13489
  "isRepaintBoundary must be true on repaintCompositedChild"
@@ -13427,7 +13504,22 @@ var _CanvasPaintingContext = class _CanvasPaintingContext {
13427
13504
  childLayer,
13428
13505
  node.canvasPainter.paintBounds
13429
13506
  );
13430
- node.canvasPainter.paint(childContext, offset_default.Constants.zero);
13507
+ const painters = [];
13508
+ __privateMethod(_a = _CanvasPaintingContext, _CanvasPaintingContext_static, collectPainters_fn).call(_a, node, offset_default.Constants.zero, [], painters);
13509
+ painters.sort((a, b) => a.renderObject.zOrder - b.renderObject.zOrder);
13510
+ const proxyCanvas = childContext.canvas;
13511
+ __privateSet(childContext, _skipChildPainting, true);
13512
+ for (const { renderObject, offset, ancestors } of painters) {
13513
+ proxyCanvas.__raw.save();
13514
+ for (const { node: ancestorNode, offset: ancOffset } of ancestors) {
13515
+ proxyCanvas.__enterSuppress();
13516
+ ancestorNode.canvasPainter.paint(childContext, ancOffset);
13517
+ proxyCanvas.__exitSuppress();
13518
+ }
13519
+ renderObject.canvasPainter.paint(childContext, offset);
13520
+ proxyCanvas.__raw.restore();
13521
+ }
13522
+ __privateSet(childContext, _skipChildPainting, false);
13431
13523
  childContext.stopRecording();
13432
13524
  }
13433
13525
  static updateLayerProperties(_) {
@@ -13450,33 +13542,49 @@ var _CanvasPaintingContext = class _CanvasPaintingContext {
13450
13542
  __privateMethod(this, _CanvasPaintingContext_instances, appendLayer_fn).call(this, layer);
13451
13543
  }
13452
13544
  /**
13453
- *
13454
- * @param child /// Paint a child [RenderObject].
13455
- * @param offset
13456
- ///
13457
- /// @todo: If the child has its own composited layer, the child will be composited
13458
- /// into the layer subtree associated with this painting context. Otherwise,
13459
- /// the child will be painted into the current PictureLayer for this context.
13545
+ * Paint a child RenderObject.
13546
+ *
13547
+ * When #skipChildPainting is true (during z-ordered paint phase),
13548
+ * this is a no-op because each painter is invoked individually
13549
+ * in z-order from repaintCompositedChild.
13460
13550
  */
13461
13551
  paintChild(child, offset) {
13552
+ if (__privateGet(this, _skipChildPainting)) return;
13462
13553
  child.canvasPainter.paint(this, offset);
13463
13554
  }
13464
13555
  };
13465
13556
  _estimateBound = new WeakMap();
13466
13557
  _containerLayer = new WeakMap();
13467
13558
  _currentLayer = new WeakMap();
13559
+ _skipChildPainting = new WeakMap();
13560
+ _CanvasPaintingContext_static = new WeakSet();
13561
+ collectPainters_fn = function(node, offset, ancestorChain, result) {
13562
+ if (node.isPainter) {
13563
+ result.push({
13564
+ renderObject: node,
13565
+ offset,
13566
+ ancestors: [...ancestorChain]
13567
+ });
13568
+ }
13569
+ const childAncestorChain = [...ancestorChain, { node, offset }];
13570
+ node.visitChildren((child) => {
13571
+ var _a;
13572
+ __privateMethod(_a = _CanvasPaintingContext, _CanvasPaintingContext_static, collectPainters_fn).call(_a, child, offset.plus(child.offset), childAncestorChain, result);
13573
+ });
13574
+ };
13468
13575
  _recorder = new WeakMap();
13469
13576
  _ctx2 = new WeakMap();
13470
13577
  _CanvasPaintingContext_instances = new WeakSet();
13471
13578
  startRecording_fn = function() {
13472
13579
  __privateSet(this, _currentLayer, new PictureLayer(__privateGet(this, _estimateBound)));
13473
13580
  __privateSet(this, _recorder, new PictureRecorder(__privateGet(this, _estimateBound)));
13474
- __privateSet(this, _ctx2, __privateGet(this, _recorder).createCanvasContext());
13581
+ __privateSet(this, _ctx2, createCanvasProxy(__privateGet(this, _recorder).createCanvasContext()));
13475
13582
  __privateGet(this, _containerLayer).append(__privateGet(this, _currentLayer));
13476
13583
  };
13477
13584
  appendLayer_fn = function(layer) {
13478
13585
  __privateGet(this, _containerLayer).append(layer);
13479
13586
  };
13587
+ __privateAdd(_CanvasPaintingContext, _CanvasPaintingContext_static);
13480
13588
  var CanvasPaintingContext = _CanvasPaintingContext;
13481
13589
 
13482
13590
  // src/framework/renderer/canvas/canvas-renderer.ts
@@ -13489,13 +13597,15 @@ var CanvasRenderPipeline = class extends RenderPipeline {
13489
13597
  drawFrame() {
13490
13598
  this.flushLayout();
13491
13599
  this.flushPaintTransformUpdate();
13492
- this.flushPaint();
13493
13600
  this.recalculateZOrder();
13601
+ this.flushPaint();
13494
13602
  __privateMethod(this, _CanvasRenderPipeline_instances, compositeFrame_fn).call(this);
13495
13603
  }
13496
13604
  reinitializeFrame() {
13497
13605
  this.renderView.layout(constraints_default.tight(this.renderContext.viewSize));
13498
13606
  this.renderView.updatePaintTransform();
13607
+ this.notifyZOrderChanged();
13608
+ this.recalculateZOrder();
13499
13609
  CanvasPaintingContext.repaintCompositedChild(this.renderView);
13500
13610
  __privateMethod(this, _CanvasRenderPipeline_instances, compositeFrame_fn).call(this);
13501
13611
  }
@@ -13831,23 +13941,95 @@ var Scheduler = class {
13831
13941
  };
13832
13942
  var Scheduler_default = Scheduler;
13833
13943
 
13944
+ // src/framework/Vsync.ts
13945
+ var Vsync = class _Vsync {
13946
+ constructor() {
13947
+ __publicField(this, "callbacks");
13948
+ __publicField(this, "frameRequested");
13949
+ __publicField(this, "rafId");
13950
+ /**
13951
+ * Handles the animation frame by executing all queued callbacks.
13952
+ */
13953
+ __publicField(this, "handleFrame", (time) => {
13954
+ this.frameRequested = false;
13955
+ this.rafId = null;
13956
+ const callbacksToRun = [...this.callbacks];
13957
+ this.callbacks = [];
13958
+ for (const callback of callbacksToRun) {
13959
+ callback(time);
13960
+ }
13961
+ if (this.callbacks.length > 0 && !this.frameRequested) {
13962
+ this.frameRequested = true;
13963
+ this.rafId = requestAnimationFrame(this.handleFrame);
13964
+ }
13965
+ });
13966
+ this.callbacks = [];
13967
+ this.frameRequested = false;
13968
+ this.rafId = null;
13969
+ }
13970
+ static getInstance() {
13971
+ if (typeof window === "undefined") {
13972
+ throw new Error("Vsync requires window object");
13973
+ }
13974
+ if (!window.__flitter_vsync__) {
13975
+ window.__flitter_vsync__ = new _Vsync();
13976
+ }
13977
+ return window.__flitter_vsync__;
13978
+ }
13979
+ /**
13980
+ * Schedules a callback to be executed in the next animation frame.
13981
+ * If there's already a frame requested, the callback will be queued
13982
+ * to run with other callbacks in that frame.
13983
+ */
13984
+ requestCallback(callback) {
13985
+ this.callbacks.push(callback);
13986
+ if (!this.frameRequested) {
13987
+ this.frameRequested = true;
13988
+ this.rafId = requestAnimationFrame(this.handleFrame);
13989
+ }
13990
+ }
13991
+ /**
13992
+ * Removes a previously scheduled callback.
13993
+ */
13994
+ cancelCallback(callback) {
13995
+ const index = this.callbacks.indexOf(callback);
13996
+ if (index !== -1) {
13997
+ this.callbacks.splice(index, 1);
13998
+ }
13999
+ if (this.callbacks.length === 0 && this.rafId !== null) {
14000
+ cancelAnimationFrame(this.rafId);
14001
+ this.frameRequested = false;
14002
+ this.rafId = null;
14003
+ }
14004
+ }
14005
+ };
14006
+
13834
14007
  // src/framework/RenderFrameDispatcher.ts
14008
+ var _vsync;
13835
14009
  var RenderFrameDispatcher = class {
13836
14010
  constructor({ onFrame } = {}) {
13837
14011
  __publicField(this, "onFrame");
14012
+ __privateAdd(this, _vsync, null);
13838
14013
  this.onFrame = onFrame;
13839
14014
  }
14015
+ get vsync() {
14016
+ if (!__privateGet(this, _vsync)) {
14017
+ __privateSet(this, _vsync, Vsync.getInstance());
14018
+ }
14019
+ return __privateGet(this, _vsync);
14020
+ }
13840
14021
  setOnFrame(callback) {
13841
14022
  this.onFrame = () => callback();
13842
14023
  }
13843
14024
  dispatch() {
13844
14025
  if (typeof window === "undefined") return;
13845
- window.requestAnimationFrame(() => {
14026
+ this.vsync.requestCallback(() => {
13846
14027
  var _a;
13847
14028
  (_a = this.onFrame) == null ? void 0 : _a.call(this);
13848
14029
  });
13849
14030
  }
13850
14031
  };
14032
+ _vsync = new WeakMap();
13851
14033
  var RenderFrameDispatcher_default = RenderFrameDispatcher;
13852
14034
 
13853
14035
  // src/framework/Globalkey.ts
@@ -13886,6 +14068,11 @@ var RenderObject = class {
13886
14068
  * Also related to event bubbling on HitTestDispatcher
13887
14069
  */
13888
14070
  __privateAdd(this, _zOrder);
14071
+ /**
14072
+ * The minimum zOrder among all painter descendants (or own zOrder if painter).
14073
+ * Used by canvas renderer to sort children for z-ordered tree walk painting.
14074
+ */
14075
+ __publicField(this, "minDescendantZOrder", 0);
13889
14076
  __privateAdd(this, _svgPainter);
13890
14077
  __privateAdd(this, _canvasPainter);
13891
14078
  __publicField(this, "type", this.constructor.name);
@@ -16970,10 +17157,9 @@ var TransformCanvasPainter = class extends CanvasPainter {
16970
17157
  }
16971
17158
  performPaint(context, offset) {
16972
17159
  const arr = this.effectiveTransform._m4storage;
16973
- const a = arr[0], b = arr[1], c = arr[4], d = arr[5], e = arr[12], f = arr[13];
16974
17160
  context.canvas.save();
16975
17161
  context.canvas.translate(offset.x, offset.y);
16976
- context.canvas.transform(a, b, c, d, e, f);
17162
+ context.canvas.transform(arr[0], arr[1], arr[4], arr[5], arr[12], arr[13]);
16977
17163
  context.canvas.translate(-offset.x, -offset.y);
16978
17164
  this.defaultPaint(context, offset);
16979
17165
  context.canvas.restore();
@@ -18360,10 +18546,10 @@ var CanvasPainterOpacity = class extends CanvasPainter {
18360
18546
  return this.renderObject.opacityProp;
18361
18547
  }
18362
18548
  performPaint(context, offset) {
18363
- const oldAlpha = context.canvas.globalAlpha;
18364
- context.canvas.globalAlpha = oldAlpha * this.opacity;
18549
+ context.canvas.save();
18550
+ context.canvas.globalAlpha *= this.opacity;
18365
18551
  this.defaultPaint(context, offset);
18366
- context.canvas.globalAlpha = oldAlpha;
18552
+ context.canvas.restore();
18367
18553
  }
18368
18554
  };
18369
18555
  var BaseOpacity_default = Opacity;
@@ -19691,7 +19877,6 @@ var ToolTipState = class extends State {
19691
19877
  __publicField(this, "show", false);
19692
19878
  }
19693
19879
  handleMouseEnter() {
19694
- this.show = true;
19695
19880
  this.setState(() => {
19696
19881
  this.show = true;
19697
19882
  });
@@ -20308,7 +20493,9 @@ var CaretState = class extends State {
20308
20493
  if (this.widget.isTyping !== oldWidget.isTyping) {
20309
20494
  if (this.widget.isTyping) {
20310
20495
  this.stopBlinking();
20311
- this.visible = true;
20496
+ this.setState(() => {
20497
+ this.visible = true;
20498
+ });
20312
20499
  } else {
20313
20500
  this.startBlinking();
20314
20501
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@meursyphus/flitter",
3
- "version": "2.0.3",
3
+ "version": "2.2.0",
4
4
  "description": "Flitter: A high-performance JavaScript rendering engine and framework inspired by Flutter. Features declarative programming, SVG and Canvas support, and optimized for complex data visualizations, interactive charts, and graphic editors in web applications.",
5
5
  "keywords": [
6
6
  "rendering-engine",
@@ -51,14 +51,14 @@
51
51
  "url": "https://github.com/meursyphus/flitter/issues"
52
52
  },
53
53
  "main": "./index.cjs",
54
+ "module": "./index.js",
55
+ "types": "./index.d.ts",
54
56
  "type": "module",
55
57
  "publishConfig": {
56
58
  "access": "public"
57
59
  },
58
- "module": "./index.js",
59
60
  "exports": {
60
61
  "import": "./index.js",
61
62
  "default": "./index.js"
62
- },
63
- "types": "./index.d.ts"
63
+ }
64
64
  }