@motionscript/code 0.1.0 → 0.1.1-alpha.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/CHANGELOG.md +19 -0
- package/README.md +2 -2
- package/dist/browser/index.js +8 -8
- package/dist/browser/index.js.map +3 -3
- package/dist/browser/manifest.json +1 -1
- package/dist/code-range.d.ts +7 -47
- package/dist/code-range.d.ts.map +1 -1
- package/dist/code-range.js +8 -45
- package/dist/code-range.js.map +1 -1
- package/dist/diff.d.ts +5 -44
- package/dist/diff.d.ts.map +1 -1
- package/dist/diff.js +22 -69
- package/dist/diff.js.map +1 -1
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +3 -7
- package/dist/engine.js.map +1 -1
- package/dist/highlight.d.ts +13 -31
- package/dist/highlight.d.ts.map +1 -1
- package/dist/highlight.js +25 -87
- package/dist/highlight.js.map +1 -1
- package/dist/layout.d.ts +7 -26
- package/dist/layout.d.ts.map +1 -1
- package/dist/layout.js +5 -20
- package/dist/layout.js.map +1 -1
- package/dist/measure-cache.d.ts +5 -27
- package/dist/measure-cache.d.ts.map +1 -1
- package/dist/measure-cache.js +0 -0
- package/dist/measure-cache.js.map +1 -1
- package/dist/node.d.ts +4 -11
- package/dist/node.d.ts.map +1 -1
- package/dist/node.js +18 -41
- package/dist/node.js.map +1 -1
- package/dist/nodes.d.ts +0 -12
- package/dist/nodes.d.ts.map +1 -1
- package/dist/nodes.js +0 -12
- package/dist/nodes.js.map +1 -1
- package/dist/render.d.ts +5 -14
- package/dist/render.d.ts.map +1 -1
- package/dist/render.js +13 -54
- package/dist/render.js.map +1 -1
- package/dist/style.d.ts +6 -61
- package/dist/style.d.ts.map +1 -1
- package/dist/style.js +4 -40
- package/dist/style.js.map +1 -1
- package/dist/tokens.d.ts +1 -10
- package/dist/tokens.d.ts.map +1 -1
- package/dist/tokens.js +3 -38
- package/dist/tokens.js.map +1 -1
- package/dist/transitions.d.ts +16 -68
- package/dist/transitions.d.ts.map +1 -1
- package/dist/transitions.js +5 -17
- package/dist/transitions.js.map +1 -1
- package/package.json +4 -4
- package/src/code-range.ts +9 -53
- package/src/diff.ts +26 -92
- package/src/engine.ts +3 -7
- package/src/highlight.ts +25 -98
- package/src/layout.ts +10 -35
- package/src/measure-cache.ts +0 -0
- package/src/node.ts +21 -57
- package/src/nodes.ts +0 -12
- package/src/render.ts +17 -61
- package/src/style.ts +9 -64
- package/src/tokens.ts +4 -46
- package/src/transitions.ts +16 -72
package/src/transitions.ts
CHANGED
|
@@ -2,77 +2,43 @@ import type { NormalizedColor } from "@motionscript/sdk";
|
|
|
2
2
|
import type { CodeLayout } from "./layout";
|
|
3
3
|
import { IdLine } from "./tokens";
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
// token id rather than (line, tokenIndex) so concurrent animations don't clobber
|
|
7
|
-
// each other when one shifts the indices of tokens the other is animating.
|
|
5
|
+
/** Keyed by token id, not (line, index), so a concurrent edit that shifts indices doesn't clobber it. */
|
|
8
6
|
export interface AnimToken {
|
|
9
7
|
id: number;
|
|
10
8
|
opacity: number[];
|
|
11
9
|
opacityKeys: number[];
|
|
12
10
|
}
|
|
13
11
|
|
|
14
|
-
/**
|
|
15
|
-
* A highlight cross-fade: opacity, and nothing else.
|
|
16
|
-
*
|
|
17
|
-
* Structure is untouched, so several of these stack happily and a listing held
|
|
18
|
-
* under a highlight still hits the static-layout cache.
|
|
19
|
-
*/
|
|
12
|
+
/** A highlight cross-fade: opacity only, so several stack and a highlighted listing still hits the static-layout cache. */
|
|
20
13
|
export interface DimTransition {
|
|
21
14
|
kind: "dim";
|
|
22
15
|
tokens: AnimToken[];
|
|
23
16
|
progress: number;
|
|
24
17
|
}
|
|
25
18
|
|
|
26
|
-
/**
|
|
27
|
-
* When each part of a structural edit happens, in normalized transition time.
|
|
28
|
-
*
|
|
29
|
-
* The order is what an edit *looks like* being made: what is going away leaves
|
|
30
|
-
* first, what stays reflows into its new place, and only then does what is new
|
|
31
|
-
* appear. Running them together is what made a replacement look like a
|
|
32
|
-
* cross-dissolve of two unrelated listings.
|
|
33
|
-
*/
|
|
19
|
+
/** When each part of an edit happens, in normalized time: out, then move, then in. Run together, a replacement reads as a cross-dissolve of two listings. */
|
|
34
20
|
export interface Phases {
|
|
35
|
-
/**
|
|
21
|
+
/** Null when the edit removes nothing. */
|
|
36
22
|
out: [number, number] | null;
|
|
37
|
-
/** Surviving tokens travel
|
|
23
|
+
/** Surviving tokens travel and the block resizes. */
|
|
38
24
|
move: [number, number];
|
|
39
|
-
/**
|
|
25
|
+
/** Null when the edit adds nothing. */
|
|
40
26
|
in: [number, number] | null;
|
|
41
27
|
}
|
|
42
28
|
|
|
43
|
-
/**
|
|
44
|
-
* One edit in flight: the structure before, the structure after, and who is
|
|
45
|
-
* doing what.
|
|
46
|
-
*
|
|
47
|
-
* Both endpoints are fixed for the transition's whole life, which is why the
|
|
48
|
-
* two resolved layouts hang off it — they are computed once and reused for
|
|
49
|
-
* every frame the edit spans, rather than rebuilt per frame from a structure
|
|
50
|
-
* that is being mutated underneath.
|
|
51
|
-
*/
|
|
29
|
+
/** One edit in flight. Both endpoints are fixed, so the two layouts are computed once and reused for every frame. */
|
|
52
30
|
export interface StructuralTransition {
|
|
53
31
|
kind: "structural";
|
|
54
32
|
from: IdLine[];
|
|
55
33
|
to: IdLine[];
|
|
56
34
|
removedIds: Set<number>;
|
|
57
35
|
addedIds: Set<number>;
|
|
58
|
-
/**
|
|
59
|
-
* Ids of rows in `to` that did not exist before, and so enter as a whole
|
|
60
|
-
* row rather than as tokens spliced into one.
|
|
61
|
-
*
|
|
62
|
-
* They enter by fading in place, and that is the *only* thing they do. An
|
|
63
|
-
* earlier version slid each one in from the edge the block had just grown
|
|
64
|
-
* along — appended rows rising from below, prepended ones descending, ones
|
|
65
|
-
* spliced into the middle arriving from the left. Every one of those is a
|
|
66
|
-
* claim about where the line came from, and a listing has no such story to
|
|
67
|
-
* tell: text is written where it belongs, it does not travel there. Sliding
|
|
68
|
-
* also puts the row under the neighbours it is meant to sit between for the
|
|
69
|
-
* length of its entrance, which reads as the listing redrawing itself.
|
|
70
|
-
*/
|
|
36
|
+
/** Rows of `to` that enter as a whole row. They only fade in place: text is written where it belongs, and sliding one in puts it under its neighbours. */
|
|
71
37
|
enteringLineIds: Set<number>;
|
|
72
38
|
fromColorById: Map<number, string | undefined>;
|
|
73
39
|
phases: Phases;
|
|
74
40
|
progress: number;
|
|
75
|
-
/** @internal
|
|
41
|
+
/** @internal */
|
|
76
42
|
layoutKey: string | null;
|
|
77
43
|
fromLayout: CodeLayout | null;
|
|
78
44
|
toLayout: CodeLayout | null;
|
|
@@ -86,10 +52,7 @@ export interface RowBand {
|
|
|
86
52
|
radius: number;
|
|
87
53
|
}
|
|
88
54
|
|
|
89
|
-
/**
|
|
90
|
-
* One set of row bands becoming another. Bands at the same position in both
|
|
91
|
-
* lists travel and recolour; one with no counterpart fades.
|
|
92
|
-
*/
|
|
55
|
+
/** Bands at the same position in both lists travel and recolour; one with no counterpart fades. */
|
|
93
56
|
export interface RowsTransition {
|
|
94
57
|
kind: "rows";
|
|
95
58
|
from: RowBand[];
|
|
@@ -99,20 +62,14 @@ export interface RowsTransition {
|
|
|
99
62
|
|
|
100
63
|
export type CodeTransition = DimTransition | StructuralTransition | RowsTransition;
|
|
101
64
|
|
|
102
|
-
/**
|
|
103
|
-
* Decides *when* (in normalized transition time) each part of a structural
|
|
104
|
-
* edit happens, given only whether the edit removes/adds anything.
|
|
105
|
-
* `phasesFor` below is the default implementation (exported as
|
|
106
|
-
* `defaultCodePhases`) — pass a `phaseStrategy` of this shape to `<Code>` to
|
|
107
|
-
* replace it with your own timing.
|
|
108
|
-
*/
|
|
65
|
+
/** Decides the {@link Phases} from whether the edit removes or adds anything; `defaultCodePhases` is the default. */
|
|
109
66
|
export type CodePhaseStrategy = (hasRemoved: boolean, hasAdded: boolean) => Phases;
|
|
110
67
|
|
|
111
68
|
export interface TokenState {
|
|
112
69
|
opacity: number;
|
|
113
70
|
}
|
|
114
71
|
|
|
115
|
-
/**
|
|
72
|
+
/** Samples a piecewise-linear curve at progress `p`. */
|
|
116
73
|
export function sampleCurve(keys: number[], values: number[], p: number): number {
|
|
117
74
|
if (p <= keys[0]) return values[0];
|
|
118
75
|
if (p >= keys[keys.length - 1]) return values[values.length - 1];
|
|
@@ -144,15 +101,8 @@ export function makeAnim(id: number, curve: { keys: number[]; values: number[] }
|
|
|
144
101
|
return { id, opacity: curve.values, opacityKeys: curve.keys };
|
|
145
102
|
}
|
|
146
103
|
|
|
147
|
-
/**
|
|
148
|
-
|
|
149
|
-
*
|
|
150
|
-
* A fixed schedule wastes time it does not need: a pure append has nothing to
|
|
151
|
-
* fade out, so holding the first 40% of the duration empty just makes the
|
|
152
|
-
* animation feel late. Each shape gets the whole duration spent on the parts
|
|
153
|
-
* that exist, with adjacent phases overlapping enough to read as one movement.
|
|
154
|
-
*/
|
|
155
|
-
export function phasesFor(hasRemoved: boolean, hasAdded: boolean): Phases {
|
|
104
|
+
/** A pure append has nothing to fade out, so each edit shape spends the whole duration on the phases it has. */
|
|
105
|
+
export function defaultCodePhases(hasRemoved: boolean, hasAdded: boolean): Phases {
|
|
156
106
|
// The overlaps are deliberate and small. Butt-joining the phases leaves the
|
|
157
107
|
// block sitting empty at its new size for a beat between the old content
|
|
158
108
|
// leaving and the new content arriving; letting the arrival start while the
|
|
@@ -164,18 +114,12 @@ export function phasesFor(hasRemoved: boolean, hasAdded: boolean): Phases {
|
|
|
164
114
|
return { out: null, move: [0, 1], in: null };
|
|
165
115
|
}
|
|
166
116
|
|
|
167
|
-
/**
|
|
168
|
-
export const defaultCodePhases: CodePhaseStrategy = phasesFor;
|
|
169
|
-
|
|
170
|
-
/** How far through the "everything reflows" phase a frame is, eased. A settled frame (no edit) is always fully moved. */
|
|
117
|
+
/** Eased progress of the move phase; a settled frame (no edit) is fully moved. */
|
|
171
118
|
export function moveProgress(edit: { phases: Phases; progress: number } | null): number {
|
|
172
119
|
return edit ? smoothstep(windowProgress(edit.phases.move, edit.progress)) : 1;
|
|
173
120
|
}
|
|
174
121
|
|
|
175
|
-
/**
|
|
176
|
-
* Resolve the per-token opacity multiplier for the current frame from the
|
|
177
|
-
* persistent highlight dim plus every active dim transition.
|
|
178
|
-
*/
|
|
122
|
+
/** Per-token opacity: the persistent highlight dim, overridden by each active dim transition. */
|
|
179
123
|
export function resolveTokenStates(
|
|
180
124
|
tokenLines: IdLine[],
|
|
181
125
|
transitions: CodeTransition[],
|