@atlaskit/top-layer 0.9.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (127) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/README.md +5 -1
  3. package/dialog/create-close-event/package.json +17 -0
  4. package/dist/cjs/animations/presets.js +10 -5
  5. package/dist/cjs/arrow/index.js +131 -0
  6. package/dist/cjs/arrow/types.js +5 -0
  7. package/dist/cjs/dialog/dialog-content.js +11 -6
  8. package/dist/cjs/entry-points/dialog/create-close-event.js +12 -0
  9. package/dist/cjs/entry-points/placement-map.js +6 -5
  10. package/dist/cjs/entry-points/popover/create-close-event.js +12 -0
  11. package/dist/cjs/focus/focus.js +71 -19
  12. package/dist/cjs/index.js +3 -4
  13. package/dist/cjs/internal/resolve-css-length-to-pixels.js +61 -10
  14. package/dist/cjs/internal/role-types.js +40 -9
  15. package/dist/cjs/internal/set-style.js +23 -25
  16. package/dist/cjs/internal/use-anchor-position.js +107 -68
  17. package/dist/cjs/internal/use-focus-wrap.js +13 -2
  18. package/dist/cjs/internal/use-initial-focus.js +31 -10
  19. package/dist/cjs/placement-map/index.js +9 -111
  20. package/dist/cjs/placement-map/legacy-placements.js +113 -0
  21. package/dist/cjs/popover/popover.js +14 -12
  22. package/dist/cjs/popup/popup-content.js +19 -13
  23. package/dist/cjs/popup/popup-surface.js +6 -0
  24. package/dist/cjs/popup/popup-trigger-function.js +1 -1
  25. package/dist/cjs/popup/popup-trigger.js +17 -37
  26. package/dist/cjs/popup/popup.js +21 -10
  27. package/dist/cjs/use-arrow-navigation/use-arrow-navigation.js +26 -10
  28. package/dist/es2019/animations/presets.js +20 -5
  29. package/dist/es2019/arrow/index.js +269 -0
  30. package/dist/es2019/arrow/types.js +1 -0
  31. package/dist/es2019/dialog/dialog-content.js +11 -6
  32. package/dist/es2019/entry-points/create-close-event.js +7 -0
  33. package/dist/es2019/entry-points/dialog/create-close-event.js +1 -0
  34. package/dist/es2019/entry-points/placement-map.js +2 -1
  35. package/dist/es2019/entry-points/popover/create-close-event.js +1 -0
  36. package/dist/es2019/focus/focus.js +56 -7
  37. package/dist/es2019/index.js +3 -4
  38. package/dist/es2019/internal/resolve-css-length-to-pixels.js +60 -7
  39. package/dist/es2019/internal/role-types.js +40 -9
  40. package/dist/es2019/internal/set-style.js +19 -22
  41. package/dist/es2019/internal/use-anchor-position.js +95 -54
  42. package/dist/es2019/internal/use-focus-wrap.js +14 -3
  43. package/dist/es2019/internal/use-initial-focus.js +32 -11
  44. package/dist/es2019/placement-map/index.js +8 -109
  45. package/dist/es2019/placement-map/legacy-placements.js +107 -0
  46. package/dist/es2019/popover/popover.js +14 -11
  47. package/dist/es2019/popup/popup-content.js +20 -14
  48. package/dist/es2019/popup/popup-surface.js +6 -0
  49. package/dist/es2019/popup/popup-trigger-function.js +1 -1
  50. package/dist/es2019/popup/popup-trigger.js +17 -37
  51. package/dist/es2019/popup/popup.js +20 -9
  52. package/dist/es2019/use-arrow-navigation/use-arrow-navigation.js +26 -10
  53. package/dist/esm/animations/presets.js +9 -4
  54. package/dist/esm/arrow/index.js +124 -0
  55. package/dist/esm/arrow/types.js +1 -0
  56. package/dist/esm/dialog/dialog-content.js +11 -6
  57. package/dist/esm/entry-points/create-close-event.js +7 -0
  58. package/dist/esm/entry-points/dialog/create-close-event.js +1 -0
  59. package/dist/esm/entry-points/placement-map.js +2 -1
  60. package/dist/esm/entry-points/popover/create-close-event.js +1 -0
  61. package/dist/esm/focus/focus.js +70 -19
  62. package/dist/esm/index.js +3 -4
  63. package/dist/esm/internal/resolve-css-length-to-pixels.js +61 -10
  64. package/dist/esm/internal/role-types.js +39 -9
  65. package/dist/esm/internal/set-style.js +23 -25
  66. package/dist/esm/internal/use-anchor-position.js +108 -64
  67. package/dist/esm/internal/use-focus-wrap.js +14 -3
  68. package/dist/esm/internal/use-initial-focus.js +32 -11
  69. package/dist/esm/placement-map/index.js +8 -109
  70. package/dist/esm/placement-map/legacy-placements.js +107 -0
  71. package/dist/esm/popover/popover.js +14 -12
  72. package/dist/esm/popup/popup-content.js +20 -14
  73. package/dist/esm/popup/popup-surface.js +6 -0
  74. package/dist/esm/popup/popup-trigger-function.js +1 -1
  75. package/dist/esm/popup/popup-trigger.js +17 -37
  76. package/dist/esm/popup/popup.js +21 -10
  77. package/dist/esm/use-arrow-navigation/use-arrow-navigation.js +26 -10
  78. package/dist/types/arrow/index.d.ts +24 -0
  79. package/dist/types/arrow/types.d.ts +29 -0
  80. package/dist/types/dialog/dialog-content.d.ts +5 -1
  81. package/dist/types/dialog/types.d.ts +50 -24
  82. package/dist/types/entry-points/create-close-event.d.ts +7 -0
  83. package/dist/types/entry-points/dialog/create-close-event.d.ts +2 -0
  84. package/dist/types/entry-points/placement-map.d.ts +2 -1
  85. package/dist/types/entry-points/popover/create-close-event.d.ts +2 -0
  86. package/dist/types/focus/focus.d.ts +8 -0
  87. package/dist/types/internal/resolve-css-length-to-pixels.d.ts +4 -6
  88. package/dist/types/internal/role-types.d.ts +25 -4
  89. package/dist/types/internal/set-style.d.ts +2 -19
  90. package/dist/types/internal/use-anchor-position.d.ts +2 -3
  91. package/dist/types/internal/use-initial-focus.d.ts +5 -4
  92. package/dist/types/placement-map/index.d.ts +8 -21
  93. package/dist/types/placement-map/legacy-placements.d.ts +21 -0
  94. package/dist/types/popover/popover.d.ts +1 -1
  95. package/dist/types/popover/types.d.ts +17 -17
  96. package/dist/types/popup/popup-surface.d.ts +6 -0
  97. package/dist/types/popup/popup-trigger-function.d.ts +10 -6
  98. package/dist/types/popup/popup-trigger.d.ts +8 -17
  99. package/dist/types/popup/popup.d.ts +2 -2
  100. package/dist/types/popup/types.d.ts +68 -22
  101. package/dist/types/use-arrow-navigation/use-arrow-navigation.d.ts +19 -5
  102. package/dist/types-ts4.5/arrow/index.d.ts +24 -0
  103. package/dist/types-ts4.5/arrow/types.d.ts +29 -0
  104. package/dist/types-ts4.5/dialog/dialog-content.d.ts +5 -1
  105. package/dist/types-ts4.5/dialog/types.d.ts +50 -24
  106. package/dist/types-ts4.5/entry-points/create-close-event.d.ts +7 -0
  107. package/dist/types-ts4.5/entry-points/dialog/create-close-event.d.ts +2 -0
  108. package/dist/types-ts4.5/entry-points/placement-map.d.ts +2 -1
  109. package/dist/types-ts4.5/entry-points/popover/create-close-event.d.ts +2 -0
  110. package/dist/types-ts4.5/focus/focus.d.ts +8 -0
  111. package/dist/types-ts4.5/internal/resolve-css-length-to-pixels.d.ts +4 -6
  112. package/dist/types-ts4.5/internal/role-types.d.ts +25 -4
  113. package/dist/types-ts4.5/internal/set-style.d.ts +2 -19
  114. package/dist/types-ts4.5/internal/use-anchor-position.d.ts +2 -3
  115. package/dist/types-ts4.5/internal/use-initial-focus.d.ts +5 -4
  116. package/dist/types-ts4.5/placement-map/index.d.ts +8 -21
  117. package/dist/types-ts4.5/placement-map/legacy-placements.d.ts +39 -0
  118. package/dist/types-ts4.5/popover/popover.d.ts +1 -1
  119. package/dist/types-ts4.5/popover/types.d.ts +17 -17
  120. package/dist/types-ts4.5/popup/popup-surface.d.ts +6 -0
  121. package/dist/types-ts4.5/popup/popup-trigger-function.d.ts +10 -6
  122. package/dist/types-ts4.5/popup/popup-trigger.d.ts +8 -17
  123. package/dist/types-ts4.5/popup/popup.d.ts +2 -2
  124. package/dist/types-ts4.5/popup/types.d.ts +68 -22
  125. package/dist/types-ts4.5/use-arrow-navigation/use-arrow-navigation.d.ts +19 -5
  126. package/package.json +1 -1
  127. package/popover/create-close-event/package.json +17 -0
