@atlaskit/react-select 2.3.0 → 2.4.0

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 (27) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/cjs/components/menu.js +5 -225
  3. package/dist/cjs/emotion/components/internal/index.js +34 -0
  4. package/dist/cjs/emotion/components/internal/scroll-manager.js +59 -0
  5. package/dist/cjs/emotion/components/internal/use-scroll-capture.js +132 -0
  6. package/dist/cjs/emotion/components/internal/use-scroll-lock.js +149 -0
  7. package/dist/es2019/components/menu.js +4 -224
  8. package/dist/es2019/emotion/components/internal/index.js +4 -0
  9. package/dist/es2019/emotion/components/internal/scroll-manager.js +51 -0
  10. package/dist/es2019/emotion/components/internal/use-scroll-capture.js +128 -0
  11. package/dist/es2019/emotion/components/internal/use-scroll-lock.js +143 -0
  12. package/dist/esm/components/menu.js +6 -228
  13. package/dist/esm/emotion/components/internal/index.js +4 -0
  14. package/dist/esm/emotion/components/internal/scroll-manager.js +51 -0
  15. package/dist/esm/emotion/components/internal/use-scroll-capture.js +126 -0
  16. package/dist/esm/emotion/components/internal/use-scroll-lock.js +143 -0
  17. package/dist/types/components/menu.d.ts +1 -1
  18. package/dist/types/emotion/components/internal/index.d.ts +4 -0
  19. package/dist/types/emotion/components/internal/scroll-manager.d.ts +17 -0
  20. package/dist/types/emotion/components/internal/use-scroll-capture.d.ts +12 -0
  21. package/dist/types/emotion/components/internal/use-scroll-lock.d.ts +9 -0
  22. package/dist/types-ts4.5/components/menu.d.ts +1 -1
  23. package/dist/types-ts4.5/emotion/components/internal/index.d.ts +4 -0
  24. package/dist/types-ts4.5/emotion/components/internal/scroll-manager.d.ts +17 -0
  25. package/dist/types-ts4.5/emotion/components/internal/use-scroll-capture.d.ts +12 -0
  26. package/dist/types-ts4.5/emotion/components/internal/use-scroll-lock.d.ts +9 -0
  27. package/package.json +2 -2
package/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # @atlaskit/react-select
2
2
 
3
+ ## 2.4.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#141922](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/pull-requests/141922)
8
+ [`a48b38cffa7e6`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/a48b38cffa7e6) -
9
+ Create a compiled select and use feature flag to toggle it
10
+
11
+ ### Patch Changes
12
+
13
+ - [#141922](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/pull-requests/141922)
14
+ [`a48b38cffa7e6`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/a48b38cffa7e6) -
15
+ Migrate emotion components to compiled components under compiled folder
16
+
3
17
  ## 2.3.0
4
18
 
5
19
  ### Minor Changes
@@ -7,245 +7,25 @@ Object.defineProperty(exports, "__esModule", {
7
7
  });
8
8
  exports.noOptionsMessageCSS = exports.menuPortalCSS = exports.menuListCSS = exports.menuCSS = exports.loadingMessageCSS = exports.default = exports.NoOptionsMessage = exports.MenuPortal = exports.MenuPlacer = exports.MenuList = exports.LoadingMessage = void 0;
9
9
  var _objectDestructuringEmpty2 = _interopRequireDefault(require("@babel/runtime/helpers/objectDestructuringEmpty"));
10
- var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
11
- var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
12
- var _react = _interopRequireWildcard(require("react"));
13
- var _useIsomorphicLayoutEffect = _interopRequireDefault(require("use-isomorphic-layout-effect"));
10
+ var _react = _interopRequireDefault(require("react"));
14
11
  var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
15
12
  var _menu = _interopRequireWildcard(require("../compiled/components/menu"));
16
13
  var _menu2 = _interopRequireWildcard(require("../emotion/components/menu"));
17
- var _utils = require("../utils");
18
14
  function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); }
19
15
  function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != _typeof(e) && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
