@atlaskit/top-layer 0.12.1 → 0.13.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 (196) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/dist/cjs/animations/presets.js +5 -5
  3. package/dist/cjs/dialog/create-close-event.js +1 -1
  4. package/dist/cjs/dialog/dialog-content.js +5 -5
  5. package/dist/cjs/entry-points/focus.js +6 -4
  6. package/dist/cjs/entry-points/use-anchor-position-at-point.js +12 -0
  7. package/dist/cjs/focus/get-first-focusable.js +19 -0
  8. package/dist/cjs/focus/get-focusables.js +30 -0
  9. package/dist/cjs/focus/get-last-focusable.js +19 -0
  10. package/dist/cjs/focus/get-next-focusable.js +43 -0
  11. package/dist/cjs/focus/is-in-same-layer.js +23 -0
  12. package/dist/cjs/focus/is-nested-layer-focused.js +32 -0
  13. package/dist/cjs/focus/selectors.js +19 -0
  14. package/dist/cjs/focus/types.js +1 -0
  15. package/dist/cjs/internal/ensure-preset-styles.js +1 -1
  16. package/dist/cjs/internal/reduced-motion.js +1 -1
  17. package/dist/cjs/internal/resolve-placement.js +2 -2
  18. package/dist/cjs/internal/role-to-aria-has-popup.js +37 -0
  19. package/dist/cjs/internal/role-types.js +1 -97
  20. package/dist/cjs/internal/should-focus-into-popover.js +19 -0
  21. package/dist/cjs/internal/slot.js +3 -3
  22. package/dist/cjs/internal/use-anchor-position-at-point.js +127 -0
  23. package/dist/cjs/internal/use-anchor-position.js +22 -33
  24. package/dist/cjs/internal/use-animated-visibility.js +10 -10
  25. package/dist/cjs/internal/use-animation-preset.js +1 -1
  26. package/dist/cjs/internal/use-focus-wrap.js +8 -5
  27. package/dist/cjs/internal/use-initial-focus.js +4 -4
  28. package/dist/cjs/internal/use-preset-styles.js +1 -1
  29. package/dist/cjs/internal/use-width-from-anchor.js +4 -4
  30. package/dist/cjs/placement-map/index.js +2 -2
  31. package/dist/cjs/placement-map/legacy-placements.js +2 -101
  32. package/dist/cjs/placement-map/placement-mapping.js +103 -0
  33. package/dist/cjs/popover/create-close-event.js +1 -1
  34. package/dist/cjs/popover/popover.js +3 -3
  35. package/dist/cjs/popup/popup-content.js +8 -7
  36. package/dist/cjs/testing/polyfill.js +8 -8
  37. package/dist/cjs/testing/to-be-visible.js +5 -5
  38. package/dist/cjs/use-arrow-navigation/is-at-current-menu-level.js +19 -12
  39. package/dist/cjs/use-arrow-navigation/use-arrow-navigation.js +7 -5
  40. package/dist/cjs/use-simple-light-dismiss/index.js +3 -3
  41. package/dist/es2019/animations/presets.js +5 -5
  42. package/dist/es2019/dialog/create-close-event.js +1 -1
  43. package/dist/es2019/dialog/dialog-content.js +5 -5
  44. package/dist/es2019/entry-points/focus.js +3 -1
  45. package/dist/es2019/entry-points/use-anchor-position-at-point.js +1 -0
  46. package/dist/es2019/focus/get-first-focusable.js +14 -0
  47. package/dist/es2019/focus/get-focusables.js +19 -0
  48. package/dist/es2019/focus/get-last-focusable.js +14 -0
  49. package/dist/es2019/focus/get-next-focusable.js +38 -0
  50. package/dist/es2019/focus/is-in-same-layer.js +18 -0
  51. package/dist/es2019/focus/is-nested-layer-focused.js +28 -0
  52. package/dist/es2019/focus/selectors.js +11 -0
  53. package/dist/es2019/focus/types.js +0 -0
  54. package/dist/es2019/internal/ensure-preset-styles.js +1 -1
  55. package/dist/es2019/internal/reduced-motion.js +1 -1
  56. package/dist/es2019/internal/resolve-placement.js +2 -2
  57. package/dist/es2019/internal/role-to-aria-has-popup.js +32 -0
  58. package/dist/es2019/internal/role-types.js +0 -92
  59. package/dist/es2019/internal/should-focus-into-popover.js +14 -0
  60. package/dist/es2019/internal/slot.js +3 -3
  61. package/dist/es2019/internal/use-anchor-position-at-point.js +122 -0
  62. package/dist/es2019/internal/use-anchor-position.js +19 -19
  63. package/dist/es2019/internal/use-animated-visibility.js +10 -10
  64. package/dist/es2019/internal/use-animation-preset.js +1 -1
  65. package/dist/es2019/internal/use-focus-wrap.js +4 -1
  66. package/dist/es2019/internal/use-initial-focus.js +1 -1
  67. package/dist/es2019/internal/use-preset-styles.js +1 -1
  68. package/dist/es2019/internal/use-width-from-anchor.js +4 -4
  69. package/dist/es2019/placement-map/index.js +1 -1
  70. package/dist/es2019/placement-map/legacy-placements.js +1 -100
  71. package/dist/es2019/placement-map/placement-mapping.js +97 -0
  72. package/dist/es2019/popover/create-close-event.js +1 -1
  73. package/dist/es2019/popover/popover.js +3 -3
  74. package/dist/es2019/popup/popup-content.js +6 -5
  75. package/dist/es2019/testing/polyfill.js +8 -8
  76. package/dist/es2019/testing/to-be-visible.js +5 -5
  77. package/dist/es2019/use-arrow-navigation/is-at-current-menu-level.js +19 -12
  78. package/dist/es2019/use-arrow-navigation/use-arrow-navigation.js +3 -1
  79. package/dist/es2019/use-simple-light-dismiss/index.js +3 -3
  80. package/dist/esm/animations/presets.js +5 -5
  81. package/dist/esm/dialog/create-close-event.js +1 -1
  82. package/dist/esm/dialog/dialog-content.js +5 -5
  83. package/dist/esm/entry-points/focus.js +3 -1
  84. package/dist/esm/entry-points/use-anchor-position-at-point.js +1 -0
  85. package/dist/esm/focus/get-first-focusable.js +13 -0
  86. package/dist/esm/focus/get-focusables.js +24 -0
  87. package/dist/esm/focus/get-last-focusable.js +13 -0
  88. package/dist/esm/focus/get-next-focusable.js +37 -0
  89. package/dist/esm/focus/is-in-same-layer.js +17 -0
  90. package/dist/esm/focus/is-nested-layer-focused.js +27 -0
  91. package/dist/esm/focus/selectors.js +13 -0
  92. package/dist/esm/focus/types.js +0 -0
  93. package/dist/esm/internal/ensure-preset-styles.js +1 -1
  94. package/dist/esm/internal/reduced-motion.js +1 -1
  95. package/dist/esm/internal/resolve-placement.js +2 -2
  96. package/dist/esm/internal/role-to-aria-has-popup.js +31 -0
  97. package/dist/esm/internal/role-types.js +0 -90
  98. package/dist/esm/internal/should-focus-into-popover.js +13 -0
  99. package/dist/esm/internal/slot.js +3 -3
  100. package/dist/esm/internal/use-anchor-position-at-point.js +122 -0
  101. package/dist/esm/internal/use-anchor-position.js +22 -33
  102. package/dist/esm/internal/use-animated-visibility.js +10 -10
  103. package/dist/esm/internal/use-animation-preset.js +1 -1
  104. package/dist/esm/internal/use-focus-wrap.js +4 -1
  105. package/dist/esm/internal/use-initial-focus.js +1 -1
  106. package/dist/esm/internal/use-preset-styles.js +1 -1
  107. package/dist/esm/internal/use-width-from-anchor.js +4 -4
  108. package/dist/esm/placement-map/index.js +1 -1
  109. package/dist/esm/placement-map/legacy-placements.js +1 -100
  110. package/dist/esm/placement-map/placement-mapping.js +97 -0
  111. package/dist/esm/popover/create-close-event.js +1 -1
  112. package/dist/esm/popover/popover.js +3 -3
  113. package/dist/esm/popup/popup-content.js +6 -5
  114. package/dist/esm/testing/polyfill.js +8 -8
  115. package/dist/esm/testing/to-be-visible.js +5 -5
  116. package/dist/esm/use-arrow-navigation/is-at-current-menu-level.js +19 -12
  117. package/dist/esm/use-arrow-navigation/use-arrow-navigation.js +3 -1
  118. package/dist/esm/use-simple-light-dismiss/index.js +3 -3
  119. package/dist/types/dialog/create-close-event.d.ts +1 -1
  120. package/dist/types/dialog/types.d.ts +8 -0
  121. package/dist/types/entry-points/focus.d.ts +4 -2
  122. package/dist/types/entry-points/use-anchor-position-at-point.d.ts +1 -0
  123. package/dist/types/focus/get-first-focusable.d.ts +8 -0
  124. package/dist/types/focus/get-focusables.d.ts +13 -0
  125. package/dist/types/focus/get-last-focusable.d.ts +8 -0
  126. package/dist/types/focus/get-next-focusable.d.ts +13 -0
  127. package/dist/types/focus/is-in-same-layer.d.ts +8 -0
  128. package/dist/types/focus/is-nested-layer-focused.d.ts +8 -0
  129. package/dist/types/focus/selectors.d.ts +4 -0
  130. package/dist/types/focus/types.d.ts +5 -0
  131. package/dist/types/internal/reduced-motion.d.ts +1 -1
  132. package/dist/types/internal/resolve-placement.d.ts +2 -2
  133. package/dist/types/internal/role-to-aria-has-popup.d.ts +13 -0
  134. package/dist/types/internal/role-types.d.ts +0 -19
  135. package/dist/types/internal/should-focus-into-popover.d.ts +8 -0
  136. package/dist/types/internal/slot.d.ts +4 -4
  137. package/dist/types/internal/use-anchor-position-at-point.d.ts +62 -0
  138. package/dist/types/internal/use-anchor-position.d.ts +6 -1
  139. package/dist/types/internal/use-animated-visibility.d.ts +3 -3
  140. package/dist/types/internal/use-animation-preset.d.ts +1 -1
  141. package/dist/types/internal/use-preset-styles.d.ts +1 -1
  142. package/dist/types/internal/use-width-from-anchor.d.ts +2 -2
  143. package/dist/types/placement-map/index.d.ts +1 -1
  144. package/dist/types/placement-map/legacy-placements.d.ts +0 -12
  145. package/dist/types/placement-map/placement-mapping.d.ts +13 -0
  146. package/dist/types/popover/create-close-event.d.ts +1 -1
  147. package/dist/types/popover/popover.d.ts +1 -1
  148. package/dist/types/popup/popup-context.d.ts +1 -1
  149. package/dist/types/testing/to-be-visible.d.ts +3 -3
  150. package/dist/types/use-arrow-navigation/use-arrow-navigation.d.ts +1 -1
  151. package/dist/types/use-simple-light-dismiss/index.d.ts +1 -1
  152. package/dist/types-ts4.5/dialog/create-close-event.d.ts +1 -1
  153. package/dist/types-ts4.5/dialog/types.d.ts +8 -0
  154. package/dist/types-ts4.5/entry-points/focus.d.ts +4 -2
  155. package/dist/types-ts4.5/entry-points/use-anchor-position-at-point.d.ts +1 -0
  156. package/dist/types-ts4.5/focus/get-first-focusable.d.ts +8 -0
  157. package/dist/types-ts4.5/focus/get-focusables.d.ts +13 -0
  158. package/dist/types-ts4.5/focus/get-last-focusable.d.ts +8 -0
  159. package/dist/types-ts4.5/focus/get-next-focusable.d.ts +13 -0
  160. package/dist/types-ts4.5/focus/is-in-same-layer.d.ts +8 -0
  161. package/dist/types-ts4.5/focus/is-nested-layer-focused.d.ts +8 -0
  162. package/dist/types-ts4.5/focus/selectors.d.ts +4 -0
  163. package/dist/types-ts4.5/focus/types.d.ts +5 -0
  164. package/dist/types-ts4.5/internal/reduced-motion.d.ts +1 -1
  165. package/dist/types-ts4.5/internal/resolve-placement.d.ts +2 -2
  166. package/dist/types-ts4.5/internal/role-to-aria-has-popup.d.ts +13 -0
  167. package/dist/types-ts4.5/internal/role-types.d.ts +0 -19
  168. package/dist/types-ts4.5/internal/should-focus-into-popover.d.ts +8 -0
  169. package/dist/types-ts4.5/internal/slot.d.ts +4 -4
  170. package/dist/types-ts4.5/internal/use-anchor-position-at-point.d.ts +62 -0
  171. package/dist/types-ts4.5/internal/use-anchor-position.d.ts +6 -1
  172. package/dist/types-ts4.5/internal/use-animated-visibility.d.ts +3 -3
  173. package/dist/types-ts4.5/internal/use-animation-preset.d.ts +1 -1
  174. package/dist/types-ts4.5/internal/use-preset-styles.d.ts +1 -1
  175. package/dist/types-ts4.5/internal/use-width-from-anchor.d.ts +2 -2
  176. package/dist/types-ts4.5/placement-map/index.d.ts +1 -1
  177. package/dist/types-ts4.5/placement-map/legacy-placements.d.ts +0 -12
  178. package/dist/types-ts4.5/placement-map/placement-mapping.d.ts +13 -0
  179. package/dist/types-ts4.5/popover/create-close-event.d.ts +1 -1
  180. package/dist/types-ts4.5/popover/popover.d.ts +1 -1
  181. package/dist/types-ts4.5/popup/popup-context.d.ts +1 -1
  182. package/dist/types-ts4.5/testing/to-be-visible.d.ts +3 -3
  183. package/dist/types-ts4.5/use-arrow-navigation/use-arrow-navigation.d.ts +1 -1
  184. package/dist/types-ts4.5/use-simple-light-dismiss/index.d.ts +1 -1
  185. package/package.json +1 -1
  186. package/use-anchor-position-at-point/package.json +17 -0
  187. package/dist/cjs/focus/focus.js +0 -169
  188. package/dist/cjs/focus/index.js +0 -24
  189. package/dist/es2019/focus/focus.js +0 -158
  190. package/dist/es2019/focus/index.js +0 -1
  191. package/dist/esm/focus/focus.js +0 -160
  192. package/dist/esm/focus/index.js +0 -1
  193. package/dist/types/focus/focus.d.ts +0 -50
  194. package/dist/types/focus/index.d.ts +0 -2
  195. package/dist/types-ts4.5/focus/focus.d.ts +0 -50
  196. package/dist/types-ts4.5/focus/index.d.ts +0 -2
