@mui/utils 6.0.0-alpha.12 → 6.0.0-alpha.14

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 (36) hide show
  1. package/CHANGELOG.md +91 -0
  2. package/getDisplayName/getDisplayName.d.ts +1 -1
  3. package/getDisplayName/getDisplayName.js +1 -1
  4. package/index.d.ts +1 -2
  5. package/index.js +2 -3
  6. package/isFocusVisible/index.d.ts +1 -0
  7. package/isFocusVisible/index.js +1 -0
  8. package/isFocusVisible/isFocusVisible.d.ts +4 -0
  9. package/isFocusVisible/isFocusVisible.js +15 -0
  10. package/{scrollLeft → isFocusVisible}/package.json +1 -1
  11. package/modern/getDisplayName/getDisplayName.js +1 -1
  12. package/modern/index.js +2 -3
  13. package/modern/isFocusVisible/index.js +1 -0
  14. package/modern/isFocusVisible/isFocusVisible.js +15 -0
  15. package/node/getDisplayName/getDisplayName.js +1 -1
  16. package/node/index.js +7 -22
  17. package/node/isFocusVisible/index.js +13 -0
  18. package/node/isFocusVisible/isFocusVisible.js +21 -0
  19. package/package.json +2 -2
  20. package/modern/scrollLeft/index.js +0 -1
  21. package/modern/scrollLeft/scrollLeft.js +0 -70
  22. package/modern/useIsFocusVisible/index.js +0 -2
  23. package/modern/useIsFocusVisible/useIsFocusVisible.js +0 -163
  24. package/node/scrollLeft/index.js +0 -16
  25. package/node/scrollLeft/scrollLeft.js +0 -77
  26. package/node/useIsFocusVisible/index.js +0 -26
  27. package/node/useIsFocusVisible/useIsFocusVisible.js +0 -171
  28. package/scrollLeft/index.d.ts +0 -1
  29. package/scrollLeft/index.js +0 -1
  30. package/scrollLeft/scrollLeft.d.ts +0 -2
  31. package/scrollLeft/scrollLeft.js +0 -70
  32. package/useIsFocusVisible/index.d.ts +0 -2
  33. package/useIsFocusVisible/index.js +0 -2
  34. package/useIsFocusVisible/package.json +0 -6
  35. package/useIsFocusVisible/useIsFocusVisible.d.ts +0 -9
  36. package/useIsFocusVisible/useIsFocusVisible.js +0 -163
package/CHANGELOG.md CHANGED
@@ -1,5 +1,96 @@
1
1
  # [Versions](https://mui.com/versions/)
2
2
 