@@ -5,16 +5,11 @@ Object.defineProperty(exports, "__esModule", {
5
5
  value: true
6
6
  });
7
7
  exports.fromLegacyPlacement = fromLegacyPlacement;
8
- exports.placementMapping = void 0;
9
8
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
10
9
  var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
10
+ var _legacyPlacements = require("./legacy-placements");
11
11
  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; }
12
12
  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) { (0, _defineProperty2.default)(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; }
13
- /**
14
- * Legacy Popper.js placement values (used by `@atlaskit/popper`, `@atlaskit/popup`,
15
- * `@atlaskit/tooltip`, etc.).
16
- */
17
-
18
13
  /**
19
14
  * Maps legacy Popper.js placement values to the new object-based
20
15
  * `Placement` values used by `@atlaskit/top-layer/popover`.
@@ -25,9 +20,11 @@ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t =
25
20
  * | ------------------- | --------------------------------------------------- |
26
21
  * | `top` | `{ axis: 'block', edge: 'start', align: 'center' }` |
27
22
  * | `top-start` | `{ axis: 'block', edge: 'start', align: 'start' }` |
23
+ * | `top-center` | `{ axis: 'block', edge: 'start', align: 'center' }` |
28
24
  * | `top-end` | `{ axis: 'block', edge: 'start', align: 'end' }` |
29
25
  * | `bottom` | `{ axis: 'block', edge: 'end', align: 'center' }` |
30
26
  * | `bottom-start` | `{ axis: 'block', edge: 'end', align: 'start' }` |
27
+ * | `bottom-center` | `{ axis: 'block', edge: 'end', align: 'center' }` |
31
28
  * | `bottom-end` | `{ axis: 'block', edge: 'end', align: 'end' }` |
32
29
  * | `right` | `{ axis: 'inline', edge: 'end', align: 'center' }` |
33
30
  * | `right-start` | `{ axis: 'inline', edge: 'end', align: 'start' }` |
@@ -39,7 +36,10 @@ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t =
39
36
  * | `auto-start` | `{ axis: 'block', edge: 'end', align: 'start' }` |
40
37
  * | `auto-end` | `{ axis: 'block', edge: 'end', align: 'end' }` |
41
38
  *
42
- * The `position-try-fallbacks` CSS property handles flipping automatically.
39
+ * `auto*` is mapped to `block-end` (a reduction in expressiveness vs Popper's
40
+ * runtime auto-flip). CSS `position-try-fallbacks` provides flipping at the
41
+ * edge - but the initial placement is fixed. If migrating away from Popper's
42
+ * dynamic auto, prefer an explicit placement.
43
43
  *
44
44
  * @example
45
45
  * ```ts
@@ -51,107 +51,10 @@ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t =
51
51
  * // newPlacement === { axis: 'block', edge: 'end', align: 'start' }
52
52
  * ```
53
53
  */
54
- var placementMapping = exports.placementMapping = {
55
- top: {
56
- axis: 'block',
57
- edge: 'start',
58
- align: 'center'
59
- },
60
- 'top-start': {
61
- axis: 'block',
62
- edge: 'start',
63
- align: 'start'
64
- },
65
- 'top-center': {
66
- axis: 'block',
67
- edge: 'start',
68
- align: 'center'
69
- },
70
- 'top-end': {
71
- axis: 'block',
72
- edge: 'start',
73
- align: 'end'
74
- },
75
- bottom: {
76
- axis: 'block',
77
- edge: 'end',
78
- align: 'center'
79
- },
80
- 'bottom-start': {
81
- axis: 'block',
82
- edge: 'end',
83
- align: 'start'
84
- },
85
- 'bottom-center': {
86
- axis: 'block',
87
- edge: 'end',
88
- align: 'center'
89
- },
90
- 'bottom-end': {
91
- axis: 'block',
92
- edge: 'end',
93
- align: 'end'
94
- },
95
- right: {
96
- axis: 'inline',
97
- edge: 'end',
98
- align: 'center'
99
- },
100
- 'right-start': {
101
- axis: 'inline',
102
- edge: 'end',
103
- align: 'start'
104
- },
105
- 'right-end': {
106
- axis: 'inline',
107
- edge: 'end',
108
- align: 'end'
109
- },
110
- left: {
111
- axis: 'inline',
112
- edge: 'start',
113
- align: 'center'
114
- },
115
- 'left-start': {
116
- axis: 'inline',
117
- edge: 'start',
118
- align: 'start'
119
- },
120
- 'left-end': {
121
- axis: 'inline',
122
- edge: 'start',
123
- align: 'end'
124
- },
125
- auto: {
126
- axis: 'block',
127
- edge: 'end',
128
- align: 'center'
129
- },
130
- 'auto-start': {
131
- axis: 'block',
132
- edge: 'end',
133
- align: 'start'
134
- },
135
- 'auto-end': {
136
- axis: 'block',
137
- edge: 'end',
138
- align: 'end'
139
- }
140
- };
141
-
142
- /**
143
- * Convert a legacy Popper.js placement to the new `position-area`-based Placement.
144
- * Optional `offset` is the legacy Popper `[along, away]` tuple (also known as
145
- * `[skidding, distance]`); negative `along` becomes `direction: 'backwards'`.
146
- *
147
- * The tuple keeps the historical popper names so call sites that already pass
148
- * `[along, away]` migrate without thinking; the new internal field names
149
- * (`gap` / `crossAxisShift`) are produced inside this adapter.
150
- */
151
54
  function fromLegacyPlacement(_ref) {
152
55
  var legacy = _ref.legacy,
153
56
  offset = _ref.offset;
154
- var basePlacement = placementMapping[legacy];
57
+ var basePlacement = _legacyPlacements.placementMapping[legacy];
155
58
  if (!offset) {
156
59
  return basePlacement;
157
60
  }
@@ -168,9 +71,4 @@ function fromLegacyPlacement(_ref) {
168
71
  }
169
72
  }
170
73
  });
