@atlaskit/react-ufo 5.4.9 → 5.4.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # @atlaskit/ufo-interaction-ignore
2
2
 
3
+ ## 5.4.10
4
+
5
+ ### Patch Changes
6
+
7
+ - [`3d793d41ae6c9`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/3d793d41ae6c9) -
8
+ Add capture-phase scroll detection for container scrollbar drags behind
9
+ platform_ufo_detect_container_scroll feature flag
10
+
3
11
  ## 5.4.9
4
12
 
5
13
  ### Patch Changes
@@ -100,8 +100,9 @@ var VCCalculator_FY25_03 = exports.default = /*#__PURE__*/function (_AbstractVCC
100
100
  var hasAbortEvent = filteredEntries.some(function (entry) {
101
101
  if (entry.data.type === 'window:event') {
102
102
  var data = entry.data;
103
- if (ABORTING_WINDOW_EVENT.includes(data.eventType)) {
104
- dirtyReason = data.eventType === 'keydown' ? 'keypress' : data.eventType;
103
+ var eventType = data.eventType;
104
+ if (ABORTING_WINDOW_EVENT.includes(eventType)) {
105
+ dirtyReason = eventType === 'keydown' ? 'keypress' : eventType;
105
106
  abortTimestamp = Math.round(entry.time);
106
107
  return true;
107
108
  }
@@ -15,6 +15,7 @@ var _fy26_ = _interopRequireDefault(require("../fy26_04"));
15
15
  function _callSuper(t, o, e) { return o = (0, _getPrototypeOf2.default)(o), (0, _possibleConstructorReturn2.default)(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], (0, _getPrototypeOf2.default)(t).constructor) : o.apply(t, e)); }
16
16
  function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }
17
17
  function _superPropGet(t, o, e, r) { var p = (0, _get2.default)((0, _getPrototypeOf2.default)(1 & r ? t.prototype : t), o, e); return 2 & r && "function" == typeof p ? function (t) { return p.apply(e, t); } : p; }
18
+ var ABORTING_WINDOW_EVENT = ['wheel', 'scroll', 'keydown', 'resize', 'scroll-container'];
18
19
  var getConsideredEntryTypes = function getConsideredEntryTypes() {
19
20
  var consideredEntryTypes = [];
20
21
  return consideredEntryTypes;
@@ -38,5 +39,39 @@ var VCCalculator_Next = exports.default = /*#__PURE__*/function (_VCCalculator_F
38
39
  }
39
40
  return getConsideredEntryTypes().includes(entry.data.type);
40
41
  }
42
+ }, {
43
+ key: "getVCCleanStatus",
44
+ value: function getVCCleanStatus(filteredEntries) {
45
+ var dirtyReason = '';
46
+ var abortTimestamp = -1;
47
+ var hasAbortEvent = filteredEntries.some(function (entry) {
48
+ if (entry.data.type === 'window:event') {
49
+ var data = entry.data;
50
+ var eventType = data.eventType;
51
+ if (ABORTING_WINDOW_EVENT.includes(eventType)) {
52
+ if (eventType === 'keydown') {
53
+ dirtyReason = 'keypress';
54
+ } else if (eventType === 'scroll-container') {
55
+ dirtyReason = 'scroll';
56
+ } else {
57
+ dirtyReason = eventType;
58
+ }
59
+ abortTimestamp = Math.round(entry.time);
60
+ return true;
61
+ }
62
+ }
63
+ return false;
64
+ });
65
+ if (hasAbortEvent && dirtyReason) {
66
+ return {
67
+ isVCClean: false,
68
+ dirtyReason: dirtyReason,
69
+ abortTimestamp: abortTimestamp
70
+ };
71
+ }
72
+ return {
73
+ isVCClean: true
74
+ };
75
+ }
41
76
  }]);
42
77
  }(_fy26_.default);