@@ -3,13 +3,13 @@
3
3
  *
4
4
  * jest-dom's `toBeVisible()` does not know about the Popover API. In real
5
5
  * browsers the UA stylesheet hides `[popover]` with `display: none`, but
6
- * jsdom has no such stylesheet — so closed popovers incorrectly appear visible.
6
+ * jsdom has no such stylesheet - so closed popovers incorrectly appear visible.
7
7
  *
8
8
  * Raw jest-dom results in jsdom:
9
9
  *
10
- * closed popover / child → true (WRONG — should be false)
10
+ * closed popover / child → true (WRONG - should be false)
11
11
  * open popover / child → true (correct)
12
- * closed dialog / child → false (correct — jsdom natively hides <dialog>)
12
+ * closed dialog / child → false (correct - jsdom natively hides <dialog>)
13
13
  * open dialog / child → true (correct)
14
14
  *
15
15
  * We correct both false positives and false negatives:
@@ -1,5 +1,5 @@
1
1
  import { type RefObject } from 'react';
2
- import { type TFocusableFilter } from '../focus';
2
+ import { type TFocusableFilter } from '../focus/types';
3
3
  /**
4
4
  * Args for `useArrowNavigation`.
5
5
  *
@@ -34,7 +34,7 @@ type TUseSimpleLightDismissOptions = {
34
34
  * **No stacking awareness:** This hook does not track a popover stack.
35
35
  * If multiple manual popovers are open and all use this hook, a single
36
36
  * Escape press or outside click will dismiss **all of them simultaneously**.
37
- * This is by design — the hook is intentionally simple for cases where
37
+ * This is by design - the hook is intentionally simple for cases where
38
38
  * only one manual popover is open at a time.
39
39
  *
40
40
  * For stacked/nested popovers that should dismiss one-at-a-time, use
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/top-layer",
3
- "version": "0.12.1",
3
+ "version": "0.13.0",
4
4
  "description": "Low-level layering primitives based on popover and dialog",
5
5
  "homepage": "https://atlassian.design/components/top-layer",
6
6
  "repository": "https://bitbucket.org/atlassian/atlassian-frontend-mirror",
@@ -0,0 +1,17 @@
1
+ {
2
+ "name": "@atlaskit/top-layer/use-anchor-position-at-point",
3
+ "main": "../dist/cjs/entry-points/use-anchor-position-at-point.js",
4
+ "module": "../dist/esm/entry-points/use-anchor-position-at-point.js",
5
+ "module:es2019": "../dist/es2019/entry-points/use-anchor-position-at-point.js",
6
+ "sideEffects": [
7
+ "*.compiled.css"
8
+ ],
9
+ "types": "../dist/types/entry-points/use-anchor-position-at-point.d.ts",
10
+ "typesVersions": {
11
+ ">=4.5 <5.9": {
12
+ "*": [
13
+ "../dist/types-ts4.5/entry-points/use-anchor-position-at-point.d.ts"
14
+ ]
15
+ }
16
+ }
17
+ }
@@ -1,169 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.getFirstFocusable = getFirstFocusable;
7
- exports.getLastFocusable = getLastFocusable;
8
- exports.getNextFocusable = getNextFocusable;
9
- exports.isNestedLayerFocused = isNestedLayerFocused;
10
- var _browserApis = require("@atlaskit/browser-apis");
11
- /**
12
- * Focusable element selectors and navigation helpers.
13
- *
14
- * Uses CSS selectors to discover focusable elements within a container,
15
- * avoiding the need for a manual registration system. Disabled elements
16
- * (both HTML `disabled` attribute and `aria-disabled="true"`) and elements
17
- * with `tabindex="-1"` are excluded automatically.
18
- *
19
- * All public functions accept an optional `filter` callback to further
20
- * restrict which focusable elements are included.
21
- */
22
-
23
- var selectors = function () {
24
- // Common exclusion filter applied to every selector.
25
- var not = ':not([tabindex="-1"]):not([aria-disabled="true"]):not([aria-hidden="true"])';
26
- var notDisabled = ":not([disabled])".concat(not);
27
- var focusable = ["a[href]".concat(not), "area[href]".concat(not), "input".concat(notDisabled, ":not([type=\"hidden\"])"), "select".concat(notDisabled), "textarea".concat(notDisabled), "button".concat(notDisabled), "iframe".concat(not), "audio[controls]".concat(not), "video[controls]".concat(not), "[contenteditable]:not([contenteditable=\"false\"])".concat(not), "[tabindex]".concat(notDisabled).concat(not)];
28
- return {
29
- focusable: focusable.join(','),
30
- // Build the `:focus` selector
31
- focused: focusable.map(function (selector) {
32
- return "".concat(selector, ":focus");
33
- }).join(',')
34
- };
35
- }();
36
- var topLayerSelector = '[popover], dialog, [role="dialog"], [role="alertdialog"]';
37
-
38
- /**
39
- * Returns true when `element` and `container` resolve to the same nearest
40
- * top-layer host (or both resolve to `null`, meaning the document layer).
41
- */
42
- function isInSameLayer(_ref) {
43
- var element = _ref.element,
44
- container = _ref.container;
45
- var elementLayer = element.closest(topLayerSelector);
46
- var containerLayer = container.closest(topLayerSelector);
47
- // Both elements are in the "document" layer
48
- if (!elementLayer && !containerLayer) {
49
- return true;
50
- }
51
- return elementLayer === containerLayer;
52
- }
53
-
54
- /**
55
- * Returns `true` when `document.activeElement` is inside a nested top-layer
56
- * descendant of `container` (a `[popover]`, `<dialog>`, `[role="dialog"]` or
57
- * `[role="alertdialog"]` that is itself a descendant of `container`).
58
- */
59
- function isNestedLayerFocused(_ref2) {
60
- var _getDocument;
61
- var container = _ref2.container;
62
- var focused = (_getDocument = (0, _browserApis.getDocument)()) === null || _getDocument === void 0 ? void 0 : _getDocument.activeElement;
63
- if (!(focused instanceof HTMLElement)) {
64
- return false;
65
- }
66
-
67
- // Cannot be in a nested layer if it is not in the container
68
- if (!container.contains(focused)) {
69
- return false;
70
- }
71
-
72
- // If not in the same layer, must be in a nested layer
73
- return !isInSameLayer({
74
- element: focused,
75
- container: container
76
- });
77
- }
78
-
79
- /**
80
- * An optional callback to restrict which focusable elements are included.
81
- * Return `true` to include the element, `false` to skip it.
82
- */
83
-
84
- /**
85
- * Returns all focusable HTMLElements within the container, optionally filtered.
86
- *
87
- * Focusables that belong to a nested top-layer scope (a `[popover]` or
88
- * `<dialog>` descendant of the container) are excluded - those elements
89
- * are owned by the inner layer's focus management. The container itself
90
- * is allowed to be a popover/dialog; only nested ones are filtered.
91
- */
92
- function getFocusables(_ref3) {
93
- var container = _ref3.container,
94
- filter = _ref3.filter;
95
- return Array.from(container.querySelectorAll(selectors.focusable)).filter(function (element) {
96
- return element instanceof HTMLElement;
97
- }).filter(function (element) {
98
- return isInSameLayer({
99
- element: element,
100
- container: container
101
- });
102
- }).filter(function (element) {
103
- return !filter || filter(element, container);
104
- });
105
- }
106
-
107
- /**
108
- * Returns the first focusable element within the container.
109
- */
110
- // eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports
111
- function getFirstFocusable(_ref4) {
112
- var container = _ref4.container,
113
- filter = _ref4.filter;
114
- var items = getFocusables({
115
- container: container,
116
- filter: filter
117
- });
118
- return items.length > 0 ? items[0] : null;
119
- }
120
-
121
- /**
122
- * Returns the last focusable element within the container.
123
- */
124
- // eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports
125
- function getLastFocusable(_ref5) {
126
- var container = _ref5.container,
127
- filter = _ref5.filter;
128
- var items = getFocusables({
129
- container: container,
130
- filter: filter
131
- });
132
- return items.length > 0 ? items[items.length - 1] : null;
133
- }
134
-
135
- /**
136
- * Returns the next focusable element in the given direction relative to the
137
- * currently focused element within the container. Wraps around at both ends.
138
- *
139
- * Returns `null` if there is no focused element within the container or if
140
- * the focused element is not in the list of focusable elements.
141
- */
142
- // eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports
143
- function getNextFocusable(_ref6) {
144
- var _all$nextIndex;
145
- var container = _ref6.container,
146
- direction = _ref6.direction,
147
- filter = _ref6.filter;
148
- var all = getFocusables({
149
- container: container,
150
- filter: filter
151
- });
152
- var current = container.querySelector(selectors.focused);
153
- if (!(current instanceof HTMLElement)) {
154
- return null;
155
- }
156
- var index = all.indexOf(current);
157
- if (index === -1) {
158
- return null;
159
- }
160
- var nextIndex = function () {
161
- if (direction === 'forwards') {
162
- return (index + 1) % all.length;
163
- }
164
- var proposed = index - 1;
165
- // if going into negative numbers, loop back to the last item
166
- return proposed < 0 ? all.length - 1 : proposed;
167
- }();
168
- return (_all$nextIndex = all[nextIndex]) !== null && _all$nextIndex !== void 0 ? _all$nextIndex : null;
169
- }
@@ -1,24 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- Object.defineProperty(exports, "getFirstFocusable", {
7
- enumerable: true,
8
- get: function get() {
9
- return _focus.getFirstFocusable;
10
- }
11
- });
12
- Object.defineProperty(exports, "getLastFocusable", {
13
- enumerable: true,
14
- get: function get() {
15
- return _focus.getLastFocusable;
16
- }
17
- });
18
- Object.defineProperty(exports, "getNextFocusable", {
19
- enumerable: true,
20
- get: function get() {
21
- return _focus.getNextFocusable;
22
- }
23
- });
24
- var _focus = require("./focus");
@@ -1,158 +0,0 @@
1
- /**
2
- * Focusable element selectors and navigation helpers.
3
- *
4
- * Uses CSS selectors to discover focusable elements within a container,
5
- * avoiding the need for a manual registration system. Disabled elements
6
- * (both HTML `disabled` attribute and `aria-disabled="true"`) and elements
7
- * with `tabindex="-1"` are excluded automatically.
8
- *
9
- * All public functions accept an optional `filter` callback to further
10
- * restrict which focusable elements are included.
11
- */
12
-
13
- import { getDocument } from '@atlaskit/browser-apis';
14
- const selectors = (() => {
15
- // Common exclusion filter applied to every selector.
16
- const not = ':not([tabindex="-1"]):not([aria-disabled="true"]):not([aria-hidden="true"])';
17
- const notDisabled = `:not([disabled])${not}`;
18
- const focusable = [`a[href]${not}`, `area[href]${not}`, `input${notDisabled}:not([type="hidden"])`, `select${notDisabled}`, `textarea${notDisabled}`, `button${notDisabled}`, `iframe${not}`, `audio[controls]${not}`, `video[controls]${not}`, `[contenteditable]:not([contenteditable="false"])${not}`, `[tabindex]${notDisabled}${not}`];
19
- return {
20
- focusable: focusable.join(','),
21
- // Build the `:focus` selector
22
- focused: focusable.map(selector => `${selector}:focus`).join(',')
23
- };
24
- })();
25
- const topLayerSelector = '[popover], dialog, [role="dialog"], [role="alertdialog"]';
26
-
27
- /**
28
- * Returns true when `element` and `container` resolve to the same nearest
29
- * top-layer host (or both resolve to `null`, meaning the document layer).
30
- */
31
- function isInSameLayer({
32
- element,
33
- container
34
- }) {
35
- const elementLayer = element.closest(topLayerSelector);
36
- const containerLayer = container.closest(topLayerSelector);
37
- // Both elements are in the "document" layer
38
- if (!elementLayer && !containerLayer) {
39
- return true;
40
- }
41
- return elementLayer === containerLayer;
42
- }
43
-
44
- /**
45
- * Returns `true` when `document.activeElement` is inside a nested top-layer
46
- * descendant of `container` (a `[popover]`, `<dialog>`, `[role="dialog"]` or
47
- * `[role="alertdialog"]` that is itself a descendant of `container`).
48
- */
49
- export function isNestedLayerFocused({
50
- container
51
- }) {
52
- var _getDocument;
53
- const focused = (_getDocument = getDocument()) === null || _getDocument === void 0 ? void 0 : _getDocument.activeElement;
54
- if (!(focused instanceof HTMLElement)) {
55
- return false;
56
- }
57
-
58
- // Cannot be in a nested layer if it is not in the container
59
- if (!container.contains(focused)) {
60
- return false;
61
- }
62
-
63
- // If not in the same layer, must be in a nested layer
64
- return !isInSameLayer({
65
- element: focused,
66
- container
67
- });
68
- }
69
-
70
- /**
71
- * An optional callback to restrict which focusable elements are included.
72
- * Return `true` to include the element, `false` to skip it.
73
- */
74
-
75
- /**
76
- * Returns all focusable HTMLElements within the container, optionally filtered.
77
- *
78
- * Focusables that belong to a nested top-layer scope (a `[popover]` or
79
- * `<dialog>` descendant of the container) are excluded - those elements
80
- * are owned by the inner layer's focus management. The container itself
81
- * is allowed to be a popover/dialog; only nested ones are filtered.
82
- */
83
- function getFocusables({
84
- container,
85
- filter
86
- }) {
87
- return Array.from(container.querySelectorAll(selectors.focusable)).filter(element => element instanceof HTMLElement).filter(element => isInSameLayer({
88
- element,
89
- container
90
- })).filter(element => !filter || filter(element, container));
91
- }
92
-
93
- /**
94
- * Returns the first focusable element within the container.
95
- */
96
- // eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports
97
- export function getFirstFocusable({
98
- container,
99
- filter
100
- }) {
101
- const items = getFocusables({
102
- container,
103
- filter
104
- });
105
- return items.length > 0 ? items[0] : null;
106
- }
107
-
108
- /**
109
- * Returns the last focusable element within the container.
110
- */
111
- // eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports
112
- export function getLastFocusable({
113
- container,
114
- filter
115
- }) {
116
- const items = getFocusables({
117
- container,
118
- filter
119
- });
120
- return items.length > 0 ? items[items.length - 1] : null;
121
- }
122
-
123
- /**
124
- * Returns the next focusable element in the given direction relative to the
125
- * currently focused element within the container. Wraps around at both ends.
126
- *
127
- * Returns `null` if there is no focused element within the container or if
128
- * the focused element is not in the list of focusable elements.
129
- */
130
- // eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports
131
- export function getNextFocusable({
132
- container,
133
- direction,
134
- filter
135
- }) {
136
- var _all$nextIndex;
137
- const all = getFocusables({
138
- container,
139
- filter
140
- });
141
- const current = container.querySelector(selectors.focused);
142
- if (!(current instanceof HTMLElement)) {
143
- return null;
144
- }
145
- const index = all.indexOf(current);
146
- if (index === -1) {
147
- return null;
148
- }
149
- const nextIndex = (() => {
150
- if (direction === 'forwards') {
151
- return (index + 1) % all.length;
152
- }
153
- const proposed = index - 1;
154
- // if going into negative numbers, loop back to the last item
155
- return proposed < 0 ? all.length - 1 : proposed;
156
- })();
157
- return (_all$nextIndex = all[nextIndex]) !== null && _all$nextIndex !== void 0 ? _all$nextIndex : null;
158
- }
@@ -1 +0,0 @@
1
- export { getFirstFocusable, getLastFocusable, getNextFocusable } from './focus';
@@ -1,160 +0,0 @@
1
- /**
2
- * Focusable element selectors and navigation helpers.
3
- *
4
- * Uses CSS selectors to discover focusable elements within a container,
5
- * avoiding the need for a manual registration system. Disabled elements
6
- * (both HTML `disabled` attribute and `aria-disabled="true"`) and elements
7
- * with `tabindex="-1"` are excluded automatically.
8
- *
9
- * All public functions accept an optional `filter` callback to further
10
- * restrict which focusable elements are included.
11
- */
12
-
13
- import { getDocument } from '@atlaskit/browser-apis';
14
- var selectors = function () {
15
- // Common exclusion filter applied to every selector.
16
- var not = ':not([tabindex="-1"]):not([aria-disabled="true"]):not([aria-hidden="true"])';
17
- var notDisabled = ":not([disabled])".concat(not);
18
- var focusable = ["a[href]".concat(not), "area[href]".concat(not), "input".concat(notDisabled, ":not([type=\"hidden\"])"), "select".concat(notDisabled), "textarea".concat(notDisabled), "button".concat(notDisabled), "iframe".concat(not), "audio[controls]".concat(not), "video[controls]".concat(not), "[contenteditable]:not([contenteditable=\"false\"])".concat(not), "[tabindex]".concat(notDisabled).concat(not)];
19
- return {
20
- focusable: focusable.join(','),
21
- // Build the `:focus` selector
22
- focused: focusable.map(function (selector) {
23
- return "".concat(selector, ":focus");
24
- }).join(',')
25
- };
26
- }();
27
- var topLayerSelector = '[popover], dialog, [role="dialog"], [role="alertdialog"]';
28
-
29
- /**
30
- * Returns true when `element` and `container` resolve to the same nearest
31
- * top-layer host (or both resolve to `null`, meaning the document layer).
32
- */
33
- function isInSameLayer(_ref) {
34
- var element = _ref.element,
35
- container = _ref.container;
36
- var elementLayer = element.closest(topLayerSelector);
37
- var containerLayer = container.closest(topLayerSelector);
38
- // Both elements are in the "document" layer
39
- if (!elementLayer && !containerLayer) {
40
- return true;
41
- }
42
- return elementLayer === containerLayer;
43
- }
44
-
45
- /**
46
- * Returns `true` when `document.activeElement` is inside a nested top-layer
47
- * descendant of `container` (a `[popover]`, `<dialog>`, `[role="dialog"]` or
48
- * `[role="alertdialog"]` that is itself a descendant of `container`).
49
- */
50
- export function isNestedLayerFocused(_ref2) {
51
- var _getDocument;
52
- var container = _ref2.container;
53
- var focused = (_getDocument = getDocument()) === null || _getDocument === void 0 ? void 0 : _getDocument.activeElement;
54
- if (!(focused instanceof HTMLElement)) {
55
- return false;
56
- }
57
-
58
- // Cannot be in a nested layer if it is not in the container
59
- if (!container.contains(focused)) {
60
- return false;
61
- }
62
-
63
- // If not in the same layer, must be in a nested layer
64
- return !isInSameLayer({
65
- element: focused,
66
- container: container
67
- });
68
- }
69
-
70
- /**
71
- * An optional callback to restrict which focusable elements are included.
72
- * Return `true` to include the element, `false` to skip it.
73
- */
74
-
75
- /**
76
- * Returns all focusable HTMLElements within the container, optionally filtered.
77
- *
78
- * Focusables that belong to a nested top-layer scope (a `[popover]` or
79
- * `<dialog>` descendant of the container) are excluded - those elements
80
- * are owned by the inner layer's focus management. The container itself
81
- * is allowed to be a popover/dialog; only nested ones are filtered.
82
- */
83
- function getFocusables(_ref3) {
84
- var container = _ref3.container,
85
- filter = _ref3.filter;
86
- return Array.from(container.querySelectorAll(selectors.focusable)).filter(function (element) {
87
- return element instanceof HTMLElement;
88
- }).filter(function (element) {
89
- return isInSameLayer({
90
- element: element,
91
- container: container
92
- });
93
- }).filter(function (element) {
94
- return !filter || filter(element, container);
95
- });
96
- }
97
-
98
- /**
99
- * Returns the first focusable element within the container.
100
- */
101
- // eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports
102
- export function getFirstFocusable(_ref4) {
103
- var container = _ref4.container,
104
- filter = _ref4.filter;
105
- var items = getFocusables({
106
- container: container,
107
- filter: filter
108
- });
109
- return items.length > 0 ? items[0] : null;
110
- }
111
-
112
- /**
113
- * Returns the last focusable element within the container.
114
- */
115
- // eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports
116
- export function getLastFocusable(_ref5) {
117
- var container = _ref5.container,
118
- filter = _ref5.filter;
119
- var items = getFocusables({
120
- container: container,
121
- filter: filter
122
- });
123
- return items.length > 0 ? items[items.length - 1] : null;
124
- }
125
-
126
- /**
127
- * Returns the next focusable element in the given direction relative to the
128
- * currently focused element within the container. Wraps around at both ends.
129
- *
130
- * Returns `null` if there is no focused element within the container or if
131
- * the focused element is not in the list of focusable elements.
132
- */
133
- // eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports
134
- export function getNextFocusable(_ref6) {
135
- var _all$nextIndex;
136
- var container = _ref6.container,
137
- direction = _ref6.direction,
138
- filter = _ref6.filter;
139
- var all = getFocusables({
140
- container: container,
141
- filter: filter
142
- });
143
- var current = container.querySelector(selectors.focused);
144
- if (!(current instanceof HTMLElement)) {
145
- return null;
146
- }
147
- var index = all.indexOf(current);
148
- if (index === -1) {
149
- return null;
150
- }
151
- var nextIndex = function () {
152
- if (direction === 'forwards') {
153
- return (index + 1) % all.length;
154
- }
155
- var proposed = index - 1;
156
- // if going into negative numbers, loop back to the last item
157
- return proposed < 0 ? all.length - 1 : proposed;
158
- }();
159
- return (_all$nextIndex = all[nextIndex]) !== null && _all$nextIndex !== void 0 ? _all$nextIndex : null;
160
- }
@@ -1 +0,0 @@
1
- export { getFirstFocusable, getLastFocusable, getNextFocusable } from './focus';
@@ -1,50 +0,0 @@
1
- /**
2
- * Focusable element selectors and navigation helpers.
3
- *
4
- * Uses CSS selectors to discover focusable elements within a container,
5
- * avoiding the need for a manual registration system. Disabled elements
6
- * (both HTML `disabled` attribute and `aria-disabled="true"`) and elements
7
- * with `tabindex="-1"` are excluded automatically.
8
- *
9
- * All public functions accept an optional `filter` callback to further
10
- * restrict which focusable elements are included.
11
- */
12
- /**
13
- * Returns `true` when `document.activeElement` is inside a nested top-layer
14
- * descendant of `container` (a `[popover]`, `<dialog>`, `[role="dialog"]` or
15
- * `[role="alertdialog"]` that is itself a descendant of `container`).
16
- */
17
- export declare function isNestedLayerFocused({ container }: {
18
- container: HTMLElement;
19
- }): boolean;
20
- /**
21
- * An optional callback to restrict which focusable elements are included.
22
- * Return `true` to include the element, `false` to skip it.
23
- */
24
- export type TFocusableFilter = (element: HTMLElement, container: HTMLElement) => boolean;
25
- /**
26
- * Returns the first focusable element within the container.
27
- */
28
- export declare function getFirstFocusable({ container, filter, }: {
29
- container: HTMLElement;
30
- filter?: TFocusableFilter;
31
- }): HTMLElement | null;
32
- /**
33
- * Returns the last focusable element within the container.
34
- */
35
- export declare function getLastFocusable({ container, filter, }: {
36
- container: HTMLElement;
37
- filter?: TFocusableFilter;
38
- }): HTMLElement | null;
39
- /**
40
- * Returns the next focusable element in the given direction relative to the
41
- * currently focused element within the container. Wraps around at both ends.
42
- *
43
- * Returns `null` if there is no focused element within the container or if
44
- * the focused element is not in the list of focusable elements.
45
- */
46
- export declare function getNextFocusable({ container, direction, filter, }: {
47
- container: HTMLElement;
48
- direction: 'forwards' | 'backwards';
49
- filter?: TFocusableFilter;
50
- }): HTMLElement | null;
@@ -1,2 +0,0 @@
1
- export { getFirstFocusable, getLastFocusable, getNextFocusable } from './focus';
2
- export type { TFocusableFilter } from './focus';
@@ -1,50 +0,0 @@
1
- /**
2
- * Focusable element selectors and navigation helpers.
3
- *
4
- * Uses CSS selectors to discover focusable elements within a container,
5
- * avoiding the need for a manual registration system. Disabled elements
6
- * (both HTML `disabled` attribute and `aria-disabled="true"`) and elements
7
- * with `tabindex="-1"` are excluded automatically.
8
- *
9
- * All public functions accept an optional `filter` callback to further
10
- * restrict which focusable elements are included.
11
- */
12
- /**
13
- * Returns `true` when `document.activeElement` is inside a nested top-layer
14
- * descendant of `container` (a `[popover]`, `<dialog>`, `[role="dialog"]` or
15
- * `[role="alertdialog"]` that is itself a descendant of `container`).
16
- */
17
- export declare function isNestedLayerFocused({ container }: {
18
- container: HTMLElement;
19
- }): boolean;
20
- /**
21
- * An optional callback to restrict which focusable elements are included.
22
- * Return `true` to include the element, `false` to skip it.
23
- */
24
- export type TFocusableFilter = (element: HTMLElement, container: HTMLElement) => boolean;
25
- /**
26
- * Returns the first focusable element within the container.
27
- */
28
- export declare function getFirstFocusable({ container, filter, }: {
29
- container: HTMLElement;
30
- filter?: TFocusableFilter;
31
- }): HTMLElement | null;
32
- /**
33
- * Returns the last focusable element within the container.
34
- */
35
- export declare function getLastFocusable({ container, filter, }: {
36
- container: HTMLElement;
37
- filter?: TFocusableFilter;
38
- }): HTMLElement | null;
39
- /**
40
- * Returns the next focusable element in the given direction relative to the
41
- * currently focused element within the container. Wraps around at both ends.
42
- *
43
- * Returns `null` if there is no focused element within the container or if
44
- * the focused element is not in the list of focusable elements.
45
- */
46
- export declare function getNextFocusable({ container, direction, filter, }: {
47
- container: HTMLElement;
48
- direction: 'forwards' | 'backwards';
49
- filter?: TFocusableFilter;
50
- }): HTMLElement | null;