171
- }
172
-
173
- /**
174
- * The full mapping record, exposed for consumers that need to iterate or introspect.
175
- */
176
- // eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports
74
+ }
@@ -0,0 +1,113 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.placementMapping = exports.LEGACY_PLACEMENTS = void 0;
7
+ /**
8
+ * Legacy Popper.js placement values (used by `@atlaskit/popper`,
9
+ * `@atlaskit/popup`, `@atlaskit/tooltip`, etc.). Re-exported from
10
+ * `@atlaskit/top-layer/placement-map` for migration consumers that need
11
+ * to enumerate every placement (e.g. for a settings dropdown). New code
12
+ * should use the object-based `TPlacementOptions` directly.
13
+ */
14
+ // eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports
15
+ var LEGACY_PLACEMENTS = exports.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'];
16
+ /**
17
+ * The full mapping record. Internal - use `fromLegacyPlacement` from the
18
+ * public entry-point so the offset-tuple translation is applied consistently.
19
+ *
20
+ * Note: `auto`, `auto-start`, `auto-end` map to `block-end` placements. This
21
+ * is a reduction in expressiveness vs Popper.js (which picked the best
22
+ * placement at runtime). CSS `position-try-fallbacks` flips at the edge but
23
+ * the initial placement is fixed. Migration consumers who relied on Popper's
24
+ * dynamic auto-flip should pick an explicit placement instead.
25
+ */
26
+ // eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports
27
+ var placementMapping = exports.placementMapping = {
28
+ top: {
29
+ axis: 'block',
30
+ edge: 'start',
31
+ align: 'center'
32
+ },
33
+ 'top-start': {
34
+ axis: 'block',
35
+ edge: 'start',
36
+ align: 'start'
37
+ },
38
+ 'top-center': {
39
+ axis: 'block',
40
+ edge: 'start',
41
+ align: 'center'
42
+ },
43
+ 'top-end': {
44
+ axis: 'block',
45
+ edge: 'start',
46
+ align: 'end'
47
+ },
48
+ bottom: {
49
+ axis: 'block',
50
+ edge: 'end',
51
+ align: 'center'
52
+ },
53
+ 'bottom-start': {
54
+ axis: 'block',
55
+ edge: 'end',
56
+ align: 'start'
57
+ },
58
+ 'bottom-center': {
59
+ axis: 'block',
60
+ edge: 'end',
61
+ align: 'center'
62
+ },
63
+ 'bottom-end': {
64
+ axis: 'block',
65
+ edge: 'end',
66
+ align: 'end'
67
+ },
68
+ right: {
69
+ axis: 'inline',
70
+ edge: 'end',
71
+ align: 'center'
72
+ },
73
+ 'right-start': {
74
+ axis: 'inline',
75
+ edge: 'end',
76
+ align: 'start'
77
+ },
78
+ 'right-end': {
79
+ axis: 'inline',
80
+ edge: 'end',
81
+ align: 'end'
82
+ },
83
+ left: {
84
+ axis: 'inline',
85
+ edge: 'start',
86
+ align: 'center'
87
+ },
88
+ 'left-start': {
89
+ axis: 'inline',
90
+ edge: 'start',
91
+ align: 'start'
92
+ },
93
+ 'left-end': {
94
+ axis: 'inline',
95
+ edge: 'start',
96
+ align: 'end'
97
+ },
98
+ auto: {
99
+ axis: 'block',
100
+ edge: 'end',
101
+ align: 'center'
102
+ },
103
+ 'auto-start': {
104
+ axis: 'block',
105
+ edge: 'end',
106
+ align: 'start'
107
+ },
108
+ 'auto-end': {
109
+ axis: 'block',
110
+ edge: 'end',
111
+ align: 'end'
112
+ }
113
+ };
@@ -15,7 +15,6 @@ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/sli
15
15
  var _react = _interopRequireWildcard(require("react"));
