@dynatrace/react-native-plugin 2.329.1 → 2.333.1
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 +102 -8
- package/android/build.gradle +1 -1
- package/android/src/main/java/com/dynatrace/android/agent/DynatraceRNBridgeImpl.kt +7 -1
- package/android/src/main/java/com/dynatrace/android/agent/DynatraceUtils.kt +1 -0
- package/android/src/new/java/com/dynatrace/android/agent/DynatraceRNBridge.kt +1 -0
- package/android/src/old/java/com/dynatrace/android/agent/DynatraceRNBridge.kt +2 -1
- package/files/plugin.gradle +1 -1
- package/instrumentation/DynatraceInstrumentation.js +1 -1
- package/instrumentation/jsx/CreateElement.js +106 -6
- package/instrumentation/jsx/JsxDevRuntime.js +2 -6
- package/instrumentation/jsx/JsxRuntime.js +2 -6
- package/instrumentation/libs/withOnPressMonitoring.js +49 -3
- package/ios/DynatraceRNBridge.mm +8 -1
- package/lib/core/Application.js +2 -0
- package/lib/core/Dynatrace.js +2 -1
- package/lib/core/UserPrivacyOptions.js +8 -1
- package/lib/core/configuration/ConfigurationHandler.js +21 -0
- package/lib/features/ui-interaction/Config.js +36 -0
- package/lib/features/ui-interaction/IUserInteractionEvent.js +16 -0
- package/lib/features/ui-interaction/Plugin.js +945 -0
- package/lib/features/ui-interaction/RootDetection.js +51 -0
- package/lib/features/ui-interaction/RootWrapper.js +236 -0
- package/lib/features/ui-interaction/Run.js +34 -0
- package/lib/features/ui-interaction/Runtime.js +1494 -0
- package/lib/features/ui-interaction/Types.js +75 -0
- package/lib/next/Dynatrace.js +35 -0
- package/lib/next/DynatraceArgValidators.js +10 -0
- package/lib/next/configuration/INativeRuntimeConfiguration.js +1 -0
- package/lib/next/configuration/RuntimeConfigurationObserver.js +47 -12
- package/lib/next/events/EventPipeline.js +9 -0
- package/lib/next/events/HttpRequestEventData.js +22 -20
- package/lib/next/events/modifier/ModifyEventValidation.js +2 -4
- package/lib/next/events/spec/EventSpecContstants.js +2 -2
- package/package.json +21 -11
- package/react-native-dynatrace.podspec +1 -1
- package/scripts/Config.js +1 -0
- package/src/lib/core/interface/NativeDynatraceBridge.ts +1 -0
- package/types.d.ts +46 -32
|
@@ -0,0 +1,1494 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TabButton = exports.LabelClaimScope = exports.AnalyticsRoot = exports.PathPrefix = exports.Segment = exports.AnalyticsProvider = exports._an_flat = exports.buildUiEventShape = exports.compactify = exports.FORCED_TOUCHABLES = exports.CfgCtx = void 0;
|
|
4
|
+
const React = require("react");
|
|
5
|
+
const react_1 = require("react");
|
|
6
|
+
const react_native_1 = require("react-native");
|
|
7
|
+
const EventPipeline_1 = require("../../../lib/next/events/EventPipeline");
|
|
8
|
+
const EventTimestamp_1 = require("../../../lib/next/events/EventTimestamp");
|
|
9
|
+
const ConsoleLogger_1 = require("../../../lib/core/logging/ConsoleLogger");
|
|
10
|
+
const IUserInteractionEvent_1 = require("./IUserInteractionEvent");
|
|
11
|
+
const ConfigurationHandler_1 = require("../../../lib/core/configuration/ConfigurationHandler");
|
|
12
|
+
class TimestampProvider {
|
|
13
|
+
constructor() {
|
|
14
|
+
this.getCurrentTimestamp = () => Date.now();
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
const logger = new ConsoleLogger_1.ConsoleLogger('DyntraceUserInteraction');
|
|
18
|
+
const NodeCtx = (0, react_1.createContext)(null);
|
|
19
|
+
const LogCtx = (0, react_1.createContext)(null);
|
|
20
|
+
exports.CfgCtx = (0, react_1.createContext)({});
|
|
21
|
+
const TouchCtx = (0, react_1.createContext)(null);
|
|
22
|
+
let LAST_EMIT_KEY = null;
|
|
23
|
+
let LAST_EMIT_TS = 0;
|
|
24
|
+
let LAST_PRESS_ID = null;
|
|
25
|
+
let LAST_PRESS_TS = 0;
|
|
26
|
+
const RE_FORWARD_REF = Symbol.for('react.forward_ref');
|
|
27
|
+
const RE_MEMO = Symbol.for('react.memo');
|
|
28
|
+
const RE_FRAGMENT = Symbol.for('react.fragment');
|
|
29
|
+
const HANDLE_REG = new Map();
|
|
30
|
+
exports.FORCED_TOUCHABLES = new Set([
|
|
31
|
+
'TouchableOpacity',
|
|
32
|
+
'TouchableHighlight',
|
|
33
|
+
'TouchableWithoutFeedback',
|
|
34
|
+
'TouchableNativeFeedback',
|
|
35
|
+
'Pressable',
|
|
36
|
+
'TouchableOpacity_GH',
|
|
37
|
+
'TouchableHighlight_GH',
|
|
38
|
+
'TouchableWithoutFeedback_GH',
|
|
39
|
+
'RectButton',
|
|
40
|
+
'BorderlessButton',
|
|
41
|
+
'HeaderBackButton',
|
|
42
|
+
'HeaderTitle',
|
|
43
|
+
'DrawerItem',
|
|
44
|
+
'DrawerToggleButton',
|
|
45
|
+
'TabBarItem',
|
|
46
|
+
]);
|
|
47
|
+
const PRESS_KEYS = new Set([
|
|
48
|
+
'onPress',
|
|
49
|
+
'onLongPress',
|
|
50
|
+
'onTap',
|
|
51
|
+
'onClick',
|
|
52
|
+
'onTouchStart',
|
|
53
|
+
]);
|
|
54
|
+
const TEXTINPUT_KEYS = new Set([
|
|
55
|
+
'onFocus',
|
|
56
|
+
'onBlur',
|
|
57
|
+
'onSubmitEditing',
|
|
58
|
+
'onEndEditing',
|
|
59
|
+
'onChangeText',
|
|
60
|
+
]);
|
|
61
|
+
const DEFAULT_ROLE_HEURISTICS = {
|
|
62
|
+
nav: [/nav/i, /stack/i, /tab/i, /drawer/i, /navigator/i, /screen$/i],
|
|
63
|
+
theme: [/theme/i],
|
|
64
|
+
provider: [/provider/i, /context/i],
|
|
65
|
+
list: [/list/i, /flatlist/i, /sectionlist/i, /virtualizedlist/i],
|
|
66
|
+
view: [/^view$/i, /^text$/i, /^image$/i, /scrollview/i, /pressable/i],
|
|
67
|
+
};
|
|
68
|
+
const isReactNodeIterable = (node) => typeof node === 'object' && node !== null && Symbol.iterator in node;
|
|
69
|
+
const SiblingCtx = (0, react_1.createContext)(null);
|
|
70
|
+
function getDtLastTouch() {
|
|
71
|
+
const g = globalThis;
|
|
72
|
+
if (!g.__DT_LAST_TOUCH)
|
|
73
|
+
g.__DT_LAST_TOUCH = { ts: 0, x: 0, y: 0 };
|
|
74
|
+
return g.__DT_LAST_TOUCH;
|
|
75
|
+
}
|
|
76
|
+
function isExpoRuntime() {
|
|
77
|
+
const g = globalThis;
|
|
78
|
+
return !!((g === null || g === void 0 ? void 0 : g.expo) || (g === null || g === void 0 ? void 0 : g.__expo) || (g === null || g === void 0 ? void 0 : g.Expo));
|
|
79
|
+
}
|
|
80
|
+
function isNativeTextInputViewTarget(t) {
|
|
81
|
+
var _a;
|
|
82
|
+
const cls = (_a = t === null || t === void 0 ? void 0 : t._viewConfig) === null || _a === void 0 ? void 0 : _a.uiViewClassName;
|
|
83
|
+
if (typeof cls !== 'string')
|
|
84
|
+
return false;
|
|
85
|
+
return (cls === 'RCTSinglelineTextInputView' ||
|
|
86
|
+
cls === 'RCTMultilineTextInputView' ||
|
|
87
|
+
cls === 'AndroidTextInput' ||
|
|
88
|
+
cls.toLowerCase().includes('textinput'));
|
|
89
|
+
}
|
|
90
|
+
function makePreIndexedRegistry(children) {
|
|
91
|
+
var _a, _b;
|
|
92
|
+
const table = new Map();
|
|
93
|
+
const counts = new Map();
|
|
94
|
+
const arr = react_1.Children.toArray(children);
|
|
95
|
+
for (let i = 0; i < arr.length; i++) {
|
|
96
|
+
const el = arr[i];
|
|
97
|
+
if (!(0, react_1.isValidElement)(el))
|
|
98
|
+
continue;
|
|
99
|
+
const name = getElTypeName(el);
|
|
100
|
+
const key = String((_a = el.key) !== null && _a !== void 0 ? _a : `__pos:${i}`);
|
|
101
|
+
const cur = ((_b = counts.get(name)) !== null && _b !== void 0 ? _b : 0) + 1;
|
|
102
|
+
counts.set(name, cur);
|
|
103
|
+
let bucket = table.get(name);
|
|
104
|
+
if (!bucket) {
|
|
105
|
+
bucket = new Map();
|
|
106
|
+
table.set(name, bucket);
|
|
107
|
+
}
|
|
108
|
+
bucket.set(key, cur);
|
|
109
|
+
}
|
|
110
|
+
return {
|
|
111
|
+
getIndex(name, key) {
|
|
112
|
+
var _a;
|
|
113
|
+
const bucket = table.get(name);
|
|
114
|
+
if (!bucket)
|
|
115
|
+
return 1;
|
|
116
|
+
return (_a = bucket.get(key)) !== null && _a !== void 0 ? _a : 1;
|
|
117
|
+
},
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
function shortSid(s) {
|
|
121
|
+
if (!s)
|
|
122
|
+
return '';
|
|
123
|
+
const str = String(s);
|
|
124
|
+
let h = 5381;
|
|
125
|
+
for (let i = 0; i < str.length; i++) {
|
|
126
|
+
h = ((h << 5) + h) ^ str.codePointAt(i);
|
|
127
|
+
}
|
|
128
|
+
const base = Math.abs(h >>> 0).toString(36);
|
|
129
|
+
return base.slice(-6);
|
|
130
|
+
}
|
|
131
|
+
function toPathString(n, cfg) {
|
|
132
|
+
var _a, _b, _c, _d, _e;
|
|
133
|
+
const parts = [];
|
|
134
|
+
const exNames = new Set((_a = cfg === null || cfg === void 0 ? void 0 : cfg.excludeNames) !== null && _a !== void 0 ? _a : []);
|
|
135
|
+
const exRoles = new Set((_b = cfg === null || cfg === void 0 ? void 0 : cfg.excludeRoles) !== null && _b !== void 0 ? _b : []);
|
|
136
|
+
const segs = [];
|
|
137
|
+
let cur = n;
|
|
138
|
+
while (cur) {
|
|
139
|
+
segs.push(cur);
|
|
140
|
+
cur = cur.parent;
|
|
141
|
+
}
|
|
142
|
+
segs.reverse();
|
|
143
|
+
const needGlobal = ((_c = cfg === null || cfg === void 0 ? void 0 : cfg.indexMode) !== null && _c !== void 0 ? _c : 'sibling') !== 'sibling';
|
|
144
|
+
const gCounts = new Map();
|
|
145
|
+
for (const seg of segs) {
|
|
146
|
+
if (exNames.has(seg.name) || (seg.role && exRoles.has(seg.role)))
|
|
147
|
+
continue;
|
|
148
|
+
let gIdx;
|
|
149
|
+
if (needGlobal) {
|
|
150
|
+
const c = ((_d = gCounts.get(seg.name)) !== null && _d !== void 0 ? _d : 0) + 1;
|
|
151
|
+
gCounts.set(seg.name, c);
|
|
152
|
+
gIdx = c;
|
|
153
|
+
}
|
|
154
|
+
parts.push(formatSegEx(seg, cfg, gIdx));
|
|
155
|
+
}
|
|
156
|
+
const sep = (_e = cfg === null || cfg === void 0 ? void 0 : cfg.separator) !== null && _e !== void 0 ? _e : '->';
|
|
157
|
+
return parts.join(sep);
|
|
158
|
+
}
|
|
159
|
+
function formatSegIndex(seg, mode, style, gIdx) {
|
|
160
|
+
const siblingIndex = typeof seg.idx === 'number' ? String(seg.idx) : '';
|
|
161
|
+
const globalIndex = typeof gIdx === 'number' ? String(gIdx) : '';
|
|
162
|
+
if (mode === 'sibling') {
|
|
163
|
+
if (!siblingIndex)
|
|
164
|
+
return '';
|
|
165
|
+
return style === 'bracket' ? `[${siblingIndex}]` : `#${siblingIndex}`;
|
|
166
|
+
}
|
|
167
|
+
if (mode === 'global') {
|
|
168
|
+
if (!globalIndex)
|
|
169
|
+
return '';
|
|
170
|
+
return style === 'bracket' ? `[${globalIndex}]` : `^g${globalIndex}`;
|
|
171
|
+
}
|
|
172
|
+
if (style === 'bracket') {
|
|
173
|
+
return `[${siblingIndex}|${globalIndex}]`;
|
|
174
|
+
}
|
|
175
|
+
const siblingPart = siblingIndex ? `#${siblingIndex}` : '';
|
|
176
|
+
const globalPart = globalIndex ? `^g${globalIndex}` : '';
|
|
177
|
+
return `${siblingPart}${globalPart}`;
|
|
178
|
+
}
|
|
179
|
+
function formatSegSid(cfg, sid) {
|
|
180
|
+
if (!(cfg === null || cfg === void 0 ? void 0 : cfg.withSid) || !sid)
|
|
181
|
+
return '';
|
|
182
|
+
const short = shortSid(sid);
|
|
183
|
+
return short ? `~k${short}` : '';
|
|
184
|
+
}
|
|
185
|
+
function formatSegEx(seg, cfg, gIdx) {
|
|
186
|
+
var _a, _b;
|
|
187
|
+
const label = seg.label ? `(${seg.label})` : '';
|
|
188
|
+
const role = (cfg === null || cfg === void 0 ? void 0 : cfg.withRole) && seg.role ? `:${seg.role}` : '';
|
|
189
|
+
const mode = (_a = cfg === null || cfg === void 0 ? void 0 : cfg.indexMode) !== null && _a !== void 0 ? _a : 'sibling';
|
|
190
|
+
const style = (_b = cfg === null || cfg === void 0 ? void 0 : cfg.indexStyle) !== null && _b !== void 0 ? _b : 'classic';
|
|
191
|
+
const idx = (cfg === null || cfg === void 0 ? void 0 : cfg.withIndex) ? formatSegIndex(seg, mode, style, gIdx) : '';
|
|
192
|
+
const sid = formatSegSid(cfg, seg.sid);
|
|
193
|
+
return `${seg.name}${label}${role}${idx}${sid}`;
|
|
194
|
+
}
|
|
195
|
+
function normPhase(k) {
|
|
196
|
+
return k.replace(/^on/, '').replace(/^[A-Z]/, (m) => m.toLowerCase());
|
|
197
|
+
}
|
|
198
|
+
function trimText(x) {
|
|
199
|
+
if (typeof x !== 'string')
|
|
200
|
+
return '';
|
|
201
|
+
const s = x.trim().split(/\s+/).join(' ');
|
|
202
|
+
return s.length > 0 ? s : '';
|
|
203
|
+
}
|
|
204
|
+
function isLabelScope(el) {
|
|
205
|
+
return (!!el &&
|
|
206
|
+
typeof el.type === 'function' &&
|
|
207
|
+
el.type.__AN_LABEL_SCOPE === true);
|
|
208
|
+
}
|
|
209
|
+
function getElTypeName(el) {
|
|
210
|
+
var _a, _b;
|
|
211
|
+
if (!el)
|
|
212
|
+
return 'Anonymous';
|
|
213
|
+
if (typeof el.type === 'string')
|
|
214
|
+
return el.type;
|
|
215
|
+
const raw = ((_a = el.type) === null || _a === void 0 ? void 0 : _a.displayName) || ((_b = el.type) === null || _b === void 0 ? void 0 : _b.name) || 'Anonymous';
|
|
216
|
+
const m = /^ForwardRef\((.+)\)$/.exec(raw) || /^Memo\((.+)\)$/.exec(raw);
|
|
217
|
+
return m ? m[1] : raw;
|
|
218
|
+
}
|
|
219
|
+
function collectLeafInfo(node, depth = 0, maxDepth = 5, maxNodes = 200, lastType) {
|
|
220
|
+
let seen = 0;
|
|
221
|
+
function makeTextLeaf(value, typeHint) {
|
|
222
|
+
const text = trimText(value);
|
|
223
|
+
if (!text)
|
|
224
|
+
return null;
|
|
225
|
+
return {
|
|
226
|
+
label: text,
|
|
227
|
+
type: typeHint || 'Text',
|
|
228
|
+
source: 'text',
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
function getIterableNode(n) {
|
|
232
|
+
if (Array.isArray(n))
|
|
233
|
+
return n;
|
|
234
|
+
if (isReactNodeIterable(n))
|
|
235
|
+
return n;
|
|
236
|
+
return null;
|
|
237
|
+
}
|
|
238
|
+
function walkIterable(iterable, d, lastT) {
|
|
239
|
+
for (const child of iterable) {
|
|
240
|
+
const found = walk(child, d + 1, lastT);
|
|
241
|
+
if (found)
|
|
242
|
+
return found;
|
|
243
|
+
}
|
|
244
|
+
return null;
|
|
245
|
+
}
|
|
246
|
+
function makePropLeaf(props, thisType) {
|
|
247
|
+
if (typeof (props === null || props === void 0 ? void 0 : props.accessibilityLabel) === 'string') {
|
|
248
|
+
return {
|
|
249
|
+
label: props.accessibilityLabel,
|
|
250
|
+
type: thisType,
|
|
251
|
+
source: 'accessibility',
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
if (typeof (props === null || props === void 0 ? void 0 : props.testID) === 'string') {
|
|
255
|
+
return {
|
|
256
|
+
label: props.testID,
|
|
257
|
+
type: thisType,
|
|
258
|
+
source: 'testid',
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
return null;
|
|
262
|
+
}
|
|
263
|
+
function walkElement(el, d, lastT) {
|
|
264
|
+
var _a, _b;
|
|
265
|
+
const rawType = getElTypeName(el);
|
|
266
|
+
const segmentName = (_a = el === null || el === void 0 ? void 0 : el.props) === null || _a === void 0 ? void 0 : _a.name;
|
|
267
|
+
const hasSegmentName = rawType === 'Segment' &&
|
|
268
|
+
typeof segmentName === 'string' &&
|
|
269
|
+
segmentName.length > 0;
|
|
270
|
+
const thisType = hasSegmentName ? segmentName : rawType;
|
|
271
|
+
if (isLabelScope(el)) {
|
|
272
|
+
const inner = walk((_b = el.props) === null || _b === void 0 ? void 0 : _b.children, d + 1, 'LabelClaimScope');
|
|
273
|
+
return inner ? Object.assign(Object.assign({}, inner), { source: 'label-claim' }) : null;
|
|
274
|
+
}
|
|
275
|
+
const props = el === null || el === void 0 ? void 0 : el.props;
|
|
276
|
+
if (!props)
|
|
277
|
+
return null;
|
|
278
|
+
const childLeaf = walk(props.children, d + 1, thisType);
|
|
279
|
+
if (childLeaf)
|
|
280
|
+
return childLeaf;
|
|
281
|
+
return makePropLeaf(props, thisType);
|
|
282
|
+
}
|
|
283
|
+
function walk(n, d, lastT) {
|
|
284
|
+
if (seen++ > maxNodes || d > maxDepth)
|
|
285
|
+
return null;
|
|
286
|
+
if (typeof n === 'string' || typeof n === 'number')
|
|
287
|
+
return makeTextLeaf(String(n), lastT);
|
|
288
|
+
if (!n)
|
|
289
|
+
return null;
|
|
290
|
+
const iterable = getIterableNode(n);
|
|
291
|
+
if (iterable)
|
|
292
|
+
return walkIterable(iterable, d, lastT);
|
|
293
|
+
if (typeof n !== 'object')
|
|
294
|
+
return null;
|
|
295
|
+
return walkElement(n, d, lastT);
|
|
296
|
+
}
|
|
297
|
+
return walk(node, depth, lastType);
|
|
298
|
+
}
|
|
299
|
+
function readGlobalPrefix() {
|
|
300
|
+
const globalRuntime = globalThis;
|
|
301
|
+
const globalPrefix = globalRuntime === null || globalRuntime === void 0 ? void 0 : globalRuntime.__AN_PREFIX;
|
|
302
|
+
if (Array.isArray(globalPrefix))
|
|
303
|
+
return globalPrefix;
|
|
304
|
+
if (typeof globalPrefix === 'function') {
|
|
305
|
+
try {
|
|
306
|
+
const resolvedPrefix = globalPrefix();
|
|
307
|
+
if (Array.isArray(resolvedPrefix))
|
|
308
|
+
return resolvedPrefix;
|
|
309
|
+
}
|
|
310
|
+
catch (e) {
|
|
311
|
+
const errorMsg = e instanceof Error ? e.stack || e.message : String(e);
|
|
312
|
+
logger.debug(`Failed to resolve global prefix: ${errorMsg}`);
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
return [];
|
|
316
|
+
}
|
|
317
|
+
function classifyByHeuristics(name, h) {
|
|
318
|
+
const rules = h
|
|
319
|
+
? Object.assign(Object.assign({}, DEFAULT_ROLE_HEURISTICS), h) : DEFAULT_ROLE_HEURISTICS;
|
|
320
|
+
const hit = (arr) => arr.some((rx) => rx.test(name));
|
|
321
|
+
if (hit(rules.nav))
|
|
322
|
+
return 'nav';
|
|
323
|
+
if (hit(rules.theme))
|
|
324
|
+
return 'theme';
|
|
325
|
+
if (hit(rules.provider))
|
|
326
|
+
return 'provider';
|
|
327
|
+
if (hit(rules.list))
|
|
328
|
+
return 'list';
|
|
329
|
+
if (hit(rules.view))
|
|
330
|
+
return 'view';
|
|
331
|
+
return null;
|
|
332
|
+
}
|
|
333
|
+
function classifyRole(name, map, heur) {
|
|
334
|
+
var _a;
|
|
335
|
+
if (map && map[name])
|
|
336
|
+
return map[name];
|
|
337
|
+
if (heur === false) {
|
|
338
|
+
if (name === 'ThemeProvider')
|
|
339
|
+
return 'theme';
|
|
340
|
+
if (name === 'FlatList' ||
|
|
341
|
+
name === 'SectionList' ||
|
|
342
|
+
name === 'VirtualizedList')
|
|
343
|
+
return 'list';
|
|
344
|
+
if (name === 'View' ||
|
|
345
|
+
name === 'Text' ||
|
|
346
|
+
name === 'Pressable' ||
|
|
347
|
+
name === 'Image' ||
|
|
348
|
+
name === 'ScrollView')
|
|
349
|
+
return 'view';
|
|
350
|
+
const low = name.toLowerCase();
|
|
351
|
+
if (/provider|context/.test(low))
|
|
352
|
+
return 'provider';
|
|
353
|
+
if (/(stack|tabs|tab|drawer|navigator|screen$)/i.test(low))
|
|
354
|
+
return 'nav';
|
|
355
|
+
return 'comp';
|
|
356
|
+
}
|
|
357
|
+
return ((_a = classifyByHeuristics(name, heur || DEFAULT_ROLE_HEURISTICS)) !== null && _a !== void 0 ? _a : 'comp');
|
|
358
|
+
}
|
|
359
|
+
function hasArrayValue(arr, value) {
|
|
360
|
+
return Array.isArray(arr) && Array.prototype.indexOf.call(arr, value) >= 0;
|
|
361
|
+
}
|
|
362
|
+
function shouldMaskLeaf(leaf, only, segRole, cfg) {
|
|
363
|
+
var _a, _b, _c, _d, _e;
|
|
364
|
+
if (((_a = only === null || only === void 0 ? void 0 : only.props) === null || _a === void 0 ? void 0 : _a.dtMask) === true)
|
|
365
|
+
return true;
|
|
366
|
+
if (isLabelScope(only) && ((_b = only === null || only === void 0 ? void 0 : only.props) === null || _b === void 0 ? void 0 : _b.mask))
|
|
367
|
+
return true;
|
|
368
|
+
const rules = cfg === null || cfg === void 0 ? void 0 : cfg.mask;
|
|
369
|
+
if (!rules)
|
|
370
|
+
return false;
|
|
371
|
+
const name = getElTypeName(only);
|
|
372
|
+
if (hasArrayValue(rules.names, name))
|
|
373
|
+
return true;
|
|
374
|
+
if (segRole && hasArrayValue(rules.roles, segRole))
|
|
375
|
+
return true;
|
|
376
|
+
if (typeof ((_c = only === null || only === void 0 ? void 0 : only.props) === null || _c === void 0 ? void 0 : _c.testID) === 'string' &&
|
|
377
|
+
((_d = rules.testID) === null || _d === void 0 ? void 0 : _d.call(rules, only.props.testID)))
|
|
378
|
+
return true;
|
|
379
|
+
if ((leaf === null || leaf === void 0 ? void 0 : leaf.source) === 'text' &&
|
|
380
|
+
typeof leaf.label === 'string' &&
|
|
381
|
+
((_e = rules.text) === null || _e === void 0 ? void 0 : _e.call(rules, leaf.label)))
|
|
382
|
+
return true;
|
|
383
|
+
return false;
|
|
384
|
+
}
|
|
385
|
+
function maskLabel(_s, cfg) {
|
|
386
|
+
var _a, _b;
|
|
387
|
+
return (_b = (_a = cfg === null || cfg === void 0 ? void 0 : cfg.mask) === null || _a === void 0 ? void 0 : _a.replaceWith) !== null && _b !== void 0 ? _b : '***';
|
|
388
|
+
}
|
|
389
|
+
function extractPosition(args, cap) {
|
|
390
|
+
if (cap === 'none')
|
|
391
|
+
return undefined;
|
|
392
|
+
const e = args[0];
|
|
393
|
+
const ne = e === null || e === void 0 ? void 0 : e.nativeEvent;
|
|
394
|
+
if (!ne)
|
|
395
|
+
return undefined;
|
|
396
|
+
if (cap === 'page')
|
|
397
|
+
return {
|
|
398
|
+
x: Number(ne.pageX),
|
|
399
|
+
y: Number(ne.pageY),
|
|
400
|
+
type: 'page',
|
|
401
|
+
};
|
|
402
|
+
if (cap === 'local')
|
|
403
|
+
return {
|
|
404
|
+
x: Number(ne.locationX),
|
|
405
|
+
y: Number(ne.locationY),
|
|
406
|
+
type: 'local',
|
|
407
|
+
};
|
|
408
|
+
return { x: Number(ne.pageX), y: Number(ne.pageY), type: 'both' };
|
|
409
|
+
}
|
|
410
|
+
function compactify(cfg, obj) {
|
|
411
|
+
var _a;
|
|
412
|
+
if (!((_a = cfg === null || cfg === void 0 ? void 0 : cfg.touch) === null || _a === void 0 ? void 0 : _a.compact))
|
|
413
|
+
return obj;
|
|
414
|
+
const mapKey = (k) => {
|
|
415
|
+
var _a;
|
|
416
|
+
const keyMap = {
|
|
417
|
+
path: 'p',
|
|
418
|
+
element: 'el',
|
|
419
|
+
isMasked: 'msk',
|
|
420
|
+
position: 'pos',
|
|
421
|
+
meta: 'm',
|
|
422
|
+
sessionId: 'sid',
|
|
423
|
+
touch: 't',
|
|
424
|
+
reason: 'r',
|
|
425
|
+
};
|
|
426
|
+
return (_a = keyMap[k]) !== null && _a !== void 0 ? _a : k;
|
|
427
|
+
};
|
|
428
|
+
const normalizeCompactObject = (compactObject) => {
|
|
429
|
+
if (compactObject.pos && compactObject.pos.type) {
|
|
430
|
+
compactObject.pos = {
|
|
431
|
+
x: compactObject.pos.x,
|
|
432
|
+
y: compactObject.pos.y,
|
|
433
|
+
t: compactObject.pos.type,
|
|
434
|
+
};
|
|
435
|
+
}
|
|
436
|
+
if (compactObject.m && compactObject.m.phase) {
|
|
437
|
+
compactObject.ph = compactObject.m.phase;
|
|
438
|
+
compactObject.ts = compactObject.m.ts;
|
|
439
|
+
delete compactObject.m;
|
|
440
|
+
}
|
|
441
|
+
if (compactObject.t) {
|
|
442
|
+
if (compactObject.t.path !== undefined) {
|
|
443
|
+
compactObject.tp = compactObject.t.path;
|
|
444
|
+
}
|
|
445
|
+
if (compactObject.t.delayMs !== undefined) {
|
|
446
|
+
compactObject.td = compactObject.t.delayMs;
|
|
447
|
+
}
|
|
448
|
+
delete compactObject.t;
|
|
449
|
+
}
|
|
450
|
+
return compactObject;
|
|
451
|
+
};
|
|
452
|
+
const walk = (value) => {
|
|
453
|
+
if (Array.isArray(value))
|
|
454
|
+
return value.map(walk);
|
|
455
|
+
if (!value || typeof value !== 'object')
|
|
456
|
+
return value;
|
|
457
|
+
const compactObject = {};
|
|
458
|
+
for (const key of Object.keys(value)) {
|
|
459
|
+
compactObject[mapKey(key)] = walk(value[key]);
|
|
460
|
+
}
|
|
461
|
+
return normalizeCompactObject(compactObject);
|
|
462
|
+
};
|
|
463
|
+
return walk(obj);
|
|
464
|
+
}
|
|
465
|
+
exports.compactify = compactify;
|
|
466
|
+
function registerHandle(handle, info) {
|
|
467
|
+
if (!handle)
|
|
468
|
+
return;
|
|
469
|
+
if (info) {
|
|
470
|
+
HANDLE_REG.set(handle, info);
|
|
471
|
+
}
|
|
472
|
+
else {
|
|
473
|
+
HANDLE_REG.delete(handle);
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
function findHitInfo(nativeTarget) {
|
|
477
|
+
const h = Number(nativeTarget || 0);
|
|
478
|
+
if (!h)
|
|
479
|
+
return null;
|
|
480
|
+
const exact = HANDLE_REG.get(h) || null;
|
|
481
|
+
if (exact)
|
|
482
|
+
return Object.assign(Object.assign({}, exact), { __dtMatch: 'exact' });
|
|
483
|
+
return null;
|
|
484
|
+
}
|
|
485
|
+
function resolveScrollableContextHit() {
|
|
486
|
+
for (const v of HANDLE_REG.values()) {
|
|
487
|
+
const p = v === null || v === void 0 ? void 0 : v.path;
|
|
488
|
+
if (typeof p === 'string' && p.includes('FlatList')) {
|
|
489
|
+
return Object.assign(Object.assign({}, v), { __dtMatch: 'override' });
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
return null;
|
|
493
|
+
}
|
|
494
|
+
function normalizeFuzzyHit(hit) {
|
|
495
|
+
if (!hit)
|
|
496
|
+
return hit;
|
|
497
|
+
if (hit.__dtMatch !== 'fuzzy')
|
|
498
|
+
return hit;
|
|
499
|
+
if (hit.element !== '<')
|
|
500
|
+
return hit;
|
|
501
|
+
const fl = resolveScrollableContextHit();
|
|
502
|
+
return fl || hit;
|
|
503
|
+
}
|
|
504
|
+
function makeSid() {
|
|
505
|
+
const t = Date.now().toString(36);
|
|
506
|
+
const r = Math.random().toString(36).slice(2, 6);
|
|
507
|
+
return `tch_${t}_${r}`;
|
|
508
|
+
}
|
|
509
|
+
function makePos(ne, cap) {
|
|
510
|
+
if (!ne)
|
|
511
|
+
return undefined;
|
|
512
|
+
if (cap === 'page')
|
|
513
|
+
return {
|
|
514
|
+
x: Number(ne.pageX),
|
|
515
|
+
y: Number(ne.pageY),
|
|
516
|
+
type: 'page',
|
|
517
|
+
};
|
|
518
|
+
if (cap === 'local')
|
|
519
|
+
return {
|
|
520
|
+
x: Number(ne.locationX),
|
|
521
|
+
y: Number(ne.locationY),
|
|
522
|
+
type: 'local',
|
|
523
|
+
};
|
|
524
|
+
if (cap === 'both')
|
|
525
|
+
return {
|
|
526
|
+
x: Number(ne.pageX),
|
|
527
|
+
y: Number(ne.pageY),
|
|
528
|
+
type: 'both',
|
|
529
|
+
};
|
|
530
|
+
return undefined;
|
|
531
|
+
}
|
|
532
|
+
function supportsRefType(type) {
|
|
533
|
+
if (!type)
|
|
534
|
+
return false;
|
|
535
|
+
if (typeof type === 'string')
|
|
536
|
+
return true;
|
|
537
|
+
const typeLike = type;
|
|
538
|
+
const $$ = typeLike.$$typeof;
|
|
539
|
+
if ($$ === RE_FORWARD_REF)
|
|
540
|
+
return true;
|
|
541
|
+
if ($$ === RE_MEMO) {
|
|
542
|
+
const inner = typeLike.type;
|
|
543
|
+
const innerSig = inner && typeof inner === 'object' ? inner.$$typeof : undefined;
|
|
544
|
+
return innerSig === RE_FORWARD_REF || typeof inner === 'string';
|
|
545
|
+
}
|
|
546
|
+
if ($$ === RE_FRAGMENT)
|
|
547
|
+
return false;
|
|
548
|
+
return !!(typeLike &&
|
|
549
|
+
typeLike.prototype &&
|
|
550
|
+
typeof typeLike.prototype.render === 'function');
|
|
551
|
+
}
|
|
552
|
+
function lastSegment(path) {
|
|
553
|
+
if (!path)
|
|
554
|
+
return '';
|
|
555
|
+
const arrow = path.lastIndexOf('->');
|
|
556
|
+
const slash = path.lastIndexOf('/');
|
|
557
|
+
const i = Math.max(arrow, slash);
|
|
558
|
+
if (i < 0)
|
|
559
|
+
return path;
|
|
560
|
+
const step = i === arrow ? 2 : 1;
|
|
561
|
+
return path.slice(i + step);
|
|
562
|
+
}
|
|
563
|
+
function parseComponent(seg) {
|
|
564
|
+
if (!seg)
|
|
565
|
+
return 'Anonymous';
|
|
566
|
+
const base = seg.split(':', 1)[0];
|
|
567
|
+
const m = /^([^(]+)(?:\(.*\))?$/.exec(base);
|
|
568
|
+
return (m ? m[1] : base) || 'Anonymous';
|
|
569
|
+
}
|
|
570
|
+
function __dt_set_scope_path(path) {
|
|
571
|
+
const g = globalThis;
|
|
572
|
+
g.__DT_UII_SCOPE_PATH = path;
|
|
573
|
+
}
|
|
574
|
+
function __dt_get_scope_path() {
|
|
575
|
+
const g = globalThis;
|
|
576
|
+
const p = g.__DT_UII_SCOPE_PATH;
|
|
577
|
+
return typeof p === 'string' && p.length > 0 ? p : 'App';
|
|
578
|
+
}
|
|
579
|
+
function liftStaticTextHitPath(path) {
|
|
580
|
+
if (!path)
|
|
581
|
+
return path;
|
|
582
|
+
const rx = /\/Text:[^/]+\/Text\([^)]*\)$/;
|
|
583
|
+
if (!rx.test(path))
|
|
584
|
+
return path;
|
|
585
|
+
return path.replace(rx, '');
|
|
586
|
+
}
|
|
587
|
+
function buildUiEventShape(input) {
|
|
588
|
+
var _a;
|
|
589
|
+
const id = input.pressPath || input.touchPath || '';
|
|
590
|
+
const seg = lastSegment(id);
|
|
591
|
+
const comp = parseComponent(seg);
|
|
592
|
+
const detected_name = input.pressElementName || input.touchElementName || comp;
|
|
593
|
+
const base = {
|
|
594
|
+
ui_element: {
|
|
595
|
+
detected_name,
|
|
596
|
+
components: [comp],
|
|
597
|
+
id,
|
|
598
|
+
masked: !!input.touchMasked,
|
|
599
|
+
reason: (_a = input.reason) !== null && _a !== void 0 ? _a : null,
|
|
600
|
+
meta: input.meta,
|
|
601
|
+
name_origin: input.name_origin ||
|
|
602
|
+
(input.touchMasked ? 'masked' : 'component'),
|
|
603
|
+
},
|
|
604
|
+
positions: input.pos ? [{ x: input.pos.x, y: input.pos.y }] : [],
|
|
605
|
+
sessionId: input.sessionId,
|
|
606
|
+
};
|
|
607
|
+
if (input.pressPath) {
|
|
608
|
+
const pressSeg = lastSegment(input.pressPath);
|
|
609
|
+
const pressComp = parseComponent(pressSeg);
|
|
610
|
+
const pressName = input.pressElementName || pressComp;
|
|
611
|
+
base.ui_element.responder = {
|
|
612
|
+
detected_name: pressName,
|
|
613
|
+
components: [pressComp],
|
|
614
|
+
id: input.pressPath,
|
|
615
|
+
name_origin: 'component',
|
|
616
|
+
};
|
|
617
|
+
}
|
|
618
|
+
return base;
|
|
619
|
+
}
|
|
620
|
+
exports.buildUiEventShape = buildUiEventShape;
|
|
621
|
+
function _an_interaction_type(e) {
|
|
622
|
+
var _a, _b;
|
|
623
|
+
const p = (_b = (_a = e === null || e === void 0 ? void 0 : e.ui_element) === null || _a === void 0 ? void 0 : _a.meta) === null || _b === void 0 ? void 0 : _b.phase;
|
|
624
|
+
if (!p)
|
|
625
|
+
return null;
|
|
626
|
+
return 'touch';
|
|
627
|
+
}
|
|
628
|
+
function _an_flat(e) {
|
|
629
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r;
|
|
630
|
+
const uiComponents = (_a = e === null || e === void 0 ? void 0 : e.ui_element) === null || _a === void 0 ? void 0 : _a.components;
|
|
631
|
+
let normalizedUiComponents = [];
|
|
632
|
+
if (Array.isArray(uiComponents)) {
|
|
633
|
+
normalizedUiComponents = uiComponents.filter((x) => typeof x === 'string' && x.length > 0);
|
|
634
|
+
}
|
|
635
|
+
else if (uiComponents) {
|
|
636
|
+
normalizedUiComponents =
|
|
637
|
+
typeof uiComponents === 'string' ? [uiComponents] : [];
|
|
638
|
+
}
|
|
639
|
+
const out = {
|
|
640
|
+
[IUserInteractionEvent_1.UserInteractionEventKey.EventHasUserInteraction]: true,
|
|
641
|
+
[IUserInteractionEvent_1.UserInteractionEventKey.UiElementDetectedName]: (_c = (_b = e === null || e === void 0 ? void 0 : e.ui_element) === null || _b === void 0 ? void 0 : _b.detected_name) !== null && _c !== void 0 ? _c : null,
|
|
642
|
+
[IUserInteractionEvent_1.UserInteractionEventKey.UiElementComponents]: normalizedUiComponents,
|
|
643
|
+
[IUserInteractionEvent_1.UserInteractionEventKey.UiElementId]: (_e = (_d = e === null || e === void 0 ? void 0 : e.ui_element) === null || _d === void 0 ? void 0 : _d.id) !== null && _e !== void 0 ? _e : null,
|
|
644
|
+
[IUserInteractionEvent_1.UserInteractionEventKey.InteractionType]: _an_interaction_type(e),
|
|
645
|
+
positions: Array.isArray(e === null || e === void 0 ? void 0 : e.positions)
|
|
646
|
+
? e.positions.map((pos) => ({
|
|
647
|
+
x: Math.trunc(pos.x),
|
|
648
|
+
y: Math.trunc(pos.y),
|
|
649
|
+
}))
|
|
650
|
+
: [],
|
|
651
|
+
};
|
|
652
|
+
const uiComponent = (_f = e === null || e === void 0 ? void 0 : e.ui_element) === null || _f === void 0 ? void 0 : _f.component;
|
|
653
|
+
const uiComponentList = uiComponent === null || uiComponent === undefined
|
|
654
|
+
? null
|
|
655
|
+
: [uiComponent];
|
|
656
|
+
const compsRaw = (_h = (_g = e === null || e === void 0 ? void 0 : e.ui_element) === null || _g === void 0 ? void 0 : _g.components) !== null && _h !== void 0 ? _h : uiComponentList;
|
|
657
|
+
out[IUserInteractionEvent_1.UserInteractionEventKey.UiElementComponents] = Array.isArray(compsRaw)
|
|
658
|
+
? compsRaw.filter((x) => typeof x === 'string' && x.length > 0)
|
|
659
|
+
: [];
|
|
660
|
+
out[IUserInteractionEvent_1.UserInteractionEventKey.UiElementNameOrigin] =
|
|
661
|
+
(_k = (_j = e === null || e === void 0 ? void 0 : e.ui_element) === null || _j === void 0 ? void 0 : _j.name_origin) !== null && _k !== void 0 ? _k : null;
|
|
662
|
+
const responder = (_m = (_l = e === null || e === void 0 ? void 0 : e.ui_element) === null || _l === void 0 ? void 0 : _l.responder) !== null && _m !== void 0 ? _m : null;
|
|
663
|
+
if (responder) {
|
|
664
|
+
out[IUserInteractionEvent_1.UserInteractionEventKey.UiElementResponderDetectedName] =
|
|
665
|
+
(_o = responder.detected_name) !== null && _o !== void 0 ? _o : null;
|
|
666
|
+
const responderComponent = responder.component;
|
|
667
|
+
const responderComponentList = responderComponent === null || responderComponent === undefined
|
|
668
|
+
? null
|
|
669
|
+
: [responderComponent];
|
|
670
|
+
const rCompsRaw = (_p = responder.components) !== null && _p !== void 0 ? _p : responderComponentList;
|
|
671
|
+
out[IUserInteractionEvent_1.UserInteractionEventKey.UiElementResponderComponents] =
|
|
672
|
+
Array.isArray(rCompsRaw)
|
|
673
|
+
? rCompsRaw.filter((x) => typeof x === 'string' && x.length > 0)
|
|
674
|
+
: [];
|
|
675
|
+
out[IUserInteractionEvent_1.UserInteractionEventKey.UiElementResponderId] =
|
|
676
|
+
(_q = responder.id) !== null && _q !== void 0 ? _q : null;
|
|
677
|
+
out[IUserInteractionEvent_1.UserInteractionEventKey.UiElementResponderOriginName] =
|
|
678
|
+
(_r = responder.name_origin) !== null && _r !== void 0 ? _r : null;
|
|
679
|
+
}
|
|
680
|
+
return out;
|
|
681
|
+
}
|
|
682
|
+
exports._an_flat = _an_flat;
|
|
683
|
+
function useTouchManager(cfg, log) {
|
|
684
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
|
|
685
|
+
const mode = (_b = (_a = cfg.touch) === null || _a === void 0 ? void 0 : _a.mode) !== null && _b !== void 0 ? _b : 'grouped';
|
|
686
|
+
const sidRef = React.useRef(null);
|
|
687
|
+
const startXRef = React.useRef(null);
|
|
688
|
+
const startYRef = React.useRef(null);
|
|
689
|
+
const movedRef = React.useRef(false);
|
|
690
|
+
const startTsRef = React.useRef(null);
|
|
691
|
+
const startPathRef = React.useRef(null);
|
|
692
|
+
const threshold = Math.max(1, (_e = (_d = (_c = cfg.touch) === null || _c === void 0 ? void 0 : _c.scroll) === null || _d === void 0 ? void 0 : _d.moveThresholdPx) !== null && _e !== void 0 ? _e : 12);
|
|
693
|
+
const touchRef = React.useRef(null);
|
|
694
|
+
const pressRef = React.useRef(null);
|
|
695
|
+
const timerRef = React.useRef(null);
|
|
696
|
+
const flushedRef = React.useRef(false);
|
|
697
|
+
const clearAll = () => {
|
|
698
|
+
if (timerRef.current) {
|
|
699
|
+
clearTimeout(timerRef.current);
|
|
700
|
+
timerRef.current = null;
|
|
701
|
+
}
|
|
702
|
+
touchRef.current = null;
|
|
703
|
+
pressRef.current = null;
|
|
704
|
+
sidRef.current = null;
|
|
705
|
+
startXRef.current = null;
|
|
706
|
+
startYRef.current = null;
|
|
707
|
+
startTsRef.current = null;
|
|
708
|
+
movedRef.current = false;
|
|
709
|
+
startPathRef.current = null;
|
|
710
|
+
flushedRef.current = false;
|
|
711
|
+
};
|
|
712
|
+
const doFlush = () => {
|
|
713
|
+
if (flushedRef.current) {
|
|
714
|
+
clearAll();
|
|
715
|
+
return;
|
|
716
|
+
}
|
|
717
|
+
const t = touchRef.current;
|
|
718
|
+
const p = pressRef.current;
|
|
719
|
+
let out = null;
|
|
720
|
+
if (t && p) {
|
|
721
|
+
const pos = p.pos || t.pos;
|
|
722
|
+
out = buildUiEventShape({
|
|
723
|
+
touchPath: t.path,
|
|
724
|
+
touchElementName: t.elementName || undefined,
|
|
725
|
+
touchMasked: t.masked,
|
|
726
|
+
pressPath: p.path,
|
|
727
|
+
pressElementName: p.elementName,
|
|
728
|
+
meta: { phase: 'press', ts: Date.now() },
|
|
729
|
+
pos: pos ? { x: pos.x, y: pos.y } : undefined,
|
|
730
|
+
reason: t.reason,
|
|
731
|
+
sessionId: sidRef.current || undefined,
|
|
732
|
+
name_origin: t.name_origin,
|
|
733
|
+
});
|
|
734
|
+
}
|
|
735
|
+
else if (p) {
|
|
736
|
+
out = buildUiEventShape({
|
|
737
|
+
pressPath: p.path,
|
|
738
|
+
pressElementName: p.elementName,
|
|
739
|
+
meta: { phase: 'press', ts: Date.now() },
|
|
740
|
+
pos: p.pos ? { x: p.pos.x, y: p.pos.y } : undefined,
|
|
741
|
+
sessionId: sidRef.current || undefined,
|
|
742
|
+
});
|
|
743
|
+
}
|
|
744
|
+
else if (t) {
|
|
745
|
+
out = buildUiEventShape({
|
|
746
|
+
touchPath: t.path,
|
|
747
|
+
touchElementName: t.elementName || undefined,
|
|
748
|
+
touchMasked: t.masked,
|
|
749
|
+
meta: { phase: 'touch', ts: Date.now() },
|
|
750
|
+
pos: t.pos ? { x: t.pos.x, y: t.pos.y } : undefined,
|
|
751
|
+
reason: t.reason,
|
|
752
|
+
sessionId: sidRef.current || undefined,
|
|
753
|
+
name_origin: t.name_origin,
|
|
754
|
+
});
|
|
755
|
+
}
|
|
756
|
+
if (out)
|
|
757
|
+
log(compactify(cfg, out));
|
|
758
|
+
flushedRef.current = true;
|
|
759
|
+
clearAll();
|
|
760
|
+
};
|
|
761
|
+
const scheduleFlush = (delay) => {
|
|
762
|
+
if (timerRef.current) {
|
|
763
|
+
clearTimeout(timerRef.current);
|
|
764
|
+
timerRef.current = null;
|
|
765
|
+
}
|
|
766
|
+
timerRef.current = setTimeout(() => doFlush(), delay);
|
|
767
|
+
};
|
|
768
|
+
const resolveTouchHit = (nativeTarget) => normalizeFuzzyHit(findHitInfo(nativeTarget)) ||
|
|
769
|
+
resolveScrollableContextHit();
|
|
770
|
+
const maybeLiftTouchHit = (hit) => {
|
|
771
|
+
var _a;
|
|
772
|
+
if (!hit || hit.__dtMatch === 'exact') {
|
|
773
|
+
return {
|
|
774
|
+
usePath: (_a = hit === null || hit === void 0 ? void 0 : hit.path) !== null && _a !== void 0 ? _a : null,
|
|
775
|
+
useElement: hit === null || hit === void 0 ? void 0 : hit.element,
|
|
776
|
+
nameOrigin: hit === null || hit === void 0 ? void 0 : hit.name_origin,
|
|
777
|
+
};
|
|
778
|
+
}
|
|
779
|
+
const lifted = liftStaticTextHitPath(hit.path);
|
|
780
|
+
if (lifted && lifted !== hit.path) {
|
|
781
|
+
return {
|
|
782
|
+
usePath: lifted,
|
|
783
|
+
useElement: undefined,
|
|
784
|
+
nameOrigin: 'component',
|
|
785
|
+
};
|
|
786
|
+
}
|
|
787
|
+
return {
|
|
788
|
+
usePath: hit.path,
|
|
789
|
+
useElement: hit.element,
|
|
790
|
+
nameOrigin: hit.name_origin,
|
|
791
|
+
};
|
|
792
|
+
};
|
|
793
|
+
const phaseReason = (phase) => phase === 'cancel' && movedRef.current ? 'moved' : undefined;
|
|
794
|
+
const flushOrSchedule = () => {
|
|
795
|
+
var _a, _b;
|
|
796
|
+
if (pressRef.current)
|
|
797
|
+
doFlush();
|
|
798
|
+
else
|
|
799
|
+
scheduleFlush((_b = (_a = cfg.touch) === null || _a === void 0 ? void 0 : _a.linkWindowMs) !== null && _b !== void 0 ? _b : 250);
|
|
800
|
+
};
|
|
801
|
+
const handleStreamEnd = (ne, phase) => {
|
|
802
|
+
var _a, _b;
|
|
803
|
+
const hit = resolveTouchHit(ne === null || ne === void 0 ? void 0 : ne.target);
|
|
804
|
+
if (!hit || !hit.path)
|
|
805
|
+
return;
|
|
806
|
+
const lifted = maybeLiftTouchHit(hit);
|
|
807
|
+
const pos = makePos(ne, (_b = (_a = cfg.click) === null || _a === void 0 ? void 0 : _a.capturePosition) !== null && _b !== void 0 ? _b : 'none');
|
|
808
|
+
const out = buildUiEventShape({
|
|
809
|
+
touchPath: lifted.usePath || hit.path,
|
|
810
|
+
touchElementName: lifted.useElement,
|
|
811
|
+
touchMasked: !!hit.isMasked,
|
|
812
|
+
meta: {
|
|
813
|
+
phase: phase === 'cancel' ? 'touch-cancel' : 'touch',
|
|
814
|
+
ts: Date.now(),
|
|
815
|
+
},
|
|
816
|
+
pos: pos ? { x: pos.x, y: pos.y } : undefined,
|
|
817
|
+
reason: phaseReason(phase),
|
|
818
|
+
sessionId: sidRef.current || undefined,
|
|
819
|
+
name_origin: lifted.nameOrigin,
|
|
820
|
+
});
|
|
821
|
+
log(compactify(cfg, out));
|
|
822
|
+
clearAll();
|
|
823
|
+
};
|
|
824
|
+
const onStart = React.useCallback((e) => {
|
|
825
|
+
var _a, _b, _c, _d, _e;
|
|
826
|
+
if (!((_a = cfg.touch) === null || _a === void 0 ? void 0 : _a.enabled))
|
|
827
|
+
return;
|
|
828
|
+
const ne = e === null || e === void 0 ? void 0 : e.nativeEvent;
|
|
829
|
+
let hit = findHitInfo(ne === null || ne === void 0 ? void 0 : ne.target);
|
|
830
|
+
hit = normalizeFuzzyHit(hit) || resolveScrollableContextHit();
|
|
831
|
+
if (!hit || !hit.path) {
|
|
832
|
+
clearAll();
|
|
833
|
+
sidRef.current = makeSid();
|
|
834
|
+
startTsRef.current = Date.now();
|
|
835
|
+
startXRef.current = Number(ne === null || ne === void 0 ? void 0 : ne.pageX) || 0;
|
|
836
|
+
startYRef.current = Number(ne === null || ne === void 0 ? void 0 : ne.pageY) || 0;
|
|
837
|
+
movedRef.current = false;
|
|
838
|
+
startPathRef.current = __dt_get_scope_path();
|
|
839
|
+
if (mode === 'stream') {
|
|
840
|
+
const pos = makePos(ne, (_c = (_b = cfg.click) === null || _b === void 0 ? void 0 : _b.capturePosition) !== null && _c !== void 0 ? _c : 'none');
|
|
841
|
+
const out = buildUiEventShape({
|
|
842
|
+
touchPath: startPathRef.current,
|
|
843
|
+
meta: { phase: 'touch-start', ts: Date.now() },
|
|
844
|
+
pos: pos ? { x: pos.x, y: pos.y } : undefined,
|
|
845
|
+
sessionId: sidRef.current || undefined,
|
|
846
|
+
});
|
|
847
|
+
log(compactify(cfg, out));
|
|
848
|
+
}
|
|
849
|
+
return;
|
|
850
|
+
}
|
|
851
|
+
clearAll();
|
|
852
|
+
startPathRef.current = hit.path;
|
|
853
|
+
sidRef.current = makeSid();
|
|
854
|
+
startTsRef.current = Date.now();
|
|
855
|
+
startXRef.current = Number(ne === null || ne === void 0 ? void 0 : ne.pageX) || 0;
|
|
856
|
+
startYRef.current = Number(ne === null || ne === void 0 ? void 0 : ne.pageY) || 0;
|
|
857
|
+
movedRef.current = false;
|
|
858
|
+
if (mode === 'stream') {
|
|
859
|
+
const pos = makePos(ne, (_e = (_d = cfg.click) === null || _d === void 0 ? void 0 : _d.capturePosition) !== null && _e !== void 0 ? _e : 'none');
|
|
860
|
+
const out = buildUiEventShape({
|
|
861
|
+
touchPath: hit.path,
|
|
862
|
+
touchElementName: hit.element || undefined,
|
|
863
|
+
touchMasked: !!hit.isMasked,
|
|
864
|
+
meta: { phase: 'touch-start', ts: Date.now() },
|
|
865
|
+
pos: pos ? { x: pos.x, y: pos.y } : undefined,
|
|
866
|
+
sessionId: sidRef.current || undefined,
|
|
867
|
+
name_origin: hit.name_origin,
|
|
868
|
+
});
|
|
869
|
+
log(compactify(cfg, out));
|
|
870
|
+
}
|
|
871
|
+
}, [(_f = cfg.touch) === null || _f === void 0 ? void 0 : _f.enabled, (_g = cfg.click) === null || _g === void 0 ? void 0 : _g.capturePosition, mode]);
|
|
872
|
+
const onMove = React.useCallback((e) => {
|
|
873
|
+
var _a, _b, _c;
|
|
874
|
+
if (!((_a = cfg.touch) === null || _a === void 0 ? void 0 : _a.enabled))
|
|
875
|
+
return;
|
|
876
|
+
if (movedRef.current)
|
|
877
|
+
return;
|
|
878
|
+
const ne = e === null || e === void 0 ? void 0 : e.nativeEvent;
|
|
879
|
+
const x = Number(ne === null || ne === void 0 ? void 0 : ne.pageX) || 0;
|
|
880
|
+
const y = Number(ne === null || ne === void 0 ? void 0 : ne.pageY) || 0;
|
|
881
|
+
const sx = (_b = startXRef.current) !== null && _b !== void 0 ? _b : x;
|
|
882
|
+
const sy = (_c = startYRef.current) !== null && _c !== void 0 ? _c : y;
|
|
883
|
+
const dx = x - sx;
|
|
884
|
+
const dy = y - sy;
|
|
885
|
+
if (dx * dx + dy * dy >= threshold * threshold)
|
|
886
|
+
movedRef.current = true;
|
|
887
|
+
}, [(_h = cfg.touch) === null || _h === void 0 ? void 0 : _h.enabled, threshold]);
|
|
888
|
+
const onEnd = React.useCallback((e, phase) => {
|
|
889
|
+
var _a, _b, _c;
|
|
890
|
+
if (!((_a = cfg.touch) === null || _a === void 0 ? void 0 : _a.enabled))
|
|
891
|
+
return;
|
|
892
|
+
const ne = e === null || e === void 0 ? void 0 : e.nativeEvent;
|
|
893
|
+
if (mode === 'stream') {
|
|
894
|
+
handleStreamEnd(ne, phase);
|
|
895
|
+
return;
|
|
896
|
+
}
|
|
897
|
+
const pos = makePos(ne, (_c = (_b = cfg.click) === null || _b === void 0 ? void 0 : _b.capturePosition) !== null && _c !== void 0 ? _c : 'none');
|
|
898
|
+
const hitRaw = resolveTouchHit(ne === null || ne === void 0 ? void 0 : ne.target);
|
|
899
|
+
const now = Date.now();
|
|
900
|
+
const lifted = maybeLiftTouchHit(hitRaw);
|
|
901
|
+
const usePath = lifted.usePath;
|
|
902
|
+
const useEl = lifted.useElement || '';
|
|
903
|
+
if (!usePath) {
|
|
904
|
+
const scopePath = startPathRef.current || __dt_get_scope_path();
|
|
905
|
+
touchRef.current = {
|
|
906
|
+
path: scopePath,
|
|
907
|
+
elementName: '',
|
|
908
|
+
masked: false,
|
|
909
|
+
name_origin: 'component',
|
|
910
|
+
pos: pos ? { x: pos.x, y: pos.y } : undefined,
|
|
911
|
+
reason: 'unmapped',
|
|
912
|
+
ts: now,
|
|
913
|
+
};
|
|
914
|
+
flushOrSchedule();
|
|
915
|
+
return;
|
|
916
|
+
}
|
|
917
|
+
touchRef.current = {
|
|
918
|
+
path: usePath,
|
|
919
|
+
elementName: useEl,
|
|
920
|
+
masked: !!(hitRaw === null || hitRaw === void 0 ? void 0 : hitRaw.isMasked),
|
|
921
|
+
name_origin: lifted.nameOrigin,
|
|
922
|
+
pos: pos ? { x: pos.x, y: pos.y } : undefined,
|
|
923
|
+
reason: phaseReason(phase),
|
|
924
|
+
ts: now,
|
|
925
|
+
};
|
|
926
|
+
flushOrSchedule();
|
|
927
|
+
}, [
|
|
928
|
+
(_j = cfg.touch) === null || _j === void 0 ? void 0 : _j.enabled,
|
|
929
|
+
(_k = cfg.click) === null || _k === void 0 ? void 0 : _k.capturePosition,
|
|
930
|
+
(_l = cfg.touch) === null || _l === void 0 ? void 0 : _l.linkWindowMs,
|
|
931
|
+
mode,
|
|
932
|
+
]);
|
|
933
|
+
const registerPress = React.useCallback((info) => {
|
|
934
|
+
var _a, _b, _c;
|
|
935
|
+
if (!((_a = cfg.touch) === null || _a === void 0 ? void 0 : _a.enabled))
|
|
936
|
+
return;
|
|
937
|
+
const now = Date.now();
|
|
938
|
+
if (mode === 'stream') {
|
|
939
|
+
const out = buildUiEventShape({
|
|
940
|
+
pressPath: info.path,
|
|
941
|
+
pressElementName: info.elementName,
|
|
942
|
+
meta: { phase: 'press', ts: now },
|
|
943
|
+
name_origin: 'component',
|
|
944
|
+
pos: info.pos
|
|
945
|
+
? { x: info.pos.x, y: info.pos.y }
|
|
946
|
+
: undefined,
|
|
947
|
+
sessionId: sidRef.current || undefined,
|
|
948
|
+
});
|
|
949
|
+
log(compactify(cfg, out));
|
|
950
|
+
return;
|
|
951
|
+
}
|
|
952
|
+
pressRef.current = {
|
|
953
|
+
path: info.path,
|
|
954
|
+
elementName: info.elementName,
|
|
955
|
+
pos: info.pos ? { x: info.pos.x, y: info.pos.y } : undefined,
|
|
956
|
+
ts: now,
|
|
957
|
+
};
|
|
958
|
+
if (touchRef.current)
|
|
959
|
+
doFlush();
|
|
960
|
+
else
|
|
961
|
+
scheduleFlush((_c = (_b = cfg.touch) === null || _b === void 0 ? void 0 : _b.linkWindowMs) !== null && _c !== void 0 ? _c : 250);
|
|
962
|
+
}, [(_m = cfg.touch) === null || _m === void 0 ? void 0 : _m.enabled, (_o = cfg.touch) === null || _o === void 0 ? void 0 : _o.linkWindowMs, mode]);
|
|
963
|
+
return {
|
|
964
|
+
onStart,
|
|
965
|
+
onMove,
|
|
966
|
+
onEnd,
|
|
967
|
+
getSessionId: React.useCallback(() => sidRef.current, []),
|
|
968
|
+
getTouchPath: React.useCallback(() => { var _a, _b; return (_b = (_a = touchRef.current) === null || _a === void 0 ? void 0 : _a.path) !== null && _b !== void 0 ? _b : null; }, []),
|
|
969
|
+
getStartTs: React.useCallback(() => startTsRef.current, []),
|
|
970
|
+
getStartPath: React.useCallback(() => startPathRef.current, []),
|
|
971
|
+
registerPress,
|
|
972
|
+
};
|
|
973
|
+
}
|
|
974
|
+
function AnalyticsProvider({ children, log, config, }) {
|
|
975
|
+
const cfg = (0, react_1.useMemo)(() => config !== null && config !== void 0 ? config : {}, [config]);
|
|
976
|
+
const baseLogger = log || ((e) => logger.debug('[DT UI]' + JSON.stringify(e)));
|
|
977
|
+
const emit = React.useCallback((e) => {
|
|
978
|
+
var _a, _b, _c;
|
|
979
|
+
if (!ConfigurationHandler_1.ConfigurationHandler.isUserInteractionEnabled()) {
|
|
980
|
+
return;
|
|
981
|
+
}
|
|
982
|
+
const phase = ((_b = (_a = e === null || e === void 0 ? void 0 : e.ui_element) === null || _a === void 0 ? void 0 : _a.meta) === null || _b === void 0 ? void 0 : _b.phase) || '';
|
|
983
|
+
const id = ((_c = e === null || e === void 0 ? void 0 : e.ui_element) === null || _c === void 0 ? void 0 : _c.id) || '';
|
|
984
|
+
const now = Date.now();
|
|
985
|
+
if (phase === 'touch' &&
|
|
986
|
+
LAST_PRESS_ID &&
|
|
987
|
+
id &&
|
|
988
|
+
id === LAST_PRESS_ID &&
|
|
989
|
+
now - LAST_PRESS_TS < 300) {
|
|
990
|
+
return;
|
|
991
|
+
}
|
|
992
|
+
const key = id && phase ? id + '|' + phase : '';
|
|
993
|
+
if (key && key === LAST_EMIT_KEY && now - LAST_EMIT_TS < 10)
|
|
994
|
+
return;
|
|
995
|
+
LAST_EMIT_KEY = key;
|
|
996
|
+
LAST_EMIT_TS = now;
|
|
997
|
+
if (phase === 'press' && id) {
|
|
998
|
+
LAST_PRESS_ID = id;
|
|
999
|
+
LAST_PRESS_TS = now;
|
|
1000
|
+
}
|
|
1001
|
+
const eventTimestamp = new EventTimestamp_1.EventTimestamp(new TimestampProvider());
|
|
1002
|
+
const produceEvent = _an_flat(e);
|
|
1003
|
+
const event = Object.assign(Object.assign({}, produceEvent), eventTimestamp.getEventTimeInfo());
|
|
1004
|
+
EventPipeline_1.EventPipeline.insertEvent(event);
|
|
1005
|
+
return baseLogger(produceEvent);
|
|
1006
|
+
}, [baseLogger]);
|
|
1007
|
+
const touch = useTouchManager(cfg, emit);
|
|
1008
|
+
React.useEffect(() => {
|
|
1009
|
+
const g = globalThis;
|
|
1010
|
+
g.__DT_UII_BRIDGE = {
|
|
1011
|
+
registerPress: touch.registerPress,
|
|
1012
|
+
getStartPath: touch.getStartPath,
|
|
1013
|
+
};
|
|
1014
|
+
return () => {
|
|
1015
|
+
if (g.__DT_UII_BRIDGE &&
|
|
1016
|
+
g.__DT_UII_BRIDGE.registerPress === touch.registerPress) {
|
|
1017
|
+
delete g.__DT_UII_BRIDGE;
|
|
1018
|
+
}
|
|
1019
|
+
};
|
|
1020
|
+
}, [touch]);
|
|
1021
|
+
return (React.createElement(exports.CfgCtx.Provider, { value: cfg },
|
|
1022
|
+
React.createElement(LogCtx.Provider, { value: emit },
|
|
1023
|
+
React.createElement(TouchCtx.Provider, { value: touch },
|
|
1024
|
+
React.createElement(NodeCtx.Provider, { value: null },
|
|
1025
|
+
React.createElement(SiblingCtx.Provider, { value: makePreIndexedRegistry(children) }, children))))));
|
|
1026
|
+
}
|
|
1027
|
+
exports.AnalyticsProvider = AnalyticsProvider;
|
|
1028
|
+
function TouchCapture({ children }) {
|
|
1029
|
+
var _a;
|
|
1030
|
+
const cfg = (0, react_1.useContext)(exports.CfgCtx);
|
|
1031
|
+
const mgr = (0, react_1.useContext)(TouchCtx);
|
|
1032
|
+
const last = getDtLastTouch();
|
|
1033
|
+
const onStart = React.useCallback((e) => {
|
|
1034
|
+
var _a, _b;
|
|
1035
|
+
last.ts = Date.now();
|
|
1036
|
+
last.x = Number((_a = e === null || e === void 0 ? void 0 : e.nativeEvent) === null || _a === void 0 ? void 0 : _a.pageX) || 0;
|
|
1037
|
+
last.y = Number((_b = e === null || e === void 0 ? void 0 : e.nativeEvent) === null || _b === void 0 ? void 0 : _b.pageY) || 0;
|
|
1038
|
+
const targetObj = e === null || e === void 0 ? void 0 : e.target;
|
|
1039
|
+
if (isExpoRuntime() && isNativeTextInputViewTarget(targetObj)) {
|
|
1040
|
+
return;
|
|
1041
|
+
}
|
|
1042
|
+
return mgr === null || mgr === void 0 ? void 0 : mgr.onStart(e);
|
|
1043
|
+
}, [mgr]);
|
|
1044
|
+
const onMove = React.useCallback((e) => mgr === null || mgr === void 0 ? void 0 : mgr.onMove(e), [mgr]);
|
|
1045
|
+
const onEnd = React.useCallback((e) => {
|
|
1046
|
+
const targetObj = e === null || e === void 0 ? void 0 : e.target;
|
|
1047
|
+
if (isExpoRuntime() && isNativeTextInputViewTarget(targetObj)) {
|
|
1048
|
+
return;
|
|
1049
|
+
}
|
|
1050
|
+
return mgr === null || mgr === void 0 ? void 0 : mgr.onEnd(e, 'end');
|
|
1051
|
+
}, [mgr]);
|
|
1052
|
+
const onCancel = React.useCallback((e) => {
|
|
1053
|
+
return mgr === null || mgr === void 0 ? void 0 : mgr.onEnd(e, 'cancel');
|
|
1054
|
+
}, [mgr]);
|
|
1055
|
+
if (!ConfigurationHandler_1.ConfigurationHandler.isUserInteractionEnabled() ||
|
|
1056
|
+
!((_a = cfg.touch) === null || _a === void 0 ? void 0 : _a.enabled) ||
|
|
1057
|
+
!mgr)
|
|
1058
|
+
return React.createElement(React.Fragment, null, children);
|
|
1059
|
+
return (React.createElement(react_native_1.View, { pointerEvents: "box-none", collapsable: false, style: { flex: 1 }, onTouchStart: onStart, onTouchMove: onMove, onTouchEnd: onEnd, onTouchCancel: onCancel, onResponderRelease: onEnd, onResponderTerminate: onCancel }, children));
|
|
1060
|
+
}
|
|
1061
|
+
function Segment({ name, label, children, }) {
|
|
1062
|
+
var _a;
|
|
1063
|
+
const parent = (0, react_1.useContext)(NodeCtx);
|
|
1064
|
+
const cfg = (0, react_1.useContext)(exports.CfgCtx);
|
|
1065
|
+
const rolesMap = (_a = cfg.path) === null || _a === void 0 ? void 0 : _a.roleMap;
|
|
1066
|
+
const heur = cfg.roleHeuristics === undefined
|
|
1067
|
+
? DEFAULT_ROLE_HEURISTICS
|
|
1068
|
+
: cfg.roleHeuristics || false;
|
|
1069
|
+
const parentReg = (0, react_1.useContext)(SiblingCtx);
|
|
1070
|
+
const only = react_1.Children.only(children);
|
|
1071
|
+
const myRole = classifyRole(name, rolesMap, heur);
|
|
1072
|
+
const node = (0, react_1.useMemo)(() => ({
|
|
1073
|
+
name,
|
|
1074
|
+
label,
|
|
1075
|
+
role: myRole,
|
|
1076
|
+
parent: parent !== null && parent !== void 0 ? parent : null,
|
|
1077
|
+
}), [name, label, myRole, parent]);
|
|
1078
|
+
if (!(0, react_1.isValidElement)(only)) {
|
|
1079
|
+
return (React.createElement(NodeCtx.Provider, { value: node },
|
|
1080
|
+
React.createElement(SiblingCtx.Provider, { value: makePreIndexedRegistry(null) }, children)));
|
|
1081
|
+
}
|
|
1082
|
+
return (React.createElement(SegmentWithElement, { name: name, label: label, only: only, parent: parent, cfg: cfg, rolesMap: rolesMap, heur: heur, parentReg: parentReg }));
|
|
1083
|
+
}
|
|
1084
|
+
exports.Segment = Segment;
|
|
1085
|
+
function buildSegmentInteractionState(params) {
|
|
1086
|
+
var _a;
|
|
1087
|
+
const { childProps, childTypeName, name, parent, myRole, cfg, only, log, mgr, node, canAttachRef, } = params;
|
|
1088
|
+
const identity = resolveSegmentIdentity({
|
|
1089
|
+
childProps,
|
|
1090
|
+
childTypeName,
|
|
1091
|
+
name,
|
|
1092
|
+
});
|
|
1093
|
+
const masking = resolveSegmentMasking({
|
|
1094
|
+
leaf: identity.leaf,
|
|
1095
|
+
childProps,
|
|
1096
|
+
childTypeName,
|
|
1097
|
+
name,
|
|
1098
|
+
myRole,
|
|
1099
|
+
cfg,
|
|
1100
|
+
only,
|
|
1101
|
+
elementId: identity.elementId,
|
|
1102
|
+
nameOrigin: identity.nameOrigin,
|
|
1103
|
+
});
|
|
1104
|
+
const nextProps = Object.assign({}, childProps);
|
|
1105
|
+
const isInnerTextOfTouchable = applyInnerTextPointerEvents({
|
|
1106
|
+
nextProps,
|
|
1107
|
+
childTypeName,
|
|
1108
|
+
parent,
|
|
1109
|
+
});
|
|
1110
|
+
const useTouchLink = !!(((_a = cfg.touch) === null || _a === void 0 ? void 0 : _a.enabled) && mgr && canAttachRef);
|
|
1111
|
+
applyTextInputFocusHandler({
|
|
1112
|
+
nextProps,
|
|
1113
|
+
childProps,
|
|
1114
|
+
childTypeName,
|
|
1115
|
+
log,
|
|
1116
|
+
cfg,
|
|
1117
|
+
node,
|
|
1118
|
+
leafTailStatic: masking.leafTailStatic,
|
|
1119
|
+
elementIdOut: masking.elementIdOut,
|
|
1120
|
+
needMask: masking.needMask,
|
|
1121
|
+
nameOrigin: masking.nameOrigin,
|
|
1122
|
+
});
|
|
1123
|
+
applyAutoPressInHandler({
|
|
1124
|
+
nextProps,
|
|
1125
|
+
childProps,
|
|
1126
|
+
childTypeName,
|
|
1127
|
+
name,
|
|
1128
|
+
useTouchLink,
|
|
1129
|
+
isInnerTextOfTouchable,
|
|
1130
|
+
node,
|
|
1131
|
+
cfg,
|
|
1132
|
+
leafTailStatic: masking.leafTailStatic,
|
|
1133
|
+
elementIdOut: masking.elementIdOut,
|
|
1134
|
+
mgr,
|
|
1135
|
+
});
|
|
1136
|
+
wireSegmentEventHandlers({
|
|
1137
|
+
nextProps,
|
|
1138
|
+
childProps,
|
|
1139
|
+
childTypeName,
|
|
1140
|
+
useTouchLink,
|
|
1141
|
+
node,
|
|
1142
|
+
cfg,
|
|
1143
|
+
leafTailStatic: masking.leafTailStatic,
|
|
1144
|
+
elementIdOut: masking.elementIdOut,
|
|
1145
|
+
nameOrigin: masking.nameOrigin,
|
|
1146
|
+
mgr,
|
|
1147
|
+
log,
|
|
1148
|
+
});
|
|
1149
|
+
return {
|
|
1150
|
+
nextProps,
|
|
1151
|
+
needMask: masking.needMask,
|
|
1152
|
+
elementIdOut: masking.elementIdOut,
|
|
1153
|
+
nameOrigin: masking.nameOrigin,
|
|
1154
|
+
leafTailStatic: masking.leafTailStatic,
|
|
1155
|
+
isInnerTextOfTouchable,
|
|
1156
|
+
};
|
|
1157
|
+
}
|
|
1158
|
+
function resolveSegmentIdentity(params) {
|
|
1159
|
+
const { childProps, childTypeName, name } = params;
|
|
1160
|
+
const leaf = collectLeafInfo(childProps === null || childProps === void 0 ? void 0 : childProps.children) || null;
|
|
1161
|
+
const childLabel = typeof (childProps === null || childProps === void 0 ? void 0 : childProps.children) === 'string'
|
|
1162
|
+
? childProps.children.trim()
|
|
1163
|
+
: '';
|
|
1164
|
+
let elementId = childTypeName;
|
|
1165
|
+
let nameOrigin = 'component';
|
|
1166
|
+
if (childTypeName === 'TextInput' &&
|
|
1167
|
+
typeof (childProps === null || childProps === void 0 ? void 0 : childProps.placeholder) === 'string' &&
|
|
1168
|
+
childProps.placeholder.trim()) {
|
|
1169
|
+
elementId = childProps.placeholder.trim();
|
|
1170
|
+
}
|
|
1171
|
+
else if (typeof (childProps === null || childProps === void 0 ? void 0 : childProps.accessibilityLabel) === 'string') {
|
|
1172
|
+
elementId = childProps.accessibilityLabel.trim();
|
|
1173
|
+
}
|
|
1174
|
+
else if (typeof (childProps === null || childProps === void 0 ? void 0 : childProps.testID) === 'string') {
|
|
1175
|
+
elementId = childProps.testID.trim();
|
|
1176
|
+
}
|
|
1177
|
+
else if (leaf && leaf.source === 'text' && leaf.label) {
|
|
1178
|
+
elementId = leaf.label.trim();
|
|
1179
|
+
nameOrigin = 'text';
|
|
1180
|
+
}
|
|
1181
|
+
else if (childLabel.length > 0) {
|
|
1182
|
+
elementId = childLabel;
|
|
1183
|
+
nameOrigin = 'text';
|
|
1184
|
+
}
|
|
1185
|
+
if (childTypeName === 'Button' && typeof (childProps === null || childProps === void 0 ? void 0 : childProps.title) === 'string') {
|
|
1186
|
+
const title = childProps.title.trim();
|
|
1187
|
+
if (title) {
|
|
1188
|
+
elementId = title;
|
|
1189
|
+
nameOrigin = 'text';
|
|
1190
|
+
}
|
|
1191
|
+
}
|
|
1192
|
+
if (elementId === 'Anonymous') {
|
|
1193
|
+
elementId = name;
|
|
1194
|
+
nameOrigin = 'component';
|
|
1195
|
+
}
|
|
1196
|
+
if (childTypeName === 'Text' && elementId.trim()) {
|
|
1197
|
+
nameOrigin = 'text';
|
|
1198
|
+
}
|
|
1199
|
+
return { leaf, elementId, nameOrigin };
|
|
1200
|
+
}
|
|
1201
|
+
function resolveSegmentMasking(params) {
|
|
1202
|
+
var _a, _b, _c;
|
|
1203
|
+
const { leaf, childProps, childTypeName, name, myRole, cfg, only, elementId, nameOrigin, } = params;
|
|
1204
|
+
const hasSelfA11y = typeof (childProps === null || childProps === void 0 ? void 0 : childProps.accessibilityLabel) === 'string' ||
|
|
1205
|
+
typeof (childProps === null || childProps === void 0 ? void 0 : childProps.testID) === 'string';
|
|
1206
|
+
const segIsTouchable = exports.FORCED_TOUCHABLES.has(name) || exports.FORCED_TOUCHABLES.has(childTypeName);
|
|
1207
|
+
const shouldAppendLeafTail = !!(leaf &&
|
|
1208
|
+
leaf.source === 'text' &&
|
|
1209
|
+
!hasSelfA11y &&
|
|
1210
|
+
!segIsTouchable);
|
|
1211
|
+
const needMask = shouldMaskLeaf(leaf, only, myRole, cfg);
|
|
1212
|
+
const nextNameOrigin = needMask ? 'masked' : nameOrigin;
|
|
1213
|
+
const maskedText = needMask
|
|
1214
|
+
? maskLabel((_a = leaf === null || leaf === void 0 ? void 0 : leaf.label) !== null && _a !== void 0 ? _a : elementId, cfg)
|
|
1215
|
+
: undefined;
|
|
1216
|
+
const elementIdOut = needMask ? maskedText : elementId;
|
|
1217
|
+
const sep = (_c = (_b = cfg === null || cfg === void 0 ? void 0 : cfg.path) === null || _b === void 0 ? void 0 : _b.separator) !== null && _c !== void 0 ? _c : '->';
|
|
1218
|
+
const leafTailStatic = shouldAppendLeafTail
|
|
1219
|
+
? `${sep}${(leaf === null || leaf === void 0 ? void 0 : leaf.type) || 'Text'}`
|
|
1220
|
+
: '';
|
|
1221
|
+
return {
|
|
1222
|
+
needMask,
|
|
1223
|
+
nameOrigin: nextNameOrigin,
|
|
1224
|
+
elementIdOut,
|
|
1225
|
+
leafTailStatic,
|
|
1226
|
+
};
|
|
1227
|
+
}
|
|
1228
|
+
function applyInnerTextPointerEvents(params) {
|
|
1229
|
+
const { nextProps, childTypeName, parent } = params;
|
|
1230
|
+
const parentSegName = parent === null || parent === void 0 ? void 0 : parent.name;
|
|
1231
|
+
const isInnerTextOfTouchable = childTypeName === 'Text' &&
|
|
1232
|
+
!!parentSegName &&
|
|
1233
|
+
exports.FORCED_TOUCHABLES.has(parentSegName);
|
|
1234
|
+
if (isInnerTextOfTouchable && nextProps.pointerEvents == null) {
|
|
1235
|
+
nextProps.pointerEvents = 'none';
|
|
1236
|
+
}
|
|
1237
|
+
return isInnerTextOfTouchable;
|
|
1238
|
+
}
|
|
1239
|
+
function applyTextInputFocusHandler(params) {
|
|
1240
|
+
const { nextProps, childProps, childTypeName, log, cfg, node, leafTailStatic, elementIdOut, needMask, nameOrigin, } = params;
|
|
1241
|
+
if (childTypeName !== 'TextInput')
|
|
1242
|
+
return;
|
|
1243
|
+
const emit = log !== null && log !== void 0 ? log : ((e) => console.log('[DT UI]', e));
|
|
1244
|
+
const origOnFocus = childProps.onFocus;
|
|
1245
|
+
nextProps.onFocus = (...args) => {
|
|
1246
|
+
var _a;
|
|
1247
|
+
const t0 = Date.now();
|
|
1248
|
+
const lastTouch = getDtLastTouch();
|
|
1249
|
+
try {
|
|
1250
|
+
if (((_a = cfg.touch) === null || _a === void 0 ? void 0 : _a.enabled) && isExpoRuntime()) {
|
|
1251
|
+
const baseNow = toPathString(node, cfg.path);
|
|
1252
|
+
const pathOut = `${baseNow}${leafTailStatic}`;
|
|
1253
|
+
const linked = t0 - (lastTouch.ts || 0) < 800;
|
|
1254
|
+
const pos = linked
|
|
1255
|
+
? {
|
|
1256
|
+
x: Number(lastTouch.x) || 0,
|
|
1257
|
+
y: Number(lastTouch.y) || 0,
|
|
1258
|
+
}
|
|
1259
|
+
: undefined;
|
|
1260
|
+
const out = buildUiEventShape({
|
|
1261
|
+
touchPath: pathOut,
|
|
1262
|
+
touchElementName: elementIdOut,
|
|
1263
|
+
touchMasked: !!needMask,
|
|
1264
|
+
meta: { phase: 'touch', ts: t0 },
|
|
1265
|
+
pos: pos ? { x: pos.x, y: pos.y } : undefined,
|
|
1266
|
+
reason: linked ? 'focus-linked' : 'focus',
|
|
1267
|
+
name_origin: nameOrigin,
|
|
1268
|
+
});
|
|
1269
|
+
emit(compactify(cfg, out));
|
|
1270
|
+
}
|
|
1271
|
+
}
|
|
1272
|
+
catch (e) {
|
|
1273
|
+
const errorMsg = e instanceof Error ? e.stack || e.message : String(e);
|
|
1274
|
+
logger.debug(`TextInput focus instrumentation failed: ${errorMsg}`);
|
|
1275
|
+
}
|
|
1276
|
+
if (typeof origOnFocus === 'function')
|
|
1277
|
+
return origOnFocus(...args);
|
|
1278
|
+
};
|
|
1279
|
+
}
|
|
1280
|
+
function hasAnyPressKey(props) {
|
|
1281
|
+
for (const key in props) {
|
|
1282
|
+
if (PRESS_KEYS.has(key))
|
|
1283
|
+
return true;
|
|
1284
|
+
}
|
|
1285
|
+
return false;
|
|
1286
|
+
}
|
|
1287
|
+
function applyAutoPressInHandler(params) {
|
|
1288
|
+
const { nextProps, childProps, childTypeName, name, useTouchLink, isInnerTextOfTouchable, node, cfg, leafTailStatic, elementIdOut, mgr, } = params;
|
|
1289
|
+
const canAutoAddPress = useTouchLink &&
|
|
1290
|
+
!isInnerTextOfTouchable &&
|
|
1291
|
+
(exports.FORCED_TOUCHABLES.has(childTypeName) || exports.FORCED_TOUCHABLES.has(name));
|
|
1292
|
+
if (!canAutoAddPress || hasAnyPressKey(childProps))
|
|
1293
|
+
return;
|
|
1294
|
+
nextProps.onPressIn = (...args) => {
|
|
1295
|
+
var _a, _b;
|
|
1296
|
+
const baseNow = toPathString(node, cfg.path);
|
|
1297
|
+
const pathOut = `${baseNow}${leafTailStatic}`;
|
|
1298
|
+
const position = extractPosition(args, (_b = (_a = cfg === null || cfg === void 0 ? void 0 : cfg.click) === null || _a === void 0 ? void 0 : _a.capturePosition) !== null && _b !== void 0 ? _b : 'none');
|
|
1299
|
+
const info = {
|
|
1300
|
+
path: pathOut,
|
|
1301
|
+
elementName: elementIdOut,
|
|
1302
|
+
};
|
|
1303
|
+
if (position)
|
|
1304
|
+
info.pos = { x: position.x, y: position.y };
|
|
1305
|
+
mgr.registerPress(info);
|
|
1306
|
+
};
|
|
1307
|
+
}
|
|
1308
|
+
function wireSegmentEventHandlers(params) {
|
|
1309
|
+
const { nextProps, childProps, childTypeName, useTouchLink, node, cfg, leafTailStatic, elementIdOut, nameOrigin, mgr, log, } = params;
|
|
1310
|
+
for (const k in childProps) {
|
|
1311
|
+
const orig = childProps[k];
|
|
1312
|
+
const isTextInputEvent = childTypeName === 'TextInput' && TEXTINPUT_KEYS.has(k);
|
|
1313
|
+
if (!PRESS_KEYS.has(k) && !isTextInputEvent)
|
|
1314
|
+
continue;
|
|
1315
|
+
if (isTextInputEvent && k === 'onFocus')
|
|
1316
|
+
continue;
|
|
1317
|
+
nextProps[k] = (...args) => {
|
|
1318
|
+
var _a, _b, _c, _d;
|
|
1319
|
+
const baseNow = toPathString(node, cfg.path);
|
|
1320
|
+
const pathOut = `${baseNow}${leafTailStatic}`;
|
|
1321
|
+
const now = Date.now();
|
|
1322
|
+
if (isTextInputEvent || !useTouchLink) {
|
|
1323
|
+
const emit = log !== null && log !== void 0 ? log : ((e) => console.log('[DT UI]', e));
|
|
1324
|
+
const position = k === 'onChangeText'
|
|
1325
|
+
? undefined
|
|
1326
|
+
: extractPosition(args, (_b = (_a = cfg === null || cfg === void 0 ? void 0 : cfg.click) === null || _a === void 0 ? void 0 : _a.capturePosition) !== null && _b !== void 0 ? _b : 'none');
|
|
1327
|
+
const out = buildUiEventShape({
|
|
1328
|
+
pressPath: pathOut,
|
|
1329
|
+
pressElementName: elementIdOut,
|
|
1330
|
+
meta: { phase: normPhase(k), ts: now },
|
|
1331
|
+
pos: position
|
|
1332
|
+
? { x: position.x, y: position.y }
|
|
1333
|
+
: undefined,
|
|
1334
|
+
name_origin: nameOrigin,
|
|
1335
|
+
});
|
|
1336
|
+
try {
|
|
1337
|
+
emit(compactify(cfg, out));
|
|
1338
|
+
}
|
|
1339
|
+
catch (e) {
|
|
1340
|
+
const errorMsg = e instanceof Error ? e.stack || e.message : String(e);
|
|
1341
|
+
logger.debug(`Segment event emission failed for ${String(k)}: ${errorMsg}`);
|
|
1342
|
+
}
|
|
1343
|
+
if (typeof orig === 'function')
|
|
1344
|
+
return orig(...args);
|
|
1345
|
+
return;
|
|
1346
|
+
}
|
|
1347
|
+
if (k === 'onPress' ||
|
|
1348
|
+
k === 'onLongPress' ||
|
|
1349
|
+
k === 'onTap' ||
|
|
1350
|
+
k === 'onClick') {
|
|
1351
|
+
const position = extractPosition(args, (_d = (_c = cfg === null || cfg === void 0 ? void 0 : cfg.click) === null || _c === void 0 ? void 0 : _c.capturePosition) !== null && _d !== void 0 ? _d : 'none');
|
|
1352
|
+
const info = {
|
|
1353
|
+
path: pathOut,
|
|
1354
|
+
elementName: elementIdOut,
|
|
1355
|
+
};
|
|
1356
|
+
if (position)
|
|
1357
|
+
info.pos = { x: position.x, y: position.y };
|
|
1358
|
+
mgr.registerPress(info);
|
|
1359
|
+
}
|
|
1360
|
+
if (typeof orig === 'function')
|
|
1361
|
+
return orig(...args);
|
|
1362
|
+
};
|
|
1363
|
+
}
|
|
1364
|
+
}
|
|
1365
|
+
function SegmentWithElement({ name, label, only, parent, cfg, rolesMap, heur, parentReg, }) {
|
|
1366
|
+
var _a;
|
|
1367
|
+
const childType = only.type;
|
|
1368
|
+
const childProps = only.props;
|
|
1369
|
+
const canAttachRef = supportsRefType(childType);
|
|
1370
|
+
const childTypeName = typeof childType === 'string'
|
|
1371
|
+
? childType
|
|
1372
|
+
: childType
|
|
1373
|
+
.displayName ||
|
|
1374
|
+
childType.name ||
|
|
1375
|
+
'Anonymous';
|
|
1376
|
+
const myNameForSiblingIndex = childTypeName;
|
|
1377
|
+
const rawKey = (_a = only.key) !== null && _a !== void 0 ? _a : null;
|
|
1378
|
+
const myKeyForSiblingIndex = String(rawKey !== null && rawKey !== void 0 ? rawKey : '__pos:unknown');
|
|
1379
|
+
const myIdx = (0, react_1.useMemo)(() => parentReg
|
|
1380
|
+
? parentReg.getIndex(myNameForSiblingIndex, myKeyForSiblingIndex)
|
|
1381
|
+
: 1, [parentReg, myNameForSiblingIndex, myKeyForSiblingIndex]);
|
|
1382
|
+
const mySid = rawKey === null || rawKey === undefined
|
|
1383
|
+
? `pos:${myNameForSiblingIndex}:${myIdx}`
|
|
1384
|
+
: String(rawKey);
|
|
1385
|
+
const myRole = classifyRole(name, rolesMap, heur);
|
|
1386
|
+
const node = (0, react_1.useMemo)(() => ({
|
|
1387
|
+
name,
|
|
1388
|
+
label,
|
|
1389
|
+
role: myRole,
|
|
1390
|
+
idx: myIdx,
|
|
1391
|
+
sid: mySid,
|
|
1392
|
+
parent: parent !== null && parent !== void 0 ? parent : null,
|
|
1393
|
+
}), [name, label, myRole, myIdx, mySid, parent]);
|
|
1394
|
+
const log = (0, react_1.useContext)(LogCtx);
|
|
1395
|
+
const mgr = (0, react_1.useContext)(TouchCtx);
|
|
1396
|
+
const { nextProps, needMask, elementIdOut, nameOrigin, leafTailStatic, isInnerTextOfTouchable, } = buildSegmentInteractionState({
|
|
1397
|
+
childProps,
|
|
1398
|
+
childTypeName,
|
|
1399
|
+
name,
|
|
1400
|
+
parent,
|
|
1401
|
+
myRole,
|
|
1402
|
+
cfg,
|
|
1403
|
+
only,
|
|
1404
|
+
log,
|
|
1405
|
+
mgr,
|
|
1406
|
+
node,
|
|
1407
|
+
canAttachRef,
|
|
1408
|
+
});
|
|
1409
|
+
const childRegistry = (0, react_1.useMemo)(() => makePreIndexedRegistry(childProps === null || childProps === void 0 ? void 0 : childProps.children), [childProps === null || childProps === void 0 ? void 0 : childProps.children]);
|
|
1410
|
+
const baseNow = toPathString(node, cfg.path);
|
|
1411
|
+
React.useEffect(() => {
|
|
1412
|
+
if (myRole === 'nav') {
|
|
1413
|
+
__dt_set_scope_path(baseNow);
|
|
1414
|
+
}
|
|
1415
|
+
}, [myRole, baseNow]);
|
|
1416
|
+
const pathOut = `${baseNow}${leafTailStatic}`;
|
|
1417
|
+
const refAnchor = React.useRef(null);
|
|
1418
|
+
React.useEffect(() => {
|
|
1419
|
+
if (!canAttachRef)
|
|
1420
|
+
return;
|
|
1421
|
+
const h = (0, react_native_1.findNodeHandle)(refAnchor.current);
|
|
1422
|
+
if (!h)
|
|
1423
|
+
return;
|
|
1424
|
+
if (!isInnerTextOfTouchable) {
|
|
1425
|
+
registerHandle(h, {
|
|
1426
|
+
path: pathOut,
|
|
1427
|
+
element: elementIdOut,
|
|
1428
|
+
isMasked: needMask || undefined,
|
|
1429
|
+
name_origin: nameOrigin,
|
|
1430
|
+
});
|
|
1431
|
+
}
|
|
1432
|
+
return () => {
|
|
1433
|
+
if (!isInnerTextOfTouchable)
|
|
1434
|
+
registerHandle(h, null);
|
|
1435
|
+
};
|
|
1436
|
+
}, [
|
|
1437
|
+
canAttachRef,
|
|
1438
|
+
pathOut,
|
|
1439
|
+
elementIdOut,
|
|
1440
|
+
needMask,
|
|
1441
|
+
isInnerTextOfTouchable,
|
|
1442
|
+
nameOrigin,
|
|
1443
|
+
]);
|
|
1444
|
+
let extraRefProps = {};
|
|
1445
|
+
if (canAttachRef) {
|
|
1446
|
+
extraRefProps =
|
|
1447
|
+
typeof childType === 'string'
|
|
1448
|
+
? { ref: refAnchor, collapsable: false }
|
|
1449
|
+
: { ref: refAnchor };
|
|
1450
|
+
}
|
|
1451
|
+
const cloned = (0, react_1.cloneElement)(only, Object.assign(Object.assign({}, nextProps), extraRefProps));
|
|
1452
|
+
return (React.createElement(NodeCtx.Provider, { value: node },
|
|
1453
|
+
React.createElement(SiblingCtx.Provider, { value: childRegistry }, cloned)));
|
|
1454
|
+
}
|
|
1455
|
+
function PathPrefix({ names, children, }) {
|
|
1456
|
+
var _a;
|
|
1457
|
+
const base = (0, react_1.useContext)(NodeCtx);
|
|
1458
|
+
const cfg = (0, react_1.useContext)(exports.CfgCtx);
|
|
1459
|
+
const tail = (0, react_1.useMemo)(() => {
|
|
1460
|
+
var _a;
|
|
1461
|
+
let cur = base !== null && base !== void 0 ? base : null;
|
|
1462
|
+
for (const n of names) {
|
|
1463
|
+
cur = {
|
|
1464
|
+
name: n.name,
|
|
1465
|
+
label: n.label,
|
|
1466
|
+
role: classifyRole(n.name, (_a = cfg.path) === null || _a === void 0 ? void 0 : _a.roleMap, cfg.roleHeuristics),
|
|
1467
|
+
idx: undefined,
|
|
1468
|
+
sid: undefined,
|
|
1469
|
+
parent: cur,
|
|
1470
|
+
};
|
|
1471
|
+
}
|
|
1472
|
+
return cur;
|
|
1473
|
+
}, [base, names, (_a = cfg.path) === null || _a === void 0 ? void 0 : _a.roleMap, cfg.roleHeuristics]);
|
|
1474
|
+
const childRegistry = (0, react_1.useMemo)(() => makePreIndexedRegistry(children), [children]);
|
|
1475
|
+
return (React.createElement(NodeCtx.Provider, { value: tail },
|
|
1476
|
+
React.createElement(SiblingCtx.Provider, { value: childRegistry }, children)));
|
|
1477
|
+
}
|
|
1478
|
+
exports.PathPrefix = PathPrefix;
|
|
1479
|
+
function AnalyticsRoot({ name = 'App', label, log, prefix, config, children, }) {
|
|
1480
|
+
var _a;
|
|
1481
|
+
const content = (React.createElement(Segment, { name: name, label: label }, children));
|
|
1482
|
+
const pref = Array.isArray(prefix) ? prefix : readGlobalPrefix();
|
|
1483
|
+
const inner = pref.length ? (React.createElement(PathPrefix, { names: pref }, content)) : (content);
|
|
1484
|
+
return (React.createElement(AnalyticsProvider, { log: log, config: config }, ((_a = config === null || config === void 0 ? void 0 : config.touch) === null || _a === void 0 ? void 0 : _a.enabled) ? (React.createElement(TouchCapture, null, inner)) : (inner)));
|
|
1485
|
+
}
|
|
1486
|
+
exports.AnalyticsRoot = AnalyticsRoot;
|
|
1487
|
+
exports.LabelClaimScope = Object.assign(({ children, mask }) => {
|
|
1488
|
+
return (0, react_1.cloneElement)(react_1.Children.only(children), { mask });
|
|
1489
|
+
}, { __AN_LABEL_SCOPE: true });
|
|
1490
|
+
exports.TabButton = React.forwardRef(function TabButton(props, ref) {
|
|
1491
|
+
const { children, style, testID, accessibilityLabel, onPress, onLongPress, onPressIn, onPressOut, } = props;
|
|
1492
|
+
return (React.createElement(Segment, { name: "TabButton" },
|
|
1493
|
+
React.createElement(react_native_1.Pressable, { ref: ref, style: style, testID: testID, accessibilityLabel: accessibilityLabel, onPress: onPress, onLongPress: onLongPress, onPressIn: onPressIn, onPressOut: onPressOut }, children)));
|
|
1494
|
+
});
|