clarity-js 0.8.11 → 0.8.13-beta
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/build/clarity.extended.js +1 -1
- package/build/clarity.insight.js +1 -1
- package/build/clarity.js +2964 -3181
- package/build/clarity.min.js +1 -1
- package/build/clarity.module.js +2964 -3181
- package/build/clarity.performance.js +1 -1
- package/package.json +69 -76
- package/rollup.config.ts +88 -84
- package/src/clarity.ts +28 -34
- package/src/core/config.ts +2 -2
- package/src/core/event.ts +32 -36
- package/src/core/hash.ts +6 -5
- package/src/core/history.ts +11 -10
- package/src/core/index.ts +11 -21
- package/src/core/measure.ts +5 -9
- package/src/core/report.ts +3 -3
- package/src/core/scrub.ts +20 -29
- package/src/core/task.ts +45 -73
- package/src/core/time.ts +3 -3
- package/src/core/timeout.ts +2 -2
- package/src/core/version.ts +1 -1
- package/src/data/baseline.ts +55 -60
- package/src/data/consent.ts +2 -2
- package/src/data/custom.ts +13 -8
- package/src/data/dimension.ts +7 -11
- package/src/data/encode.ts +30 -36
- package/src/data/envelope.ts +38 -38
- package/src/data/extract.ts +77 -86
- package/src/data/index.ts +6 -10
- package/src/data/limit.ts +1 -1
- package/src/data/metadata.ts +266 -305
- package/src/data/metric.ts +8 -18
- package/src/data/ping.ts +4 -8
- package/src/data/signal.ts +18 -18
- package/src/data/summary.ts +4 -6
- package/src/data/token.ts +8 -10
- package/src/data/upgrade.ts +3 -7
- package/src/data/upload.ts +49 -100
- package/src/data/variable.ts +20 -27
- package/src/diagnostic/encode.ts +2 -2
- package/src/diagnostic/fraud.ts +4 -3
- package/src/diagnostic/internal.ts +5 -11
- package/src/diagnostic/script.ts +8 -12
- package/src/global.ts +1 -1
- package/src/insight/blank.ts +4 -4
- package/src/insight/encode.ts +17 -23
- package/src/insight/snapshot.ts +37 -57
- package/src/interaction/change.ts +6 -9
- package/src/interaction/click.ts +28 -34
- package/src/interaction/clipboard.ts +2 -2
- package/src/interaction/encode.ts +31 -35
- package/src/interaction/input.ts +9 -11
- package/src/interaction/pointer.ts +24 -35
- package/src/interaction/resize.ts +5 -5
- package/src/interaction/scroll.ts +11 -14
- package/src/interaction/selection.ts +8 -12
- package/src/interaction/submit.ts +2 -2
- package/src/interaction/timeline.ts +9 -13
- package/src/interaction/unload.ts +1 -1
- package/src/interaction/visibility.ts +2 -2
- package/src/layout/animation.ts +41 -47
- package/src/layout/discover.ts +5 -5
- package/src/layout/document.ts +19 -31
- package/src/layout/dom.ts +91 -141
- package/src/layout/encode.ts +37 -52
- package/src/layout/mutation.ts +318 -321
- package/src/layout/node.ts +81 -104
- package/src/layout/offset.ts +6 -7
- package/src/layout/region.ts +40 -60
- package/src/layout/schema.ts +8 -15
- package/src/layout/selector.ts +25 -47
- package/src/layout/style.ts +36 -44
- package/src/layout/target.ts +10 -14
- package/src/layout/traverse.ts +11 -17
- package/src/performance/blank.ts +1 -1
- package/src/performance/encode.ts +4 -4
- package/src/performance/interaction.ts +70 -58
- package/src/performance/navigation.ts +2 -2
- package/src/performance/observer.ts +26 -59
- package/src/queue.ts +9 -16
- package/tsconfig.json +1 -1
- package/tslint.json +32 -25
- package/types/core.d.ts +13 -13
- package/types/data.d.ts +29 -32
- package/types/diagnostic.d.ts +1 -1
- package/types/interaction.d.ts +4 -4
- package/types/layout.d.ts +21 -36
- package/types/performance.d.ts +5 -6
- package/.lintstagedrc.yml +0 -3
- package/biome.json +0 -43
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { Constant, Event,
|
|
1
|
+
import { Constant, Event, Token } from "@clarity-types/data";
|
|
2
2
|
import * as scrub from "@src/core/scrub";
|
|
3
3
|
import { time } from "@src/core/time";
|
|
4
4
|
import * as baseline from "@src/data/baseline";
|
|
5
5
|
import { queue } from "@src/data/upload";
|
|
6
|
+
import { metadata } from "@src/layout/target";
|
|
6
7
|
import * as change from "@src/interaction/change";
|
|
7
8
|
import * as click from "@src/interaction/click";
|
|
8
9
|
import * as clipboard from "@src/interaction/clipboard";
|
|
@@ -15,10 +16,9 @@ import * as submit from "@src/interaction/submit";
|
|
|
15
16
|
import * as timeline from "@src/interaction/timeline";
|
|
16
17
|
import * as unload from "@src/interaction/unload";
|
|
17
18
|
import * as visibility from "@src/interaction/visibility";
|
|
18
|
-
import { metadata } from "@src/layout/target";
|
|
19
19
|
|
|
20
20
|
export default async function (type: Event, ts: number = null): Promise<void> {
|
|
21
|
-
|
|
21
|
+
let t = ts || time();
|
|
22
22
|
let tokens: Token[] = [t, type];
|
|
23
23
|
switch (type) {
|
|
24
24
|
case Event.MouseDown:
|
|
@@ -30,15 +30,15 @@ export default async function (type: Event, ts: number = null): Promise<void> {
|
|
|
30
30
|
case Event.TouchEnd:
|
|
31
31
|
case Event.TouchMove:
|
|
32
32
|
case Event.TouchCancel:
|
|
33
|
-
for (
|
|
34
|
-
|
|
33
|
+
for (let entry of pointer.state) {
|
|
34
|
+
let pTarget = metadata(entry.data.target as Node, entry.event);
|
|
35
35
|
if (pTarget.id > 0) {
|
|
36
36
|
tokens = [entry.time, entry.event];
|
|
37
37
|
tokens.push(pTarget.id);
|
|
38
38
|
tokens.push(entry.data.x);
|
|
39
39
|
tokens.push(entry.data.y);
|
|
40
|
-
if (entry.data.id !== undefined) {
|
|
41
|
-
tokens.push(entry.data.id);
|
|
40
|
+
if (entry.data.id !== undefined) {
|
|
41
|
+
tokens.push(entry.data.id);
|
|
42
42
|
|
|
43
43
|
if (entry.data.isPrimary !== undefined) {
|
|
44
44
|
tokens.push(entry.data.isPrimary.toString());
|
|
@@ -53,10 +53,10 @@ export default async function (type: Event, ts: number = null): Promise<void> {
|
|
|
53
53
|
pointer.reset();
|
|
54
54
|
break;
|
|
55
55
|
case Event.Click:
|
|
56
|
-
for (
|
|
57
|
-
|
|
56
|
+
for (let entry of click.state) {
|
|
57
|
+
let cTarget = metadata(entry.data.target as Node, entry.event, entry.data.text);
|
|
58
58
|
tokens = [entry.time, entry.event];
|
|
59
|
-
|
|
59
|
+
let cHash = cTarget.hash ? cTarget.hash.join(Constant.Dot) : Constant.Empty;
|
|
60
60
|
tokens.push(cTarget.id);
|
|
61
61
|
tokens.push(entry.data.x);
|
|
62
62
|
tokens.push(entry.data.y);
|
|
@@ -76,9 +76,9 @@ export default async function (type: Event, ts: number = null): Promise<void> {
|
|
|
76
76
|
click.reset();
|
|
77
77
|
break;
|
|
78
78
|
case Event.Clipboard:
|
|
79
|
-
for (
|
|
79
|
+
for (let entry of clipboard.state) {
|
|
80
80
|
tokens = [entry.time, entry.event];
|
|
81
|
-
|
|
81
|
+
let target = metadata(entry.data.target as Node, entry.event);
|
|
82
82
|
if (target.id > 0) {
|
|
83
83
|
tokens.push(target.id);
|
|
84
84
|
tokens.push(entry.data.action);
|
|
@@ -87,26 +87,24 @@ export default async function (type: Event, ts: number = null): Promise<void> {
|
|
|
87
87
|
}
|
|
88
88
|
clipboard.reset();
|
|
89
89
|
break;
|
|
90
|
-
case Event.Resize:
|
|
91
|
-
|
|
90
|
+
case Event.Resize:
|
|
91
|
+
let r = resize.data;
|
|
92
92
|
tokens.push(r.width);
|
|
93
93
|
tokens.push(r.height);
|
|
94
94
|
baseline.track(type, r.width, r.height);
|
|
95
95
|
resize.reset();
|
|
96
96
|
queue(tokens);
|
|
97
97
|
break;
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
const u = unload.data;
|
|
98
|
+
case Event.Unload:
|
|
99
|
+
let u = unload.data;
|
|
101
100
|
tokens.push(u.name);
|
|
102
101
|
tokens.push(u.persisted);
|
|
103
102
|
unload.reset();
|
|
104
103
|
queue(tokens);
|
|
105
104
|
break;
|
|
106
|
-
}
|
|
107
105
|
case Event.Input:
|
|
108
|
-
for (
|
|
109
|
-
|
|
106
|
+
for (let entry of input.state) {
|
|
107
|
+
let iTarget = metadata(entry.data.target as Node, entry.event, entry.data.value);
|
|
110
108
|
tokens = [entry.time, entry.event];
|
|
111
109
|
tokens.push(iTarget.id);
|
|
112
110
|
tokens.push(scrub.text(entry.data.value, "input", iTarget.privacy, false, entry.data.type));
|
|
@@ -114,11 +112,11 @@ export default async function (type: Event, ts: number = null): Promise<void> {
|
|
|
114
112
|
}
|
|
115
113
|
input.reset();
|
|
116
114
|
break;
|
|
117
|
-
case Event.Selection:
|
|
118
|
-
|
|
115
|
+
case Event.Selection:
|
|
116
|
+
let s = selection.data;
|
|
119
117
|
if (s) {
|
|
120
|
-
|
|
121
|
-
|
|
118
|
+
let startTarget = metadata(s.start as Node, type);
|
|
119
|
+
let endTarget = metadata(s.end as Node, type);
|
|
122
120
|
tokens.push(startTarget.id);
|
|
123
121
|
tokens.push(s.startOffset);
|
|
124
122
|
tokens.push(endTarget.id);
|
|
@@ -127,10 +125,9 @@ export default async function (type: Event, ts: number = null): Promise<void> {
|
|
|
127
125
|
queue(tokens);
|
|
128
126
|
}
|
|
129
127
|
break;
|
|
130
|
-
}
|
|
131
128
|
case Event.Scroll:
|
|
132
|
-
for (
|
|
133
|
-
|
|
129
|
+
for (let entry of scroll.state) {
|
|
130
|
+
let sTarget = metadata(entry.data.target as Node, entry.event);
|
|
134
131
|
const top = metadata(entry.data.top as Node, entry.event);
|
|
135
132
|
const bottom = metadata(entry.data.bottom as Node, entry.event);
|
|
136
133
|
const sTopHash = top?.hash ? top.hash.join(Constant.Dot) : Constant.Empty;
|
|
@@ -149,9 +146,9 @@ export default async function (type: Event, ts: number = null): Promise<void> {
|
|
|
149
146
|
scroll.reset();
|
|
150
147
|
break;
|
|
151
148
|
case Event.Change:
|
|
152
|
-
for (
|
|
149
|
+
for (let entry of change.state) {
|
|
153
150
|
tokens = [entry.time, entry.event];
|
|
154
|
-
|
|
151
|
+
let target = metadata(entry.data.target as Node, entry.event);
|
|
155
152
|
if (target.id > 0) {
|
|
156
153
|
tokens = [entry.time, entry.event];
|
|
157
154
|
tokens.push(target.id);
|
|
@@ -164,9 +161,9 @@ export default async function (type: Event, ts: number = null): Promise<void> {
|
|
|
164
161
|
change.reset();
|
|
165
162
|
break;
|
|
166
163
|
case Event.Submit:
|
|
167
|
-
for (
|
|
164
|
+
for (let entry of submit.state) {
|
|
168
165
|
tokens = [entry.time, entry.event];
|
|
169
|
-
|
|
166
|
+
let target = metadata(entry.data.target as Node, entry.event);
|
|
170
167
|
if (target.id > 0) {
|
|
171
168
|
tokens.push(target.id);
|
|
172
169
|
queue(tokens);
|
|
@@ -175,7 +172,7 @@ export default async function (type: Event, ts: number = null): Promise<void> {
|
|
|
175
172
|
submit.reset();
|
|
176
173
|
break;
|
|
177
174
|
case Event.Timeline:
|
|
178
|
-
for (
|
|
175
|
+
for (let entry of timeline.updates) {
|
|
179
176
|
tokens = [entry.time, entry.event];
|
|
180
177
|
tokens.push(entry.data.type);
|
|
181
178
|
tokens.push(entry.data.hash);
|
|
@@ -187,13 +184,12 @@ export default async function (type: Event, ts: number = null): Promise<void> {
|
|
|
187
184
|
}
|
|
188
185
|
timeline.reset();
|
|
189
186
|
break;
|
|
190
|
-
case Event.Visibility:
|
|
191
|
-
|
|
187
|
+
case Event.Visibility:
|
|
188
|
+
let v = visibility.data;
|
|
192
189
|
tokens.push(v.visible);
|
|
193
190
|
queue(tokens);
|
|
194
191
|
baseline.visibility(t, v.visible);
|
|
195
192
|
visibility.reset();
|
|
196
193
|
break;
|
|
197
|
-
}
|
|
198
194
|
}
|
|
199
195
|
}
|
package/src/interaction/input.ts
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { Event } from "@clarity-types/data";
|
|
2
|
-
import {
|
|
2
|
+
import { InputData, InputState, Setting } from "@clarity-types/interaction";
|
|
3
3
|
import { FunctionNames } from "@clarity-types/performance";
|
|
4
4
|
import { bind } from "@src/core/event";
|
|
5
5
|
import { schedule } from "@src/core/task";
|
|
6
6
|
import { time } from "@src/core/time";
|
|
7
7
|
import { clearTimeout, setTimeout } from "@src/core/timeout";
|
|
8
8
|
import { get } from "@src/layout/dom";
|
|
9
|
-
import { target } from "@src/layout/target";
|
|
10
9
|
import encode from "./encode";
|
|
10
|
+
import { target } from "@src/layout/target";
|
|
11
11
|
|
|
12
12
|
let timeout: number = null;
|
|
13
13
|
export let state: InputState[] = [];
|
|
@@ -22,11 +22,11 @@ export function observe(root: Node): void {
|
|
|
22
22
|
|
|
23
23
|
function recompute(evt: UIEvent): void {
|
|
24
24
|
recompute.dn = FunctionNames.InputRecompute;
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
if (input
|
|
25
|
+
let input = target(evt) as HTMLInputElement;
|
|
26
|
+
let value = get(input);
|
|
27
|
+
if (input && input.type && value) {
|
|
28
28
|
let v = input.value;
|
|
29
|
-
|
|
29
|
+
let t = input.type;
|
|
30
30
|
switch (input.type) {
|
|
31
31
|
case "radio":
|
|
32
32
|
case "checkbox":
|
|
@@ -34,12 +34,10 @@ function recompute(evt: UIEvent): void {
|
|
|
34
34
|
break;
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
|
|
37
|
+
let data: InputData = { target: input, value: v, type: t };
|
|
38
38
|
|
|
39
39
|
// If last entry in the queue is for the same target node as the current one, remove it so we can later swap it with current data.
|
|
40
|
-
if (state.length > 0 && state[state.length - 1].data.target === data.target) {
|
|
41
|
-
state.pop();
|
|
42
|
-
}
|
|
40
|
+
if (state.length > 0 && (state[state.length - 1].data.target === data.target)) { state.pop(); }
|
|
43
41
|
|
|
44
42
|
state.push({ time: time(evt), event: Event.Input, data });
|
|
45
43
|
|
|
@@ -59,4 +57,4 @@ export function reset(): void {
|
|
|
59
57
|
export function stop(): void {
|
|
60
58
|
clearTimeout(timeout);
|
|
61
59
|
reset();
|
|
62
|
-
}
|
|
60
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Event } from "@clarity-types/data";
|
|
2
|
-
import {
|
|
2
|
+
import { PointerState, Setting } from "@clarity-types/interaction";
|
|
3
3
|
import { FunctionNames } from "@clarity-types/performance";
|
|
4
4
|
import { bind } from "@src/core/event";
|
|
5
5
|
import { schedule } from "@src/core/task";
|
|
@@ -34,47 +34,45 @@ export function observe(root: Node): void {
|
|
|
34
34
|
|
|
35
35
|
function mouse(event: Event, root: Node, evt: MouseEvent): void {
|
|
36
36
|
mouse.dn = FunctionNames.PointerMouse;
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
let x = "pageX" in evt ? Math.round(evt.pageX) : "clientX" in evt ? Math.round(
|
|
40
|
-
let y = "pageY" in evt ? Math.round(evt.pageY) : "clientY" in evt ? Math.round(
|
|
37
|
+
let frame = iframe(root);
|
|
38
|
+
let d = frame ? frame.contentDocument.documentElement : document.documentElement;
|
|
39
|
+
let x = "pageX" in evt ? Math.round(evt.pageX) : ("clientX" in evt ? Math.round(evt["clientX"] + d.scrollLeft) : null);
|
|
40
|
+
let y = "pageY" in evt ? Math.round(evt.pageY) : ("clientY" in evt ? Math.round(evt["clientY"] + d.scrollTop) : null);
|
|
41
41
|
// In case of iframe, we adjust (x,y) to be relative to top parent's origin
|
|
42
42
|
if (frame) {
|
|
43
|
-
|
|
43
|
+
let distance = offset(frame);
|
|
44
44
|
x = x ? x + Math.round(distance.x) : x;
|
|
45
45
|
y = y ? y + Math.round(distance.y) : y;
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
// Check for null values before processing this event
|
|
49
|
-
if (x !== null && y !== null) {
|
|
50
|
-
handler({ time: time(evt), event, data: { target: target(evt), x, y } });
|
|
51
|
-
}
|
|
49
|
+
if (x !== null && y !== null) { handler({ time: time(evt), event, data: { target: target(evt), x, y } }); }
|
|
52
50
|
}
|
|
53
51
|
|
|
54
52
|
function touch(event: Event, root: Node, evt: TouchEvent): void {
|
|
55
53
|
touch.dn = FunctionNames.PointerTouch;
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
54
|
+
let frame = iframe(root);
|
|
55
|
+
let d = frame ? frame.contentDocument.documentElement : document.documentElement;
|
|
56
|
+
let touches = evt.changedTouches;
|
|
59
57
|
|
|
60
|
-
|
|
58
|
+
let t = time(evt);
|
|
61
59
|
if (touches) {
|
|
62
60
|
for (let i = 0; i < touches.length; i++) {
|
|
63
|
-
|
|
64
|
-
let x = "clientX" in entry ? Math.round(entry
|
|
65
|
-
let y = "clientY" in entry ? Math.round(entry
|
|
61
|
+
let entry = touches[i];
|
|
62
|
+
let x = "clientX" in entry ? Math.round(entry["clientX"] + d.scrollLeft) : null;
|
|
63
|
+
let y = "clientY" in entry ? Math.round(entry["clientY"] + d.scrollTop) : null;
|
|
66
64
|
x = x && frame ? x + Math.round(frame.offsetLeft) : x;
|
|
67
65
|
y = y && frame ? y + Math.round(frame.offsetTop) : y;
|
|
68
66
|
|
|
69
67
|
// We cannot rely on identifier to determine primary touch as its value doesn't always start with 0.
|
|
70
68
|
// Safari/Webkit uses the address of the UITouch object as the identifier value for each touch point.
|
|
71
|
-
const id = "identifier" in entry ? entry
|
|
69
|
+
const id = "identifier" in entry ? entry["identifier"] : undefined;
|
|
72
70
|
|
|
73
|
-
switch
|
|
71
|
+
switch(event) {
|
|
74
72
|
case Event.TouchStart:
|
|
75
73
|
if (activeTouchPointIds.size === 0) {
|
|
76
74
|
// Track presence of primary touch separately to handle scenarios when same id is repeated
|
|
77
|
-
hasPrimaryTouch = true;
|
|
75
|
+
hasPrimaryTouch = true;
|
|
78
76
|
primaryTouchId = id;
|
|
79
77
|
}
|
|
80
78
|
activeTouchPointIds.add(id);
|
|
@@ -87,15 +85,11 @@ function touch(event: Event, root: Node, evt: TouchEvent): void {
|
|
|
87
85
|
const isPrimary = hasPrimaryTouch && primaryTouchId === id;
|
|
88
86
|
|
|
89
87
|
// Check for null values before processing this event
|
|
90
|
-
if (x !== null && y !== null) {
|
|
91
|
-
handler({ time: t, event, data: { target: target(evt), x, y, id, isPrimary } });
|
|
92
|
-
}
|
|
88
|
+
if (x !== null && y !== null) { handler({ time: t, event, data: { target: target(evt), x, y, id, isPrimary } }); }
|
|
93
89
|
|
|
94
90
|
// Reset primary touch point id once touch event ends
|
|
95
91
|
if (event === Event.TouchCancel || event === Event.TouchEnd) {
|
|
96
|
-
if (primaryTouchId === id) {
|
|
97
|
-
hasPrimaryTouch = false;
|
|
98
|
-
}
|
|
92
|
+
if (primaryTouchId === id) { hasPrimaryTouch = false; }
|
|
99
93
|
}
|
|
100
94
|
}
|
|
101
95
|
}
|
|
@@ -105,18 +99,15 @@ function handler(current: PointerState): void {
|
|
|
105
99
|
switch (current.event) {
|
|
106
100
|
case Event.MouseMove:
|
|
107
101
|
case Event.MouseWheel:
|
|
108
|
-
case Event.TouchMove:
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
if (last && similar(last, current)) {
|
|
112
|
-
state.pop();
|
|
113
|
-
}
|
|
102
|
+
case Event.TouchMove:
|
|
103
|
+
let length = state.length;
|
|
104
|
+
let last = length > 1 ? state[length - 2] : null;
|
|
105
|
+
if (last && similar(last, current)) { state.pop(); }
|
|
114
106
|
state.push(current);
|
|
115
107
|
|
|
116
108
|
clearTimeout(timeout);
|
|
117
109
|
timeout = setTimeout(process, Setting.LookAhead, current.event);
|
|
118
110
|
break;
|
|
119
|
-
}
|
|
120
111
|
default:
|
|
121
112
|
state.push(current);
|
|
122
113
|
process(current.event);
|
|
@@ -145,7 +136,5 @@ function similar(last: PointerState, current: PointerState): boolean {
|
|
|
145
136
|
export function stop(): void {
|
|
146
137
|
clearTimeout(timeout);
|
|
147
138
|
// Send out any pending pointer events in the pipeline
|
|
148
|
-
if (state.length > 0) {
|
|
149
|
-
process(state[state.length - 1].event);
|
|
150
|
-
}
|
|
139
|
+
if (state.length > 0) { process(state[state.length - 1].event); }
|
|
151
140
|
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { Event } from "@clarity-types/data";
|
|
2
|
-
import {
|
|
2
|
+
import { ResizeData, Setting } from "@clarity-types/interaction";
|
|
3
3
|
import { FunctionNames } from "@clarity-types/performance";
|
|
4
|
-
import { bind } from "@src/core/event";
|
|
5
|
-
import { schedule } from "@src/core/task";
|
|
6
4
|
import { clearTimeout, setTimeout } from "@src/core/timeout";
|
|
5
|
+
import { bind } from "@src/core/event";
|
|
7
6
|
import encode from "./encode";
|
|
7
|
+
import { schedule } from "@src/core/task";
|
|
8
8
|
|
|
9
9
|
export let data: ResizeData;
|
|
10
10
|
let timeout: number = null;
|
|
@@ -18,7 +18,7 @@ export function start(): void {
|
|
|
18
18
|
|
|
19
19
|
function recompute(): void {
|
|
20
20
|
recompute.dn = FunctionNames.ResizeRecompute;
|
|
21
|
-
|
|
21
|
+
let de = document.documentElement;
|
|
22
22
|
// window.innerWidth includes width of the scrollbar and is not a true representation of the viewport width.
|
|
23
23
|
// Therefore, when possible, use documentElement's clientWidth property.
|
|
24
24
|
data = {
|
|
@@ -45,4 +45,4 @@ export function reset(): void {
|
|
|
45
45
|
|
|
46
46
|
export function stop(): void {
|
|
47
47
|
reset();
|
|
48
|
-
}
|
|
48
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Constant, Dimension, Event } from "@clarity-types/data";
|
|
2
|
-
import {
|
|
2
|
+
import { ScrollState, Setting } from "@clarity-types/interaction";
|
|
3
3
|
import { FunctionNames } from "@clarity-types/performance";
|
|
4
4
|
import { bind } from "@src/core/event";
|
|
5
5
|
import { schedule } from "@src/core/task";
|
|
@@ -8,7 +8,7 @@ import { clearTimeout, setTimeout } from "@src/core/timeout";
|
|
|
8
8
|
import throttle from "@src/core/throttle";
|
|
9
9
|
import * as dimension from "@src/data/dimension";
|
|
10
10
|
import { iframe } from "@src/layout/dom";
|
|
11
|
-
import {
|
|
11
|
+
import { target, metadata } from "@src/layout/target";
|
|
12
12
|
import encode from "./encode";
|
|
13
13
|
|
|
14
14
|
export let state: ScrollState[] = [];
|
|
@@ -35,7 +35,7 @@ function recompute(event: UIEvent = null): void {
|
|
|
35
35
|
|
|
36
36
|
// If the target is a Document node, then identify corresponding documentElement and window for this document
|
|
37
37
|
if (element && element.nodeType === Node.DOCUMENT_NODE) {
|
|
38
|
-
|
|
38
|
+
let frame = iframe(element);
|
|
39
39
|
w = frame ? frame.contentWindow : w;
|
|
40
40
|
element = de = (element as Document).documentElement;
|
|
41
41
|
}
|
|
@@ -43,8 +43,8 @@ function recompute(event: UIEvent = null): void {
|
|
|
43
43
|
// Edge doesn't support scrollTop position on document.documentElement.
|
|
44
44
|
// For cross browser compatibility, looking up pageYOffset on window if the scroll is on document.
|
|
45
45
|
// And, if for some reason that is not available, fall back to looking up scrollTop on document.documentElement.
|
|
46
|
-
|
|
47
|
-
|
|
46
|
+
let x = element === de && "pageXOffset" in w ? Math.round(w.pageXOffset) : Math.round((element as HTMLElement).scrollLeft);
|
|
47
|
+
let y = element === de && "pageYOffset" in w ? Math.round(w.pageYOffset) : Math.round((element as HTMLElement).scrollTop);
|
|
48
48
|
const width = window.innerWidth;
|
|
49
49
|
const height = window.innerHeight;
|
|
50
50
|
const xPosition = width / 3;
|
|
@@ -54,20 +54,18 @@ function recompute(event: UIEvent = null): void {
|
|
|
54
54
|
const top = getPositionNode(xPosition, startYPosition);
|
|
55
55
|
const bottom = getPositionNode(xPosition, endYPosition);
|
|
56
56
|
|
|
57
|
-
|
|
57
|
+
let current: ScrollState = { time: time(event), event: Event.Scroll, data: {target: element, x, y, top, bottom} };
|
|
58
58
|
|
|
59
59
|
// We don't send any scroll events if this is the first event and the current position is top (0,0)
|
|
60
|
-
if ((event === null && x === 0 && y === 0) || x === null || y === null) {
|
|
60
|
+
if ((event === null && x === 0 && y === 0) || (x === null || y === null)) {
|
|
61
61
|
initialTop = top;
|
|
62
62
|
initialBottom = bottom;
|
|
63
63
|
return;
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
if (last && similar(last, current)) {
|
|
69
|
-
state.pop();
|
|
70
|
-
}
|
|
66
|
+
let length = state.length;
|
|
67
|
+
let last = length > 1 ? state[length - 2] : null;
|
|
68
|
+
if (last && similar(last, current)) { state.pop(); }
|
|
71
69
|
state.push(current);
|
|
72
70
|
|
|
73
71
|
clearTimeout(timeout);
|
|
@@ -79,10 +77,9 @@ const throttledRecompute = throttle(recompute, Setting.Throttle);
|
|
|
79
77
|
function getPositionNode(x: number, y: number): Node {
|
|
80
78
|
let node: Node;
|
|
81
79
|
if ("caretPositionFromPoint" in document) {
|
|
82
|
-
// biome-ignore lint/suspicious/noExplicitAny: caretPositionFromPoint is not defined on all browsers, makes typescript unhappy
|
|
83
80
|
node = (document as any).caretPositionFromPoint(x, y)?.offsetNode;
|
|
84
81
|
} else if ("caretRangeFromPoint" in document) {
|
|
85
|
-
node = (document as
|
|
82
|
+
node = (document as any).caretRangeFromPoint(x, y)?.startContainer;
|
|
86
83
|
}
|
|
87
84
|
if (!node) {
|
|
88
85
|
node = document.elementFromPoint(x, y) as Node;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Event } from "@clarity-types/data";
|
|
2
|
-
import {
|
|
2
|
+
import { SelectionData, Setting } from "@clarity-types/interaction";
|
|
3
3
|
import { FunctionNames } from "@clarity-types/performance";
|
|
4
4
|
import { bind } from "@src/core/event";
|
|
5
5
|
import { schedule } from "@src/core/task";
|
|
@@ -21,25 +21,21 @@ export function observe(root: Node): void {
|
|
|
21
21
|
|
|
22
22
|
function recompute(root: Node): void {
|
|
23
23
|
recompute.dn = FunctionNames.SelectionRecompute;
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
let doc = root.nodeType === Node.DOCUMENT_NODE ? root as Document : document;
|
|
25
|
+
let current = doc.getSelection();
|
|
26
26
|
|
|
27
27
|
// Bail out if we don't have a valid selection
|
|
28
|
-
if (current === null) {
|
|
29
|
-
return;
|
|
30
|
-
}
|
|
28
|
+
if (current === null) { return; }
|
|
31
29
|
|
|
32
30
|
// Bail out if we got a valid selection but not valid nodes
|
|
33
31
|
// In Edge, selectionchange gets fired even on interactions like right clicks and
|
|
34
32
|
// can result in null anchorNode and focusNode if there was no previous selection on page
|
|
35
33
|
// Also, ignore any selections that start and end at the exact same point
|
|
36
|
-
if (
|
|
37
|
-
(current.anchorNode ===
|
|
38
|
-
(current.anchorNode === current.focusNode && current.anchorOffset === current.focusOffset)
|
|
39
|
-
) {
|
|
34
|
+
if ((current.anchorNode === null && current.focusNode === null) ||
|
|
35
|
+
(current.anchorNode === current.focusNode && current.anchorOffset === current.focusOffset)) {
|
|
40
36
|
return;
|
|
41
37
|
}
|
|
42
|
-
|
|
38
|
+
let startNode = data.start ? data.start : null;
|
|
43
39
|
if (previous !== null && data.start !== null && startNode !== current.anchorNode) {
|
|
44
40
|
clearTimeout(timeout);
|
|
45
41
|
process(Event.Selection);
|
|
@@ -49,7 +45,7 @@ function recompute(root: Node): void {
|
|
|
49
45
|
start: current.anchorNode,
|
|
50
46
|
startOffset: current.anchorOffset,
|
|
51
47
|
end: current.focusNode,
|
|
52
|
-
endOffset: current.focusOffset
|
|
48
|
+
endOffset: current.focusOffset
|
|
53
49
|
};
|
|
54
50
|
previous = current;
|
|
55
51
|
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { Event } from "@clarity-types/data";
|
|
2
|
-
import
|
|
2
|
+
import { SubmitState } from "@clarity-types/interaction";
|
|
3
3
|
import { FunctionNames } from "@clarity-types/performance";
|
|
4
4
|
import { bind } from "@src/core/event";
|
|
5
5
|
import { schedule } from "@src/core/task";
|
|
6
6
|
import { time } from "@src/core/time";
|
|
7
|
-
import { target } from "@src/layout/target";
|
|
8
7
|
import encode from "./encode";
|
|
8
|
+
import { target } from "@src/layout/target";
|
|
9
9
|
|
|
10
10
|
export let state: SubmitState[] = [];
|
|
11
11
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { BooleanFlag, Event } from "@clarity-types/data";
|
|
2
|
-
import { BrowsingContext, Setting,
|
|
2
|
+
import { BrowsingContext, Setting, TimelineState } from "@clarity-types/interaction";
|
|
3
3
|
import * as baseline from "@src/data/baseline";
|
|
4
4
|
import * as envelope from "@src/data/envelope";
|
|
5
5
|
import encode from "@src/interaction/encode";
|
|
@@ -16,15 +16,13 @@ export function reset(): void {
|
|
|
16
16
|
updates = [];
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
export function track(
|
|
20
|
-
time: number,
|
|
19
|
+
export function track(time: number,
|
|
21
20
|
event: Event,
|
|
22
21
|
hash: string,
|
|
23
22
|
x: number,
|
|
24
23
|
y: number,
|
|
25
24
|
reaction: number = BooleanFlag.True,
|
|
26
|
-
context: number = BrowsingContext.Self
|
|
27
|
-
): void {
|
|
25
|
+
context: number = BrowsingContext.Self): void {
|
|
28
26
|
state.push({
|
|
29
27
|
time,
|
|
30
28
|
event: Event.Timeline,
|
|
@@ -34,8 +32,8 @@ export function track(
|
|
|
34
32
|
x,
|
|
35
33
|
y,
|
|
36
34
|
reaction,
|
|
37
|
-
context
|
|
38
|
-
}
|
|
35
|
+
context
|
|
36
|
+
}
|
|
39
37
|
});
|
|
40
38
|
|
|
41
39
|
// Since timeline only keeps the data for configured time, we still want to continue tracking these values
|
|
@@ -47,14 +45,12 @@ export function track(
|
|
|
47
45
|
export function compute(): void {
|
|
48
46
|
const temp = [];
|
|
49
47
|
updates = [];
|
|
50
|
-
|
|
51
|
-
|
|
48
|
+
let max = envelope.data.start + envelope.data.duration;
|
|
49
|
+
let min = Math.max(max - Setting.TimelineSpan, 0);
|
|
52
50
|
|
|
53
|
-
for (
|
|
51
|
+
for (let s of state) {
|
|
54
52
|
if (s.time >= min) {
|
|
55
|
-
if (s.time <= max) {
|
|
56
|
-
updates.push(s);
|
|
57
|
-
}
|
|
53
|
+
if (s.time <= max) { updates.push(s); }
|
|
58
54
|
temp.push(s);
|
|
59
55
|
}
|
|
60
56
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { BooleanFlag, Event } from "@clarity-types/data";
|
|
2
|
-
import
|
|
2
|
+
import { UnloadData } from "@clarity-types/interaction";
|
|
3
3
|
import { FunctionNames } from "@clarity-types/performance";
|
|
4
4
|
import * as clarity from "@src/clarity";
|
|
5
5
|
import { bind } from "@src/core/event";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Event } from "@clarity-types/data";
|
|
2
|
-
import
|
|
2
|
+
import { VisibilityData } from "@clarity-types/interaction";
|
|
3
3
|
import { FunctionNames } from "@clarity-types/performance";
|
|
4
4
|
import { bind } from "@src/core/event";
|
|
5
5
|
import { time } from "@src/core/time";
|
|
@@ -24,4 +24,4 @@ export function reset(): void {
|
|
|
24
24
|
|
|
25
25
|
export function stop(): void {
|
|
26
26
|
reset();
|
|
27
|
-
}
|
|
27
|
+
}
|