saccade 0.0.1 → 0.0.3
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/README.md +6 -6
- package/dist/core.cjs +74 -58
- package/dist/core.cjs.map +1 -1
- package/dist/core.d.cts +4 -4
- package/dist/core.d.ts +4 -4
- package/dist/core.mjs +73 -57
- package/dist/core.mjs.map +1 -1
- package/dist/index.cjs +105 -85
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +11 -11
- package/dist/index.d.ts +11 -11
- package/dist/index.mjs +101 -81
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/core.d.cts
CHANGED
|
@@ -87,15 +87,15 @@ type TimelineExport = {
|
|
|
87
87
|
}[];
|
|
88
88
|
};
|
|
89
89
|
|
|
90
|
-
type
|
|
91
|
-
declare class
|
|
90
|
+
type SaccadeState = 'idle' | 'recording' | 'scrubbing';
|
|
91
|
+
declare class SaccadeEngine {
|
|
92
92
|
private timing;
|
|
93
93
|
private recorder;
|
|
94
94
|
private scrubber;
|
|
95
95
|
private capture;
|
|
96
96
|
private _state;
|
|
97
97
|
private listeners;
|
|
98
|
-
get state():
|
|
98
|
+
get state(): SaccadeState;
|
|
99
99
|
getCapture(): TimelineCapture | null;
|
|
100
100
|
setSpeed(speed: number): void;
|
|
101
101
|
getSpeed(): number;
|
|
@@ -273,4 +273,4 @@ declare function getFrameAtTime(frames: FrameSnapshot[], timeMs: number): FrameS
|
|
|
273
273
|
declare function generateExport(animations: AnimationInfo[], frames: FrameSnapshot[], timeMs: number, filter?: ExportFilter): TimelineExport;
|
|
274
274
|
declare function formatExportForLLM(exp: TimelineExport, detail?: OutputDetailLevel): string;
|
|
275
275
|
|
|
276
|
-
export { type AnimationInfo, type ElementSnapshot, type ExportFilter, type FrameAnimation, type FrameSnapshot, type InterceptedAnimation,
|
|
276
|
+
export { type AnimationInfo, type ElementSnapshot, type ExportFilter, type FrameAnimation, type FrameSnapshot, type InterceptedAnimation, type OutputDetailLevel, type PropertySnapshot, type Rect, SaccadeEngine, type SaccadeState, type ScrubberState, type TimelineCapture, type TimelineExport, TimelineRecorder, TimelineScrubber, TimingController, formatExportForLLM, generateExport, getFrameAtTime };
|
package/dist/core.d.ts
CHANGED
|
@@ -87,15 +87,15 @@ type TimelineExport = {
|
|
|
87
87
|
}[];
|
|
88
88
|
};
|
|
89
89
|
|
|
90
|
-
type
|
|
91
|
-
declare class
|
|
90
|
+
type SaccadeState = 'idle' | 'recording' | 'scrubbing';
|
|
91
|
+
declare class SaccadeEngine {
|
|
92
92
|
private timing;
|
|
93
93
|
private recorder;
|
|
94
94
|
private scrubber;
|
|
95
95
|
private capture;
|
|
96
96
|
private _state;
|
|
97
97
|
private listeners;
|
|
98
|
-
get state():
|
|
98
|
+
get state(): SaccadeState;
|
|
99
99
|
getCapture(): TimelineCapture | null;
|
|
100
100
|
setSpeed(speed: number): void;
|
|
101
101
|
getSpeed(): number;
|
|
@@ -273,4 +273,4 @@ declare function getFrameAtTime(frames: FrameSnapshot[], timeMs: number): FrameS
|
|
|
273
273
|
declare function generateExport(animations: AnimationInfo[], frames: FrameSnapshot[], timeMs: number, filter?: ExportFilter): TimelineExport;
|
|
274
274
|
declare function formatExportForLLM(exp: TimelineExport, detail?: OutputDetailLevel): string;
|
|
275
275
|
|
|
276
|
-
export { type AnimationInfo, type ElementSnapshot, type ExportFilter, type FrameAnimation, type FrameSnapshot, type InterceptedAnimation,
|
|
276
|
+
export { type AnimationInfo, type ElementSnapshot, type ExportFilter, type FrameAnimation, type FrameSnapshot, type InterceptedAnimation, type OutputDetailLevel, type PropertySnapshot, type Rect, SaccadeEngine, type SaccadeState, type ScrubberState, type TimelineCapture, type TimelineExport, TimelineRecorder, TimelineScrubber, TimingController, formatExportForLLM, generateExport, getFrameAtTime };
|
package/dist/core.mjs
CHANGED
|
@@ -1004,11 +1004,12 @@ var _TimelineRecorder = class _TimelineRecorder {
|
|
|
1004
1004
|
document.removeEventListener("pointerup", this.onPointerUp, true);
|
|
1005
1005
|
try {
|
|
1006
1006
|
for (const anim of document.getAnimations()) {
|
|
1007
|
+
const target = anim.effect?.target;
|
|
1008
|
+
if (target?.closest?.("[data-lapse-panel]")) continue;
|
|
1007
1009
|
anim.cancel();
|
|
1008
1010
|
}
|
|
1009
1011
|
} catch (_) {
|
|
1010
1012
|
}
|
|
1011
|
-
window.requestAnimationFrame = () => 0;
|
|
1012
1013
|
const noTransitions = document.createElement("style");
|
|
1013
1014
|
noTransitions.id = "__lapse-no-transitions";
|
|
1014
1015
|
noTransitions.textContent = "*, *::before, *::after { transition: none !important; animation: none !important; }";
|
|
@@ -1020,64 +1021,61 @@ var _TimelineRecorder = class _TimelineRecorder {
|
|
|
1020
1021
|
blocker.title = "Clear the timeline to interact with the page";
|
|
1021
1022
|
document.body.appendChild(blocker);
|
|
1022
1023
|
this.blockerEl = blocker;
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
if (t && (t.includes(":hover") || t.includes(":focus"))) {
|
|
1041
|
-
allCss += t + "\n";
|
|
1024
|
+
setTimeout(() => {
|
|
1025
|
+
try {
|
|
1026
|
+
const lapseStyle = document.createElement("style");
|
|
1027
|
+
lapseStyle.id = "__lapse-state-rules";
|
|
1028
|
+
const hoverFocusRules = [];
|
|
1029
|
+
for (const sheet of document.styleSheets) {
|
|
1030
|
+
try {
|
|
1031
|
+
const walk = (rules) => {
|
|
1032
|
+
for (const rule of rules) {
|
|
1033
|
+
if (rule.cssRules) {
|
|
1034
|
+
walk(rule.cssRules);
|
|
1035
|
+
continue;
|
|
1036
|
+
}
|
|
1037
|
+
const t = rule.cssText;
|
|
1038
|
+
if (t && (t.includes(":hover") || t.includes(":focus"))) {
|
|
1039
|
+
hoverFocusRules.push(t);
|
|
1040
|
+
}
|
|
1042
1041
|
}
|
|
1043
|
-
}
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
walk2(sheet.cssRules);
|
|
1047
|
-
} catch (_) {
|
|
1048
|
-
}
|
|
1049
|
-
}
|
|
1050
|
-
const stateRegex = /([^{}]*(?::hover|:focus-visible|:focus-within|:focus(?!-))[^{}]*)\{([^{}]*)\}/g;
|
|
1051
|
-
let match;
|
|
1052
|
-
while ((match = stateRegex.exec(allCss)) !== null) {
|
|
1053
|
-
const selector = match[1].trim();
|
|
1054
|
-
const body = match[2].trim();
|
|
1055
|
-
if (!body) continue;
|
|
1056
|
-
const newBody = body.replace(
|
|
1057
|
-
/([^;:]+):\s*([^;]+)(;|$)/g,
|
|
1058
|
-
(m, prop, val, end) => {
|
|
1059
|
-
if (val.includes("!important")) return m;
|
|
1060
|
-
return prop + ": " + val.trim() + " !important" + end;
|
|
1042
|
+
};
|
|
1043
|
+
walk(sheet.cssRules);
|
|
1044
|
+
} catch (_) {
|
|
1061
1045
|
}
|
|
1062
|
-
);
|
|
1063
|
-
if (selector.includes(":hover")) {
|
|
1064
|
-
lapseStyle.textContent += selector.replace(/:hover/g, "[data-lapse-hover]") + " { " + newBody + " }\n";
|
|
1065
1046
|
}
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1047
|
+
const parts = [];
|
|
1048
|
+
for (const ruleText of hoverFocusRules) {
|
|
1049
|
+
const braceIdx = ruleText.indexOf("{");
|
|
1050
|
+
if (braceIdx === -1) continue;
|
|
1051
|
+
const selector = ruleText.slice(0, braceIdx).trim();
|
|
1052
|
+
const bodyEnd = ruleText.lastIndexOf("}");
|
|
1053
|
+
const body = ruleText.slice(braceIdx + 1, bodyEnd).trim();
|
|
1054
|
+
if (!body) continue;
|
|
1055
|
+
const newBody = body.replace(
|
|
1056
|
+
/([^;:]+):\s*([^;]+)(;|$)/g,
|
|
1057
|
+
(m, prop, val, end) => {
|
|
1058
|
+
if (val.includes("!important")) return m;
|
|
1059
|
+
return prop + ": " + val.trim() + " !important" + end;
|
|
1060
|
+
}
|
|
1061
|
+
);
|
|
1062
|
+
if (selector.includes(":hover")) {
|
|
1063
|
+
parts.push(selector.replace(/:hover/g, "[data-lapse-hover]") + " { " + newBody + " }");
|
|
1064
|
+
}
|
|
1065
|
+
if (selector.includes(":focus-visible")) {
|
|
1066
|
+
parts.push(selector.replace(/:focus-visible/g, "[data-lapse-focus]") + " { " + newBody + " }");
|
|
1067
|
+
} else if (selector.includes(":focus-within")) {
|
|
1068
|
+
parts.push(selector.replace(/:focus-within/g, ":has([data-lapse-focus])") + " { " + newBody + " }");
|
|
1069
|
+
} else if (selector.includes(":focus")) {
|
|
1070
|
+
parts.push(selector.replace(/:focus(?!-)/g, "[data-lapse-focus]") + " { " + newBody + " }");
|
|
1071
|
+
}
|
|
1075
1072
|
}
|
|
1073
|
+
lapseStyle.textContent = parts.join("\n");
|
|
1074
|
+
document.head.appendChild(lapseStyle);
|
|
1075
|
+
this.lapseStyleEl = lapseStyle;
|
|
1076
|
+
} catch (_) {
|
|
1076
1077
|
}
|
|
1077
|
-
|
|
1078
|
-
this.lapseStyleEl = lapseStyle;
|
|
1079
|
-
} catch (_) {
|
|
1080
|
-
}
|
|
1078
|
+
}, 0);
|
|
1081
1079
|
if (this.frames.length > 0) {
|
|
1082
1080
|
const frame0 = this.frames[0];
|
|
1083
1081
|
if (frame0.elementSnapshots) {
|
|
@@ -1590,7 +1588,7 @@ function formatExportForLLM(exp, detail = "standard") {
|
|
|
1590
1588
|
}
|
|
1591
1589
|
|
|
1592
1590
|
// src/core/engine.ts
|
|
1593
|
-
var
|
|
1591
|
+
var SaccadeEngine = class {
|
|
1594
1592
|
constructor() {
|
|
1595
1593
|
this.timing = new TimingController();
|
|
1596
1594
|
this.recorder = new TimelineRecorder();
|
|
@@ -1632,7 +1630,25 @@ var LapseEngine = class {
|
|
|
1632
1630
|
boundingBox: null
|
|
1633
1631
|
};
|
|
1634
1632
|
}
|
|
1635
|
-
|
|
1633
|
+
let capture;
|
|
1634
|
+
try {
|
|
1635
|
+
capture = this.recorder.stopRecording();
|
|
1636
|
+
} catch (e) {
|
|
1637
|
+
console.error("[Saccade] stopRecording failed:", e);
|
|
1638
|
+
document.getElementById("__lapse-scrub-blocker")?.remove();
|
|
1639
|
+
document.getElementById("__lapse-no-transitions")?.remove();
|
|
1640
|
+
document.getElementById("__lapse-state-rules")?.remove();
|
|
1641
|
+
this._state = "idle";
|
|
1642
|
+
this.notify();
|
|
1643
|
+
return {
|
|
1644
|
+
startTime: 0,
|
|
1645
|
+
endTime: 0,
|
|
1646
|
+
duration: 0,
|
|
1647
|
+
animations: [],
|
|
1648
|
+
frames: [],
|
|
1649
|
+
boundingBox: null
|
|
1650
|
+
};
|
|
1651
|
+
}
|
|
1636
1652
|
this.capture = capture;
|
|
1637
1653
|
const scrubberState = {
|
|
1638
1654
|
elements: this.recorder.elements,
|
|
@@ -1692,7 +1708,7 @@ var LapseEngine = class {
|
|
|
1692
1708
|
}
|
|
1693
1709
|
};
|
|
1694
1710
|
export {
|
|
1695
|
-
|
|
1711
|
+
SaccadeEngine,
|
|
1696
1712
|
TimelineRecorder,
|
|
1697
1713
|
TimelineScrubber,
|
|
1698
1714
|
TimingController,
|