@sentry/replay 7.54.0 → 7.55.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.
Files changed (39) hide show
  1. package/cjs/index.js +104 -63
  2. package/cjs/index.js.map +1 -1
  3. package/esm/index.js +104 -63
  4. package/esm/index.js.map +1 -1
  5. package/package.json +5 -5
  6. package/types/constants.d.ts +2 -0
  7. package/types/constants.d.ts.map +1 -1
  8. package/types/coreHandlers/handleDom.d.ts.map +1 -1
  9. package/types/coreHandlers/handleKeyboardEvent.d.ts.map +1 -1
  10. package/types/coreHandlers/handleScope.d.ts +4 -1
  11. package/types/coreHandlers/handleScope.d.ts.map +1 -1
  12. package/types/coreHandlers/handleSlowClick.d.ts +2 -0
  13. package/types/coreHandlers/handleSlowClick.d.ts.map +1 -1
  14. package/types/coreHandlers/util/getAttributesToRecord.d.ts.map +1 -1
  15. package/types/index.d.ts +1 -0
  16. package/types/index.d.ts.map +1 -1
  17. package/types/integration.d.ts +1 -1
  18. package/types/integration.d.ts.map +1 -1
  19. package/types/replay.d.ts +8 -0
  20. package/types/replay.d.ts.map +1 -1
  21. package/types/session/getSession.d.ts.map +1 -1
  22. package/types/types/index.d.ts +6 -0
  23. package/types/types/index.d.ts.map +1 -0
  24. package/types/types/performance.d.ts +124 -0
  25. package/types/types/performance.d.ts.map +1 -0
  26. package/types/{types.d.ts → types/replay.d.ts} +21 -144
  27. package/types/types/replay.d.ts.map +1 -0
  28. package/types/types/replayFrame.d.ts +160 -0
  29. package/types/types/replayFrame.d.ts.map +1 -0
  30. package/types/types/request.d.ts +15 -0
  31. package/types/types/request.d.ts.map +1 -0
  32. package/types/types/rrweb.d.ts +1 -9
  33. package/types/types/rrweb.d.ts.map +1 -1
  34. package/types/util/addEvent.d.ts.map +1 -1
  35. package/types/util/createBreadcrumb.d.ts +2 -4
  36. package/types/util/createBreadcrumb.d.ts.map +1 -1
  37. package/types/util/handleRecordingEmit.d.ts +2 -2
  38. package/types/util/handleRecordingEmit.d.ts.map +1 -1
  39. package/types/types.d.ts.map +0 -1
package/cjs/index.js CHANGED
@@ -40,6 +40,11 @@ const NETWORK_BODY_MAX_SIZE = 150000;
40
40
  /* The max size of a single console arg that is captured. Any arg larger than this will be truncated. */
41
41
  const CONSOLE_ARG_MAX_SIZE = 5000;
42
42
 
43
+ /* Min. time to wait before we consider something a slow click. */
44
+ const SLOW_CLICK_THRESHOLD = 3000;
45
+ /* For scroll actions after a click, we only look for a very short time period to detect programmatic scrolling. */
46
+ const SLOW_CLICK_SCROLL_TIMEOUT = 300;
47
+
43
48
  var NodeType$1;
44
49
  (function (NodeType) {
45
50
  NodeType[NodeType["Document"] = 0] = "Document";
@@ -993,7 +998,7 @@ function skipAttribute(tagName, attributeName, value) {
993
998
  return ((tagName === 'video' || tagName === 'audio') && attributeName === 'autoplay');
994
999
  }
995
1000
 
996
- var EventType$1;
1001
+ var EventType;
997
1002
  (function (EventType) {
998
1003
  EventType[EventType["DomContentLoaded"] = 0] = "DomContentLoaded";
999
1004
  EventType[EventType["Load"] = 1] = "Load";
@@ -1002,7 +1007,7 @@ var EventType$1;
1002
1007
  EventType[EventType["Meta"] = 4] = "Meta";
1003
1008
  EventType[EventType["Custom"] = 5] = "Custom";
1004
1009
  EventType[EventType["Plugin"] = 6] = "Plugin";
1005
- })(EventType$1 || (EventType$1 = {}));
1010
+ })(EventType || (EventType = {}));
1006
1011
  var IncrementalSource;