16
16
  var _bindEventListener = require("bind-event-listener");
17
17
  var _mergeRefs = _interopRequireDefault(require("@atlaskit/ds-lib/merge-refs"));
18
- var _noop = _interopRequireDefault(require("@atlaskit/ds-lib/noop"));
19
18
  var _once = _interopRequireDefault(require("@atlaskit/ds-lib/once"));
20
19
  var _openLayerObserver = require("@atlaskit/layering/experimental/open-layer-observer");
21
20
  var _useAnimatedVisibility = require("../internal/use-animated-visibility");
@@ -67,15 +66,14 @@ var POPUP_ROLES = new Set(['menu', 'listbox', 'dialog', 'alertdialog', 'tree', '
67
66
  *
68
67
  * For `mode="auto"`, the browser can dismiss the popover via light dismiss
69
68
  * (Escape, click outside). When that happens, `onClose` is called and the
70
- * consumer must set `isOpen` to `false`. The DOM owns the dismiss — React
69
+ * consumer must set `isOpen` to `false`. The DOM owns the dismiss; React
71
70
  * must follow.
72
71
  */
73
72
  var Popover = exports.Popover = /*#__PURE__*/(0, _react.forwardRef)(function Popover(_ref, ref) {
74
73
  var children = _ref.children,
75
74
  _ref$mode = _ref.mode,
76
75
  modeProp = _ref$mode === void 0 ? 'auto' : _ref$mode,
77
- _ref$onClose = _ref.onClose,
78
- onClose = _ref$onClose === void 0 ? _noop.default : _ref$onClose,
76
+ onClose = _ref.onClose,
79
77
  onOpenChange = _ref.onOpenChange,
80
78
  onExitFinish = _ref.onExitFinish,
81
79
  animate = _ref.animate,
@@ -90,7 +88,7 @@ var Popover = exports.Popover = /*#__PURE__*/(0, _react.forwardRef)(function Pop
90
88
  var autoId = (0, _react.useId)();
91
89
  var ownRef = (0, _react.useRef)(null);
92
90
  var combinedRef = (0, _mergeRefs.default)([ownRef, ref].filter(Boolean));
93
- // Regex is intentional — `replaceAll` is not available in our supported
91
+ // Regex is intentional: `replaceAll` is not available in our supported
94
92
  // browser matrix. In React 18, `useId()` returns IDs containing colons
95
93
  // (e.g. `:r1:`) which are invalid in CSS selectors and `popover` target
96
94
  // attributes. React 19.2.0 replaced colons with underscores, making this
@@ -108,7 +106,7 @@ var Popover = exports.Popover = /*#__PURE__*/(0, _react.forwardRef)(function Pop
108
106
  // ── Focus management ──
109
107
  // Initial focus: on open, moves focus into the popover (role-dependent).
110
108
  // Focus wrap: Tab/Shift+Tab cycle within the popover for dialog roles.
111
- // Focus restoration: handled natively by the Popover API — the browser
109
+ // Focus restoration: handled natively by the Popover API. The browser
112
110
  // tracks `previouslyFocusedElement` on show and restores it on hide.
113
111
  // No custom restoration hook is needed. See: notes/architecture/focus-restoration.md
114
112
  (0, _useFocusWrap.useFocusWrap)({
@@ -129,7 +127,7 @@ var Popover = exports.Popover = /*#__PURE__*/(0, _react.forwardRef)(function Pop
129
127
  // Passive/informational roles (tooltip, note, status, alert, log) and
130
128
  // no-role cases do not map to LayerType 'popup', so type is left undefined.
131
129
  var handleObserverClose = (0, _react.useCallback)(function () {
132
- onClose({
130
+ onClose === null || onClose === void 0 || onClose({
133
131
  reason: 'programmatic'
134
132
  });
135
133
  }, [onClose]);
@@ -151,8 +149,8 @@ var Popover = exports.Popover = /*#__PURE__*/(0, _react.forwardRef)(function Pop
151
149
  var mode = modeProp === 'hint' && !supportsPopoverHint() ? 'auto' : modeProp;
152
150
 
153
151
  // Distinguishes programmatic hidePopover() from browser-initiated dismiss.
154
- // When we call hidePopover() ourselves the beforetoggle event fires synchronously —
155
- // this ref prevents the toggle handler from calling onClose redundantly.
152
+ // When we call hidePopover() ourselves the beforetoggle event fires synchronously,
153
+ // so this ref prevents the toggle handler from calling onClose redundantly.
156
154
  var programmaticCloseRef = (0, _react.useRef)(false);
157
155
 
158
156
  // Escape key tracking: set in a capture-phase keydown listener (fires before
@@ -185,7 +183,11 @@ var Popover = exports.Popover = /*#__PURE__*/(0, _react.forwardRef)(function Pop
185
183
  // Browser dismiss (Escape or click-outside). Notify consumer.
186
184
  var reason = closeReasonRef.current;
187
185
  closeReasonRef.current = 'light-dismiss'; // reset for next dismiss
188
- onClose({
186
+ // `onClose` is required for `auto`/`hint` and forbidden for
187
+ // `manual`, but `TPopoverForwardedProps` is a flat type used
188
+ // internally by `PopupContent` - the optional check guards
189
+ // the manual-mode forwarded path where the field is undefined.
190
+ onClose === null || onClose === void 0 || onClose({
189
191
  reason: reason
190
192
  });
191
193
  }
@@ -220,7 +222,7 @@ var Popover = exports.Popover = /*#__PURE__*/(0, _react.forwardRef)(function Pop
220
222
 
221
223
  // Placement-dependent animation CSS vars (e.g. slide direction).
222
224
  // Separate from show/hide so that preset reference changes
223
- // (e.g. inline `animate={slideAndFade()}`) don't re-trigger visibility.
225
+ // (e.g. inline `animate={slideAndFade()}`) do not re-trigger visibility.
224
226
  (0, _react.useLayoutEffect)(function () {
225
227
  var el = ownRef.current;
226
228
  if (!el || !(preset !== null && preset !== void 0 && preset.getProperties) || !placement) {
@@ -242,7 +244,7 @@ var Popover = exports.Popover = /*#__PURE__*/(0, _react.forwardRef)(function Pop
242
244
  // in the target state (e.g. browser dismissed via light-dismiss before our
243
245
  // effect ran).
244
246
  // Defensive try/catch: these APIs throw InvalidStateError if the element
245
- // is disconnected or missing the popover attribute. While we don't expect
247
+ // is disconnected or missing the popover attribute. While we do not expect
246
248
  // that to happen in normal usage, it can occur in edge cases (e.g. React
247
249
  // concurrent mode, StrictMode double-effects, or unmount races).
248
250
  (0, _react.useLayoutEffect)(function () {
@@ -40,7 +40,8 @@ var PopupContent = exports.PopupContent = /*#__PURE__*/(0, _react.forwardRef)(fu
40
40
  placementProp = _ref.placement,
41
41
  onCloseProp = _ref.onClose,
42
42
  testIdProp = _ref.testId,
43
- forceFallbackPositioningProp = _ref.forceFallbackPositioning;
43
+ forceFallbackPositioningProp = _ref.forceFallbackPositioning,
44
+ idProp = _ref.id;
44
45
  // When inside <Popup>, context provides defaults. Props always win.
45
46
  var ctx = (0, _popupContext.useMaybePopupContext)();
46
47
  var triggerRef = triggerRefProp !== null && triggerRefProp !== void 0 ? triggerRefProp : ctx === null || ctx === void 0 ? void 0 : ctx.triggerRef;
@@ -83,7 +84,7 @@ var PopupContent = exports.PopupContent = /*#__PURE__*/(0, _react.forwardRef)(fu
83
84
  // does not restore focus when they close.
84
85
  //
85
86
  // To handle this, we listen for the close transition via `onOpenChange` and
86
- // restore focus to the trigger if the browser didn't. This runs after the
87
+ // restore focus to the trigger if the browser did not. This runs after the
87
88
  // browser's native restoration (which happens synchronously during hidePopover),
88
89
  // so it only takes effect when the browser skipped restoration (nested case).
89
90
  //
@@ -100,7 +101,7 @@ var PopupContent = exports.PopupContent = /*#__PURE__*/(0, _react.forwardRef)(fu
100
101
  // focus when they close.
101
102
  //
102
103
  // We detect this case by checking if focus is still inside the
103
- // closing popover element. If it is, the browser didn't restore,
104
+ // closing popover element. If it is, the browser did not restore,
104
105
  // and we need to move focus to the trigger ourselves.
105
106
  //
106
107
  // This does NOT fire for:
@@ -109,13 +110,15 @@ var PopupContent = exports.PopupContent = /*#__PURE__*/(0, _react.forwardRef)(fu
109
110
  if (!args.isOpen) {
110
111
  var trigger = triggerRef === null || triggerRef === void 0 ? void 0 : triggerRef.current;
111
112
  var focusStillInPopover = trigger && args.element.contains(document.activeElement);
112
- if (focusStillInPopover) {
113
- var shouldRestore = role === 'dialog' || role === 'alertdialog' || role === 'menu' || role === 'listbox';
114
- if (shouldRestore) {
115
- trigger.focus({
116
- preventScroll: true
117
- });
118
- }
113
+ // Single source of truth for "this role moves focus on open
114
+ // and therefore needs to be restored on close" - see
115
+ // `shouldFocusIntoPopover` in `internal/role-types.tsx`.
116
+ if (focusStillInPopover && (0, _roleTypes.shouldFocusIntoPopover)({
117
+ role: role
118
+ })) {
119
+ trigger.focus({
120
+ preventScroll: true
121
+ });
119
122
  }
120
123
  }
121
124
  }, [setIsOpen, consumerOnOpenChange, triggerRef, role]);
@@ -145,8 +148,8 @@ var PopupContent = exports.PopupContent = /*#__PURE__*/(0, _react.forwardRef)(fu
145
148
  var combinedRef = (0, _mergeRefs.default)([popoverRef, ref]);
146
149
 
147
150
  // TPopupContentProps already validates the discriminated union (role + label,
148
- // mode + onClose) at its API boundary. Popover accepts TPopoverInternalProps
149
- // internally so individual prop forwarding doesn't need to re-prove the union.
151
+ // mode + onClose) at its API boundary. Popover accepts TPopoverForwardedProps
152
+ // internally so individual prop forwarding does not need to re-prove the union.
150
153
  var popoverProps = {
151
154
  isOpen: isOpen,
152
155
  animate: animate,
@@ -159,7 +162,10 @@ var PopupContent = exports.PopupContent = /*#__PURE__*/(0, _react.forwardRef)(fu
159
162
  onOpenChange: handleOpenChange,
160
163
  testId: testId,
161
164
  children: children,
162
- id: ctx === null || ctx === void 0 ? void 0 : ctx.popoverId,
165
+ // Standalone consumers can pass an explicit `id` - used by their own
166
+ // trigger to wire `aria-controls`. Inside the `<Popup>` compound, the
167
+ // id flows from context (`ctx.popoverId`).
168
+ id: idProp !== null && idProp !== void 0 ? idProp : ctx === null || ctx === void 0 ? void 0 : ctx.popoverId,
163
169
  xcss: xcss
164
170
  };
165
171
  return /*#__PURE__*/_react.default.createElement(_popover.Popover, (0, _extends2.default)({
@@ -21,6 +21,12 @@ var styles = {
21
21
  * should use `Popup.Content` without wrapping in `PopupSurface`.
22
22
  *
23
23
  * Exposed as `Popup.Surface` on the compound component.
24
+ *
25
+ * **Presentational primitive - `children`-only by design.** This component
26
+ * intentionally exposes no `style`, `className`, `xcss`, `id`, or `ref`
27
+ * props. If you need any of those, render your own wrapper element inside
28
+ * `Popup.Content` instead - `PopupSurface` is the no-config "give me the
29
+ * default ADS overlay look" surface, nothing more.
24
30
  */
25
31
  function PopupSurface(_ref) {
26
32
  var children = _ref.children;
@@ -13,7 +13,7 @@ var _popupContext = require("./popup-context");
13
13
  /**
14
14
  * Render-prop alternative to `Popup.Trigger`.
15
15
  *
16
- * Use when you need full control over the trigger element — for example,
16
+ * Use when you need full control over the trigger element. For example,
17
17
  * to compose your own trigger with custom event handlers, wrap a third-party
18
18
  * component, or build a trigger from multiple elements.
19
19
  *
@@ -10,24 +10,15 @@ var _slot = require("../internal/slot");
10
10
  var _popupContext = require("./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
- * Wraps the trigger element. Attaches aria attributes and handles
14
- * click to toggle the popover. Sets the anchor-name on the trigger
15
- * for CSS Anchor Positioning.
13
+ * Wraps a single trigger element via `cloneElement`. Attaches aria
14
+ * attributes, the toggle handler, and the anchor-name. `aria-haspopup`
15
+ * is derived from `Popup.Content`'s role via context.
16
16
  *
17
- * `aria-haspopup` is derived from the content's role via context
18
- * (set by `Popup.Content`). This ensures the trigger always matches
19
- * the content's semantic role without the consumer specifying it
20
- * in two places.
21
- *
22
- * **Limitation:** Uses `cloneElement` internally (via `Slot`), which is
23
- * incompatible with Compiled's `css` prop on the direct child element.
24
- * The `@jsx jsx` pragma transforms the child before `cloneElement` can
25
- * inject `onClick` and `ref` onto the DOM node, preventing the popover
26
- * from opening.
27
- *
28
- * If you need Compiled `css` on the trigger, use `Popup.TriggerFunction`
29
- * instead - it hands you raw props via a render-prop and avoids
30
- * `cloneElement` entirely.
17
+ * Child constraints: must be a single ref-forwarding element. The child's
18
+ * `onClick` is composed (runs after); other event handlers are NOT.
19
+ * Children using Compiled's `css` prop swallow injected props - use
20
+ * `Popup.TriggerFunction` for these cases or any time you need handler
21
+ * composition.
31
22
  */
32
23
  function PopupTrigger(_ref) {
33
24
  var children = _ref.children;
@@ -39,35 +30,24 @@ function PopupTrigger(_ref) {
39
30
  ariaHasPopup = _usePopupContext.ariaHasPopup;
40
31
  var childOnClick = /*#__PURE__*/(0, _react.isValidElement)(children) ? children.props.onClick : undefined;
41
32
 
42
- // Use a ref to track the latest isOpen value so the click handler
43
- // does not need isOpen in its dependency array (which would recreate
44
- // the handler on every open/close, breaking cloneElement identity).
33
+ // Track latest isOpen via ref so the click handler keeps a stable
34
+ // identity (cloneElement relies on it).
45
35
  var isOpenRef = _react.default.useRef(isOpen);
46
36
  isOpenRef.current = isOpen;
47
37
  var handleClick = (0, _react.useCallback)(function (event) {
48
38
  var popoverEl = popoverRef.current;
49
39
  if (popoverEl) {
50
- // For popover="auto", clicking the trigger (which is outside
51
- // the popover) can cause the browser's built-in light-dismiss
52
- // to fire before our click handler runs. This means by the time
53
- // we get here, the DOM may have already closed the popover.
54
- //
55
- // We use React's `isOpen` state (via ref) rather than the DOM
56
- // state to determine intent:
57
- // - If React thinks it was open → the user wants to close.
58
- // The browser already did this via light-dismiss, so do nothing.
59
- // - If React thinks it was closed → the user wants to open.
60
- // Call showPopover().
40
+ // `popover="auto"` light-dismiss can close the popover BEFORE
41
+ // our click handler runs, so trust React's isOpen rather than
42
+ // DOM state. If React still thinks it is closed, open it; if
43
+ // it was open, the browser already closed it.
61
44
  if (!isOpenRef.current) {
62
- // Defensive: element may be disconnected or in an unexpected state.
63
45
  try {
64
46
  popoverEl.showPopover();
65
- } catch (_unused) {}
47
+ } catch (_unused) {
48
+ // Element may be disconnected; ignore.
49
+ }
66
50
  }
67
- // When isOpenRef.current is true, the browser's light-dismiss
68
- // already closed the popover and fired the toggle event, which
69
- // will update React state via handleToggle → setIsOpen(false).
70
- // No action needed here.
71
51
  }
72
52
  childOnClick === null || childOnClick === void 0 || childOnClick(event);
73
53
  }, [popoverRef, childOnClick]);
@@ -11,10 +11,10 @@ var _react = _interopRequireWildcard(require("react"));
11
11
  var _popupContext = require("./popup-context");
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
- * Popup compound — trigger + popover content.
14
+ * Popup compound: trigger + popover content.
15
15
  *
16
16
  * Use when a button opens anchored content (dropdown, menu, dialog).
17
- * The browser manages visibility via `togglePopover()` — the consumer
17
+ * The browser manages visibility via `togglePopover()`; the consumer
18
18
  * never manages `isOpen`. For custom trigger lifecycles (hover, timers,
19
19
  * external state), use `Popover` directly instead.
20
20
  *
@@ -22,18 +22,24 @@ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r
22
22
  * `Popup.Content` reads and forwards to the underlying `Popover`.
23
23
  */
24
24
  function PopupRoot(props) {
25
- var _props$mode;
26
- var placement = props.placement,
27
- children = props.children,
25
+ var _props$placement, _props$mode;
26
+ var children = props.children,
28
27
  testId = props.testId,
29
28
  forceFallbackPositioning = props.forceFallbackPositioning,
30
29
  onOpenChange = props.onOpenChange;
30
+ // `{}` resolves to "below the trigger, centered, with `space.100` gap"
31
+ // inside `useAnchorPosition`, which is the common case.
32
+ var placement = (_props$placement = props.placement) !== null && _props$placement !== void 0 ? _props$placement : {};
31
33
  var mode = (_props$mode = props.mode) !== null && _props$mode !== void 0 ? _props$mode : 'auto';
32
- var onClose = mode === 'manual' ? null : props.onClose;
34
+
35
+ // `TPopupProps` discriminates on `mode`: `manual` types `onClose` as
36
+ // `never`, so for manual consumers `props.onClose` is always `undefined`
37
+ // here. No runtime guard needed; the type contract carries the rule.
38
+ var onClose = props.onClose;
33
39
  var id = (0, _react.useId)();
34
- // Regex is intentional — `replaceAll` is not available in our supported
35
- // browser matrix. `useId()` returns IDs containing colons (e.g. `:r1:`)
36
- // which are invalid in CSS selectors and `popover` target attributes.
40
+ // `useId()` returns IDs containing colons (`:r1:`), which are invalid
41
+ // in CSS selectors and `popover` target attributes. `replaceAll` is
42
+ // not in our browser matrix.
37
43
  var sanitizedId = id.replace(/:/g, '');
38
44
  var popoverId = "popover-".concat(sanitizedId);
39
45
  var triggerRef = (0, _react.useRef)(null);
@@ -42,6 +48,8 @@ function PopupRoot(props) {
42
48
  _useState2 = (0, _slicedToArray2.default)(_useState, 2),
43
49
  isOpen = _useState2[0],
44
50
  setIsOpen = _useState2[1];
51
+ // Initial seed before `Popup.Content`'s layout effect resolves the
52
+ // real role on first paint.
45
53
  var _useState3 = (0, _react.useState)('dialog'),
46
54
  _useState4 = (0, _slicedToArray2.default)(_useState3, 2),
47
55
  ariaHasPopup = _useState4[0],
@@ -52,7 +60,10 @@ function PopupRoot(props) {
52
60
  var contextValue = {
53
61
  popoverId: popoverId,
54
62
  placement: placement,
55
- onClose: mode === 'manual' ? null : handleClose,
63
+ // `null` when the consumer did not supply a handler (manual mode, or
64
+ // auto/hint without a light-dismiss handler). `Popup.Content` reads
65
+ // this to decide whether to forward an `onClose` to `Popover`.
66
+ onClose: onClose ? handleClose : null,
56
67
  triggerRef: triggerRef,
57
68
  popoverRef: popoverRef,
58
69
  isOpen: isOpen,