3
+ ## v6.0.0-alpha.14
4
+
5
+ <!-- generated comparing v6.0.0-alpha.13..next -->
6
+
7
+ _Jul 3, 2024_
8
+
9
+ A big thanks to the 12 contributors who made this release possible. Here are some highlights ✨:
10
+
11
+ - ✨ Updated Grid v2 to match PigmentGrid (#42742) @DiegoAndai
12
+
13
+ ### `@mui/material@v6.0.0-alpha.14`
14
+
15
+ #### BREAKING CHANGES
16
+
17
+ - [Grid] Update Grid props to match PigmentGrid (#42742) @DiegoAndai
18
+
19
+ Use the codemod below to migrate the props:
20
+
21
+ ```bash
22
+ npx @mui/codemod@next v6.0.0/grid-v2-props /path/to/folder
23
+ ```
24
+
25
+ #### Changes
26
+
27
+ - [Alert] Add ability to override slot props (#42787) @alexey-kozlenkov
28
+ - [Dialog] Revert incorrect textAlign style removal (#42778) @DiegoAndai
29
+ - [theme] Support `CssVarsTheme` in `responsiveFontSizes` return type (#42786) @jxdp
30
+
31
+ ### Docs
32
+
33
+ - [material-ui] Add some writing tweaks to v6 migration page (#42623) @danilo-leal
34
+ - [material-ui] Fix issues reported by react-compiler in docs folder (#42830) @sai6855
35
+ - [material-ui] Add some writing tweaks to v6 migration page (#42623) @danilo-leal
36
+ - [base-ui] Fix wrong description for `UseTabParameters.onChange` (#42749) @ohgree
37
+ - Fix 301 MDN redirections @oliviertassinari
38
+
39
+ ### Core
40
+
41
+ - [core] Bump React to 18.3.1 (#42047) @renovate[bot]
42
+ - [core] Revert lint for `useThemeProps` (#42817) @siriwatknp
43
+ - [core] Remove useIsFocusVisible util (#42467) @DiegoAndai
44
+ - [core] Remove react-test-renderer (#42784) @aarongarciah
45
+ - [core][mui-utils] Remove remaining IE11 references (#42777) @DiegoAndai
46
+ - [code-infra] Move `HighlightedCode` test into `@mui/docs` package (#42835) @LukasTy
47
+ - [code-infra] Cleanup `@mui/docs` usage and legacy re-exports (#42833) @LukasTy
48
+ - [docs-infra] Fix React Compiler ESLint issues in website components (#42566) @aarongarciah
49
+ - [docs-infra] Add batch of design polish (#42823) @danilo-leal
50
+ - [test][mui-utils] Remove usages of deprecated react-dom APIs (#42780) @aarongarciah
51
+ - [test][joy-ui][Autocomplete] Fix spread key error in test (#42775) @aarongarciah
52
+
53
+ All contributors of this release in alphabetical order: @aarongarciah, @alexey-kozlenkov, @danilo-leal, @DiegoAndai, @Janpot, @jxdp, @LukasTy, @ohgree, @oliviertassinari, @renovate[bot], @sai6855, @siriwatknp
54
+
55
+ ## v6.0.0-alpha.13
56
+
57
+ <!-- generated comparing v6.0.0-alpha.12..next -->
58
+
59
+ _Jun 27, 2024_
60
+
61
+ A big thanks to the 10 contributors who made this release possible. Here are some highlights ✨:
62
+
63
+ - 🚀 Added layout components for Pigment CSS integration (#42693) @siriwatknp
64
+
65
+ ### `@mui/material@6.0.0-alpha.13`
66
+
67
+ - [Autocomplete] Fix more React 18.3 key spread warnings in demos (#42639) @wbt
68
+ - [Container][Grid][Stack][Hidden] Export Pigment CSS layout components (#42693) @siriwatknp
69
+ - [Text Field] when click password visibility button, text caret position change to very front. (#42595) @appleSimple
70
+ - [Modal] migrate useSlotProps to useSLot (#42150) @sai6855
71
+
72
+ ### `@mui/styles@6.0.0-alpha.13`
73
+
74
+ - [withStyles] Expect React defaultProps warning in test (#42752) @aarongarciah
75
+
76
+ ### Docs
77
+
78
+ - Fix link in CONTRIBUTING.md (#42755) @Janpot
79
+ - Add documentation on migrating JSS's alternative, array-based syntax to syntax supported by Emotion (#42053) @cjl750
80
+ - Fix type error in virtualized table demo (#42757) @aarongarciah
81
+ - Add first batch of v6 migration (#42242) @siriwatknp
82
+ - Fix quotes on font-family dedeclaration in the Landing Page template theme (#42748) @joetats
83
+
84
+ ### Core
85
+
86
+ - [code-infra] Refactor eslint `import/no-cycle` rule (#42705) @LukasTy
87
+ - [core] Target direct version for prerelease (#42768) @siriwatknp
88
+ - [test] Remove enzyme (#42706) @aarongarciah
89
+ - [test] Remove createMount test util (#42703) @aarongarciah
90
+ - [website] Add Ale to team (#42764) @alelthomas
91
+
92
+ All contributors of this release in alphabetical order: @aarongarciah, @alelthomas, @appleSimple, @cjl750, @Janpot, @joetats, @LukasTy, @sai6855, @siriwatknp, @wbt
93
+
3
94
  ## v6.0.0-alpha.12
4
95
 
5
96
  <!-- generated comparing v6.0.0-alpha.11..next -->
@@ -2,6 +2,6 @@ import * as React from 'react';
2
2
  /**
3
3
  * cherry-pick from
4
4
  * https://github.com/facebook/react/blob/769b1f270e1251d9dbdce0fcbd9e92e502d059b8/packages/shared/getComponentName.js
5
- * originally forked from recompose/getDisplayName with added IE11 support
5
+ * originally forked from recompose/getDisplayName
6
6
  */
7
7
  export default function getDisplayName(Component: React.ElementType): string | undefined;
@@ -10,7 +10,7 @@ function getWrappedName(outerType, innerType, wrapperName) {
10
10
  /**
11
11
  * cherry-pick from
12
12
  * https://github.com/facebook/react/blob/769b1f270e1251d9dbdce0fcbd9e92e502d059b8/packages/shared/getComponentName.js
13
- * originally forked from recompose/getDisplayName with added IE11 support
13
+ * originally forked from recompose/getDisplayName
14
14
  */
15
15
  export default function getDisplayName(Component) {
16
16
  if (Component == null) {
package/index.d.ts CHANGED
@@ -27,9 +27,8 @@ export { default as unstable_useForkRef } from './useForkRef';
27
27
  export { default as unstable_useLazyRef } from './useLazyRef';
28
28
  export { default as unstable_useTimeout, Timeout as unstable_Timeout } from './useTimeout';
29
29
  export { default as unstable_useOnMount } from './useOnMount';
30
- export { default as unstable_useIsFocusVisible } from './useIsFocusVisible';
30
+ export { default as unstable_isFocusVisible } from './isFocusVisible';
31
31
  export { default as unstable_getScrollbarSize } from './getScrollbarSize';
32
- export { detectScrollType as unstable_detectScrollType, getNormalizedScrollLeft as unstable_getNormalizedScrollLeft, } from './scrollLeft';
33
32
  export { default as usePreviousProps } from './usePreviousProps';
34
33
  export { default as getValidReactChildren } from './getValidReactChildren';
35
34
  export { default as visuallyHidden } from './visuallyHidden';
package/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @mui/utils v6.0.0-alpha.12
2
+ * @mui/utils v6.0.0-alpha.14
3
3
  *
4
4
  * @license MIT
5
5
  * This source code is licensed under the MIT license found in the
@@ -34,9 +34,8 @@ export { default as unstable_useForkRef } from './useForkRef';
34
34
  export { default as unstable_useLazyRef } from './useLazyRef';
35
35
  export { default as unstable_useTimeout, Timeout as unstable_Timeout } from './useTimeout';
36
36
  export { default as unstable_useOnMount } from './useOnMount';
37
- export { default as unstable_useIsFocusVisible } from './useIsFocusVisible';
37
+ export { default as unstable_isFocusVisible } from './isFocusVisible';
38
38
  export { default as unstable_getScrollbarSize } from './getScrollbarSize';
39
- export { detectScrollType as unstable_detectScrollType, getNormalizedScrollLeft as unstable_getNormalizedScrollLeft } from './scrollLeft';
40
39
  export { default as usePreviousProps } from './usePreviousProps';
41
40
  export { default as getValidReactChildren } from './getValidReactChildren';
42
41
  export { default as visuallyHidden } from './visuallyHidden';
@@ -0,0 +1 @@
1
+ export { default } from './isFocusVisible';
@@ -0,0 +1 @@
1
+ export { default } from './isFocusVisible';
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Returns a boolean indicating if the event's target has :focus-visible
3
+ */
4
+ export default function isFocusVisible(element: Element): boolean;
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Returns a boolean indicating if the event's target has :focus-visible
3
+ */
4
+ export default function isFocusVisible(element) {
5
+ try {
6
+ return element.matches(':focus-visible');
7
+ } catch (error) {
8
+ // Do not warn on jsdom tests, otherwise all tests that rely on focus have to be skipped
9
+ // Tests that rely on `:focus-visible` will still have to be skipped in jsdom
10
+ if (process.env.NODE_ENV !== 'production' && !/jsdom/.test(window.navigator.userAgent)) {
11
+ console.warn(['MUI: The `:focus-visible` pseudo class is not supported in this browser.', 'Some components rely on this feature to work properly.'].join('\n'));
12
+ }
13
+ }
14
+ return false;
15
+ }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "sideEffects": false,
3
3
  "module": "./index.js",
4
- "main": "../node/scrollLeft/index.js",
4
+ "main": "../node/isFocusVisible/index.js",
5
5
  "types": "./index.d.ts"
6
6
  }
@@ -10,7 +10,7 @@ function getWrappedName(outerType, innerType, wrapperName) {
10
10
  /**
11
11
  * cherry-pick from
12
12
  * https://github.com/facebook/react/blob/769b1f270e1251d9dbdce0fcbd9e92e502d059b8/packages/shared/getComponentName.js
13
- * originally forked from recompose/getDisplayName with added IE11 support
13
+ * originally forked from recompose/getDisplayName
14
14
  */
15
15
  export default function getDisplayName(Component) {
16
16
  if (Component == null) {
package/modern/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @mui/utils v6.0.0-alpha.12
2
+ * @mui/utils v6.0.0-alpha.14
3
3
  *
4
4
  * @license MIT
5
5
  * This source code is licensed under the MIT license found in the
@@ -34,9 +34,8 @@ export { default as unstable_useForkRef } from './useForkRef';
34
34
  export { default as unstable_useLazyRef } from './useLazyRef';
35
35
  export { default as unstable_useTimeout, Timeout as unstable_Timeout } from './useTimeout';
36
36
  export { default as unstable_useOnMount } from './useOnMount';
37
- export { default as unstable_useIsFocusVisible } from './useIsFocusVisible';
37
+ export { default as unstable_isFocusVisible } from './isFocusVisible';
38
38
  export { default as unstable_getScrollbarSize } from './getScrollbarSize';
39
- export { detectScrollType as unstable_detectScrollType, getNormalizedScrollLeft as unstable_getNormalizedScrollLeft } from './scrollLeft';
40
39
  export { default as usePreviousProps } from './usePreviousProps';
41
40
  export { default as getValidReactChildren } from './getValidReactChildren';
42
41
  export { default as visuallyHidden } from './visuallyHidden';
@@ -0,0 +1 @@
1
+ export { default } from './isFocusVisible';
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Returns a boolean indicating if the event's target has :focus-visible
3
+ */
4
+ export default function isFocusVisible(element) {
5
+ try {
6
+ return element.matches(':focus-visible');
7
+ } catch (error) {
8
+ // Do not warn on jsdom tests, otherwise all tests that rely on focus have to be skipped
9
+ // Tests that rely on `:focus-visible` will still have to be skipped in jsdom
10
+ if (process.env.NODE_ENV !== 'production' && !/jsdom/.test(window.navigator.userAgent)) {
11
+ console.warn(['MUI: The `:focus-visible` pseudo class is not supported in this browser.', 'Some components rely on this feature to work properly.'].join('\n'));
12
+ }
13
+ }
14
+ return false;
15
+ }
@@ -16,7 +16,7 @@ function getWrappedName(outerType, innerType, wrapperName) {
16
16
  /**
17
17
  * cherry-pick from
18
18
  * https://github.com/facebook/react/blob/769b1f270e1251d9dbdce0fcbd9e92e502d059b8/packages/shared/getComponentName.js
19
- * originally forked from recompose/getDisplayName with added IE11 support
19
+ * originally forked from recompose/getDisplayName
20
20
  */
21
21
  function getDisplayName(Component) {
22
22
  if (Component == null) {
package/node/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @mui/utils v6.0.0-alpha.12
2
+ * @mui/utils v6.0.0-alpha.14
3
3
  *
4
4
  * @license MIT
5
5
  * This source code is licensed under the MIT license found in the
@@ -42,10 +42,8 @@ var _exportNames = {
42
42
  unstable_useTimeout: true,
43
43
  unstable_Timeout: true,
44
44
  unstable_useOnMount: true,
45
- unstable_useIsFocusVisible: true,
45
+ unstable_isFocusVisible: true,
46
46
  unstable_getScrollbarSize: true,
47
- unstable_detectScrollType: true,
48
- unstable_getNormalizedScrollLeft: true,
49
47
  usePreviousProps: true,
50
48
  getValidReactChildren: true,
51
49
  visuallyHidden: true,
@@ -190,12 +188,6 @@ Object.defineProperty(exports, "unstable_deprecatedPropType", {
190
188
  return _deprecatedPropType.default;
191
189
  }
192
190
  });
193
- Object.defineProperty(exports, "unstable_detectScrollType", {
194
- enumerable: true,
195
- get: function () {
196
- return _scrollLeft.detectScrollType;
197
- }
198
- });
199
191
  Object.defineProperty(exports, "unstable_generateUtilityClass", {
200
192
  enumerable: true,
201
193
  get: function () {
@@ -208,16 +200,16 @@ Object.defineProperty(exports, "unstable_generateUtilityClasses", {
208
200
  return _generateUtilityClasses.default;
209
201
  }
210
202
  });
211
- Object.defineProperty(exports, "unstable_getNormalizedScrollLeft", {
203
+ Object.defineProperty(exports, "unstable_getScrollbarSize", {
212
204
  enumerable: true,
213
205
  get: function () {
214
- return _scrollLeft.getNormalizedScrollLeft;
206
+ return _getScrollbarSize.default;
215
207
  }
216
208
  });
217
- Object.defineProperty(exports, "unstable_getScrollbarSize", {
209
+ Object.defineProperty(exports, "unstable_isFocusVisible", {
218
210
  enumerable: true,
219
211
  get: function () {
220
- return _getScrollbarSize.default;
212
+ return _isFocusVisible.default;
221
213
  }
222
214
  });
223
215
  Object.defineProperty(exports, "unstable_isGlobalState", {
@@ -292,12 +284,6 @@ Object.defineProperty(exports, "unstable_useId", {
292
284
  return _useId.default;
293
285
  }
294
286
  });
295
- Object.defineProperty(exports, "unstable_useIsFocusVisible", {
296
- enumerable: true,
297
- get: function () {
298
- return _useIsFocusVisible.default;
299
- }
300
- });
301
287
  Object.defineProperty(exports, "unstable_useLazyRef", {
302
288
  enumerable: true,
303
289
  get: function () {
@@ -356,9 +342,8 @@ var _useForkRef = _interopRequireDefault(require("./useForkRef"));
356
342
  var _useLazyRef = _interopRequireDefault(require("./useLazyRef"));
357
343
  var _useTimeout = _interopRequireWildcard(require("./useTimeout"));
358
344
  var _useOnMount = _interopRequireDefault(require("./useOnMount"));
359
- var _useIsFocusVisible = _interopRequireDefault(require("./useIsFocusVisible"));
345
+ var _isFocusVisible = _interopRequireDefault(require("./isFocusVisible"));
360
346
  var _getScrollbarSize = _interopRequireDefault(require("./getScrollbarSize"));
361
- var _scrollLeft = require("./scrollLeft");
362
347
  var _usePreviousProps = _interopRequireDefault(require("./usePreviousProps"));
363
348
  var _getValidReactChildren = _interopRequireDefault(require("./getValidReactChildren"));
364
349
  var _visuallyHidden = _interopRequireDefault(require("./visuallyHidden"));
@@ -0,0 +1,13 @@
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, "default", {
8
+ enumerable: true,
9
+ get: function () {
10
+ return _isFocusVisible.default;
11
+ }
12
+ });
13
+ var _isFocusVisible = _interopRequireDefault(require("./isFocusVisible"));
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = isFocusVisible;
7
+ /**
8
+ * Returns a boolean indicating if the event's target has :focus-visible
9
+ */
10
+ function isFocusVisible(element) {
11
+ try {
12
+ return element.matches(':focus-visible');
13
+ } catch (error) {
14
+ // Do not warn on jsdom tests, otherwise all tests that rely on focus have to be skipped
15
+ // Tests that rely on `:focus-visible` will still have to be skipped in jsdom
16
+ if (process.env.NODE_ENV !== 'production' && !/jsdom/.test(window.navigator.userAgent)) {
17
+ console.warn(['MUI: The `:focus-visible` pseudo class is not supported in this browser.', 'Some components rely on this feature to work properly.'].join('\n'));
18
+ }
19
+ }
20
+ return false;
21
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mui/utils",
3
- "version": "6.0.0-alpha.12",
3
+ "version": "6.0.0-alpha.14",
4
4
  "private": false,
5
5
  "author": "MUI Team",
6
6
  "description": "Utility functions for React components.",
@@ -29,7 +29,7 @@
29
29
  "@babel/runtime": "^7.24.7",
30
30
  "@types/prop-types": "^15.7.12",
31
31
  "prop-types": "^15.8.1",
32
- "react-is": "^18.2.0"
32
+ "react-is": "^18.3.1"
33
33
  },
34
34
  "peerDependencies": {
35
35
  "@types/react": "^17.0.0 || ^18.0.0",
@@ -1 +0,0 @@
1
- export * from './scrollLeft';
@@ -1,70 +0,0 @@
1
- // Source from https://github.com/alitaheri/normalize-scroll-left
2
- let cachedType;
3
-
4
- /**
5
- * Based on the jquery plugin https://github.com/othree/jquery.rtl-scroll-type
6
- *
7
- * Types of scrollLeft, assuming scrollWidth=100 and direction is rtl.
8
- *
9
- * Type | <- Most Left | Most Right -> | Initial
10
- * ---------------- | ------------ | ------------- | -------
11
- * default | 0 | 100 | 100
12
- * negative (spec*) | -100 | 0 | 0
13
- * reverse | 100 | 0 | 0
14
- *
15
- * Edge 85: default
16
- * Safari 14: negative
17
- * Chrome 85: negative
18
- * Firefox 81: negative
19
- * IE11: reverse
20
- *
21
- * spec* https://drafts.csswg.org/cssom-view/#dom-window-scroll
22
- */
23
- export function detectScrollType() {
24
- if (cachedType) {
25
- return cachedType;
26
- }
27
- const dummy = document.createElement('div');
28
- const container = document.createElement('div');
29
- container.style.width = '10px';
30
- container.style.height = '1px';
31
- dummy.appendChild(container);
32
- dummy.dir = 'rtl';
33
- dummy.style.fontSize = '14px';
34
- dummy.style.width = '4px';
35
- dummy.style.height = '1px';
36
- dummy.style.position = 'absolute';
37
- dummy.style.top = '-1000px';
38
- dummy.style.overflow = 'scroll';
39
- document.body.appendChild(dummy);
40
- cachedType = 'reverse';
41
- if (dummy.scrollLeft > 0) {
42
- cachedType = 'default';
43
- } else {
44
- dummy.scrollLeft = 1;
45
- if (dummy.scrollLeft === 0) {
46
- cachedType = 'negative';
47
- }
48
- }
49
- document.body.removeChild(dummy);
50
- return cachedType;
51
- }
52
-
53
- // Based on https://stackoverflow.com/a/24394376
54
- export function getNormalizedScrollLeft(element, direction) {
55
- const scrollLeft = element.scrollLeft;
56
-
57
- // Perform the calculations only when direction is rtl to avoid messing up the ltr behavior
58
- if (direction !== 'rtl') {
59
- return scrollLeft;
60
- }
61
- const type = detectScrollType();
62
- switch (type) {
63
- case 'negative':
64
- return element.scrollWidth - element.clientWidth + scrollLeft;
65
- case 'reverse':
66
- return element.scrollWidth - element.clientWidth - scrollLeft;
67
- default:
68
- return scrollLeft;
69
- }
70
- }
@@ -1,2 +0,0 @@
1
- export { default } from './useIsFocusVisible';
2
- export * from './useIsFocusVisible';
@@ -1,163 +0,0 @@
1
- 'use client';
2
-
3
- // based on https://github.com/WICG/focus-visible/blob/v4.1.5/src/focus-visible.js
4
- import * as React from 'react';
5
- import { Timeout } from '../useTimeout/useTimeout';
6
- let hadKeyboardEvent = true;
7
- let hadFocusVisibleRecently = false;
8
- const hadFocusVisibleRecentlyTimeout = new Timeout();
9
- const inputTypesWhitelist = {
10
- text: true,
11
- search: true,
12
- url: true,
13
- tel: true,
14
- email: true,
15
- password: true,
16
- number: true,
17
- date: true,
18
- month: true,
19
- week: true,
20
- time: true,
21
- datetime: true,
22
- 'datetime-local': true
23
- };
24
-
25
- /**
26
- * Computes whether the given element should automatically trigger the
27
- * `focus-visible` class being added, i.e. whether it should always match
28
- * `:focus-visible` when focused.
29
- * @param {Element} node
30
- * @returns {boolean}
31
- */
32
- function focusTriggersKeyboardModality(node) {
33
- const {
34
- type,
35
- tagName
36
- } = node;
37
- if (tagName === 'INPUT' && inputTypesWhitelist[type] && !node.readOnly) {
38
- return true;
39
- }
40
- if (tagName === 'TEXTAREA' && !node.readOnly) {
41
- return true;
42
- }
43
- if (node.isContentEditable) {
44
- return true;
45
- }
46
- return false;
47
- }
48
-
49
- /**
50
- * Keep track of our keyboard modality state with `hadKeyboardEvent`.
51
- * If the most recent user interaction was via the keyboard;
52
- * and the key press did not include a meta, alt/option, or control key;
53
- * then the modality is keyboard. Otherwise, the modality is not keyboard.
54
- * @param {KeyboardEvent} event
55
- */
56
- function handleKeyDown(event) {
57
- if (event.metaKey || event.altKey || event.ctrlKey) {
58
- return;
59
- }
60
- hadKeyboardEvent = true;
61
- }
62
-
63
- /**
64
- * If at any point a user clicks with a pointing device, ensure that we change
65
- * the modality away from keyboard.
66
- * This avoids the situation where a user presses a key on an already focused
67
- * element, and then clicks on a different element, focusing it with a
68
- * pointing device, while we still think we're in keyboard modality.
69
- */
70
- function handlePointerDown() {
71
- hadKeyboardEvent = false;
72
- }
73
- function handleVisibilityChange() {
74
- if (this.visibilityState === 'hidden') {
75
- // If the tab becomes active again, the browser will handle calling focus
76
- // on the element (Safari actually calls it twice).
77
- // If this tab change caused a blur on an element with focus-visible,
78
- // re-apply the class when the user switches back to the tab.
79
- if (hadFocusVisibleRecently) {
80
- hadKeyboardEvent = true;
81
- }
82
- }
83
- }
84
- function prepare(doc) {
85
- doc.addEventListener('keydown', handleKeyDown, true);
86
- doc.addEventListener('mousedown', handlePointerDown, true);
87
- doc.addEventListener('pointerdown', handlePointerDown, true);
88
- doc.addEventListener('touchstart', handlePointerDown, true);
89
- doc.addEventListener('visibilitychange', handleVisibilityChange, true);
90
- }
91
- export function teardown(doc) {
92
- doc.removeEventListener('keydown', handleKeyDown, true);
93
- doc.removeEventListener('mousedown', handlePointerDown, true);
94
- doc.removeEventListener('pointerdown', handlePointerDown, true);
95
- doc.removeEventListener('touchstart', handlePointerDown, true);
96
- doc.removeEventListener('visibilitychange', handleVisibilityChange, true);
97
- }
98
- function isFocusVisible(event) {
99
- const {
100
- target
101
- } = event;
102
- try {
103
- return target.matches(':focus-visible');
104
- } catch (error) {
105
- // Browsers not implementing :focus-visible will throw a SyntaxError.
106
- // We use our own heuristic for those browsers.
107
- // Rethrow might be better if it's not the expected error but do we really
108
- // want to crash if focus-visible malfunctioned?
109
- }
110
-
111
- // No need for validFocusTarget check. The user does that by attaching it to
112
- // focusable events only.
113
- return hadKeyboardEvent || focusTriggersKeyboardModality(target);
114
- }
115
- export default function useIsFocusVisible() {
116
- const ref = React.useCallback(node => {
117
- if (node != null) {
118
- prepare(node.ownerDocument);
119
- }
120
- }, []);
121
- const isFocusVisibleRef = React.useRef(false);
122
-
123
- /**
124
- * Should be called if a blur event is fired
125
- */
126
- function handleBlurVisible() {
127
- // checking against potential state variable does not suffice if we focus and blur synchronously.
128
- // React wouldn't have time to trigger a re-render so `focusVisible` would be stale.
129
- // Ideally we would adjust `isFocusVisible(event)` to look at `relatedTarget` for blur events.
130
- // This doesn't work in IE11 due to https://github.com/facebook/react/issues/3751
131
- // TODO: check again if React releases their internal changes to focus event handling (https://github.com/facebook/react/pull/19186).
132
- if (isFocusVisibleRef.current) {
133
- // To detect a tab/window switch, we look for a blur event followed
134
- // rapidly by a visibility change.
135
- // If we don't see a visibility change within 100ms, it's probably a
136
- // regular focus change.
137
- hadFocusVisibleRecently = true;
138
- hadFocusVisibleRecentlyTimeout.start(100, () => {
139
- hadFocusVisibleRecently = false;
140
- });
141
- isFocusVisibleRef.current = false;
142
- return true;
143
- }
144
- return false;
145
- }
146
-
147
- /**
148
- * Should be called if a blur event is fired
149
- */
150
- function handleFocusVisible(event) {
151
- if (isFocusVisible(event)) {
152
- isFocusVisibleRef.current = true;
153
- return true;
154
- }
155
- return false;
156
- }
157
- return {
158
- isFocusVisibleRef,
159
- onFocus: handleFocusVisible,
160
- onBlur: handleBlurVisible,
161
- ref
162
- };
163
- }
@@ -1,16 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- var _scrollLeft = require("./scrollLeft");
7
- Object.keys(_scrollLeft).forEach(function (key) {
8
- if (key === "default" || key === "__esModule") return;
9
- if (key in exports && exports[key] === _scrollLeft[key]) return;
10
- Object.defineProperty(exports, key, {
11
- enumerable: true,
12
- get: function () {
13
- return _scrollLeft[key];
14
- }
15
- });
16
- });
@@ -1,77 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.detectScrollType = detectScrollType;
7
- exports.getNormalizedScrollLeft = getNormalizedScrollLeft;
8
- // Source from https://github.com/alitaheri/normalize-scroll-left
9
- let cachedType;
10
-
11
- /**
12
- * Based on the jquery plugin https://github.com/othree/jquery.rtl-scroll-type
13
- *
14
- * Types of scrollLeft, assuming scrollWidth=100 and direction is rtl.
15
- *
16
- * Type | <- Most Left | Most Right -> | Initial
17
- * ---------------- | ------------ | ------------- | -------
18
- * default | 0 | 100 | 100
19
- * negative (spec*) | -100 | 0 | 0
20
- * reverse | 100 | 0 | 0
21
- *
22
- * Edge 85: default
23
- * Safari 14: negative
24
- * Chrome 85: negative
25
- * Firefox 81: negative
26
- * IE11: reverse
27
- *
28
- * spec* https://drafts.csswg.org/cssom-view/#dom-window-scroll
29
- */
30
- function detectScrollType() {
31
- if (cachedType) {
32
- return cachedType;
33
- }
34
- const dummy = document.createElement('div');
35
- const container = document.createElement('div');
36
- container.style.width = '10px';
37
- container.style.height = '1px';
38
- dummy.appendChild(container);
39
- dummy.dir = 'rtl';
40
- dummy.style.fontSize = '14px';
41
- dummy.style.width = '4px';
42
- dummy.style.height = '1px';
43
- dummy.style.position = 'absolute';
44
- dummy.style.top = '-1000px';
45
- dummy.style.overflow = 'scroll';
46
- document.body.appendChild(dummy);
47
- cachedType = 'reverse';
48
- if (dummy.scrollLeft > 0) {
49
- cachedType = 'default';
50
- } else {
51
- dummy.scrollLeft = 1;
52
- if (dummy.scrollLeft === 0) {
53
- cachedType = 'negative';
54
- }
55
- }
56
- document.body.removeChild(dummy);
57
- return cachedType;
58
- }
59
-
60
- // Based on https://stackoverflow.com/a/24394376
61
- function getNormalizedScrollLeft(element, direction) {
62
- const scrollLeft = element.scrollLeft;
63
-
64
- // Perform the calculations only when direction is rtl to avoid messing up the ltr behavior
65
- if (direction !== 'rtl') {
66
- return scrollLeft;
67
- }
68
- const type = detectScrollType();
69
- switch (type) {
70
- case 'negative':
71
- return element.scrollWidth - element.clientWidth + scrollLeft;
72
- case 'reverse':
73
- return element.scrollWidth - element.clientWidth - scrollLeft;
74
- default:
75
- return scrollLeft;
76
- }
77
- }
@@ -1,26 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- var _exportNames = {};
7
- Object.defineProperty(exports, "default", {
8
- enumerable: true,
9
- get: function () {
10
- return _useIsFocusVisible.default;
11
- }
12
- });
13
- var _useIsFocusVisible = _interopRequireWildcard(require("./useIsFocusVisible"));
14
- Object.keys(_useIsFocusVisible).forEach(function (key) {
15
- if (key === "default" || key === "__esModule") return;
16
- if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
17
- if (key in exports && exports[key] === _useIsFocusVisible[key]) return;
18
- Object.defineProperty(exports, key, {
19
- enumerable: true,
20
- get: function () {
21
- return _useIsFocusVisible[key];
22
- }
23
- });
24
- });
25
- function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
26
- 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; }
@@ -1,171 +0,0 @@
1
- "use strict";
2
- 'use client';
3
-
4
- // based on https://github.com/WICG/focus-visible/blob/v4.1.5/src/focus-visible.js
5
- Object.defineProperty(exports, "__esModule", {
6
- value: true
7
- });
8
- exports.default = useIsFocusVisible;
9
- exports.teardown = teardown;
10
- var React = _interopRequireWildcard(require("react"));
11
- var _useTimeout = require("../useTimeout/useTimeout");
12
- function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
13
- 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; }
14
- let hadKeyboardEvent = true;
15
- let hadFocusVisibleRecently = false;
16
- const hadFocusVisibleRecentlyTimeout = new _useTimeout.Timeout();
17
- const inputTypesWhitelist = {
18
- text: true,
19
- search: true,
20
- url: true,
21
- tel: true,
22
- email: true,
23
- password: true,
24
- number: true,
25
- date: true,
26
- month: true,
27
- week: true,
28
- time: true,
29
- datetime: true,
30
- 'datetime-local': true
31
- };
32
-
33
- /**
34
- * Computes whether the given element should automatically trigger the
35
- * `focus-visible` class being added, i.e. whether it should always match
36
- * `:focus-visible` when focused.
37
- * @param {Element} node
38
- * @returns {boolean}
39
- */
40
- function focusTriggersKeyboardModality(node) {
41
- const {
42
- type,
43
- tagName
44
- } = node;
45
- if (tagName === 'INPUT' && inputTypesWhitelist[type] && !node.readOnly) {
46
- return true;
47
- }
48
- if (tagName === 'TEXTAREA' && !node.readOnly) {
49
- return true;
50
- }
51
- if (node.isContentEditable) {
52
- return true;
53
- }
54
- return false;
55
- }
56
-
57
- /**
58
- * Keep track of our keyboard modality state with `hadKeyboardEvent`.
59
- * If the most recent user interaction was via the keyboard;
60
- * and the key press did not include a meta, alt/option, or control key;
61
- * then the modality is keyboard. Otherwise, the modality is not keyboard.
62
- * @param {KeyboardEvent} event
63
- */
64
- function handleKeyDown(event) {
65
- if (event.metaKey || event.altKey || event.ctrlKey) {
66
- return;
67
- }
68
- hadKeyboardEvent = true;
69
- }
70
-
71
- /**
72
- * If at any point a user clicks with a pointing device, ensure that we change
73
- * the modality away from keyboard.
74
- * This avoids the situation where a user presses a key on an already focused
75
- * element, and then clicks on a different element, focusing it with a
76
- * pointing device, while we still think we're in keyboard modality.
77
- */
78
- function handlePointerDown() {
79
- hadKeyboardEvent = false;
80
- }
81
- function handleVisibilityChange() {
82
- if (this.visibilityState === 'hidden') {
83
- // If the tab becomes active again, the browser will handle calling focus
84
- // on the element (Safari actually calls it twice).
85
- // If this tab change caused a blur on an element with focus-visible,
86
- // re-apply the class when the user switches back to the tab.
87
- if (hadFocusVisibleRecently) {
88
- hadKeyboardEvent = true;
89
- }
90
- }
91
- }
92
- function prepare(doc) {
93
- doc.addEventListener('keydown', handleKeyDown, true);
94
- doc.addEventListener('mousedown', handlePointerDown, true);
95
- doc.addEventListener('pointerdown', handlePointerDown, true);
96
- doc.addEventListener('touchstart', handlePointerDown, true);
97
- doc.addEventListener('visibilitychange', handleVisibilityChange, true);
98
- }
99
- function teardown(doc) {
100
- doc.removeEventListener('keydown', handleKeyDown, true);
101
- doc.removeEventListener('mousedown', handlePointerDown, true);
102
- doc.removeEventListener('pointerdown', handlePointerDown, true);
103
- doc.removeEventListener('touchstart', handlePointerDown, true);
104
- doc.removeEventListener('visibilitychange', handleVisibilityChange, true);
105
- }
106
- function isFocusVisible(event) {
107
- const {
108
- target
109
- } = event;
110
- try {
111
- return target.matches(':focus-visible');
112
- } catch (error) {
113
- // Browsers not implementing :focus-visible will throw a SyntaxError.
114
- // We use our own heuristic for those browsers.
115
- // Rethrow might be better if it's not the expected error but do we really
116
- // want to crash if focus-visible malfunctioned?
117
- }
118
-
119
- // No need for validFocusTarget check. The user does that by attaching it to
120
- // focusable events only.
121
- return hadKeyboardEvent || focusTriggersKeyboardModality(target);
122
- }
123
- function useIsFocusVisible() {
124
- const ref = React.useCallback(node => {
125
- if (node != null) {
126
- prepare(node.ownerDocument);
127
- }
128
- }, []);
129
- const isFocusVisibleRef = React.useRef(false);
130
-
131
- /**
132
- * Should be called if a blur event is fired
133
- */
134
- function handleBlurVisible() {
135
- // checking against potential state variable does not suffice if we focus and blur synchronously.
136
- // React wouldn't have time to trigger a re-render so `focusVisible` would be stale.
137
- // Ideally we would adjust `isFocusVisible(event)` to look at `relatedTarget` for blur events.
138
- // This doesn't work in IE11 due to https://github.com/facebook/react/issues/3751
139
- // TODO: check again if React releases their internal changes to focus event handling (https://github.com/facebook/react/pull/19186).
140
- if (isFocusVisibleRef.current) {
141
- // To detect a tab/window switch, we look for a blur event followed
142
- // rapidly by a visibility change.
143
- // If we don't see a visibility change within 100ms, it's probably a
144
- // regular focus change.
145
- hadFocusVisibleRecently = true;
146
- hadFocusVisibleRecentlyTimeout.start(100, () => {
147
- hadFocusVisibleRecently = false;
148
- });
149
- isFocusVisibleRef.current = false;
150
- return true;
151
- }
152
- return false;
153
- }
154
-
155
- /**
156
- * Should be called if a blur event is fired
157
- */
158
- function handleFocusVisible(event) {
159
- if (isFocusVisible(event)) {
160
- isFocusVisibleRef.current = true;
161
- return true;
162
- }
163
- return false;
164
- }
165
- return {
166
- isFocusVisibleRef,
167
- onFocus: handleFocusVisible,
168
- onBlur: handleBlurVisible,
169
- ref
170
- };
171
- }
@@ -1 +0,0 @@
1
- export * from './scrollLeft';
@@ -1 +0,0 @@
1
- export * from './scrollLeft';
@@ -1,2 +0,0 @@
1
- export function detectScrollType(): string;
2
- export function getNormalizedScrollLeft(element: HTMLElement, direction: string): number;
@@ -1,70 +0,0 @@
1
- // Source from https://github.com/alitaheri/normalize-scroll-left
2
- let cachedType;
3
-
4
- /**
5
- * Based on the jquery plugin https://github.com/othree/jquery.rtl-scroll-type
6
- *
7
- * Types of scrollLeft, assuming scrollWidth=100 and direction is rtl.
8
- *
9
- * Type | <- Most Left | Most Right -> | Initial
10
- * ---------------- | ------------ | ------------- | -------
11
- * default | 0 | 100 | 100
12
- * negative (spec*) | -100 | 0 | 0
13
- * reverse | 100 | 0 | 0
14
- *
15
- * Edge 85: default
16
- * Safari 14: negative
17
- * Chrome 85: negative
18
- * Firefox 81: negative
19
- * IE11: reverse
20
- *
21
- * spec* https://drafts.csswg.org/cssom-view/#dom-window-scroll
22
- */
23
- export function detectScrollType() {
24
- if (cachedType) {
25
- return cachedType;
26
- }
27
- const dummy = document.createElement('div');
28
- const container = document.createElement('div');
29
- container.style.width = '10px';
30
- container.style.height = '1px';
31
- dummy.appendChild(container);
32
- dummy.dir = 'rtl';
33
- dummy.style.fontSize = '14px';
34
- dummy.style.width = '4px';
35
- dummy.style.height = '1px';
36
- dummy.style.position = 'absolute';
37
- dummy.style.top = '-1000px';
38
- dummy.style.overflow = 'scroll';
39
- document.body.appendChild(dummy);
40
- cachedType = 'reverse';
41
- if (dummy.scrollLeft > 0) {
42
- cachedType = 'default';
43
- } else {
44
- dummy.scrollLeft = 1;
45
- if (dummy.scrollLeft === 0) {
46
- cachedType = 'negative';
47
- }
48
- }
49
- document.body.removeChild(dummy);
50
- return cachedType;
51
- }
52
-
53
- // Based on https://stackoverflow.com/a/24394376
54
- export function getNormalizedScrollLeft(element, direction) {
55
- const scrollLeft = element.scrollLeft;
56
-
57
- // Perform the calculations only when direction is rtl to avoid messing up the ltr behavior
58
- if (direction !== 'rtl') {
59
- return scrollLeft;
60
- }
61
- const type = detectScrollType();
62
- switch (type) {
63
- case 'negative':
64
- return element.scrollWidth - element.clientWidth + scrollLeft;
65
- case 'reverse':
66
- return element.scrollWidth - element.clientWidth - scrollLeft;
67
- default:
68
- return scrollLeft;
69
- }
70
- }
@@ -1,2 +0,0 @@
1
- export { default } from './useIsFocusVisible';
2
- export * from './useIsFocusVisible';
@@ -1,2 +0,0 @@
1
- export { default } from './useIsFocusVisible';
2
- export * from './useIsFocusVisible';
@@ -1,6 +0,0 @@
1
- {
2
- "sideEffects": false,
3
- "module": "./index.js",
4
- "main": "../node/useIsFocusVisible/index.js",
5
- "types": "./index.d.ts"
6
- }
@@ -1,9 +0,0 @@
1
- import * as React from 'react';
2
- export declare function teardown(doc: Document): void;
3
- export interface UseIsFocusVisibleResult {
4
- isFocusVisibleRef: React.MutableRefObject<boolean>;
5
- onBlur: (event: React.FocusEvent<any>) => void;
6
- onFocus: (event: React.FocusEvent<any>) => void;
7
- ref: React.RefCallback<Element>;
8
- }
9
- export default function useIsFocusVisible(): UseIsFocusVisibleResult;
@@ -1,163 +0,0 @@
1
- 'use client';
2
-
3
- // based on https://github.com/WICG/focus-visible/blob/v4.1.5/src/focus-visible.js
4
- import * as React from 'react';
5
- import { Timeout } from '../useTimeout/useTimeout';
6
- let hadKeyboardEvent = true;
7
- let hadFocusVisibleRecently = false;
8
- const hadFocusVisibleRecentlyTimeout = new Timeout();
9
- const inputTypesWhitelist = {
10
- text: true,
11
- search: true,
12
- url: true,
13
- tel: true,
14
- email: true,
15
- password: true,
16
- number: true,
17
- date: true,
18
- month: true,
19
- week: true,
20
- time: true,
21
- datetime: true,
22
- 'datetime-local': true
23
- };
24
-
25
- /**
26
- * Computes whether the given element should automatically trigger the
27
- * `focus-visible` class being added, i.e. whether it should always match
28
- * `:focus-visible` when focused.
29
- * @param {Element} node
30
- * @returns {boolean}
31
- */
32
- function focusTriggersKeyboardModality(node) {
33
- const {
34
- type,
35
- tagName
36
- } = node;
37
- if (tagName === 'INPUT' && inputTypesWhitelist[type] && !node.readOnly) {
38
- return true;
39
- }
40
- if (tagName === 'TEXTAREA' && !node.readOnly) {
41
- return true;
42
- }
43
- if (node.isContentEditable) {
44
- return true;
45
- }
46
- return false;
47
- }
48
-
49
- /**
50
- * Keep track of our keyboard modality state with `hadKeyboardEvent`.
51
- * If the most recent user interaction was via the keyboard;
52
- * and the key press did not include a meta, alt/option, or control key;
53
- * then the modality is keyboard. Otherwise, the modality is not keyboard.
54
- * @param {KeyboardEvent} event
55
- */
56
- function handleKeyDown(event) {
57
- if (event.metaKey || event.altKey || event.ctrlKey) {
58
- return;
59
- }
60
- hadKeyboardEvent = true;
61
- }
62
-
63
- /**
64
- * If at any point a user clicks with a pointing device, ensure that we change
65
- * the modality away from keyboard.
66
- * This avoids the situation where a user presses a key on an already focused
67
- * element, and then clicks on a different element, focusing it with a
68
- * pointing device, while we still think we're in keyboard modality.
69
- */
70
- function handlePointerDown() {
71
- hadKeyboardEvent = false;
72
- }
73
- function handleVisibilityChange() {
74
- if (this.visibilityState === 'hidden') {
75
- // If the tab becomes active again, the browser will handle calling focus
76
- // on the element (Safari actually calls it twice).
77
- // If this tab change caused a blur on an element with focus-visible,
78
- // re-apply the class when the user switches back to the tab.
79
- if (hadFocusVisibleRecently) {
80
- hadKeyboardEvent = true;
81
- }
82
- }
83
- }
84
- function prepare(doc) {
85
- doc.addEventListener('keydown', handleKeyDown, true);
86
- doc.addEventListener('mousedown', handlePointerDown, true);
87
- doc.addEventListener('pointerdown', handlePointerDown, true);
88
- doc.addEventListener('touchstart', handlePointerDown, true);
89
- doc.addEventListener('visibilitychange', handleVisibilityChange, true);
90
- }
91
- export function teardown(doc) {
92
- doc.removeEventListener('keydown', handleKeyDown, true);
93
- doc.removeEventListener('mousedown', handlePointerDown, true);
94
- doc.removeEventListener('pointerdown', handlePointerDown, true);
95
- doc.removeEventListener('touchstart', handlePointerDown, true);
96
- doc.removeEventListener('visibilitychange', handleVisibilityChange, true);
97
- }
98
- function isFocusVisible(event) {
99
- const {
100
- target
101
- } = event;
102
- try {
103
- return target.matches(':focus-visible');
104
- } catch (error) {
105
- // Browsers not implementing :focus-visible will throw a SyntaxError.
106
- // We use our own heuristic for those browsers.
107
- // Rethrow might be better if it's not the expected error but do we really
108
- // want to crash if focus-visible malfunctioned?
109
- }
110
-
111
- // No need for validFocusTarget check. The user does that by attaching it to
112
- // focusable events only.
113
- return hadKeyboardEvent || focusTriggersKeyboardModality(target);
114
- }
115
- export default function useIsFocusVisible() {
116
- const ref = React.useCallback(node => {
117
- if (node != null) {
118
- prepare(node.ownerDocument);
119
- }
120
- }, []);
121
- const isFocusVisibleRef = React.useRef(false);
122
-
123
- /**
124
- * Should be called if a blur event is fired
125
- */
126
- function handleBlurVisible() {
127
- // checking against potential state variable does not suffice if we focus and blur synchronously.
128
- // React wouldn't have time to trigger a re-render so `focusVisible` would be stale.
129
- // Ideally we would adjust `isFocusVisible(event)` to look at `relatedTarget` for blur events.
130
- // This doesn't work in IE11 due to https://github.com/facebook/react/issues/3751
131
- // TODO: check again if React releases their internal changes to focus event handling (https://github.com/facebook/react/pull/19186).
132
- if (isFocusVisibleRef.current) {
133
- // To detect a tab/window switch, we look for a blur event followed
134
- // rapidly by a visibility change.
135
- // If we don't see a visibility change within 100ms, it's probably a
136
- // regular focus change.
137
- hadFocusVisibleRecently = true;
138
- hadFocusVisibleRecentlyTimeout.start(100, () => {
139
- hadFocusVisibleRecently = false;
140
- });
141
- isFocusVisibleRef.current = false;
142
- return true;
143
- }
144
- return false;
145
- }
146
-
147
- /**
148
- * Should be called if a blur event is fired
149
- */
150
- function handleFocusVisible(event) {
151
- if (isFocusVisible(event)) {
152
- isFocusVisibleRef.current = true;
153
- return true;
154
- }
155
- return false;
156
- }
157
- return {
158
- isFocusVisibleRef,
159
- onFocus: handleFocusVisible,
160
- onBlur: handleBlurVisible,
161
- ref
162
- };
163
- }