@loomhq/lens 10.63.10 → 10.64.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.
@@ -13,6 +13,7 @@ var __rest = (this && this.__rest) || function (s, e) {
13
13
  import FocusTrap from 'focus-trap-react';
14
14
  import { getColorValue, getPlacement, getRadius, getShadow, getSize, getSizeValue, u, } from '../../utilities';
15
15
  import React, { useEffect } from 'react';
16
+ import { usePreventScroll } from '../../hooks/use-prevent-scroll';
16
17
  import Backdrop from '../backdrop/backdrop';
17
18
  import Container from '../container/container';
18
19
  import IconButton from '../icon-button/icon-button';
@@ -111,9 +112,6 @@ export const ModalCard = (_a) => {
111
112
  // TODO: LNS-151: Abstract into useKeyDown hook for reuse
112
113
  var { children, onCloseClick, isOpen, maxWidth = 60, maxHeight = '70vh', placement = 'center', ariaLabel, ref } = _a, props = __rest(_a, ["children", "onCloseClick", "isOpen", "maxWidth", "maxHeight", "placement", "ariaLabel", "ref"]);
113
114
  useEffect(() => {
114
- if (!isOpen) {
115
- return;
116
- }
117
115
  const keyListener = e => {
118
116
  if (e.key === 'Escape') {
119
117
  e.preventDefault();
@@ -125,6 +123,7 @@ export const ModalCard = (_a) => {
125
123
  window.removeEventListener('keydown', keyListener);
126
124
  };
127
125
  }, [isOpen, onCloseClick]);
126
+ usePreventScroll('body', isOpen);
128
127
  return (React.createElement(FocusTrap, { active: isOpen, focusTrapOptions: {
129
128
  clickOutsideDeactivates: false,
130
129
  allowOutsideClick: true,
@@ -1,3 +1,4 @@
1
1
  export { default as useMedia } from './use-media.js';
2
2
  export { default as useOnClickOutside } from './use-on-click-outside.js';
3
3
  export { default as useFocusedElement } from './use-focused-element';
4
+ export { default as usePreventScroll } from './use-prevent-scroll';
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Usage:
3
+ * usePreventScroll(<level>, <boolean-condition>);
4
+ *
5
+ * `level` allows you to control whether the styles
6
+ * are passed to html or body, whichever level makes more sense
7
+ * for your application.
8
+ **/
9
+ export declare function usePreventScroll(level: 'body' | 'html', enabled?: boolean): void;
@@ -0,0 +1,72 @@
1
+ import { useLayoutEffect } from 'react';
2
+ /**
3
+ * Usage:
4
+ * usePreventScroll(<level>, <boolean-condition>);
5
+ *
6
+ * `level` allows you to control whether the styles
7
+ * are passed to html or body, whichever level makes more sense
8
+ * for your application.
9
+ **/
10
+ export function usePreventScroll(level, enabled) {
11
+ const safeDocument = document;
12
+ useLayoutEffect(() => {
13
+ const html = safeDocument === null || safeDocument === void 0 ? void 0 : safeDocument.documentElement;
14
+ const body = safeDocument === null || safeDocument === void 0 ? void 0 : safeDocument.body;
15
+ if (safeDocument == undefined || !html || !body) {
16
+ return;
17
+ }
18
+ if (enabled) {
19
+ // Add styles if enabled
20
+ const scrollBarWidth = window.innerWidth - html.clientWidth;
21
+ const bodyPaddingRight = parseInt(window.getComputedStyle(body).getPropertyValue('padding-right'),
22
+ /* Force radixValue to be base-10 system to avoid errors:
23
+ * https://stackoverflow.com/questions/6611824/why-do-we-need-to-use-radix-parameter-when-calling-parseint
24
+ */
25
+ 10) || 0;
26
+ /**
27
+ * [1] iOS and desktop Safari bug: Requires position to make `overflow: hidden`
28
+ * prevent scrolling.
29
+ * [2] Desktop Safari bug: Must override overflow in both directions
30
+ * since `overflowY` won't prevent scroll if `overflowX` is applied.
31
+ * [3] paddingRight takes into account scrollbars by running a check.
32
+ **/
33
+ switch (level) {
34
+ case 'html': {
35
+ html.style.position = 'relative'; /* [1] */
36
+ html.style.overflow = 'hidden'; /* [2] */
37
+ body.style.paddingRight = `${bodyPaddingRight +
38
+ scrollBarWidth}px`; /* [3] */
39
+ break;
40
+ }
41
+ case 'body': {
42
+ body.style.setProperty('position', 'relative'); /* [1] */
43
+ body.style.setProperty('overflow', 'hidden'); /* [2] */
44
+ body.style.setProperty('padding-right', `${bodyPaddingRight + scrollBarWidth}px`); /* [3] */
45
+ break;
46
+ }
47
+ default:
48
+ return;
49
+ }
50
+ }
51
+ return () => {
52
+ switch (level) {
53
+ case 'html': {
54
+ // TODO(LNS-221): Preserve previous style states rather than resetting to empty values for more robust utility
55
+ html.style.position = ''; /* [1] */
56
+ html.style.overflow = ''; /* [2] */
57
+ body.style.paddingRight = ''; /* [3] */
58
+ break;
59
+ }
60
+ case 'body': {
61
+ body.style.removeProperty('position'); /* [1] */
62
+ body.style.removeProperty('overflow'); /* [2] */
63
+ body.style.removeProperty('padding-right'); /* [3] */
64
+ break;
65
+ }
66
+ default:
67
+ return;
68
+ }
69
+ };
70
+ // TODO(LNS-215): Clear styles on return to make utility more extendable for other uses
71
+ }, [safeDocument, enabled, level]);
72
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@loomhq/lens",
3
- "version": "10.63.10",
3
+ "version": "10.64.0",
4
4
  "scripts": {
5
5
  "dev": "next",
6
6
  "build:next": "next build",