1007
1012
  (function (IncrementalSource) {
1008
1013
  IncrementalSource[IncrementalSource["Mutation"] = 0] = "Mutation";
@@ -2975,17 +2980,17 @@ function record(options = {}) {
2975
2980
  wrappedEmit = (e, isCheckout) => {
2976
2981
  var _a;
2977
2982
  if (((_a = mutationBuffers[0]) === null || _a === void 0 ? void 0 : _a.isFrozen()) &&
2978
- e.type !== EventType$1.FullSnapshot &&
2979
- !(e.type === EventType$1.IncrementalSnapshot &&
2983
+ e.type !== EventType.FullSnapshot &&
2984
+ !(e.type === EventType.IncrementalSnapshot &&
2980
2985
  e.data.source === IncrementalSource.Mutation)) {
2981
2986
  mutationBuffers.forEach((buf) => buf.unfreeze());
2982
2987
  }
2983
2988
  emit(eventProcessor(e), isCheckout);
2984
- if (e.type === EventType$1.FullSnapshot) {
2989
+ if (e.type === EventType.FullSnapshot) {
2985
2990
  lastFullSnapshotEvent = e;
2986
2991
  incrementalSnapshotCount = 0;
2987
2992
  }
2988
- else if (e.type === EventType$1.IncrementalSnapshot) {
2993
+ else if (e.type === EventType.IncrementalSnapshot) {
2989
2994
  if (e.data.source === IncrementalSource.Mutation &&
2990
2995
  e.data.isAttachIframe) {
2991
2996
  return;
@@ -3001,16 +3006,16 @@ function record(options = {}) {
3001
3006
  };
3002
3007
  const wrappedMutationEmit = (m) => {
3003
3008
  wrappedEmit(wrapEvent({
3004
- type: EventType$1.IncrementalSnapshot,
3009
+ type: EventType.IncrementalSnapshot,
3005
3010
  data: Object.assign({ source: IncrementalSource.Mutation }, m),
3006
3011
  }));
3007
3012
  };
3008
3013
  const wrappedScrollEmit = (p) => wrappedEmit(wrapEvent({
3009
- type: EventType$1.IncrementalSnapshot,
3014
+ type: EventType.IncrementalSnapshot,
3010
3015
  data: Object.assign({ source: IncrementalSource.Scroll }, p),
3011
3016
  }));
3012
3017
  const wrappedCanvasMutationEmit = (p) => wrappedEmit(wrapEvent({
3013
- type: EventType$1.IncrementalSnapshot,
3018
+ type: EventType.IncrementalSnapshot,
3014
3019
  data: Object.assign({ source: IncrementalSource.CanvasMutation }, p),
3015
3020
  }));
3016
3021
  const iframeManager = new IframeManager({
@@ -3055,7 +3060,7 @@ function record(options = {}) {
3055
3060
  takeFullSnapshot = (isCheckout = false) => {
3056
3061
  var _a, _b, _c, _d;
3057
3062
  wrappedEmit(wrapEvent({
3058
- type: EventType$1.Meta,
3063
+ type: EventType.Meta,
3059
3064
  data: {
3060
3065
  href: window.location.href,
3061
3066
  width: getWindowWidth(),
@@ -3098,7 +3103,7 @@ function record(options = {}) {
3098
3103
  }
3099
3104
  mirror.map = idNodeMap;
3100
3105
  wrappedEmit(wrapEvent({
3101
- type: EventType$1.FullSnapshot,
3106
+ type: EventType.FullSnapshot,
3102
3107
  data: {
3103
3108
  node,
3104
3109
  initialOffset: {
@@ -3123,7 +3128,7 @@ function record(options = {}) {
3123
3128
  const handlers = [];
3124
3129
  handlers.push(on('DOMContentLoaded', () => {
3125
3130
  wrappedEmit(wrapEvent({
3126
- type: EventType$1.DomContentLoaded,
3131
+ type: EventType.DomContentLoaded,
3127
3132
  data: {},
3128
3133
  }));
3129
3134
  }));
@@ -3133,40 +3138,40 @@ function record(options = {}) {
3133
3138
  onMutation,
3134
3139
  mutationCb: wrappedMutationEmit,
3135
3140
  mousemoveCb: (positions, source) => wrappedEmit(wrapEvent({
3136
- type: EventType$1.IncrementalSnapshot,
3141
+ type: EventType.IncrementalSnapshot,
3137
3142
  data: {
3138
3143
  source,
3139
3144
  positions,
3140
3145
  },
3141
3146
  })),
3142
3147
  mouseInteractionCb: (d) => wrappedEmit(wrapEvent({
3143
- type: EventType$1.IncrementalSnapshot,
3148
+ type: EventType.IncrementalSnapshot,
3144
3149
  data: Object.assign({ source: IncrementalSource.MouseInteraction }, d),
3145
3150
  })),
3146
3151
  scrollCb: wrappedScrollEmit,
3147
3152
  viewportResizeCb: (d) => wrappedEmit(wrapEvent({
3148
- type: EventType$1.IncrementalSnapshot,
3153
+ type: EventType.IncrementalSnapshot,
3149
3154
  data: Object.assign({ source: IncrementalSource.ViewportResize }, d),
3150
3155
  })),
3151
3156
  inputCb: (v) => wrappedEmit(wrapEvent({
3152
- type: EventType$1.IncrementalSnapshot,
3157
+ type: EventType.IncrementalSnapshot,
3153
3158
  data: Object.assign({ source: IncrementalSource.Input }, v),
3154
3159
  })),
3155
3160
  mediaInteractionCb: (p) => wrappedEmit(wrapEvent({
3156
- type: EventType$1.IncrementalSnapshot,
3161
+ type: EventType.IncrementalSnapshot,
3157
3162
  data: Object.assign({ source: IncrementalSource.MediaInteraction }, p),
3158
3163
  })),
3159
3164
  styleSheetRuleCb: (r) => wrappedEmit(wrapEvent({
3160
- type: EventType$1.IncrementalSnapshot,
3165
+ type: EventType.IncrementalSnapshot,
3161
3166
  data: Object.assign({ source: IncrementalSource.StyleSheetRule }, r),
3162
3167
  })),
3163
3168
  styleDeclarationCb: (r) => wrappedEmit(wrapEvent({
3164
- type: EventType$1.IncrementalSnapshot,
3169
+ type: EventType.IncrementalSnapshot,
3165
3170
  data: Object.assign({ source: IncrementalSource.StyleDeclaration }, r),
3166
3171
  })),
3167
3172
  canvasMutationCb: wrappedCanvasMutationEmit,
3168
3173
  fontCb: (p) => wrappedEmit(wrapEvent({
3169
- type: EventType$1.IncrementalSnapshot,
3174
+ type: EventType.IncrementalSnapshot,
3170
3175
  data: Object.assign({ source: IncrementalSource.Font }, p),
3171
3176
  })),
3172
3177
  blockClass,
@@ -3199,7 +3204,7 @@ function record(options = {}) {
3199
3204
  observer: p.observer,
3200
3205
  options: p.options,
3201
3206
  callback: (payload) => wrappedEmit(wrapEvent({
3202
- type: EventType$1.Plugin,
3207
+ type: EventType.Plugin,
3203
3208
  data: {
3204
3209
  plugin: p.name,
3205
3210
  payload,
@@ -3227,7 +3232,7 @@ function record(options = {}) {
3227
3232
  else {
3228
3233
  handlers.push(on('load', () => {
3229
3234
  wrappedEmit(wrapEvent({
3230
- type: EventType$1.Load,
3235
+ type: EventType.Load,
3231
3236
  data: {},
3232
3237
  }));
3233
3238
  init();
@@ -3246,7 +3251,7 @@ record.addCustomEvent = (tag, payload) => {
3246
3251
  throw new Error('please add custom event after start recording');
3247
3252
  }
3248
3253
  wrappedEmit(wrapEvent({
3249
- type: EventType$1.Custom,
3254
+ type: EventType.Custom,
3250
3255
  data: {
3251
3256
  tag,
3252
3257
  payload,
@@ -3303,7 +3308,7 @@ function addBreadcrumbEvent(replay, breadcrumb) {
3303
3308
 
3304
3309
  replay.addUpdate(() => {
3305
3310
  void replay.throttledAddEvent({
3306
- type: EventType$1.Custom,
3311
+ type: EventType.Custom,
3307
3312
  // TODO: We were converting from ms to seconds for breadcrumbs, spans,
3308
3313
  // but maybe we should just keep them as milliseconds
3309
3314
  timestamp: (breadcrumb.timestamp || 0) * 1000,
@@ -3425,15 +3430,16 @@ function handleSlowClick(
3425
3430
  addBreadcrumbEvent(replay, breadcrumb);
3426
3431
  }
3427
3432
 
3428
- const SLOW_CLICK_IGNORE_TAGS = ['SELECT', 'OPTION'];
3433
+ const SLOW_CLICK_TAGS = ['A', 'BUTTON', 'INPUT'];
3429
3434
 
3435
+ /** exported for tests only */
3430
3436
  function ignoreElement(node, config) {
3431
- // If <input> tag, we only want to consider input[type='submit'] & input[type='button']
3432
- if (node.tagName === 'INPUT' && !['submit', 'button'].includes(node.getAttribute('type') || '')) {
3437
+ if (!SLOW_CLICK_TAGS.includes(node.tagName)) {
3433
3438
  return true;
3434
3439
  }
3435
3440
 
3436
- if (SLOW_CLICK_IGNORE_TAGS.includes(node.tagName)) {
3441
+ // If <input> tag, we only want to consider input[type='submit'] & input[type='button']
3442
+ if (node.tagName === 'INPUT' && !['submit', 'button'].includes(node.getAttribute('type') || '')) {
3437
3443
  return true;
3438
3444
  }
3439
3445
 
@@ -3466,6 +3472,8 @@ const ATTRIBUTES_TO_RECORD = new Set([
3466
3472
  'title',
3467
3473
  'data-test-id',
3468
3474
  'data-testid',
3475
+ 'disabled',
3476
+ 'aria-disabled',
3469
3477
  ]);
3470
3478
 
3471
3479
  /**
@@ -3491,14 +3499,14 @@ function getAttributesToRecord(attributes) {
3491
3499
  const handleDomListener = (
3492
3500
  replay,
3493
3501
  ) => {
3494
- const slowClickExperiment = replay.getOptions()._experiments.slowClicks;
3502
+ const { slowClickTimeout, slowClickIgnoreSelectors } = replay.getOptions();
3495
3503
 
3496
- const slowClickConfig = slowClickExperiment
3504
+ const slowClickConfig = slowClickTimeout
3497
3505
  ? {
3498
- threshold: slowClickExperiment.threshold,
3499
- timeout: slowClickExperiment.timeout,
3500
- scrollTimeout: slowClickExperiment.scrollTimeout,
3501
- ignoreSelector: slowClickExperiment.ignoreSelectors ? slowClickExperiment.ignoreSelectors.join(',') : '',
3506
+ threshold: Math.min(SLOW_CLICK_THRESHOLD, slowClickTimeout),
3507
+ timeout: slowClickTimeout,
3508
+ scrollTimeout: SLOW_CLICK_SCROLL_TIMEOUT,
3509
+ ignoreSelector: slowClickIgnoreSelectors ? slowClickIgnoreSelectors.join(',') : '',
3502
3510
  }
3503
3511
  : undefined;
3504
3512
 
@@ -3627,7 +3635,10 @@ function handleKeyboardEvent(replay, event) {
3627
3635
  return;
3628
3636
  }
3629
3637
 
3630
- replay.triggerUserActivity();
3638
+ // Update user activity, but do not restart recording as it can create
3639
+ // noisy/low-value replays (e.g. user comes back from idle, hits alt-tab, new
3640
+ // session with a single "keydown" breadcrumb is created)
3641
+ replay.updateUserActivity();
3631
3642
 
3632
3643
  const breadcrumb = getKeyboardBreadcrumb(event);
3633
3644
 
@@ -4378,11 +4389,13 @@ function getSession({
4378
4389
  // within "max session time").
4379
4390
  const isExpired = isSessionExpired(session, timeouts);
4380
4391
 
4381
- if (!isExpired) {
4392
+ if (!isExpired || (allowBuffering && session.shouldRefresh)) {
4382
4393
  return { type: 'saved', session };
4383
4394
  } else if (!session.shouldRefresh) {
4384
- // In this case, stop
4385
- // This is the case if we have an error session that is completed (=triggered an error)
4395
+ // This is the case if we have an error session that is completed
4396
+ // (=triggered an error). Session will continue as session-based replay,
4397
+ // and when this session is expired, it will not be renewed until user
4398
+ // reloads.
4386
4399
  const discardedSession = makeSession({ sampled: false });
4387
4400
  return { type: 'new', session: discardedSession };
4388
4401
  } else {
@@ -4400,22 +4413,9 @@ function getSession({
4400
4413
  return { type: 'new', session: newSession };
4401
4414
  }
4402
4415
 
4403
- /* eslint-disable @typescript-eslint/naming-convention */
4404
-
4405
- var EventType; (function (EventType) {
4406
- const DomContentLoaded = 0; EventType[EventType["DomContentLoaded"] = DomContentLoaded] = "DomContentLoaded";
4407
- const Load = 1; EventType[EventType["Load"] = Load] = "Load";
4408
- const FullSnapshot = 2; EventType[EventType["FullSnapshot"] = FullSnapshot] = "FullSnapshot";
4409
- const IncrementalSnapshot = 3; EventType[EventType["IncrementalSnapshot"] = IncrementalSnapshot] = "IncrementalSnapshot";
4410
- const Meta = 4; EventType[EventType["Meta"] = Meta] = "Meta";
4411
- const Custom = 5; EventType[EventType["Custom"] = Custom] = "Custom";
4412
- const Plugin = 6; EventType[EventType["Plugin"] = Plugin] = "Plugin";
4413
- })(EventType || (EventType = {}));
4414
-
4415
- /**
4416
- * This is a partial copy of rrweb's eventWithTime type which only contains the properties
4417
- * we specifcally need in the SDK.
4418
- */
4416
+ function isCustomEvent(event) {
4417
+ return event.type === EventType.Custom;
4418
+ }
4419
4419
 
4420
4420
  /**
4421
4421
  * Add an event to the event buffer.
@@ -4454,7 +4454,7 @@ async function addEvent(
4454
4454
  const replayOptions = replay.getOptions();
4455
4455
 
4456
4456
  const eventAfterPossibleCallback =
4457
- typeof replayOptions.beforeAddRecordingEvent === 'function' && event.type === EventType.Custom
4457
+ typeof replayOptions.beforeAddRecordingEvent === 'function' && isCustomEvent(event)
4458
4458
  ? replayOptions.beforeAddRecordingEvent(event)
4459
4459
  : event;
4460
4460
 
@@ -4669,7 +4669,7 @@ function createPerformanceSpans(
4669
4669
  ) {
4670
4670
  return entries.map(({ type, start, end, name, data }) => {
4671
4671
  const response = replay.throttledAddEvent({
4672
- type: EventType$1.Custom,
4672
+ type: EventType.Custom,
4673
4673
  timestamp: start,
4674
4674
  data: {
4675
4675
  tag: 'performanceSpan',
@@ -5903,6 +5903,10 @@ function _isFetchHint(hint) {
5903
5903
 
5904
5904
  let _LAST_BREADCRUMB = null;
5905
5905
 
5906
+ function isBreadcrumbWithCategory(breadcrumb) {
5907
+ return !!breadcrumb.category;
5908
+ }
5909
+
5906
5910
  const handleScopeListener =
5907
5911
  (replay) =>
5908
5912
  (scope) => {
@@ -5938,9 +5942,9 @@ function handleScope(scope) {
5938
5942
  _LAST_BREADCRUMB = newBreadcrumb;
5939
5943
 
5940
5944
  if (
5941
- newBreadcrumb.category &&
5942
- (['fetch', 'xhr', 'sentry.event', 'sentry.transaction'].includes(newBreadcrumb.category) ||
5943
- newBreadcrumb.category.startsWith('ui.'))
5945
+ !isBreadcrumbWithCategory(newBreadcrumb) ||
5946
+ ['fetch', 'xhr', 'sentry.event', 'sentry.transaction'].includes(newBreadcrumb.category) ||
5947
+ newBreadcrumb.category.startsWith('ui.')
5944
5948
  ) {
5945
5949
  return null;
5946
5950
  }
@@ -5953,7 +5957,9 @@ function handleScope(scope) {
5953
5957
  }
5954
5958
 
5955
5959
  /** exported for tests only */
5956
- function normalizeConsoleBreadcrumb(breadcrumb) {
5960
+ function normalizeConsoleBreadcrumb(
5961
+ breadcrumb,
5962
+ ) {
5957
5963
  const args = breadcrumb.data && breadcrumb.data.arguments;
5958
5964
 
5959
5965
  if (!Array.isArray(args) || args.length === 0) {
@@ -6402,6 +6408,10 @@ function getHandleRecordingEmit(replay) {
6402
6408
  // a previous session ID. In this case, we want to buffer events
6403
6409
  // for a set amount of time before flushing. This can help avoid
6404
6410
  // capturing replays of users that immediately close the window.
6411
+ // TODO: We should check `recordingMode` here and do nothing if it's
6412
+ // buffer, instead of checking inside of timeout, this will make our
6413
+ // tests a bit cleaner as we will need to wait on the delay in order to
6414
+ // do nothing.
6405
6415
  setTimeout(() => replay.conditionalFlush(), options._experiments.delayFlushOnCheckout);
6406
6416
 
6407
6417
  // Cancel any previously debounced flushes to ensure there are no [near]
@@ -7168,6 +7178,8 @@ class ReplayContainer {
7168
7178
  return this.flushImmediate();
7169
7179
  }
7170
7180
 
7181
+ const activityTime = Date.now();
7182
+
7171
7183
  // Allow flush to complete before resuming as a session recording, otherwise
7172
7184
  // the checkout from `startRecording` may be included in the payload.
7173
7185
  // Prefer to keep the error replay as a separate (and smaller) segment
@@ -7189,6 +7201,18 @@ class ReplayContainer {
7189
7201
  // Once this session ends, we do not want to refresh it
7190
7202
  if (this.session) {
7191
7203
  this.session.shouldRefresh = false;
7204
+
7205
+ // It's possible that the session lifespan is > max session lifespan
7206
+ // because we have been buffering beyond max session lifespan (we ignore
7207
+ // expiration given that `shouldRefresh` is true). Since we flip
7208
+ // `shouldRefresh`, the session could be considered expired due to
7209
+ // lifespan, which is not what we want. Update session start date to be
7210
+ // the current timestamp, so that session is not considered to be
7211
+ // expired. This means that max replay duration can be MAX_SESSION_LIFE +
7212
+ // (length of buffer), which we are ok with.
7213
+ this._updateUserActivity(activityTime);
7214
+ this._updateSessionActivity(activityTime);
7215
+ this.session.started = activityTime;
7192
7216
  this._maybeSaveSession();
7193
7217
  }
7194
7218
 
@@ -7252,6 +7276,18 @@ class ReplayContainer {
7252
7276
  this._updateSessionActivity();
7253
7277
  }
7254
7278
 
7279
+ /**
7280
+ * Updates the user activity timestamp *without* resuming
7281
+ * recording. Some user events (e.g. keydown) can be create
7282
+ * low-value replays that only contain the keypress as a
7283
+ * breadcrumb. Instead this would require other events to
7284
+ * create a new replay after a session has expired.
7285
+ */
7286
+ updateUserActivity() {
7287
+ this._updateUserActivity();
7288
+ this._updateSessionActivity();
7289
+ }
7290
+
7255
7291
  /**
7256
7292
  * Only flush if `this.recordingMode === 'session'`
7257
7293
  */
@@ -7372,7 +7408,7 @@ class ReplayContainer {
7372
7408
 
7373
7409
  this.addUpdate(() => {
7374
7410
  void addEvent(this, {
7375
- type: EventType$1.Custom,
7411
+ type: EventType.Custom,
7376
7412
  timestamp: breadcrumb.timestamp || 0,
7377
7413
  data: {
7378
7414
  tag: 'breadcrumb',
@@ -7442,7 +7478,7 @@ class ReplayContainer {
7442
7478
  stickySession: Boolean(this._options.stickySession),
7443
7479
  currentSession: this.session,
7444
7480
  sessionSampleRate: this._options.sessionSampleRate,
7445
- allowBuffering: this._options.errorSampleRate > 0,
7481
+ allowBuffering: this._options.errorSampleRate > 0 || this.recordingMode === 'buffer',
7446
7482
  });
7447
7483
 
7448
7484
  // If session was newly created (i.e. was not loaded from storage), then
@@ -7638,7 +7674,7 @@ class ReplayContainer {
7638
7674
  _createCustomBreadcrumb(breadcrumb) {
7639
7675
  this.addUpdate(() => {
7640
7676
  void this.throttledAddEvent({
7641
- type: EventType$1.Custom,
7677
+ type: EventType.Custom,
7642
7678
  timestamp: breadcrumb.timestamp || 0,
7643
7679
  data: {
7644
7680
  tag: 'breadcrumb',
@@ -8012,6 +8048,9 @@ class Replay {
8012
8048
  mutationBreadcrumbLimit = 750,
8013
8049
  mutationLimit = 10000,
8014
8050
 
8051
+ slowClickTimeout = 7000,
8052
+ slowClickIgnoreSelectors = [],
8053
+
8015
8054
  networkDetailAllowUrls = [],
8016
8055
  networkCaptureBodies = true,
8017
8056
  networkRequestHeaders = [],
@@ -8081,6 +8120,8 @@ class Replay {
8081
8120
  maskAllText,
8082
8121
  mutationBreadcrumbLimit,
8083
8122
  mutationLimit,
8123
+ slowClickTimeout,
8124
+ slowClickIgnoreSelectors,
8084
8125
  networkDetailAllowUrls,
8085
8126
  networkCaptureBodies,
8086
8127
  networkRequestHeaders: _getMergedNetworkHeaders(networkRequestHeaders),