@atlaskit/top-layer 0.1.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 +44 -0
- package/README.md +151 -0
- package/animations/package.json +17 -0
- package/arrow/package.json +17 -0
- package/create-close-event/package.json +17 -0
- package/dialog/package.json +17 -0
- package/dialog-scroll-lock/package.json +17 -0
- package/dist/cjs/animations/presets.js +199 -0
- package/dist/cjs/animations/types.js +5 -0
- package/dist/cjs/arrow/index.js +130 -0
- package/dist/cjs/arrow/types.js +5 -0
- package/dist/cjs/dialog/create-close-event.js +39 -0
- package/dist/cjs/dialog/dialog-content.compiled.css +14 -0
- package/dist/cjs/dialog/dialog-content.js +144 -0
- package/dist/cjs/dialog/index.js +19 -0
- package/dist/cjs/dialog/types.js +5 -0
- package/dist/cjs/dialog-scroll-lock/index.js +46 -0
- package/dist/cjs/entry-points/animations.js +36 -0
- package/dist/cjs/entry-points/arrow.js +12 -0
- package/dist/cjs/entry-points/create-close-event.js +19 -0
- package/dist/cjs/entry-points/dialog-scroll-lock.js +12 -0
- package/dist/cjs/entry-points/dialog.js +12 -0
- package/dist/cjs/entry-points/focus.js +24 -0
- package/dist/cjs/entry-points/placement-map.js +18 -0
- package/dist/cjs/entry-points/popover.js +12 -0
- package/dist/cjs/entry-points/popup-surface.js +12 -0
- package/dist/cjs/entry-points/popup.js +12 -0
- package/dist/cjs/entry-points/use-anchor-position.js +12 -0
- package/dist/cjs/entry-points/use-arrow-navigation.js +18 -0
- package/dist/cjs/entry-points/use-simple-light-dismiss.js +12 -0
- package/dist/cjs/focus/focus.js +115 -0
- package/dist/cjs/focus/index.js +24 -0
- package/dist/cjs/index.js +8 -0
- package/dist/cjs/internal/anchor-positioning-fallback.js +154 -0
- package/dist/cjs/internal/combine.js +29 -0
- package/dist/cjs/internal/ensure-preset-styles.js +34 -0
- package/dist/cjs/internal/reduced-motion.js +27 -0
- package/dist/cjs/internal/resolve-placement.js +24 -0
- package/dist/cjs/internal/role-types.js +66 -0
- package/dist/cjs/internal/set-style.js +42 -0
- package/dist/cjs/internal/slot.js +65 -0
- package/dist/cjs/internal/use-anchor-positioning.js +336 -0
- package/dist/cjs/internal/use-animated-visibility.js +169 -0
- package/dist/cjs/internal/use-animation-preset.js +24 -0
- package/dist/cjs/internal/use-focus-wrap.js +94 -0
- package/dist/cjs/internal/use-initial-focus.js +112 -0
- package/dist/cjs/internal/use-preset-styles.js +27 -0
- package/dist/cjs/placement-map/index.js +147 -0
- package/dist/cjs/popover/create-close-event.js +44 -0
- package/dist/cjs/popover/index.js +19 -0
- package/dist/cjs/popover/popover.compiled.css +13 -0
- package/dist/cjs/popover/popover.js +251 -0
- package/dist/cjs/popover/types.js +5 -0
- package/dist/cjs/popup/index.js +37 -0
- package/dist/cjs/popup/popup-content.js +201 -0
- package/dist/cjs/popup/popup-context.js +42 -0
- package/dist/cjs/popup/popup-surface.compiled.css +5 -0
- package/dist/cjs/popup/popup-surface.js +30 -0
- package/dist/cjs/popup/popup-trigger-function.js +74 -0
- package/dist/cjs/popup/popup-trigger.js +82 -0
- package/dist/cjs/popup/popup.js +70 -0
- package/dist/cjs/popup/types.js +5 -0
- package/dist/cjs/use-arrow-navigation/index.js +18 -0
- package/dist/cjs/use-arrow-navigation/use-arrow-navigation.js +245 -0
- package/dist/cjs/use-simple-light-dismiss/index.js +84 -0
- package/dist/es2019/animations/presets.js +375 -0
- package/dist/es2019/animations/types.js +1 -0
- package/dist/es2019/arrow/index.js +249 -0
- package/dist/es2019/arrow/types.js +1 -0
- package/dist/es2019/dialog/create-close-event.js +34 -0
- package/dist/es2019/dialog/dialog-content.compiled.css +14 -0
- package/dist/es2019/dialog/dialog-content.js +138 -0
- package/dist/es2019/dialog/index.js +2 -0
- package/dist/es2019/dialog/types.js +1 -0
- package/dist/es2019/dialog-scroll-lock/index.js +41 -0
- package/dist/es2019/entry-points/animations.js +1 -0
- package/dist/es2019/entry-points/arrow.js +1 -0
- package/dist/es2019/entry-points/create-close-event.js +2 -0
- package/dist/es2019/entry-points/dialog-scroll-lock.js +1 -0
- package/dist/es2019/entry-points/dialog.js +1 -0
- package/dist/es2019/entry-points/focus.js +1 -0
- package/dist/es2019/entry-points/placement-map.js +1 -0
- package/dist/es2019/entry-points/popover.js +1 -0
- package/dist/es2019/entry-points/popup-surface.js +1 -0
- package/dist/es2019/entry-points/popup.js +1 -0
- package/dist/es2019/entry-points/use-anchor-position.js +1 -0
- package/dist/es2019/entry-points/use-arrow-navigation.js +1 -0
- package/dist/es2019/entry-points/use-simple-light-dismiss.js +1 -0
- package/dist/es2019/focus/focus.js +107 -0
- package/dist/es2019/focus/index.js +1 -0
- package/dist/es2019/index.js +7 -0
- package/dist/es2019/internal/anchor-positioning-fallback.js +153 -0
- package/dist/es2019/internal/combine.js +18 -0
- package/dist/es2019/internal/ensure-preset-styles.js +29 -0
- package/dist/es2019/internal/reduced-motion.js +21 -0
- package/dist/es2019/internal/resolve-placement.js +19 -0
- package/dist/es2019/internal/role-types.js +61 -0
- package/dist/es2019/internal/set-style.js +39 -0
- package/dist/es2019/internal/slot.js +57 -0
- package/dist/es2019/internal/use-anchor-positioning.js +330 -0
- package/dist/es2019/internal/use-animated-visibility.js +159 -0
- package/dist/es2019/internal/use-animation-preset.js +18 -0
- package/dist/es2019/internal/use-focus-wrap.js +90 -0
- package/dist/es2019/internal/use-initial-focus.js +109 -0
- package/dist/es2019/internal/use-preset-styles.js +22 -0
- package/dist/es2019/placement-map/index.js +142 -0
- package/dist/es2019/popover/create-close-event.js +39 -0
- package/dist/es2019/popover/index.js +2 -0
- package/dist/es2019/popover/popover.compiled.css +13 -0
- package/dist/es2019/popover/popover.js +240 -0
- package/dist/es2019/popover/types.js +1 -0
- package/dist/es2019/popup/index.js +33 -0
- package/dist/es2019/popup/popup-content.js +192 -0
- package/dist/es2019/popup/popup-context.js +34 -0
- package/dist/es2019/popup/popup-surface.compiled.css +5 -0
- package/dist/es2019/popup/popup-surface.js +24 -0
- package/dist/es2019/popup/popup-trigger-function.js +69 -0
- package/dist/es2019/popup/popup-trigger.js +76 -0
- package/dist/es2019/popup/popup.js +56 -0
- package/dist/es2019/popup/types.js +1 -0
- package/dist/es2019/use-arrow-navigation/index.js +1 -0
- package/dist/es2019/use-arrow-navigation/use-arrow-navigation.js +238 -0
- package/dist/es2019/use-simple-light-dismiss/index.js +79 -0
- package/dist/esm/animations/presets.js +190 -0
- package/dist/esm/animations/types.js +1 -0
- package/dist/esm/arrow/index.js +123 -0
- package/dist/esm/arrow/types.js +1 -0
- package/dist/esm/dialog/create-close-event.js +33 -0
- package/dist/esm/dialog/dialog-content.compiled.css +14 -0
- package/dist/esm/dialog/dialog-content.js +135 -0
- package/dist/esm/dialog/index.js +2 -0
- package/dist/esm/dialog/types.js +1 -0
- package/dist/esm/dialog-scroll-lock/index.js +41 -0
- package/dist/esm/entry-points/animations.js +1 -0
- package/dist/esm/entry-points/arrow.js +1 -0
- package/dist/esm/entry-points/create-close-event.js +2 -0
- package/dist/esm/entry-points/dialog-scroll-lock.js +1 -0
- package/dist/esm/entry-points/dialog.js +1 -0
- package/dist/esm/entry-points/focus.js +1 -0
- package/dist/esm/entry-points/placement-map.js +1 -0
- package/dist/esm/entry-points/popover.js +1 -0
- package/dist/esm/entry-points/popup-surface.js +1 -0
- package/dist/esm/entry-points/popup.js +1 -0
- package/dist/esm/entry-points/use-anchor-position.js +1 -0
- package/dist/esm/entry-points/use-arrow-navigation.js +1 -0
- package/dist/esm/entry-points/use-simple-light-dismiss.js +1 -0
- package/dist/esm/focus/focus.js +107 -0
- package/dist/esm/focus/index.js +1 -0
- package/dist/esm/index.js +7 -0
- package/dist/esm/internal/anchor-positioning-fallback.js +147 -0
- package/dist/esm/internal/combine.js +23 -0
- package/dist/esm/internal/ensure-preset-styles.js +28 -0
- package/dist/esm/internal/reduced-motion.js +21 -0
- package/dist/esm/internal/resolve-placement.js +18 -0
- package/dist/esm/internal/role-types.js +60 -0
- package/dist/esm/internal/set-style.js +36 -0
- package/dist/esm/internal/slot.js +59 -0
- package/dist/esm/internal/use-anchor-positioning.js +323 -0
- package/dist/esm/internal/use-animated-visibility.js +162 -0
- package/dist/esm/internal/use-animation-preset.js +18 -0
- package/dist/esm/internal/use-focus-wrap.js +89 -0
- package/dist/esm/internal/use-initial-focus.js +107 -0
- package/dist/esm/internal/use-preset-styles.js +21 -0
- package/dist/esm/placement-map/index.js +141 -0
- package/dist/esm/popover/create-close-event.js +38 -0
- package/dist/esm/popover/index.js +2 -0
- package/dist/esm/popover/popover.compiled.css +13 -0
- package/dist/esm/popover/popover.js +242 -0
- package/dist/esm/popover/types.js +1 -0
- package/dist/esm/popup/index.js +33 -0
- package/dist/esm/popup/popup-content.js +192 -0
- package/dist/esm/popup/popup-context.js +34 -0
- package/dist/esm/popup/popup-surface.compiled.css +5 -0
- package/dist/esm/popup/popup-surface.js +23 -0
- package/dist/esm/popup/popup-trigger-function.js +69 -0
- package/dist/esm/popup/popup-trigger.js +74 -0
- package/dist/esm/popup/popup.js +61 -0
- package/dist/esm/popup/types.js +1 -0
- package/dist/esm/use-arrow-navigation/index.js +1 -0
- package/dist/esm/use-arrow-navigation/use-arrow-navigation.js +238 -0
- package/dist/esm/use-simple-light-dismiss/index.js +78 -0
- package/dist/types/animations/presets.d.ts +94 -0
- package/dist/types/animations/types.d.ts +42 -0
- package/dist/types/arrow/index.d.ts +24 -0
- package/dist/types/arrow/types.d.ts +29 -0
- package/dist/types/dialog/create-close-event.d.ts +24 -0
- package/dist/types/dialog/dialog-content.d.ts +20 -0
- package/dist/types/dialog/index.d.ts +3 -0
- package/dist/types/dialog/types.d.ts +92 -0
- package/dist/types/dialog-scroll-lock/index.d.ts +24 -0
- package/dist/types/entry-points/animations.d.ts +2 -0
- package/dist/types/entry-points/arrow.d.ts +2 -0
- package/dist/types/entry-points/create-close-event.d.ts +4 -0
- package/dist/types/entry-points/dialog-scroll-lock.d.ts +1 -0
- package/dist/types/entry-points/dialog.d.ts +2 -0
- package/dist/types/entry-points/focus.d.ts +2 -0
- package/dist/types/entry-points/placement-map.d.ts +2 -0
- package/dist/types/entry-points/popover.d.ts +2 -0
- package/dist/types/entry-points/popup-surface.d.ts +2 -0
- package/dist/types/entry-points/popup.d.ts +2 -0
- package/dist/types/entry-points/use-anchor-position.d.ts +1 -0
- package/dist/types/entry-points/use-arrow-navigation.d.ts +2 -0
- package/dist/types/entry-points/use-simple-light-dismiss.d.ts +2 -0
- package/dist/types/focus/focus.d.ts +42 -0
- package/dist/types/focus/index.d.ts +2 -0
- package/dist/types/index.d.ts +0 -0
- package/dist/types/internal/anchor-positioning-fallback.d.ts +24 -0
- package/dist/types/internal/combine.d.ts +14 -0
- package/dist/types/internal/ensure-preset-styles.d.ts +6 -0
- package/dist/types/internal/reduced-motion.d.ts +14 -0
- package/dist/types/internal/resolve-placement.d.ts +16 -0
- package/dist/types/internal/role-types.d.ts +62 -0
- package/dist/types/internal/set-style.d.ts +28 -0
- package/dist/types/internal/slot.d.ts +29 -0
- package/dist/types/internal/use-anchor-positioning.d.ts +95 -0
- package/dist/types/internal/use-animated-visibility.d.ts +74 -0
- package/dist/types/internal/use-animation-preset.d.ts +11 -0
- package/dist/types/internal/use-focus-wrap.d.ts +20 -0
- package/dist/types/internal/use-initial-focus.d.ts +21 -0
- package/dist/types/internal/use-preset-styles.d.ts +15 -0
- package/dist/types/placement-map/index.d.ts +55 -0
- package/dist/types/popover/create-close-event.d.ts +26 -0
- package/dist/types/popover/index.d.ts +3 -0
- package/dist/types/popover/popover.d.ts +22 -0
- package/dist/types/popover/types.d.ts +153 -0
- package/dist/types/popup/index.d.ts +34 -0
- package/dist/types/popup/popup-content.d.ts +14 -0
- package/dist/types/popup/popup-context.d.ts +96 -0
- package/dist/types/popup/popup-surface.d.ts +16 -0
- package/dist/types/popup/popup-trigger-function.d.ts +108 -0
- package/dist/types/popup/popup-trigger.d.ts +23 -0
- package/dist/types/popup/popup.d.ts +14 -0
- package/dist/types/popup/types.d.ts +289 -0
- package/dist/types/use-arrow-navigation/index.d.ts +2 -0
- package/dist/types/use-arrow-navigation/use-arrow-navigation.d.ts +136 -0
- package/dist/types/use-simple-light-dismiss/index.d.ts +45 -0
- package/dist/types-ts4.5/animations/presets.d.ts +94 -0
- package/dist/types-ts4.5/animations/types.d.ts +42 -0
- package/dist/types-ts4.5/arrow/index.d.ts +24 -0
- package/dist/types-ts4.5/arrow/types.d.ts +29 -0
- package/dist/types-ts4.5/dialog/create-close-event.d.ts +24 -0
- package/dist/types-ts4.5/dialog/dialog-content.d.ts +20 -0
- package/dist/types-ts4.5/dialog/index.d.ts +3 -0
- package/dist/types-ts4.5/dialog/types.d.ts +92 -0
- package/dist/types-ts4.5/dialog-scroll-lock/index.d.ts +24 -0
- package/dist/types-ts4.5/entry-points/animations.d.ts +2 -0
- package/dist/types-ts4.5/entry-points/arrow.d.ts +2 -0
- package/dist/types-ts4.5/entry-points/create-close-event.d.ts +4 -0
- package/dist/types-ts4.5/entry-points/dialog-scroll-lock.d.ts +1 -0
- package/dist/types-ts4.5/entry-points/dialog.d.ts +2 -0
- package/dist/types-ts4.5/entry-points/focus.d.ts +2 -0
- package/dist/types-ts4.5/entry-points/placement-map.d.ts +2 -0
- package/dist/types-ts4.5/entry-points/popover.d.ts +2 -0
- package/dist/types-ts4.5/entry-points/popup-surface.d.ts +2 -0
- package/dist/types-ts4.5/entry-points/popup.d.ts +2 -0
- package/dist/types-ts4.5/entry-points/use-anchor-position.d.ts +1 -0
- package/dist/types-ts4.5/entry-points/use-arrow-navigation.d.ts +2 -0
- package/dist/types-ts4.5/entry-points/use-simple-light-dismiss.d.ts +2 -0
- package/dist/types-ts4.5/focus/focus.d.ts +42 -0
- package/dist/types-ts4.5/focus/index.d.ts +2 -0
- package/dist/types-ts4.5/index.d.ts +0 -0
- package/dist/types-ts4.5/internal/anchor-positioning-fallback.d.ts +24 -0
- package/dist/types-ts4.5/internal/combine.d.ts +14 -0
- package/dist/types-ts4.5/internal/ensure-preset-styles.d.ts +6 -0
- package/dist/types-ts4.5/internal/reduced-motion.d.ts +14 -0
- package/dist/types-ts4.5/internal/resolve-placement.d.ts +16 -0
- package/dist/types-ts4.5/internal/role-types.d.ts +62 -0
- package/dist/types-ts4.5/internal/set-style.d.ts +28 -0
- package/dist/types-ts4.5/internal/slot.d.ts +29 -0
- package/dist/types-ts4.5/internal/use-anchor-positioning.d.ts +95 -0
- package/dist/types-ts4.5/internal/use-animated-visibility.d.ts +74 -0
- package/dist/types-ts4.5/internal/use-animation-preset.d.ts +11 -0
- package/dist/types-ts4.5/internal/use-focus-wrap.d.ts +20 -0
- package/dist/types-ts4.5/internal/use-initial-focus.d.ts +21 -0
- package/dist/types-ts4.5/internal/use-preset-styles.d.ts +15 -0
- package/dist/types-ts4.5/placement-map/index.d.ts +55 -0
- package/dist/types-ts4.5/popover/create-close-event.d.ts +26 -0
- package/dist/types-ts4.5/popover/index.d.ts +3 -0
- package/dist/types-ts4.5/popover/popover.d.ts +22 -0
- package/dist/types-ts4.5/popover/types.d.ts +153 -0
- package/dist/types-ts4.5/popup/index.d.ts +34 -0
- package/dist/types-ts4.5/popup/popup-content.d.ts +14 -0
- package/dist/types-ts4.5/popup/popup-context.d.ts +96 -0
- package/dist/types-ts4.5/popup/popup-surface.d.ts +16 -0
- package/dist/types-ts4.5/popup/popup-trigger-function.d.ts +108 -0
- package/dist/types-ts4.5/popup/popup-trigger.d.ts +23 -0
- package/dist/types-ts4.5/popup/popup.d.ts +14 -0
- package/dist/types-ts4.5/popup/types.d.ts +289 -0
- package/dist/types-ts4.5/use-arrow-navigation/index.d.ts +2 -0
- package/dist/types-ts4.5/use-arrow-navigation/use-arrow-navigation.d.ts +136 -0
- package/dist/types-ts4.5/use-simple-light-dismiss/index.d.ts +45 -0
- package/focus/package.json +17 -0
- package/package.json +95 -0
- package/placement-map/package.json +17 -0
- package/popover/package.json +17 -0
- package/popup/package.json +17 -0
- package/popup-surface/package.json +17 -0
- package/use-anchor-position/package.json +17 -0
- package/use-arrow-navigation/package.json +17 -0
- package/use-simple-light-dismiss/package.json +17 -0
|
@@ -0,0 +1,336 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
Object.defineProperty(exports, "getPlacement", {
|
|
8
|
+
enumerable: true,
|
|
9
|
+
get: function get() {
|
|
10
|
+
return _resolvePlacement.getPlacement;
|
|
11
|
+
}
|
|
12
|
+
});
|
|
13
|
+
exports.placementToPositionArea = placementToPositionArea;
|
|
14
|
+
exports.placementToTryFallbacks = placementToTryFallbacks;
|
|
15
|
+
exports.useAnchorPosition = useAnchorPosition;
|
|
16
|
+
var _react = require("react");
|
|
17
|
+
var _bindEventListener = require("bind-event-listener");
|
|
18
|
+
var _rafSchd = _interopRequireDefault(require("raf-schd"));
|
|
19
|
+
var _once = _interopRequireDefault(require("@atlaskit/ds-lib/once"));
|
|
20
|
+
var _anchorPositioningFallback = require("./anchor-positioning-fallback");
|
|
21
|
+
var _combine = require("./combine");
|
|
22
|
+
var _resolvePlacement = require("./resolve-placement");
|
|
23
|
+
var _setStyle = require("./set-style");
|
|
24
|
+
/**
|
|
25
|
+
* Resolves placement options to CSS `position-area` syntax.
|
|
26
|
+
*
|
|
27
|
+
* The `align` field represents the *visual* alignment:
|
|
28
|
+
* - `align: 'start'` means "aligned to the trigger's start edge" (left in LTR for block axis)
|
|
29
|
+
* - `align: 'end'` means "aligned to the trigger's end edge"
|
|
30
|
+
* - `align: 'center'` means centered (single-axis position-area)
|
|
31
|
+
*
|
|
32
|
+
* CSS `position-area` uses `span-*` keywords which indicate the *expansion direction*.
|
|
33
|
+
* Visual start-alignment requires `span-{cross-axis}-end` (expand toward end = start-aligned).
|
|
34
|
+
* This function handles the inversion internally.
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* placementToPositionArea({ placement: { axis: 'block', edge: 'end', align: 'center' } }) // → 'block-end'
|
|
38
|
+
* placementToPositionArea({ placement: { axis: 'block', edge: 'end', align: 'start' } }) // → 'block-end span-inline-end'
|
|
39
|
+
* placementToPositionArea({ placement: { axis: 'block', edge: 'end', align: 'end' } }) // → 'block-end span-inline-start'
|
|
40
|
+
*/
|
|
41
|
+
function placementToPositionArea(_ref) {
|
|
42
|
+
var placement = _ref.placement;
|
|
43
|
+
var _getPlacement = (0, _resolvePlacement.getPlacement)({
|
|
44
|
+
placement: placement
|
|
45
|
+
}),
|
|
46
|
+
axis = _getPlacement.axis,
|
|
47
|
+
edge = _getPlacement.edge,
|
|
48
|
+
align = _getPlacement.align;
|
|
49
|
+
var edgeValue = "".concat(axis, "-").concat(edge);
|
|
50
|
+
if (align === 'center') {
|
|
51
|
+
return edgeValue;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Cross-axis name: block ↔ inline
|
|
55
|
+
var crossAxis = axis === 'block' ? 'inline' : 'block';
|
|
56
|
+
// Invert align → CSS span direction: visual 'start' → span toward 'end'
|
|
57
|
+
var spanDir = align === 'start' ? 'end' : 'start';
|
|
58
|
+
return "".concat(edgeValue, " span-").concat(crossAxis, "-").concat(spanDir);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Returns `position-try-fallbacks` value based on placement.
|
|
63
|
+
*
|
|
64
|
+
* For centered placements, includes cross-axis aligned position-area
|
|
65
|
+
* values so the browser can shift the popover along the cross-axis
|
|
66
|
+
* when the centered position would overflow the viewport edge.
|
|
67
|
+
*
|
|
68
|
+
* Fallback order for centered placements (e.g. `block-end`):
|
|
69
|
+
* 1. Same edge, start-aligned (shift for near-edge overflow)
|
|
70
|
+
* 2. Same edge, end-aligned (shift for far-edge overflow)
|
|
71
|
+
* 3. Flipped edge, centered
|
|
72
|
+
* 4. Flipped edge, start-aligned
|
|
73
|
+
* 5. Flipped edge, end-aligned
|
|
74
|
+
*
|
|
75
|
+
* For aligned placements (start/end), includes the same-edge centered
|
|
76
|
+
* position as fallbacks so the browser can try centering when the aligned
|
|
77
|
+
* position would overflow, before flipping to the opposite edge.
|
|
78
|
+
*/
|
|
79
|
+
function placementToTryFallbacks(_ref2) {
|
|
80
|
+
var placement = _ref2.placement;
|
|
81
|
+
var _getPlacement2 = (0, _resolvePlacement.getPlacement)({
|
|
82
|
+
placement: placement
|
|
83
|
+
}),
|
|
84
|
+
axis = _getPlacement2.axis,
|
|
85
|
+
edge = _getPlacement2.edge,
|
|
86
|
+
align = _getPlacement2.align;
|
|
87
|
+
var crossAxis = axis === 'block' ? 'inline' : 'block';
|
|
88
|
+
var flippedEdge = edge === 'start' ? 'end' : 'start';
|
|
89
|
+
if (align !== 'center') {
|
|
90
|
+
var _sameEdge = "".concat(axis, "-").concat(edge);
|
|
91
|
+
var _oppositeEdge = "".concat(axis, "-").concat(flippedEdge);
|
|
92
|
+
var _flipKeyword = axis === 'block' ? 'flip-block' : 'flip-inline';
|
|
93
|
+
// Legacy Popper fallbacks for e.g. bottom-start: [bottom, bottom-end, top-start, top, top-end, auto].
|
|
94
|
+
// Include same-edge centered so the browser can try center when start/end would overflow.
|
|
95
|
+
return ["".concat(_sameEdge, " span-").concat(crossAxis, "-").concat(align === 'start' ? 'end' : 'start'), _sameEdge, "".concat(_sameEdge, " span-").concat(crossAxis, "-").concat(align === 'start' ? 'start' : 'end'), _flipKeyword, "".concat(_oppositeEdge, " span-").concat(crossAxis, "-").concat(align === 'start' ? 'end' : 'start'), _oppositeEdge, "".concat(_oppositeEdge, " span-").concat(crossAxis, "-").concat(align === 'start' ? 'start' : 'end')].join(', ');
|
|
96
|
+
}
|
|
97
|
+
var sameEdge = "".concat(axis, "-").concat(edge);
|
|
98
|
+
var oppositeEdge = "".concat(axis, "-").concat(flippedEdge);
|
|
99
|
+
var flipKeyword = axis === 'block' ? 'flip-block' : 'flip-inline';
|
|
100
|
+
return ["".concat(sameEdge, " span-").concat(crossAxis, "-end"), "".concat(sameEdge, " span-").concat(crossAxis, "-start"), flipKeyword, "".concat(oppositeEdge, " span-").concat(crossAxis, "-end"), "".concat(oppositeEdge, " span-").concat(crossAxis, "-start")].join(', ');
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Detects whether the browser supports CSS Anchor Positioning.
|
|
105
|
+
* Uses `once()` for lazy evaluation — safe for SSR and avoids hydration mismatches.
|
|
106
|
+
*/
|
|
107
|
+
var supportsAnchorPositioning = (0, _once.default)(function () {
|
|
108
|
+
if (typeof window === 'undefined' || typeof CSS === 'undefined' || typeof CSS.supports !== 'function') {
|
|
109
|
+
return false;
|
|
110
|
+
}
|
|
111
|
+
return CSS.supports('anchor-name', '--a');
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Default gap between the popover and its trigger (in pixels).
|
|
116
|
+
* Maps to `space.100` (8px) in the design token scale.
|
|
117
|
+
*/
|
|
118
|
+
var DEFAULT_OFFSET = 8;
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Returns the CSS margin declaration that creates a gap between the
|
|
122
|
+
* popover and its trigger on the side facing the anchor.
|
|
123
|
+
*
|
|
124
|
+
* For example, a `block-end` placement (popover below) gets
|
|
125
|
+
* `margin-block-start: 8px` to push it away from the trigger's bottom edge.
|
|
126
|
+
*/
|
|
127
|
+
function edgeMargin(_ref3) {
|
|
128
|
+
var placement = _ref3.placement,
|
|
129
|
+
offset = _ref3.offset;
|
|
130
|
+
var axis = placement.axis,
|
|
131
|
+
edge = placement.edge;
|
|
132
|
+
var value = "".concat(offset, "px");
|
|
133
|
+
if (axis === 'block' && edge === 'end') {
|
|
134
|
+
return {
|
|
135
|
+
property: 'margin-block-start',
|
|
136
|
+
value: value
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
if (axis === 'block' && edge === 'start') {
|
|
140
|
+
return {
|
|
141
|
+
property: 'margin-block-end',
|
|
142
|
+
value: value
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
if (axis === 'inline' && edge === 'end') {
|
|
146
|
+
return {
|
|
147
|
+
property: 'margin-inline-start',
|
|
148
|
+
value: value
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
if (axis === 'inline' && edge === 'start') {
|
|
152
|
+
return {
|
|
153
|
+
property: 'margin-inline-end',
|
|
154
|
+
value: value
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
return {
|
|
158
|
+
property: 'margin-block-start',
|
|
159
|
+
value: value
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Hook that positions an element relative to an anchor element using
|
|
165
|
+
* CSS Anchor Positioning (with a JS fallback for older browsers).
|
|
166
|
+
*
|
|
167
|
+
* This hook is the positioning primitive — it has no knowledge of popovers,
|
|
168
|
+
* visibility, or animation. Compose it with `Popover` for anchor-positioned
|
|
169
|
+
* top-layer content.
|
|
170
|
+
*
|
|
171
|
+
* When CSS Anchor Positioning is supported, it sets CSS properties
|
|
172
|
+
* (`anchor-name`, `position-anchor`, `position-area`, `position-try-fallbacks`)
|
|
173
|
+
* directly on the elements via `el.style.setProperty()`.
|
|
174
|
+
*
|
|
175
|
+
* When not supported, it falls back to JavaScript-based positioning using
|
|
176
|
+
* `position: fixed` with measured coordinates, re-running on scroll (capture)
|
|
177
|
+
* and resize events.
|
|
178
|
+
*/
|
|
179
|
+
function useAnchorPosition(_ref4) {
|
|
180
|
+
var anchorRef = _ref4.anchorRef,
|
|
181
|
+
popoverRef = _ref4.popoverRef,
|
|
182
|
+
placement = _ref4.placement,
|
|
183
|
+
_ref4$offset = _ref4.offset,
|
|
184
|
+
offset = _ref4$offset === void 0 ? DEFAULT_OFFSET : _ref4$offset,
|
|
185
|
+
_ref4$forceFallbackPo = _ref4.forceFallbackPositioning,
|
|
186
|
+
forceFallbackPositioning = _ref4$forceFallbackPo === void 0 ? false : _ref4$forceFallbackPo,
|
|
187
|
+
arrow = _ref4.arrow;
|
|
188
|
+
var id = (0, _react.useId)();
|
|
189
|
+
var anchorName = "--anchor-".concat(id.replace(/:/g, ''));
|
|
190
|
+
(0, _react.useLayoutEffect)(function () {
|
|
191
|
+
var trigger = anchorRef.current;
|
|
192
|
+
var popover = popoverRef.current;
|
|
193
|
+
if (!trigger || !popover) {
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
var resolvedPlacement = (0, _resolvePlacement.getPlacement)({
|
|
197
|
+
placement: placement
|
|
198
|
+
});
|
|
199
|
+
var shouldForceFallback = Boolean(forceFallbackPositioning);
|
|
200
|
+
if (supportsAnchorPositioning() && !shouldForceFallback) {
|
|
201
|
+
var gap = edgeMargin({
|
|
202
|
+
placement: resolvedPlacement,
|
|
203
|
+
offset: offset
|
|
204
|
+
});
|
|
205
|
+
var popoverStyles = [{
|
|
206
|
+
property: 'position-anchor',
|
|
207
|
+
value: anchorName
|
|
208
|
+
}, {
|
|
209
|
+
property: 'position-area',
|
|
210
|
+
value: placementToPositionArea({
|
|
211
|
+
placement: resolvedPlacement
|
|
212
|
+
})
|
|
213
|
+
}, {
|
|
214
|
+
property: 'position-try-fallbacks',
|
|
215
|
+
value: arrow ? arrow.getTryFallbacks({
|
|
216
|
+
placement: resolvedPlacement
|
|
217
|
+
}) : placementToTryFallbacks({
|
|
218
|
+
placement: resolvedPlacement
|
|
219
|
+
})
|
|
220
|
+
},
|
|
221
|
+
// Reset browser default popover positioning that conflicts
|
|
222
|
+
// with anchor positioning (UA: `inset: 0; margin: auto;`)
|
|
223
|
+
{
|
|
224
|
+
property: 'margin',
|
|
225
|
+
value: '0'
|
|
226
|
+
}, {
|
|
227
|
+
property: 'inset',
|
|
228
|
+
value: 'auto'
|
|
229
|
+
},
|
|
230
|
+
// Gap between the popover and its trigger
|
|
231
|
+
{
|
|
232
|
+
property: gap.property,
|
|
233
|
+
value: gap.value
|
|
234
|
+
}];
|
|
235
|
+
if (arrow) {
|
|
236
|
+
// Set the arrow size variable used by the injected arrow CSS
|
|
237
|
+
// and the @position-try rules for margin values.
|
|
238
|
+
popoverStyles.push({
|
|
239
|
+
property: '--ds-arrow-size',
|
|
240
|
+
value: "".concat(offset, "px")
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
var _undoPositioning = (0, _combine.combine)((0, _setStyle.setStyle)({
|
|
244
|
+
el: trigger,
|
|
245
|
+
styles: [{
|
|
246
|
+
property: 'anchor-name',
|
|
247
|
+
value: anchorName
|
|
248
|
+
}]
|
|
249
|
+
}), (0, _setStyle.setStyle)({
|
|
250
|
+
el: popover,
|
|
251
|
+
styles: popoverStyles
|
|
252
|
+
}));
|
|
253
|
+
return _undoPositioning;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// ── JS fallback ──
|
|
257
|
+
// The popover is already in the browser's top layer via popover="auto",
|
|
258
|
+
// so it does not need position:fixed. We only reset the UA defaults
|
|
259
|
+
// (inset: 0; margin: auto) and set top/left based on measurements.
|
|
260
|
+
var cleanupBaseStyles = (0, _setStyle.setStyle)({
|
|
261
|
+
el: popover,
|
|
262
|
+
styles: [{
|
|
263
|
+
property: 'margin',
|
|
264
|
+
value: '0'
|
|
265
|
+
}, {
|
|
266
|
+
property: 'inset',
|
|
267
|
+
value: 'auto'
|
|
268
|
+
}]
|
|
269
|
+
});
|
|
270
|
+
function update() {
|
|
271
|
+
if (!trigger || !popover) {
|
|
272
|
+
return;
|
|
273
|
+
}
|
|
274
|
+
var triggerRect = trigger.getBoundingClientRect();
|
|
275
|
+
var viewport = {
|
|
276
|
+
width: window.innerWidth,
|
|
277
|
+
height: window.innerHeight
|
|
278
|
+
};
|
|
279
|
+
var _computeFallbackPosit = (0, _anchorPositioningFallback.computeFallbackPosition)({
|
|
280
|
+
triggerRect: triggerRect,
|
|
281
|
+
popoverEl: popover,
|
|
282
|
+
placement: resolvedPlacement,
|
|
283
|
+
viewport: viewport,
|
|
284
|
+
offset: offset
|
|
285
|
+
}),
|
|
286
|
+
top = _computeFallbackPosit.top,
|
|
287
|
+
left = _computeFallbackPosit.left;
|
|
288
|
+
popover.style.setProperty('top', "".concat(top, "px"));
|
|
289
|
+
popover.style.setProperty('left', "".concat(left, "px"));
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
// Throttle scroll/resize updates to one per animation frame
|
|
293
|
+
var scheduledUpdate = (0, _rafSchd.default)(update);
|
|
294
|
+
var pendingFrame = null;
|
|
295
|
+
var undoPositioning = (0, _combine.combine)(cleanupBaseStyles,
|
|
296
|
+
// Position when the popover transitions to visible.
|
|
297
|
+
// The popover starts hidden (`display: none` per the popover
|
|
298
|
+
// UA stylesheet), so `offsetWidth`/`offsetHeight` are 0 until
|
|
299
|
+
// `showPopover()` is called. We defer positioning to the next
|
|
300
|
+
// animation frame because some browsers (Firefox) fire the
|
|
301
|
+
// `toggle` event synchronously during `showPopover()`, before
|
|
302
|
+
// the element has been laid out — so dimensions are still 0.
|
|
303
|
+
// Waiting one frame guarantees layout has run and measurements
|
|
304
|
+
// are accurate.
|
|
305
|
+
(0, _bindEventListener.bind)(popover, {
|
|
306
|
+
type: 'toggle',
|
|
307
|
+
listener: function listener(event) {
|
|
308
|
+
var toggleEvent = event;
|
|
309
|
+
if (toggleEvent.newState === 'open') {
|
|
310
|
+
pendingFrame = requestAnimationFrame(update);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
}), (0, _bindEventListener.bind)(window, {
|
|
314
|
+
type: 'scroll',
|
|
315
|
+
listener: scheduledUpdate,
|
|
316
|
+
options: {
|
|
317
|
+
capture: true,
|
|
318
|
+
passive: true
|
|
319
|
+
}
|
|
320
|
+
}), (0, _bindEventListener.bind)(window, {
|
|
321
|
+
type: 'resize',
|
|
322
|
+
listener: scheduledUpdate,
|
|
323
|
+
options: {
|
|
324
|
+
passive: true
|
|
325
|
+
}
|
|
326
|
+
}), function () {
|
|
327
|
+
scheduledUpdate.cancel();
|
|
328
|
+
if (pendingFrame !== null) {
|
|
329
|
+
cancelAnimationFrame(pendingFrame);
|
|
330
|
+
}
|
|
331
|
+
popover.style.removeProperty('top');
|
|
332
|
+
popover.style.removeProperty('left');
|
|
333
|
+
});
|
|
334
|
+
return undoPositioning;
|
|
335
|
+
}, [anchorRef, popoverRef, placement, anchorName, offset, forceFallbackPositioning, arrow]);
|
|
336
|
+
}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports.useAnimatedVisibility = useAnimatedVisibility;
|
|
8
|
+
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
|
|
9
|
+
var _react = require("react");
|
|
10
|
+
var _bindEventListener = require("bind-event-listener");
|
|
11
|
+
var _reducedMotion = require("./reduced-motion");
|
|
12
|
+
var _usePresetStyles = require("./use-preset-styles");
|
|
13
|
+
/**
|
|
14
|
+
* Manages the children mount/unmount lifecycle around CSS exit transitions.
|
|
15
|
+
*
|
|
16
|
+
* Used by both `Popover` and `Dialog` to share the same animation lifecycle
|
|
17
|
+
* logic. Those components own their own show/hide mechanisms (showPopover /
|
|
18
|
+
* hidePopover vs showModal / close) and event handling — this hook only
|
|
19
|
+
* manages the relationship between `isOpen` and when children are rendered.
|
|
20
|
+
*
|
|
21
|
+
* ## Problem
|
|
22
|
+
*
|
|
23
|
+
* We want to delay the unmount of children until a CSS exit transition has
|
|
24
|
+
* finished playing. If we unmount children the moment `isOpen` becomes
|
|
25
|
+
* `false`, the exit animation is never visible — the content just disappears.
|
|
26
|
+
*
|
|
27
|
+
* ## How it works
|
|
28
|
+
*
|
|
29
|
+
* `showChildren` tracks whether the consumer's children should be in the DOM.
|
|
30
|
+
* It does not mirror `isOpen` exactly — it intentionally lags behind during
|
|
31
|
+
* exit animations:
|
|
32
|
+
*
|
|
33
|
+
* ```
|
|
34
|
+
* isOpen: true ──────────────── false
|
|
35
|
+
* showChildren: true ──────────────── true ─── (exit animation) ─── false
|
|
36
|
+
* ```
|
|
37
|
+
*
|
|
38
|
+
* Two close paths exist:
|
|
39
|
+
*
|
|
40
|
+
* 1. **Animated close** (`willAnimate === true`):
|
|
41
|
+
* `isOpen` goes `false` → `showChildren` stays `true` → the CSS exit
|
|
42
|
+
* transition plays → `transitionend` fires → `showChildren` → `false`
|
|
43
|
+
* → `onExitFinish` fires. A timeout fallback ensures we still unmount
|
|
44
|
+
* if `transitionend` never fires (e.g. browser quirks, zero-duration).
|
|
45
|
+
*
|
|
46
|
+
* 2. **Non-animated close** (`willAnimate === false`):
|
|
47
|
+
* `isOpen` goes `false` → `showChildren` → `false` synchronously during
|
|
48
|
+
* the same render → `onExitFinish` fires in a follow-up effect.
|
|
49
|
+
*/
|
|
50
|
+
function useAnimatedVisibility(_ref) {
|
|
51
|
+
var isOpen = _ref.isOpen,
|
|
52
|
+
animate = _ref.animate,
|
|
53
|
+
elementRef = _ref.elementRef,
|
|
54
|
+
onExitFinish = _ref.onExitFinish;
|
|
55
|
+
// Resolve the animation preset and inject its CSS (idempotent).
|
|
56
|
+
// Returns `null` when `animate` is falsy.
|
|
57
|
+
var preset = (0, _usePresetStyles.usePresetStyles)({
|
|
58
|
+
preset: animate
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
// Whether we should play CSS transitions. False when there is no preset
|
|
62
|
+
// or the user has enabled the "prefers reduced motion" OS setting.
|
|
63
|
+
var willAnimate = Boolean(animate) && !(0, _reducedMotion.prefersReducedMotion)();
|
|
64
|
+
|
|
65
|
+
// ── showChildren state ──
|
|
66
|
+
//
|
|
67
|
+
// This is the core of the hook. `showChildren` controls whether the
|
|
68
|
+
// consumer's children are in the DOM. The two `if` blocks below are
|
|
69
|
+
// intentionally written as synchronous state updates during render
|
|
70
|
+
// (React supports this pattern — setState during render is treated as
|
|
71
|
+
// a synchronous re-render before the browser paints).
|
|
72
|
+
//
|
|
73
|
+
// Mount path: isOpen went true but showChildren is still false → mount.
|
|
74
|
+
// Unmount path: isOpen went false, showChildren is still true, and we
|
|
75
|
+
// are NOT animating → unmount immediately (no transition
|
|
76
|
+
// to wait for). If we ARE animating, showChildren stays
|
|
77
|
+
// true here and the effect below will set it to false
|
|
78
|
+
// after `transitionend`.
|
|
79
|
+
var _useState = (0, _react.useState)(isOpen),
|
|
80
|
+
_useState2 = (0, _slicedToArray2.default)(_useState, 2),
|
|
81
|
+
showChildren = _useState2[0],
|
|
82
|
+
setShowChildren = _useState2[1];
|
|
83
|
+
if (isOpen && !showChildren) {
|
|
84
|
+
setShowChildren(true);
|
|
85
|
+
}
|
|
86
|
+
if (!isOpen && showChildren && !willAnimate) {
|
|
87
|
+
setShowChildren(false);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Keep a stable ref to the latest `onExitFinish` so the effect and
|
|
91
|
+
// timeout closures below always call the current callback without
|
|
92
|
+
// needing `onExitFinish` in dependency arrays (which would reset
|
|
93
|
+
// the timeout on every new closure).
|
|
94
|
+
var onExitFinishRef = (0, _react.useRef)(onExitFinish);
|
|
95
|
+
onExitFinishRef.current = onExitFinish;
|
|
96
|
+
|
|
97
|
+
// ── Animated exit effect ──
|
|
98
|
+
//
|
|
99
|
+
// Runs when all three conditions are true:
|
|
100
|
+
// • `isOpen` is false (consumer wants to close)
|
|
101
|
+
// • `showChildren` is true (children are still mounted for exit anim)
|
|
102
|
+
// • `willAnimate` is true (we have a preset and reduced motion is off)
|
|
103
|
+
//
|
|
104
|
+
// Listens for `transitionend` on the element to know when the CSS exit
|
|
105
|
+
// transition has finished, then unmounts children and fires onExitFinish.
|
|
106
|
+
//
|
|
107
|
+
// Fallback timeout: `transitionend` can fail to fire in edge cases
|
|
108
|
+
// (e.g. element removed from top layer by browser, zero-duration
|
|
109
|
+
// transition, interrupted animation). The timeout is set to the
|
|
110
|
+
// preset's exit duration + 50ms buffer to guarantee we always unmount.
|
|
111
|
+
(0, _react.useEffect)(function () {
|
|
112
|
+
var _preset$exitDurationM;
|
|
113
|
+
// Guard: only run during the "exiting" window
|
|
114
|
+
if (isOpen || !showChildren || !willAnimate) {
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
var el = elementRef.current;
|
|
118
|
+
if (!el) {
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
function finish() {
|
|
122
|
+
var _onExitFinishRef$curr;
|
|
123
|
+
clearTimeout(fallbackId);
|
|
124
|
+
setShowChildren(false);
|
|
125
|
+
(_onExitFinishRef$curr = onExitFinishRef.current) === null || _onExitFinishRef$curr === void 0 || _onExitFinishRef$curr.call(onExitFinishRef);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Fallback: unmount even if transitionend never fires
|
|
129
|
+
var fallbackId = setTimeout(finish, ((_preset$exitDurationM = preset === null || preset === void 0 ? void 0 : preset.exitDurationMs) !== null && _preset$exitDurationM !== void 0 ? _preset$exitDurationM : 0) + 50);
|
|
130
|
+
|
|
131
|
+
// Primary: listen for the CSS transition to complete
|
|
132
|
+
var unbind = (0, _bindEventListener.bind)(el, {
|
|
133
|
+
type: 'transitionend',
|
|
134
|
+
listener: finish,
|
|
135
|
+
options: {
|
|
136
|
+
once: true
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
// Cleanup on re-render or unmount: cancel pending timeout and listener
|
|
141
|
+
return function () {
|
|
142
|
+
clearTimeout(fallbackId);
|
|
143
|
+
unbind();
|
|
144
|
+
};
|
|
145
|
+
}, [isOpen, showChildren, willAnimate, preset === null || preset === void 0 ? void 0 : preset.exitDurationMs, elementRef]);
|
|
146
|
+
|
|
147
|
+
// ── Non-animated exit callback ──
|
|
148
|
+
//
|
|
149
|
+
// When there is no animation, children unmount synchronously (handled
|
|
150
|
+
// by the `if` block above). But `onExitFinish` still needs to fire —
|
|
151
|
+
// we do that in a follow-up effect so the consumer can react to it.
|
|
152
|
+
//
|
|
153
|
+
// Uses a previous-value ref (`wasOpenRef`) to detect the exact
|
|
154
|
+
// true→false transition of `isOpen`, avoiding false positives on
|
|
155
|
+
// mount or re-renders where `isOpen` was already false.
|
|
156
|
+
var wasOpenRef = (0, _react.useRef)(isOpen);
|
|
157
|
+
(0, _react.useEffect)(function () {
|
|
158
|
+
var wasOpen = wasOpenRef.current;
|
|
159
|
+
wasOpenRef.current = isOpen;
|
|
160
|
+
if (wasOpen && !isOpen && !willAnimate) {
|
|
161
|
+
var _onExitFinishRef$curr2;
|
|
162
|
+
(_onExitFinishRef$curr2 = onExitFinishRef.current) === null || _onExitFinishRef$curr2 === void 0 || _onExitFinishRef$curr2.call(onExitFinishRef);
|
|
163
|
+
}
|
|
164
|
+
}, [isOpen, willAnimate]);
|
|
165
|
+
return {
|
|
166
|
+
showChildren: showChildren,
|
|
167
|
+
preset: preset
|
|
168
|
+
};
|
|
169
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.useAnimationPreset = useAnimationPreset;
|
|
7
|
+
var _react = require("react");
|
|
8
|
+
var _ensurePresetStyles = require("./ensure-preset-styles");
|
|
9
|
+
/**
|
|
10
|
+
* Normalizes the `animate` prop to a preset (or null) and ensures its CSS
|
|
11
|
+
* is injected once into document.head. Used by PopupContent, Popover, and
|
|
12
|
+
* DialogContent so they don't duplicate this logic.
|
|
13
|
+
*/
|
|
14
|
+
function useAnimationPreset(animate) {
|
|
15
|
+
var preset = animate != null && animate !== false ? animate : null;
|
|
16
|
+
(0, _react.useInsertionEffect)(function () {
|
|
17
|
+
if (preset) {
|
|
18
|
+
(0, _ensurePresetStyles.ensurePresetStyles)({
|
|
19
|
+
preset: preset
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
}, [preset]);
|
|
23
|
+
return preset;
|
|
24
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.useFocusWrap = useFocusWrap;
|
|
7
|
+
var _react = require("react");
|
|
8
|
+
var _bindEventListener = require("bind-event-listener");
|
|
9
|
+
var _focus = require("../focus/focus");
|
|
10
|
+
/**
|
|
11
|
+
* Roles that require focus wrapping per WAI-ARIA APG.
|
|
12
|
+
*
|
|
13
|
+
* - `dialog`: https://www.w3.org/WAI/ARIA/apg/patterns/dialog-modal/
|
|
14
|
+
* - `alertdialog`: same keyboard pattern as dialog
|
|
15
|
+
*
|
|
16
|
+
* `menu` is intentionally excluded. Menus are composite widgets
|
|
17
|
+
* (https://www.w3.org/WAI/ARIA/apg/practices/keyboard-interface/#kbd_general_within)
|
|
18
|
+
* that manage their own internal keyboard navigation via arrow keys,
|
|
19
|
+
* not Tab. Tab/Shift+Tab should move focus OUT of a menu entirely.
|
|
20
|
+
*
|
|
21
|
+
* Menu keyboard behavior (arrow keys, Home/End, type-ahead, Enter/Space)
|
|
22
|
+
* is context-dependent — it varies by orientation, nesting depth, item
|
|
23
|
+
* type, and control pattern (menu button vs menubar). This makes it
|
|
24
|
+
* impossible to implement generically here. The consumer component
|
|
25
|
+
* (e.g. `dropdown-menu`) owns all menu keyboard navigation.
|
|
26
|
+
*
|
|
27
|
+
* See: notes/outputs/menu-keyboard-decision.md
|
|
28
|
+
*/
|
|
29
|
+
function roleRequiresFocusWrap(role) {
|
|
30
|
+
return role === 'dialog' || role === 'alertdialog';
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Wraps Tab/Shift+Tab focus within a popover element when its role
|
|
35
|
+
* semantically requires it (dialog, alertdialog).
|
|
36
|
+
*
|
|
37
|
+
* While the popover is open, Tab and Shift+Tab are intercepted
|
|
38
|
+
* (via `preventDefault`) and remapped to cycle through focusable
|
|
39
|
+
* elements within the container using wrapping navigation.
|
|
40
|
+
*
|
|
41
|
+
* Light dismiss (Escape, click outside) continues to work natively
|
|
42
|
+
* via `popover="auto"` — this hook only intercepts Tab.
|
|
43
|
+
*
|
|
44
|
+
* Always call this hook unconditionally. The listener is only
|
|
45
|
+
* attached when the role requires focus wrapping, and is cleaned
|
|
46
|
+
* up and re-evaluated when the role changes.
|
|
47
|
+
*/
|
|
48
|
+
function useFocusWrap(_ref) {
|
|
49
|
+
var elementRef = _ref.elementRef,
|
|
50
|
+
role = _ref.role;
|
|
51
|
+
(0, _react.useEffect)(function () {
|
|
52
|
+
var el = elementRef.current;
|
|
53
|
+
if (!el || !roleRequiresFocusWrap(role)) {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
var unbind = (0, _bindEventListener.bind)(el, {
|
|
57
|
+
type: 'keydown',
|
|
58
|
+
listener: function listener(event) {
|
|
59
|
+
if (event.key !== 'Tab') {
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
event.preventDefault();
|
|
63
|
+
var direction = event.shiftKey ? 'backwards' : 'forwards';
|
|
64
|
+
|
|
65
|
+
// Try to move to the next/previous focusable element relative
|
|
66
|
+
// to the currently focused element within the container.
|
|
67
|
+
var next = (0, _focus.getNextFocusable)({
|
|
68
|
+
container: el,
|
|
69
|
+
direction: direction
|
|
70
|
+
});
|
|
71
|
+
if (next) {
|
|
72
|
+
next.focus();
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Nothing is currently focused inside the container (or the
|
|
77
|
+
// focused element isn't in the focusable list). Fall back to
|
|
78
|
+
// the first or last focusable element depending on direction.
|
|
79
|
+
var fallback = direction === 'forwards' ? (0, _focus.getFirstFocusable)({
|
|
80
|
+
container: el
|
|
81
|
+
}) : (0, _focus.getLastFocusable)({
|
|
82
|
+
container: el
|
|
83
|
+
});
|
|
84
|
+
if (fallback) {
|
|
85
|
+
fallback.focus();
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
options: {
|
|
89
|
+
capture: true
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
return unbind;
|
|
93
|
+
}, [elementRef, role]);
|
|
94
|
+
}
|