@kgdiff/scene 0.0.0-stage → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +50 -2
- package/dist/build.d.ts +23 -0
- package/dist/build.d.ts.map +1 -0
- package/dist/build.js +407 -0
- package/dist/build.js.map +1 -0
- package/dist/choreography.d.ts +98 -0
- package/dist/choreography.d.ts.map +1 -0
- package/dist/choreography.js +271 -0
- package/dist/choreography.js.map +1 -0
- package/dist/color.d.ts +42 -0
- package/dist/color.d.ts.map +1 -0
- package/dist/color.js +169 -0
- package/dist/color.js.map +1 -0
- package/dist/constants.d.ts +89 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +89 -0
- package/dist/constants.js.map +1 -0
- package/dist/easing.d.ts +28 -0
- package/dist/easing.d.ts.map +1 -0
- package/dist/easing.js +103 -0
- package/dist/easing.js.map +1 -0
- package/dist/focus.d.ts +45 -0
- package/dist/focus.d.ts.map +1 -0
- package/dist/focus.js +317 -0
- package/dist/focus.js.map +1 -0
- package/dist/frame.d.ts +13 -0
- package/dist/frame.d.ts.map +1 -0
- package/dist/frame.js +32 -0
- package/dist/frame.js.map +1 -0
- package/dist/geometry.d.ts +61 -0
- package/dist/geometry.d.ts.map +1 -0
- package/dist/geometry.js +122 -0
- package/dist/geometry.js.map +1 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -0
- package/dist/resolver.d.ts +9 -0
- package/dist/resolver.d.ts.map +1 -0
- package/dist/resolver.js +1621 -0
- package/dist/resolver.js.map +1 -0
- package/dist/roles.d.ts +46 -0
- package/dist/roles.d.ts.map +1 -0
- package/dist/roles.js +197 -0
- package/dist/roles.js.map +1 -0
- package/dist/styles.d.ts +116 -0
- package/dist/styles.d.ts.map +1 -0
- package/dist/styles.js +391 -0
- package/dist/styles.js.map +1 -0
- package/dist/theme.d.ts +14 -0
- package/dist/theme.d.ts.map +1 -0
- package/dist/theme.js +154 -0
- package/dist/theme.js.map +1 -0
- package/dist/timeline.d.ts +69 -0
- package/dist/timeline.d.ts.map +1 -0
- package/dist/timeline.js +362 -0
- package/dist/timeline.js.map +1 -0
- package/dist/types.d.ts +493 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/view.d.ts +11 -0
- package/dist/view.d.ts.map +1 -0
- package/dist/view.js +22 -0
- package/dist/view.js.map +1 -0
- package/package.json +46 -3
- package/src/build.ts +450 -0
- package/src/choreography.ts +342 -0
- package/src/color.ts +194 -0
- package/src/constants.ts +97 -0
- package/src/easing.ts +104 -0
- package/src/focus.ts +335 -0
- package/src/frame.ts +37 -0
- package/src/geometry.ts +162 -0
- package/src/index.ts +15 -0
- package/src/resolver.ts +1710 -0
- package/src/roles.ts +203 -0
- package/src/styles.ts +513 -0
- package/src/theme.ts +185 -0
- package/src/timeline.ts +391 -0
- package/src/types.ts +544 -0
- package/src/view.ts +27 -0
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Numeric constants of the visual language (docs/visual-language.md §Geometry, §Typography,
|
|
3
|
+
* §Level of detail, §Replay choreography). One place so every module agrees.
|
|
4
|
+
*/
|
|
5
|
+
/** Stroke widths in screen px (constant under zoom). */
|
|
6
|
+
export const STROKE = {
|
|
7
|
+
neutralEdge: 1,
|
|
8
|
+
changedEdge: 1.75,
|
|
9
|
+
selectedEdge: 2.5,
|
|
10
|
+
node: 1.25,
|
|
11
|
+
hoveredNode: 2,
|
|
12
|
+
ring: 1.5,
|
|
13
|
+
/** Gap between the node boundary and its ring, px. */
|
|
14
|
+
ringGap: 3.5,
|
|
15
|
+
glyph: 1.5,
|
|
16
|
+
suggestion: 1.25,
|
|
17
|
+
/** Diameter of a pivot dot, px. */
|
|
18
|
+
pivot: 5,
|
|
19
|
+
};
|
|
20
|
+
/** Dash patterns, px. Frozen so they can be shared by every visual without copying. */
|
|
21
|
+
export const DASH_GHOST = Object.freeze([3, 2.5]);
|
|
22
|
+
export const DASH_EDGE = Object.freeze([4, 3]);
|
|
23
|
+
export const DASH_DOTTED = Object.freeze([1, 3]);
|
|
24
|
+
export const HALO = {
|
|
25
|
+
/** Dark themes: radial glow radius as a multiple of r. */
|
|
26
|
+
glowScale: 2.6,
|
|
27
|
+
glowAlpha: 0.32,
|
|
28
|
+
/** Light themes: offset ring; `radius` is r and renderers draw the ring 5 px outside it, 2 px wide. */
|
|
29
|
+
ringAlpha: 0.35,
|
|
30
|
+
ringOffset: 5,
|
|
31
|
+
ringWidth: 2,
|
|
32
|
+
};
|
|
33
|
+
/** Label typography in px. */
|
|
34
|
+
export const LABEL = {
|
|
35
|
+
size: 12,
|
|
36
|
+
oldSize: 11,
|
|
37
|
+
edgeSize: 10.5,
|
|
38
|
+
/** Gap between the node's bottom and its label, px (`offset = r·k + 5 px`). */
|
|
39
|
+
offset: 5,
|
|
40
|
+
/** Secondary label sits this much lower than the primary one. */
|
|
41
|
+
secondaryGap: 14,
|
|
42
|
+
/** Line box used for bounds estimation (font size × line height). */
|
|
43
|
+
lineHeight: 1.3,
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* Level-of-detail thresholds (camera zoom). Label thresholds are permissive on purpose: the
|
|
47
|
+
* renderer's greedy collision culling decides what fits, so the overview of a small graph is
|
|
48
|
+
* not a field of anonymous dots.
|
|
49
|
+
*/
|
|
50
|
+
export const LOD = {
|
|
51
|
+
changedLabel: 0.35,
|
|
52
|
+
neutralLabel: 0.5,
|
|
53
|
+
importantNeutralLabel: 0.35,
|
|
54
|
+
importantThreshold: 0.7,
|
|
55
|
+
/** Scenes with at most this many visible nodes (after focus) use the small-scene thresholds. */
|
|
56
|
+
smallScene: 300,
|
|
57
|
+
smallChangedLabel: 0.2,
|
|
58
|
+
smallNeutralLabel: 0.25,
|
|
59
|
+
edgeLabel: 1.1,
|
|
60
|
+
badge: 1.2,
|
|
61
|
+
/** Renderers draw arrowheads on edges with `arrow: false` from this zoom on. */
|
|
62
|
+
arrow: 1.2,
|
|
63
|
+
};
|
|
64
|
+
/** Parallel edges between one pair curve with ±k·this (k = 1, 2, …). */
|
|
65
|
+
export const PARALLEL_CURVATURE = 0.18;
|
|
66
|
+
/** Alpha levels of the selection spotlight, the replay spotlight, filters and focus. */
|
|
67
|
+
export const EMPHASIS = {
|
|
68
|
+
selectedContext: 0.7,
|
|
69
|
+
selectedRest: 0.18,
|
|
70
|
+
replayContext: 0.7,
|
|
71
|
+
replayRest: 0.3,
|
|
72
|
+
filtered: 0.4,
|
|
73
|
+
focusContext: 0.55,
|
|
74
|
+
ghostEdge: 0.45,
|
|
75
|
+
collapsedEdge: 0.5,
|
|
76
|
+
};
|
|
77
|
+
/** Replay window phases as fractions of the window (spotlight / transform / settle). */
|
|
78
|
+
export const PHASE = {
|
|
79
|
+
spotlightEnd: 0.18,
|
|
80
|
+
settleStart: 0.82,
|
|
81
|
+
};
|
|
82
|
+
/** Replay timeline (docs/algorithms.md §10). */
|
|
83
|
+
export const TIMELINE = {
|
|
84
|
+
pace: 1100,
|
|
85
|
+
chapterThreshold: 40,
|
|
86
|
+
gap: 160,
|
|
87
|
+
maxStagger: 0.35,
|
|
88
|
+
};
|
|
89
|
+
//# sourceMappingURL=constants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,wDAAwD;AACxD,MAAM,CAAC,MAAM,MAAM,GAAG;IACpB,WAAW,EAAE,CAAC;IACd,WAAW,EAAE,IAAI;IACjB,YAAY,EAAE,GAAG;IACjB,IAAI,EAAE,IAAI;IACV,WAAW,EAAE,CAAC;IACd,IAAI,EAAE,GAAG;IACT,sDAAsD;IACtD,OAAO,EAAE,GAAG;IACZ,KAAK,EAAE,GAAG;IACV,UAAU,EAAE,IAAI;IAChB,mCAAmC;IACnC,KAAK,EAAE,CAAC;CACA,CAAC;AAEX,uFAAuF;AACvF,MAAM,CAAC,MAAM,UAAU,GAAsB,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;AACrE,MAAM,CAAC,MAAM,SAAS,GAAsB,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AAClE,MAAM,CAAC,MAAM,WAAW,GAAsB,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AAEpE,MAAM,CAAC,MAAM,IAAI,GAAG;IAClB,0DAA0D;IAC1D,SAAS,EAAE,GAAG;IACd,SAAS,EAAE,IAAI;IACf,uGAAuG;IACvG,SAAS,EAAE,IAAI;IACf,UAAU,EAAE,CAAC;IACb,SAAS,EAAE,CAAC;CACJ,CAAC;AAEX,8BAA8B;AAC9B,MAAM,CAAC,MAAM,KAAK,GAAG;IACnB,IAAI,EAAE,EAAE;IACR,OAAO,EAAE,EAAE;IACX,QAAQ,EAAE,IAAI;IACd,+EAA+E;IAC/E,MAAM,EAAE,CAAC;IACT,iEAAiE;IACjE,YAAY,EAAE,EAAE;IAChB,qEAAqE;IACrE,UAAU,EAAE,GAAG;CACP,CAAC;AAEX;;;;GAIG;AACH,MAAM,CAAC,MAAM,GAAG,GAAG;IACjB,YAAY,EAAE,IAAI;IAClB,YAAY,EAAE,GAAG;IACjB,qBAAqB,EAAE,IAAI;IAC3B,kBAAkB,EAAE,GAAG;IACvB,gGAAgG;IAChG,UAAU,EAAE,GAAG;IACf,iBAAiB,EAAE,GAAG;IACtB,iBAAiB,EAAE,IAAI;IACvB,SAAS,EAAE,GAAG;IACd,KAAK,EAAE,GAAG;IACV,gFAAgF;IAChF,KAAK,EAAE,GAAG;CACF,CAAC;AAEX,wEAAwE;AACxE,MAAM,CAAC,MAAM,kBAAkB,GAAG,IAAI,CAAC;AAEvC,wFAAwF;AACxF,MAAM,CAAC,MAAM,QAAQ,GAAG;IACtB,eAAe,EAAE,GAAG;IACpB,YAAY,EAAE,IAAI;IAClB,aAAa,EAAE,GAAG;IAClB,UAAU,EAAE,GAAG;IACf,QAAQ,EAAE,GAAG;IACb,YAAY,EAAE,IAAI;IAClB,SAAS,EAAE,IAAI;IACf,aAAa,EAAE,GAAG;CACV,CAAC;AAEX,wFAAwF;AACxF,MAAM,CAAC,MAAM,KAAK,GAAG;IACnB,YAAY,EAAE,IAAI;IAClB,WAAW,EAAE,IAAI;CACT,CAAC;AAEX,gDAAgD;AAChD,MAAM,CAAC,MAAM,QAAQ,GAAG;IACtB,IAAI,EAAE,IAAI;IACV,gBAAgB,EAAE,EAAE;IACpB,GAAG,EAAE,GAAG;IACR,UAAU,EAAE,IAAI;CACR,CAAC"}
|
package/dist/easing.d.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export declare const clamp01: (v: number) => number;
|
|
2
|
+
export declare const lerp: (a: number, b: number, t: number) => number;
|
|
3
|
+
/** Local progress of `u` inside the sub-interval [a, b], clamped to [0, 1]. */
|
|
4
|
+
export declare const segment: (u: number, a: number, b: number) => number;
|
|
5
|
+
/** 0 → 1 → 0 bump over [0, 1] (flashes, pulses). */
|
|
6
|
+
export declare const bump: (t: number) => number;
|
|
7
|
+
/**
|
|
8
|
+
* CSS `cubic-bezier(x1, y1, x2, y2)` as a function of progress in [0, 1]: Newton–Raphson on
|
|
9
|
+
* the x polynomial with a bisection fallback (WebKit's UnitBezier approach), precise to 1e-7.
|
|
10
|
+
*
|
|
11
|
+
* @throws KgdiffError(`invalid-input`) when x1 or x2 lie outside [0, 1] (x must be monotonic).
|
|
12
|
+
*/
|
|
13
|
+
export declare function cubicBezier(x1: number, y1: number, x2: number, y2: number): (t: number) => number;
|
|
14
|
+
/**
|
|
15
|
+
* The house easing `cubic-bezier(0.2, 0, 0, 1)` (theme.motion.easing), sampled into a
|
|
16
|
+
* 1024-step table with linear interpolation (max error ≈ 1e-5). Kept tiny on purpose: the
|
|
17
|
+
* replay calls it many times per frame, and only functions small enough to be inlined return
|
|
18
|
+
* doubles without boxing them on the heap.
|
|
19
|
+
*/
|
|
20
|
+
export declare const easeStandard: (t: number) => number;
|
|
21
|
+
/** Symmetric cubic ease-in-out, for travel along arcs. */
|
|
22
|
+
export declare const easeInOut: (t: number) => number;
|
|
23
|
+
/**
|
|
24
|
+
* Back-out easing: overshoots then settles at 1. The peak is `1 + 4s³ / (27 (s + 1)²)`, so the
|
|
25
|
+
* default `s = 1.5` peaks at exactly 1.08 (the node pop: scale 0 → 1.08 → 1).
|
|
26
|
+
*/
|
|
27
|
+
export declare const backOut: (t: number, s?: number) => number;
|
|
28
|
+
//# sourceMappingURL=easing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"easing.d.ts","sourceRoot":"","sources":["../src/easing.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,OAAO,MAAO,MAAM,KAAG,MAAqC,CAAC;AAE1E,eAAO,MAAM,IAAI,MAAO,MAAM,KAAK,MAAM,KAAK,MAAM,KAAG,MAAyB,CAAC;AAEjF,+EAA+E;AAC/E,eAAO,MAAM,OAAO,MAAO,MAAM,KAAK,MAAM,KAAK,MAAM,KAAG,MAIzD,CAAC;AAEF,oDAAoD;AACpD,eAAO,MAAM,IAAI,MAAO,MAAM,KAAG,MAAwD,CAAC;AAE1F;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAsCjG;AAQD;;;;;GAKG;AACH,eAAO,MAAM,YAAY,MAAO,MAAM,KAAG,MAOxC,CAAC;AAEF,0DAA0D;AAC1D,eAAO,MAAM,SAAS,MAAO,MAAM,KAAG,MAKrC,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,OAAO,MAAO,MAAM,iBAAY,MAG5C,CAAC"}
|
package/dist/easing.js
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Easing and interpolation helpers for the replay choreography. All functions are pure and
|
|
3
|
+
* allocation-free once created (curves are built once at module load). The per-frame helpers are
|
|
4
|
+
* deliberately tiny so the JIT inlines them: a non-inlined call returning a double boxes it.
|
|
5
|
+
*/
|
|
6
|
+
import { KgdiffError } from '@kgdiff/core';
|
|
7
|
+
export const clamp01 = (v) => Math.min(1, Math.max(0, v));
|
|
8
|
+
export const lerp = (a, b, t) => a + (b - a) * t;
|
|
9
|
+
/** Local progress of `u` inside the sub-interval [a, b], clamped to [0, 1]. */
|
|
10
|
+
export const segment = (u, a, b) => {
|
|
11
|
+
if (b <= a)
|
|
12
|
+
return u >= b ? 1 : 0;
|
|
13
|
+
const v = (u - a) / (b - a);
|
|
14
|
+
return Math.min(1, Math.max(0, v));
|
|
15
|
+
};
|
|
16
|
+
/** 0 → 1 → 0 bump over [0, 1] (flashes, pulses). */
|
|
17
|
+
export const bump = (t) => (t <= 0 || t >= 1 ? 0 : Math.sin(Math.PI * t));
|
|
18
|
+
/**
|
|
19
|
+
* CSS `cubic-bezier(x1, y1, x2, y2)` as a function of progress in [0, 1]: Newton–Raphson on
|
|
20
|
+
* the x polynomial with a bisection fallback (WebKit's UnitBezier approach), precise to 1e-7.
|
|
21
|
+
*
|
|
22
|
+
* @throws KgdiffError(`invalid-input`) when x1 or x2 lie outside [0, 1] (x must be monotonic).
|
|
23
|
+
*/
|
|
24
|
+
export function cubicBezier(x1, y1, x2, y2) {
|
|
25
|
+
if (!(x1 >= 0 && x1 <= 1 && x2 >= 0 && x2 <= 1)) {
|
|
26
|
+
throw new KgdiffError('invalid-input', `cubicBezier: x1 and x2 must be in [0, 1], got ${x1}, ${x2}.`);
|
|
27
|
+
}
|
|
28
|
+
const cx = 3 * x1;
|
|
29
|
+
const bx = 3 * (x2 - x1) - cx;
|
|
30
|
+
const ax = 1 - cx - bx;
|
|
31
|
+
const cy = 3 * y1;
|
|
32
|
+
const by = 3 * (y2 - y1) - cy;
|
|
33
|
+
const ay = 1 - cy - by;
|
|
34
|
+
const sampleX = (t) => ((ax * t + bx) * t + cx) * t;
|
|
35
|
+
const sampleY = (t) => ((ay * t + by) * t + cy) * t;
|
|
36
|
+
const slopeX = (t) => (3 * ax * t + 2 * bx) * t + cx;
|
|
37
|
+
const solveX = (x) => {
|
|
38
|
+
let t = x;
|
|
39
|
+
for (let i = 0; i < 8; i++) {
|
|
40
|
+
const err = sampleX(t) - x;
|
|
41
|
+
if (Math.abs(err) < 1e-7)
|
|
42
|
+
return t;
|
|
43
|
+
const d = slopeX(t);
|
|
44
|
+
if (Math.abs(d) < 1e-6)
|
|
45
|
+
break;
|
|
46
|
+
t -= err / d;
|
|
47
|
+
}
|
|
48
|
+
let lo = 0;
|
|
49
|
+
let hi = 1;
|
|
50
|
+
t = x;
|
|
51
|
+
for (let i = 0; i < 64 && hi - lo > 1e-7; i++) {
|
|
52
|
+
const v = sampleX(t);
|
|
53
|
+
if (Math.abs(v - x) < 1e-7)
|
|
54
|
+
return t;
|
|
55
|
+
if (x > v)
|
|
56
|
+
lo = t;
|
|
57
|
+
else
|
|
58
|
+
hi = t;
|
|
59
|
+
t = (lo + hi) / 2;
|
|
60
|
+
}
|
|
61
|
+
return t;
|
|
62
|
+
};
|
|
63
|
+
return (t) => (t <= 0 ? 0 : t >= 1 ? 1 : sampleY(solveX(t)));
|
|
64
|
+
}
|
|
65
|
+
const STANDARD = cubicBezier(0.2, 0, 0, 1);
|
|
66
|
+
const LUT_STEPS = 1024;
|
|
67
|
+
const LUT = new Float64Array(LUT_STEPS + 2);
|
|
68
|
+
for (let i = 0; i <= LUT_STEPS; i++)
|
|
69
|
+
LUT[i] = STANDARD(i / LUT_STEPS);
|
|
70
|
+
LUT[LUT_STEPS + 1] = 1;
|
|
71
|
+
/**
|
|
72
|
+
* The house easing `cubic-bezier(0.2, 0, 0, 1)` (theme.motion.easing), sampled into a
|
|
73
|
+
* 1024-step table with linear interpolation (max error ≈ 1e-5). Kept tiny on purpose: the
|
|
74
|
+
* replay calls it many times per frame, and only functions small enough to be inlined return
|
|
75
|
+
* doubles without boxing them on the heap.
|
|
76
|
+
*/
|
|
77
|
+
export const easeStandard = (t) => {
|
|
78
|
+
if (!(t > 0))
|
|
79
|
+
return 0;
|
|
80
|
+
if (t >= 1)
|
|
81
|
+
return 1;
|
|
82
|
+
const x = t * LUT_STEPS;
|
|
83
|
+
const i = x | 0;
|
|
84
|
+
const a = LUT[i];
|
|
85
|
+
return a + (LUT[i + 1] - a) * (x - i);
|
|
86
|
+
};
|
|
87
|
+
/** Symmetric cubic ease-in-out, for travel along arcs. */
|
|
88
|
+
export const easeInOut = (t) => {
|
|
89
|
+
const u = Math.min(1, Math.max(0, t));
|
|
90
|
+
if (u < 0.5)
|
|
91
|
+
return 4 * u * u * u;
|
|
92
|
+
const v = 2 - 2 * u;
|
|
93
|
+
return 1 - (v * v * v) / 2;
|
|
94
|
+
};
|
|
95
|
+
/**
|
|
96
|
+
* Back-out easing: overshoots then settles at 1. The peak is `1 + 4s³ / (27 (s + 1)²)`, so the
|
|
97
|
+
* default `s = 1.5` peaks at exactly 1.08 (the node pop: scale 0 → 1.08 → 1).
|
|
98
|
+
*/
|
|
99
|
+
export const backOut = (t, s = 1.5) => {
|
|
100
|
+
const u = Math.min(1, Math.max(0, t)) - 1;
|
|
101
|
+
return 1 + (s + 1) * u * u * u + s * u * u;
|
|
102
|
+
};
|
|
103
|
+
//# sourceMappingURL=easing.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"easing.js","sourceRoot":"","sources":["../src/easing.ts"],"names":[],"mappings":"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"}
|
package/dist/focus.d.ts
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Changes-only visibility (docs/algorithms.md §11).
|
|
3
|
+
*/
|
|
4
|
+
import { type Locale } from '@kgdiff/core';
|
|
5
|
+
import type { FocusState, Scene } from './types.js';
|
|
6
|
+
/** “+38 unchanged” / “+38 个未变节点”; “hidden” when the pill also hides changed nodes. */
|
|
7
|
+
export declare function pillLabel(count: number, unchangedOnly: boolean, locale: Locale): string;
|
|
8
|
+
/** Default hub threshold, as in layout's `changes` scope (docs/algorithms.md §12). */
|
|
9
|
+
export declare const DEFAULT_HUB_DEGREE = 40;
|
|
10
|
+
/**
|
|
11
|
+
* Changes-only visibility: every changed element plus context, with the same rule as the layout's
|
|
12
|
+
* `changes` scope (docs/algorithms.md §12), so the changes-only view and a `changes` layout agree:
|
|
13
|
+
*
|
|
14
|
+
* - Changed nodes are visible (distance 0); both versions' endpoints of every changed edge are
|
|
15
|
+
* visible at distance 1 (needed to draw the edge), even with `hops: 0`.
|
|
16
|
+
* - Context is a breadth-first search over both versions' edges from the changed nodes, `hops`
|
|
17
|
+
* deep (default 1; edge endpoints continue from hop 1), that never expands **from** a hub — a
|
|
18
|
+
* node whose degree (max over both versions) exceeds `hubDegree` (default 40; `Infinity`
|
|
19
|
+
* disables). A hub is shown when it is changed or reached; its skipped neighbours collapse.
|
|
20
|
+
* - `expanded` nodes are added (not expanded from). With `hunk`, the hunk's nodes and edges are
|
|
21
|
+
* the changes.
|
|
22
|
+
* - `context` marks visible nodes outside the change set (rendered quieter).
|
|
23
|
+
* - Hidden nodes are grouped: next to a visible hub that was not expanded from (its skipped
|
|
24
|
+
* neighbours), else next to the lowest-index visible neighbour; nodes further out join the
|
|
25
|
+
* group of the frontier node that reaches them first (BFS through hidden nodes); hidden
|
|
26
|
+
* components touching nothing visible form one group each. Ids are stable across rebuilds:
|
|
27
|
+
* `near:<union id>` / `component:<smallest union id>`.
|
|
28
|
+
* - `count` also includes neighbours left out of the layout (`SceneNode.hidden`, scope
|
|
29
|
+
* `changes`); `nodes` lists only in-scene members. A group with no in-scene member sits
|
|
30
|
+
* just outside its node, away from its visible neighbours.
|
|
31
|
+
* - `label` is the localized pill text in `scene.locale` (“+38 unchanged”, “+38 个未变节点”;
|
|
32
|
+
* “hidden” instead of “unchanged” when a hunk-restricted focus hides changed nodes too).
|
|
33
|
+
*
|
|
34
|
+
* O(N + E).
|
|
35
|
+
*
|
|
36
|
+
* @throws KgdiffError(`invalid-input`) for a negative / non-finite `hops`, a negative / NaN
|
|
37
|
+
* `hubDegree` or an unknown hunk.
|
|
38
|
+
*/
|
|
39
|
+
export declare function computeFocus(scene: Scene, options?: {
|
|
40
|
+
readonly hops?: number;
|
|
41
|
+
readonly hunk?: number;
|
|
42
|
+
readonly expanded?: ReadonlySet<number>;
|
|
43
|
+
readonly hubDegree?: number;
|
|
44
|
+
}): FocusState;
|
|
45
|
+
//# sourceMappingURL=focus.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"focus.d.ts","sourceRoot":"","sources":["../src/focus.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAe,KAAK,MAAM,EAAE,MAAM,cAAc,CAAC;AACxD,OAAO,KAAK,EAAkB,UAAU,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AA8CpE,sFAAsF;AACtF,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CASvF;AAKD,sFAAsF;AACtF,eAAO,MAAM,kBAAkB,KAAK,CAAC;AAErC;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,YAAY,CAC1B,KAAK,EAAE,KAAK,EACZ,OAAO,GAAE;IACP,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,QAAQ,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACxC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CACxB,GACL,UAAU,CA6FZ"}
|
package/dist/focus.js
ADDED
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Changes-only visibility (docs/algorithms.md §11).
|
|
3
|
+
*/
|
|
4
|
+
import { KgdiffError } from '@kgdiff/core';
|
|
5
|
+
const adjacencyCache = new WeakMap();
|
|
6
|
+
function adjacency(scene) {
|
|
7
|
+
const cached = adjacencyCache.get(scene);
|
|
8
|
+
if (cached !== undefined)
|
|
9
|
+
return cached;
|
|
10
|
+
const N = scene.nodes.length;
|
|
11
|
+
const deg = new Int32Array(N + 1);
|
|
12
|
+
const pairs = [];
|
|
13
|
+
const add = (a, b) => {
|
|
14
|
+
if (a === b)
|
|
15
|
+
return;
|
|
16
|
+
pairs.push(a, b);
|
|
17
|
+
deg[a + 1] = deg[a + 1] + 1;
|
|
18
|
+
deg[b + 1] = deg[b + 1] + 1;
|
|
19
|
+
};
|
|
20
|
+
for (const e of scene.edges) {
|
|
21
|
+
add(e.s, e.t);
|
|
22
|
+
if (e.sb !== e.s || e.tb !== e.t)
|
|
23
|
+
add(e.sb, e.tb);
|
|
24
|
+
}
|
|
25
|
+
for (let i = 0; i < N; i++)
|
|
26
|
+
deg[i + 1] = deg[i + 1] + deg[i];
|
|
27
|
+
const fill = deg.slice(0, N);
|
|
28
|
+
const list = new Int32Array(pairs.length);
|
|
29
|
+
for (let k = 0; k < pairs.length; k += 2) {
|
|
30
|
+
const a = pairs[k];
|
|
31
|
+
const b = pairs[k + 1];
|
|
32
|
+
list[fill[a]] = b;
|
|
33
|
+
fill[a] = fill[a] + 1;
|
|
34
|
+
list[fill[b]] = a;
|
|
35
|
+
fill[b] = fill[b] + 1;
|
|
36
|
+
}
|
|
37
|
+
// Sorted neighbour lists make every traversal below independent of edge order.
|
|
38
|
+
for (let i = 0; i < N; i++)
|
|
39
|
+
list.subarray(deg[i], deg[i + 1]).sort();
|
|
40
|
+
const adj = { start: deg, list };
|
|
41
|
+
adjacencyCache.set(scene, adj);
|
|
42
|
+
return adj;
|
|
43
|
+
}
|
|
44
|
+
const numberFormats = new Map();
|
|
45
|
+
/** “+38 unchanged” / “+38 个未变节点”; “hidden” when the pill also hides changed nodes. */
|
|
46
|
+
export function pillLabel(count, unchangedOnly, locale) {
|
|
47
|
+
let nf = numberFormats.get(locale);
|
|
48
|
+
if (nf === undefined) {
|
|
49
|
+
nf = new Intl.NumberFormat(locale);
|
|
50
|
+
numberFormats.set(locale, nf);
|
|
51
|
+
}
|
|
52
|
+
const n = nf.format(count);
|
|
53
|
+
if (locale === 'zh-CN')
|
|
54
|
+
return unchangedOnly ? `+${n} 个未变节点` : `+${n} 个隐藏节点`;
|
|
55
|
+
return unchangedOnly ? `+${n} unchanged` : `+${n} hidden`;
|
|
56
|
+
}
|
|
57
|
+
/** World-unit distance of a pill that has no in-scene member from its node's boundary. */
|
|
58
|
+
const PILL_OFFSET = 28;
|
|
59
|
+
/** Default hub threshold, as in layout's `changes` scope (docs/algorithms.md §12). */
|
|
60
|
+
export const DEFAULT_HUB_DEGREE = 40;
|
|
61
|
+
/**
|
|
62
|
+
* Changes-only visibility: every changed element plus context, with the same rule as the layout's
|
|
63
|
+
* `changes` scope (docs/algorithms.md §12), so the changes-only view and a `changes` layout agree:
|
|
64
|
+
*
|
|
65
|
+
* - Changed nodes are visible (distance 0); both versions' endpoints of every changed edge are
|
|
66
|
+
* visible at distance 1 (needed to draw the edge), even with `hops: 0`.
|
|
67
|
+
* - Context is a breadth-first search over both versions' edges from the changed nodes, `hops`
|
|
68
|
+
* deep (default 1; edge endpoints continue from hop 1), that never expands **from** a hub — a
|
|
69
|
+
* node whose degree (max over both versions) exceeds `hubDegree` (default 40; `Infinity`
|
|
70
|
+
* disables). A hub is shown when it is changed or reached; its skipped neighbours collapse.
|
|
71
|
+
* - `expanded` nodes are added (not expanded from). With `hunk`, the hunk's nodes and edges are
|
|
72
|
+
* the changes.
|
|
73
|
+
* - `context` marks visible nodes outside the change set (rendered quieter).
|
|
74
|
+
* - Hidden nodes are grouped: next to a visible hub that was not expanded from (its skipped
|
|
75
|
+
* neighbours), else next to the lowest-index visible neighbour; nodes further out join the
|
|
76
|
+
* group of the frontier node that reaches them first (BFS through hidden nodes); hidden
|
|
77
|
+
* components touching nothing visible form one group each. Ids are stable across rebuilds:
|
|
78
|
+
* `near:<union id>` / `component:<smallest union id>`.
|
|
79
|
+
* - `count` also includes neighbours left out of the layout (`SceneNode.hidden`, scope
|
|
80
|
+
* `changes`); `nodes` lists only in-scene members. A group with no in-scene member sits
|
|
81
|
+
* just outside its node, away from its visible neighbours.
|
|
82
|
+
* - `label` is the localized pill text in `scene.locale` (“+38 unchanged”, “+38 个未变节点”;
|
|
83
|
+
* “hidden” instead of “unchanged” when a hunk-restricted focus hides changed nodes too).
|
|
84
|
+
*
|
|
85
|
+
* O(N + E).
|
|
86
|
+
*
|
|
87
|
+
* @throws KgdiffError(`invalid-input`) for a negative / non-finite `hops`, a negative / NaN
|
|
88
|
+
* `hubDegree` or an unknown hunk.
|
|
89
|
+
*/
|
|
90
|
+
export function computeFocus(scene, options = {}) {
|
|
91
|
+
const hops = options.hops ?? 1;
|
|
92
|
+
if (!(Number.isFinite(hops) && hops >= 0)) {
|
|
93
|
+
throw new KgdiffError('invalid-input', `computeFocus: hops must be a finite number ≥ 0, got ${hops}.`);
|
|
94
|
+
}
|
|
95
|
+
const hubDegree = options.hubDegree ?? DEFAULT_HUB_DEGREE;
|
|
96
|
+
if (!(hubDegree >= 0)) {
|
|
97
|
+
throw new KgdiffError('invalid-input', `computeFocus: hubDegree must be a number ≥ 0 (Infinity disables), got ${hubDegree}.`);
|
|
98
|
+
}
|
|
99
|
+
const hunk = options.hunk;
|
|
100
|
+
if (hunk !== undefined && !(Number.isInteger(hunk) && hunk >= 0 && hunk < scene.hunks.length)) {
|
|
101
|
+
throw new KgdiffError('invalid-input', `computeFocus: hunk ${hunk} is out of range [0, ${scene.hunks.length}).`);
|
|
102
|
+
}
|
|
103
|
+
const N = scene.nodes.length;
|
|
104
|
+
const M = scene.edges.length;
|
|
105
|
+
const { start, list } = adjacency(scene);
|
|
106
|
+
const visible = new Uint8Array(N);
|
|
107
|
+
const primary = new Uint8Array(N);
|
|
108
|
+
const dist = new Int32Array(N).fill(-1);
|
|
109
|
+
const queue = new Int32Array(N);
|
|
110
|
+
let qHead = 0;
|
|
111
|
+
let qTail = 0;
|
|
112
|
+
const reach = (i, d) => {
|
|
113
|
+
if (i < 0 || i >= N || dist[i] !== -1)
|
|
114
|
+
return;
|
|
115
|
+
dist[i] = d;
|
|
116
|
+
visible[i] = 1;
|
|
117
|
+
queue[qTail++] = i;
|
|
118
|
+
};
|
|
119
|
+
// Distance 0 first, then distance 1, so the FIFO queue stays ordered by distance.
|
|
120
|
+
const changedEdges = [];
|
|
121
|
+
if (hunk !== undefined) {
|
|
122
|
+
const h = scene.hunks[hunk];
|
|
123
|
+
for (const i of h?.nodes ?? []) {
|
|
124
|
+
primary[i] = 1;
|
|
125
|
+
reach(i, 0);
|
|
126
|
+
}
|
|
127
|
+
for (const j of h?.edges ?? [])
|
|
128
|
+
changedEdges.push(j);
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
for (const n of scene.nodes) {
|
|
132
|
+
if (n.status === 'unchanged')
|
|
133
|
+
continue;
|
|
134
|
+
primary[n.index] = 1;
|
|
135
|
+
reach(n.index, 0);
|
|
136
|
+
}
|
|
137
|
+
for (const e of scene.edges)
|
|
138
|
+
if (e.status !== 'unchanged')
|
|
139
|
+
changedEdges.push(e.index);
|
|
140
|
+
}
|
|
141
|
+
for (const j of changedEdges) {
|
|
142
|
+
const e = scene.edges[j];
|
|
143
|
+
if (e === undefined)
|
|
144
|
+
continue;
|
|
145
|
+
reach(e.s, 1);
|
|
146
|
+
reach(e.t, 1);
|
|
147
|
+
reach(e.sb, 1);
|
|
148
|
+
reach(e.tb, 1);
|
|
149
|
+
}
|
|
150
|
+
// Context: breadth-first within `hops`, never expanding from a hub.
|
|
151
|
+
const maxHops = Math.floor(hops);
|
|
152
|
+
const skippedHub = new Uint8Array(N);
|
|
153
|
+
while (qHead < qTail) {
|
|
154
|
+
const i = queue[qHead++];
|
|
155
|
+
const d = dist[i];
|
|
156
|
+
if (d >= maxHops)
|
|
157
|
+
continue;
|
|
158
|
+
if ((scene.nodes[i]?.degree ?? 0) > hubDegree) {
|
|
159
|
+
skippedHub[i] = 1;
|
|
160
|
+
continue;
|
|
161
|
+
}
|
|
162
|
+
for (let k = start[i]; k < start[i + 1]; k++) {
|
|
163
|
+
reach(list[k], d + 1);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
for (const i of options.expanded ?? [])
|
|
167
|
+
if (i >= 0 && i < N)
|
|
168
|
+
visible[i] = 1;
|
|
169
|
+
const context = new Uint8Array(N);
|
|
170
|
+
for (let i = 0; i < N; i++)
|
|
171
|
+
if (visible[i] === 1 && primary[i] === 0)
|
|
172
|
+
context[i] = 1;
|
|
173
|
+
const edges = new Uint8Array(M);
|
|
174
|
+
for (let j = 0; j < M; j++) {
|
|
175
|
+
const e = scene.edges[j];
|
|
176
|
+
if (e !== undefined && visible[e.s] === 1 && visible[e.t] === 1)
|
|
177
|
+
edges[j] = 1;
|
|
178
|
+
}
|
|
179
|
+
return {
|
|
180
|
+
nodes: visible,
|
|
181
|
+
edges,
|
|
182
|
+
context,
|
|
183
|
+
collapsed: collapse(scene, visible, skippedHub, start, list),
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
function collapse(scene, visible, skippedHub, start, list) {
|
|
187
|
+
const N = scene.nodes.length;
|
|
188
|
+
// owner[i] = the node whose group i joins: a visible frontier node, or a component root.
|
|
189
|
+
const owner = new Int32Array(N).fill(-1);
|
|
190
|
+
const queue = new Int32Array(N);
|
|
191
|
+
let head = 0;
|
|
192
|
+
let tail = 0;
|
|
193
|
+
for (let i = 0; i < N; i++) {
|
|
194
|
+
if (visible[i] === 1)
|
|
195
|
+
continue;
|
|
196
|
+
// A hub that was not expanded from claims its skipped neighbours; else the lowest index.
|
|
197
|
+
let first = -1;
|
|
198
|
+
let hub = -1;
|
|
199
|
+
for (let k = start[i]; k < start[i + 1]; k++) {
|
|
200
|
+
const n = list[k];
|
|
201
|
+
if (visible[n] !== 1)
|
|
202
|
+
continue;
|
|
203
|
+
if (first < 0)
|
|
204
|
+
first = n;
|
|
205
|
+
if (skippedHub[n] === 1) {
|
|
206
|
+
hub = n;
|
|
207
|
+
break;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
if (first >= 0) {
|
|
211
|
+
owner[i] = hub >= 0 ? hub : first;
|
|
212
|
+
queue[tail++] = i;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
const spread = () => {
|
|
216
|
+
while (head < tail) {
|
|
217
|
+
const i = queue[head++];
|
|
218
|
+
for (let k = start[i]; k < start[i + 1]; k++) {
|
|
219
|
+
const n = list[k];
|
|
220
|
+
if (visible[n] === 1 || owner[n] !== -1)
|
|
221
|
+
continue;
|
|
222
|
+
owner[n] = owner[i];
|
|
223
|
+
queue[tail++] = n;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
};
|
|
227
|
+
spread();
|
|
228
|
+
const isComponent = new Uint8Array(N);
|
|
229
|
+
for (let i = 0; i < N; i++) {
|
|
230
|
+
if (visible[i] === 1 || owner[i] !== -1)
|
|
231
|
+
continue;
|
|
232
|
+
owner[i] = i;
|
|
233
|
+
isComponent[i] = 1;
|
|
234
|
+
queue[tail++] = i;
|
|
235
|
+
spread();
|
|
236
|
+
}
|
|
237
|
+
const groups = new Map();
|
|
238
|
+
const acc = (o) => {
|
|
239
|
+
let g = groups.get(o);
|
|
240
|
+
if (g === undefined) {
|
|
241
|
+
g = { owner: o, members: [], extra: 0, changed: false, sx: 0, sy: 0 };
|
|
242
|
+
groups.set(o, g);
|
|
243
|
+
}
|
|
244
|
+
return g;
|
|
245
|
+
};
|
|
246
|
+
for (let i = 0; i < N; i++) {
|
|
247
|
+
if (visible[i] === 1)
|
|
248
|
+
continue;
|
|
249
|
+
const g = acc(owner[i]);
|
|
250
|
+
const n = scene.nodes[i];
|
|
251
|
+
g.members.push(i);
|
|
252
|
+
if (n !== undefined && n.status !== 'unchanged')
|
|
253
|
+
g.changed = true;
|
|
254
|
+
g.sx += n?.x ?? 0;
|
|
255
|
+
g.sy += n?.y ?? 0;
|
|
256
|
+
}
|
|
257
|
+
// Neighbours outside the layout belong behind the node that has them.
|
|
258
|
+
for (const n of scene.nodes) {
|
|
259
|
+
if (n.hidden <= 0)
|
|
260
|
+
continue;
|
|
261
|
+
acc(visible[n.index] === 1 ? n.index : owner[n.index]).extra += n.hidden;
|
|
262
|
+
}
|
|
263
|
+
const out = [];
|
|
264
|
+
for (const g of groups.values()) {
|
|
265
|
+
const ownerNode = scene.nodes[g.owner];
|
|
266
|
+
if (ownerNode === undefined)
|
|
267
|
+
continue;
|
|
268
|
+
const count = g.members.length + g.extra;
|
|
269
|
+
if (count === 0)
|
|
270
|
+
continue;
|
|
271
|
+
let x;
|
|
272
|
+
let y;
|
|
273
|
+
if (g.members.length > 0) {
|
|
274
|
+
x = g.sx / g.members.length;
|
|
275
|
+
y = g.sy / g.members.length;
|
|
276
|
+
}
|
|
277
|
+
else {
|
|
278
|
+
// Outside the node, away from the centroid of its visible neighbours.
|
|
279
|
+
let mx = 0;
|
|
280
|
+
let my = 0;
|
|
281
|
+
let k0 = 0;
|
|
282
|
+
for (let k = start[g.owner]; k < start[g.owner + 1]; k++) {
|
|
283
|
+
const n = scene.nodes[list[k]];
|
|
284
|
+
if (n === undefined || visible[n.index] !== 1)
|
|
285
|
+
continue;
|
|
286
|
+
mx += n.x;
|
|
287
|
+
my += n.y;
|
|
288
|
+
k0++;
|
|
289
|
+
}
|
|
290
|
+
let dx = 0;
|
|
291
|
+
let dy = -1;
|
|
292
|
+
if (k0 > 0) {
|
|
293
|
+
const vx = ownerNode.x - mx / k0;
|
|
294
|
+
const vy = ownerNode.y - my / k0;
|
|
295
|
+
const len = Math.hypot(vx, vy);
|
|
296
|
+
if (len > 1e-9) {
|
|
297
|
+
dx = vx / len;
|
|
298
|
+
dy = vy / len;
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
const d = ownerNode.r + PILL_OFFSET;
|
|
302
|
+
x = ownerNode.x + dx * d;
|
|
303
|
+
y = ownerNode.y + dy * d;
|
|
304
|
+
}
|
|
305
|
+
out.push({
|
|
306
|
+
id: isComponent[g.owner] === 1 ? `component:${ownerNode.id}` : `near:${ownerNode.id}`,
|
|
307
|
+
x,
|
|
308
|
+
y,
|
|
309
|
+
count,
|
|
310
|
+
nodes: g.members,
|
|
311
|
+
label: pillLabel(count, !g.changed, scene.locale),
|
|
312
|
+
});
|
|
313
|
+
}
|
|
314
|
+
out.sort((a, b) => (a.id < b.id ? -1 : a.id > b.id ? 1 : 0));
|
|
315
|
+
return out;
|
|
316
|
+
}
|
|
317
|
+
//# sourceMappingURL=focus.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"focus.js","sourceRoot":"","sources":["../src/focus.ts"],"names":[],"mappings":"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"}
|
package/dist/frame.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Camera targets.
|
|
3
|
+
*/
|
|
4
|
+
import type { Rect } from '@kgdiff/core';
|
|
5
|
+
import type { Scene } from './types.js';
|
|
6
|
+
/**
|
|
7
|
+
* Camera target for a hunk / chapter / whole scene: the union of the hunks' bounds (or the
|
|
8
|
+
* scene bounds when `hunks` is omitted, empty or has no valid index), padded by
|
|
9
|
+
* `max(16, 6% of the larger side)` per side and grown to at least 160 × 160 world units,
|
|
10
|
+
* centered. UI chrome is reserved by the renderer's `safeArea`.
|
|
11
|
+
*/
|
|
12
|
+
export declare function frameBounds(scene: Scene, hunks?: readonly number[]): Rect;
|
|
13
|
+
//# sourceMappingURL=frame.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"frame.d.ts","sourceRoot":"","sources":["../src/frame.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAEzC,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AASxC;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,CAgBzE"}
|