20
- function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
21
- function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } /* eslint-disable @repo/internal/react/no-unsafe-spread-props */
22
- // ==============================
23
- // Menu
24
- // ==============================
25
-
26
- // Get Menu Placement
27
- // ------------------------------
28
-
29
- function getMenuPlacement(_ref) {
30
- var preferredMaxHeight = _ref.maxHeight,
31
- menuEl = _ref.menuEl,
32
- minHeight = _ref.minHeight,
33
- preferredPlacement = _ref.placement,
34
- shouldScroll = _ref.shouldScroll,
35
- isFixedPosition = _ref.isFixedPosition,
36
- controlHeight = _ref.controlHeight;
37
- var scrollParent = (0, _utils.getScrollParent)(menuEl);
38
- var defaultState = {
39
- placement: 'bottom',
40
- maxHeight: preferredMaxHeight
41
- };
42
-
43
- // something went wrong, return default state
44
- if (!menuEl || !menuEl.offsetParent) {
45
- return defaultState;
46
- }
47
-
48
- // we can't trust `scrollParent.scrollHeight` --> it may increase when
49
- // the menu is rendered
50
- var _scrollParent$getBoun = scrollParent.getBoundingClientRect(),
51
- scrollHeight = _scrollParent$getBoun.height,
52
- scrollParentTop = _scrollParent$getBoun.top;
53
- var _menuEl$getBoundingCl = menuEl.getBoundingClientRect(),
54
- menuBottom = _menuEl$getBoundingCl.bottom,
55
- menuHeight = _menuEl$getBoundingCl.height,
56
- menuTop = _menuEl$getBoundingCl.top;
57
- var _menuEl$offsetParent$ = menuEl.offsetParent.getBoundingClientRect(),
58
- containerTop = _menuEl$offsetParent$.top;
59
- var viewHeight = isFixedPosition ? window.innerHeight : (0, _utils.normalizedHeight)(scrollParent);
60
- var scrollTop = (0, _utils.getScrollTop)(scrollParent);
61
- // use menuTop - scrollParentTop for the actual top space of menu in the scroll container
62
- var menuTopFromParent = (0, _platformFeatureFlags.fg)('design-system-select-fix-placement') ? menuTop - scrollParentTop : menuTop;
63
- var marginBottom = parseInt(getComputedStyle(menuEl).marginBottom, 10);
64
- var marginTop = parseInt(getComputedStyle(menuEl).marginTop, 10);
65
- var viewSpaceAbove = containerTop - marginTop;
66
- var viewSpaceBelow = viewHeight - menuTopFromParent;
67
- var scrollSpaceAbove = viewSpaceAbove + scrollTop;
68
- var scrollSpaceBelow = scrollHeight - scrollTop - menuTopFromParent;
69
- var scrollDown = menuBottom - viewHeight + scrollTop + marginBottom;
70
- var scrollUp = scrollTop + menuTop - marginTop;
71
- var scrollDuration = 160;
72
- switch (preferredPlacement) {
73
- case 'auto':
74
- case 'bottom':
75
- // 1: the menu will fit, do nothing
76
- if (viewSpaceBelow >= menuHeight) {
77
- return {
78
- placement: 'bottom',
79
- maxHeight: preferredMaxHeight
80
- };
81
- }
82
-
83
- // 2: the menu will fit, if scrolled
84
- if (scrollSpaceBelow >= menuHeight && !isFixedPosition) {
85
- if (shouldScroll) {
86
- (0, _utils.animatedScrollTo)(scrollParent, scrollDown, scrollDuration);
87
- }
88
- return {
89
- placement: 'bottom',
90
- maxHeight: preferredMaxHeight
91
- };
92
- }
93
-
94
- // 3: the menu will fit, if constrained
95
- if (!isFixedPosition && scrollSpaceBelow >= minHeight || isFixedPosition && viewSpaceBelow >= minHeight) {
96
- if (shouldScroll) {
97
- (0, _utils.animatedScrollTo)(scrollParent, scrollDown, scrollDuration);
98
- }
99
-
100
- // we want to provide as much of the menu as possible to the user,
101
- // so give them whatever is available below rather than the minHeight.
102
- var constrainedHeight = isFixedPosition ? viewSpaceBelow - marginBottom : scrollSpaceBelow - marginBottom;
103
- return {
104
- placement: 'bottom',
105
- maxHeight: constrainedHeight
106
- };
107
- }
108
-
109
- // 4. Forked beviour when there isn't enough space below
110
-
111
- // AUTO: flip the menu, render above
112
- if (preferredPlacement === 'auto' || isFixedPosition) {
113
- // may need to be constrained after flipping
114
- var _constrainedHeight = preferredMaxHeight;
115
- var spaceAbove = isFixedPosition ? viewSpaceAbove : scrollSpaceAbove;
116
- if (spaceAbove >= minHeight) {
117
- _constrainedHeight = Math.min(spaceAbove - marginBottom - controlHeight, preferredMaxHeight);
118
- }
119
- return {
120
- placement: 'top',
121
- maxHeight: _constrainedHeight
122
- };
123
- }
124
-
125
- // BOTTOM: allow browser to increase scrollable area and immediately set scroll
126
- if (preferredPlacement === 'bottom') {
127
- if (shouldScroll) {
128
- (0, _utils.scrollTo)(scrollParent, scrollDown);
129
- }
130
- return {
131
- placement: 'bottom',
132
- maxHeight: preferredMaxHeight
133
- };
134
- }
135
- break;
136
- case 'top':
137
- // 1: the menu will fit, do nothing
138
- if (viewSpaceAbove >= menuHeight) {
139
- return {
140
- placement: 'top',
141
- maxHeight: preferredMaxHeight
142
- };
143
- }
144
-
145
- // 2: the menu will fit, if scrolled
146
- if (scrollSpaceAbove >= menuHeight && !isFixedPosition) {
147
- if (shouldScroll) {
148
- (0, _utils.animatedScrollTo)(scrollParent, scrollUp, scrollDuration);
149
- }
150
- return {
151
- placement: 'top',
152
- maxHeight: preferredMaxHeight
153
- };
154
- }
155
-
156
- // 3: the menu will fit, if constrained
157
- if (!isFixedPosition && scrollSpaceAbove >= minHeight || isFixedPosition && viewSpaceAbove >= minHeight) {
158
- var _constrainedHeight2 = preferredMaxHeight;
159
-
160
- // we want to provide as much of the menu as possible to the user,
161
- // so give them whatever is available below rather than the minHeight.
162
- if (!isFixedPosition && scrollSpaceAbove >= minHeight || isFixedPosition && viewSpaceAbove >= minHeight) {
163
- _constrainedHeight2 = isFixedPosition ? viewSpaceAbove - marginTop : scrollSpaceAbove - marginTop;
164
- }
165
- if (shouldScroll) {
166
- (0, _utils.animatedScrollTo)(scrollParent, scrollUp, scrollDuration);
167
- }
168
- return {
169
- placement: 'top',
170
- maxHeight: _constrainedHeight2
171
- };
172
- }
173
-
174
- // 4. not enough space, the browser WILL NOT increase scrollable area when
175
- // absolutely positioned element rendered above the viewport (only below).
176
- // Flip the menu, render below
177
- return {
178
- placement: 'bottom',
179
- maxHeight: preferredMaxHeight
180
- };
181
- default:
182
- throw new Error("Invalid placement provided \"".concat(preferredPlacement, "\"."));
183
- }
184
- return defaultState;
185
- }
16
+ /* eslint-disable @repo/internal/react/no-unsafe-spread-props */
186
17
 
