@atlaskit/top-layer 0.11.0 → 0.12.1
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 +24 -0
- package/dist/cjs/animations/presets.js +5 -0
- package/dist/cjs/entry-points/use-arrow-navigation.js +3 -2
- package/dist/cjs/internal/placement-to-position-area.js +43 -0
- package/dist/cjs/internal/placement-to-try-fallbacks.js +82 -0
- package/dist/cjs/internal/use-anchor-position.js +18 -131
- package/dist/cjs/internal/use-animated-visibility.js +84 -7
- package/dist/cjs/popover/popover.js +2 -0
- package/dist/cjs/popup/popup-content.js +55 -15
- package/dist/cjs/popup/popup-context.js +14 -33
- package/dist/cjs/popup/popup-provider.js +15 -0
- package/dist/cjs/popup/popup-trigger-function.js +9 -6
- package/dist/cjs/popup/popup-trigger.js +14 -9
- package/dist/cjs/popup/popup.js +7 -7
- package/dist/cjs/popup/use-maybe-popup-context.js +17 -0
- package/dist/cjs/popup/use-popup-context.js +20 -0
- package/dist/cjs/use-arrow-navigation/index.js +3 -2
- package/dist/cjs/use-arrow-navigation/is-at-current-menu-level.js +87 -0
- package/dist/cjs/use-arrow-navigation/use-arrow-navigation.js +0 -82
- package/dist/es2019/animations/presets.js +5 -0
- package/dist/es2019/entry-points/use-arrow-navigation.js +2 -1
- package/dist/es2019/internal/placement-to-position-area.js +40 -0
- package/dist/es2019/internal/placement-to-try-fallbacks.js +77 -0
- package/dist/es2019/internal/use-anchor-position.js +2 -116
- package/dist/es2019/internal/use-animated-visibility.js +84 -7
- package/dist/es2019/popover/popover.js +2 -0
- package/dist/es2019/popup/popup-content.js +55 -14
- package/dist/es2019/popup/popup-context.js +14 -30
- package/dist/es2019/popup/popup-provider.js +10 -0
- package/dist/es2019/popup/popup-trigger-function.js +8 -5
- package/dist/es2019/popup/popup-trigger.js +14 -8
- package/dist/es2019/popup/popup.js +4 -4
- package/dist/es2019/popup/use-maybe-popup-context.js +12 -0
- package/dist/es2019/popup/use-popup-context.js +15 -0
- package/dist/es2019/use-arrow-navigation/index.js +2 -1
- package/dist/es2019/use-arrow-navigation/is-at-current-menu-level.js +81 -0
- package/dist/es2019/use-arrow-navigation/use-arrow-navigation.js +0 -81
- package/dist/esm/animations/presets.js +5 -0
- package/dist/esm/entry-points/use-arrow-navigation.js +2 -1
- package/dist/esm/internal/placement-to-position-area.js +38 -0
- package/dist/esm/internal/placement-to-try-fallbacks.js +76 -0
- package/dist/esm/internal/use-anchor-position.js +16 -127
- package/dist/esm/internal/use-animated-visibility.js +84 -7
- package/dist/esm/popover/popover.js +2 -0
- package/dist/esm/popup/popup-content.js +55 -14
- package/dist/esm/popup/popup-context.js +14 -30
- package/dist/esm/popup/popup-provider.js +10 -0
- package/dist/esm/popup/popup-trigger-function.js +8 -5
- package/dist/esm/popup/popup-trigger.js +14 -8
- package/dist/esm/popup/popup.js +6 -6
- package/dist/esm/popup/use-maybe-popup-context.js +12 -0
- package/dist/esm/popup/use-popup-context.js +15 -0
- package/dist/esm/use-arrow-navigation/index.js +2 -1
- package/dist/esm/use-arrow-navigation/is-at-current-menu-level.js +81 -0
- package/dist/esm/use-arrow-navigation/use-arrow-navigation.js +0 -81
- package/dist/types/animations/types.d.ts +5 -1
- package/dist/types/entry-points/use-arrow-navigation.d.ts +2 -1
- package/dist/types/internal/placement-to-position-area.d.ts +21 -0
- package/dist/types/internal/placement-to-try-fallbacks.d.ts +36 -0
- package/dist/types/internal/use-anchor-position.d.ts +0 -55
- package/dist/types/internal/use-animated-visibility.d.ts +8 -2
- package/dist/types/popover/types.d.ts +8 -0
- package/dist/types/popup/popup-context.d.ts +25 -25
- package/dist/types/popup/popup-provider.d.ts +10 -0
- package/dist/types/popup/types.d.ts +12 -0
- package/dist/types/popup/use-maybe-popup-context.d.ts +8 -0
- package/dist/types/popup/use-popup-context.d.ts +7 -0
- package/dist/types/use-arrow-navigation/index.d.ts +2 -1
- package/dist/types/use-arrow-navigation/is-at-current-menu-level.d.ts +48 -0
- package/dist/types/use-arrow-navigation/use-arrow-navigation.d.ts +0 -48
- package/dist/types-ts4.5/animations/types.d.ts +5 -1
- package/dist/types-ts4.5/entry-points/use-arrow-navigation.d.ts +2 -1
- package/dist/types-ts4.5/internal/placement-to-position-area.d.ts +21 -0
- package/dist/types-ts4.5/internal/placement-to-try-fallbacks.d.ts +36 -0
- package/dist/types-ts4.5/internal/use-anchor-position.d.ts +0 -55
- package/dist/types-ts4.5/internal/use-animated-visibility.d.ts +8 -2
- package/dist/types-ts4.5/popover/types.d.ts +8 -0
- package/dist/types-ts4.5/popup/popup-context.d.ts +25 -25
- package/dist/types-ts4.5/popup/popup-provider.d.ts +10 -0
- package/dist/types-ts4.5/popup/types.d.ts +12 -0
- package/dist/types-ts4.5/popup/use-maybe-popup-context.d.ts +8 -0
- package/dist/types-ts4.5/popup/use-popup-context.d.ts +7 -0
- package/dist/types-ts4.5/use-arrow-navigation/index.d.ts +2 -1
- package/dist/types-ts4.5/use-arrow-navigation/is-at-current-menu-level.d.ts +48 -0
- package/dist/types-ts4.5/use-arrow-navigation/use-arrow-navigation.d.ts +0 -48
- package/package.json +2 -2
- package/dist/cjs/arrow/index.js +0 -131
- package/dist/cjs/arrow/types.js +0 -5
- package/dist/es2019/arrow/index.js +0 -269
- package/dist/es2019/arrow/types.js +0 -1
- package/dist/esm/arrow/index.js +0 -124
- package/dist/esm/arrow/types.js +0 -1
- package/dist/types/arrow/index.d.ts +0 -24
- package/dist/types/arrow/types.d.ts +0 -29
- package/dist/types-ts4.5/arrow/index.d.ts +0 -24
- package/dist/types-ts4.5/arrow/types.d.ts +0 -29
|
@@ -11,11 +11,12 @@ var _runtime = require("@compiled/react/runtime");
|
|
|
11
11
|
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
|
|
12
12
|
var _react = _interopRequireWildcard(require("react"));
|
|
13
13
|
var _mergeRefs = _interopRequireDefault(require("@atlaskit/ds-lib/merge-refs"));
|
|
14
|
+
var _reducedMotion = require("../internal/reduced-motion");
|
|
14
15
|
var _roleTypes = require("../internal/role-types");
|
|
15
16
|
var _useAnchorPosition = require("../internal/use-anchor-position");
|
|
16
17
|
var _useWidthFromAnchor = require("../internal/use-width-from-anchor");
|
|
17
18
|
var _popover = require("../popover/popover");
|
|
18
|
-
var
|
|
19
|
+
var _useMaybePopupContext = require("./use-maybe-popup-context");
|
|
19
20
|
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
|
|
20
21
|
/**
|
|
21
22
|
* Thin context wrapper that composes `Popover` + `useAnchorPosition`.
|
|
@@ -25,7 +26,7 @@ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r
|
|
|
25
26
|
* use `Popover` + `useAnchorPosition` directly.
|
|
26
27
|
*/
|
|
27
28
|
var PopupContent = exports.PopupContent = /*#__PURE__*/(0, _react.forwardRef)(function PopupContent(_ref, ref) {
|
|
28
|
-
var _ref2,
|
|
29
|
+
var _ref2, _ctx$popoverRef;
|
|
29
30
|
var children = _ref.children,
|
|
30
31
|
role = _ref.role,
|
|
31
32
|
label = _ref.label,
|
|
@@ -41,25 +42,58 @@ var PopupContent = exports.PopupContent = /*#__PURE__*/(0, _react.forwardRef)(fu
|
|
|
41
42
|
onCloseProp = _ref.onClose,
|
|
42
43
|
testIdProp = _ref.testId,
|
|
43
44
|
forceFallbackPositioningProp = _ref.forceFallbackPositioning,
|
|
44
|
-
idProp = _ref.id
|
|
45
|
+
idProp = _ref.id,
|
|
46
|
+
onEnterFinish = _ref.onEnterFinish,
|
|
47
|
+
onExitFinish = _ref.onExitFinish;
|
|
45
48
|
// When inside <Popup>, context provides defaults. Props always win.
|
|
46
|
-
var ctx = (0,
|
|
49
|
+
var ctx = (0, _useMaybePopupContext.useMaybePopupContext)();
|
|
47
50
|
var triggerRef = triggerRefProp !== null && triggerRefProp !== void 0 ? triggerRefProp : ctx === null || ctx === void 0 ? void 0 : ctx.triggerRef;
|
|
48
51
|
var placement = (_ref2 = placementProp !== null && placementProp !== void 0 ? placementProp : ctx === null || ctx === void 0 ? void 0 : ctx.placement) !== null && _ref2 !== void 0 ? _ref2 : {};
|
|
49
52
|
var onClose = onCloseProp !== null && onCloseProp !== void 0 ? onCloseProp : ctx === null || ctx === void 0 ? void 0 : ctx.onClose;
|
|
50
53
|
var testId = testIdProp !== null && testIdProp !== void 0 ? testIdProp : ctx === null || ctx === void 0 ? void 0 : ctx.testId;
|
|
51
54
|
var forceFallbackPositioning = forceFallbackPositioningProp !== null && forceFallbackPositioningProp !== void 0 ? forceFallbackPositioningProp : ctx === null || ctx === void 0 ? void 0 : ctx.forceFallbackPositioning;
|
|
52
55
|
|
|
53
|
-
//
|
|
54
|
-
//
|
|
55
|
-
var isOpen =
|
|
56
|
-
|
|
57
|
-
// Combine internal state sync with consumer's onOpenChange callback.
|
|
58
|
-
// The Popup compound needs setIsOpen to keep aria-expanded on the trigger
|
|
59
|
-
// in sync, and the consumer may also want to respond to open/close events
|
|
60
|
-
// (e.g. for focus management).
|
|
61
|
-
var setIsOpen = ctx === null || ctx === void 0 ? void 0 : ctx.setIsOpen;
|
|
56
|
+
// isOpen: prop wins, otherwise derive from context popupState.
|
|
57
|
+
// 'animating-open' counts as open so <Popover> stays visible during entry animation.
|
|
58
|
+
var isOpen = isOpenProp !== null && isOpenProp !== void 0 ? isOpenProp : ctx !== null ? ctx.popupState === 'open' || ctx.popupState === 'animating-open' : false;
|
|
59
|
+
var setPopupState = ctx === null || ctx === void 0 ? void 0 : ctx.setPopupState;
|
|
62
60
|
var consumerOnOpenChange = ctx === null || ctx === void 0 ? void 0 : ctx.onOpenChange;
|
|
61
|
+
|
|
62
|
+
// ── TPopupState ──
|
|
63
|
+
//
|
|
64
|
+
// popupState is driven by handleOpenChange (below), which fires on every browser
|
|
65
|
+
// toggle event (showPopover / hidePopover / light-dismiss).
|
|
66
|
+
//
|
|
67
|
+
// Exception — initial mount with isOpen=true (prop-controlled usage):
|
|
68
|
+
// handleOpenChange only fires from the Popover's toggle event listener, which
|
|
69
|
+
// is registered in a useEffect. On the first render, useEffect hasn't run yet,
|
|
70
|
+
// so handleOpenChange never fires. We sync popupState here instead.
|
|
71
|
+
//
|
|
72
|
+
// Transitions when animations are active:
|
|
73
|
+
// closed → animating-open → open (enter)
|
|
74
|
+
// open → animating-closed → closed (exit, via onExitFinish)
|
|
75
|
+
//
|
|
76
|
+
// Without animation: closed ↔ open directly.
|
|
77
|
+
var willAnimate = Boolean(animate) && !(0, _reducedMotion.prefersReducedMotion)();
|
|
78
|
+
var hasMountedRef = (0, _react.useRef)(false);
|
|
79
|
+
(0, _react.useLayoutEffect)(function () {
|
|
80
|
+
if (hasMountedRef.current) {
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
hasMountedRef.current = true;
|
|
84
|
+
if (isOpen) {
|
|
85
|
+
setPopupState === null || setPopupState === void 0 || setPopupState(willAnimate ? 'animating-open' : 'open');
|
|
86
|
+
}
|
|
87
|
+
}, [isOpen, setPopupState, willAnimate]);
|
|
88
|
+
var handleEnterFinish = (0, _react.useCallback)(function () {
|
|
89
|
+
setPopupState === null || setPopupState === void 0 || setPopupState('open');
|
|
90
|
+
onEnterFinish === null || onEnterFinish === void 0 || onEnterFinish();
|
|
91
|
+
}, [setPopupState, onEnterFinish]);
|
|
92
|
+
var handleExitFinish = (0, _react.useCallback)(function () {
|
|
93
|
+
setPopupState === null || setPopupState === void 0 || setPopupState('closed');
|
|
94
|
+
onExitFinish === null || onExitFinish === void 0 || onExitFinish();
|
|
95
|
+
}, [setPopupState, onExitFinish]);
|
|
96
|
+
|
|
63
97
|
// Note: onOpenChange composition is handled by handleOpenChange below,
|
|
64
98
|
// which also adds nested-popover focus restoration.
|
|
65
99
|
|
|
@@ -91,7 +125,11 @@ var PopupContent = exports.PopupContent = /*#__PURE__*/(0, _react.forwardRef)(fu
|
|
|
91
125
|
// See: notes/architecture/focus-restoration.md
|
|
92
126
|
var handleOpenChange = (0, _react.useCallback)(function (args) {
|
|
93
127
|
// Sync compound state
|
|
94
|
-
|
|
128
|
+
if (args.isOpen) {
|
|
129
|
+
setPopupState === null || setPopupState === void 0 || setPopupState(willAnimate ? 'animating-open' : 'open');
|
|
130
|
+
} else {
|
|
131
|
+
setPopupState === null || setPopupState === void 0 || setPopupState(willAnimate ? 'animating-closed' : 'closed');
|
|
132
|
+
}
|
|
95
133
|
consumerOnOpenChange === null || consumerOnOpenChange === void 0 || consumerOnOpenChange(args);
|
|
96
134
|
|
|
97
135
|
// ── Nested popover focus restoration fallback ──
|
|
@@ -121,7 +159,7 @@ var PopupContent = exports.PopupContent = /*#__PURE__*/(0, _react.forwardRef)(fu
|
|
|
121
159
|
});
|
|
122
160
|
}
|
|
123
161
|
}
|
|
124
|
-
}, [
|
|
162
|
+
}, [consumerOnOpenChange, triggerRef, role, setPopupState, willAnimate]);
|
|
125
163
|
|
|
126
164
|
// ── Anchor positioning ──
|
|
127
165
|
// Compose useAnchorPosition with Popover. The hook positions the popover
|
|
@@ -160,6 +198,8 @@ var PopupContent = exports.PopupContent = /*#__PURE__*/(0, _react.forwardRef)(fu
|
|
|
160
198
|
labelledBy: labelledBy,
|
|
161
199
|
onClose: onClose !== null && onClose !== void 0 ? onClose : undefined,
|
|
162
200
|
onOpenChange: handleOpenChange,
|
|
201
|
+
onEnterFinish: handleEnterFinish,
|
|
202
|
+
onExitFinish: handleExitFinish,
|
|
163
203
|
testId: testId,
|
|
164
204
|
children: children,
|
|
165
205
|
// Standalone consumers can pass an explicit `id` - used by their own
|
|
@@ -3,42 +3,23 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.
|
|
7
|
-
exports.useMaybePopupContext = useMaybePopupContext;
|
|
8
|
-
exports.usePopupContext = usePopupContext;
|
|
6
|
+
exports.PopupContext = void 0;
|
|
9
7
|
var _react = require("react");
|
|
10
|
-
var PopupContext = /*#__PURE__*/(0, _react.createContext)(null);
|
|
11
|
-
|
|
12
8
|
/**
|
|
13
|
-
*
|
|
9
|
+
* Represents the lifecycle state of the popup.
|
|
14
10
|
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
* `
|
|
18
|
-
|
|
19
|
-
var PopupProvider = exports.PopupProvider = PopupContext.Provider;
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Returns the nearest `Popup` context value.
|
|
11
|
+
* - `'closed'`: fully closed, not visible, no animation playing.
|
|
12
|
+
* - `'animating-open'`: entry animation is playing (popup is opening but not yet settled).
|
|
13
|
+
* - `'open'`: fully open, browser popover is showing, entry animation complete.
|
|
14
|
+
* - `'animating-closed'`: exit animation is playing (popup is closing but still visible).
|
|
23
15
|
*
|
|
24
|
-
*
|
|
25
|
-
|
|
26
|
-
// eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports
|
|
27
|
-
function usePopupContext() {
|
|
28
|
-
var ctx = (0, _react.useContext)(PopupContext);
|
|
29
|
-
if (ctx === null) {
|
|
30
|
-
throw new Error('@atlaskit/top-layer: Popup compound components must be used within <Popup>.');
|
|
31
|
-
}
|
|
32
|
-
return ctx;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Returns the popup context if available, or `null` when used outside `<Popup>`.
|
|
16
|
+
* Used to derive `aria-expanded` on the trigger:
|
|
17
|
+
* - `aria-expanded` is `true` in `'animating-open'`, `'open'`, and `'animating-closed'`.
|
|
37
18
|
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
19
|
+
* This avoids screen readers announcing the popup as closed while it is
|
|
20
|
+
* still visually present on screen during animations, and prevents consumers
|
|
21
|
+
* that conditionally show/hide trigger UI based on `aria-expanded` from hiding
|
|
22
|
+
* the trigger (and thus the popup anchor) mid-animation.
|
|
40
23
|
*/
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
return (0, _react.useContext)(PopupContext);
|
|
44
|
-
}
|
|
24
|
+
|
|
25
|
+
var PopupContext = exports.PopupContext = /*#__PURE__*/(0, _react.createContext)(null);
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.PopupProvider = void 0;
|
|
7
|
+
var _popupContext = require("./popup-context");
|
|
8
|
+
/**
|
|
9
|
+
* __Popup provider__
|
|
10
|
+
*
|
|
11
|
+
* Provides shared popup state (placement, popoverId, triggerRef,
|
|
12
|
+
* isOpen, onClose) to compound child components such as `Popup.Trigger` and
|
|
13
|
+
* `Popup.Content`.
|
|
14
|
+
*/
|
|
15
|
+
var PopupProvider = exports.PopupProvider = _popupContext.PopupContext.Provider;
|
|
@@ -5,7 +5,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.PopupTriggerFunction = PopupTriggerFunction;
|
|
7
7
|
var _react = require("react");
|
|
8
|
-
var
|
|
8
|
+
var _usePopupContext2 = require("./use-popup-context");
|
|
9
9
|
/**
|
|
10
10
|
* Props passed to the `TriggerFunction` render-prop child.
|
|
11
11
|
*/
|
|
@@ -42,11 +42,11 @@ var _popupContext = require("./popup-context");
|
|
|
42
42
|
*/
|
|
43
43
|
function PopupTriggerFunction(_ref) {
|
|
44
44
|
var children = _ref.children;
|
|
45
|
-
var _usePopupContext = (0,
|
|
45
|
+
var _usePopupContext = (0, _usePopupContext2.usePopupContext)(),
|
|
46
46
|
triggerRef = _usePopupContext.triggerRef,
|
|
47
47
|
popoverRef = _usePopupContext.popoverRef,
|
|
48
48
|
popoverId = _usePopupContext.popoverId,
|
|
49
|
-
|
|
49
|
+
popupState = _usePopupContext.popupState,
|
|
50
50
|
ariaHasPopup = _usePopupContext.ariaHasPopup;
|
|
51
51
|
var ref = (0, _react.useCallback)(function (node) {
|
|
52
52
|
triggerRef.current = node;
|
|
@@ -62,14 +62,17 @@ function PopupTriggerFunction(_ref) {
|
|
|
62
62
|
}, [popoverRef]);
|
|
63
63
|
var ariaAttributes = (0, _react.useMemo)(function () {
|
|
64
64
|
return {
|
|
65
|
-
|
|
65
|
+
// aria-expanded stays true throughout entry and exit animations so screen readers
|
|
66
|
+
// don't announce the popup as closed while it's still visible, and consumers
|
|
67
|
+
// relying on aria-expanded to show/hide trigger UI don't lose the anchor mid-animation.
|
|
68
|
+
'aria-expanded': popupState === 'open' || popupState === 'animating-open' || popupState === 'animating-closed',
|
|
66
69
|
'aria-controls': popoverId,
|
|
67
70
|
'aria-haspopup': ariaHasPopup
|
|
68
71
|
};
|
|
69
|
-
}, [
|
|
72
|
+
}, [popupState, popoverId, ariaHasPopup]);
|
|
70
73
|
return children({
|
|
71
74
|
ref: ref,
|
|
72
|
-
isOpen:
|
|
75
|
+
isOpen: popupState === 'open' || popupState === 'animating-open',
|
|
73
76
|
popoverId: popoverId,
|
|
74
77
|
toggle: toggle,
|
|
75
78
|
ariaAttributes: ariaAttributes
|
|
@@ -7,7 +7,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
7
7
|
exports.PopupTrigger = PopupTrigger;
|
|
8
8
|
var _react = _interopRequireWildcard(require("react"));
|
|
9
9
|
var _slot = require("../internal/slot");
|
|
10
|
-
var
|
|
10
|
+
var _usePopupContext2 = require("./use-popup-context");
|
|
11
11
|
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
|
|
12
12
|
/**
|
|
13
13
|
* Wraps a single trigger element via `cloneElement`. Attaches aria
|
|
@@ -22,18 +22,19 @@ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r
|
|
|
22
22
|
*/
|
|
23
23
|
function PopupTrigger(_ref) {
|
|
24
24
|
var children = _ref.children;
|
|
25
|
-
var _usePopupContext = (0,
|
|
25
|
+
var _usePopupContext = (0, _usePopupContext2.usePopupContext)(),
|
|
26
26
|
triggerRef = _usePopupContext.triggerRef,
|
|
27
27
|
popoverRef = _usePopupContext.popoverRef,
|
|
28
28
|
popoverId = _usePopupContext.popoverId,
|
|
29
|
-
|
|
29
|
+
popupState = _usePopupContext.popupState,
|
|
30
30
|
ariaHasPopup = _usePopupContext.ariaHasPopup;
|
|
31
31
|
var childOnClick = /*#__PURE__*/(0, _react.isValidElement)(children) ? children.props.onClick : undefined;
|
|
32
32
|
|
|
33
|
-
//
|
|
34
|
-
//
|
|
35
|
-
|
|
36
|
-
isOpenRef
|
|
33
|
+
// Use a ref to track the latest isOpen value so the click handler
|
|
34
|
+
// does not need isOpen in its dependency array (which would recreate
|
|
35
|
+
// the handler on every open/close, breaking cloneElement identity).
|
|
36
|
+
var isOpenRef = _react.default.useRef(popupState === 'open' || popupState === 'animating-open');
|
|
37
|
+
isOpenRef.current = popupState === 'open' || popupState === 'animating-open';
|
|
37
38
|
var handleClick = (0, _react.useCallback)(function (event) {
|
|
38
39
|
var popoverEl = popoverRef.current;
|
|
39
40
|
if (popoverEl) {
|
|
@@ -53,8 +54,12 @@ function PopupTrigger(_ref) {
|
|
|
53
54
|
}, [popoverRef, childOnClick]);
|
|
54
55
|
return /*#__PURE__*/_react.default.createElement(_slot.Slot, {
|
|
55
56
|
ref: triggerRef,
|
|
56
|
-
onClick: handleClick
|
|
57
|
-
|
|
57
|
+
onClick: handleClick
|
|
58
|
+
// aria-expanded stays true throughout entry and exit animations so screen readers
|
|
59
|
+
// don't announce the popup as closed while it's still visible, and consumers
|
|
60
|
+
// relying on aria-expanded to show/hide trigger UI don't lose the anchor mid-animation.
|
|
61
|
+
,
|
|
62
|
+
"aria-expanded": popupState === 'open' || popupState === 'animating-open' || popupState === 'animating-closed',
|
|
58
63
|
"aria-controls": popoverId,
|
|
59
64
|
"aria-haspopup": ariaHasPopup
|
|
60
65
|
}, children);
|
package/dist/cjs/popup/popup.js
CHANGED
|
@@ -8,7 +8,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
8
8
|
exports.PopupRoot = PopupRoot;
|
|
9
9
|
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
|
|
10
10
|
var _react = _interopRequireWildcard(require("react"));
|
|
11
|
-
var
|
|
11
|
+
var _popupProvider = require("./popup-provider");
|
|
12
12
|
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
|
|
13
13
|
/**
|
|
14
14
|
* Popup compound: trigger + popover content.
|
|
@@ -44,10 +44,10 @@ function PopupRoot(props) {
|
|
|
44
44
|
var popoverId = "popover-".concat(sanitizedId);
|
|
45
45
|
var triggerRef = (0, _react.useRef)(null);
|
|
46
46
|
var popoverRef = (0, _react.useRef)(null);
|
|
47
|
-
var _useState = (0, _react.useState)(
|
|
47
|
+
var _useState = (0, _react.useState)('closed'),
|
|
48
48
|
_useState2 = (0, _slicedToArray2.default)(_useState, 2),
|
|
49
|
-
|
|
50
|
-
|
|
49
|
+
popupState = _useState2[0],
|
|
50
|
+
setPopupState = _useState2[1];
|
|
51
51
|
// Initial seed before `Popup.Content`'s layout effect resolves the
|
|
52
52
|
// real role on first paint.
|
|
53
53
|
var _useState3 = (0, _react.useState)('dialog'),
|
|
@@ -66,8 +66,8 @@ function PopupRoot(props) {
|
|
|
66
66
|
onClose: onClose ? handleClose : null,
|
|
67
67
|
triggerRef: triggerRef,
|
|
68
68
|
popoverRef: popoverRef,
|
|
69
|
-
|
|
70
|
-
|
|
69
|
+
popupState: popupState,
|
|
70
|
+
setPopupState: setPopupState,
|
|
71
71
|
onOpenChange: onOpenChange,
|
|
72
72
|
mode: mode,
|
|
73
73
|
ariaHasPopup: ariaHasPopup,
|
|
@@ -75,7 +75,7 @@ function PopupRoot(props) {
|
|
|
75
75
|
testId: testId,
|
|
76
76
|
forceFallbackPositioning: forceFallbackPositioning
|
|
77
77
|
};
|
|
78
|
-
return /*#__PURE__*/_react.default.createElement(
|
|
78
|
+
return /*#__PURE__*/_react.default.createElement(_popupProvider.PopupProvider, {
|
|
79
79
|
value: contextValue
|
|
80
80
|
}, children);
|
|
81
81
|
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.useMaybePopupContext = useMaybePopupContext;
|
|
7
|
+
var _react = require("react");
|
|
8
|
+
var _popupContext = require("./popup-context");
|
|
9
|
+
/**
|
|
10
|
+
* Returns the popup context if available, or `null` when used outside `<Popup>`.
|
|
11
|
+
*
|
|
12
|
+
* Used by `PopupContent` to support standalone usage (e.g. tooltip)
|
|
13
|
+
* where values are passed as props instead of coming from a compound component.
|
|
14
|
+
*/
|
|
15
|
+
function useMaybePopupContext() {
|
|
16
|
+
return (0, _react.useContext)(_popupContext.PopupContext);
|
|
17
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.usePopupContext = usePopupContext;
|
|
7
|
+
var _react = require("react");
|
|
8
|
+
var _popupContext = require("./popup-context");
|
|
9
|
+
/**
|
|
10
|
+
* Returns the nearest `Popup` context value.
|
|
11
|
+
*
|
|
12
|
+
* Throws if called outside of a `<Popup>` compound component.
|
|
13
|
+
*/
|
|
14
|
+
function usePopupContext() {
|
|
15
|
+
var ctx = (0, _react.useContext)(_popupContext.PopupContext);
|
|
16
|
+
if (ctx === null) {
|
|
17
|
+
throw new Error('@atlaskit/top-layer: Popup compound components must be used within <Popup>.');
|
|
18
|
+
}
|
|
19
|
+
return ctx;
|
|
20
|
+
}
|
|
@@ -6,7 +6,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
Object.defineProperty(exports, "isAtCurrentMenuLevel", {
|
|
7
7
|
enumerable: true,
|
|
8
8
|
get: function get() {
|
|
9
|
-
return
|
|
9
|
+
return _isAtCurrentMenuLevel.isAtCurrentMenuLevel;
|
|
10
10
|
}
|
|
11
11
|
});
|
|
12
12
|
Object.defineProperty(exports, "useArrowNavigation", {
|
|
@@ -15,4 +15,5 @@ Object.defineProperty(exports, "useArrowNavigation", {
|
|
|
15
15
|
return _useArrowNavigation.useArrowNavigation;
|
|
16
16
|
}
|
|
17
17
|
});
|
|
18
|
-
var _useArrowNavigation = require("./use-arrow-navigation");
|
|
18
|
+
var _useArrowNavigation = require("./use-arrow-navigation");
|
|
19
|
+
var _isAtCurrentMenuLevel = require("./is-at-current-menu-level");
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.isAtCurrentMenuLevel = isAtCurrentMenuLevel;
|
|
7
|
+
var menuScope = '[role="menu"]';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Returns true if the element belongs to the current menu level of the
|
|
11
|
+
* container, i.e. it is NOT inside a nested `role="menu"` sub-container.
|
|
12
|
+
*
|
|
13
|
+
* Uses `element.closest('[role="menu"]')` to determine the nearest menu
|
|
14
|
+
* scope. If the nearest scope is the container's own `role="menu"` element,
|
|
15
|
+
* the element belongs to this level. If it is a different (nested) menu,
|
|
16
|
+
* the element belongs to a child level and should be excluded.
|
|
17
|
+
*
|
|
18
|
+
* Supports two container patterns:
|
|
19
|
+
*
|
|
20
|
+
* **1. Container has `role="menu"` directly** (preferred, used by avatar-group):
|
|
21
|
+
* ```
|
|
22
|
+
* <div ref={containerRef} role="menu">
|
|
23
|
+
* <button role="menuitem" /> ← isAtCurrentMenuLevel → true
|
|
24
|
+
* <div role="menu"> ← nested sub-menu
|
|
25
|
+
* <button role="menuitem" /> ← isAtCurrentMenuLevel → false
|
|
26
|
+
* </div>
|
|
27
|
+
* </div>
|
|
28
|
+
* ```
|
|
29
|
+
* Uses the simple check: `element.closest('[role="menu"]') === container`
|
|
30
|
+
*
|
|
31
|
+
* **2. Container is a wrapper without `role="menu"`** (used by dropdown-menu,
|
|
32
|
+
* where `MenuGroup` owns `role="menu"` but does not accept a ref):
|
|
33
|
+
* ```
|
|
34
|
+
* <div ref={containerRef}> ← wrapper (no role="menu")
|
|
35
|
+
* <MenuGroup role="menu">
|
|
36
|
+
* <button role="menuitem" /> ← isAtCurrentMenuLevel → true
|
|
37
|
+
* <div role="menu"> ← nested sub-menu
|
|
38
|
+
* <button role="menuitem" /> ← isAtCurrentMenuLevel → false
|
|
39
|
+
* </div>
|
|
40
|
+
* </MenuGroup>
|
|
41
|
+
* </div>
|
|
42
|
+
* ```
|
|
43
|
+
* Falls back to walking the DOM to check that the element's closest
|
|
44
|
+
* `role="menu"` is the container's own menu (not doubly nested).
|
|
45
|
+
*
|
|
46
|
+
* Ideally all consumers should use pattern 1 (place the ref directly on the
|
|
47
|
+
* `role="menu"` element). Pattern 2 exists because `@atlaskit/menu`'s
|
|
48
|
+
* `MenuGroup` does not currently accept a ref. If `MenuGroup` gains ref
|
|
49
|
+
* support in the future, dropdown-menu should switch to pattern 1 and the
|
|
50
|
+
* fallback path can be removed.
|
|
51
|
+
*
|
|
52
|
+
* Used both as a `TFocusableFilter` (to scope getNextFocusable etc.) and as
|
|
53
|
+
* a guard to prevent parent menu handlers from acting on events that
|
|
54
|
+
* belong to a nested menu.
|
|
55
|
+
*/
|
|
56
|
+
function isAtCurrentMenuLevel(element, container) {
|
|
57
|
+
var closestMenu = element.closest(menuScope);
|
|
58
|
+
|
|
59
|
+
// Container itself has role="menu". Element belongs to this level
|
|
60
|
+
// if its closest menu is the container.
|
|
61
|
+
if (container.getAttribute('role') === 'menu') {
|
|
62
|
+
return closestMenu === container;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Container is a wrapper without role="menu" (e.g. dropdown-menu
|
|
66
|
+
// wraps a MenuGroup). The element belongs to the top level if its
|
|
67
|
+
// closest role="menu" ancestor is a direct child of the container,
|
|
68
|
+
// i.e. there is no nested role="menu" between them.
|
|
69
|
+
if (closestMenu === null) {
|
|
70
|
+
return true;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Walk up from the closest menu to see if it is "owned" by this
|
|
74
|
+
// container without passing through another role="menu" first.
|
|
75
|
+
var parent = closestMenu.parentElement;
|
|
76
|
+
while (parent && parent !== container) {
|
|
77
|
+
if (parent.getAttribute('role') === 'menu') {
|
|
78
|
+
// There is a parent menu between the closest menu and the
|
|
79
|
+
// container, so the element is in a nested sub-menu.
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
parent = parent.parentElement;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// The closest menu is directly inside the container (no nesting).
|
|
86
|
+
return parent === container;
|
|
87
|
+
}
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.isAtCurrentMenuLevel = isAtCurrentMenuLevel;
|
|
7
6
|
exports.useArrowNavigation = useArrowNavigation;
|
|
8
7
|
var _react = require("react");
|
|
9
8
|
var _bindEventListener = require("bind-event-listener");
|
|
@@ -12,86 +11,6 @@ var _keycodes = require("@atlaskit/ds-lib/keycodes");
|
|
|
12
11
|
var _focus = require("../focus");
|
|
13
12
|
var menuScope = '[role="menu"]';
|
|
14
13
|
|
|
15
|
-
/**
|
|
16
|
-
* Returns true if the element belongs to the current menu level of the
|
|
17
|
-
* container, i.e. it is NOT inside a nested `role="menu"` sub-container.
|
|
18
|
-
*
|
|
19
|
-
* Uses `element.closest('[role="menu"]')` to determine the nearest menu
|
|
20
|
-
* scope. If the nearest scope is the container's own `role="menu"` element,
|
|
21
|
-
* the element belongs to this level. If it is a different (nested) menu,
|
|
22
|
-
* the element belongs to a child level and should be excluded.
|
|
23
|
-
*
|
|
24
|
-
* Supports two container patterns:
|
|
25
|
-
*
|
|
26
|
-
* **1. Container has `role="menu"` directly** (preferred, used by avatar-group):
|
|
27
|
-
* ```
|
|
28
|
-
* <div ref={containerRef} role="menu">
|
|
29
|
-
* <button role="menuitem" /> ← isAtCurrentMenuLevel → true
|
|
30
|
-
* <div role="menu"> ← nested sub-menu
|
|
31
|
-
* <button role="menuitem" /> ← isAtCurrentMenuLevel → false
|
|
32
|
-
* </div>
|
|
33
|
-
* </div>
|
|
34
|
-
* ```
|
|
35
|
-
* Uses the simple check: `element.closest('[role="menu"]') === container`
|
|
36
|
-
*
|
|
37
|
-
* **2. Container is a wrapper without `role="menu"`** (used by dropdown-menu,
|
|
38
|
-
* where `MenuGroup` owns `role="menu"` but does not accept a ref):
|
|
39
|
-
* ```
|
|
40
|
-
* <div ref={containerRef}> ← wrapper (no role="menu")
|
|
41
|
-
* <MenuGroup role="menu">
|
|
42
|
-
* <button role="menuitem" /> ← isAtCurrentMenuLevel → true
|
|
43
|
-
* <div role="menu"> ← nested sub-menu
|
|
44
|
-
* <button role="menuitem" /> ← isAtCurrentMenuLevel → false
|
|
45
|
-
* </div>
|
|
46
|
-
* </MenuGroup>
|
|
47
|
-
* </div>
|
|
48
|
-
* ```
|
|
49
|
-
* Falls back to walking the DOM to check that the element's closest
|
|
50
|
-
* `role="menu"` is the container's own menu (not doubly nested).
|
|
51
|
-
*
|
|
52
|
-
* Ideally all consumers should use pattern 1 (place the ref directly on the
|
|
53
|
-
* `role="menu"` element). Pattern 2 exists because `@atlaskit/menu`'s
|
|
54
|
-
* `MenuGroup` does not currently accept a ref. If `MenuGroup` gains ref
|
|
55
|
-
* support in the future, dropdown-menu should switch to pattern 1 and the
|
|
56
|
-
* fallback path can be removed.
|
|
57
|
-
*
|
|
58
|
-
* Used both as a `TFocusableFilter` (to scope getNextFocusable etc.) and as
|
|
59
|
-
* a guard to prevent parent menu handlers from acting on events that
|
|
60
|
-
* belong to a nested menu.
|
|
61
|
-
*/
|
|
62
|
-
function isAtCurrentMenuLevel(element, container) {
|
|
63
|
-
var closestMenu = element.closest(menuScope);
|
|
64
|
-
|
|
65
|
-
// Container itself has role="menu". Element belongs to this level
|
|
66
|
-
// if its closest menu is the container.
|
|
67
|
-
if (container.getAttribute('role') === 'menu') {
|
|
68
|
-
return closestMenu === container;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
// Container is a wrapper without role="menu" (e.g. dropdown-menu
|
|
72
|
-
// wraps a MenuGroup). The element belongs to the top level if its
|
|
73
|
-
// closest role="menu" ancestor is a direct child of the container,
|
|
74
|
-
// i.e. there is no nested role="menu" between them.
|
|
75
|
-
if (closestMenu === null) {
|
|
76
|
-
return true;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
// Walk up from the closest menu to see if it is "owned" by this
|
|
80
|
-
// container without passing through another role="menu" first.
|
|
81
|
-
var parent = closestMenu.parentElement;
|
|
82
|
-
while (parent && parent !== container) {
|
|
83
|
-
if (parent.getAttribute('role') === 'menu') {
|
|
84
|
-
// There is a parent menu between the closest menu and the
|
|
85
|
-
// container, so the element is in a nested sub-menu.
|
|
86
|
-
return false;
|
|
87
|
-
}
|
|
88
|
-
parent = parent.parentElement;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
// The closest menu is directly inside the container (no nesting).
|
|
92
|
-
return parent === container;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
14
|
/**
|
|
96
15
|
* Args for `useArrowNavigation`.
|
|
97
16
|
*
|
|
@@ -142,7 +61,6 @@ function isAtCurrentMenuLevel(element, container) {
|
|
|
142
61
|
* });
|
|
143
62
|
* ```
|
|
144
63
|
*/
|
|
145
|
-
// eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports
|
|
146
64
|
function useArrowNavigation(_ref) {
|
|
147
65
|
var containerRef = _ref.containerRef,
|
|
148
66
|
onClose = _ref.onClose,
|
|
@@ -118,6 +118,7 @@ export function slideAndFade(options) {
|
|
|
118
118
|
placement,
|
|
119
119
|
distance
|
|
120
120
|
}),
|
|
121
|
+
enterDurationMs: 350,
|
|
121
122
|
exitDurationMs: 175
|
|
122
123
|
};
|
|
123
124
|
}
|
|
@@ -169,6 +170,7 @@ export function fade() {
|
|
|
169
170
|
return {
|
|
170
171
|
name: 'fade',
|
|
171
172
|
css: FADE_CSS,
|
|
173
|
+
enterDurationMs: 350,
|
|
172
174
|
exitDurationMs: 175
|
|
173
175
|
};
|
|
174
176
|
}
|
|
@@ -224,6 +226,7 @@ export function scaleAndFade() {
|
|
|
224
226
|
return {
|
|
225
227
|
name: 'scale-and-fade',
|
|
226
228
|
css: SCALE_AND_FADE_CSS,
|
|
229
|
+
enterDurationMs: 350,
|
|
227
230
|
exitDurationMs: 175
|
|
228
231
|
};
|
|
229
232
|
}
|
|
@@ -314,6 +317,7 @@ export function dialogSlideUpAndFade(options) {
|
|
|
314
317
|
return {
|
|
315
318
|
name: distance === 12 ? 'slide-up-and-fade' : `slide-up-and-fade-${distance}`,
|
|
316
319
|
css: distance === 12 ? DIALOG_SLIDE_UP_AND_FADE_CSS : DIALOG_SLIDE_UP_AND_FADE_CSS.replace(/12px/g, `${distance}px`),
|
|
320
|
+
enterDurationMs: 350,
|
|
317
321
|
exitDurationMs: 175
|
|
318
322
|
};
|
|
319
323
|
}
|
|
@@ -389,6 +393,7 @@ export function dialogFade() {
|
|
|
389
393
|
return {
|
|
390
394
|
name: 'fade',
|
|
391
395
|
css: DIALOG_FADE_CSS,
|
|
396
|
+
enterDurationMs: 350,
|
|
392
397
|
exitDurationMs: 175
|
|
393
398
|
};
|
|
394
399
|
}
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
export { useArrowNavigation
|
|
1
|
+
export { useArrowNavigation } from '../use-arrow-navigation';
|
|
2
|
+
export { isAtCurrentMenuLevel } from '../use-arrow-navigation/is-at-current-menu-level';
|