@atlaskit/top-layer 0.12.2 → 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.
- package/CHANGELOG.md +16 -0
- package/dist/cjs/entry-points/focus.js +6 -4
- package/dist/cjs/entry-points/use-anchor-position-at-point.js +12 -0
- package/dist/cjs/focus/get-first-focusable.js +19 -0
- package/dist/cjs/focus/get-focusables.js +30 -0
- package/dist/cjs/focus/get-last-focusable.js +19 -0
- package/dist/cjs/focus/get-next-focusable.js +43 -0
- package/dist/cjs/focus/is-in-same-layer.js +23 -0
- package/dist/cjs/focus/is-nested-layer-focused.js +32 -0
- package/dist/cjs/focus/selectors.js +19 -0
- package/dist/cjs/focus/types.js +1 -0
- package/dist/cjs/internal/role-to-aria-has-popup.js +37 -0
- package/dist/cjs/internal/role-types.js +1 -97
- package/dist/cjs/internal/should-focus-into-popover.js +19 -0
- package/dist/cjs/internal/use-anchor-position-at-point.js +127 -0
- package/dist/cjs/internal/use-anchor-position.js +7 -3
- package/dist/cjs/internal/use-focus-wrap.js +8 -5
- package/dist/cjs/internal/use-initial-focus.js +4 -4
- package/dist/cjs/placement-map/index.js +2 -2
- package/dist/cjs/placement-map/legacy-placements.js +2 -101
- package/dist/cjs/placement-map/placement-mapping.js +103 -0
- package/dist/cjs/popup/popup-content.js +4 -3
- package/dist/cjs/use-arrow-navigation/use-arrow-navigation.js +7 -5
- package/dist/es2019/entry-points/focus.js +3 -1
- package/dist/es2019/entry-points/use-anchor-position-at-point.js +1 -0
- package/dist/es2019/focus/get-first-focusable.js +14 -0
- package/dist/es2019/focus/get-focusables.js +19 -0
- package/dist/es2019/focus/get-last-focusable.js +14 -0
- package/dist/es2019/focus/get-next-focusable.js +38 -0
- package/dist/es2019/focus/is-in-same-layer.js +18 -0
- package/dist/es2019/focus/is-nested-layer-focused.js +28 -0
- package/dist/es2019/focus/selectors.js +11 -0
- package/dist/es2019/focus/types.js +0 -0
- package/dist/es2019/internal/role-to-aria-has-popup.js +32 -0
- package/dist/es2019/internal/role-types.js +0 -92
- package/dist/es2019/internal/should-focus-into-popover.js +14 -0
- package/dist/es2019/internal/use-anchor-position-at-point.js +122 -0
- package/dist/es2019/internal/use-anchor-position.js +6 -3
- package/dist/es2019/internal/use-focus-wrap.js +4 -1
- package/dist/es2019/internal/use-initial-focus.js +1 -1
- package/dist/es2019/placement-map/index.js +1 -1
- package/dist/es2019/placement-map/legacy-placements.js +1 -100
- package/dist/es2019/placement-map/placement-mapping.js +97 -0
- package/dist/es2019/popup/popup-content.js +2 -1
- package/dist/es2019/use-arrow-navigation/use-arrow-navigation.js +3 -1
- package/dist/esm/entry-points/focus.js +3 -1
- package/dist/esm/entry-points/use-anchor-position-at-point.js +1 -0
- package/dist/esm/focus/get-first-focusable.js +13 -0
- package/dist/esm/focus/get-focusables.js +24 -0
- package/dist/esm/focus/get-last-focusable.js +13 -0
- package/dist/esm/focus/get-next-focusable.js +37 -0
- package/dist/esm/focus/is-in-same-layer.js +17 -0
- package/dist/esm/focus/is-nested-layer-focused.js +27 -0
- package/dist/esm/focus/selectors.js +13 -0
- package/dist/esm/focus/types.js +0 -0
- package/dist/esm/internal/role-to-aria-has-popup.js +31 -0
- package/dist/esm/internal/role-types.js +0 -90
- package/dist/esm/internal/should-focus-into-popover.js +13 -0
- package/dist/esm/internal/use-anchor-position-at-point.js +122 -0
- package/dist/esm/internal/use-anchor-position.js +7 -3
- package/dist/esm/internal/use-focus-wrap.js +4 -1
- package/dist/esm/internal/use-initial-focus.js +1 -1
- package/dist/esm/placement-map/index.js +1 -1
- package/dist/esm/placement-map/legacy-placements.js +1 -100
- package/dist/esm/placement-map/placement-mapping.js +97 -0
- package/dist/esm/popup/popup-content.js +2 -1
- package/dist/esm/use-arrow-navigation/use-arrow-navigation.js +3 -1
- package/dist/types/entry-points/focus.d.ts +4 -2
- package/dist/types/entry-points/use-anchor-position-at-point.d.ts +1 -0
- package/dist/types/focus/get-first-focusable.d.ts +8 -0
- package/dist/types/focus/get-focusables.d.ts +13 -0
- package/dist/types/focus/get-last-focusable.d.ts +8 -0
- package/dist/types/focus/get-next-focusable.d.ts +13 -0
- package/dist/types/focus/is-in-same-layer.d.ts +8 -0
- package/dist/types/focus/is-nested-layer-focused.d.ts +8 -0
- package/dist/types/focus/selectors.d.ts +4 -0
- package/dist/types/focus/types.d.ts +5 -0
- package/dist/types/internal/role-to-aria-has-popup.d.ts +13 -0
- package/dist/types/internal/role-types.d.ts +0 -19
- package/dist/types/internal/should-focus-into-popover.d.ts +8 -0
- package/dist/types/internal/use-anchor-position-at-point.d.ts +62 -0
- package/dist/types/internal/use-anchor-position.d.ts +6 -1
- package/dist/types/placement-map/index.d.ts +1 -1
- package/dist/types/placement-map/legacy-placements.d.ts +0 -12
- package/dist/types/placement-map/placement-mapping.d.ts +13 -0
- package/dist/types/use-arrow-navigation/use-arrow-navigation.d.ts +1 -1
- package/dist/types-ts4.5/entry-points/focus.d.ts +4 -2
- package/dist/types-ts4.5/entry-points/use-anchor-position-at-point.d.ts +1 -0
- package/dist/types-ts4.5/focus/get-first-focusable.d.ts +8 -0
- package/dist/types-ts4.5/focus/get-focusables.d.ts +13 -0
- package/dist/types-ts4.5/focus/get-last-focusable.d.ts +8 -0
- package/dist/types-ts4.5/focus/get-next-focusable.d.ts +13 -0
- package/dist/types-ts4.5/focus/is-in-same-layer.d.ts +8 -0
- package/dist/types-ts4.5/focus/is-nested-layer-focused.d.ts +8 -0
- package/dist/types-ts4.5/focus/selectors.d.ts +4 -0
- package/dist/types-ts4.5/focus/types.d.ts +5 -0
- package/dist/types-ts4.5/internal/role-to-aria-has-popup.d.ts +13 -0
- package/dist/types-ts4.5/internal/role-types.d.ts +0 -19
- package/dist/types-ts4.5/internal/should-focus-into-popover.d.ts +8 -0
- package/dist/types-ts4.5/internal/use-anchor-position-at-point.d.ts +62 -0
- package/dist/types-ts4.5/internal/use-anchor-position.d.ts +6 -1
- package/dist/types-ts4.5/placement-map/index.d.ts +1 -1
- package/dist/types-ts4.5/placement-map/legacy-placements.d.ts +0 -12
- package/dist/types-ts4.5/placement-map/placement-mapping.d.ts +13 -0
- package/dist/types-ts4.5/use-arrow-navigation/use-arrow-navigation.d.ts +1 -1
- package/package.json +1 -1
- package/use-anchor-position-at-point/package.json +17 -0
- package/dist/cjs/focus/focus.js +0 -169
- package/dist/cjs/focus/index.js +0 -24
- package/dist/es2019/focus/focus.js +0 -158
- package/dist/es2019/focus/index.js +0 -1
- package/dist/esm/focus/focus.js +0 -160
- package/dist/esm/focus/index.js +0 -1
- package/dist/types/focus/focus.d.ts +0 -50
- package/dist/types/focus/index.d.ts +0 -2
- package/dist/types-ts4.5/focus/focus.d.ts +0 -50
- package/dist/types-ts4.5/focus/index.d.ts +0 -2
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Valid values for the `aria-haspopup` attribute.
|
|
3
|
-
*
|
|
4
|
-
* Derived from the HTML spec - maps popover roles to what the trigger
|
|
5
|
-
* announces. `undefined` means the attribute is omitted entirely (used for
|
|
6
|
-
* non-popup roles like `tooltip`/`status`/`alert`/`note`/`log` where
|
|
7
|
-
* `aria-haspopup` would be misleading).
|
|
8
|
-
*
|
|
9
|
-
* `true` is intentionally NOT in the union - the runtime only ever produces
|
|
10
|
-
* the explicit string forms, so widening the type would invite consumers to
|
|
11
|
-
* pass `true` and get an `aria-haspopup="true"` serialisation that the
|
|
12
|
-
* runtime no longer emits.
|
|
13
|
-
*/
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Roles that require an accessible name (`label` or `labelledBy`) per WCAG 4.1.2.
|
|
17
|
-
* Without a name, assistive technology cannot identify these landmarks.
|
|
18
|
-
*/
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Roles where the accessible name is derived from content or provided externally
|
|
22
|
-
* (e.g. a combobox labels its listbox, tooltip content IS the accessible name).
|
|
23
|
-
*/
|
|
24
|
-
|
|
25
|
-
// Shared ARIA role discrimination types
|
|
26
|
-
//
|
|
27
|
-
// These encode the WCAG 4.1.2 constraint: roles like `dialog`, `alertdialog`,
|
|
28
|
-
// and `menu` MUST have an accessible name (either `label` or `labelledBy`).
|
|
29
|
-
// TypeScript enforces this at compile time via discriminated unions.
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* ARIA role props where a role is always required.
|
|
33
|
-
*
|
|
34
|
-
* Used by `TPopupContentProps`. Popup content must always declare
|
|
35
|
-
* its role so assistive technology can identify the layer.
|
|
36
|
-
*/
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* ARIA role props where a role is optional.
|
|
40
|
-
*
|
|
41
|
-
* Used by `TPopoverProps`. The low-level primitive allows omitting
|
|
42
|
-
* the role for cases where it is set externally or not needed.
|
|
43
|
-
*/
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Maps a popover content role to the correct `aria-haspopup` value
|
|
47
|
-
* for its trigger element.
|
|
48
|
-
*
|
|
49
|
-
* Returns `undefined` for roles that are not popups in the ARIA sense
|
|
50
|
-
* (`tooltip`, `note`, `status`, `alert`, `log`). Triggers for those roles
|
|
51
|
-
* should not announce a popup at all - emitting `aria-haspopup="dialog"`
|
|
52
|
-
* on a tooltip trigger would mislead assistive technology.
|
|
53
|
-
*/
|
|
54
|
-
// eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports
|
|
55
|
-
export function roleToAriaHasPopup(_ref) {
|
|
56
|
-
var role = _ref.role;
|
|
57
|
-
if (role === 'menu') {
|
|
58
|
-
return 'menu';
|
|
59
|
-
}
|
|
60
|
-
if (role === 'listbox') {
|
|
61
|
-
return 'listbox';
|
|
62
|
-
}
|
|
63
|
-
if (role === 'tree') {
|
|
64
|
-
return 'tree';
|
|
65
|
-
}
|
|
66
|
-
if (role === 'grid') {
|
|
67
|
-
return 'grid';
|
|
68
|
-
}
|
|
69
|
-
if (role === 'dialog' || role === 'alertdialog') {
|
|
70
|
-
return 'dialog';
|
|
71
|
-
}
|
|
72
|
-
// Non-popup roles (tooltip, note, status, alert, log) and the
|
|
73
|
-
// no-role case: omit `aria-haspopup` entirely. React drops the
|
|
74
|
-
// attribute when the value is `undefined`.
|
|
75
|
-
return undefined;
|
|
76
|
-
}
|
|
77
|
-
var rolesThatMoveFocus = new Set(['dialog', 'alertdialog', 'menu', 'listbox', 'tree', 'grid']);
|
|
78
|
-
|
|
79
|
-
/**
|
|
80
|
-
* Returns `true` when the given popover role moves focus into the popover
|
|
81
|
-
* on open, and `false` otherwise (including when `role` is `undefined`).
|
|
82
|
-
*/
|
|
83
|
-
// eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports
|
|
84
|
-
export function shouldFocusIntoPopover(_ref2) {
|
|
85
|
-
var role = _ref2.role;
|
|
86
|
-
if (!role) {
|
|
87
|
-
return false;
|
|
88
|
-
}
|
|
89
|
-
return rolesThatMoveFocus.has(role);
|
|
90
|
-
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
var rolesThatMoveFocus = new Set(['dialog', 'alertdialog', 'menu', 'listbox', 'tree', 'grid']);
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Returns `true` when the given popover role moves focus into the popover
|
|
5
|
+
* on open, and `false` otherwise (including when `role` is `undefined`).
|
|
6
|
+
*/
|
|
7
|
+
export function shouldFocusIntoPopover(_ref) {
|
|
8
|
+
var role = _ref.role;
|
|
9
|
+
if (!role) {
|
|
10
|
+
return false;
|
|
11
|
+
}
|
|
12
|
+
return rolesThatMoveFocus.has(role);
|
|
13
|
+
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { useLayoutEffect, useRef } from 'react';
|
|
2
|
+
import { useAnchorPosition } from './use-anchor-position';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* A point in viewport coordinates (CSS pixels) at which the synthetic
|
|
6
|
+
* anchor should be placed.
|
|
7
|
+
*
|
|
8
|
+
* Axis-named (`x`/`y`) rather than edge-named (`left`/`top`) so the
|
|
9
|
+
* shape is unambiguous in RTL writing modes — there is no ambiguity
|
|
10
|
+
* about whether a coordinate is logical (`inline-start`/`block-start`)
|
|
11
|
+
* or physical (`left`/`top`). Viewport coordinates are always
|
|
12
|
+
* physical, so we name them with the physical axis labels.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Styles the synthetic anchor as an invisible, zero-size point.
|
|
17
|
+
* Dynamic `inset-*` overrides are written by the positioning effect.
|
|
18
|
+
*
|
|
19
|
+
* Uses `Object.assign` rather than Compiled CSS (element is outside the React tree)
|
|
20
|
+
* or the internal `setStyle` helper (we own this element entirely — it is created
|
|
21
|
+
* and removed by this hook — so the snapshot/restore semantics `setStyle`
|
|
22
|
+
* provides for caller-owned elements would be dead work here).
|
|
23
|
+
*/
|
|
24
|
+
function applyStaticAnchorStyles(el) {
|
|
25
|
+
Object.assign(el.style, {
|
|
26
|
+
position: 'fixed',
|
|
27
|
+
// `top`/`left` rather than `inset-block-start`/`inset-inline-start`
|
|
28
|
+
// for consistency with the dynamic positioning effect below, which
|
|
29
|
+
// uses physical properties (see comment there for the rationale).
|
|
30
|
+
top: '0',
|
|
31
|
+
left: '0',
|
|
32
|
+
// Zero size — placement decides which side the popover sits on.
|
|
33
|
+
width: '0',
|
|
34
|
+
height: '0',
|
|
35
|
+
// Prevent the overlay from intercepting pointer events.
|
|
36
|
+
pointerEvents: 'none'
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// `useAnchorPosition` requires a real DOM element. When the caller only
|
|
41
|
+
// has a viewport coordinate (e.g. cursor at hover time), this hook
|
|
42
|
+
// manages a hidden `<div>` at that point and delegates the rest.
|
|
43
|
+
//
|
|
44
|
+
// The `<div>` is appended directly to `document.body` to escape any
|
|
45
|
+
// transformed ancestor, which would otherwise break `position: fixed`
|
|
46
|
+
// viewport-relative resolution.
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Positions a popover at a consumer-supplied viewport coordinate using a
|
|
50
|
+
* hidden synthetic anchor.
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* ```tsx
|
|
54
|
+
* function PointPositionedPopover({ popoverRef, placement, mousePos }) {
|
|
55
|
+
* useAnchorPositionAtPoint({
|
|
56
|
+
* popoverRef,
|
|
57
|
+
* placement,
|
|
58
|
+
* isEnabled: Boolean(mousePos),
|
|
59
|
+
* getPoint: () => {
|
|
60
|
+
* if (!mousePos) return null;
|
|
61
|
+
* return { x: mousePos.clientX, y: mousePos.clientY };
|
|
62
|
+
* },
|
|
63
|
+
* });
|
|
64
|
+
* return <Popover ref={popoverRef}>...</Popover>;
|
|
65
|
+
* }
|
|
66
|
+
* ```
|
|
67
|
+
*/
|
|
68
|
+
export function useAnchorPositionAtPoint(_ref) {
|
|
69
|
+
var popoverRef = _ref.popoverRef,
|
|
70
|
+
placement = _ref.placement,
|
|
71
|
+
getPoint = _ref.getPoint,
|
|
72
|
+
_ref$isEnabled = _ref.isEnabled,
|
|
73
|
+
isEnabled = _ref$isEnabled === void 0 ? true : _ref$isEnabled;
|
|
74
|
+
var syntheticAnchorRef = useRef(null);
|
|
75
|
+
|
|
76
|
+
// `getPoint` is kept in a ref so the layout effect can call the
|
|
77
|
+
// latest version without listing it as a dep — that would re-fire
|
|
78
|
+
// on every render and re-latch the point.
|
|
79
|
+
var getPointRef = useRef(getPoint);
|
|
80
|
+
getPointRef.current = getPoint;
|
|
81
|
+
|
|
82
|
+
// Lazy element creation: the `<div>` is only created when both
|
|
83
|
+
// `isEnabled` is true AND `getPoint()` returns a non-null point.
|
|
84
|
+
// `useLayoutEffect` ensures the element exists before the inner
|
|
85
|
+
// `useAnchorPosition` (also a layout effect) reads the ref.
|
|
86
|
+
useLayoutEffect(function () {
|
|
87
|
+
if (!isEnabled) {
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
var point = getPointRef.current();
|
|
91
|
+
if (!point) {
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
var anchor = document.createElement('div');
|
|
95
|
+
anchor.setAttribute('aria-hidden', 'true');
|
|
96
|
+
applyStaticAnchorStyles(anchor);
|
|
97
|
+
// `point.x`/`y` are physical viewport coordinates (from
|
|
98
|
+
// `MouseEvent.clientX/Y`), so map directly onto physical
|
|
99
|
+
// `left`/`top`. This is RTL-safe: `position: fixed` + physical
|
|
100
|
+
// insets is direction-independent. Using logical
|
|
101
|
+
// `inset-inline-start` would need `viewportWidth - point.x` in
|
|
102
|
+
// RTL to land at the same physical pixel.
|
|
103
|
+
anchor.style.top = "".concat(point.y, "px");
|
|
104
|
+
anchor.style.left = "".concat(point.x, "px");
|
|
105
|
+
document.body.appendChild(anchor);
|
|
106
|
+
syntheticAnchorRef.current = anchor;
|
|
107
|
+
return function cleanup() {
|
|
108
|
+
anchor.remove();
|
|
109
|
+
syntheticAnchorRef.current = null;
|
|
110
|
+
};
|
|
111
|
+
}, [isEnabled]);
|
|
112
|
+
|
|
113
|
+
// Mirror `isEnabled` so both hooks stay in sync — when disabled,
|
|
114
|
+
// neither this hook nor the inner one touches the popover, leaving
|
|
115
|
+
// any other positioning the consumer has set up free to take effect.
|
|
116
|
+
useAnchorPosition({
|
|
117
|
+
anchorRef: syntheticAnchorRef,
|
|
118
|
+
popoverRef: popoverRef,
|
|
119
|
+
placement: placement,
|
|
120
|
+
isEnabled: isEnabled
|
|
121
|
+
});
|
|
122
|
+
}
|
|
@@ -193,19 +193,23 @@ function useStablePlacement(placement) {
|
|
|
193
193
|
* comparison is used internally so re-runs are skipped when the resolved
|
|
194
194
|
* placement shape is unchanged.
|
|
195
195
|
*/
|
|
196
|
-
// eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports
|
|
197
196
|
export function useAnchorPosition(_ref3) {
|
|
198
197
|
var anchorRef = _ref3.anchorRef,
|
|
199
198
|
popoverRef = _ref3.popoverRef,
|
|
200
199
|
_ref3$placement = _ref3.placement,
|
|
201
200
|
placement = _ref3$placement === void 0 ? {} : _ref3$placement,
|
|
202
201
|
_ref3$forceFallbackPo = _ref3.forceFallbackPositioning,
|
|
203
|
-
forceFallbackPositioning = _ref3$forceFallbackPo === void 0 ? false : _ref3$forceFallbackPo
|
|
202
|
+
forceFallbackPositioning = _ref3$forceFallbackPo === void 0 ? false : _ref3$forceFallbackPo,
|
|
203
|
+
_ref3$isEnabled = _ref3.isEnabled,
|
|
204
|
+
isEnabled = _ref3$isEnabled === void 0 ? true : _ref3$isEnabled;
|
|
204
205
|
var id = useId();
|
|
205
206
|
// Stabilize `placement` object so the same object literal
|
|
206
207
|
// value returns an object with the same reference
|
|
207
208
|
var stablePlacement = useStablePlacement(placement);
|
|
208
209
|
useLayoutEffect(function () {
|
|
210
|
+
if (!isEnabled) {
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
209
213
|
var trigger = anchorRef.current;
|
|
210
214
|
var popover = popoverRef.current;
|
|
211
215
|
if (!trigger || !popover) {
|
|
@@ -454,5 +458,5 @@ export function useAnchorPosition(_ref3) {
|
|
|
454
458
|
popover.style.removeProperty('opacity');
|
|
455
459
|
});
|
|
456
460
|
return undoPositioning;
|
|
457
|
-
}, [anchorRef, popoverRef, stablePlacement, forceFallbackPositioning, id]);
|
|
461
|
+
}, [anchorRef, popoverRef, stablePlacement, forceFallbackPositioning, isEnabled, id]);
|
|
458
462
|
}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { useEffect } from 'react';
|
|
2
2
|
import { bind } from 'bind-event-listener';
|
|
3
|
-
import { getFirstFocusable
|
|
3
|
+
import { getFirstFocusable } from '../focus/get-first-focusable';
|
|
4
|
+
import { getLastFocusable } from '../focus/get-last-focusable';
|
|
5
|
+
import { getNextFocusable } from '../focus/get-next-focusable';
|
|
6
|
+
import { isNestedLayerFocused } from '../focus/is-nested-layer-focused';
|
|
4
7
|
|
|
5
8
|
/**
|
|
6
9
|
* Roles that require focus wrapping per WAI-ARIA APG.
|
|
@@ -2,7 +2,7 @@ import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
|
2
2
|
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
|
|
3
3
|
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; }
|
|
4
4
|
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) { _defineProperty(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; }
|
|
5
|
-
import { placementMapping } from './
|
|
5
|
+
import { placementMapping } from './placement-mapping';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Maps legacy Popper.js placement values to the new object-based
|
|
@@ -5,103 +5,4 @@
|
|
|
5
5
|
* to enumerate every placement (e.g. for a settings dropdown). New code
|
|
6
6
|
* should use the object-based `TPlacementOptions` directly.
|
|
7
7
|
*/
|
|
8
|
-
|
|
9
|
-
export var LEGACY_PLACEMENTS = ['auto', 'auto-start', 'auto-end', 'top', 'top-start', 'top-center', 'top-end', 'bottom', 'bottom-start', 'bottom-center', 'bottom-end', 'right', 'right-start', 'right-end', 'left', 'left-start', 'left-end'];
|
|
10
|
-
/**
|
|
11
|
-
* The full mapping record. Internal - use `fromLegacyPlacement` from the
|
|
12
|
-
* public entry-point so the offset-tuple translation is applied consistently.
|
|
13
|
-
*
|
|
14
|
-
* Note: `auto`, `auto-start`, `auto-end` map to `block-end` placements. This
|
|
15
|
-
* is a reduction in expressiveness vs Popper.js (which picked the best
|
|
16
|
-
* placement at runtime). CSS `position-try-fallbacks` flips at the edge but
|
|
17
|
-
* the initial placement is fixed. Migration consumers who relied on Popper's
|
|
18
|
-
* dynamic auto-flip should pick an explicit placement instead.
|
|
19
|
-
*/
|
|
20
|
-
// eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports
|
|
21
|
-
export var placementMapping = {
|
|
22
|
-
top: {
|
|
23
|
-
axis: 'block',
|
|
24
|
-
edge: 'start',
|
|
25
|
-
align: 'center'
|
|
26
|
-
},
|
|
27
|
-
'top-start': {
|
|
28
|
-
axis: 'block',
|
|
29
|
-
edge: 'start',
|
|
30
|
-
align: 'start'
|
|
31
|
-
},
|
|
32
|
-
'top-center': {
|
|
33
|
-
axis: 'block',
|
|
34
|
-
edge: 'start',
|
|
35
|
-
align: 'center'
|
|
36
|
-
},
|
|
37
|
-
'top-end': {
|
|
38
|
-
axis: 'block',
|
|
39
|
-
edge: 'start',
|
|
40
|
-
align: 'end'
|
|
41
|
-
},
|
|
42
|
-
bottom: {
|
|
43
|
-
axis: 'block',
|
|
44
|
-
edge: 'end',
|
|
45
|
-
align: 'center'
|
|
46
|
-
},
|
|
47
|
-
'bottom-start': {
|
|
48
|
-
axis: 'block',
|
|
49
|
-
edge: 'end',
|
|
50
|
-
align: 'start'
|
|
51
|
-
},
|
|
52
|
-
'bottom-center': {
|
|
53
|
-
axis: 'block',
|
|
54
|
-
edge: 'end',
|
|
55
|
-
align: 'center'
|
|
56
|
-
},
|
|
57
|
-
'bottom-end': {
|
|
58
|
-
axis: 'block',
|
|
59
|
-
edge: 'end',
|
|
60
|
-
align: 'end'
|
|
61
|
-
},
|
|
62
|
-
right: {
|
|
63
|
-
axis: 'inline',
|
|
64
|
-
edge: 'end',
|
|
65
|
-
align: 'center'
|
|
66
|
-
},
|
|
67
|
-
'right-start': {
|
|
68
|
-
axis: 'inline',
|
|
69
|
-
edge: 'end',
|
|
70
|
-
align: 'start'
|
|
71
|
-
},
|
|
72
|
-
'right-end': {
|
|
73
|
-
axis: 'inline',
|
|
74
|
-
edge: 'end',
|
|
75
|
-
align: 'end'
|
|
76
|
-
},
|
|
77
|
-
left: {
|
|
78
|
-
axis: 'inline',
|
|
79
|
-
edge: 'start',
|
|
80
|
-
align: 'center'
|
|
81
|
-
},
|
|
82
|
-
'left-start': {
|
|
83
|
-
axis: 'inline',
|
|
84
|
-
edge: 'start',
|
|
85
|
-
align: 'start'
|
|
86
|
-
},
|
|
87
|
-
'left-end': {
|
|
88
|
-
axis: 'inline',
|
|
89
|
-
edge: 'start',
|
|
90
|
-
align: 'end'
|
|
91
|
-
},
|
|
92
|
-
auto: {
|
|
93
|
-
axis: 'block',
|
|
94
|
-
edge: 'end',
|
|
95
|
-
align: 'center'
|
|
96
|
-
},
|
|
97
|
-
'auto-start': {
|
|
98
|
-
axis: 'block',
|
|
99
|
-
edge: 'end',
|
|
100
|
-
align: 'start'
|
|
101
|
-
},
|
|
102
|
-
'auto-end': {
|
|
103
|
-
axis: 'block',
|
|
104
|
-
edge: 'end',
|
|
105
|
-
align: 'end'
|
|
106
|
-
}
|
|
107
|
-
};
|
|
8
|
+
export var LEGACY_PLACEMENTS = ['auto', 'auto-start', 'auto-end', 'top', 'top-start', 'top-center', 'top-end', 'bottom', 'bottom-start', 'bottom-center', 'bottom-end', 'right', 'right-start', 'right-end', 'left', 'left-start', 'left-end'];
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The full mapping record. Internal - use `fromLegacyPlacement` from the
|
|
3
|
+
* public entry-point so the offset-tuple translation is applied consistently.
|
|
4
|
+
*
|
|
5
|
+
* Note: `auto`, `auto-start`, `auto-end` map to `block-end` placements. This
|
|
6
|
+
* is a reduction in expressiveness vs Popper.js (which picked the best
|
|
7
|
+
* placement at runtime). CSS `position-try-fallbacks` flips at the edge but
|
|
8
|
+
* the initial placement is fixed. Migration consumers who relied on Popper's
|
|
9
|
+
* dynamic auto-flip should pick an explicit placement instead.
|
|
10
|
+
*/
|
|
11
|
+
export var placementMapping = {
|
|
12
|
+
top: {
|
|
13
|
+
axis: 'block',
|
|
14
|
+
edge: 'start',
|
|
15
|
+
align: 'center'
|
|
16
|
+
},
|
|
17
|
+
'top-start': {
|
|
18
|
+
axis: 'block',
|
|
19
|
+
edge: 'start',
|
|
20
|
+
align: 'start'
|
|
21
|
+
},
|
|
22
|
+
'top-center': {
|
|
23
|
+
axis: 'block',
|
|
24
|
+
edge: 'start',
|
|
25
|
+
align: 'center'
|
|
26
|
+
},
|
|
27
|
+
'top-end': {
|
|
28
|
+
axis: 'block',
|
|
29
|
+
edge: 'start',
|
|
30
|
+
align: 'end'
|
|
31
|
+
},
|
|
32
|
+
bottom: {
|
|
33
|
+
axis: 'block',
|
|
34
|
+
edge: 'end',
|
|
35
|
+
align: 'center'
|
|
36
|
+
},
|
|
37
|
+
'bottom-start': {
|
|
38
|
+
axis: 'block',
|
|
39
|
+
edge: 'end',
|
|
40
|
+
align: 'start'
|
|
41
|
+
},
|
|
42
|
+
'bottom-center': {
|
|
43
|
+
axis: 'block',
|
|
44
|
+
edge: 'end',
|
|
45
|
+
align: 'center'
|
|
46
|
+
},
|
|
47
|
+
'bottom-end': {
|
|
48
|
+
axis: 'block',
|
|
49
|
+
edge: 'end',
|
|
50
|
+
align: 'end'
|
|
51
|
+
},
|
|
52
|
+
right: {
|
|
53
|
+
axis: 'inline',
|
|
54
|
+
edge: 'end',
|
|
55
|
+
align: 'center'
|
|
56
|
+
},
|
|
57
|
+
'right-start': {
|
|
58
|
+
axis: 'inline',
|
|
59
|
+
edge: 'end',
|
|
60
|
+
align: 'start'
|
|
61
|
+
},
|
|
62
|
+
'right-end': {
|
|
63
|
+
axis: 'inline',
|
|
64
|
+
edge: 'end',
|
|
65
|
+
align: 'end'
|
|
66
|
+
},
|
|
67
|
+
left: {
|
|
68
|
+
axis: 'inline',
|
|
69
|
+
edge: 'start',
|
|
70
|
+
align: 'center'
|
|
71
|
+
},
|
|
72
|
+
'left-start': {
|
|
73
|
+
axis: 'inline',
|
|
74
|
+
edge: 'start',
|
|
75
|
+
align: 'start'
|
|
76
|
+
},
|
|
77
|
+
'left-end': {
|
|
78
|
+
axis: 'inline',
|
|
79
|
+
edge: 'start',
|
|
80
|
+
align: 'end'
|
|
81
|
+
},
|
|
82
|
+
auto: {
|
|
83
|
+
axis: 'block',
|
|
84
|
+
edge: 'end',
|
|
85
|
+
align: 'center'
|
|
86
|
+
},
|
|
87
|
+
'auto-start': {
|
|
88
|
+
axis: 'block',
|
|
89
|
+
edge: 'end',
|
|
90
|
+
align: 'start'
|
|
91
|
+
},
|
|
92
|
+
'auto-end': {
|
|
93
|
+
axis: 'block',
|
|
94
|
+
edge: 'end',
|
|
95
|
+
align: 'end'
|
|
96
|
+
}
|
|
97
|
+
};
|
|
@@ -4,7 +4,8 @@ import { ax, ix } from "@compiled/react/runtime";
|
|
|
4
4
|
import React, { forwardRef, useCallback, useLayoutEffect, useRef } from 'react';
|
|
5
5
|
import mergeRefs from '@atlaskit/ds-lib/merge-refs';
|
|
6
6
|
import { prefersReducedMotion } from '../internal/reduced-motion';
|
|
7
|
-
import { roleToAriaHasPopup
|
|
7
|
+
import { roleToAriaHasPopup } from '../internal/role-to-aria-has-popup';
|
|
8
|
+
import { shouldFocusIntoPopover } from '../internal/should-focus-into-popover';
|
|
8
9
|
import { useAnchorPosition } from '../internal/use-anchor-position';
|
|
9
10
|
import { useWidthFromAnchor } from '../internal/use-width-from-anchor';
|
|
10
11
|
import { Popover } from '../popover/popover';
|
|
@@ -2,7 +2,9 @@ import { useCallback, useEffect } from 'react';
|
|
|
2
2
|
import { bind } from 'bind-event-listener';
|
|
3
3
|
import { getDocument } from '@atlaskit/browser-apis';
|
|
4
4
|
import { KEY_DOWN, KEY_END, KEY_HOME, KEY_TAB, KEY_UP } from '@atlaskit/ds-lib/keycodes';
|
|
5
|
-
import { getFirstFocusable
|
|
5
|
+
import { getFirstFocusable } from '../focus/get-first-focusable';
|
|
6
|
+
import { getLastFocusable } from '../focus/get-last-focusable';
|
|
7
|
+
import { getNextFocusable } from '../focus/get-next-focusable';
|
|
6
8
|
var menuScope = '[role="menu"]';
|
|
7
9
|
|
|
8
10
|
/**
|
|
@@ -1,2 +1,4 @@
|
|
|
1
|
-
export {
|
|
2
|
-
export
|
|
1
|
+
export type { TFocusableFilter } from '../focus/types';
|
|
2
|
+
export { getFirstFocusable } from '../focus/get-first-focusable';
|
|
3
|
+
export { getLastFocusable } from '../focus/get-last-focusable';
|
|
4
|
+
export { getNextFocusable } from '../focus/get-next-focusable';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { useAnchorPositionAtPoint, type TAnchorPoint, } from '../internal/use-anchor-position-at-point';
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { TFocusableFilter } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Returns the first focusable element within the container.
|
|
4
|
+
*/
|
|
5
|
+
export declare function getFirstFocusable({ container, filter, }: {
|
|
6
|
+
container: HTMLElement;
|
|
7
|
+
filter?: TFocusableFilter;
|
|
8
|
+
}): HTMLElement | null;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { TFocusableFilter } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Returns all focusable HTMLElements within the container, optionally filtered.
|
|
4
|
+
*
|
|
5
|
+
* Focusables that belong to a nested top-layer scope (a `[popover]` or
|
|
6
|
+
* `<dialog>` descendant of the container) are excluded - those elements
|
|
7
|
+
* are owned by the inner layer's focus management. The container itself
|
|
8
|
+
* is allowed to be a popover/dialog; only nested ones are filtered.
|
|
9
|
+
*/
|
|
10
|
+
export declare function getFocusables({ container, filter, }: {
|
|
11
|
+
container: HTMLElement;
|
|
12
|
+
filter?: TFocusableFilter;
|
|
13
|
+
}): HTMLElement[];
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { TFocusableFilter } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Returns the last focusable element within the container.
|
|
4
|
+
*/
|
|
5
|
+
export declare function getLastFocusable({ container, filter, }: {
|
|
6
|
+
container: HTMLElement;
|
|
7
|
+
filter?: TFocusableFilter;
|
|
8
|
+
}): HTMLElement | null;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns the next focusable element in the given direction relative to the
|
|
3
|
+
* currently focused element within the container. Wraps around at both ends.
|
|
4
|
+
*
|
|
5
|
+
* Returns `null` if there is no focused element within the container or if
|
|
6
|
+
* the focused element is not in the list of focusable elements.
|
|
7
|
+
*/
|
|
8
|
+
import type { TFocusableFilter } from './types';
|
|
9
|
+
export declare function getNextFocusable({ container, direction, filter, }: {
|
|
10
|
+
container: HTMLElement;
|
|
11
|
+
direction: 'forwards' | 'backwards';
|
|
12
|
+
filter?: TFocusableFilter;
|
|
13
|
+
}): HTMLElement | null;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns true when `element` and `container` resolve to the same nearest
|
|
3
|
+
* top-layer host (or both resolve to `null`, meaning the document layer).
|
|
4
|
+
*/
|
|
5
|
+
export declare function isInSameLayer({ element, container, }: {
|
|
6
|
+
element: HTMLElement;
|
|
7
|
+
container: HTMLElement;
|
|
8
|
+
}): boolean;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns `true` when `document.activeElement` is inside a nested top-layer
|
|
3
|
+
* descendant of `container` (a `[popover]`, `<dialog>`, `[role="dialog"]` or
|
|
4
|
+
* `[role="alertdialog"]` that is itself a descendant of `container`).
|
|
5
|
+
*/
|
|
6
|
+
export declare function isNestedLayerFocused({ container }: {
|
|
7
|
+
container: HTMLElement;
|
|
8
|
+
}): boolean;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { TAriaHasPopupValue, TRoleRequiringAccessibleName, TRoleWithImplicitName } from './role-types';
|
|
2
|
+
/**
|
|
3
|
+
* Maps a popover content role to the correct `aria-haspopup` value
|
|
4
|
+
* for its trigger element.
|
|
5
|
+
*
|
|
6
|
+
* Returns `undefined` for roles that are not popups in the ARIA sense
|
|
7
|
+
* (`tooltip`, `note`, `status`, `alert`, `log`). Triggers for those roles
|
|
8
|
+
* should not announce a popup at all - emitting `aria-haspopup="dialog"`
|
|
9
|
+
* on a tooltip trigger would mislead assistive technology.
|
|
10
|
+
*/
|
|
11
|
+
export declare function roleToAriaHasPopup({ role, }: {
|
|
12
|
+
role: TRoleRequiringAccessibleName | TRoleWithImplicitName | undefined;
|
|
13
|
+
}): TAriaHasPopupValue;
|
|
@@ -61,23 +61,4 @@ export type TAriaRoleOptional = ({
|
|
|
61
61
|
} & TAccessibleNameRequired) | ({
|
|
62
62
|
role?: TRoleWithImplicitName;
|
|
63
63
|
} & TAccessibleNameOptional);
|
|
64
|
-
/**
|
|
65
|
-
* Maps a popover content role to the correct `aria-haspopup` value
|
|
66
|
-
* for its trigger element.
|
|
67
|
-
*
|
|
68
|
-
* Returns `undefined` for roles that are not popups in the ARIA sense
|
|
69
|
-
* (`tooltip`, `note`, `status`, `alert`, `log`). Triggers for those roles
|
|
70
|
-
* should not announce a popup at all - emitting `aria-haspopup="dialog"`
|
|
71
|
-
* on a tooltip trigger would mislead assistive technology.
|
|
72
|
-
*/
|
|
73
|
-
export declare function roleToAriaHasPopup({ role, }: {
|
|
74
|
-
role: TRoleRequiringAccessibleName | TRoleWithImplicitName | undefined;
|
|
75
|
-
}): TAriaHasPopupValue;
|
|
76
|
-
/**
|
|
77
|
-
* Returns `true` when the given popover role moves focus into the popover
|
|
78
|
-
* on open, and `false` otherwise (including when `role` is `undefined`).
|
|
79
|
-
*/
|
|
80
|
-
export declare function shouldFocusIntoPopover({ role, }: {
|
|
81
|
-
role: TRoleRequiringAccessibleName | TRoleWithImplicitName | undefined;
|
|
82
|
-
}): boolean;
|
|
83
64
|
export {};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { TRoleRequiringAccessibleName, TRoleWithImplicitName } from './role-types';
|
|
2
|
+
/**
|
|
3
|
+
* Returns `true` when the given popover role moves focus into the popover
|
|
4
|
+
* on open, and `false` otherwise (including when `role` is `undefined`).
|
|
5
|
+
*/
|
|
6
|
+
export declare function shouldFocusIntoPopover({ role, }: {
|
|
7
|
+
role: TRoleRequiringAccessibleName | TRoleWithImplicitName | undefined;
|
|
8
|
+
}): boolean;
|