187
18
  // Menu Component
188
19
  // ------------------------------
189
20
 
190
- var coercePlacement = function coercePlacement(p) {
191
- return p === 'auto' ? 'bottom' : p;
192
- };
193
21
  var menuCSS = exports.menuCSS = function menuCSS(props) {
194
22
  return (0, _platformFeatureFlags.fg)('compiled-react-select') ? (0, _menu.menuCSS)() : (0, _menu2.menuCSS)(props);
195
23
  };
196
- var PortalPlacementContext = /*#__PURE__*/(0, _react.createContext)(null);
197
24
 
198
25
  // NOTE: internal only
199
26
  // eslint-disable-next-line @repo/internal/react/require-jsdoc
200
27
  var MenuPlacer = exports.MenuPlacer = function MenuPlacer(props) {
201
- var children = props.children,
202
- minMenuHeight = props.minMenuHeight,
203
- maxMenuHeight = props.maxMenuHeight,
204
- menuPlacement = props.menuPlacement,
205
- menuPosition = props.menuPosition,
206
- menuShouldScrollIntoView = props.menuShouldScrollIntoView;
207
- var _ref2 = (0, _react.useContext)(PortalPlacementContext) || {},
208
- setPortalPlacement = _ref2.setPortalPlacement;
209
- var ref = (0, _react.useRef)(null);
210
- var _useState = (0, _react.useState)(maxMenuHeight),
211
- _useState2 = (0, _slicedToArray2.default)(_useState, 2),
212
- maxHeight = _useState2[0],
213
- setMaxHeight = _useState2[1];
214
- var _useState3 = (0, _react.useState)(null),
215
- _useState4 = (0, _slicedToArray2.default)(_useState3, 2),
216
- placement = _useState4[0],
217
- setPlacement = _useState4[1];
218
- // The minimum height of the control
219
- var controlHeight = 38;
220
- (0, _useIsomorphicLayoutEffect.default)(function () {
221
- var menuEl = ref.current;
222
- if (!menuEl) {
223
- return;
224
- }
225
-
226
- // DO NOT scroll if position is fixed
227
- var isFixedPosition = menuPosition === 'fixed';
228
- var shouldScroll = menuShouldScrollIntoView && !isFixedPosition;
229
- var state = getMenuPlacement({
230
- maxHeight: maxMenuHeight,
231
- menuEl: menuEl,
232
- minHeight: minMenuHeight,
233
- placement: menuPlacement,
234
- shouldScroll: shouldScroll,
235
- isFixedPosition: isFixedPosition,
236
- controlHeight: controlHeight
237
- });
238
- setMaxHeight(state.maxHeight);
239
- setPlacement(state.placement);
240
- setPortalPlacement === null || setPortalPlacement === void 0 || setPortalPlacement(state.placement);
241
- }, [maxMenuHeight, menuPlacement, menuPosition, menuShouldScrollIntoView, minMenuHeight, setPortalPlacement, controlHeight]);
242
- return children({
243
- ref: ref,
244
- placerProps: _objectSpread(_objectSpread({}, props), {}, {
245
- placement: placement || coercePlacement(menuPlacement),
246
- maxHeight: maxHeight
247
- })
248
- });
28
+ return (0, _platformFeatureFlags.fg)('compiled-react-select') ? /*#__PURE__*/_react.default.createElement(_menu.MenuPlacer, props) : /*#__PURE__*/_react.default.createElement(_menu2.MenuPlacer, props);
249
29
  };