@@ -36,8 +36,9 @@ var RawDataHandler = exports.default = /*#__PURE__*/function () {
36
36
  var hasAbortEvent = filteredEntries.some(function (entry) {
37
37
  if (entry.data.type === 'window:event') {
38
38
  var data = entry.data;
39
- if (ABORTING_WINDOW_EVENT.includes(data.eventType)) {
40
- dirtyReason = data.eventType === 'keydown' ? 'keypress' : data.eventType;
39
+ var eventType = data.eventType;
40
+ if (ABORTING_WINDOW_EVENT.includes(eventType)) {
41
+ dirtyReason = eventType === 'keydown' ? 'keypress' : eventType;
41
42
  abortTimestamp = Math.round(entry.time);
42
43
  return true;
43
44
  }
@@ -9,6 +9,7 @@ var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/cl
9
9
  var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
10
10
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
11
11
  var _bindEventListener = require("bind-event-listener");
12
+ var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
12
13
  var WindowEventObserver = exports.default = /*#__PURE__*/function () {
13
14
  function WindowEventObserver(opts) {
14
15
  (0, _classCallCheck2.default)(this, WindowEventObserver);
@@ -38,6 +39,38 @@ var WindowEventObserver = exports.default = /*#__PURE__*/function () {
38
39
  });
39
40
  this.unbindFns.push(unbindCallback);
40
41
  }
42
+
43
+ /**
44
+ * Binds a scroll listener on `document` using the capture phase.
45
+ * The `scroll` event does not bubble, so listening on `window` only catches
46
+ * document-level scrolls. By using `{ capture: true }` on `document`, we can
47
+ * detect scroll events from any element in the DOM tree, including inner
48
+ * scrollable containers (e.g. when the user drags a scrollbar).
49
+ */
50
+ }, {
51
+ key: "bindCaptureScrollEvent",
52
+ value: function bindCaptureScrollEvent() {
53
+ var _this2 = this;
54
+ var unbindCallback = (0, _bindEventListener.bind)(document, {
55
+ type: 'scroll',
56
+ listener: function listener(event) {
57
+ if (!event.isTrusted) {
58
+ return;
59
+ }
60
+ _this2.onEvent({
61
+ time: event.timeStamp,
62
+ type: 'scroll-container',
63
+ event: event
64
+ });
65
+ },
66
+ options: {
67
+ capture: true,
68
+ passive: true,
69
+ once: true
70
+ }
71
+ });
72
+ this.unbindFns.push(unbindCallback);
73
+ }
41
74
  }, {
42
75
  key: "start",
43
76
  value: function start() {
@@ -45,6 +78,9 @@ var WindowEventObserver = exports.default = /*#__PURE__*/function () {
45
78
  this.bindEvent('scroll');
46
79
  this.bindEvent('keydown');
47
80
  this.bindEvent('resize');
81
+ if ((0, _platformFeatureFlags.fg)('platform_ufo_detect_container_scroll')) {
82
+ this.bindCaptureScrollEvent();
83
+ }
48
84
  }
49
85
  }, {
50
86
  key: "stop",
@@ -80,8 +80,9 @@ export default class VCCalculator_FY25_03 extends AbstractVCCalculatorBase {
80
80
  const hasAbortEvent = filteredEntries.some(entry => {
81
81
  if (entry.data.type === 'window:event') {
82
82
  const data = entry.data;
83
- if (ABORTING_WINDOW_EVENT.includes(data.eventType)) {
84
- dirtyReason = data.eventType === 'keydown' ? 'keypress' : data.eventType;
83
+ const eventType = data.eventType;
84
+ if (ABORTING_WINDOW_EVENT.includes(eventType)) {
85
+ dirtyReason = eventType === 'keydown' ? 'keypress' : eventType;
85
86
  abortTimestamp = Math.round(entry.time);
86
87
  return true;
87
88
  }
@@ -1,4 +1,5 @@
1
1
  import VCCalculator_FY26_04 from '../fy26_04';
2
+ const ABORTING_WINDOW_EVENT = ['wheel', 'scroll', 'keydown', 'resize', 'scroll-container'];
2
3
  const getConsideredEntryTypes = () => {
3
4
  const consideredEntryTypes = [];
4
5
  return consideredEntryTypes;
@@ -18,4 +19,36 @@ export default class VCCalculator_Next extends VCCalculator_FY26_04 {
18
19
  }
19
20
  return getConsideredEntryTypes().includes(entry.data.type);
20
21
  }
22
+ getVCCleanStatus(filteredEntries) {
23
+ let dirtyReason = '';
24
+ let abortTimestamp = -1;
25
+ const hasAbortEvent = filteredEntries.some(entry => {
26
+ if (entry.data.type === 'window:event') {
27
+ const data = entry.data;
28
+ const eventType = data.eventType;
29
+ if (ABORTING_WINDOW_EVENT.includes(eventType)) {
30
+ if (eventType === 'keydown') {
31
+ dirtyReason = 'keypress';
32
+ } else if (eventType === 'scroll-container') {
33
+ dirtyReason = 'scroll';
34
+ } else {
35
+ dirtyReason = eventType;
36
+ }
37
+ abortTimestamp = Math.round(entry.time);
38
+ return true;
39
+ }
40
+ }
41
+ return false;
42
+ });
43
+ if (hasAbortEvent && dirtyReason) {
44
+ return {
45
+ isVCClean: false,
46
+ dirtyReason,
47
+ abortTimestamp
48
+ };
49
+ }
50
+ return {
51
+ isVCClean: true
52
+ };
53
+ }
21
54
  }
@@ -16,8 +16,9 @@ export default class RawDataHandler {
16
16
  const hasAbortEvent = filteredEntries.some(entry => {
17
17
  if (entry.data.type === 'window:event') {
18
18
  const data = entry.data;
19
- if (ABORTING_WINDOW_EVENT.includes(data.eventType)) {
20
- dirtyReason = data.eventType === 'keydown' ? 'keypress' : data.eventType;
19
+ const eventType = data.eventType;
20
+ if (ABORTING_WINDOW_EVENT.includes(eventType)) {
21
+ dirtyReason = eventType === 'keydown' ? 'keypress' : eventType;
21
22
  abortTimestamp = Math.round(entry.time);
22
23
  return true;
23
24
  }
@@ -1,5 +1,6 @@
1
1
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
2
  import { bind } from 'bind-event-listener';
3
+ import { fg } from '@atlaskit/platform-feature-flags';
3
4
  export default class WindowEventObserver {
4
5
  constructor(opts) {
5
6
  _defineProperty(this, "unbindFns", []);
@@ -25,11 +26,43 @@ export default class WindowEventObserver {
25
26
  });
26
27
  this.unbindFns.push(unbindCallback);
27
28
  }
29
+
30
+ /**
31
+ * Binds a scroll listener on `document` using the capture phase.
32
+ * The `scroll` event does not bubble, so listening on `window` only catches
33
+ * document-level scrolls. By using `{ capture: true }` on `document`, we can
34
+ * detect scroll events from any element in the DOM tree, including inner
35
+ * scrollable containers (e.g. when the user drags a scrollbar).
36
+ */
37
+ bindCaptureScrollEvent() {
38
+ const unbindCallback = bind(document, {
39
+ type: 'scroll',
40
+ listener: event => {
41
+ if (!event.isTrusted) {
42
+ return;
43
+ }
44
+ this.onEvent({
45
+ time: event.timeStamp,
46
+ type: 'scroll-container',
47
+ event
48
+ });
49
+ },
50
+ options: {
51
+ capture: true,
52
+ passive: true,
53
+ once: true
54
+ }
55
+ });
56
+ this.unbindFns.push(unbindCallback);
57
+ }
28
58
  start() {
29
59
  this.bindEvent('wheel');
30
60
  this.bindEvent('scroll');
31
61
  this.bindEvent('keydown');
32
62
  this.bindEvent('resize');
63
+ if (fg('platform_ufo_detect_container_scroll')) {
64
+ this.bindCaptureScrollEvent();
65
+ }
33
66
  }
34
67
  stop() {
35
68
  this.unbindFns.forEach(cb => {
@@ -93,8 +93,9 @@ var VCCalculator_FY25_03 = /*#__PURE__*/function (_AbstractVCCalculator) {
93
93
  var hasAbortEvent = filteredEntries.some(function (entry) {
94
94
  if (entry.data.type === 'window:event') {
95
95
  var data = entry.data;
96
- if (ABORTING_WINDOW_EVENT.includes(data.eventType)) {
97
- dirtyReason = data.eventType === 'keydown' ? 'keypress' : data.eventType;
96
+ var eventType = data.eventType;
97
+ if (ABORTING_WINDOW_EVENT.includes(eventType)) {
98
+ dirtyReason = eventType === 'keydown' ? 'keypress' : eventType;
98
99
  abortTimestamp = Math.round(entry.time);
99
100
  return true;
100
101
  }
@@ -8,6 +8,7 @@ function _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstruct
8
8
  function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }
9
9
  function _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && "function" == typeof p ? function (t) { return p.apply(e, t); } : p; }
10
10
  import VCCalculator_FY26_04 from '../fy26_04';
11
+ var ABORTING_WINDOW_EVENT = ['wheel', 'scroll', 'keydown', 'resize', 'scroll-container'];
11
12
  var getConsideredEntryTypes = function getConsideredEntryTypes() {
12
13
  var consideredEntryTypes = [];
13
14
  return consideredEntryTypes;
@@ -31,6 +32,40 @@ var VCCalculator_Next = /*#__PURE__*/function (_VCCalculator_FY26_) {
31
32
  }
32
33
  return getConsideredEntryTypes().includes(entry.data.type);
33
34
  }
35
+ }, {
36
+ key: "getVCCleanStatus",
37
+ value: function getVCCleanStatus(filteredEntries) {
38
+ var dirtyReason = '';
39
+ var abortTimestamp = -1;
40
+ var hasAbortEvent = filteredEntries.some(function (entry) {
41
+ if (entry.data.type === 'window:event') {
42
+ var data = entry.data;
43
+ var eventType = data.eventType;
44
+ if (ABORTING_WINDOW_EVENT.includes(eventType)) {
45
+ if (eventType === 'keydown') {
46
+ dirtyReason = 'keypress';
47
+ } else if (eventType === 'scroll-container') {
48
+ dirtyReason = 'scroll';
49
+ } else {
50
+ dirtyReason = eventType;
51
+ }
52
+ abortTimestamp = Math.round(entry.time);
53
+ return true;
54
+ }
55
+ }
56
+ return false;
57
+ });
58
+ if (hasAbortEvent && dirtyReason) {
59
+ return {
60
+ isVCClean: false,
61
+ dirtyReason: dirtyReason,
62
+ abortTimestamp: abortTimestamp
63
+ };
64
+ }
65
+ return {
66
+ isVCClean: true
67
+ };
68
+ }
34
69
  }]);
35
70
  }(VCCalculator_FY26_04);
36
71
  export { VCCalculator_Next as default };
@@ -29,8 +29,9 @@ var RawDataHandler = /*#__PURE__*/function () {
29
29
  var hasAbortEvent = filteredEntries.some(function (entry) {
30
30
  if (entry.data.type === 'window:event') {
31
31
  var data = entry.data;
32
- if (ABORTING_WINDOW_EVENT.includes(data.eventType)) {
33
- dirtyReason = data.eventType === 'keydown' ? 'keypress' : data.eventType;
32
+ var eventType = data.eventType;
33
+ if (ABORTING_WINDOW_EVENT.includes(eventType)) {
34
+ dirtyReason = eventType === 'keydown' ? 'keypress' : eventType;
34
35
  abortTimestamp = Math.round(entry.time);
35
36
  return true;
36
37
  }
@@ -2,6 +2,7 @@ import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
2
2
  import _createClass from "@babel/runtime/helpers/createClass";
3
3
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
4
4
  import { bind } from 'bind-event-listener';
5
+ import { fg } from '@atlaskit/platform-feature-flags';
5
6
  var WindowEventObserver = /*#__PURE__*/function () {
6
7
  function WindowEventObserver(opts) {
7
8
  _classCallCheck(this, WindowEventObserver);
@@ -31,6 +32,38 @@ var WindowEventObserver = /*#__PURE__*/function () {
31
32
  });
32
33
  this.unbindFns.push(unbindCallback);
33
34
  }
35
+
36
+ /**
37
+ * Binds a scroll listener on `document` using the capture phase.
38
+ * The `scroll` event does not bubble, so listening on `window` only catches
39
+ * document-level scrolls. By using `{ capture: true }` on `document`, we can
40
+ * detect scroll events from any element in the DOM tree, including inner
41
+ * scrollable containers (e.g. when the user drags a scrollbar).
42
+ */
43
+ }, {
44
+ key: "bindCaptureScrollEvent",
45
+ value: function bindCaptureScrollEvent() {
46
+ var _this2 = this;
47
+ var unbindCallback = bind(document, {
48
+ type: 'scroll',
49
+ listener: function listener(event) {
50
+ if (!event.isTrusted) {
51
+ return;
52
+ }
53
+ _this2.onEvent({
54
+ time: event.timeStamp,
55
+ type: 'scroll-container',
56
+ event: event
57
+ });
58
+ },
59
+ options: {
60
+ capture: true,
61
+ passive: true,
62
+ once: true
63
+ }
64
+ });
65
+ this.unbindFns.push(unbindCallback);
66
+ }
34
67
  }, {
35
68
  key: "start",
36
69
  value: function start() {
@@ -38,6 +71,9 @@ var WindowEventObserver = /*#__PURE__*/function () {
38
71
  this.bindEvent('scroll');
39
72
  this.bindEvent('keydown');
40
73
  this.bindEvent('resize');
74
+ if (fg('platform_ufo_detect_container_scroll')) {
75
+ this.bindCaptureScrollEvent();
76
+ }
41
77
  }
42
78
  }, {
43
79
  key: "stop",
@@ -3,4 +3,13 @@ import VCCalculator_FY26_04 from '../fy26_04';
3
3
  export default class VCCalculator_Next extends VCCalculator_FY26_04 {
4
4
  constructor();
5
5
  protected isEntryIncluded(entry: VCObserverEntry, include3p?: boolean, excludeSmartAnswersInSearch?: boolean): boolean;
6
+ protected getVCCleanStatus(filteredEntries: readonly VCObserverEntry[]): {
7
+ isVCClean: boolean;
8
+ dirtyReason: never;
9
+ abortTimestamp: number;
10
+ } | {
11
+ isVCClean: boolean;
12
+ dirtyReason?: undefined;
13
+ abortTimestamp?: undefined;
14
+ };
6
15
  }
@@ -1,5 +1,5 @@
1
1
  import type { AbortReasonType, InteractionType } from '../../common/common/types';
2
- import type { ObservedWindowEvent } from './window-event-observer';
2
+ import type { ObservedWindowEventExtended } from './window-event-observer';
3
3
  export type VCObserverEntryType = 'mutation:child-element' | 'mutation:remount' | 'mutation:element' | 'mutation:element-replacement' | 'mutation:display-contents-children-element' | 'mutation:display-contents-children-attribute' | 'mutation:attribute:no-layout-shift' | 'mutation:attribute:non-visual-style' | 'mutation:attribute:non-visual-input-name' | 'mutation:attribute:framework-routing' | 'mutation:attribute' | 'mutation:media' | 'mutation:rll-placeholder' | 'mutation:third-party-element' | 'mutation:third-party-attribute' | 'mutation:smart-answers-element' | 'mutation:smart-answers-attribute' | 'mutation:ssr-placeholder' | 'layout-shift' | 'layout-shift:same-rect' | 'window:event' | 'ssr-hydration' | 'unknown';
4
4
  export type ViewportEntryData = {
5
5
  readonly type: VCObserverEntryType;
@@ -19,7 +19,7 @@ export type VCObserverLabelStacks = {
19
19
  };
20
20
  export type WindowEventEntryData = {
21
21
  readonly type: VCObserverEntryType;
22
- readonly eventType: ObservedWindowEvent;
22
+ readonly eventType: ObservedWindowEventExtended;
23
23
  };
24
24
  export type VCObserverEntry = {
25
25
  readonly time: DOMHighResTimeStamp;
@@ -1,7 +1,8 @@
1
1
  export type ObservedWindowEvent = 'wheel' | 'scroll' | 'keydown' | 'resize';
2
+ export type ObservedWindowEventExtended = ObservedWindowEvent | 'scroll-container';
2
3
  export type OnEventCallback = (args: {
3
4
  time: DOMHighResTimeStamp;
4
- type: ObservedWindowEvent;
5
+ type: ObservedWindowEventExtended;
5
6
  event: Event;
6
7
  }) => void;
7
8
  export type WindowEventObserverOptions = {
@@ -12,6 +13,14 @@ export default class WindowEventObserver {
12
13
  private onEvent;
13
14
  constructor(opts: WindowEventObserverOptions);
14
15
  private bindEvent;
16
+ /**
17
+ * Binds a scroll listener on `document` using the capture phase.
18
+ * The `scroll` event does not bubble, so listening on `window` only catches
19
+ * document-level scrolls. By using `{ capture: true }` on `document`, we can
20
+ * detect scroll events from any element in the DOM tree, including inner
21
+ * scrollable containers (e.g. when the user drags a scrollbar).
22
+ */
23
+ private bindCaptureScrollEvent;
15
24
  start(): void;
16
25
  stop(): void;
17
26
  }
@@ -3,4 +3,13 @@ import VCCalculator_FY26_04 from '../fy26_04';
3
3
  export default class VCCalculator_Next extends VCCalculator_FY26_04 {
4
4
  constructor();
5
5
  protected isEntryIncluded(entry: VCObserverEntry, include3p?: boolean, excludeSmartAnswersInSearch?: boolean): boolean;
6
+ protected getVCCleanStatus(filteredEntries: readonly VCObserverEntry[]): {
7
+ isVCClean: boolean;
8
+ dirtyReason: never;
9
+ abortTimestamp: number;
10
+ } | {
11
+ isVCClean: boolean;
12
+ dirtyReason?: undefined;
13
+ abortTimestamp?: undefined;
14
+ };
6
15
  }
@@ -1,5 +1,5 @@
1
1
  import type { AbortReasonType, InteractionType } from '../../common/common/types';
2
- import type { ObservedWindowEvent } from './window-event-observer';
2
+ import type { ObservedWindowEventExtended } from './window-event-observer';
3
3
  export type VCObserverEntryType = 'mutation:child-element' | 'mutation:remount' | 'mutation:element' | 'mutation:element-replacement' | 'mutation:display-contents-children-element' | 'mutation:display-contents-children-attribute' | 'mutation:attribute:no-layout-shift' | 'mutation:attribute:non-visual-style' | 'mutation:attribute:non-visual-input-name' | 'mutation:attribute:framework-routing' | 'mutation:attribute' | 'mutation:media' | 'mutation:rll-placeholder' | 'mutation:third-party-element' | 'mutation:third-party-attribute' | 'mutation:smart-answers-element' | 'mutation:smart-answers-attribute' | 'mutation:ssr-placeholder' | 'layout-shift' | 'layout-shift:same-rect' | 'window:event' | 'ssr-hydration' | 'unknown';
4
4
  export type ViewportEntryData = {
5
5
  readonly type: VCObserverEntryType;
@@ -19,7 +19,7 @@ export type VCObserverLabelStacks = {
19
19
  };
20
20
  export type WindowEventEntryData = {
21
21
  readonly type: VCObserverEntryType;
22
- readonly eventType: ObservedWindowEvent;
22
+ readonly eventType: ObservedWindowEventExtended;
23
23
  };
24
24
  export type VCObserverEntry = {
25
25
  readonly time: DOMHighResTimeStamp;
@@ -1,7 +1,8 @@
1
1
  export type ObservedWindowEvent = 'wheel' | 'scroll' | 'keydown' | 'resize';
2
+ export type ObservedWindowEventExtended = ObservedWindowEvent | 'scroll-container';
2
3
  export type OnEventCallback = (args: {
3
4
  time: DOMHighResTimeStamp;
4
- type: ObservedWindowEvent;
5
+ type: ObservedWindowEventExtended;
5
6
  event: Event;
6
7
  }) => void;
7
8
  export type WindowEventObserverOptions = {
@@ -12,6 +13,14 @@ export default class WindowEventObserver {
12
13
  private onEvent;
13
14
  constructor(opts: WindowEventObserverOptions);
14
15
  private bindEvent;
16
+ /**
17
+ * Binds a scroll listener on `document` using the capture phase.
18
+ * The `scroll` event does not bubble, so listening on `window` only catches
19
+ * document-level scrolls. By using `{ capture: true }` on `document`, we can
20
+ * detect scroll events from any element in the DOM tree, including inner
21
+ * scrollable containers (e.g. when the user drags a scrollbar).
22
+ */
23
+ private bindCaptureScrollEvent;
15
24
  start(): void;
16
25
  stop(): void;
17
26
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/react-ufo",
3
- "version": "5.4.9",
3
+ "version": "5.4.10",
4
4
  "description": "Parts of React UFO that are publicly available",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",
@@ -214,6 +214,9 @@
214
214
  },
215
215
  "platform_ufo_exclude_dark_reader_extension": {
216
216
  "type": "boolean"
217
+ },
218
+ "platform_ufo_detect_container_scroll": {
219
+ "type": "boolean"
217
220
  }
218
221
  }
219
222
  }