@grahlnn/comps 0.1.8 → 0.1.9
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/dist/index.js +1840 -1148
- package/dist/torph/index.d.ts +2 -1
- package/dist/torph/src/components/Torph.d.ts +3 -112
- package/dist/torph/src/core/dom-measurement.d.ts +42 -0
- package/dist/torph/src/core/finalize-barrier.d.ts +13 -0
- package/dist/torph/src/core/layout-observer.d.ts +8 -0
- package/dist/torph/src/core/math.d.ts +1 -0
- package/dist/torph/src/core/measurement-policy.d.ts +23 -0
- package/dist/torph/src/core/render.d.ts +16 -0
- package/dist/torph/src/core/root-motion-bridge.d.ts +6 -0
- package/dist/torph/src/core/session.d.ts +81 -0
- package/dist/torph/src/core/snapshot.d.ts +3 -0
- package/dist/torph/src/core/types.d.ts +108 -0
- package/dist/torph/src/debug/trace.d.ts +121 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
// torph/src/components/Torph.tsx
|
|
2
2
|
import {
|
|
3
|
-
useLayoutEffect,
|
|
3
|
+
useLayoutEffect as useLayoutEffect2,
|
|
4
4
|
useMemo,
|
|
5
|
-
useRef,
|
|
6
|
-
useState
|
|
5
|
+
useRef as useRef2,
|
|
6
|
+
useState as useState2
|
|
7
7
|
} from "react";
|
|
8
8
|
|
|
9
9
|
// torph/src/vendor/pretext/bidi.ts
|
|
@@ -2516,8 +2516,12 @@ function measureMorphSnapshotWithPretext(text, layoutContext) {
|
|
|
2516
2516
|
};
|
|
2517
2517
|
}
|
|
2518
2518
|
|
|
2519
|
-
// torph/src/
|
|
2520
|
-
|
|
2519
|
+
// torph/src/core/math.ts
|
|
2520
|
+
function nearlyEqual(a, b, epsilon = 0.5) {
|
|
2521
|
+
return Math.abs(a - b) <= epsilon;
|
|
2522
|
+
}
|
|
2523
|
+
|
|
2524
|
+
// torph/src/core/types.ts
|
|
2521
2525
|
var MORPH = {
|
|
2522
2526
|
durationMs: 280,
|
|
2523
2527
|
maxFadeMs: 150,
|
|
@@ -2526,8 +2530,6 @@ var MORPH = {
|
|
|
2526
2530
|
contentWidthLockEpsilon: 2,
|
|
2527
2531
|
lineGroupingEpsilon: 1
|
|
2528
2532
|
};
|
|
2529
|
-
var MORPH_SEGMENT_CACHE_LIMIT = 256;
|
|
2530
|
-
var DOM_MEASUREMENT_SNAPSHOT_CACHE_LIMIT = 8;
|
|
2531
2533
|
var EMPTY_STATE = {
|
|
2532
2534
|
stage: "idle",
|
|
2533
2535
|
measurement: null,
|
|
@@ -2548,22 +2550,19 @@ var ZERO_BRIDGE = {
|
|
|
2548
2550
|
offsetY: 0
|
|
2549
2551
|
};
|
|
2550
2552
|
var EMPTY_SEGMENTS = [];
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
|
|
2555
|
-
|
|
2556
|
-
|
|
2553
|
+
function resolveContentWidthLockInlineSize(layoutHint) {
|
|
2554
|
+
if (layoutHint.flowInlineSize !== null) {
|
|
2555
|
+
return layoutHint.flowInlineSize;
|
|
2556
|
+
}
|
|
2557
|
+
return layoutHint.snapshot.width;
|
|
2558
|
+
}
|
|
2559
|
+
|
|
2560
|
+
// torph/src/core/render.ts
|
|
2561
|
+
var OVERLAY_STYLE = {
|
|
2557
2562
|
position: "absolute",
|
|
2558
|
-
|
|
2559
|
-
|
|
2560
|
-
|
|
2561
|
-
padding: 0,
|
|
2562
|
-
border: 0,
|
|
2563
|
-
clip: "rect(0 0 0 0)",
|
|
2564
|
-
clipPath: "inset(50%)",
|
|
2565
|
-
overflow: "hidden",
|
|
2566
|
-
whiteSpace: "nowrap"
|
|
2563
|
+
inset: 0,
|
|
2564
|
+
minWidth: 0,
|
|
2565
|
+
pointerEvents: "none"
|
|
2567
2566
|
};
|
|
2568
2567
|
var MEASUREMENT_LAYER_STYLE = {
|
|
2569
2568
|
pointerEvents: "none",
|
|
@@ -2574,299 +2573,708 @@ var MEASUREMENT_LAYER_STYLE = {
|
|
|
2574
2573
|
right: 0,
|
|
2575
2574
|
display: "block"
|
|
2576
2575
|
};
|
|
2577
|
-
|
|
2578
|
-
|
|
2579
|
-
gridArea: "1 / 1"
|
|
2580
|
-
};
|
|
2581
|
-
var OVERLAY_STYLE = {
|
|
2582
|
-
position: "absolute",
|
|
2583
|
-
inset: 0,
|
|
2584
|
-
minWidth: 0,
|
|
2585
|
-
pointerEvents: "none"
|
|
2586
|
-
};
|
|
2587
|
-
var SHARED_GLYPH_TYPOGRAPHY_STYLE = {
|
|
2588
|
-
font: "inherit",
|
|
2589
|
-
fontKerning: "inherit",
|
|
2590
|
-
fontFeatureSettings: "inherit",
|
|
2591
|
-
fontOpticalSizing: "inherit",
|
|
2592
|
-
fontStretch: "inherit",
|
|
2593
|
-
fontStyle: "inherit",
|
|
2594
|
-
fontVariant: "inherit",
|
|
2595
|
-
fontVariantNumeric: "inherit",
|
|
2596
|
-
fontVariationSettings: "inherit",
|
|
2597
|
-
fontWeight: "inherit",
|
|
2598
|
-
letterSpacing: "inherit",
|
|
2599
|
-
textTransform: "inherit",
|
|
2600
|
-
wordSpacing: "inherit",
|
|
2601
|
-
direction: "inherit"
|
|
2602
|
-
};
|
|
2603
|
-
var ABSOLUTE_GLYPH_STYLE = {
|
|
2604
|
-
position: "absolute",
|
|
2605
|
-
display: "block",
|
|
2606
|
-
overflow: "hidden",
|
|
2607
|
-
transformOrigin: "left top"
|
|
2608
|
-
};
|
|
2609
|
-
var CONTEXT_SLICE_TEXT_STYLE = {
|
|
2610
|
-
...SHARED_GLYPH_TYPOGRAPHY_STYLE,
|
|
2611
|
-
position: "absolute",
|
|
2612
|
-
display: "block",
|
|
2613
|
-
minWidth: 0,
|
|
2614
|
-
whiteSpace: "inherit"
|
|
2615
|
-
};
|
|
2616
|
-
var graphemeSegmenter = null;
|
|
2617
|
-
var domMeasurementService = null;
|
|
2618
|
-
var torphDebugInstanceOrdinal = 0;
|
|
2619
|
-
var TORPH_TRACE_MAX_BYTES = 4 * 1024 * 1024;
|
|
2620
|
-
var TORPH_TRACE_MAX_LINES = 4000;
|
|
2621
|
-
var TORPH_TRACE_SCHEMA_VERSION = 2;
|
|
2622
|
-
function nextTorphDebugInstanceId() {
|
|
2623
|
-
torphDebugInstanceOrdinal += 1;
|
|
2624
|
-
return torphDebugInstanceOrdinal;
|
|
2625
|
-
}
|
|
2626
|
-
function readTorphDebugConfig() {
|
|
2627
|
-
const scope = globalThis;
|
|
2628
|
-
return scope.__TORPH_DEBUG__ ?? null;
|
|
2576
|
+
function getFadeDuration(fraction) {
|
|
2577
|
+
return Math.min(MORPH.durationMs * fraction, MORPH.maxFadeMs);
|
|
2629
2578
|
}
|
|
2630
|
-
function
|
|
2631
|
-
if (
|
|
2632
|
-
return
|
|
2579
|
+
function getOverlayStyle(stage, plan) {
|
|
2580
|
+
if (stage === "idle") {
|
|
2581
|
+
return OVERLAY_STYLE;
|
|
2633
2582
|
}
|
|
2634
|
-
|
|
2635
|
-
|
|
2583
|
+
return {
|
|
2584
|
+
...OVERLAY_STYLE,
|
|
2585
|
+
right: "auto",
|
|
2586
|
+
bottom: "auto",
|
|
2587
|
+
width: plan.frameWidth,
|
|
2588
|
+
height: plan.frameHeight
|
|
2589
|
+
};
|
|
2590
|
+
}
|
|
2591
|
+
function getLiveTransform(item, stage, visualBridge) {
|
|
2592
|
+
if (stage !== "prepare") {
|
|
2593
|
+
return "translate(0px, 0px)";
|
|
2636
2594
|
}
|
|
2637
|
-
if (
|
|
2638
|
-
return
|
|
2595
|
+
if (item.kind === "move") {
|
|
2596
|
+
return `translate(${(item.fromLeft ?? item.left) - item.left + visualBridge.offsetX}px, ${(item.fromTop ?? item.top) - item.top + visualBridge.offsetY}px)`;
|
|
2639
2597
|
}
|
|
2640
|
-
return
|
|
2598
|
+
return `translate(${visualBridge.offsetX}px, ${visualBridge.offsetY}px)`;
|
|
2641
2599
|
}
|
|
2642
|
-
function
|
|
2643
|
-
if (
|
|
2644
|
-
return
|
|
2600
|
+
function getLiveTransition(item, stage) {
|
|
2601
|
+
if (stage !== "animate") {
|
|
2602
|
+
return;
|
|
2645
2603
|
}
|
|
2646
|
-
if (
|
|
2647
|
-
return
|
|
2604
|
+
if (item.kind === "enter") {
|
|
2605
|
+
return `opacity ${getFadeDuration(0.5)}ms linear ${getFadeDuration(0.25)}ms`;
|
|
2648
2606
|
}
|
|
2649
|
-
|
|
2650
|
-
|
|
2607
|
+
return `transform ${MORPH.durationMs}ms ${MORPH.ease}, opacity ${getFadeDuration(0.25)}ms linear`;
|
|
2608
|
+
}
|
|
2609
|
+
function getExitTransform(visualBridge) {
|
|
2610
|
+
return `translate(${visualBridge.offsetX}px, ${visualBridge.offsetY}px)`;
|
|
2611
|
+
}
|
|
2612
|
+
function getExitTransition(stage) {
|
|
2613
|
+
if (stage !== "animate") {
|
|
2614
|
+
return;
|
|
2651
2615
|
}
|
|
2652
|
-
return
|
|
2616
|
+
return `transform ${MORPH.durationMs}ms ${MORPH.ease}, opacity ${getFadeDuration(0.25)}ms linear`;
|
|
2653
2617
|
}
|
|
2654
|
-
function
|
|
2655
|
-
|
|
2618
|
+
function supportsIntrinsicWidthLock(display, parentDisplay) {
|
|
2619
|
+
let parentNeedsReservation = false;
|
|
2620
|
+
if (parentDisplay === "flex" || parentDisplay === "inline-flex" || parentDisplay === "grid" || parentDisplay === "inline-grid") {
|
|
2621
|
+
parentNeedsReservation = true;
|
|
2622
|
+
}
|
|
2623
|
+
if (display === "inline" || display === "inline-block" || display === "inline-flex" || display === "inline-grid") {
|
|
2656
2624
|
return true;
|
|
2657
2625
|
}
|
|
2658
|
-
return
|
|
2626
|
+
return parentNeedsReservation;
|
|
2659
2627
|
}
|
|
2660
|
-
function
|
|
2661
|
-
|
|
2662
|
-
|
|
2663
|
-
if (store !== undefined) {
|
|
2664
|
-
return store;
|
|
2628
|
+
function getRootDisplay(layoutContext) {
|
|
2629
|
+
if (layoutContext === null) {
|
|
2630
|
+
return "grid";
|
|
2665
2631
|
}
|
|
2666
|
-
|
|
2667
|
-
|
|
2668
|
-
|
|
2669
|
-
|
|
2670
|
-
};
|
|
2671
|
-
scope.__TORPH_TRACE_STORE__ = store;
|
|
2672
|
-
return store;
|
|
2673
|
-
}
|
|
2674
|
-
function getTorphTraceText() {
|
|
2675
|
-
return getTorphTraceStore().lines.join("");
|
|
2676
|
-
}
|
|
2677
|
-
function clearTorphTrace() {
|
|
2678
|
-
const store = getTorphTraceStore();
|
|
2679
|
-
store.lines = [];
|
|
2680
|
-
store.nextSeq = 1;
|
|
2681
|
-
store.totalBytes = 0;
|
|
2632
|
+
if (supportsIntrinsicWidthLock(layoutContext.display, layoutContext.parentDisplay)) {
|
|
2633
|
+
return "inline-grid";
|
|
2634
|
+
}
|
|
2635
|
+
return "grid";
|
|
2682
2636
|
}
|
|
2683
|
-
function
|
|
2684
|
-
|
|
2685
|
-
|
|
2637
|
+
function getRootStyle(stage, plan, measurement, layoutContext) {
|
|
2638
|
+
let width = measurement?.reservedInlineSize;
|
|
2639
|
+
if (measurement !== null && measurement.flowInlineSize !== null) {
|
|
2640
|
+
width = measurement.layoutInlineSize;
|
|
2686
2641
|
}
|
|
2687
|
-
|
|
2688
|
-
|
|
2689
|
-
const href = URL.createObjectURL(blob);
|
|
2690
|
-
const anchor = document.createElement("a");
|
|
2691
|
-
let resolvedFilename = filename;
|
|
2692
|
-
if (resolvedFilename === undefined) {
|
|
2693
|
-
resolvedFilename = `torph-trace-${new Date().toISOString().replaceAll(":", "-")}.jsonl`;
|
|
2642
|
+
if (plan !== null) {
|
|
2643
|
+
width = plan.layoutInlineSizeTo;
|
|
2694
2644
|
}
|
|
2695
|
-
|
|
2696
|
-
|
|
2697
|
-
|
|
2698
|
-
window.setTimeout(() => {
|
|
2699
|
-
URL.revokeObjectURL(href);
|
|
2700
|
-
}, 0);
|
|
2701
|
-
return resolvedFilename;
|
|
2702
|
-
}
|
|
2703
|
-
function ensureTorphTraceApi() {
|
|
2704
|
-
const scope = globalThis;
|
|
2705
|
-
if (scope.__TORPH_TRACE__ !== undefined) {
|
|
2706
|
-
return scope.__TORPH_TRACE__;
|
|
2645
|
+
let height;
|
|
2646
|
+
if (plan !== null) {
|
|
2647
|
+
height = plan.frameHeight;
|
|
2707
2648
|
}
|
|
2708
|
-
const
|
|
2709
|
-
|
|
2710
|
-
|
|
2711
|
-
download: downloadTorphTrace,
|
|
2712
|
-
text: getTorphTraceText
|
|
2649
|
+
const style = {
|
|
2650
|
+
position: "relative",
|
|
2651
|
+
display: getRootDisplay(layoutContext)
|
|
2713
2652
|
};
|
|
2714
|
-
|
|
2715
|
-
|
|
2653
|
+
if (width !== null && width !== undefined) {
|
|
2654
|
+
style.width = width;
|
|
2655
|
+
}
|
|
2656
|
+
if (height !== undefined) {
|
|
2657
|
+
style.height = height;
|
|
2658
|
+
}
|
|
2659
|
+
return style;
|
|
2716
2660
|
}
|
|
2717
|
-
function
|
|
2718
|
-
|
|
2719
|
-
|
|
2720
|
-
|
|
2721
|
-
|
|
2722
|
-
|
|
2723
|
-
|
|
2724
|
-
seq: store.nextSeq,
|
|
2725
|
-
time: new Date().toISOString()
|
|
2726
|
-
};
|
|
2727
|
-
store.nextSeq += 1;
|
|
2728
|
-
const line = `${JSON.stringify(entry)}
|
|
2729
|
-
`;
|
|
2730
|
-
store.lines.push(line);
|
|
2731
|
-
store.totalBytes += line.length;
|
|
2732
|
-
while (store.lines.length > TORPH_TRACE_MAX_LINES || store.totalBytes > TORPH_TRACE_MAX_BYTES) {
|
|
2733
|
-
const removed = store.lines.shift();
|
|
2734
|
-
if (removed === undefined) {
|
|
2735
|
-
break;
|
|
2661
|
+
function getMeasurementLayerStyle(layoutContext, useContentInlineSize = false) {
|
|
2662
|
+
let intrinsicWidthLock = false;
|
|
2663
|
+
if (layoutContext !== null) {
|
|
2664
|
+
if (useContentInlineSize) {
|
|
2665
|
+
intrinsicWidthLock = true;
|
|
2666
|
+
} else if (supportsIntrinsicWidthLock(layoutContext.display, layoutContext.parentDisplay)) {
|
|
2667
|
+
intrinsicWidthLock = true;
|
|
2736
2668
|
}
|
|
2737
|
-
store.totalBytes = Math.max(0, store.totalBytes - removed.length);
|
|
2738
2669
|
}
|
|
2670
|
+
if (!intrinsicWidthLock) {
|
|
2671
|
+
return MEASUREMENT_LAYER_STYLE;
|
|
2672
|
+
}
|
|
2673
|
+
return {
|
|
2674
|
+
...MEASUREMENT_LAYER_STYLE,
|
|
2675
|
+
right: "auto",
|
|
2676
|
+
width: "max-content"
|
|
2677
|
+
};
|
|
2739
2678
|
}
|
|
2740
|
-
function
|
|
2741
|
-
|
|
2742
|
-
|
|
2679
|
+
function resolveFlowText(committedMeasurement, stateMeasurement, text) {
|
|
2680
|
+
return stateMeasurement?.snapshot.text ?? committedMeasurement?.snapshot.text ?? text;
|
|
2681
|
+
}
|
|
2682
|
+
function shouldRenderGlyphLayer(stage, plan, measurement) {
|
|
2683
|
+
if (stage === "idle") {
|
|
2684
|
+
return measurement !== null;
|
|
2743
2685
|
}
|
|
2744
|
-
return
|
|
2686
|
+
return plan !== null;
|
|
2745
2687
|
}
|
|
2746
|
-
function
|
|
2688
|
+
function resolveGlyphSliceWhiteSpace(snapshot) {
|
|
2747
2689
|
if (snapshot === null) {
|
|
2748
|
-
return
|
|
2690
|
+
return "inherit";
|
|
2749
2691
|
}
|
|
2692
|
+
return "nowrap";
|
|
2693
|
+
}
|
|
2694
|
+
function toSteadyLiveItem(grapheme) {
|
|
2750
2695
|
return {
|
|
2751
|
-
|
|
2752
|
-
|
|
2753
|
-
|
|
2754
|
-
|
|
2755
|
-
graphemes: snapshot.graphemes.length
|
|
2696
|
+
...grapheme,
|
|
2697
|
+
kind: "move",
|
|
2698
|
+
fromLeft: grapheme.left,
|
|
2699
|
+
fromTop: grapheme.top
|
|
2756
2700
|
};
|
|
2757
2701
|
}
|
|
2758
|
-
function
|
|
2759
|
-
|
|
2760
|
-
return null;
|
|
2761
|
-
}
|
|
2702
|
+
function createSteadyGlyphPlan(measurement) {
|
|
2703
|
+
const snapshot = measurement.snapshot;
|
|
2762
2704
|
return {
|
|
2763
|
-
|
|
2764
|
-
|
|
2765
|
-
|
|
2766
|
-
|
|
2767
|
-
|
|
2768
|
-
|
|
2769
|
-
|
|
2770
|
-
|
|
2705
|
+
frameWidth: snapshot.width,
|
|
2706
|
+
frameHeight: snapshot.height,
|
|
2707
|
+
layoutInlineSizeFrom: measurement.layoutInlineSize,
|
|
2708
|
+
layoutInlineSizeTo: measurement.layoutInlineSize,
|
|
2709
|
+
sourceRenderText: snapshot.renderText,
|
|
2710
|
+
targetRenderText: snapshot.renderText,
|
|
2711
|
+
sourceRootOrigin: measurement.rootOrigin,
|
|
2712
|
+
visualBridge: ZERO_BRIDGE,
|
|
2713
|
+
liveItems: snapshot.graphemes.map(toSteadyLiveItem),
|
|
2714
|
+
exitItems: []
|
|
2771
2715
|
};
|
|
2772
2716
|
}
|
|
2773
|
-
|
|
2774
|
-
|
|
2717
|
+
|
|
2718
|
+
// torph/src/core/snapshot.ts
|
|
2719
|
+
function isSingleLineSnapshot(snapshot) {
|
|
2720
|
+
if (snapshot.graphemes.length <= 1) {
|
|
2721
|
+
return true;
|
|
2722
|
+
}
|
|
2723
|
+
const firstTop = snapshot.graphemes[0].top;
|
|
2724
|
+
return snapshot.graphemes.every((grapheme) => nearlyEqual(grapheme.top, firstTop, MORPH.lineGroupingEpsilon));
|
|
2725
|
+
}
|
|
2726
|
+
function assertSingleLineSnapshot(snapshot) {
|
|
2727
|
+
if (isSingleLineSnapshot(snapshot)) {
|
|
2728
|
+
return snapshot;
|
|
2729
|
+
}
|
|
2730
|
+
throw new Error(`Torph only supports single-line text layout. Received wrapped text: "${snapshot.renderText}"`);
|
|
2731
|
+
}
|
|
2732
|
+
|
|
2733
|
+
// torph/src/core/measurement-policy.ts
|
|
2734
|
+
var MORPH_SEGMENT_CACHE_LIMIT = 256;
|
|
2735
|
+
var morphSegmentCache = new Map;
|
|
2736
|
+
var pretextMorphTrustCache = new Map;
|
|
2737
|
+
var morphMeasurementEpoch = 1;
|
|
2738
|
+
var graphemeSegmenter = null;
|
|
2739
|
+
function getGraphemeSegmenter() {
|
|
2740
|
+
if (graphemeSegmenter !== null) {
|
|
2741
|
+
return graphemeSegmenter;
|
|
2742
|
+
}
|
|
2743
|
+
graphemeSegmenter = new Intl.Segmenter(undefined, {
|
|
2744
|
+
granularity: "grapheme"
|
|
2745
|
+
});
|
|
2746
|
+
return graphemeSegmenter;
|
|
2747
|
+
}
|
|
2748
|
+
function clearPretextMorphTrustCache() {
|
|
2749
|
+
pretextMorphTrustCache.clear();
|
|
2750
|
+
}
|
|
2751
|
+
function clearMorphMeasurementCaches() {
|
|
2752
|
+
morphSegmentCache.clear();
|
|
2753
|
+
clearPretextMorphTrustCache();
|
|
2754
|
+
clearPretextMorphCaches();
|
|
2755
|
+
}
|
|
2756
|
+
function bumpMorphMeasurementEpoch() {
|
|
2757
|
+
morphMeasurementEpoch += 1;
|
|
2758
|
+
}
|
|
2759
|
+
function getMorphMeasurementEpoch() {
|
|
2760
|
+
return morphMeasurementEpoch;
|
|
2761
|
+
}
|
|
2762
|
+
function readCachedMorphSegments(text) {
|
|
2763
|
+
const cached = morphSegmentCache.get(text);
|
|
2764
|
+
if (cached !== undefined) {
|
|
2765
|
+
morphSegmentCache.delete(text);
|
|
2766
|
+
morphSegmentCache.set(text, cached);
|
|
2767
|
+
return cached;
|
|
2768
|
+
}
|
|
2769
|
+
const segments = Array.from(getGraphemeSegmenter().segment(text), (segment, index) => ({
|
|
2770
|
+
glyph: segment.segment,
|
|
2771
|
+
key: `${segment.segment}:${index}`
|
|
2772
|
+
}));
|
|
2773
|
+
morphSegmentCache.set(text, segments);
|
|
2774
|
+
if (morphSegmentCache.size > MORPH_SEGMENT_CACHE_LIMIT) {
|
|
2775
|
+
const oldest = morphSegmentCache.keys().next();
|
|
2776
|
+
if (!oldest.done) {
|
|
2777
|
+
morphSegmentCache.delete(oldest.value);
|
|
2778
|
+
}
|
|
2779
|
+
}
|
|
2780
|
+
return segments;
|
|
2781
|
+
}
|
|
2782
|
+
function shouldMeasureUsingContentInlineSize(layoutContext, layoutHint) {
|
|
2783
|
+
if (supportsIntrinsicWidthLock(layoutContext.display, layoutContext.parentDisplay)) {
|
|
2784
|
+
return true;
|
|
2785
|
+
}
|
|
2786
|
+
if (layoutContext.whiteSpace === "nowrap") {
|
|
2787
|
+
return true;
|
|
2788
|
+
}
|
|
2789
|
+
if (layoutHint === null) {
|
|
2790
|
+
return false;
|
|
2791
|
+
}
|
|
2792
|
+
if (!isSingleLineSnapshot(layoutHint.snapshot)) {
|
|
2793
|
+
return false;
|
|
2794
|
+
}
|
|
2795
|
+
return nearlyEqual(layoutHint.layoutInlineSize, resolveContentWidthLockInlineSize(layoutHint), MORPH.contentWidthLockEpsilon);
|
|
2796
|
+
}
|
|
2797
|
+
function getTrustedPretextMeasurementBackend(text, renderText, layoutContext, useContentInlineSize) {
|
|
2798
|
+
const backend = getPretextMorphMeasurementBackend(text, layoutContext);
|
|
2799
|
+
if (backend !== "probe") {
|
|
2800
|
+
return backend;
|
|
2801
|
+
}
|
|
2802
|
+
const signature = getPretextMorphTrustSignature({
|
|
2803
|
+
renderText,
|
|
2804
|
+
layoutContext,
|
|
2805
|
+
useContentInlineSize
|
|
2806
|
+
});
|
|
2807
|
+
if (signature === null) {
|
|
2808
|
+
return "dom";
|
|
2809
|
+
}
|
|
2810
|
+
const trusted = pretextMorphTrustCache.get(signature);
|
|
2811
|
+
if (trusted === undefined) {
|
|
2812
|
+
return "probe";
|
|
2813
|
+
}
|
|
2814
|
+
if (trusted) {
|
|
2815
|
+
return "pretext";
|
|
2816
|
+
}
|
|
2817
|
+
return "dom";
|
|
2818
|
+
}
|
|
2819
|
+
function getDomMeasurementRequestKey(text, renderText, layoutContext, useContentInlineSize) {
|
|
2820
|
+
let inlineSizeMode = "container";
|
|
2821
|
+
if (useContentInlineSize) {
|
|
2822
|
+
inlineSizeMode = "content";
|
|
2823
|
+
}
|
|
2824
|
+
return `dom\x00${inlineSizeMode}\x00${text}\x00${renderText}\x00${layoutContext.measurementVersion}\x00${getMorphMeasurementEpoch()}`;
|
|
2825
|
+
}
|
|
2826
|
+
function needsMeasurementLayer(measurementBackend, renderText) {
|
|
2827
|
+
if (measurementBackend === "pretext") {
|
|
2828
|
+
return false;
|
|
2829
|
+
}
|
|
2830
|
+
return renderText.length > 0;
|
|
2831
|
+
}
|
|
2832
|
+
function canCacheMeasurementLayerSnapshot(measurementBackend) {
|
|
2833
|
+
return measurementBackend === "dom";
|
|
2834
|
+
}
|
|
2835
|
+
function createMorphMeasurementRequest({
|
|
2836
|
+
text,
|
|
2837
|
+
layoutContext,
|
|
2838
|
+
layoutHint
|
|
2839
|
+
}) {
|
|
2840
|
+
if (layoutContext === null) {
|
|
2775
2841
|
return null;
|
|
2776
2842
|
}
|
|
2843
|
+
const renderText = getPretextMorphRenderedText(text, layoutContext);
|
|
2844
|
+
const useContentInlineSize = shouldMeasureUsingContentInlineSize(layoutContext, layoutHint);
|
|
2845
|
+
const measurementBackend = getTrustedPretextMeasurementBackend(text, renderText, layoutContext, useContentInlineSize);
|
|
2846
|
+
let segments = readCachedMorphSegments(renderText);
|
|
2847
|
+
if (measurementBackend === "pretext") {
|
|
2848
|
+
segments = EMPTY_SEGMENTS;
|
|
2849
|
+
}
|
|
2850
|
+
let domMeasurementKey = null;
|
|
2851
|
+
if (needsMeasurementLayer(measurementBackend, renderText)) {
|
|
2852
|
+
domMeasurementKey = getDomMeasurementRequestKey(text, renderText, layoutContext, useContentInlineSize);
|
|
2853
|
+
}
|
|
2777
2854
|
return {
|
|
2778
|
-
|
|
2779
|
-
|
|
2780
|
-
|
|
2781
|
-
|
|
2855
|
+
text,
|
|
2856
|
+
renderText,
|
|
2857
|
+
segments,
|
|
2858
|
+
measurementBackend,
|
|
2859
|
+
useContentInlineSize,
|
|
2860
|
+
domMeasurementKey
|
|
2782
2861
|
};
|
|
2783
2862
|
}
|
|
2784
|
-
function
|
|
2785
|
-
|
|
2786
|
-
|
|
2787
|
-
|
|
2863
|
+
function rememberPretextMeasurementTrust({
|
|
2864
|
+
renderText,
|
|
2865
|
+
layoutContext,
|
|
2866
|
+
useContentInlineSize,
|
|
2867
|
+
trusted
|
|
2868
|
+
}) {
|
|
2869
|
+
const signature = getPretextMorphTrustSignature({
|
|
2870
|
+
renderText,
|
|
2871
|
+
layoutContext,
|
|
2872
|
+
useContentInlineSize
|
|
2873
|
+
});
|
|
2874
|
+
if (signature === null) {
|
|
2875
|
+
return;
|
|
2788
2876
|
}
|
|
2789
|
-
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
|
|
2877
|
+
pretextMorphTrustCache.set(signature, trusted);
|
|
2878
|
+
}
|
|
2879
|
+
function areSnapshotsEquivalentForPretextTrust(left, right) {
|
|
2880
|
+
if (left.renderText !== right.renderText || left.graphemes.length !== right.graphemes.length) {
|
|
2881
|
+
return false;
|
|
2793
2882
|
}
|
|
2794
|
-
if (
|
|
2795
|
-
|
|
2883
|
+
if (Math.abs(left.width - right.width) > MORPH.geometryEpsilon) {
|
|
2884
|
+
return false;
|
|
2796
2885
|
}
|
|
2797
|
-
|
|
2798
|
-
|
|
2886
|
+
if (Math.abs(left.height - right.height) > MORPH.geometryEpsilon) {
|
|
2887
|
+
return false;
|
|
2888
|
+
}
|
|
2889
|
+
for (let index = 0;index < left.graphemes.length; index += 1) {
|
|
2890
|
+
const from = left.graphemes[index];
|
|
2891
|
+
const to = right.graphemes[index];
|
|
2892
|
+
if (from.glyph !== to.glyph) {
|
|
2893
|
+
return false;
|
|
2894
|
+
}
|
|
2895
|
+
if (Math.abs(from.left - to.left) > MORPH.geometryEpsilon) {
|
|
2896
|
+
return false;
|
|
2897
|
+
}
|
|
2898
|
+
if (Math.abs(from.top - to.top) > MORPH.geometryEpsilon) {
|
|
2899
|
+
return false;
|
|
2900
|
+
}
|
|
2901
|
+
if (Math.abs(from.width - to.width) > MORPH.geometryEpsilon) {
|
|
2902
|
+
return false;
|
|
2903
|
+
}
|
|
2904
|
+
if (Math.abs(from.height - to.height) > MORPH.geometryEpsilon) {
|
|
2905
|
+
return false;
|
|
2906
|
+
}
|
|
2907
|
+
}
|
|
2908
|
+
return true;
|
|
2799
2909
|
}
|
|
2800
|
-
|
|
2801
|
-
|
|
2802
|
-
|
|
2910
|
+
|
|
2911
|
+
// torph/src/core/finalize-barrier.ts
|
|
2912
|
+
function createMorphFinalizeBarrier(hasMoveTransitions) {
|
|
2913
|
+
return {
|
|
2914
|
+
waitForLiveTransform: hasMoveTransitions,
|
|
2915
|
+
sawLiveTransform: false
|
|
2916
|
+
};
|
|
2917
|
+
}
|
|
2918
|
+
function recordMorphFinalizeSignal(barrier, signal) {
|
|
2919
|
+
return {
|
|
2920
|
+
...barrier,
|
|
2921
|
+
sawLiveTransform: signal === "live-transform"
|
|
2922
|
+
};
|
|
2923
|
+
}
|
|
2924
|
+
function isMorphFinalizeBarrierSatisfied(barrier) {
|
|
2925
|
+
if (barrier.waitForLiveTransform && !barrier.sawLiveTransform) {
|
|
2926
|
+
return false;
|
|
2803
2927
|
}
|
|
2804
|
-
|
|
2805
|
-
|
|
2806
|
-
|
|
2807
|
-
|
|
2808
|
-
|
|
2928
|
+
return true;
|
|
2929
|
+
}
|
|
2930
|
+
function summarizeMorphFinalizeBarrier(barrier) {
|
|
2931
|
+
return {
|
|
2932
|
+
waitForLiveTransform: barrier.waitForLiveTransform,
|
|
2933
|
+
sawLiveTransform: barrier.sawLiveTransform,
|
|
2934
|
+
satisfied: isMorphFinalizeBarrierSatisfied(barrier)
|
|
2935
|
+
};
|
|
2936
|
+
}
|
|
2937
|
+
|
|
2938
|
+
// torph/src/core/session.ts
|
|
2939
|
+
function bucketByGlyph(graphemes) {
|
|
2940
|
+
const buckets = new Map;
|
|
2941
|
+
for (const grapheme of graphemes) {
|
|
2942
|
+
const bucket = buckets.get(grapheme.glyph);
|
|
2943
|
+
if (bucket !== undefined) {
|
|
2944
|
+
bucket.push(grapheme);
|
|
2809
2945
|
continue;
|
|
2810
2946
|
}
|
|
2811
|
-
|
|
2812
|
-
index,
|
|
2813
|
-
glyph: grapheme.glyph,
|
|
2814
|
-
left: roundDebugValue(rootRect.left + grapheme.left),
|
|
2815
|
-
top: roundDebugValue(rootRect.top + grapheme.top),
|
|
2816
|
-
width: roundDebugValue(grapheme.width),
|
|
2817
|
-
height: roundDebugValue(grapheme.height)
|
|
2818
|
-
});
|
|
2947
|
+
buckets.set(grapheme.glyph, [grapheme]);
|
|
2819
2948
|
}
|
|
2820
|
-
return
|
|
2949
|
+
return buckets;
|
|
2950
|
+
}
|
|
2951
|
+
function pairMorphCharacters(previous, next) {
|
|
2952
|
+
const previousBuckets = bucketByGlyph(previous);
|
|
2953
|
+
const nextBuckets = bucketByGlyph(next);
|
|
2954
|
+
const pairings = [];
|
|
2955
|
+
for (const [glyph, previousItems] of previousBuckets) {
|
|
2956
|
+
const nextItems = nextBuckets.get(glyph) ?? [];
|
|
2957
|
+
const shared = Math.min(previousItems.length, nextItems.length);
|
|
2958
|
+
for (let index = 0;index < shared; index += 1) {
|
|
2959
|
+
pairings.push({
|
|
2960
|
+
kind: "move",
|
|
2961
|
+
from: previousItems[index],
|
|
2962
|
+
to: nextItems[index]
|
|
2963
|
+
});
|
|
2964
|
+
}
|
|
2965
|
+
for (let index = shared;index < previousItems.length; index += 1) {
|
|
2966
|
+
pairings.push({
|
|
2967
|
+
kind: "exit",
|
|
2968
|
+
from: previousItems[index]
|
|
2969
|
+
});
|
|
2970
|
+
}
|
|
2971
|
+
}
|
|
2972
|
+
for (const [glyph, nextItems] of nextBuckets) {
|
|
2973
|
+
const previousItems = previousBuckets.get(glyph) ?? [];
|
|
2974
|
+
const shared = Math.min(previousItems.length, nextItems.length);
|
|
2975
|
+
for (let index = shared;index < nextItems.length; index += 1) {
|
|
2976
|
+
pairings.push({
|
|
2977
|
+
kind: "enter",
|
|
2978
|
+
to: nextItems[index]
|
|
2979
|
+
});
|
|
2980
|
+
}
|
|
2981
|
+
}
|
|
2982
|
+
return pairings;
|
|
2983
|
+
}
|
|
2984
|
+
function resolveMorphFrameBounds(previous, next) {
|
|
2985
|
+
return {
|
|
2986
|
+
width: Math.max(previous.width, next.width),
|
|
2987
|
+
height: Math.max(previous.height, next.height)
|
|
2988
|
+
};
|
|
2989
|
+
}
|
|
2990
|
+
function buildMorphPlan(previous, next, visualBridge = ZERO_BRIDGE) {
|
|
2991
|
+
const pairings = pairMorphCharacters(previous.snapshot.graphemes, next.snapshot.graphemes);
|
|
2992
|
+
const movesByDestinationKey = new Map;
|
|
2993
|
+
const exitItems = [];
|
|
2994
|
+
for (const pairing of pairings) {
|
|
2995
|
+
if (pairing.kind === "move") {
|
|
2996
|
+
movesByDestinationKey.set(pairing.to.key, pairing);
|
|
2997
|
+
continue;
|
|
2998
|
+
}
|
|
2999
|
+
if (pairing.kind === "exit") {
|
|
3000
|
+
exitItems.push(pairing.from);
|
|
3001
|
+
}
|
|
3002
|
+
}
|
|
3003
|
+
const frame = resolveMorphFrameBounds(previous.snapshot, next.snapshot);
|
|
3004
|
+
return {
|
|
3005
|
+
frameWidth: frame.width,
|
|
3006
|
+
frameHeight: frame.height,
|
|
3007
|
+
layoutInlineSizeFrom: previous.layoutInlineSize,
|
|
3008
|
+
layoutInlineSizeTo: next.layoutInlineSize,
|
|
3009
|
+
sourceRenderText: previous.snapshot.renderText,
|
|
3010
|
+
targetRenderText: next.snapshot.renderText,
|
|
3011
|
+
sourceRootOrigin: previous.rootOrigin,
|
|
3012
|
+
visualBridge,
|
|
3013
|
+
liveItems: next.snapshot.graphemes.map((grapheme) => {
|
|
3014
|
+
const move = movesByDestinationKey.get(grapheme.key);
|
|
3015
|
+
if (move !== undefined) {
|
|
3016
|
+
return {
|
|
3017
|
+
...grapheme,
|
|
3018
|
+
kind: "move",
|
|
3019
|
+
fromLeft: move.from.left,
|
|
3020
|
+
fromTop: move.from.top
|
|
3021
|
+
};
|
|
3022
|
+
}
|
|
3023
|
+
return {
|
|
3024
|
+
...grapheme,
|
|
3025
|
+
kind: "enter",
|
|
3026
|
+
fromLeft: null,
|
|
3027
|
+
fromTop: null
|
|
3028
|
+
};
|
|
3029
|
+
}),
|
|
3030
|
+
exitItems
|
|
3031
|
+
};
|
|
3032
|
+
}
|
|
3033
|
+
function sameSnapshot(a, b) {
|
|
3034
|
+
if (a === b) {
|
|
3035
|
+
return true;
|
|
3036
|
+
}
|
|
3037
|
+
if (a.text !== b.text || a.renderText !== b.renderText || a.graphemes.length !== b.graphemes.length) {
|
|
3038
|
+
return false;
|
|
3039
|
+
}
|
|
3040
|
+
if (!nearlyEqual(a.width, b.width, MORPH.geometryEpsilon)) {
|
|
3041
|
+
return false;
|
|
3042
|
+
}
|
|
3043
|
+
if (!nearlyEqual(a.height, b.height, MORPH.geometryEpsilon)) {
|
|
3044
|
+
return false;
|
|
3045
|
+
}
|
|
3046
|
+
for (let index = 0;index < a.graphemes.length; index += 1) {
|
|
3047
|
+
const left = a.graphemes[index];
|
|
3048
|
+
const right = b.graphemes[index];
|
|
3049
|
+
if (left.glyph !== right.glyph || left.key !== right.key) {
|
|
3050
|
+
return false;
|
|
3051
|
+
}
|
|
3052
|
+
if (!nearlyEqual(left.left, right.left, MORPH.geometryEpsilon)) {
|
|
3053
|
+
return false;
|
|
3054
|
+
}
|
|
3055
|
+
if (!nearlyEqual(left.top, right.top, MORPH.geometryEpsilon)) {
|
|
3056
|
+
return false;
|
|
3057
|
+
}
|
|
3058
|
+
if (!nearlyEqual(left.width, right.width, MORPH.geometryEpsilon)) {
|
|
3059
|
+
return false;
|
|
3060
|
+
}
|
|
3061
|
+
if (!nearlyEqual(left.height, right.height, MORPH.geometryEpsilon)) {
|
|
3062
|
+
return false;
|
|
3063
|
+
}
|
|
3064
|
+
}
|
|
3065
|
+
return true;
|
|
3066
|
+
}
|
|
3067
|
+
function sameMeasurement(a, b) {
|
|
3068
|
+
const sameReservedInlineSize = a.reservedInlineSize === null && b.reservedInlineSize === null || a.reservedInlineSize !== null && b.reservedInlineSize !== null && nearlyEqual(a.reservedInlineSize, b.reservedInlineSize, MORPH.geometryEpsilon);
|
|
3069
|
+
const sameFlowInlineSize = a.flowInlineSize === null && b.flowInlineSize === null || a.flowInlineSize !== null && b.flowInlineSize !== null && nearlyEqual(a.flowInlineSize, b.flowInlineSize, MORPH.geometryEpsilon);
|
|
3070
|
+
return sameSnapshot(a.snapshot, b.snapshot) && nearlyEqual(a.layoutInlineSize, b.layoutInlineSize, MORPH.geometryEpsilon) && sameReservedInlineSize && sameFlowInlineSize && nearlyEqual(a.rootOrigin.left, b.rootOrigin.left, MORPH.geometryEpsilon) && nearlyEqual(a.rootOrigin.top, b.rootOrigin.top, MORPH.geometryEpsilon);
|
|
3071
|
+
}
|
|
3072
|
+
function selectMorphLayoutHint(session) {
|
|
3073
|
+
if (session.animating && session.target !== null) {
|
|
3074
|
+
return session.target;
|
|
3075
|
+
}
|
|
3076
|
+
return session.committed;
|
|
3077
|
+
}
|
|
3078
|
+
function decideMorphSessionUpdate({
|
|
3079
|
+
committed,
|
|
3080
|
+
target,
|
|
3081
|
+
animating,
|
|
3082
|
+
nextMeasurement,
|
|
3083
|
+
fontsReady
|
|
3084
|
+
}) {
|
|
3085
|
+
let source = committed;
|
|
3086
|
+
if (animating && target !== null) {
|
|
3087
|
+
source = target;
|
|
3088
|
+
}
|
|
3089
|
+
if (source === null) {
|
|
3090
|
+
return {
|
|
3091
|
+
kind: "commit-static",
|
|
3092
|
+
measurement: nextMeasurement
|
|
3093
|
+
};
|
|
3094
|
+
}
|
|
3095
|
+
if (!fontsReady) {
|
|
3096
|
+
return {
|
|
3097
|
+
kind: "commit-static",
|
|
3098
|
+
measurement: nextMeasurement
|
|
3099
|
+
};
|
|
3100
|
+
}
|
|
3101
|
+
if (animating && target !== null) {
|
|
3102
|
+
if (nextMeasurement.snapshot.renderText === target.snapshot.renderText) {
|
|
3103
|
+
return {
|
|
3104
|
+
kind: "freeze-animating-target",
|
|
3105
|
+
target
|
|
3106
|
+
};
|
|
3107
|
+
}
|
|
3108
|
+
}
|
|
3109
|
+
if (committed !== null) {
|
|
3110
|
+
if (committed.snapshot.renderText === nextMeasurement.snapshot.renderText) {
|
|
3111
|
+
if (sameMeasurement(committed, nextMeasurement)) {
|
|
3112
|
+
return {
|
|
3113
|
+
kind: "commit-static",
|
|
3114
|
+
measurement: committed
|
|
3115
|
+
};
|
|
3116
|
+
}
|
|
3117
|
+
return {
|
|
3118
|
+
kind: "commit-static",
|
|
3119
|
+
measurement: nextMeasurement
|
|
3120
|
+
};
|
|
3121
|
+
}
|
|
3122
|
+
}
|
|
3123
|
+
return {
|
|
3124
|
+
kind: "start-morph",
|
|
3125
|
+
source,
|
|
3126
|
+
target: nextMeasurement
|
|
3127
|
+
};
|
|
2821
3128
|
}
|
|
2822
|
-
function
|
|
2823
|
-
if (measurement
|
|
2824
|
-
return
|
|
3129
|
+
function pinMeasurementToCurrentOrigin(measurement, origin) {
|
|
3130
|
+
if (nearlyEqual(measurement.rootOrigin.left, origin.left, MORPH.geometryEpsilon) && nearlyEqual(measurement.rootOrigin.top, origin.top, MORPH.geometryEpsilon)) {
|
|
3131
|
+
return measurement;
|
|
2825
3132
|
}
|
|
2826
3133
|
return {
|
|
2827
|
-
|
|
2828
|
-
|
|
2829
|
-
|
|
2830
|
-
|
|
2831
|
-
|
|
2832
|
-
deltaTop: roundDebugValue(rootRect.top - measurement.rootOrigin.top)
|
|
3134
|
+
snapshot: measurement.snapshot,
|
|
3135
|
+
layoutInlineSize: measurement.layoutInlineSize,
|
|
3136
|
+
reservedInlineSize: measurement.reservedInlineSize,
|
|
3137
|
+
flowInlineSize: measurement.flowInlineSize,
|
|
3138
|
+
rootOrigin: origin
|
|
2833
3139
|
};
|
|
2834
3140
|
}
|
|
2835
|
-
function
|
|
3141
|
+
function createStaticState(measurement) {
|
|
2836
3142
|
return {
|
|
2837
|
-
|
|
2838
|
-
|
|
2839
|
-
|
|
2840
|
-
snapshotWidthDelta: roundDebugValue(drift.snapshotWidthDelta),
|
|
2841
|
-
snapshotHeightDelta: roundDebugValue(drift.snapshotHeightDelta),
|
|
2842
|
-
maxAbsLeftDelta: roundDebugValue(drift.maxAbsLeftDelta),
|
|
2843
|
-
maxAbsTopDelta: roundDebugValue(drift.maxAbsTopDelta),
|
|
2844
|
-
maxAbsWidthDelta: roundDebugValue(drift.maxAbsWidthDelta),
|
|
2845
|
-
maxAbsHeightDelta: roundDebugValue(drift.maxAbsHeightDelta),
|
|
2846
|
-
mismatches: drift.mismatches.map((mismatch) => ({
|
|
2847
|
-
index: mismatch.index,
|
|
2848
|
-
glyph: mismatch.glyph,
|
|
2849
|
-
leftDelta: roundDebugValue(mismatch.leftDelta),
|
|
2850
|
-
topDelta: roundDebugValue(mismatch.topDelta),
|
|
2851
|
-
widthDelta: roundDebugValue(mismatch.widthDelta),
|
|
2852
|
-
heightDelta: roundDebugValue(mismatch.heightDelta)
|
|
2853
|
-
}))
|
|
3143
|
+
stage: "idle",
|
|
3144
|
+
measurement,
|
|
3145
|
+
plan: null
|
|
2854
3146
|
};
|
|
2855
3147
|
}
|
|
2856
|
-
function
|
|
2857
|
-
|
|
2858
|
-
|
|
2859
|
-
|
|
2860
|
-
if (
|
|
3148
|
+
function areFontsReady() {
|
|
3149
|
+
return document.fonts.status === "loaded";
|
|
3150
|
+
}
|
|
3151
|
+
function cancelTimeline(timeline) {
|
|
3152
|
+
if (timeline.prepareFrame !== null) {
|
|
3153
|
+
cancelAnimationFrame(timeline.prepareFrame);
|
|
3154
|
+
timeline.prepareFrame = null;
|
|
3155
|
+
}
|
|
3156
|
+
if (timeline.animateFrame !== null) {
|
|
3157
|
+
cancelAnimationFrame(timeline.animateFrame);
|
|
3158
|
+
timeline.animateFrame = null;
|
|
3159
|
+
}
|
|
3160
|
+
if (timeline.finalizeTimer !== null) {
|
|
3161
|
+
window.clearTimeout(timeline.finalizeTimer);
|
|
3162
|
+
timeline.finalizeTimer = null;
|
|
3163
|
+
}
|
|
3164
|
+
}
|
|
3165
|
+
function resetMorph(session, timeline, setState) {
|
|
3166
|
+
cancelTimeline(timeline);
|
|
3167
|
+
session.committed = null;
|
|
3168
|
+
session.target = null;
|
|
3169
|
+
session.animating = false;
|
|
3170
|
+
setState(EMPTY_STATE);
|
|
3171
|
+
}
|
|
3172
|
+
function commitStaticMeasurement(session, measurement, setState) {
|
|
3173
|
+
if (!session.animating && session.target === null && session.committed !== null && sameMeasurement(session.committed, measurement)) {
|
|
2861
3174
|
return;
|
|
2862
3175
|
}
|
|
2863
|
-
|
|
2864
|
-
|
|
3176
|
+
session.committed = measurement;
|
|
3177
|
+
session.target = null;
|
|
3178
|
+
session.animating = false;
|
|
3179
|
+
setState((current) => {
|
|
3180
|
+
if (current.stage === "idle" && current.plan === null && current.measurement !== null && sameMeasurement(current.measurement, measurement)) {
|
|
3181
|
+
return current;
|
|
3182
|
+
}
|
|
3183
|
+
return createStaticState(measurement);
|
|
3184
|
+
});
|
|
3185
|
+
}
|
|
3186
|
+
function applyMorphSessionDecision({
|
|
3187
|
+
decision,
|
|
3188
|
+
session,
|
|
3189
|
+
timeline,
|
|
3190
|
+
setState
|
|
3191
|
+
}) {
|
|
3192
|
+
if (decision.kind === "freeze-animating-target") {
|
|
3193
|
+
return decision.target;
|
|
2865
3194
|
}
|
|
2866
|
-
|
|
2867
|
-
|
|
3195
|
+
cancelTimeline(timeline);
|
|
3196
|
+
if (decision.kind === "commit-static") {
|
|
3197
|
+
commitStaticMeasurement(session, decision.measurement, setState);
|
|
3198
|
+
return decision.measurement;
|
|
3199
|
+
}
|
|
3200
|
+
startMorph({
|
|
3201
|
+
source: decision.source,
|
|
3202
|
+
target: decision.target,
|
|
3203
|
+
session,
|
|
3204
|
+
timeline,
|
|
3205
|
+
setState
|
|
3206
|
+
});
|
|
3207
|
+
return decision.target;
|
|
3208
|
+
}
|
|
3209
|
+
function reconcileMorphSessionUpdate({
|
|
3210
|
+
session,
|
|
3211
|
+
timeline,
|
|
3212
|
+
nextMeasurement,
|
|
3213
|
+
fontsReady,
|
|
3214
|
+
setState
|
|
3215
|
+
}) {
|
|
3216
|
+
const decision = decideMorphSessionUpdate({
|
|
3217
|
+
committed: session.committed,
|
|
3218
|
+
target: session.target,
|
|
3219
|
+
animating: session.animating,
|
|
3220
|
+
nextMeasurement,
|
|
3221
|
+
fontsReady
|
|
3222
|
+
});
|
|
3223
|
+
return applyMorphSessionDecision({
|
|
3224
|
+
decision,
|
|
3225
|
+
session,
|
|
3226
|
+
timeline,
|
|
3227
|
+
setState
|
|
3228
|
+
});
|
|
3229
|
+
}
|
|
3230
|
+
function finalizeMorphTransition({
|
|
3231
|
+
session,
|
|
3232
|
+
timeline,
|
|
3233
|
+
measurement,
|
|
3234
|
+
setState
|
|
3235
|
+
}) {
|
|
3236
|
+
cancelTimeline(timeline);
|
|
3237
|
+
commitStaticMeasurement(session, session.target ?? measurement, setState);
|
|
3238
|
+
}
|
|
3239
|
+
function resolvePreparedMeasurementOrigin(measurement, origin) {
|
|
3240
|
+
return pinMeasurementToCurrentOrigin(measurement, origin);
|
|
3241
|
+
}
|
|
3242
|
+
function resolvePreparedPlanVisualBridge(plan, origin) {
|
|
3243
|
+
const offsetX = plan.sourceRootOrigin.left - origin.left;
|
|
3244
|
+
const offsetY = plan.sourceRootOrigin.top - origin.top;
|
|
3245
|
+
if (nearlyEqual(plan.visualBridge.offsetX, offsetX, MORPH.geometryEpsilon) && nearlyEqual(plan.visualBridge.offsetY, offsetY, MORPH.geometryEpsilon)) {
|
|
3246
|
+
return plan;
|
|
2868
3247
|
}
|
|
3248
|
+
return {
|
|
3249
|
+
...plan,
|
|
3250
|
+
visualBridge: {
|
|
3251
|
+
offsetX,
|
|
3252
|
+
offsetY
|
|
3253
|
+
}
|
|
3254
|
+
};
|
|
3255
|
+
}
|
|
3256
|
+
function startMorph({
|
|
3257
|
+
source,
|
|
3258
|
+
target,
|
|
3259
|
+
session,
|
|
3260
|
+
timeline,
|
|
3261
|
+
setState
|
|
3262
|
+
}) {
|
|
3263
|
+
const plan = buildMorphPlan(source, target, ZERO_BRIDGE);
|
|
3264
|
+
session.target = target;
|
|
3265
|
+
session.animating = true;
|
|
3266
|
+
setState({
|
|
3267
|
+
stage: "prepare",
|
|
3268
|
+
measurement: target,
|
|
3269
|
+
plan
|
|
3270
|
+
});
|
|
2869
3271
|
}
|
|
3272
|
+
|
|
3273
|
+
// torph/src/core/layout-observer.ts
|
|
3274
|
+
import { useLayoutEffect, useRef, useState } from "react";
|
|
3275
|
+
var activeMorphMeasurementConsumers = 0;
|
|
3276
|
+
var detachMorphMeasurementInvalidationListeners = null;
|
|
3277
|
+
var morphMeasurementInvalidationSubscribers = new Set;
|
|
2870
3278
|
function parsePx(value) {
|
|
2871
3279
|
const parsed = Number.parseFloat(value);
|
|
2872
3280
|
if (Number.isFinite(parsed)) {
|
|
@@ -2933,41 +3341,16 @@ function sameLayoutContext(a, b) {
|
|
|
2933
3341
|
}
|
|
2934
3342
|
return a.display === b.display && a.direction === b.direction && a.font === b.font && a.fontFeatureSettings === b.fontFeatureSettings && a.fontVariationSettings === b.fontVariationSettings && Math.abs(a.letterSpacingPx - b.letterSpacingPx) < MORPH.geometryEpsilon && Math.abs(a.lineHeightPx - b.lineHeightPx) < MORPH.geometryEpsilon && a.parentDisplay === b.parentDisplay && a.textTransform === b.textTransform && a.whiteSpace === b.whiteSpace && Math.abs(a.width - b.width) < MORPH.geometryEpsilon && Math.abs(a.wordSpacingPx - b.wordSpacingPx) < MORPH.geometryEpsilon;
|
|
2935
3343
|
}
|
|
2936
|
-
function
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
function clearMorphMeasurementCaches() {
|
|
2940
|
-
morphSegmentCache.clear();
|
|
2941
|
-
clearPretextMorphTrustCache();
|
|
2942
|
-
clearPretextMorphCaches();
|
|
2943
|
-
}
|
|
2944
|
-
function bumpMorphMeasurementEpoch() {
|
|
2945
|
-
morphMeasurementEpoch += 1;
|
|
2946
|
-
}
|
|
2947
|
-
function getMorphMeasurementEpoch() {
|
|
2948
|
-
return morphMeasurementEpoch;
|
|
2949
|
-
}
|
|
2950
|
-
function isSingleLineSnapshot(snapshot) {
|
|
2951
|
-
if (snapshot.graphemes.length <= 1) {
|
|
2952
|
-
return true;
|
|
3344
|
+
function notifyMorphMeasurementInvalidationSubscribers() {
|
|
3345
|
+
for (const subscriber of morphMeasurementInvalidationSubscribers) {
|
|
3346
|
+
subscriber();
|
|
2953
3347
|
}
|
|
2954
|
-
const firstTop = snapshot.graphemes[0].top;
|
|
2955
|
-
return snapshot.graphemes.every((grapheme) => nearlyEqual(grapheme.top, firstTop, MORPH.lineGroupingEpsilon));
|
|
2956
3348
|
}
|
|
2957
|
-
function
|
|
2958
|
-
|
|
2959
|
-
|
|
2960
|
-
|
|
2961
|
-
|
|
2962
|
-
let currentTop = snapshot.graphemes[0].top;
|
|
2963
|
-
for (let index = 1;index < snapshot.graphemes.length; index += 1) {
|
|
2964
|
-
const top = snapshot.graphemes[index].top;
|
|
2965
|
-
if (!nearlyEqual(top, currentTop, MORPH.lineGroupingEpsilon)) {
|
|
2966
|
-
currentTop = top;
|
|
2967
|
-
lineCount += 1;
|
|
2968
|
-
}
|
|
2969
|
-
}
|
|
2970
|
-
return lineCount;
|
|
3349
|
+
function subscribeMorphMeasurementInvalidation(subscriber) {
|
|
3350
|
+
morphMeasurementInvalidationSubscribers.add(subscriber);
|
|
3351
|
+
return () => {
|
|
3352
|
+
morphMeasurementInvalidationSubscribers.delete(subscriber);
|
|
3353
|
+
};
|
|
2971
3354
|
}
|
|
2972
3355
|
function acquireMorphMeasurementInvalidationListeners() {
|
|
2973
3356
|
activeMorphMeasurementConsumers += 1;
|
|
@@ -2975,6 +3358,7 @@ function acquireMorphMeasurementInvalidationListeners() {
|
|
|
2975
3358
|
const handleFontChange = () => {
|
|
2976
3359
|
clearMorphMeasurementCaches();
|
|
2977
3360
|
bumpMorphMeasurementEpoch();
|
|
3361
|
+
notifyMorphMeasurementInvalidationSubscribers();
|
|
2978
3362
|
};
|
|
2979
3363
|
document.fonts.ready.then(handleFontChange);
|
|
2980
3364
|
if (typeof document.fonts.addEventListener === "function") {
|
|
@@ -2997,6 +3381,7 @@ function releaseMorphMeasurementInvalidationListeners() {
|
|
|
2997
3381
|
function useObservedLayoutContext(deps) {
|
|
2998
3382
|
const ref = useRef(null);
|
|
2999
3383
|
const [layoutContext, setLayoutContext] = useState(null);
|
|
3384
|
+
const syncLayoutContextRef = useRef(null);
|
|
3000
3385
|
useLayoutEffect(() => {
|
|
3001
3386
|
const node = ref.current;
|
|
3002
3387
|
if (node === null) {
|
|
@@ -3025,9 +3410,15 @@ function useObservedLayoutContext(deps) {
|
|
|
3025
3410
|
const next = readLayoutContext(node, width);
|
|
3026
3411
|
commitLayoutContext(next, refreshMeasurements);
|
|
3027
3412
|
};
|
|
3413
|
+
syncLayoutContextRef.current = syncLayoutContext;
|
|
3028
3414
|
const initialLayoutContext = readLayoutContext(node);
|
|
3029
3415
|
const shouldObserveWrappingWidth = initialLayoutContext.whiteSpace !== "nowrap" && !supportsIntrinsicWidthLock(initialLayoutContext.display, initialLayoutContext.parentDisplay);
|
|
3030
3416
|
commitLayoutContext(initialLayoutContext, true);
|
|
3417
|
+
const unsubscribeInvalidation = subscribeMorphMeasurementInvalidation(() => {
|
|
3418
|
+
syncLayoutContext({
|
|
3419
|
+
refreshMeasurements: true
|
|
3420
|
+
});
|
|
3421
|
+
});
|
|
3031
3422
|
let resizeObserver = null;
|
|
3032
3423
|
if (shouldObserveWrappingWidth) {
|
|
3033
3424
|
resizeObserver = new ResizeObserver(([entry]) => {
|
|
@@ -3040,24 +3431,27 @@ function useObservedLayoutContext(deps) {
|
|
|
3040
3431
|
acquireMorphMeasurementInvalidationListeners();
|
|
3041
3432
|
return () => {
|
|
3042
3433
|
disposed = true;
|
|
3434
|
+
syncLayoutContextRef.current = null;
|
|
3435
|
+
unsubscribeInvalidation();
|
|
3043
3436
|
resizeObserver?.disconnect();
|
|
3044
3437
|
releaseMorphMeasurementInvalidationListeners();
|
|
3045
3438
|
};
|
|
3046
3439
|
}, deps);
|
|
3047
3440
|
return { ref, layoutContext };
|
|
3048
3441
|
}
|
|
3049
|
-
|
|
3050
|
-
|
|
3051
|
-
|
|
3442
|
+
|
|
3443
|
+
// torph/src/core/dom-measurement.ts
|
|
3444
|
+
var domMeasurementService = null;
|
|
3445
|
+
function readFirstTextNode(node) {
|
|
3446
|
+
if (node === null) {
|
|
3447
|
+
return null;
|
|
3052
3448
|
}
|
|
3053
|
-
const
|
|
3054
|
-
|
|
3055
|
-
|
|
3449
|
+
for (const childNode of node.childNodes) {
|
|
3450
|
+
if (childNode.nodeType === Node.TEXT_NODE) {
|
|
3451
|
+
return childNode;
|
|
3452
|
+
}
|
|
3056
3453
|
}
|
|
3057
|
-
|
|
3058
|
-
granularity: "grapheme"
|
|
3059
|
-
});
|
|
3060
|
-
return graphemeSegmenter;
|
|
3454
|
+
return null;
|
|
3061
3455
|
}
|
|
3062
3456
|
function getDomMeasurementService() {
|
|
3063
3457
|
if (domMeasurementService !== null) {
|
|
@@ -3129,51 +3523,6 @@ function applyMeasurementHostStyle({
|
|
|
3129
3523
|
host.style.width = "max-content";
|
|
3130
3524
|
}
|
|
3131
3525
|
}
|
|
3132
|
-
function segmentTorphText(text) {
|
|
3133
|
-
const segments = [];
|
|
3134
|
-
let ordinal = 0;
|
|
3135
|
-
for (const segment of getSegmenter().segment(text)) {
|
|
3136
|
-
segments.push({
|
|
3137
|
-
glyph: segment.segment,
|
|
3138
|
-
key: `${segment.segment}:${ordinal}`
|
|
3139
|
-
});
|
|
3140
|
-
ordinal += 1;
|
|
3141
|
-
}
|
|
3142
|
-
return segments;
|
|
3143
|
-
}
|
|
3144
|
-
function readCachedMorphSegments(text) {
|
|
3145
|
-
const cached = morphSegmentCache.get(text);
|
|
3146
|
-
if (cached !== undefined) {
|
|
3147
|
-
morphSegmentCache.delete(text);
|
|
3148
|
-
morphSegmentCache.set(text, cached);
|
|
3149
|
-
return cached;
|
|
3150
|
-
}
|
|
3151
|
-
const segments = segmentTorphText(text);
|
|
3152
|
-
morphSegmentCache.set(text, segments);
|
|
3153
|
-
if (morphSegmentCache.size > MORPH_SEGMENT_CACHE_LIMIT) {
|
|
3154
|
-
const oldest = morphSegmentCache.keys().next();
|
|
3155
|
-
if (!oldest.done) {
|
|
3156
|
-
morphSegmentCache.delete(oldest.value);
|
|
3157
|
-
}
|
|
3158
|
-
}
|
|
3159
|
-
return segments;
|
|
3160
|
-
}
|
|
3161
|
-
function getDomMeasurementRequestKey(text, renderText, layoutContext, useContentInlineSize) {
|
|
3162
|
-
let inlineSizeMode = "container";
|
|
3163
|
-
if (useContentInlineSize) {
|
|
3164
|
-
inlineSizeMode = "content";
|
|
3165
|
-
}
|
|
3166
|
-
return `dom\x00${inlineSizeMode}\x00${text}\x00${renderText}\x00${layoutContext.measurementVersion}\x00${getMorphMeasurementEpoch()}`;
|
|
3167
|
-
}
|
|
3168
|
-
function needsMeasurementLayer(measurementBackend, renderText) {
|
|
3169
|
-
if (measurementBackend === "pretext") {
|
|
3170
|
-
return false;
|
|
3171
|
-
}
|
|
3172
|
-
return renderText.length > 0;
|
|
3173
|
-
}
|
|
3174
|
-
function canCacheMeasurementLayerSnapshot(measurementBackend) {
|
|
3175
|
-
return measurementBackend === "dom";
|
|
3176
|
-
}
|
|
3177
3526
|
function readCachedMorphSnapshot(cache, cacheKey) {
|
|
3178
3527
|
const cached = cache.get(cacheKey);
|
|
3179
3528
|
if (cached === undefined) {
|
|
@@ -3186,7 +3535,7 @@ function readCachedMorphSnapshot(cache, cacheKey) {
|
|
|
3186
3535
|
function rememberCachedMorphSnapshot(cache, cacheKey, snapshot) {
|
|
3187
3536
|
cache.delete(cacheKey);
|
|
3188
3537
|
cache.set(cacheKey, snapshot);
|
|
3189
|
-
if (cache.size >
|
|
3538
|
+
if (cache.size > 8) {
|
|
3190
3539
|
const oldest = cache.keys().next();
|
|
3191
3540
|
if (!oldest.done) {
|
|
3192
3541
|
cache.delete(oldest.value);
|
|
@@ -3267,65 +3616,27 @@ function measureMorphSnapshotWithDomService({
|
|
|
3267
3616
|
useContentInlineSize
|
|
3268
3617
|
}) {
|
|
3269
3618
|
if (renderText.length === 0) {
|
|
3270
|
-
return {
|
|
3271
|
-
text,
|
|
3272
|
-
renderText,
|
|
3273
|
-
width: 0,
|
|
3274
|
-
height: 0,
|
|
3275
|
-
graphemes: []
|
|
3276
|
-
};
|
|
3277
|
-
}
|
|
3278
|
-
const service = getDomMeasurementService();
|
|
3279
|
-
applyMeasurementHostStyle({
|
|
3280
|
-
host: service.host,
|
|
3281
|
-
root,
|
|
3282
|
-
layoutContext,
|
|
3283
|
-
useContentInlineSize
|
|
3284
|
-
});
|
|
3285
|
-
service.host.textContent = renderText;
|
|
3286
|
-
return measureMorphSnapshotFromLayer(text, renderText, segments, service.host);
|
|
3287
|
-
}
|
|
3288
|
-
function readRootOrigin(node) {
|
|
3289
|
-
const rect = node.getBoundingClientRect();
|
|
3290
|
-
return { left: rect.left, top: rect.top };
|
|
3291
|
-
}
|
|
3292
|
-
function readFlowInlineSize(node) {
|
|
3293
|
-
if (node === null) {
|
|
3294
|
-
return null;
|
|
3295
|
-
}
|
|
3296
|
-
return node.getBoundingClientRect().width;
|
|
3297
|
-
}
|
|
3298
|
-
function readFlowLineCount(node) {
|
|
3299
|
-
if (node === null) {
|
|
3300
|
-
return null;
|
|
3301
|
-
}
|
|
3302
|
-
const rects = Array.from(node.getClientRects());
|
|
3303
|
-
if (rects.length === 0) {
|
|
3304
|
-
if ((node.textContent ?? "").length === 0) {
|
|
3305
|
-
return 0;
|
|
3306
|
-
}
|
|
3307
|
-
return 1;
|
|
3308
|
-
}
|
|
3309
|
-
let lineCount = 0;
|
|
3310
|
-
let currentTop = null;
|
|
3311
|
-
for (const rect of rects) {
|
|
3312
|
-
if (currentTop === null || !nearlyEqual(rect.top, currentTop, MORPH.lineGroupingEpsilon)) {
|
|
3313
|
-
currentTop = rect.top;
|
|
3314
|
-
lineCount += 1;
|
|
3315
|
-
}
|
|
3316
|
-
}
|
|
3317
|
-
return lineCount;
|
|
3318
|
-
}
|
|
3319
|
-
function readFirstTextNode(node) {
|
|
3320
|
-
if (node === null) {
|
|
3321
|
-
return null;
|
|
3322
|
-
}
|
|
3323
|
-
for (const childNode of node.childNodes) {
|
|
3324
|
-
if (childNode.nodeType === Node.TEXT_NODE) {
|
|
3325
|
-
return childNode;
|
|
3326
|
-
}
|
|
3619
|
+
return {
|
|
3620
|
+
text,
|
|
3621
|
+
renderText,
|
|
3622
|
+
width: 0,
|
|
3623
|
+
height: 0,
|
|
3624
|
+
graphemes: []
|
|
3625
|
+
};
|
|
3327
3626
|
}
|
|
3328
|
-
|
|
3627
|
+
const service = getDomMeasurementService();
|
|
3628
|
+
applyMeasurementHostStyle({
|
|
3629
|
+
host: service.host,
|
|
3630
|
+
root,
|
|
3631
|
+
layoutContext,
|
|
3632
|
+
useContentInlineSize
|
|
3633
|
+
});
|
|
3634
|
+
service.host.textContent = renderText;
|
|
3635
|
+
return measureMorphSnapshotFromLayer(text, renderText, segments, service.host);
|
|
3636
|
+
}
|
|
3637
|
+
function readRootOrigin(node) {
|
|
3638
|
+
const rect = node.getBoundingClientRect();
|
|
3639
|
+
return { left: rect.left, top: rect.top };
|
|
3329
3640
|
}
|
|
3330
3641
|
function measureLiveFlowSnapshot(root, flowTextNode) {
|
|
3331
3642
|
const textNode = readFirstTextNode(flowTextNode);
|
|
@@ -3458,141 +3769,6 @@ function measureOverlayBoxSnapshot(root, overlayRoot, role) {
|
|
|
3458
3769
|
graphemes
|
|
3459
3770
|
};
|
|
3460
3771
|
}
|
|
3461
|
-
function getTrustedPretextMeasurementBackend(text, renderText, layoutContext, useContentInlineSize) {
|
|
3462
|
-
const backend = getPretextMorphMeasurementBackend(text, layoutContext);
|
|
3463
|
-
if (backend !== "probe") {
|
|
3464
|
-
return backend;
|
|
3465
|
-
}
|
|
3466
|
-
const signature = getPretextMorphTrustSignature({
|
|
3467
|
-
renderText,
|
|
3468
|
-
layoutContext,
|
|
3469
|
-
useContentInlineSize
|
|
3470
|
-
});
|
|
3471
|
-
if (signature === null) {
|
|
3472
|
-
return "dom";
|
|
3473
|
-
}
|
|
3474
|
-
const trusted = pretextMorphTrustCache.get(signature);
|
|
3475
|
-
if (trusted === undefined) {
|
|
3476
|
-
return "probe";
|
|
3477
|
-
}
|
|
3478
|
-
if (trusted) {
|
|
3479
|
-
return "pretext";
|
|
3480
|
-
}
|
|
3481
|
-
return "dom";
|
|
3482
|
-
}
|
|
3483
|
-
function resolveContentWidthLockInlineSize(layoutHint) {
|
|
3484
|
-
if (layoutHint.flowInlineSize !== null) {
|
|
3485
|
-
return layoutHint.flowInlineSize;
|
|
3486
|
-
}
|
|
3487
|
-
return layoutHint.snapshot.width;
|
|
3488
|
-
}
|
|
3489
|
-
function shouldMeasureUsingContentInlineSize(layoutContext, layoutHint) {
|
|
3490
|
-
if (supportsIntrinsicWidthLock(layoutContext.display, layoutContext.parentDisplay)) {
|
|
3491
|
-
return true;
|
|
3492
|
-
}
|
|
3493
|
-
if (layoutContext.whiteSpace === "nowrap") {
|
|
3494
|
-
return true;
|
|
3495
|
-
}
|
|
3496
|
-
if (layoutHint === null || !isSingleLineSnapshot(layoutHint.snapshot)) {
|
|
3497
|
-
return false;
|
|
3498
|
-
}
|
|
3499
|
-
return nearlyEqual(layoutHint.layoutInlineSize, resolveContentWidthLockInlineSize(layoutHint), MORPH.contentWidthLockEpsilon);
|
|
3500
|
-
}
|
|
3501
|
-
function shouldHealIdleMeasurementFromFlow(measurement, flowLineCount) {
|
|
3502
|
-
if (flowLineCount !== 1) {
|
|
3503
|
-
return false;
|
|
3504
|
-
}
|
|
3505
|
-
return countSnapshotLines(measurement.snapshot) > 1;
|
|
3506
|
-
}
|
|
3507
|
-
function refineMeasurementWithLiveGeometry(measurement, liveGeometry) {
|
|
3508
|
-
const sameFlowInlineSize = measurement.flowInlineSize === null && liveGeometry.flowInlineSize === null || measurement.flowInlineSize !== null && liveGeometry.flowInlineSize !== null && nearlyEqual(measurement.flowInlineSize, liveGeometry.flowInlineSize);
|
|
3509
|
-
if (sameFlowInlineSize && nearlyEqual(measurement.rootOrigin.left, liveGeometry.rootOrigin.left) && nearlyEqual(measurement.rootOrigin.top, liveGeometry.rootOrigin.top)) {
|
|
3510
|
-
return measurement;
|
|
3511
|
-
}
|
|
3512
|
-
return {
|
|
3513
|
-
snapshot: measurement.snapshot,
|
|
3514
|
-
layoutInlineSize: measurement.layoutInlineSize,
|
|
3515
|
-
reservedInlineSize: measurement.reservedInlineSize,
|
|
3516
|
-
flowInlineSize: liveGeometry.flowInlineSize,
|
|
3517
|
-
rootOrigin: liveGeometry.rootOrigin
|
|
3518
|
-
};
|
|
3519
|
-
}
|
|
3520
|
-
function refineMeasurementFromLiveNodes(measurement, root, flowTextNode) {
|
|
3521
|
-
if (root === null) {
|
|
3522
|
-
return measurement;
|
|
3523
|
-
}
|
|
3524
|
-
return refineMeasurementWithLiveGeometry(measurement, {
|
|
3525
|
-
flowInlineSize: readFlowInlineSize(flowTextNode),
|
|
3526
|
-
rootOrigin: readRootOrigin(root)
|
|
3527
|
-
});
|
|
3528
|
-
}
|
|
3529
|
-
function createMorphMeasurementRequest({
|
|
3530
|
-
text,
|
|
3531
|
-
layoutContext,
|
|
3532
|
-
layoutHint,
|
|
3533
|
-
forceContentInlineSize = false
|
|
3534
|
-
}) {
|
|
3535
|
-
if (layoutContext === null) {
|
|
3536
|
-
return null;
|
|
3537
|
-
}
|
|
3538
|
-
const renderText = getPretextMorphRenderedText(text, layoutContext);
|
|
3539
|
-
let useContentInlineSize = shouldMeasureUsingContentInlineSize(layoutContext, layoutHint);
|
|
3540
|
-
if (forceContentInlineSize) {
|
|
3541
|
-
useContentInlineSize = true;
|
|
3542
|
-
}
|
|
3543
|
-
const measurementBackend = getTrustedPretextMeasurementBackend(text, renderText, layoutContext, useContentInlineSize);
|
|
3544
|
-
let segments = readCachedMorphSegments(renderText);
|
|
3545
|
-
if (measurementBackend === "pretext") {
|
|
3546
|
-
segments = EMPTY_SEGMENTS;
|
|
3547
|
-
}
|
|
3548
|
-
let domMeasurementKey = null;
|
|
3549
|
-
if (needsMeasurementLayer(measurementBackend, renderText)) {
|
|
3550
|
-
domMeasurementKey = getDomMeasurementRequestKey(text, renderText, layoutContext, useContentInlineSize);
|
|
3551
|
-
}
|
|
3552
|
-
return {
|
|
3553
|
-
text,
|
|
3554
|
-
renderText,
|
|
3555
|
-
segments,
|
|
3556
|
-
measurementBackend,
|
|
3557
|
-
useContentInlineSize,
|
|
3558
|
-
domMeasurementKey
|
|
3559
|
-
};
|
|
3560
|
-
}
|
|
3561
|
-
function rememberPretextMeasurementTrust({
|
|
3562
|
-
renderText,
|
|
3563
|
-
layoutContext,
|
|
3564
|
-
useContentInlineSize,
|
|
3565
|
-
trusted
|
|
3566
|
-
}) {
|
|
3567
|
-
const signature = getPretextMorphTrustSignature({
|
|
3568
|
-
renderText,
|
|
3569
|
-
layoutContext,
|
|
3570
|
-
useContentInlineSize
|
|
3571
|
-
});
|
|
3572
|
-
if (signature === null) {
|
|
3573
|
-
return;
|
|
3574
|
-
}
|
|
3575
|
-
pretextMorphTrustCache.set(signature, trusted);
|
|
3576
|
-
}
|
|
3577
|
-
function areSnapshotsEquivalentForPretextTrust(left, right) {
|
|
3578
|
-
if (left.renderText !== right.renderText || left.graphemes.length !== right.graphemes.length) {
|
|
3579
|
-
return false;
|
|
3580
|
-
}
|
|
3581
|
-
if (Math.abs(left.width - right.width) > MORPH.geometryEpsilon || Math.abs(left.height - right.height) > MORPH.geometryEpsilon) {
|
|
3582
|
-
return false;
|
|
3583
|
-
}
|
|
3584
|
-
for (let index = 0;index < left.graphemes.length; index += 1) {
|
|
3585
|
-
const from = left.graphemes[index];
|
|
3586
|
-
const to = right.graphemes[index];
|
|
3587
|
-
if (from.glyph !== to.glyph) {
|
|
3588
|
-
return false;
|
|
3589
|
-
}
|
|
3590
|
-
if (Math.abs(from.left - to.left) > MORPH.geometryEpsilon || Math.abs(from.top - to.top) > MORPH.geometryEpsilon || Math.abs(from.width - to.width) > MORPH.geometryEpsilon || Math.abs(from.height - to.height) > MORPH.geometryEpsilon) {
|
|
3591
|
-
return false;
|
|
3592
|
-
}
|
|
3593
|
-
}
|
|
3594
|
-
return true;
|
|
3595
|
-
}
|
|
3596
3772
|
function measureFromNodes({
|
|
3597
3773
|
root,
|
|
3598
3774
|
layoutContext,
|
|
@@ -3612,7 +3788,7 @@ function measureFromNodes({
|
|
|
3612
3788
|
width: Number.MAX_SAFE_INTEGER / 4
|
|
3613
3789
|
};
|
|
3614
3790
|
}
|
|
3615
|
-
const snapshot = snapshotOverride ?? (() => {
|
|
3791
|
+
const snapshot = assertSingleLineSnapshot(snapshotOverride ?? (() => {
|
|
3616
3792
|
let pretextSnapshot = null;
|
|
3617
3793
|
if (measurementBackend !== "dom") {
|
|
3618
3794
|
pretextSnapshot = measureMorphSnapshotWithPretext(text, measurementLayoutContext);
|
|
@@ -3649,294 +3825,378 @@ function measureFromNodes({
|
|
|
3649
3825
|
if (resolvedSnapshot === null) {
|
|
3650
3826
|
throw new Error("Torph failed to resolve a measurement snapshot.");
|
|
3651
3827
|
}
|
|
3652
|
-
return resolvedSnapshot;
|
|
3653
|
-
})();
|
|
3654
|
-
let layoutInlineSize = layoutContext.width;
|
|
3655
|
-
if (useContentInlineSize) {
|
|
3656
|
-
layoutInlineSize = snapshot.width;
|
|
3828
|
+
return resolvedSnapshot;
|
|
3829
|
+
})());
|
|
3830
|
+
let layoutInlineSize = layoutContext.width;
|
|
3831
|
+
if (useContentInlineSize) {
|
|
3832
|
+
layoutInlineSize = snapshot.width;
|
|
3833
|
+
}
|
|
3834
|
+
let reservedInlineSize = null;
|
|
3835
|
+
if (supportsIntrinsicWidthLock(layoutContext.display, layoutContext.parentDisplay)) {
|
|
3836
|
+
reservedInlineSize = snapshot.width;
|
|
3837
|
+
}
|
|
3838
|
+
let flowInlineSize = null;
|
|
3839
|
+
if (useContentInlineSize) {
|
|
3840
|
+
flowInlineSize = snapshot.width;
|
|
3841
|
+
}
|
|
3842
|
+
return {
|
|
3843
|
+
snapshot,
|
|
3844
|
+
layoutInlineSize,
|
|
3845
|
+
reservedInlineSize,
|
|
3846
|
+
flowInlineSize,
|
|
3847
|
+
rootOrigin: readRootOrigin(root)
|
|
3848
|
+
};
|
|
3849
|
+
}
|
|
3850
|
+
|
|
3851
|
+
// torph/src/debug/trace.ts
|
|
3852
|
+
var TORPH_TRACE_MAX_BYTES = 4 * 1024 * 1024;
|
|
3853
|
+
var TORPH_TRACE_MAX_LINES = 4000;
|
|
3854
|
+
var TORPH_TRACE_SCHEMA_VERSION = 7;
|
|
3855
|
+
var DEFAULT_TORPH_DEBUG_CONFIG = {
|
|
3856
|
+
capture: false,
|
|
3857
|
+
console: false
|
|
3858
|
+
};
|
|
3859
|
+
var torphDebugInstanceOrdinal = 0;
|
|
3860
|
+
function nextTorphDebugInstanceId() {
|
|
3861
|
+
torphDebugInstanceOrdinal += 1;
|
|
3862
|
+
return torphDebugInstanceOrdinal;
|
|
3863
|
+
}
|
|
3864
|
+
function readTorphDebugConfig() {
|
|
3865
|
+
const scope = globalThis;
|
|
3866
|
+
return scope.__TORPH_DEBUG__ ?? DEFAULT_TORPH_DEBUG_CONFIG;
|
|
3867
|
+
}
|
|
3868
|
+
function shouldCaptureTorphTrace(config) {
|
|
3869
|
+
if (config === null) {
|
|
3870
|
+
return false;
|
|
3871
|
+
}
|
|
3872
|
+
if (typeof config === "boolean") {
|
|
3873
|
+
return config;
|
|
3874
|
+
}
|
|
3875
|
+
if (config.capture === true) {
|
|
3876
|
+
return true;
|
|
3877
|
+
}
|
|
3878
|
+
return false;
|
|
3879
|
+
}
|
|
3880
|
+
function isTorphDebugEnabled(config) {
|
|
3881
|
+
if (config === null) {
|
|
3882
|
+
return false;
|
|
3883
|
+
}
|
|
3884
|
+
if (typeof config === "boolean") {
|
|
3885
|
+
return config;
|
|
3886
|
+
}
|
|
3887
|
+
if (config.console !== undefined) {
|
|
3888
|
+
return config.console;
|
|
3889
|
+
}
|
|
3890
|
+
if (config.enabled === true) {
|
|
3891
|
+
return true;
|
|
3892
|
+
}
|
|
3893
|
+
return false;
|
|
3894
|
+
}
|
|
3895
|
+
function shouldRunTorphInstrumentation(config) {
|
|
3896
|
+
if (shouldCaptureTorphTrace(config)) {
|
|
3897
|
+
return true;
|
|
3898
|
+
}
|
|
3899
|
+
return isTorphDebugEnabled(config);
|
|
3900
|
+
}
|
|
3901
|
+
function getTorphTraceStore() {
|
|
3902
|
+
const scope = globalThis;
|
|
3903
|
+
let store = scope.__TORPH_TRACE_STORE__;
|
|
3904
|
+
if (store !== undefined) {
|
|
3905
|
+
return store;
|
|
3906
|
+
}
|
|
3907
|
+
store = {
|
|
3908
|
+
lines: [],
|
|
3909
|
+
nextSeq: 1,
|
|
3910
|
+
totalBytes: 0
|
|
3911
|
+
};
|
|
3912
|
+
scope.__TORPH_TRACE_STORE__ = store;
|
|
3913
|
+
return store;
|
|
3914
|
+
}
|
|
3915
|
+
function getTorphTraceText() {
|
|
3916
|
+
return getTorphTraceStore().lines.join("");
|
|
3917
|
+
}
|
|
3918
|
+
function clearTorphTrace() {
|
|
3919
|
+
const store = getTorphTraceStore();
|
|
3920
|
+
store.lines = [];
|
|
3921
|
+
store.nextSeq = 1;
|
|
3922
|
+
store.totalBytes = 0;
|
|
3923
|
+
}
|
|
3924
|
+
function downloadTorphTrace(filename) {
|
|
3925
|
+
if (typeof document === "undefined") {
|
|
3926
|
+
return null;
|
|
3927
|
+
}
|
|
3928
|
+
const text = getTorphTraceText();
|
|
3929
|
+
const blob = new Blob([text], { type: "application/x-ndjson;charset=utf-8" });
|
|
3930
|
+
const href = URL.createObjectURL(blob);
|
|
3931
|
+
const anchor = document.createElement("a");
|
|
3932
|
+
let resolvedFilename = filename;
|
|
3933
|
+
if (resolvedFilename === undefined) {
|
|
3934
|
+
resolvedFilename = `torph-trace-${new Date().toISOString().replaceAll(":", "-")}.jsonl`;
|
|
3935
|
+
}
|
|
3936
|
+
anchor.href = href;
|
|
3937
|
+
anchor.download = resolvedFilename;
|
|
3938
|
+
anchor.click();
|
|
3939
|
+
window.setTimeout(() => {
|
|
3940
|
+
URL.revokeObjectURL(href);
|
|
3941
|
+
}, 0);
|
|
3942
|
+
return resolvedFilename;
|
|
3943
|
+
}
|
|
3944
|
+
function ensureTorphTraceApi() {
|
|
3945
|
+
const scope = globalThis;
|
|
3946
|
+
if (scope.__TORPH_TRACE__ !== undefined) {
|
|
3947
|
+
return scope.__TORPH_TRACE__;
|
|
3948
|
+
}
|
|
3949
|
+
const api = {
|
|
3950
|
+
clear: clearTorphTrace,
|
|
3951
|
+
count: () => getTorphTraceStore().lines.length,
|
|
3952
|
+
download: downloadTorphTrace,
|
|
3953
|
+
text: getTorphTraceText
|
|
3954
|
+
};
|
|
3955
|
+
scope.__TORPH_TRACE__ = api;
|
|
3956
|
+
return api;
|
|
3957
|
+
}
|
|
3958
|
+
function appendTorphTrace(instanceId, event, payload) {
|
|
3959
|
+
ensureTorphTraceApi();
|
|
3960
|
+
const store = getTorphTraceStore();
|
|
3961
|
+
const entry = {
|
|
3962
|
+
instanceId,
|
|
3963
|
+
event,
|
|
3964
|
+
payload,
|
|
3965
|
+
seq: store.nextSeq,
|
|
3966
|
+
time: new Date().toISOString()
|
|
3967
|
+
};
|
|
3968
|
+
store.nextSeq += 1;
|
|
3969
|
+
const line = `${JSON.stringify(entry)}
|
|
3970
|
+
`;
|
|
3971
|
+
store.lines.push(line);
|
|
3972
|
+
store.totalBytes += line.length;
|
|
3973
|
+
while (store.lines.length > TORPH_TRACE_MAX_LINES || store.totalBytes > TORPH_TRACE_MAX_BYTES) {
|
|
3974
|
+
const removed = store.lines.shift();
|
|
3975
|
+
if (removed === undefined) {
|
|
3976
|
+
break;
|
|
3977
|
+
}
|
|
3978
|
+
store.totalBytes = Math.max(0, store.totalBytes - removed.length);
|
|
3657
3979
|
}
|
|
3658
|
-
|
|
3659
|
-
|
|
3660
|
-
|
|
3980
|
+
}
|
|
3981
|
+
function roundDebugValue(value) {
|
|
3982
|
+
if (value === null || value === undefined) {
|
|
3983
|
+
return value;
|
|
3661
3984
|
}
|
|
3662
|
-
return
|
|
3663
|
-
snapshot,
|
|
3664
|
-
layoutInlineSize,
|
|
3665
|
-
reservedInlineSize,
|
|
3666
|
-
flowInlineSize: null,
|
|
3667
|
-
rootOrigin: readRootOrigin(root)
|
|
3668
|
-
};
|
|
3985
|
+
return Math.round(value * 1e4) / 1e4;
|
|
3669
3986
|
}
|
|
3670
|
-
function
|
|
3671
|
-
if (
|
|
3672
|
-
return
|
|
3987
|
+
function summarizeDebugSnapshot(snapshot) {
|
|
3988
|
+
if (snapshot === null) {
|
|
3989
|
+
return null;
|
|
3673
3990
|
}
|
|
3674
3991
|
return {
|
|
3675
|
-
|
|
3676
|
-
|
|
3677
|
-
|
|
3678
|
-
|
|
3679
|
-
|
|
3992
|
+
text: snapshot.text,
|
|
3993
|
+
renderText: snapshot.renderText,
|
|
3994
|
+
width: roundDebugValue(snapshot.width),
|
|
3995
|
+
height: roundDebugValue(snapshot.height),
|
|
3996
|
+
graphemes: snapshot.graphemes.length
|
|
3680
3997
|
};
|
|
3681
3998
|
}
|
|
3682
|
-
function
|
|
3683
|
-
|
|
3684
|
-
|
|
3685
|
-
const bucket = buckets.get(grapheme.glyph);
|
|
3686
|
-
if (bucket) {
|
|
3687
|
-
bucket.push(grapheme);
|
|
3688
|
-
} else {
|
|
3689
|
-
buckets.set(grapheme.glyph, [grapheme]);
|
|
3690
|
-
}
|
|
3999
|
+
function summarizeDebugGlyphs(snapshot) {
|
|
4000
|
+
if (snapshot === null) {
|
|
4001
|
+
return null;
|
|
3691
4002
|
}
|
|
3692
|
-
return
|
|
4003
|
+
return snapshot.graphemes.map((grapheme, index) => ({
|
|
4004
|
+
index,
|
|
4005
|
+
glyph: grapheme.glyph,
|
|
4006
|
+
key: grapheme.key,
|
|
4007
|
+
left: roundDebugValue(grapheme.left),
|
|
4008
|
+
top: roundDebugValue(grapheme.top),
|
|
4009
|
+
width: roundDebugValue(grapheme.width),
|
|
4010
|
+
height: roundDebugValue(grapheme.height)
|
|
4011
|
+
}));
|
|
3693
4012
|
}
|
|
3694
|
-
function
|
|
3695
|
-
|
|
3696
|
-
|
|
3697
|
-
const pairings = [];
|
|
3698
|
-
for (const [glyph, previousItems] of previousBuckets) {
|
|
3699
|
-
const nextItems = nextBuckets.get(glyph) ?? [];
|
|
3700
|
-
const shared = Math.min(previousItems.length, nextItems.length);
|
|
3701
|
-
for (let index = 0;index < shared; index += 1) {
|
|
3702
|
-
pairings.push({
|
|
3703
|
-
kind: "move",
|
|
3704
|
-
from: previousItems[index],
|
|
3705
|
-
to: nextItems[index]
|
|
3706
|
-
});
|
|
3707
|
-
}
|
|
3708
|
-
for (let index = shared;index < previousItems.length; index += 1) {
|
|
3709
|
-
pairings.push({
|
|
3710
|
-
kind: "exit",
|
|
3711
|
-
from: previousItems[index]
|
|
3712
|
-
});
|
|
3713
|
-
}
|
|
3714
|
-
}
|
|
3715
|
-
for (const [glyph, nextItems] of nextBuckets) {
|
|
3716
|
-
const previousItems = previousBuckets.get(glyph) ?? [];
|
|
3717
|
-
const shared = Math.min(previousItems.length, nextItems.length);
|
|
3718
|
-
for (let index = shared;index < nextItems.length; index += 1) {
|
|
3719
|
-
pairings.push({
|
|
3720
|
-
kind: "enter",
|
|
3721
|
-
to: nextItems[index]
|
|
3722
|
-
});
|
|
3723
|
-
}
|
|
4013
|
+
function summarizeDebugMeasurement(measurement) {
|
|
4014
|
+
if (measurement === null) {
|
|
4015
|
+
return null;
|
|
3724
4016
|
}
|
|
3725
|
-
return pairings;
|
|
3726
|
-
}
|
|
3727
|
-
function resolveMorphFrameBounds(previous, next) {
|
|
3728
4017
|
return {
|
|
3729
|
-
|
|
3730
|
-
|
|
4018
|
+
layoutInlineSize: roundDebugValue(measurement.layoutInlineSize),
|
|
4019
|
+
reservedInlineSize: roundDebugValue(measurement.reservedInlineSize),
|
|
4020
|
+
flowInlineSize: roundDebugValue(measurement.flowInlineSize),
|
|
4021
|
+
rootOrigin: {
|
|
4022
|
+
left: roundDebugValue(measurement.rootOrigin.left),
|
|
4023
|
+
top: roundDebugValue(measurement.rootOrigin.top)
|
|
4024
|
+
},
|
|
4025
|
+
snapshot: summarizeDebugSnapshot(measurement.snapshot)
|
|
3731
4026
|
};
|
|
3732
4027
|
}
|
|
3733
|
-
function
|
|
4028
|
+
function summarizeDebugLayoutContext(layoutContext) {
|
|
4029
|
+
if (layoutContext === null) {
|
|
4030
|
+
return null;
|
|
4031
|
+
}
|
|
3734
4032
|
return {
|
|
3735
|
-
|
|
3736
|
-
|
|
4033
|
+
display: layoutContext.display,
|
|
4034
|
+
parentDisplay: layoutContext.parentDisplay,
|
|
4035
|
+
whiteSpace: layoutContext.whiteSpace,
|
|
4036
|
+
width: roundDebugValue(layoutContext.width),
|
|
4037
|
+
measurementVersion: layoutContext.measurementVersion
|
|
3737
4038
|
};
|
|
3738
4039
|
}
|
|
3739
|
-
function
|
|
3740
|
-
|
|
3741
|
-
|
|
3742
|
-
const exitItems = [];
|
|
3743
|
-
for (const pairing of pairings) {
|
|
3744
|
-
if (pairing.kind === "move") {
|
|
3745
|
-
movesByDestinationKey.set(pairing.to.key, pairing);
|
|
3746
|
-
continue;
|
|
3747
|
-
}
|
|
3748
|
-
if (pairing.kind === "exit") {
|
|
3749
|
-
exitItems.push(pairing.from);
|
|
3750
|
-
}
|
|
4040
|
+
function summarizeDebugRect(rect) {
|
|
4041
|
+
if (rect === null) {
|
|
4042
|
+
return null;
|
|
3751
4043
|
}
|
|
3752
|
-
const frame = resolveMorphFrameBounds(previous.snapshot, next.snapshot);
|
|
3753
4044
|
return {
|
|
3754
|
-
|
|
3755
|
-
|
|
3756
|
-
|
|
3757
|
-
|
|
3758
|
-
sourceRenderText: previous.snapshot.renderText,
|
|
3759
|
-
targetRenderText: next.snapshot.renderText,
|
|
3760
|
-
visualBridge,
|
|
3761
|
-
liveItems: next.snapshot.graphemes.map((grapheme) => {
|
|
3762
|
-
const move = movesByDestinationKey.get(grapheme.key);
|
|
3763
|
-
if (move) {
|
|
3764
|
-
return {
|
|
3765
|
-
...grapheme,
|
|
3766
|
-
kind: "move",
|
|
3767
|
-
fromLeft: move.from.left,
|
|
3768
|
-
fromTop: move.from.top
|
|
3769
|
-
};
|
|
3770
|
-
}
|
|
3771
|
-
return {
|
|
3772
|
-
...grapheme,
|
|
3773
|
-
kind: "enter",
|
|
3774
|
-
fromLeft: null,
|
|
3775
|
-
fromTop: null
|
|
3776
|
-
};
|
|
3777
|
-
}),
|
|
3778
|
-
exitItems
|
|
4045
|
+
left: roundDebugValue(rect.left),
|
|
4046
|
+
top: roundDebugValue(rect.top),
|
|
4047
|
+
width: roundDebugValue(rect.width),
|
|
4048
|
+
height: roundDebugValue(rect.height)
|
|
3779
4049
|
};
|
|
3780
4050
|
}
|
|
3781
|
-
function
|
|
3782
|
-
|
|
3783
|
-
|
|
3784
|
-
|
|
3785
|
-
if (a === b) {
|
|
3786
|
-
return true;
|
|
3787
|
-
}
|
|
3788
|
-
if (a.text !== b.text || a.renderText !== b.renderText || a.graphemes.length !== b.graphemes.length) {
|
|
3789
|
-
return false;
|
|
4051
|
+
function collectDebugAnchorIndices(length) {
|
|
4052
|
+
const indices = new Set;
|
|
4053
|
+
if (length <= 0) {
|
|
4054
|
+
return [];
|
|
3790
4055
|
}
|
|
3791
|
-
|
|
3792
|
-
|
|
4056
|
+
indices.add(0);
|
|
4057
|
+
if (length > 1) {
|
|
4058
|
+
indices.add(1);
|
|
4059
|
+
indices.add(length - 2);
|
|
3793
4060
|
}
|
|
3794
|
-
|
|
3795
|
-
|
|
3796
|
-
const right = b.graphemes[index];
|
|
3797
|
-
if (left.glyph !== right.glyph || left.key !== right.key) {
|
|
3798
|
-
return false;
|
|
3799
|
-
}
|
|
3800
|
-
if (!nearlyEqual(left.left, right.left) || !nearlyEqual(left.top, right.top) || !nearlyEqual(left.width, right.width) || !nearlyEqual(left.height, right.height)) {
|
|
3801
|
-
return false;
|
|
3802
|
-
}
|
|
4061
|
+
if (length > 2) {
|
|
4062
|
+
indices.add(Math.floor((length - 1) / 2));
|
|
3803
4063
|
}
|
|
3804
|
-
|
|
4064
|
+
indices.add(length - 1);
|
|
4065
|
+
return Array.from(indices).sort((left, right) => left - right);
|
|
3805
4066
|
}
|
|
3806
|
-
function
|
|
3807
|
-
if (
|
|
3808
|
-
return
|
|
4067
|
+
function summarizeDebugViewportAnchors(snapshot, rootRect) {
|
|
4068
|
+
if (snapshot === null || rootRect === null) {
|
|
4069
|
+
return null;
|
|
3809
4070
|
}
|
|
3810
|
-
|
|
3811
|
-
|
|
3812
|
-
|
|
3813
|
-
|
|
3814
|
-
|
|
4071
|
+
const anchors = [];
|
|
4072
|
+
const anchorIndices = collectDebugAnchorIndices(snapshot.graphemes.length);
|
|
4073
|
+
for (const index of anchorIndices) {
|
|
4074
|
+
const grapheme = snapshot.graphemes[index];
|
|
4075
|
+
if (grapheme === undefined) {
|
|
4076
|
+
continue;
|
|
4077
|
+
}
|
|
4078
|
+
anchors.push({
|
|
4079
|
+
index,
|
|
4080
|
+
glyph: grapheme.glyph,
|
|
4081
|
+
left: roundDebugValue(rootRect.left + grapheme.left),
|
|
4082
|
+
top: roundDebugValue(rootRect.top + grapheme.top),
|
|
4083
|
+
width: roundDebugValue(grapheme.width),
|
|
4084
|
+
height: roundDebugValue(grapheme.height)
|
|
4085
|
+
});
|
|
3815
4086
|
}
|
|
3816
|
-
return
|
|
3817
|
-
snapshot: activeTarget.snapshot,
|
|
3818
|
-
layoutInlineSize: measurement.layoutInlineSize,
|
|
3819
|
-
reservedInlineSize: measurement.reservedInlineSize,
|
|
3820
|
-
flowInlineSize: activeTarget.flowInlineSize,
|
|
3821
|
-
rootOrigin: measurement.rootOrigin
|
|
3822
|
-
};
|
|
4087
|
+
return anchors;
|
|
3823
4088
|
}
|
|
3824
|
-
function
|
|
3825
|
-
if (
|
|
3826
|
-
return
|
|
4089
|
+
function summarizeDebugRootOriginDrift(measurement, rootRect) {
|
|
4090
|
+
if (measurement === null || rootRect === null) {
|
|
4091
|
+
return null;
|
|
3827
4092
|
}
|
|
3828
|
-
return measurement;
|
|
3829
|
-
}
|
|
3830
|
-
function createStaticState(measurement) {
|
|
3831
4093
|
return {
|
|
3832
|
-
|
|
3833
|
-
measurement,
|
|
3834
|
-
|
|
4094
|
+
expectedLeft: roundDebugValue(measurement.rootOrigin.left),
|
|
4095
|
+
expectedTop: roundDebugValue(measurement.rootOrigin.top),
|
|
4096
|
+
actualLeft: roundDebugValue(rootRect.left),
|
|
4097
|
+
actualTop: roundDebugValue(rootRect.top),
|
|
4098
|
+
deltaLeft: roundDebugValue(rootRect.left - measurement.rootOrigin.left),
|
|
4099
|
+
deltaTop: roundDebugValue(rootRect.top - measurement.rootOrigin.top)
|
|
3835
4100
|
};
|
|
3836
4101
|
}
|
|
3837
|
-
function
|
|
3838
|
-
return
|
|
3839
|
-
|
|
3840
|
-
|
|
3841
|
-
|
|
3842
|
-
|
|
3843
|
-
|
|
3844
|
-
|
|
3845
|
-
|
|
3846
|
-
|
|
3847
|
-
|
|
3848
|
-
|
|
3849
|
-
|
|
3850
|
-
|
|
3851
|
-
|
|
3852
|
-
|
|
3853
|
-
|
|
3854
|
-
|
|
3855
|
-
|
|
3856
|
-
|
|
3857
|
-
session.target = null;
|
|
3858
|
-
session.animating = false;
|
|
3859
|
-
setState(EMPTY_STATE);
|
|
4102
|
+
function summarizeSnapshotDrift(drift) {
|
|
4103
|
+
return {
|
|
4104
|
+
comparedGlyphs: drift.comparedGlyphs,
|
|
4105
|
+
expectedGlyphs: drift.expectedGlyphs,
|
|
4106
|
+
actualGlyphs: drift.actualGlyphs,
|
|
4107
|
+
snapshotWidthDelta: roundDebugValue(drift.snapshotWidthDelta),
|
|
4108
|
+
snapshotHeightDelta: roundDebugValue(drift.snapshotHeightDelta),
|
|
4109
|
+
maxAbsLeftDelta: roundDebugValue(drift.maxAbsLeftDelta),
|
|
4110
|
+
maxAbsTopDelta: roundDebugValue(drift.maxAbsTopDelta),
|
|
4111
|
+
maxAbsWidthDelta: roundDebugValue(drift.maxAbsWidthDelta),
|
|
4112
|
+
maxAbsHeightDelta: roundDebugValue(drift.maxAbsHeightDelta),
|
|
4113
|
+
mismatches: drift.mismatches.map((mismatch) => ({
|
|
4114
|
+
index: mismatch.index,
|
|
4115
|
+
glyph: mismatch.glyph,
|
|
4116
|
+
leftDelta: roundDebugValue(mismatch.leftDelta),
|
|
4117
|
+
topDelta: roundDebugValue(mismatch.topDelta),
|
|
4118
|
+
widthDelta: roundDebugValue(mismatch.widthDelta),
|
|
4119
|
+
heightDelta: roundDebugValue(mismatch.heightDelta)
|
|
4120
|
+
}))
|
|
4121
|
+
};
|
|
3860
4122
|
}
|
|
3861
|
-
function
|
|
3862
|
-
|
|
4123
|
+
function logTorphDebug(instanceId, event, payload) {
|
|
4124
|
+
const config = readTorphDebugConfig();
|
|
4125
|
+
const captureTrace = shouldCaptureTorphTrace(config);
|
|
4126
|
+
const logToConsole = isTorphDebugEnabled(config);
|
|
4127
|
+
if (!captureTrace && !logToConsole) {
|
|
3863
4128
|
return;
|
|
3864
4129
|
}
|
|
3865
|
-
|
|
3866
|
-
|
|
3867
|
-
|
|
3868
|
-
|
|
3869
|
-
|
|
3870
|
-
|
|
3871
|
-
}
|
|
3872
|
-
return createStaticState(measurement);
|
|
3873
|
-
});
|
|
3874
|
-
}
|
|
3875
|
-
function scheduleMorphTimeline({
|
|
3876
|
-
session,
|
|
3877
|
-
timeline,
|
|
3878
|
-
finalizeMeasurement,
|
|
3879
|
-
measurement,
|
|
3880
|
-
plan,
|
|
3881
|
-
setState
|
|
3882
|
-
}) {
|
|
3883
|
-
timeline.prepareFrame = requestAnimationFrame(() => {
|
|
3884
|
-
timeline.prepareFrame = null;
|
|
3885
|
-
setState((current) => {
|
|
3886
|
-
if (current.measurement !== measurement || current.plan !== plan) {
|
|
3887
|
-
return current;
|
|
3888
|
-
}
|
|
3889
|
-
return {
|
|
3890
|
-
stage: "animate",
|
|
3891
|
-
measurement,
|
|
3892
|
-
plan
|
|
3893
|
-
};
|
|
3894
|
-
});
|
|
3895
|
-
timeline.animateFrame = requestAnimationFrame(() => {
|
|
3896
|
-
timeline.animateFrame = null;
|
|
3897
|
-
timeline.finalizeTimer = window.setTimeout(() => {
|
|
3898
|
-
timeline.finalizeTimer = null;
|
|
3899
|
-
commitStaticMeasurement(session, finalizeMeasurement(session.target ?? measurement), setState);
|
|
3900
|
-
}, MORPH.durationMs);
|
|
3901
|
-
});
|
|
3902
|
-
});
|
|
4130
|
+
if (captureTrace) {
|
|
4131
|
+
appendTorphTrace(instanceId, event, payload);
|
|
4132
|
+
}
|
|
4133
|
+
if (logToConsole) {
|
|
4134
|
+
console.log(`[Torph#${instanceId}] ${event}`, payload);
|
|
4135
|
+
}
|
|
3903
4136
|
}
|
|
3904
|
-
|
|
3905
|
-
|
|
3906
|
-
|
|
3907
|
-
|
|
3908
|
-
|
|
3909
|
-
|
|
3910
|
-
|
|
3911
|
-
|
|
3912
|
-
|
|
3913
|
-
|
|
4137
|
+
|
|
4138
|
+
// torph/src/components/Torph.tsx
|
|
4139
|
+
import { jsxDEV } from "react/jsx-dev-runtime";
|
|
4140
|
+
var SCREEN_READER_ONLY_STYLE = {
|
|
4141
|
+
position: "absolute",
|
|
4142
|
+
width: "1px",
|
|
4143
|
+
height: "1px",
|
|
4144
|
+
margin: "-1px",
|
|
4145
|
+
padding: 0,
|
|
4146
|
+
border: 0,
|
|
4147
|
+
clip: "rect(0 0 0 0)",
|
|
4148
|
+
clipPath: "inset(50%)",
|
|
4149
|
+
overflow: "hidden",
|
|
4150
|
+
whiteSpace: "nowrap"
|
|
4151
|
+
};
|
|
4152
|
+
var FALLBACK_TEXT_STYLE = {
|
|
4153
|
+
display: "block",
|
|
4154
|
+
gridArea: "1 / 1"
|
|
4155
|
+
};
|
|
4156
|
+
var SHARED_GLYPH_TYPOGRAPHY_STYLE = {
|
|
4157
|
+
font: "inherit",
|
|
4158
|
+
fontKerning: "inherit",
|
|
4159
|
+
fontFeatureSettings: "inherit",
|
|
4160
|
+
fontOpticalSizing: "inherit",
|
|
4161
|
+
fontStretch: "inherit",
|
|
4162
|
+
fontStyle: "inherit",
|
|
4163
|
+
fontVariant: "inherit",
|
|
4164
|
+
fontVariantNumeric: "inherit",
|
|
4165
|
+
fontVariationSettings: "inherit",
|
|
4166
|
+
fontWeight: "inherit",
|
|
4167
|
+
letterSpacing: "inherit",
|
|
4168
|
+
textTransform: "inherit",
|
|
4169
|
+
wordSpacing: "inherit",
|
|
4170
|
+
direction: "inherit"
|
|
4171
|
+
};
|
|
4172
|
+
var ABSOLUTE_GLYPH_STYLE = {
|
|
4173
|
+
position: "absolute",
|
|
4174
|
+
display: "block",
|
|
4175
|
+
overflow: "hidden",
|
|
4176
|
+
transformOrigin: "left top"
|
|
4177
|
+
};
|
|
4178
|
+
var CONTEXT_SLICE_TEXT_STYLE = {
|
|
4179
|
+
...SHARED_GLYPH_TYPOGRAPHY_STYLE,
|
|
4180
|
+
position: "absolute",
|
|
4181
|
+
display: "block",
|
|
4182
|
+
minWidth: 0,
|
|
4183
|
+
whiteSpace: "inherit"
|
|
4184
|
+
};
|
|
4185
|
+
var debugDomNodeIds = new WeakMap;
|
|
4186
|
+
var debugDomNodeOrdinal = 0;
|
|
4187
|
+
function getDebugDomNodeId(node) {
|
|
4188
|
+
if (node === null) {
|
|
4189
|
+
return null;
|
|
3914
4190
|
}
|
|
3915
|
-
|
|
3916
|
-
|
|
3917
|
-
return;
|
|
4191
|
+
const existing = debugDomNodeIds.get(node);
|
|
4192
|
+
if (existing !== undefined) {
|
|
4193
|
+
return existing;
|
|
3918
4194
|
}
|
|
3919
|
-
|
|
3920
|
-
|
|
3921
|
-
|
|
3922
|
-
session.target = nextMeasurement;
|
|
3923
|
-
session.animating = true;
|
|
3924
|
-
setState({
|
|
3925
|
-
stage: "prepare",
|
|
3926
|
-
measurement: nextMeasurement,
|
|
3927
|
-
plan
|
|
3928
|
-
});
|
|
3929
|
-
scheduleMorphTimeline({
|
|
3930
|
-
session,
|
|
3931
|
-
timeline,
|
|
3932
|
-
finalizeMeasurement,
|
|
3933
|
-
measurement: nextMeasurement,
|
|
3934
|
-
plan,
|
|
3935
|
-
setState
|
|
3936
|
-
});
|
|
4195
|
+
debugDomNodeOrdinal += 1;
|
|
4196
|
+
debugDomNodeIds.set(node, debugDomNodeOrdinal);
|
|
4197
|
+
return debugDomNodeOrdinal;
|
|
3937
4198
|
}
|
|
3938
4199
|
function reconcileMorphChange({
|
|
3939
|
-
finalizeMeasurement,
|
|
3940
4200
|
root,
|
|
3941
4201
|
measurementLayer,
|
|
3942
4202
|
measurementBackend,
|
|
@@ -3956,10 +4216,7 @@ function reconcileMorphChange({
|
|
|
3956
4216
|
if (measurementBackend === null) {
|
|
3957
4217
|
throw new Error("Torph measurement backend is missing.");
|
|
3958
4218
|
}
|
|
3959
|
-
|
|
3960
|
-
if (session.animating && session.target !== null) {
|
|
3961
|
-
layoutHint = session.target;
|
|
3962
|
-
}
|
|
4219
|
+
const layoutHint = selectMorphLayoutHint(session);
|
|
3963
4220
|
const nextMeasurement = measureFromNodes({
|
|
3964
4221
|
root,
|
|
3965
4222
|
layoutContext,
|
|
@@ -3971,73 +4228,13 @@ function reconcileMorphChange({
|
|
|
3971
4228
|
renderText,
|
|
3972
4229
|
segments
|
|
3973
4230
|
});
|
|
3974
|
-
|
|
3975
|
-
if (nextMeasurement.snapshot.renderText === session.target.snapshot.renderText) {
|
|
3976
|
-
session.target = refreshAnimatingTarget(session.target, nextMeasurement);
|
|
3977
|
-
return nextMeasurement;
|
|
3978
|
-
}
|
|
3979
|
-
}
|
|
3980
|
-
cancelTimeline(timeline);
|
|
3981
|
-
if (session.committed === null) {
|
|
3982
|
-
commitStaticMeasurement(session, nextMeasurement, setState);
|
|
3983
|
-
return nextMeasurement;
|
|
3984
|
-
}
|
|
3985
|
-
if (!areFontsReady()) {
|
|
3986
|
-
commitStaticMeasurement(session, nextMeasurement, setState);
|
|
3987
|
-
return nextMeasurement;
|
|
3988
|
-
}
|
|
3989
|
-
if (session.committed.snapshot.renderText === nextMeasurement.snapshot.renderText) {
|
|
3990
|
-
commitStaticMeasurement(session, reuseCommittedMeasurement(session.committed, nextMeasurement), setState);
|
|
3991
|
-
return nextMeasurement;
|
|
3992
|
-
}
|
|
3993
|
-
startMorph({
|
|
3994
|
-
finalizeMeasurement,
|
|
3995
|
-
nextMeasurement,
|
|
4231
|
+
return reconcileMorphSessionUpdate({
|
|
3996
4232
|
session,
|
|
3997
4233
|
timeline,
|
|
4234
|
+
nextMeasurement,
|
|
4235
|
+
fontsReady: areFontsReady(),
|
|
3998
4236
|
setState
|
|
3999
4237
|
});
|
|
4000
|
-
return nextMeasurement;
|
|
4001
|
-
}
|
|
4002
|
-
function syncCommittedRootOriginWhenIdle({
|
|
4003
|
-
root,
|
|
4004
|
-
flowTextRef,
|
|
4005
|
-
layoutContext,
|
|
4006
|
-
state,
|
|
4007
|
-
session
|
|
4008
|
-
}) {
|
|
4009
|
-
if (root === null || layoutContext === null) {
|
|
4010
|
-
return;
|
|
4011
|
-
}
|
|
4012
|
-
if (state.stage !== "idle" || state.measurement === null) {
|
|
4013
|
-
return;
|
|
4014
|
-
}
|
|
4015
|
-
const nextRootOrigin = readRootOrigin(root);
|
|
4016
|
-
const nextFlowInlineSize = readFlowInlineSize(flowTextRef.current);
|
|
4017
|
-
const committedMeasurement = state.measurement;
|
|
4018
|
-
if (nearlyEqual(committedMeasurement.rootOrigin.left, nextRootOrigin.left) && nearlyEqual(committedMeasurement.rootOrigin.top, nextRootOrigin.top) && (committedMeasurement.flowInlineSize === null && nextFlowInlineSize === null || committedMeasurement.flowInlineSize !== null && nextFlowInlineSize !== null && nearlyEqual(committedMeasurement.flowInlineSize, nextFlowInlineSize))) {
|
|
4019
|
-
session.committed = committedMeasurement;
|
|
4020
|
-
return;
|
|
4021
|
-
}
|
|
4022
|
-
session.committed = {
|
|
4023
|
-
snapshot: committedMeasurement.snapshot,
|
|
4024
|
-
layoutInlineSize: committedMeasurement.layoutInlineSize,
|
|
4025
|
-
reservedInlineSize: committedMeasurement.reservedInlineSize,
|
|
4026
|
-
flowInlineSize: nextFlowInlineSize,
|
|
4027
|
-
rootOrigin: nextRootOrigin
|
|
4028
|
-
};
|
|
4029
|
-
}
|
|
4030
|
-
function getFadeDuration(fraction) {
|
|
4031
|
-
return Math.min(MORPH.durationMs * fraction, MORPH.maxFadeMs);
|
|
4032
|
-
}
|
|
4033
|
-
function getLiveTransform(item, stage, visualBridge) {
|
|
4034
|
-
if (stage !== "prepare") {
|
|
4035
|
-
return "translate(0px, 0px)";
|
|
4036
|
-
}
|
|
4037
|
-
if (item.kind === "move") {
|
|
4038
|
-
return `translate(${(item.fromLeft ?? item.left) - item.left + visualBridge.offsetX}px, ${(item.fromTop ?? item.top) - item.top + visualBridge.offsetY}px)`;
|
|
4039
|
-
}
|
|
4040
|
-
return `translate(${visualBridge.offsetX}px, ${visualBridge.offsetY}px)`;
|
|
4041
4238
|
}
|
|
4042
4239
|
function getLiveOpacity(item, stage) {
|
|
4043
4240
|
if (stage === "prepare" && item.kind === "enter") {
|
|
@@ -4045,96 +4242,14 @@ function getLiveOpacity(item, stage) {
|
|
|
4045
4242
|
}
|
|
4046
4243
|
return 1;
|
|
4047
4244
|
}
|
|
4048
|
-
function getLiveTransition(item, stage) {
|
|
4049
|
-
if (stage !== "animate") {
|
|
4050
|
-
return;
|
|
4051
|
-
}
|
|
4052
|
-
if (item.kind === "enter") {
|
|
4053
|
-
return `opacity ${getFadeDuration(0.5)}ms linear ${getFadeDuration(0.25)}ms`;
|
|
4054
|
-
}
|
|
4055
|
-
return `transform ${MORPH.durationMs}ms ${MORPH.ease}, opacity ${getFadeDuration(0.25)}ms linear`;
|
|
4056
|
-
}
|
|
4057
4245
|
function getExitOpacity(stage) {
|
|
4058
4246
|
if (stage === "animate") {
|
|
4059
4247
|
return 0;
|
|
4060
4248
|
}
|
|
4061
4249
|
return 1;
|
|
4062
4250
|
}
|
|
4063
|
-
function
|
|
4064
|
-
|
|
4065
|
-
}
|
|
4066
|
-
function getExitTransition(stage) {
|
|
4067
|
-
if (stage !== "animate") {
|
|
4068
|
-
return;
|
|
4069
|
-
}
|
|
4070
|
-
return `transform ${MORPH.durationMs}ms ${MORPH.ease}, opacity ${getFadeDuration(0.25)}ms linear`;
|
|
4071
|
-
}
|
|
4072
|
-
function supportsIntrinsicWidthLock(display, parentDisplay) {
|
|
4073
|
-
const parentNeedsReservation = parentDisplay === "flex" || parentDisplay === "inline-flex" || parentDisplay === "grid" || parentDisplay === "inline-grid";
|
|
4074
|
-
return display === "inline" || display === "inline-block" || display === "inline-flex" || display === "inline-grid" || parentNeedsReservation;
|
|
4075
|
-
}
|
|
4076
|
-
function getRootDisplay(layoutContext) {
|
|
4077
|
-
if (layoutContext === null) {
|
|
4078
|
-
return "grid";
|
|
4079
|
-
}
|
|
4080
|
-
if (supportsIntrinsicWidthLock(layoutContext.display, layoutContext.parentDisplay)) {
|
|
4081
|
-
return "inline-grid";
|
|
4082
|
-
}
|
|
4083
|
-
return "grid";
|
|
4084
|
-
}
|
|
4085
|
-
function getRootStyle(stage, plan, measurement, layoutContext) {
|
|
4086
|
-
let width = measurement?.reservedInlineSize ?? undefined;
|
|
4087
|
-
if (plan !== null) {
|
|
4088
|
-
width = plan.layoutInlineSizeTo;
|
|
4089
|
-
if (stage === "prepare") {
|
|
4090
|
-
width = plan.layoutInlineSizeFrom;
|
|
4091
|
-
}
|
|
4092
|
-
}
|
|
4093
|
-
let height;
|
|
4094
|
-
if (plan !== null) {
|
|
4095
|
-
height = plan.frameHeight;
|
|
4096
|
-
}
|
|
4097
|
-
const shouldTransitionWidth = stage === "animate" && plan !== null && !nearlyEqual(plan.layoutInlineSizeFrom, plan.layoutInlineSizeTo);
|
|
4098
|
-
const style = {
|
|
4099
|
-
position: "relative",
|
|
4100
|
-
display: getRootDisplay(layoutContext)
|
|
4101
|
-
};
|
|
4102
|
-
if (width !== undefined) {
|
|
4103
|
-
style.width = width;
|
|
4104
|
-
}
|
|
4105
|
-
if (height !== undefined) {
|
|
4106
|
-
style.height = height;
|
|
4107
|
-
}
|
|
4108
|
-
if (shouldTransitionWidth) {
|
|
4109
|
-
style.transition = `width ${MORPH.durationMs}ms ${MORPH.ease}`;
|
|
4110
|
-
}
|
|
4111
|
-
return style;
|
|
4112
|
-
}
|
|
4113
|
-
function getMeasurementLayerStyle(layoutContext, useContentInlineSize = false) {
|
|
4114
|
-
const intrinsicWidthLock = layoutContext !== null && (useContentInlineSize || supportsIntrinsicWidthLock(layoutContext.display, layoutContext.parentDisplay));
|
|
4115
|
-
if (!intrinsicWidthLock) {
|
|
4116
|
-
return MEASUREMENT_LAYER_STYLE;
|
|
4117
|
-
}
|
|
4118
|
-
return {
|
|
4119
|
-
...MEASUREMENT_LAYER_STYLE,
|
|
4120
|
-
right: "auto",
|
|
4121
|
-
width: "max-content"
|
|
4122
|
-
};
|
|
4123
|
-
}
|
|
4124
|
-
function resolveFlowText(committedMeasurement, stateMeasurement, text) {
|
|
4125
|
-
return stateMeasurement?.snapshot.text ?? committedMeasurement?.snapshot.text ?? text;
|
|
4126
|
-
}
|
|
4127
|
-
function getOverlayStyle(plan) {
|
|
4128
|
-
return {
|
|
4129
|
-
...OVERLAY_STYLE,
|
|
4130
|
-
right: "auto",
|
|
4131
|
-
bottom: "auto",
|
|
4132
|
-
width: plan.frameWidth,
|
|
4133
|
-
height: plan.frameHeight
|
|
4134
|
-
};
|
|
4135
|
-
}
|
|
4136
|
-
function getFallbackTextStyle(shouldRenderOverlay) {
|
|
4137
|
-
if (!shouldRenderOverlay) {
|
|
4251
|
+
function getFallbackTextStyle(shouldHideFlowText) {
|
|
4252
|
+
if (!shouldHideFlowText) {
|
|
4138
4253
|
return FALLBACK_TEXT_STYLE;
|
|
4139
4254
|
}
|
|
4140
4255
|
return {
|
|
@@ -4167,18 +4282,136 @@ function getExitGlyphStyle(item, stage, visualBridge) {
|
|
|
4167
4282
|
transition: getExitTransition(stage)
|
|
4168
4283
|
};
|
|
4169
4284
|
}
|
|
4170
|
-
function getContextSliceStyle(layoutInlineSize, item) {
|
|
4285
|
+
function getContextSliceStyle(layoutInlineSize, item, whiteSpace) {
|
|
4286
|
+
return {
|
|
4287
|
+
...CONTEXT_SLICE_TEXT_STYLE,
|
|
4288
|
+
left: -item.left,
|
|
4289
|
+
top: -item.top,
|
|
4290
|
+
width: layoutInlineSize,
|
|
4291
|
+
whiteSpace
|
|
4292
|
+
};
|
|
4293
|
+
}
|
|
4294
|
+
function summarizePreciseRect(rect) {
|
|
4295
|
+
if (rect === null) {
|
|
4296
|
+
return null;
|
|
4297
|
+
}
|
|
4298
|
+
return {
|
|
4299
|
+
left: roundDebugValue(rect.left),
|
|
4300
|
+
top: roundDebugValue(rect.top),
|
|
4301
|
+
width: roundDebugValue(rect.width),
|
|
4302
|
+
height: roundDebugValue(rect.height)
|
|
4303
|
+
};
|
|
4304
|
+
}
|
|
4305
|
+
function summarizePreciseGlyphs(snapshot, rootRect) {
|
|
4306
|
+
if (snapshot === null) {
|
|
4307
|
+
return null;
|
|
4308
|
+
}
|
|
4309
|
+
return snapshot.graphemes.map((grapheme, index) => ({
|
|
4310
|
+
index,
|
|
4311
|
+
glyph: grapheme.glyph,
|
|
4312
|
+
key: grapheme.key,
|
|
4313
|
+
left: roundDebugValue(grapheme.left),
|
|
4314
|
+
top: roundDebugValue(grapheme.top),
|
|
4315
|
+
width: roundDebugValue(grapheme.width),
|
|
4316
|
+
height: roundDebugValue(grapheme.height),
|
|
4317
|
+
viewportLeft: rootRect === null ? null : roundDebugValue(rootRect.left + grapheme.left),
|
|
4318
|
+
viewportTop: rootRect === null ? null : roundDebugValue(rootRect.top + grapheme.top)
|
|
4319
|
+
}));
|
|
4320
|
+
}
|
|
4321
|
+
function summarizeLiveNodeStyles(overlayNode) {
|
|
4322
|
+
if (overlayNode === null) {
|
|
4323
|
+
return null;
|
|
4324
|
+
}
|
|
4325
|
+
return Array.from(overlayNode.querySelectorAll("[data-morph-role='live']")).map((node, index) => {
|
|
4326
|
+
const styles = getComputedStyle(node);
|
|
4327
|
+
const sliceNode = node.firstElementChild;
|
|
4328
|
+
let sliceStyles = null;
|
|
4329
|
+
let sliceRect = null;
|
|
4330
|
+
if (sliceNode instanceof HTMLElement) {
|
|
4331
|
+
sliceStyles = getComputedStyle(sliceNode);
|
|
4332
|
+
sliceRect = sliceNode.getBoundingClientRect();
|
|
4333
|
+
}
|
|
4334
|
+
let nodeRect = null;
|
|
4335
|
+
nodeRect = node.getBoundingClientRect();
|
|
4336
|
+
let sliceScrollWidth = null;
|
|
4337
|
+
let sliceClientWidth = null;
|
|
4338
|
+
let sliceOffsetWidth = null;
|
|
4339
|
+
if (sliceNode instanceof HTMLElement) {
|
|
4340
|
+
sliceScrollWidth = sliceNode.scrollWidth;
|
|
4341
|
+
sliceClientWidth = sliceNode.clientWidth;
|
|
4342
|
+
sliceOffsetWidth = sliceNode.offsetWidth;
|
|
4343
|
+
}
|
|
4344
|
+
return {
|
|
4345
|
+
index,
|
|
4346
|
+
nodeId: getDebugDomNodeId(node),
|
|
4347
|
+
key: node.dataset.morphKey ?? null,
|
|
4348
|
+
glyph: node.dataset.morphGlyph ?? null,
|
|
4349
|
+
kind: node.dataset.morphKind ?? null,
|
|
4350
|
+
transform: styles.transform,
|
|
4351
|
+
inlineTransform: node.style.transform,
|
|
4352
|
+
opacity: styles.opacity,
|
|
4353
|
+
transitionProperty: styles.transitionProperty,
|
|
4354
|
+
transitionDuration: styles.transitionDuration,
|
|
4355
|
+
transitionTimingFunction: styles.transitionTimingFunction,
|
|
4356
|
+
nodeRect: summarizePreciseRect(nodeRect),
|
|
4357
|
+
sliceNodeId: getDebugDomNodeId(sliceNode),
|
|
4358
|
+
sliceInlineLeft: node.firstElementChild instanceof HTMLElement ? node.firstElementChild.style.left : null,
|
|
4359
|
+
sliceInlineTop: node.firstElementChild instanceof HTMLElement ? node.firstElementChild.style.top : null,
|
|
4360
|
+
sliceInlineWidth: node.firstElementChild instanceof HTMLElement ? node.firstElementChild.style.width : null,
|
|
4361
|
+
sliceLeft: sliceStyles?.left ?? null,
|
|
4362
|
+
sliceTop: sliceStyles?.top ?? null,
|
|
4363
|
+
sliceWidth: sliceStyles?.width ?? null,
|
|
4364
|
+
sliceWhiteSpace: sliceStyles?.whiteSpace ?? null,
|
|
4365
|
+
sliceText: sliceNode instanceof HTMLElement ? sliceNode.textContent : null,
|
|
4366
|
+
sliceRect: summarizePreciseRect(sliceRect),
|
|
4367
|
+
sliceScrollWidth: roundDebugValue(sliceScrollWidth),
|
|
4368
|
+
sliceClientWidth: roundDebugValue(sliceClientWidth),
|
|
4369
|
+
sliceOffsetWidth: roundDebugValue(sliceOffsetWidth)
|
|
4370
|
+
};
|
|
4371
|
+
});
|
|
4372
|
+
}
|
|
4373
|
+
function summarizeRootRuntimeStyles(root) {
|
|
4374
|
+
if (root === null) {
|
|
4375
|
+
return null;
|
|
4376
|
+
}
|
|
4377
|
+
const styles = getComputedStyle(root);
|
|
4378
|
+
const parent = root.parentElement;
|
|
4379
|
+
let parentStyles = null;
|
|
4380
|
+
let parentRect = null;
|
|
4381
|
+
if (parent instanceof HTMLElement) {
|
|
4382
|
+
parentStyles = getComputedStyle(parent);
|
|
4383
|
+
parentRect = parent.getBoundingClientRect();
|
|
4384
|
+
}
|
|
4385
|
+
let parentSummary = null;
|
|
4386
|
+
if (parent !== null) {
|
|
4387
|
+
parentSummary = {
|
|
4388
|
+
display: parentStyles?.display ?? null,
|
|
4389
|
+
justifyContent: parentStyles?.justifyContent ?? null,
|
|
4390
|
+
alignItems: parentStyles?.alignItems ?? null,
|
|
4391
|
+
placeItems: parentStyles?.placeItems ?? null,
|
|
4392
|
+
textAlign: parentStyles?.textAlign ?? null,
|
|
4393
|
+
rect: summarizePreciseRect(parentRect)
|
|
4394
|
+
};
|
|
4395
|
+
}
|
|
4171
4396
|
return {
|
|
4172
|
-
|
|
4173
|
-
|
|
4174
|
-
|
|
4175
|
-
|
|
4397
|
+
inlineWidth: root.style.width || null,
|
|
4398
|
+
computedWidth: styles.width,
|
|
4399
|
+
inlineTransition: root.style.transition || null,
|
|
4400
|
+
computedTransitionProperty: styles.transitionProperty,
|
|
4401
|
+
computedTransitionDuration: styles.transitionDuration,
|
|
4402
|
+
computedTransform: styles.transform,
|
|
4403
|
+
offsetWidth: roundDebugValue(root.offsetWidth),
|
|
4404
|
+
clientWidth: roundDebugValue(root.clientWidth),
|
|
4405
|
+
scrollWidth: roundDebugValue(root.scrollWidth),
|
|
4406
|
+
parent: parentSummary
|
|
4176
4407
|
};
|
|
4177
4408
|
}
|
|
4178
4409
|
function MorphOverlay({
|
|
4179
4410
|
overlayRef,
|
|
4180
4411
|
stage,
|
|
4181
|
-
plan
|
|
4412
|
+
plan,
|
|
4413
|
+
sourceSliceWhiteSpace,
|
|
4414
|
+
targetSliceWhiteSpace
|
|
4182
4415
|
}) {
|
|
4183
4416
|
let exitItems = [];
|
|
4184
4417
|
if (stage !== "idle") {
|
|
@@ -4187,7 +4420,7 @@ function MorphOverlay({
|
|
|
4187
4420
|
return /* @__PURE__ */ jsxDEV("div", {
|
|
4188
4421
|
ref: overlayRef,
|
|
4189
4422
|
"aria-hidden": "true",
|
|
4190
|
-
style: getOverlayStyle(plan),
|
|
4423
|
+
style: getOverlayStyle(stage, plan),
|
|
4191
4424
|
children: [
|
|
4192
4425
|
exitItems.map((item) => /* @__PURE__ */ jsxDEV("span", {
|
|
4193
4426
|
"data-morph-role": "exit",
|
|
@@ -4195,7 +4428,8 @@ function MorphOverlay({
|
|
|
4195
4428
|
"data-morph-glyph": item.glyph,
|
|
4196
4429
|
style: getExitGlyphStyle(item, stage, plan.visualBridge),
|
|
4197
4430
|
children: /* @__PURE__ */ jsxDEV("span", {
|
|
4198
|
-
|
|
4431
|
+
"data-morph-slice": "context",
|
|
4432
|
+
style: getContextSliceStyle(plan.layoutInlineSizeFrom, item, sourceSliceWhiteSpace),
|
|
4199
4433
|
children: plan.sourceRenderText
|
|
4200
4434
|
}, undefined, false, undefined, this)
|
|
4201
4435
|
}, `exit-${item.key}`, false, undefined, this)),
|
|
@@ -4203,9 +4437,11 @@ function MorphOverlay({
|
|
|
4203
4437
|
"data-morph-role": "live",
|
|
4204
4438
|
"data-morph-key": item.key,
|
|
4205
4439
|
"data-morph-glyph": item.glyph,
|
|
4440
|
+
"data-morph-kind": item.kind,
|
|
4206
4441
|
style: getLiveGlyphStyle(item, stage, plan.visualBridge),
|
|
4207
4442
|
children: /* @__PURE__ */ jsxDEV("span", {
|
|
4208
|
-
|
|
4443
|
+
"data-morph-slice": "context",
|
|
4444
|
+
style: getContextSliceStyle(plan.layoutInlineSizeTo, item, targetSliceWhiteSpace),
|
|
4209
4445
|
children: plan.targetRenderText
|
|
4210
4446
|
}, undefined, false, undefined, this)
|
|
4211
4447
|
}, item.key, false, undefined, this))
|
|
@@ -4225,54 +4461,92 @@ function MeasurementLayer({
|
|
|
4225
4461
|
children: text
|
|
4226
4462
|
}, undefined, false, undefined, this);
|
|
4227
4463
|
}
|
|
4464
|
+
function isMorphOverlayTransformFinalizeEvent(event, hasMoveTransitions) {
|
|
4465
|
+
if (!hasMoveTransitions) {
|
|
4466
|
+
return false;
|
|
4467
|
+
}
|
|
4468
|
+
const target = event.target;
|
|
4469
|
+
if (!(target instanceof HTMLElement)) {
|
|
4470
|
+
return false;
|
|
4471
|
+
}
|
|
4472
|
+
if (target.dataset.morphRole !== "live") {
|
|
4473
|
+
return false;
|
|
4474
|
+
}
|
|
4475
|
+
return event.propertyName === "transform";
|
|
4476
|
+
}
|
|
4477
|
+
function resolveMorphFinalizeSignal(event, hasMoveTransitions) {
|
|
4478
|
+
if (isMorphOverlayTransformFinalizeEvent(event, hasMoveTransitions)) {
|
|
4479
|
+
return "live-transform";
|
|
4480
|
+
}
|
|
4481
|
+
return null;
|
|
4482
|
+
}
|
|
4228
4483
|
function useMorphTransition(text, className) {
|
|
4229
|
-
const
|
|
4230
|
-
const
|
|
4231
|
-
|
|
4232
|
-
|
|
4233
|
-
const
|
|
4234
|
-
const
|
|
4235
|
-
const
|
|
4236
|
-
const
|
|
4237
|
-
const
|
|
4238
|
-
const
|
|
4239
|
-
const
|
|
4240
|
-
const
|
|
4484
|
+
const [state, setState] = useState2(EMPTY_STATE);
|
|
4485
|
+
const { ref, layoutContext } = useObservedLayoutContext([
|
|
4486
|
+
className
|
|
4487
|
+
]);
|
|
4488
|
+
const debugInstanceIdRef = useRef2(null);
|
|
4489
|
+
const debugRenderOrdinalRef = useRef2(0);
|
|
4490
|
+
const flowTextRef = useRef2(null);
|
|
4491
|
+
const measurementLayerRef = useRef2(null);
|
|
4492
|
+
const completedDomMeasurementKeyRef = useRef2(null);
|
|
4493
|
+
const domMeasurementSnapshotCacheRef = useRef2(new Map);
|
|
4494
|
+
const sessionRef = useRef2({ ...EMPTY_SESSION });
|
|
4495
|
+
const timelineRef = useRef2({ ...EMPTY_TIMELINE });
|
|
4496
|
+
const debugDriftSignatureRef = useRef2(null);
|
|
4497
|
+
const [domMeasurementRequestKey, setDomMeasurementRequestKey] = useState2(null);
|
|
4498
|
+
debugRenderOrdinalRef.current += 1;
|
|
4499
|
+
const debugRenderOrdinal = debugRenderOrdinalRef.current;
|
|
4241
4500
|
if (debugInstanceIdRef.current === null) {
|
|
4242
4501
|
debugInstanceIdRef.current = nextTorphDebugInstanceId();
|
|
4243
4502
|
}
|
|
4244
|
-
|
|
4245
|
-
if (sessionRef.current.animating) {
|
|
4246
|
-
measurementHint = sessionRef.current.target ?? sessionRef.current.committed;
|
|
4247
|
-
}
|
|
4248
|
-
const forceContentInlineSize = forceContentMeasurementText === text;
|
|
4503
|
+
const measurementHint = selectMorphLayoutHint(sessionRef.current);
|
|
4249
4504
|
const measurementRequest = useMemo(() => createMorphMeasurementRequest({
|
|
4250
4505
|
text,
|
|
4251
4506
|
layoutContext,
|
|
4252
|
-
layoutHint: measurementHint
|
|
4253
|
-
|
|
4254
|
-
}), [text, layoutContext, measurementHint, forceContentInlineSize]);
|
|
4507
|
+
layoutHint: measurementHint
|
|
4508
|
+
}), [text, layoutContext, measurementHint]);
|
|
4255
4509
|
const renderText = measurementRequest?.renderText ?? text;
|
|
4256
4510
|
const useContentInlineSize = measurementRequest?.useContentInlineSize ?? false;
|
|
4257
4511
|
const measurementBackend = measurementRequest?.measurementBackend ?? null;
|
|
4258
4512
|
const segments = measurementRequest?.segments ?? EMPTY_SEGMENTS;
|
|
4259
4513
|
const domMeasurementKey = measurementRequest?.domMeasurementKey ?? null;
|
|
4260
|
-
|
|
4514
|
+
const logTransitionTrace = (event, payload = {}) => {
|
|
4261
4515
|
const config = readTorphDebugConfig();
|
|
4262
|
-
if (!
|
|
4516
|
+
if (!shouldRunTorphInstrumentation(config)) {
|
|
4263
4517
|
return;
|
|
4264
4518
|
}
|
|
4519
|
+
logTorphDebug(debugInstanceIdRef.current, event, {
|
|
4520
|
+
traceSchemaVersion: TORPH_TRACE_SCHEMA_VERSION,
|
|
4521
|
+
renderOrdinal: debugRenderOrdinal,
|
|
4522
|
+
text,
|
|
4523
|
+
renderText,
|
|
4524
|
+
stateStage: state.stage,
|
|
4525
|
+
committed: summarizeDebugMeasurement(sessionRef.current.committed),
|
|
4526
|
+
stateMeasurement: summarizeDebugMeasurement(state.measurement),
|
|
4527
|
+
layoutContext: summarizeDebugLayoutContext(layoutContext),
|
|
4528
|
+
measurementBackend,
|
|
4529
|
+
useContentInlineSize,
|
|
4530
|
+
domMeasurementKey,
|
|
4531
|
+
domMeasurementRequestKey,
|
|
4532
|
+
completedDomMeasurementKey: completedDomMeasurementKeyRef.current,
|
|
4533
|
+
...payload
|
|
4534
|
+
});
|
|
4535
|
+
};
|
|
4536
|
+
useLayoutEffect2(() => {
|
|
4265
4537
|
ensureTorphTraceApi();
|
|
4266
4538
|
}, []);
|
|
4267
|
-
|
|
4268
|
-
const finalizeMeasurement = (measurement) => refineMeasurementFromLiveNodes(measurement, ref.current, flowTextRef.current);
|
|
4539
|
+
useLayoutEffect2(() => {
|
|
4269
4540
|
if (ref.current === null || layoutContext === null) {
|
|
4270
4541
|
completedDomMeasurementKeyRef.current = null;
|
|
4271
4542
|
if (domMeasurementRequestKey !== null) {
|
|
4543
|
+
logTransitionTrace("effect:dom-measurement-request-update", {
|
|
4544
|
+
reason: "clear-missing-root-or-layout",
|
|
4545
|
+
nextDomMeasurementRequestKey: null
|
|
4546
|
+
});
|
|
4272
4547
|
setDomMeasurementRequestKey(null);
|
|
4273
4548
|
}
|
|
4274
4549
|
reconcileMorphChange({
|
|
4275
|
-
finalizeMeasurement,
|
|
4276
4550
|
root: ref.current,
|
|
4277
4551
|
measurementLayer: measurementLayerRef.current,
|
|
4278
4552
|
measurementBackend,
|
|
@@ -4295,10 +4569,14 @@ function useMorphTransition(text, className) {
|
|
|
4295
4569
|
if (cachedSnapshot !== null) {
|
|
4296
4570
|
completedDomMeasurementKeyRef.current = domMeasurementKey;
|
|
4297
4571
|
if (domMeasurementRequestKey !== null) {
|
|
4572
|
+
logTransitionTrace("effect:dom-measurement-request-update", {
|
|
4573
|
+
reason: "clear-after-cache-hit",
|
|
4574
|
+
nextDomMeasurementRequestKey: null,
|
|
4575
|
+
snapshotSource: "cache"
|
|
4576
|
+
});
|
|
4298
4577
|
setDomMeasurementRequestKey(null);
|
|
4299
4578
|
}
|
|
4300
4579
|
reconcileMorphChange({
|
|
4301
|
-
finalizeMeasurement,
|
|
4302
4580
|
root: ref.current,
|
|
4303
4581
|
measurementLayer: null,
|
|
4304
4582
|
measurementBackend,
|
|
@@ -4315,14 +4593,20 @@ function useMorphTransition(text, className) {
|
|
|
4315
4593
|
}
|
|
4316
4594
|
if (completedDomMeasurementKeyRef.current !== domMeasurementKey) {
|
|
4317
4595
|
if (domMeasurementRequestKey !== domMeasurementKey) {
|
|
4596
|
+
logTransitionTrace("effect:dom-measurement-request-update", {
|
|
4597
|
+
reason: "request-measurement-layer",
|
|
4598
|
+
nextDomMeasurementRequestKey: domMeasurementKey
|
|
4599
|
+
});
|
|
4318
4600
|
setDomMeasurementRequestKey(domMeasurementKey);
|
|
4319
4601
|
return;
|
|
4320
4602
|
}
|
|
4321
4603
|
if (measurementLayerRef.current === null) {
|
|
4604
|
+
logTransitionTrace("effect:dom-measurement-await-layer", {
|
|
4605
|
+
reason: "measurement-layer-not-mounted"
|
|
4606
|
+
});
|
|
4322
4607
|
return;
|
|
4323
4608
|
}
|
|
4324
4609
|
const nextMeasurement2 = reconcileMorphChange({
|
|
4325
|
-
finalizeMeasurement,
|
|
4326
4610
|
root: ref.current,
|
|
4327
4611
|
measurementLayer: measurementLayerRef.current,
|
|
4328
4612
|
measurementBackend,
|
|
@@ -4342,21 +4626,33 @@ function useMorphTransition(text, className) {
|
|
|
4342
4626
|
}
|
|
4343
4627
|
completedDomMeasurementKeyRef.current = domMeasurementKey;
|
|
4344
4628
|
if (domMeasurementRequestKey !== null) {
|
|
4629
|
+
logTransitionTrace("effect:dom-measurement-request-update", {
|
|
4630
|
+
reason: "clear-after-live-measurement",
|
|
4631
|
+
nextDomMeasurementRequestKey: null,
|
|
4632
|
+
snapshotSource: "layer"
|
|
4633
|
+
});
|
|
4345
4634
|
setDomMeasurementRequestKey(null);
|
|
4346
4635
|
}
|
|
4347
4636
|
return;
|
|
4348
4637
|
}
|
|
4349
4638
|
if (domMeasurementRequestKey !== null) {
|
|
4639
|
+
logTransitionTrace("effect:dom-measurement-request-update", {
|
|
4640
|
+
reason: "clear-completed-measurement",
|
|
4641
|
+
nextDomMeasurementRequestKey: null
|
|
4642
|
+
});
|
|
4350
4643
|
setDomMeasurementRequestKey(null);
|
|
4351
4644
|
}
|
|
4352
4645
|
return;
|
|
4353
4646
|
}
|
|
4354
4647
|
completedDomMeasurementKeyRef.current = null;
|
|
4355
4648
|
if (domMeasurementRequestKey !== null) {
|
|
4649
|
+
logTransitionTrace("effect:dom-measurement-request-update", {
|
|
4650
|
+
reason: "clear-no-dom-measurement-needed",
|
|
4651
|
+
nextDomMeasurementRequestKey: null
|
|
4652
|
+
});
|
|
4356
4653
|
setDomMeasurementRequestKey(null);
|
|
4357
4654
|
}
|
|
4358
4655
|
const nextMeasurement = reconcileMorphChange({
|
|
4359
|
-
finalizeMeasurement,
|
|
4360
4656
|
root: ref.current,
|
|
4361
4657
|
measurementLayer: measurementLayerRef.current,
|
|
4362
4658
|
measurementBackend,
|
|
@@ -4379,36 +4675,7 @@ function useMorphTransition(text, className) {
|
|
|
4379
4675
|
domMeasurementKey,
|
|
4380
4676
|
domMeasurementRequestKey
|
|
4381
4677
|
]);
|
|
4382
|
-
|
|
4383
|
-
syncCommittedRootOriginWhenIdle({
|
|
4384
|
-
root: ref.current,
|
|
4385
|
-
flowTextRef,
|
|
4386
|
-
layoutContext,
|
|
4387
|
-
state,
|
|
4388
|
-
session: sessionRef.current
|
|
4389
|
-
});
|
|
4390
|
-
}, [layoutContext, state]);
|
|
4391
|
-
useLayoutEffect(() => {
|
|
4392
|
-
if (forceContentMeasurementText !== null && forceContentMeasurementText !== text) {
|
|
4393
|
-
setForceContentMeasurementText(null);
|
|
4394
|
-
return;
|
|
4395
|
-
}
|
|
4396
|
-
if (state.stage !== "idle" || state.measurement === null) {
|
|
4397
|
-
return;
|
|
4398
|
-
}
|
|
4399
|
-
const flowLineCount = readFlowLineCount(flowTextRef.current);
|
|
4400
|
-
const shouldHeal = shouldHealIdleMeasurementFromFlow(state.measurement, flowLineCount);
|
|
4401
|
-
if (shouldHeal) {
|
|
4402
|
-
if (forceContentMeasurementText !== text) {
|
|
4403
|
-
setForceContentMeasurementText(text);
|
|
4404
|
-
}
|
|
4405
|
-
return;
|
|
4406
|
-
}
|
|
4407
|
-
if (forceContentMeasurementText === text) {
|
|
4408
|
-
setForceContentMeasurementText(null);
|
|
4409
|
-
}
|
|
4410
|
-
}, [forceContentMeasurementText, state, text]);
|
|
4411
|
-
useLayoutEffect(() => {
|
|
4678
|
+
useLayoutEffect2(() => {
|
|
4412
4679
|
const config = readTorphDebugConfig();
|
|
4413
4680
|
if (!shouldRunTorphInstrumentation(config)) {
|
|
4414
4681
|
debugDriftSignatureRef.current = null;
|
|
@@ -4451,55 +4718,171 @@ function useMorphTransition(text, className) {
|
|
|
4451
4718
|
drift: summarizeSnapshotDrift(drift)
|
|
4452
4719
|
});
|
|
4453
4720
|
}, [state, text]);
|
|
4454
|
-
|
|
4721
|
+
useLayoutEffect2(() => {
|
|
4455
4722
|
return () => {
|
|
4456
4723
|
cancelTimeline(timelineRef.current);
|
|
4457
4724
|
};
|
|
4458
4725
|
}, []);
|
|
4726
|
+
useLayoutEffect2(() => {
|
|
4727
|
+
if (state.stage !== "prepare" || state.measurement === null || state.plan === null) {
|
|
4728
|
+
return;
|
|
4729
|
+
}
|
|
4730
|
+
const root = ref.current;
|
|
4731
|
+
if (root === null) {
|
|
4732
|
+
return;
|
|
4733
|
+
}
|
|
4734
|
+
const nextOrigin = readRootOrigin(root);
|
|
4735
|
+
const nextMeasurement = resolvePreparedMeasurementOrigin(state.measurement, nextOrigin);
|
|
4736
|
+
const nextPlan = resolvePreparedPlanVisualBridge(state.plan, nextOrigin);
|
|
4737
|
+
if (nextMeasurement !== state.measurement || nextPlan !== state.plan) {
|
|
4738
|
+
sessionRef.current.target = nextMeasurement;
|
|
4739
|
+
logTransitionTrace("effect:prepare-refine", {
|
|
4740
|
+
preparedOrigin: {
|
|
4741
|
+
left: roundDebugValue(nextOrigin.left),
|
|
4742
|
+
top: roundDebugValue(nextOrigin.top)
|
|
4743
|
+
},
|
|
4744
|
+
refinedMeasurement: summarizeDebugMeasurement(nextMeasurement),
|
|
4745
|
+
refinedVisualBridge: {
|
|
4746
|
+
offsetX: roundDebugValue(nextPlan.visualBridge.offsetX),
|
|
4747
|
+
offsetY: roundDebugValue(nextPlan.visualBridge.offsetY)
|
|
4748
|
+
}
|
|
4749
|
+
});
|
|
4750
|
+
setState((current) => {
|
|
4751
|
+
if (current.stage !== "prepare" || current.measurement === null || current.plan === null) {
|
|
4752
|
+
return current;
|
|
4753
|
+
}
|
|
4754
|
+
if (current.measurement === nextMeasurement && current.plan === nextPlan) {
|
|
4755
|
+
return current;
|
|
4756
|
+
}
|
|
4757
|
+
return {
|
|
4758
|
+
stage: "prepare",
|
|
4759
|
+
measurement: nextMeasurement,
|
|
4760
|
+
plan: nextPlan
|
|
4761
|
+
};
|
|
4762
|
+
});
|
|
4763
|
+
return;
|
|
4764
|
+
}
|
|
4765
|
+
timelineRef.current.prepareFrame = requestAnimationFrame(() => {
|
|
4766
|
+
timelineRef.current.prepareFrame = null;
|
|
4767
|
+
timelineRef.current.animateFrame = requestAnimationFrame(() => {
|
|
4768
|
+
timelineRef.current.animateFrame = null;
|
|
4769
|
+
logTransitionTrace("effect:prepare-animate", {
|
|
4770
|
+
preparedOrigin: {
|
|
4771
|
+
left: roundDebugValue(nextOrigin.left),
|
|
4772
|
+
top: roundDebugValue(nextOrigin.top)
|
|
4773
|
+
},
|
|
4774
|
+
visualBridge: {
|
|
4775
|
+
offsetX: roundDebugValue(nextPlan.visualBridge.offsetX),
|
|
4776
|
+
offsetY: roundDebugValue(nextPlan.visualBridge.offsetY)
|
|
4777
|
+
}
|
|
4778
|
+
});
|
|
4779
|
+
setState((current) => {
|
|
4780
|
+
if (current.stage !== "prepare" || current.measurement === null || current.plan === null) {
|
|
4781
|
+
return current;
|
|
4782
|
+
}
|
|
4783
|
+
return {
|
|
4784
|
+
stage: "animate",
|
|
4785
|
+
measurement: current.measurement,
|
|
4786
|
+
plan: current.plan
|
|
4787
|
+
};
|
|
4788
|
+
});
|
|
4789
|
+
});
|
|
4790
|
+
});
|
|
4791
|
+
return () => {
|
|
4792
|
+
if (timelineRef.current.prepareFrame !== null) {
|
|
4793
|
+
cancelAnimationFrame(timelineRef.current.prepareFrame);
|
|
4794
|
+
timelineRef.current.prepareFrame = null;
|
|
4795
|
+
}
|
|
4796
|
+
if (timelineRef.current.animateFrame !== null) {
|
|
4797
|
+
cancelAnimationFrame(timelineRef.current.animateFrame);
|
|
4798
|
+
timelineRef.current.animateFrame = null;
|
|
4799
|
+
}
|
|
4800
|
+
};
|
|
4801
|
+
}, [state.measurement, state.plan, state.stage]);
|
|
4802
|
+
const finalizeMorphTransition2 = (measurement, reason) => {
|
|
4803
|
+
logTransitionTrace("effect:finalize-trigger", {
|
|
4804
|
+
reason,
|
|
4805
|
+
measurement: summarizeDebugMeasurement(measurement)
|
|
4806
|
+
});
|
|
4807
|
+
finalizeMorphTransition({
|
|
4808
|
+
session: sessionRef.current,
|
|
4809
|
+
timeline: timelineRef.current,
|
|
4810
|
+
measurement,
|
|
4811
|
+
setState
|
|
4812
|
+
});
|
|
4813
|
+
};
|
|
4459
4814
|
return {
|
|
4460
4815
|
debugInstanceId: debugInstanceIdRef.current,
|
|
4816
|
+
debugRenderOrdinal,
|
|
4461
4817
|
committedMeasurement: sessionRef.current.committed,
|
|
4462
4818
|
domMeasurementRequestKey,
|
|
4463
4819
|
flowTextRef,
|
|
4464
4820
|
ref,
|
|
4465
4821
|
measurementLayerRef,
|
|
4822
|
+
measurementBackend,
|
|
4823
|
+
domMeasurementKey,
|
|
4466
4824
|
renderText,
|
|
4467
4825
|
segments,
|
|
4468
4826
|
layoutContext,
|
|
4469
4827
|
state,
|
|
4470
|
-
useContentInlineSize
|
|
4828
|
+
useContentInlineSize,
|
|
4829
|
+
finalizeMorphTransition: finalizeMorphTransition2,
|
|
4830
|
+
timelineRef
|
|
4471
4831
|
};
|
|
4472
4832
|
}
|
|
4473
4833
|
function ActiveTorph({
|
|
4474
4834
|
text,
|
|
4475
4835
|
className
|
|
4476
4836
|
}) {
|
|
4477
|
-
const
|
|
4478
|
-
const
|
|
4479
|
-
const
|
|
4480
|
-
const
|
|
4481
|
-
const
|
|
4482
|
-
const
|
|
4483
|
-
const
|
|
4484
|
-
const
|
|
4837
|
+
const debugRenderOrdinalRef = useRef2(0);
|
|
4838
|
+
const overlayRef = useRef2(null);
|
|
4839
|
+
const debugFinalizeSignatureRef = useRef2(null);
|
|
4840
|
+
const debugFrameHandleRef = useRef2(null);
|
|
4841
|
+
const debugFrameOrdinalRef = useRef2(0);
|
|
4842
|
+
const debugAnimateTailFramesRef = useRef2([]);
|
|
4843
|
+
const debugIdlePostFrameHandleRef = useRef2(null);
|
|
4844
|
+
const debugIdlePostFrameOrdinalRef = useRef2(0);
|
|
4845
|
+
const debugIdlePostFrameTokenRef = useRef2(0);
|
|
4846
|
+
const debugPendingIdlePostFramesRef = useRef2(false);
|
|
4847
|
+
const debugPreviousStageRef = useRef2(null);
|
|
4848
|
+
debugRenderOrdinalRef.current += 1;
|
|
4849
|
+
const debugRenderOrdinal = debugRenderOrdinalRef.current;
|
|
4485
4850
|
const {
|
|
4486
4851
|
debugInstanceId,
|
|
4852
|
+
debugRenderOrdinal: hookRenderOrdinal,
|
|
4487
4853
|
committedMeasurement,
|
|
4488
4854
|
domMeasurementRequestKey,
|
|
4855
|
+
domMeasurementKey,
|
|
4489
4856
|
flowTextRef,
|
|
4490
4857
|
ref,
|
|
4491
4858
|
measurementLayerRef,
|
|
4859
|
+
measurementBackend,
|
|
4492
4860
|
renderText,
|
|
4493
4861
|
segments,
|
|
4494
4862
|
layoutContext,
|
|
4495
4863
|
state,
|
|
4496
|
-
useContentInlineSize
|
|
4864
|
+
useContentInlineSize,
|
|
4865
|
+
finalizeMorphTransition: finalizeMorphTransition2,
|
|
4866
|
+
timelineRef
|
|
4497
4867
|
} = useMorphTransition(text, className);
|
|
4498
4868
|
const plan = state.plan;
|
|
4499
|
-
|
|
4869
|
+
let visibleGlyphPlan = plan;
|
|
4870
|
+
if (state.stage === "idle" && state.measurement !== null) {
|
|
4871
|
+
visibleGlyphPlan = createSteadyGlyphPlan(state.measurement);
|
|
4872
|
+
}
|
|
4873
|
+
let sourceSliceWhiteSpace = "inherit";
|
|
4874
|
+
if (committedMeasurement !== null) {
|
|
4875
|
+
sourceSliceWhiteSpace = resolveGlyphSliceWhiteSpace(committedMeasurement.snapshot);
|
|
4876
|
+
}
|
|
4877
|
+
let targetSliceWhiteSpace = "inherit";
|
|
4878
|
+
if (state.measurement !== null) {
|
|
4879
|
+
targetSliceWhiteSpace = resolveGlyphSliceWhiteSpace(state.measurement.snapshot);
|
|
4880
|
+
}
|
|
4881
|
+
const shouldRenderGlyphLayer2 = shouldRenderGlyphLayer(state.stage, visibleGlyphPlan, state.measurement);
|
|
4882
|
+
const shouldHideFlowText = shouldRenderGlyphLayer2;
|
|
4500
4883
|
const shouldRenderMeasurementLayer = domMeasurementRequestKey !== null;
|
|
4501
4884
|
const flowText = resolveFlowText(committedMeasurement, state.measurement, text);
|
|
4502
|
-
|
|
4885
|
+
useLayoutEffect2(() => {
|
|
4503
4886
|
const config = readTorphDebugConfig();
|
|
4504
4887
|
if (!shouldRunTorphInstrumentation(config)) {
|
|
4505
4888
|
return;
|
|
@@ -4507,11 +4890,264 @@ function ActiveTorph({
|
|
|
4507
4890
|
logTorphDebug(debugInstanceId, "effect:trace-meta", {
|
|
4508
4891
|
traceSchemaVersion: TORPH_TRACE_SCHEMA_VERSION,
|
|
4509
4892
|
includesIdlePostFrame: true,
|
|
4893
|
+
includesIdlePostFrameLifecycle: true,
|
|
4510
4894
|
includesViewportAnchors: true,
|
|
4511
|
-
includesRootOriginRefine: true
|
|
4895
|
+
includesRootOriginRefine: true,
|
|
4896
|
+
includesFullGlyphLayouts: true,
|
|
4897
|
+
includesIdleVisibleGlyphLayer: true,
|
|
4898
|
+
includesPreciseGlyphGeometry: true,
|
|
4899
|
+
includesAnimateTailFrames: true,
|
|
4900
|
+
includesLiveNodeStyles: true
|
|
4512
4901
|
});
|
|
4513
4902
|
}, [debugInstanceId]);
|
|
4514
|
-
|
|
4903
|
+
useLayoutEffect2(() => {
|
|
4904
|
+
const config = readTorphDebugConfig();
|
|
4905
|
+
if (!shouldRunTorphInstrumentation(config)) {
|
|
4906
|
+
debugFinalizeSignatureRef.current = null;
|
|
4907
|
+
return;
|
|
4908
|
+
}
|
|
4909
|
+
if (state.stage !== "animate" || state.measurement === null || plan === null) {
|
|
4910
|
+
debugFinalizeSignatureRef.current = null;
|
|
4911
|
+
}
|
|
4912
|
+
}, [plan, state.measurement, state.stage]);
|
|
4913
|
+
const logAnimateFinalizeSnapshot = (measurement, activePlan, reason, barrier, signal, event) => {
|
|
4914
|
+
const config = readTorphDebugConfig();
|
|
4915
|
+
if (!shouldRunTorphInstrumentation(config)) {
|
|
4916
|
+
return;
|
|
4917
|
+
}
|
|
4918
|
+
const root = ref.current;
|
|
4919
|
+
const overlayNode = overlayRef.current;
|
|
4920
|
+
const flowNode = flowTextRef.current;
|
|
4921
|
+
if (root === null || overlayNode === null || flowNode === null) {
|
|
4922
|
+
return;
|
|
4923
|
+
}
|
|
4924
|
+
const overlayLiveSnapshot = measureOverlayBoxSnapshot(root, overlayNode, "live");
|
|
4925
|
+
const overlayExitSnapshot = measureOverlayBoxSnapshot(root, overlayNode, "exit");
|
|
4926
|
+
const flowSnapshot = measureLiveFlowSnapshot(root, flowNode);
|
|
4927
|
+
if (overlayLiveSnapshot === null || flowSnapshot === null) {
|
|
4928
|
+
return;
|
|
4929
|
+
}
|
|
4930
|
+
const overlayLiveDrift = measureSnapshotDrift(measurement.snapshot, overlayLiveSnapshot);
|
|
4931
|
+
const flowDrift = measureSnapshotDrift(measurement.snapshot, flowSnapshot);
|
|
4932
|
+
const rootRect = root.getBoundingClientRect();
|
|
4933
|
+
const flowRect = flowNode.getBoundingClientRect();
|
|
4934
|
+
const overlayRect = overlayNode.getBoundingClientRect();
|
|
4935
|
+
const signature = JSON.stringify({
|
|
4936
|
+
text,
|
|
4937
|
+
renderText: measurement.snapshot.renderText,
|
|
4938
|
+
reason,
|
|
4939
|
+
signal,
|
|
4940
|
+
barrier: summarizeMorphFinalizeBarrier(barrier),
|
|
4941
|
+
overlayLiveDrift: summarizeSnapshotDrift(overlayLiveDrift),
|
|
4942
|
+
flowDrift: summarizeSnapshotDrift(flowDrift),
|
|
4943
|
+
overlayWidth: roundDebugValue(overlayRect.width),
|
|
4944
|
+
rootWidth: roundDebugValue(rootRect.width)
|
|
4945
|
+
});
|
|
4946
|
+
if (debugFinalizeSignatureRef.current === signature) {
|
|
4947
|
+
return;
|
|
4948
|
+
}
|
|
4949
|
+
debugFinalizeSignatureRef.current = signature;
|
|
4950
|
+
let morphRole = null;
|
|
4951
|
+
let morphKey = null;
|
|
4952
|
+
let morphGlyph = null;
|
|
4953
|
+
const target = event?.target;
|
|
4954
|
+
if (target instanceof HTMLElement) {
|
|
4955
|
+
morphRole = target.dataset.morphRole ?? null;
|
|
4956
|
+
morphKey = target.dataset.morphKey ?? null;
|
|
4957
|
+
morphGlyph = target.dataset.morphGlyph ?? null;
|
|
4958
|
+
}
|
|
4959
|
+
logTorphDebug(debugInstanceId, "effect:animate-finalize-snapshot", {
|
|
4960
|
+
text,
|
|
4961
|
+
reason,
|
|
4962
|
+
propertyName: event?.propertyName ?? null,
|
|
4963
|
+
finalizeSignal: signal,
|
|
4964
|
+
morphRole,
|
|
4965
|
+
morphKey,
|
|
4966
|
+
morphGlyph,
|
|
4967
|
+
barrier: summarizeMorphFinalizeBarrier(barrier),
|
|
4968
|
+
target: {
|
|
4969
|
+
layoutInlineSize: roundDebugValue(measurement.layoutInlineSize),
|
|
4970
|
+
reservedInlineSize: roundDebugValue(measurement.reservedInlineSize),
|
|
4971
|
+
flowInlineSize: roundDebugValue(measurement.flowInlineSize),
|
|
4972
|
+
rootOrigin: {
|
|
4973
|
+
left: roundDebugValue(measurement.rootOrigin.left),
|
|
4974
|
+
top: roundDebugValue(measurement.rootOrigin.top)
|
|
4975
|
+
},
|
|
4976
|
+
snapshot: summarizeDebugSnapshot(measurement.snapshot)
|
|
4977
|
+
},
|
|
4978
|
+
plan: {
|
|
4979
|
+
frameWidth: roundDebugValue(activePlan.frameWidth),
|
|
4980
|
+
frameHeight: roundDebugValue(activePlan.frameHeight),
|
|
4981
|
+
layoutInlineSizeFrom: roundDebugValue(activePlan.layoutInlineSizeFrom),
|
|
4982
|
+
layoutInlineSizeTo: roundDebugValue(activePlan.layoutInlineSizeTo),
|
|
4983
|
+
sourceRenderText: activePlan.sourceRenderText,
|
|
4984
|
+
targetRenderText: activePlan.targetRenderText
|
|
4985
|
+
},
|
|
4986
|
+
overlayLive: summarizeDebugSnapshot(overlayLiveSnapshot),
|
|
4987
|
+
overlayLiveGlyphs: summarizeDebugGlyphs(overlayLiveSnapshot),
|
|
4988
|
+
overlayLiveGlyphsPrecise: summarizePreciseGlyphs(overlayLiveSnapshot, rootRect),
|
|
4989
|
+
overlayLiveDrift: summarizeSnapshotDrift(overlayLiveDrift),
|
|
4990
|
+
overlayExit: summarizeDebugSnapshot(overlayExitSnapshot),
|
|
4991
|
+
overlayExitGlyphs: summarizeDebugGlyphs(overlayExitSnapshot),
|
|
4992
|
+
flow: summarizeDebugSnapshot(flowSnapshot),
|
|
4993
|
+
flowGlyphs: summarizeDebugGlyphs(flowSnapshot),
|
|
4994
|
+
flowGlyphsPrecise: summarizePreciseGlyphs(flowSnapshot, rootRect),
|
|
4995
|
+
flowDrift: summarizeSnapshotDrift(flowDrift),
|
|
4996
|
+
rootOriginDrift: summarizeDebugRootOriginDrift(measurement, rootRect),
|
|
4997
|
+
overlayLiveViewportAnchors: summarizeDebugViewportAnchors(overlayLiveSnapshot, rootRect),
|
|
4998
|
+
overlayExitViewportAnchors: summarizeDebugViewportAnchors(overlayExitSnapshot, rootRect),
|
|
4999
|
+
flowViewportAnchors: summarizeDebugViewportAnchors(flowSnapshot, rootRect),
|
|
5000
|
+
rootBox: {
|
|
5001
|
+
width: roundDebugValue(rootRect.width),
|
|
5002
|
+
height: roundDebugValue(rootRect.height)
|
|
5003
|
+
},
|
|
5004
|
+
overlayBox: {
|
|
5005
|
+
width: roundDebugValue(overlayRect.width),
|
|
5006
|
+
height: roundDebugValue(overlayRect.height)
|
|
5007
|
+
},
|
|
5008
|
+
flowBox: {
|
|
5009
|
+
width: roundDebugValue(flowRect.width),
|
|
5010
|
+
height: roundDebugValue(flowRect.height)
|
|
5011
|
+
},
|
|
5012
|
+
rootBoxPrecise: summarizePreciseRect(rootRect),
|
|
5013
|
+
overlayBoxPrecise: summarizePreciseRect(overlayRect),
|
|
5014
|
+
flowBoxPrecise: summarizePreciseRect(flowRect),
|
|
5015
|
+
rootRuntimeStyles: summarizeRootRuntimeStyles(root),
|
|
5016
|
+
overlayLiveNodeStyles: summarizeLiveNodeStyles(overlayNode),
|
|
5017
|
+
animateTailFrames: debugAnimateTailFramesRef.current
|
|
5018
|
+
});
|
|
5019
|
+
debugAnimateTailFramesRef.current = [];
|
|
5020
|
+
};
|
|
5021
|
+
useLayoutEffect2(() => {
|
|
5022
|
+
if (state.stage !== "animate" || state.measurement === null || plan === null) {
|
|
5023
|
+
return;
|
|
5024
|
+
}
|
|
5025
|
+
const root = ref.current;
|
|
5026
|
+
if (root === null) {
|
|
5027
|
+
return;
|
|
5028
|
+
}
|
|
5029
|
+
const measurement = state.measurement;
|
|
5030
|
+
const hasMoveTransitions = plan.liveItems.some((item) => item.kind === "move");
|
|
5031
|
+
let barrier = createMorphFinalizeBarrier(hasMoveTransitions);
|
|
5032
|
+
let finalizeScheduled = false;
|
|
5033
|
+
let finalizeCommitted = false;
|
|
5034
|
+
let finalizeFrame = null;
|
|
5035
|
+
const armedAt = performance.now();
|
|
5036
|
+
const finalizeNow = (reason, signal, barrierState, event) => {
|
|
5037
|
+
if (finalizeCommitted) {
|
|
5038
|
+
return;
|
|
5039
|
+
}
|
|
5040
|
+
finalizeCommitted = true;
|
|
5041
|
+
const target = event?.target;
|
|
5042
|
+
let morphRole = null;
|
|
5043
|
+
let morphKey = null;
|
|
5044
|
+
let morphGlyph = null;
|
|
5045
|
+
if (target instanceof HTMLElement) {
|
|
5046
|
+
morphRole = target.dataset.morphRole ?? null;
|
|
5047
|
+
morphKey = target.dataset.morphKey ?? null;
|
|
5048
|
+
morphGlyph = target.dataset.morphGlyph ?? null;
|
|
5049
|
+
}
|
|
5050
|
+
logAnimateFinalizeSnapshot(measurement, plan, reason, barrierState, signal, event);
|
|
5051
|
+
finalizeMorphTransition2(measurement, reason);
|
|
5052
|
+
const config = readTorphDebugConfig();
|
|
5053
|
+
if (!shouldRunTorphInstrumentation(config)) {
|
|
5054
|
+
return;
|
|
5055
|
+
}
|
|
5056
|
+
logTorphDebug(debugInstanceId, "effect:finalize-authority", {
|
|
5057
|
+
text,
|
|
5058
|
+
reason,
|
|
5059
|
+
propertyName: event?.propertyName ?? null,
|
|
5060
|
+
morphRole,
|
|
5061
|
+
morphKey,
|
|
5062
|
+
morphGlyph,
|
|
5063
|
+
elapsedMs: roundDebugValue(performance.now() - armedAt),
|
|
5064
|
+
hasMoveTransitions,
|
|
5065
|
+
finalizeSignal: signal,
|
|
5066
|
+
barrier: summarizeMorphFinalizeBarrier(barrierState),
|
|
5067
|
+
measurement: summarizeDebugMeasurement(measurement)
|
|
5068
|
+
});
|
|
5069
|
+
};
|
|
5070
|
+
const scheduleFinalize = (reason, signal, barrierState, event) => {
|
|
5071
|
+
if (finalizeCommitted || finalizeScheduled) {
|
|
5072
|
+
return;
|
|
5073
|
+
}
|
|
5074
|
+
finalizeScheduled = true;
|
|
5075
|
+
if (timelineRef.current.finalizeTimer !== null) {
|
|
5076
|
+
window.clearTimeout(timelineRef.current.finalizeTimer);
|
|
5077
|
+
timelineRef.current.finalizeTimer = null;
|
|
5078
|
+
}
|
|
5079
|
+
logTorphDebug(debugInstanceId, "effect:finalize-raf-schedule", {
|
|
5080
|
+
text,
|
|
5081
|
+
reason,
|
|
5082
|
+
propertyName: event?.propertyName ?? null,
|
|
5083
|
+
finalizeSignal: signal,
|
|
5084
|
+
elapsedMs: roundDebugValue(performance.now() - armedAt),
|
|
5085
|
+
barrier: summarizeMorphFinalizeBarrier(barrierState)
|
|
5086
|
+
});
|
|
5087
|
+
finalizeFrame = requestAnimationFrame(() => {
|
|
5088
|
+
finalizeFrame = null;
|
|
5089
|
+
finalizeNow(reason, signal, barrierState, event);
|
|
5090
|
+
});
|
|
5091
|
+
};
|
|
5092
|
+
const onTransitionEnd = (event) => {
|
|
5093
|
+
const signal = resolveMorphFinalizeSignal(event, hasMoveTransitions);
|
|
5094
|
+
if (signal === null) {
|
|
5095
|
+
return;
|
|
5096
|
+
}
|
|
5097
|
+
barrier = recordMorphFinalizeSignal(barrier, signal);
|
|
5098
|
+
const target = event.target;
|
|
5099
|
+
let morphRole = null;
|
|
5100
|
+
let morphKey = null;
|
|
5101
|
+
let morphGlyph = null;
|
|
5102
|
+
if (target instanceof HTMLElement) {
|
|
5103
|
+
morphRole = target.dataset.morphRole ?? null;
|
|
5104
|
+
morphKey = target.dataset.morphKey ?? null;
|
|
5105
|
+
morphGlyph = target.dataset.morphGlyph ?? null;
|
|
5106
|
+
}
|
|
5107
|
+
logTorphDebug(debugInstanceId, "effect:finalize-barrier-progress", {
|
|
5108
|
+
text,
|
|
5109
|
+
propertyName: event.propertyName,
|
|
5110
|
+
signal,
|
|
5111
|
+
morphRole,
|
|
5112
|
+
morphKey,
|
|
5113
|
+
morphGlyph,
|
|
5114
|
+
elapsedMs: roundDebugValue(performance.now() - armedAt),
|
|
5115
|
+
barrier: summarizeMorphFinalizeBarrier(barrier)
|
|
5116
|
+
});
|
|
5117
|
+
if (!isMorphFinalizeBarrierSatisfied(barrier)) {
|
|
5118
|
+
return;
|
|
5119
|
+
}
|
|
5120
|
+
scheduleFinalize("transitionend", signal, barrier, event);
|
|
5121
|
+
};
|
|
5122
|
+
root.addEventListener("transitionend", onTransitionEnd);
|
|
5123
|
+
if (timelineRef.current.finalizeTimer !== null) {
|
|
5124
|
+
window.clearTimeout(timelineRef.current.finalizeTimer);
|
|
5125
|
+
}
|
|
5126
|
+
timelineRef.current.finalizeTimer = window.setTimeout(() => {
|
|
5127
|
+
timelineRef.current.finalizeTimer = null;
|
|
5128
|
+
scheduleFinalize("watchdog-timeout", null, barrier);
|
|
5129
|
+
}, MORPH.durationMs + 32);
|
|
5130
|
+
return () => {
|
|
5131
|
+
root.removeEventListener("transitionend", onTransitionEnd);
|
|
5132
|
+
if (finalizeFrame !== null) {
|
|
5133
|
+
cancelAnimationFrame(finalizeFrame);
|
|
5134
|
+
finalizeFrame = null;
|
|
5135
|
+
}
|
|
5136
|
+
if (timelineRef.current.finalizeTimer !== null) {
|
|
5137
|
+
window.clearTimeout(timelineRef.current.finalizeTimer);
|
|
5138
|
+
timelineRef.current.finalizeTimer = null;
|
|
5139
|
+
}
|
|
5140
|
+
};
|
|
5141
|
+
}, [
|
|
5142
|
+
debugInstanceId,
|
|
5143
|
+
finalizeMorphTransition2,
|
|
5144
|
+
plan,
|
|
5145
|
+
state.measurement,
|
|
5146
|
+
state.stage,
|
|
5147
|
+
text,
|
|
5148
|
+
timelineRef
|
|
5149
|
+
]);
|
|
5150
|
+
useLayoutEffect2(() => {
|
|
4515
5151
|
const config = readTorphDebugConfig();
|
|
4516
5152
|
if (!shouldRunTorphInstrumentation(config)) {
|
|
4517
5153
|
debugPendingIdlePostFramesRef.current = false;
|
|
@@ -4522,25 +5158,34 @@ function ActiveTorph({
|
|
|
4522
5158
|
if (previousStage !== state.stage) {
|
|
4523
5159
|
if (state.stage === "idle") {
|
|
4524
5160
|
debugPendingIdlePostFramesRef.current = true;
|
|
5161
|
+
debugIdlePostFrameTokenRef.current += 1;
|
|
5162
|
+
} else {
|
|
5163
|
+
debugPendingIdlePostFramesRef.current = false;
|
|
4525
5164
|
}
|
|
4526
5165
|
logTorphDebug(debugInstanceId, "effect:stage-transition", {
|
|
5166
|
+
traceSchemaVersion: TORPH_TRACE_SCHEMA_VERSION,
|
|
5167
|
+
renderOrdinal: debugRenderOrdinal,
|
|
4527
5168
|
text,
|
|
4528
5169
|
fromStage: previousStage,
|
|
4529
5170
|
toStage: state.stage,
|
|
4530
5171
|
committed: summarizeDebugMeasurement(committedMeasurement),
|
|
4531
5172
|
stateMeasurement: summarizeDebugMeasurement(state.measurement),
|
|
4532
|
-
flowText
|
|
5173
|
+
flowText,
|
|
5174
|
+
domMeasurementRequestKey,
|
|
5175
|
+
domMeasurementKey,
|
|
5176
|
+
measurementBackend
|
|
4533
5177
|
});
|
|
4534
5178
|
debugPreviousStageRef.current = state.stage;
|
|
4535
5179
|
}
|
|
4536
5180
|
}, [committedMeasurement, debugInstanceId, flowText, state, text]);
|
|
4537
|
-
|
|
5181
|
+
useLayoutEffect2(() => {
|
|
4538
5182
|
const config = readTorphDebugConfig();
|
|
4539
5183
|
if (!shouldRunTorphInstrumentation(config)) {
|
|
4540
5184
|
if (debugFrameHandleRef.current !== null) {
|
|
4541
5185
|
cancelAnimationFrame(debugFrameHandleRef.current);
|
|
4542
5186
|
debugFrameHandleRef.current = null;
|
|
4543
5187
|
}
|
|
5188
|
+
debugAnimateTailFramesRef.current = [];
|
|
4544
5189
|
return;
|
|
4545
5190
|
}
|
|
4546
5191
|
if (state.stage === "idle" || state.measurement === null) {
|
|
@@ -4549,6 +5194,7 @@ function ActiveTorph({
|
|
|
4549
5194
|
debugFrameHandleRef.current = null;
|
|
4550
5195
|
}
|
|
4551
5196
|
debugFrameOrdinalRef.current = 0;
|
|
5197
|
+
debugAnimateTailFramesRef.current = [];
|
|
4552
5198
|
return;
|
|
4553
5199
|
}
|
|
4554
5200
|
debugFrameOrdinalRef.current = 0;
|
|
@@ -4593,6 +5239,19 @@ function ActiveTorph({
|
|
|
4593
5239
|
if (flowSnapshot !== null) {
|
|
4594
5240
|
flowDrift = summarizeSnapshotDrift(measureSnapshotDrift(measurement.snapshot, flowSnapshot));
|
|
4595
5241
|
}
|
|
5242
|
+
debugAnimateTailFramesRef.current.push({
|
|
5243
|
+
frame: debugFrameOrdinalRef.current,
|
|
5244
|
+
stateStage: state.stage,
|
|
5245
|
+
rootBoxPrecise: summarizePreciseRect(rootRect),
|
|
5246
|
+
overlayBoxPrecise: summarizePreciseRect(overlayRect),
|
|
5247
|
+
flowBoxPrecise: summarizePreciseRect(flowRect),
|
|
5248
|
+
overlayLiveGlyphsPrecise: summarizePreciseGlyphs(overlayLiveSnapshot, rootRect),
|
|
5249
|
+
flowGlyphsPrecise: summarizePreciseGlyphs(flowSnapshot, rootRect),
|
|
5250
|
+
overlayLiveNodeStyles: summarizeLiveNodeStyles(overlayNode)
|
|
5251
|
+
});
|
|
5252
|
+
if (debugAnimateTailFramesRef.current.length > 8) {
|
|
5253
|
+
debugAnimateTailFramesRef.current.shift();
|
|
5254
|
+
}
|
|
4596
5255
|
let planSummary = null;
|
|
4597
5256
|
if (plan !== null) {
|
|
4598
5257
|
planSummary = {
|
|
@@ -4624,13 +5283,17 @@ function ActiveTorph({
|
|
|
4624
5283
|
flowBox: summarizeDebugRect(flowRect),
|
|
4625
5284
|
rootOriginDrift: summarizeDebugRootOriginDrift(measurement, rootRect),
|
|
4626
5285
|
overlayLive: summarizeDebugSnapshot(overlayLiveSnapshot),
|
|
5286
|
+
overlayLiveGlyphs: summarizeDebugGlyphs(overlayLiveSnapshot),
|
|
4627
5287
|
overlayLiveViewportAnchors: summarizeDebugViewportAnchors(overlayLiveSnapshot, rootRect),
|
|
4628
5288
|
overlayLiveDrift,
|
|
4629
5289
|
overlayExit: summarizeDebugSnapshot(overlayExitSnapshot),
|
|
5290
|
+
overlayExitGlyphs: summarizeDebugGlyphs(overlayExitSnapshot),
|
|
4630
5291
|
overlayExitViewportAnchors: summarizeDebugViewportAnchors(overlayExitSnapshot, rootRect),
|
|
4631
5292
|
flow: summarizeDebugSnapshot(flowSnapshot),
|
|
5293
|
+
flowGlyphs: summarizeDebugGlyphs(flowSnapshot),
|
|
4632
5294
|
flowViewportAnchors: summarizeDebugViewportAnchors(flowSnapshot, rootRect),
|
|
4633
|
-
flowDrift
|
|
5295
|
+
flowDrift,
|
|
5296
|
+
rootRuntimeStyles: summarizeRootRuntimeStyles(root)
|
|
4634
5297
|
});
|
|
4635
5298
|
debugFrameOrdinalRef.current += 1;
|
|
4636
5299
|
debugFrameHandleRef.current = requestAnimationFrame(captureFrame);
|
|
@@ -4644,11 +5307,22 @@ function ActiveTorph({
|
|
|
4644
5307
|
}
|
|
4645
5308
|
};
|
|
4646
5309
|
}, [committedMeasurement, debugInstanceId, flowText, plan, ref, state, text]);
|
|
4647
|
-
|
|
5310
|
+
useLayoutEffect2(() => {
|
|
4648
5311
|
const config = readTorphDebugConfig();
|
|
4649
5312
|
if (!shouldRunTorphInstrumentation(config)) {
|
|
4650
5313
|
debugPendingIdlePostFramesRef.current = false;
|
|
4651
5314
|
if (debugIdlePostFrameHandleRef.current !== null) {
|
|
5315
|
+
logTorphDebug(debugInstanceId, "effect:idle-post-frame-cleanup", {
|
|
5316
|
+
traceSchemaVersion: TORPH_TRACE_SCHEMA_VERSION,
|
|
5317
|
+
reason: "instrumentation-disabled",
|
|
5318
|
+
renderOrdinal: debugRenderOrdinal,
|
|
5319
|
+
hookRenderOrdinal,
|
|
5320
|
+
token: debugIdlePostFrameTokenRef.current,
|
|
5321
|
+
handle: debugIdlePostFrameHandleRef.current,
|
|
5322
|
+
domMeasurementRequestKey,
|
|
5323
|
+
domMeasurementKey,
|
|
5324
|
+
measurementBackend
|
|
5325
|
+
});
|
|
4652
5326
|
cancelAnimationFrame(debugIdlePostFrameHandleRef.current);
|
|
4653
5327
|
debugIdlePostFrameHandleRef.current = null;
|
|
4654
5328
|
}
|
|
@@ -4660,28 +5334,93 @@ function ActiveTorph({
|
|
|
4660
5334
|
if (state.stage !== "idle" || state.measurement === null) {
|
|
4661
5335
|
return;
|
|
4662
5336
|
}
|
|
4663
|
-
debugPendingIdlePostFramesRef.current = false;
|
|
4664
5337
|
debugIdlePostFrameOrdinalRef.current = 0;
|
|
5338
|
+
const token = debugIdlePostFrameTokenRef.current;
|
|
5339
|
+
const scheduledRenderOrdinal = debugRenderOrdinal;
|
|
5340
|
+
const scheduledHookRenderOrdinal = hookRenderOrdinal;
|
|
4665
5341
|
const measurement = state.measurement;
|
|
4666
5342
|
let remainingFrames = 3;
|
|
4667
5343
|
let cancelled = false;
|
|
5344
|
+
logTorphDebug(debugInstanceId, "effect:idle-post-frame-arm", {
|
|
5345
|
+
traceSchemaVersion: TORPH_TRACE_SCHEMA_VERSION,
|
|
5346
|
+
renderOrdinal: scheduledRenderOrdinal,
|
|
5347
|
+
hookRenderOrdinal: scheduledHookRenderOrdinal,
|
|
5348
|
+
token,
|
|
5349
|
+
text,
|
|
5350
|
+
stateStage: state.stage,
|
|
5351
|
+
flowText,
|
|
5352
|
+
committed: summarizeDebugMeasurement(committedMeasurement),
|
|
5353
|
+
stateMeasurement: summarizeDebugMeasurement(measurement),
|
|
5354
|
+
domMeasurementRequestKey,
|
|
5355
|
+
domMeasurementKey,
|
|
5356
|
+
measurementBackend
|
|
5357
|
+
});
|
|
4668
5358
|
const captureIdlePostFrame = () => {
|
|
4669
5359
|
if (cancelled) {
|
|
4670
5360
|
return;
|
|
4671
5361
|
}
|
|
5362
|
+
if (debugPendingIdlePostFramesRef.current) {
|
|
5363
|
+
debugPendingIdlePostFramesRef.current = false;
|
|
5364
|
+
}
|
|
5365
|
+
logTorphDebug(debugInstanceId, "effect:idle-post-frame-fire", {
|
|
5366
|
+
traceSchemaVersion: TORPH_TRACE_SCHEMA_VERSION,
|
|
5367
|
+
renderOrdinal: debugRenderOrdinalRef.current,
|
|
5368
|
+
hookRenderOrdinal,
|
|
5369
|
+
scheduledRenderOrdinal,
|
|
5370
|
+
scheduledHookRenderOrdinal,
|
|
5371
|
+
token,
|
|
5372
|
+
frame: debugIdlePostFrameOrdinalRef.current,
|
|
5373
|
+
remainingFrames,
|
|
5374
|
+
text,
|
|
5375
|
+
stateStage: state.stage,
|
|
5376
|
+
flowText
|
|
5377
|
+
});
|
|
4672
5378
|
const root = ref.current;
|
|
4673
5379
|
const flowNode = flowTextRef.current;
|
|
4674
|
-
|
|
5380
|
+
const overlayNode = overlayRef.current;
|
|
5381
|
+
if (root === null || flowNode === null || overlayNode === null) {
|
|
5382
|
+
logTorphDebug(debugInstanceId, "effect:idle-post-frame-skip", {
|
|
5383
|
+
traceSchemaVersion: TORPH_TRACE_SCHEMA_VERSION,
|
|
5384
|
+
renderOrdinal: debugRenderOrdinalRef.current,
|
|
5385
|
+
hookRenderOrdinal,
|
|
5386
|
+
scheduledRenderOrdinal,
|
|
5387
|
+
scheduledHookRenderOrdinal,
|
|
5388
|
+
token,
|
|
5389
|
+
text,
|
|
5390
|
+
stateStage: state.stage,
|
|
5391
|
+
frame: debugIdlePostFrameOrdinalRef.current,
|
|
5392
|
+
hasRoot: root !== null,
|
|
5393
|
+
hasFlowNode: flowNode !== null,
|
|
5394
|
+
hasOverlayNode: overlayNode !== null,
|
|
5395
|
+
flowText,
|
|
5396
|
+
committed: summarizeDebugMeasurement(committedMeasurement),
|
|
5397
|
+
stateMeasurement: summarizeDebugMeasurement(measurement)
|
|
5398
|
+
});
|
|
4675
5399
|
return;
|
|
4676
5400
|
}
|
|
4677
5401
|
const rootRect = root.getBoundingClientRect();
|
|
4678
5402
|
const flowRect = flowNode.getBoundingClientRect();
|
|
5403
|
+
const overlayRect = overlayNode.getBoundingClientRect();
|
|
4679
5404
|
const flowSnapshot = measureLiveFlowSnapshot(root, flowNode);
|
|
5405
|
+
let visibleSnapshot = null;
|
|
5406
|
+
if (overlayNode !== null) {
|
|
5407
|
+
visibleSnapshot = measureOverlayBoxSnapshot(root, overlayNode, "live");
|
|
5408
|
+
}
|
|
4680
5409
|
let flowDrift = null;
|
|
4681
5410
|
if (flowSnapshot !== null) {
|
|
4682
5411
|
flowDrift = summarizeSnapshotDrift(measureSnapshotDrift(measurement.snapshot, flowSnapshot));
|
|
4683
5412
|
}
|
|
5413
|
+
let visibleDrift = null;
|
|
5414
|
+
if (visibleSnapshot !== null) {
|
|
5415
|
+
visibleDrift = summarizeSnapshotDrift(measureSnapshotDrift(measurement.snapshot, visibleSnapshot));
|
|
5416
|
+
}
|
|
4684
5417
|
logTorphDebug(debugInstanceId, "effect:idle-post-frame", {
|
|
5418
|
+
traceSchemaVersion: TORPH_TRACE_SCHEMA_VERSION,
|
|
5419
|
+
renderOrdinal: debugRenderOrdinalRef.current,
|
|
5420
|
+
hookRenderOrdinal,
|
|
5421
|
+
scheduledRenderOrdinal,
|
|
5422
|
+
scheduledHookRenderOrdinal,
|
|
5423
|
+
token,
|
|
4685
5424
|
text,
|
|
4686
5425
|
frame: debugIdlePostFrameOrdinalRef.current,
|
|
4687
5426
|
stateStage: state.stage,
|
|
@@ -4690,11 +5429,24 @@ function ActiveTorph({
|
|
|
4690
5429
|
committed: summarizeDebugMeasurement(committedMeasurement),
|
|
4691
5430
|
stateMeasurement: summarizeDebugMeasurement(measurement),
|
|
4692
5431
|
rootBox: summarizeDebugRect(rootRect),
|
|
5432
|
+
rootBoxPrecise: summarizePreciseRect(rootRect),
|
|
5433
|
+
overlayBox: summarizeDebugRect(overlayRect),
|
|
5434
|
+
overlayBoxPrecise: summarizePreciseRect(overlayRect),
|
|
4693
5435
|
flowBox: summarizeDebugRect(flowRect),
|
|
5436
|
+
flowBoxPrecise: summarizePreciseRect(flowRect),
|
|
5437
|
+
rootRuntimeStyles: summarizeRootRuntimeStyles(root),
|
|
4694
5438
|
rootOriginDrift: summarizeDebugRootOriginDrift(measurement, rootRect),
|
|
4695
5439
|
flow: summarizeDebugSnapshot(flowSnapshot),
|
|
5440
|
+
flowGlyphs: summarizeDebugGlyphs(flowSnapshot),
|
|
5441
|
+
flowGlyphsPrecise: summarizePreciseGlyphs(flowSnapshot, rootRect),
|
|
4696
5442
|
flowViewportAnchors: summarizeDebugViewportAnchors(flowSnapshot, rootRect),
|
|
4697
|
-
flowDrift
|
|
5443
|
+
flowDrift,
|
|
5444
|
+
visible: summarizeDebugSnapshot(visibleSnapshot),
|
|
5445
|
+
visibleGlyphs: summarizeDebugGlyphs(visibleSnapshot),
|
|
5446
|
+
visibleGlyphsPrecise: summarizePreciseGlyphs(visibleSnapshot, rootRect),
|
|
5447
|
+
visibleViewportAnchors: summarizeDebugViewportAnchors(visibleSnapshot, rootRect),
|
|
5448
|
+
visibleDrift,
|
|
5449
|
+
visibleLiveNodeStyles: summarizeLiveNodeStyles(overlayNode)
|
|
4698
5450
|
});
|
|
4699
5451
|
debugIdlePostFrameOrdinalRef.current += 1;
|
|
4700
5452
|
remainingFrames -= 1;
|
|
@@ -4703,121 +5455,77 @@ function ActiveTorph({
|
|
|
4703
5455
|
return;
|
|
4704
5456
|
}
|
|
4705
5457
|
debugIdlePostFrameHandleRef.current = requestAnimationFrame(captureIdlePostFrame);
|
|
5458
|
+
logTorphDebug(debugInstanceId, "effect:idle-post-frame-reschedule", {
|
|
5459
|
+
traceSchemaVersion: TORPH_TRACE_SCHEMA_VERSION,
|
|
5460
|
+
renderOrdinal: debugRenderOrdinalRef.current,
|
|
5461
|
+
hookRenderOrdinal,
|
|
5462
|
+
scheduledRenderOrdinal,
|
|
5463
|
+
scheduledHookRenderOrdinal,
|
|
5464
|
+
token,
|
|
5465
|
+
handle: debugIdlePostFrameHandleRef.current,
|
|
5466
|
+
nextFrame: debugIdlePostFrameOrdinalRef.current,
|
|
5467
|
+
remainingFrames,
|
|
5468
|
+
text,
|
|
5469
|
+
stateStage: state.stage,
|
|
5470
|
+
flowText
|
|
5471
|
+
});
|
|
4706
5472
|
};
|
|
4707
5473
|
debugIdlePostFrameHandleRef.current = requestAnimationFrame(captureIdlePostFrame);
|
|
5474
|
+
logTorphDebug(debugInstanceId, "effect:idle-post-frame-schedule", {
|
|
5475
|
+
traceSchemaVersion: TORPH_TRACE_SCHEMA_VERSION,
|
|
5476
|
+
renderOrdinal: scheduledRenderOrdinal,
|
|
5477
|
+
hookRenderOrdinal: scheduledHookRenderOrdinal,
|
|
5478
|
+
token,
|
|
5479
|
+
handle: debugIdlePostFrameHandleRef.current,
|
|
5480
|
+
remainingFrames,
|
|
5481
|
+
text,
|
|
5482
|
+
stateStage: state.stage,
|
|
5483
|
+
flowText,
|
|
5484
|
+
domMeasurementRequestKey,
|
|
5485
|
+
domMeasurementKey,
|
|
5486
|
+
measurementBackend
|
|
5487
|
+
});
|
|
4708
5488
|
return () => {
|
|
4709
5489
|
cancelled = true;
|
|
4710
5490
|
if (debugIdlePostFrameHandleRef.current !== null) {
|
|
5491
|
+
logTorphDebug(debugInstanceId, "effect:idle-post-frame-cleanup", {
|
|
5492
|
+
traceSchemaVersion: TORPH_TRACE_SCHEMA_VERSION,
|
|
5493
|
+
reason: "effect-rerun-or-unmount",
|
|
5494
|
+
renderOrdinal: debugRenderOrdinalRef.current,
|
|
5495
|
+
hookRenderOrdinal,
|
|
5496
|
+
scheduledRenderOrdinal,
|
|
5497
|
+
scheduledHookRenderOrdinal,
|
|
5498
|
+
token,
|
|
5499
|
+
handle: debugIdlePostFrameHandleRef.current,
|
|
5500
|
+
completedFrames: debugIdlePostFrameOrdinalRef.current,
|
|
5501
|
+
remainingFrames,
|
|
5502
|
+
text,
|
|
5503
|
+
stateStage: state.stage,
|
|
5504
|
+
flowText,
|
|
5505
|
+
domMeasurementRequestKey,
|
|
5506
|
+
domMeasurementKey,
|
|
5507
|
+
measurementBackend
|
|
5508
|
+
});
|
|
4711
5509
|
cancelAnimationFrame(debugIdlePostFrameHandleRef.current);
|
|
4712
5510
|
debugIdlePostFrameHandleRef.current = null;
|
|
4713
5511
|
}
|
|
4714
5512
|
};
|
|
4715
5513
|
}, [committedMeasurement, debugInstanceId, flowText, ref, state, text]);
|
|
4716
|
-
|
|
5514
|
+
useLayoutEffect2(() => {
|
|
4717
5515
|
return () => {
|
|
4718
5516
|
if (debugIdlePostFrameHandleRef.current !== null) {
|
|
5517
|
+
logTorphDebug(debugInstanceId, "effect:idle-post-frame-cleanup", {
|
|
5518
|
+
traceSchemaVersion: TORPH_TRACE_SCHEMA_VERSION,
|
|
5519
|
+
reason: "component-unmount",
|
|
5520
|
+
renderOrdinal: debugRenderOrdinalRef.current,
|
|
5521
|
+
token: debugIdlePostFrameTokenRef.current,
|
|
5522
|
+
handle: debugIdlePostFrameHandleRef.current
|
|
5523
|
+
});
|
|
4719
5524
|
cancelAnimationFrame(debugIdlePostFrameHandleRef.current);
|
|
4720
5525
|
debugIdlePostFrameHandleRef.current = null;
|
|
4721
5526
|
}
|
|
4722
5527
|
};
|
|
4723
5528
|
}, []);
|
|
4724
|
-
useLayoutEffect(() => {
|
|
4725
|
-
const config = readTorphDebugConfig();
|
|
4726
|
-
if (!shouldRunTorphInstrumentation(config)) {
|
|
4727
|
-
debugFinalizeSignatureRef.current = null;
|
|
4728
|
-
return;
|
|
4729
|
-
}
|
|
4730
|
-
if (state.stage !== "animate" || state.measurement === null || plan === null) {
|
|
4731
|
-
debugFinalizeSignatureRef.current = null;
|
|
4732
|
-
return;
|
|
4733
|
-
}
|
|
4734
|
-
const root = ref.current;
|
|
4735
|
-
const overlayNode = overlayRef.current;
|
|
4736
|
-
const flowNode = flowTextRef.current;
|
|
4737
|
-
if (root === null || overlayNode === null || flowNode === null) {
|
|
4738
|
-
debugFinalizeSignatureRef.current = null;
|
|
4739
|
-
return;
|
|
4740
|
-
}
|
|
4741
|
-
const measurement = state.measurement;
|
|
4742
|
-
let handled = false;
|
|
4743
|
-
const capture = (event) => {
|
|
4744
|
-
if (handled) {
|
|
4745
|
-
return;
|
|
4746
|
-
}
|
|
4747
|
-
if (event.propertyName !== "transform") {
|
|
4748
|
-
return;
|
|
4749
|
-
}
|
|
4750
|
-
const target = event.target;
|
|
4751
|
-
if (!(target instanceof HTMLElement)) {
|
|
4752
|
-
return;
|
|
4753
|
-
}
|
|
4754
|
-
if (target.dataset.morphRole !== "live") {
|
|
4755
|
-
return;
|
|
4756
|
-
}
|
|
4757
|
-
handled = true;
|
|
4758
|
-
const overlayLiveSnapshot = measureOverlayBoxSnapshot(root, overlayNode, "live");
|
|
4759
|
-
const overlayExitSnapshot = measureOverlayBoxSnapshot(root, overlayNode, "exit");
|
|
4760
|
-
const flowSnapshot = measureLiveFlowSnapshot(root, flowNode);
|
|
4761
|
-
if (overlayLiveSnapshot === null || flowSnapshot === null) {
|
|
4762
|
-
return;
|
|
4763
|
-
}
|
|
4764
|
-
const overlayLiveDrift = measureSnapshotDrift(measurement.snapshot, overlayLiveSnapshot);
|
|
4765
|
-
const flowDrift = measureSnapshotDrift(measurement.snapshot, flowSnapshot);
|
|
4766
|
-
const rootRect = root.getBoundingClientRect();
|
|
4767
|
-
const flowRect = flowNode.getBoundingClientRect();
|
|
4768
|
-
const overlayRect = overlayNode.getBoundingClientRect();
|
|
4769
|
-
const signature = JSON.stringify({
|
|
4770
|
-
text,
|
|
4771
|
-
renderText: measurement.snapshot.renderText,
|
|
4772
|
-
overlayLiveDrift: summarizeSnapshotDrift(overlayLiveDrift),
|
|
4773
|
-
flowDrift: summarizeSnapshotDrift(flowDrift),
|
|
4774
|
-
overlayWidth: roundDebugValue(overlayRect.width),
|
|
4775
|
-
rootWidth: roundDebugValue(rootRect.width)
|
|
4776
|
-
});
|
|
4777
|
-
if (debugFinalizeSignatureRef.current === signature) {
|
|
4778
|
-
return;
|
|
4779
|
-
}
|
|
4780
|
-
debugFinalizeSignatureRef.current = signature;
|
|
4781
|
-
logTorphDebug(debugInstanceId, "effect:animate-finalize-snapshot", {
|
|
4782
|
-
text,
|
|
4783
|
-
target: {
|
|
4784
|
-
layoutInlineSize: roundDebugValue(measurement.layoutInlineSize),
|
|
4785
|
-
reservedInlineSize: roundDebugValue(measurement.reservedInlineSize),
|
|
4786
|
-
flowInlineSize: roundDebugValue(measurement.flowInlineSize),
|
|
4787
|
-
rootOrigin: {
|
|
4788
|
-
left: roundDebugValue(measurement.rootOrigin.left),
|
|
4789
|
-
top: roundDebugValue(measurement.rootOrigin.top)
|
|
4790
|
-
},
|
|
4791
|
-
snapshot: summarizeDebugSnapshot(measurement.snapshot)
|
|
4792
|
-
},
|
|
4793
|
-
overlayLive: summarizeDebugSnapshot(overlayLiveSnapshot),
|
|
4794
|
-
overlayLiveDrift: summarizeSnapshotDrift(overlayLiveDrift),
|
|
4795
|
-
overlayExit: summarizeDebugSnapshot(overlayExitSnapshot),
|
|
4796
|
-
flow: summarizeDebugSnapshot(flowSnapshot),
|
|
4797
|
-
flowDrift: summarizeSnapshotDrift(flowDrift),
|
|
4798
|
-
rootOriginDrift: summarizeDebugRootOriginDrift(measurement, rootRect),
|
|
4799
|
-
overlayLiveViewportAnchors: summarizeDebugViewportAnchors(overlayLiveSnapshot, rootRect),
|
|
4800
|
-
overlayExitViewportAnchors: summarizeDebugViewportAnchors(overlayExitSnapshot, rootRect),
|
|
4801
|
-
flowViewportAnchors: summarizeDebugViewportAnchors(flowSnapshot, rootRect),
|
|
4802
|
-
rootBox: {
|
|
4803
|
-
width: roundDebugValue(rootRect.width),
|
|
4804
|
-
height: roundDebugValue(rootRect.height)
|
|
4805
|
-
},
|
|
4806
|
-
overlayBox: {
|
|
4807
|
-
width: roundDebugValue(overlayRect.width),
|
|
4808
|
-
height: roundDebugValue(overlayRect.height)
|
|
4809
|
-
},
|
|
4810
|
-
flowBox: {
|
|
4811
|
-
width: roundDebugValue(flowRect.width),
|
|
4812
|
-
height: roundDebugValue(flowRect.height)
|
|
4813
|
-
}
|
|
4814
|
-
});
|
|
4815
|
-
};
|
|
4816
|
-
overlayNode.addEventListener("transitionend", capture);
|
|
4817
|
-
return () => {
|
|
4818
|
-
overlayNode.removeEventListener("transitionend", capture);
|
|
4819
|
-
};
|
|
4820
|
-
}, [debugInstanceId, plan, ref, state, text]);
|
|
4821
5529
|
let measurementLayer = null;
|
|
4822
5530
|
if (shouldRenderMeasurementLayer) {
|
|
4823
5531
|
measurementLayer = /* @__PURE__ */ jsxDEV(MeasurementLayer, {
|
|
@@ -4828,11 +5536,13 @@ function ActiveTorph({
|
|
|
4828
5536
|
}, undefined, false, undefined, this);
|
|
4829
5537
|
}
|
|
4830
5538
|
let overlay = null;
|
|
4831
|
-
if (
|
|
5539
|
+
if (shouldRenderGlyphLayer2 && visibleGlyphPlan !== null) {
|
|
4832
5540
|
overlay = /* @__PURE__ */ jsxDEV(MorphOverlay, {
|
|
4833
5541
|
overlayRef,
|
|
4834
5542
|
stage: state.stage,
|
|
4835
|
-
plan
|
|
5543
|
+
plan: visibleGlyphPlan,
|
|
5544
|
+
sourceSliceWhiteSpace,
|
|
5545
|
+
targetSliceWhiteSpace
|
|
4836
5546
|
}, undefined, false, undefined, this);
|
|
4837
5547
|
}
|
|
4838
5548
|
return /* @__PURE__ */ jsxDEV("div", {
|
|
@@ -4846,7 +5556,7 @@ function ActiveTorph({
|
|
|
4846
5556
|
}, undefined, false, undefined, this),
|
|
4847
5557
|
/* @__PURE__ */ jsxDEV("span", {
|
|
4848
5558
|
"aria-hidden": "true",
|
|
4849
|
-
style: getFallbackTextStyle(
|
|
5559
|
+
style: getFallbackTextStyle(shouldHideFlowText),
|
|
4850
5560
|
children: /* @__PURE__ */ jsxDEV("span", {
|
|
4851
5561
|
ref: flowTextRef,
|
|
4852
5562
|
children: flowText
|
|
@@ -4867,23 +5577,5 @@ function Torph({
|
|
|
4867
5577
|
}, undefined, false, undefined, this);
|
|
4868
5578
|
}
|
|
4869
5579
|
export {
|
|
4870
|
-
supportsIntrinsicWidthLock,
|
|
4871
|
-
shouldHealIdleMeasurementFromFlow,
|
|
4872
|
-
resolveMorphFrameBounds,
|
|
4873
|
-
resolveFlowText,
|
|
4874
|
-
resolveContentWidthLockInlineSize,
|
|
4875
|
-
refineMeasurementWithLiveGeometry,
|
|
4876
|
-
pairMorphCharacters,
|
|
4877
|
-
needsMeasurementLayer,
|
|
4878
|
-
measureMorphSnapshotFromLayer,
|
|
4879
|
-
getRootStyle,
|
|
4880
|
-
getRootDisplay,
|
|
4881
|
-
getMeasurementLayerStyle,
|
|
4882
|
-
getLiveTransition,
|
|
4883
|
-
getLiveTransform,
|
|
4884
|
-
getExitTransition,
|
|
4885
|
-
getExitTransform,
|
|
4886
|
-
buildMorphVisualBridge,
|
|
4887
|
-
buildMorphPlan,
|
|
4888
5580
|
Torph
|
|
4889
5581
|
};
|