250
30
  var Menu = function Menu(props) {
251
31
  return (0, _platformFeatureFlags.fg)('compiled-react-select') ? /*#__PURE__*/_react.default.createElement(_menu.default, props) : /*#__PURE__*/_react.default.createElement(_menu2.default, props);
@@ -268,8 +48,8 @@ var MenuList = exports.MenuList = function MenuList(props) {
268
48
  // Menu Notices
269
49
  // ==============================
270
50
 
271
- var noticeCSS = function noticeCSS(_ref3) {
272
- (0, _objectDestructuringEmpty2.default)(_ref3);
51
+ var noticeCSS = function noticeCSS(_ref) {
52
+ (0, _objectDestructuringEmpty2.default)(_ref);
273
53
  return {
274
54
  textAlign: 'center',
275
55
  padding: "var(--ds-space-100, 8px)".concat(" ", "var(--ds-space-150, 12px)")
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ Object.defineProperty(exports, "A11yText", {
8
+ enumerable: true,
9
+ get: function get() {
10
+ return _a11yText.default;
11
+ }
12
+ });
13
+ Object.defineProperty(exports, "DummyInput", {
14
+ enumerable: true,
15
+ get: function get() {
16
+ return _dummyInput.default;
17
+ }
18
+ });
19
+ Object.defineProperty(exports, "RequiredInput", {
20
+ enumerable: true,
21
+ get: function get() {
22
+ return _requiredInput.default;
23
+ }
24
+ });
25
+ Object.defineProperty(exports, "ScrollManager", {
26
+ enumerable: true,
27
+ get: function get() {
28
+ return _scrollManager.default;
29
+ }
30
+ });
31
+ var _a11yText = _interopRequireDefault(require("./a11y-text"));
32
+ var _dummyInput = _interopRequireDefault(require("./dummy-input"));
33
+ var _scrollManager = _interopRequireDefault(require("./scroll-manager"));
34
+ var _requiredInput = _interopRequireDefault(require("./required-input"));
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.default = ScrollManager;
8
+ var _react = require("react");
9
+ var _react2 = require("@emotion/react");
10
+ var _useScrollCapture = _interopRequireDefault(require("./use-scroll-capture"));
11
+ var _useScrollLock = _interopRequireDefault(require("./use-scroll-lock"));
12
+ /**
13
+ * @jsxRuntime classic
14
+ * @jsx jsx
15
+ */
16
+
17
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled
18
+
19
+ var styles = (0, _react2.css)({
20
+ position: 'fixed',
21
+ insetBlockEnd: 0,
22
+ insetBlockStart: 0,
23
+ insetInlineEnd: 0,
24
+ insetInlineStart: 0
25
+ });
26
+ var blurSelectInput = function blurSelectInput(event) {
27
+ var element = event.target;
28
+ return element.ownerDocument.activeElement && element.ownerDocument.activeElement.blur();
29
+ };
30
+ function ScrollManager(_ref) {
31
+ var children = _ref.children,
32
+ lockEnabled = _ref.lockEnabled,
33
+ _ref$captureEnabled = _ref.captureEnabled,
34
+ captureEnabled = _ref$captureEnabled === void 0 ? true : _ref$captureEnabled,
35
+ onBottomArrive = _ref.onBottomArrive,
36
+ onBottomLeave = _ref.onBottomLeave,
37
+ onTopArrive = _ref.onTopArrive,
38
+ onTopLeave = _ref.onTopLeave;
39
+ var setScrollCaptureTarget = (0, _useScrollCapture.default)({
40
+ isEnabled: captureEnabled,
41
+ onBottomArrive: onBottomArrive,
42
+ onBottomLeave: onBottomLeave,
43
+ onTopArrive: onTopArrive,
44
+ onTopLeave: onTopLeave
45
+ });
46
+ var setScrollLockTarget = (0, _useScrollLock.default)({
47
+ isEnabled: lockEnabled
48
+ });
49
+ var targetRef = function targetRef(element) {
50
+ setScrollCaptureTarget(element);
51
+ setScrollLockTarget(element);
52
+ };
53
+ return (0, _react2.jsx)(_react.Fragment, null, lockEnabled &&
54
+ // eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions
55
+ (0, _react2.jsx)("div", {
56
+ onClick: blurSelectInput,
57
+ css: styles
58
+ }), children(targetRef));
59
+ }
@@ -0,0 +1,132 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = useScrollCapture;
7
+ var _react = require("react");
8
+ var _utils = require("../../../utils");
9
+ var cancelScroll = function cancelScroll(event) {
10
+ if (event.cancelable) {
11
+ event.preventDefault();
12
+ }
13
+ event.stopPropagation();
14
+ };
15
+ // TODO: Fill in the hook {description}.
16
+ /**
17
+ * {description}.
18
+ */
19
+ function useScrollCapture(_ref) {
20
+ var isEnabled = _ref.isEnabled,
21
+ onBottomArrive = _ref.onBottomArrive,
22
+ onBottomLeave = _ref.onBottomLeave,
23
+ onTopArrive = _ref.onTopArrive,
24
+ onTopLeave = _ref.onTopLeave;
25
+ var isBottom = (0, _react.useRef)(false);
26
+ var isTop = (0, _react.useRef)(false);
27
+ var touchStart = (0, _react.useRef)(0);
28
+ var scrollTarget = (0, _react.useRef)(null);
29
+ var handleEventDelta = (0, _react.useCallback)(function (event, delta) {
30
+ if (scrollTarget.current === null) {
31
+ return;
32
+ }
33
+ var _scrollTarget$current = scrollTarget.current,
34
+ scrollTop = _scrollTarget$current.scrollTop,
35
+ scrollHeight = _scrollTarget$current.scrollHeight,
36
+ clientHeight = _scrollTarget$current.clientHeight;
37
+ var target = scrollTarget.current;
38
+ var isDeltaPositive = delta > 0;
39
+ var availableScroll = scrollHeight - clientHeight - scrollTop;
40
+ var shouldCancelScroll = false;
41
+
42
+ // reset bottom/top flags
43
+ if (availableScroll > delta && isBottom.current) {
44
+ if (onBottomLeave) {
45
+ onBottomLeave(event);
46
+ }
47
+ isBottom.current = false;
48
+ }
49
+ if (isDeltaPositive && isTop.current) {
50
+ if (onTopLeave) {
51
+ onTopLeave(event);
52
+ }
53
+ isTop.current = false;
54
+ }
55
+
56
+ // bottom limit
57
+ if (isDeltaPositive && delta > availableScroll) {
58
+ if (onBottomArrive && !isBottom.current) {
59
+ onBottomArrive(event);
60
+ }
61
+ target.scrollTop = scrollHeight;
62
+ shouldCancelScroll = true;
63
+ isBottom.current = true;
64
+
65
+ // top limit
66
+ } else if (!isDeltaPositive && -delta > scrollTop) {
67
+ if (onTopArrive && !isTop.current) {
68
+ onTopArrive(event);
69
+ }
70
+ target.scrollTop = 0;
71
+ shouldCancelScroll = true;
72
+ isTop.current = true;
73
+ }
74
+
75
+ // cancel scroll
76
+ if (shouldCancelScroll) {
77
+ cancelScroll(event);
78
+ }
79
+ }, [onBottomArrive, onBottomLeave, onTopArrive, onTopLeave]);
80
+ var onWheel = (0, _react.useCallback)(function (event) {
81
+ handleEventDelta(event, event.deltaY);
82
+ }, [handleEventDelta]);
83
+ var onTouchStart = (0, _react.useCallback)(function (event) {
84
+ // set touch start so we can calculate touchmove delta
85
+ touchStart.current = event.changedTouches[0].clientY;
86
+ }, []);
87
+ var onTouchMove = (0, _react.useCallback)(function (event) {
88
+ var deltaY = touchStart.current - event.changedTouches[0].clientY;
89
+ handleEventDelta(event, deltaY);
90
+ }, [handleEventDelta]);
91
+ var startListening = (0, _react.useCallback)(function (el) {
92
+ // bail early if no element is available to attach to
93
+ if (!el) {
94
+ return;
95
+ }
96
+ var notPassive = _utils.supportsPassiveEvents ? {
97
+ passive: false
98
+ } : false;
99
+ // eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
100
+ el.addEventListener('wheel', onWheel, notPassive);
101
+ // eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
102
+ el.addEventListener('touchstart', onTouchStart, notPassive);
103
+ // eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
104
+ el.addEventListener('touchmove', onTouchMove, notPassive);
105
+ }, [onTouchMove, onTouchStart, onWheel]);
106
+ var stopListening = (0, _react.useCallback)(function (el) {
107
+ // bail early if no element is available to detach from
108
+ if (!el) {
109
+ return;
110
+ }
111
+
112
+ // eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
113
+ el.removeEventListener('wheel', onWheel, false);
114
+ // eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
115
+ el.removeEventListener('touchstart', onTouchStart, false);
116
+ // eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
117
+ el.removeEventListener('touchmove', onTouchMove, false);
118
+ }, [onTouchMove, onTouchStart, onWheel]);
119
+ (0, _react.useEffect)(function () {
120
+ if (!isEnabled) {
121
+ return;
122
+ }
123
+ var element = scrollTarget.current;
124
+ startListening(element);
125
+ return function () {
126
+ stopListening(element);
127
+ };
128
+ }, [isEnabled, startListening, stopListening]);
129
+ return function (element) {
130
+ scrollTarget.current = element;
131
+ };
132
+ }
@@ -0,0 +1,149 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = useScrollLock;
7
+ var _react = require("react");
8
+ var STYLE_KEYS = ['boxSizing', 'height', 'overflow', 'paddingRight', 'position'];
9
+ var LOCK_STYLES = {
10
+ boxSizing: 'border-box',
11
+ // account for possible declaration `width: 100%;` on body
12
+ overflow: 'hidden',
13
+ position: 'relative',
14
+ height: '100%'
15
+ };
16
+ function preventTouchMove(e) {
17
+ e.preventDefault();
18
+ }
19
+ function allowTouchMove(e) {
20
+ e.stopPropagation();
21
+ }
22
+ function preventInertiaScroll() {
23
+ var top = this.scrollTop;
24
+ var totalScroll = this.scrollHeight;
25
+ var currentScroll = top + this.offsetHeight;
26
+ if (top === 0) {
27
+ this.scrollTop = 1;
28
+ } else if (currentScroll === totalScroll) {
29
+ this.scrollTop = top - 1;
30
+ }
31
+ }
32
+
33
+ // `ontouchstart` check works on most browsers
34
+ // `maxTouchPoints` works on IE10/11 and Surface
35
+ function isTouchDevice() {
36
+ // eslint-disable-next-line compat/compat
37
+ return 'ontouchstart' in window || navigator.maxTouchPoints;
38
+ }
39
+ var canUseDOM = !!(typeof window !== 'undefined' && window.document && window.document.createElement);
40
+ var activeScrollLocks = 0;
41
+ var listenerOptions = {
42
+ capture: false,
43
+ passive: false
44
+ };
45
+
46
+ // TODO: Fill in the hook {description}.
47
+ /**
48
+ * {description}.
49
+ */
50
+ function useScrollLock(_ref) {
51
+ var isEnabled = _ref.isEnabled,
52
+ _ref$accountForScroll = _ref.accountForScrollbars,
53
+ accountForScrollbars = _ref$accountForScroll === void 0 ? true : _ref$accountForScroll;
54
+ var originalStyles = (0, _react.useRef)({});
55
+ var scrollTarget = (0, _react.useRef)(null);
56
+ var addScrollLock = (0, _react.useCallback)(function (touchScrollTarget) {
57
+ if (!canUseDOM) {
58
+ return;
59
+ }
60
+ var target = document.body;
61
+ var targetStyle = target && target.style;
62
+ if (accountForScrollbars) {
63
+ // store any styles already applied to the body
64
+ STYLE_KEYS.forEach(function (key) {
65
+ var val = targetStyle && targetStyle[key];
66
+ originalStyles.current[key] = val;
67
+ });
68
+ }
69
+
70
+ // apply the lock styles and padding if this is the first scroll lock
71
+ if (accountForScrollbars && activeScrollLocks < 1) {
72
+ var currentPadding = parseInt(originalStyles.current.paddingRight, 10) || 0;
73
+ var clientWidth = document.body ? document.body.clientWidth : 0;
74
+ var adjustedPadding = window.innerWidth - clientWidth + currentPadding || 0;
75
+ Object.keys(LOCK_STYLES).forEach(function (key) {
76
+ var val = LOCK_STYLES[key];
77
+ if (targetStyle) {
78
+ targetStyle[key] = val;
79
+ }
80
+ });
81
+ if (targetStyle) {
82
+ targetStyle.paddingRight = "".concat(adjustedPadding, "px");
83
+ }
84
+ }
85
+
86
+ // account for touch devices
87
+ if (target && isTouchDevice()) {
88
+ // Mobile Safari ignores { overflow: hidden } declaration on the body.
89
+ // eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
90
+ target.addEventListener('touchmove', preventTouchMove, listenerOptions);
91
+
92
+ // Allow scroll on provided target
93
+ if (touchScrollTarget) {
94
+ // eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
95
+ touchScrollTarget.addEventListener('touchstart', preventInertiaScroll, listenerOptions);
96
+ // eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
97
+ touchScrollTarget.addEventListener('touchmove', allowTouchMove, listenerOptions);
98
+ }
99
+ }
100
+
101
+ // increment active scroll locks
102
+ activeScrollLocks += 1;
103
+ }, [accountForScrollbars]);
104
+ var removeScrollLock = (0, _react.useCallback)(function (touchScrollTarget) {
105
+ if (!canUseDOM) {
106
+ return;
107
+ }
108
+ var target = document.body;
109
+ var targetStyle = target && target.style;
110
+
111
+ // safely decrement active scroll locks
112
+ activeScrollLocks = Math.max(activeScrollLocks - 1, 0);
113
+
114
+ // reapply original body styles, if any
115
+ if (accountForScrollbars && activeScrollLocks < 1) {
116
+ STYLE_KEYS.forEach(function (key) {
117
+ var val = originalStyles.current[key];
118
+ if (targetStyle) {
119
+ targetStyle[key] = val;
120
+ }
121
+ });
122
+ }
123
+
124
+ // remove touch listeners
125
+ if (target && isTouchDevice()) {
126
+ // eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
127
+ target.removeEventListener('touchmove', preventTouchMove, listenerOptions);
128
+ if (touchScrollTarget) {
129
+ // eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
130
+ touchScrollTarget.removeEventListener('touchstart', preventInertiaScroll, listenerOptions);
131
+ // eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
132
+ touchScrollTarget.removeEventListener('touchmove', allowTouchMove, listenerOptions);
133
+ }
134
+ }
135
+ }, [accountForScrollbars]);
136
+ (0, _react.useEffect)(function () {
137
+ if (!isEnabled) {
138
+ return;
139
+ }
140
+ var element = scrollTarget.current;
141
+ addScrollLock(element);
142
+ return function () {
143
+ removeScrollLock(element);
144
+ };
145
+ }, [isEnabled, addScrollLock, removeScrollLock]);
146
+ return function (element) {
147
+ scrollTarget.current = element;
148
+ };
149
+ }