@atlaskit/top-layer 0.7.1 → 0.9.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 (59) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/dist/cjs/animations/presets.js +4 -0
  3. package/dist/cjs/dialog/dialog-content.js +12 -0
  4. package/dist/cjs/focus/focus.js +2 -0
  5. package/dist/cjs/internal/ensure-preset-styles.js +1 -1
  6. package/dist/cjs/internal/use-anchor-position.js +6 -22
  7. package/dist/cjs/internal/use-preset-styles.js +1 -1
  8. package/dist/cjs/placement-map/index.js +2 -1
  9. package/dist/cjs/popover/popover.js +31 -0
  10. package/dist/cjs/popup/popup-content.js +1 -7
  11. package/dist/cjs/popup/popup-context.js +2 -0
  12. package/dist/cjs/use-arrow-navigation/use-arrow-navigation.js +1 -0
  13. package/dist/es2019/animations/presets.js +4 -0
  14. package/dist/es2019/dialog/dialog-content.js +12 -0
  15. package/dist/es2019/focus/focus.js +2 -0
  16. package/dist/es2019/internal/ensure-preset-styles.js +1 -1
  17. package/dist/es2019/internal/use-anchor-position.js +6 -20
  18. package/dist/es2019/internal/use-preset-styles.js +1 -1
  19. package/dist/es2019/placement-map/index.js +1 -0
  20. package/dist/es2019/popover/popover.js +31 -0
  21. package/dist/es2019/popup/popup-content.js +1 -7
  22. package/dist/es2019/popup/popup-context.js +2 -0
  23. package/dist/es2019/use-arrow-navigation/use-arrow-navigation.js +1 -0
  24. package/dist/esm/animations/presets.js +4 -0
  25. package/dist/esm/dialog/dialog-content.js +12 -0
  26. package/dist/esm/focus/focus.js +2 -0
  27. package/dist/esm/internal/ensure-preset-styles.js +1 -1
  28. package/dist/esm/internal/use-anchor-position.js +6 -22
  29. package/dist/esm/internal/use-preset-styles.js +1 -1
  30. package/dist/esm/placement-map/index.js +1 -0
  31. package/dist/esm/popover/popover.js +31 -0
  32. package/dist/esm/popup/popup-content.js +1 -7
  33. package/dist/esm/popup/popup-context.js +2 -0
  34. package/dist/esm/use-arrow-navigation/use-arrow-navigation.js +1 -0
  35. package/dist/types/internal/use-anchor-position.d.ts +1 -11
  36. package/dist/types/internal/use-preset-styles.d.ts +1 -1
  37. package/dist/types/popover/types.d.ts +4 -4
  38. package/dist/types/popup/types.d.ts +1 -28
  39. package/dist/types-ts4.5/internal/use-anchor-position.d.ts +1 -11
  40. package/dist/types-ts4.5/internal/use-preset-styles.d.ts +1 -1
  41. package/dist/types-ts4.5/popover/types.d.ts +4 -4
  42. package/dist/types-ts4.5/popup/types.d.ts +1 -28
  43. package/package.json +3 -1
  44. package/arrow/package.json +0 -17
  45. package/dist/cjs/arrow/index.js +0 -130
  46. package/dist/cjs/arrow/types.js +0 -5
  47. package/dist/cjs/entry-points/arrow.js +0 -12
  48. package/dist/es2019/arrow/index.js +0 -268
  49. package/dist/es2019/arrow/types.js +0 -1
  50. package/dist/es2019/entry-points/arrow.js +0 -1
  51. package/dist/esm/arrow/index.js +0 -123
  52. package/dist/esm/arrow/types.js +0 -1
  53. package/dist/esm/entry-points/arrow.js +0 -1
  54. package/dist/types/arrow/index.d.ts +0 -24
  55. package/dist/types/arrow/types.d.ts +0 -29
  56. package/dist/types/entry-points/arrow.d.ts +0 -2
  57. package/dist/types-ts4.5/arrow/index.d.ts +0 -24
  58. package/dist/types-ts4.5/arrow/types.d.ts +0 -29
  59. package/dist/types-ts4.5/entry-points/arrow.d.ts +0 -2
package/CHANGELOG.md CHANGED
@@ -1,5 +1,27 @@
1
1
  # @atlaskit/top-layer
2
2
 
3
+ ## 0.9.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [`8e9ab10567283`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/8e9ab10567283) -
8
+ When `platform-dst-top-layer` is enabled, the open layer observer registration now happens inside
9
+ the `Dialog` and `Popover` primitives directly, so `popup`, `modal-dialog`, and `tooltip` no
10
+ longer register with the open layer observer separately (avoiding double-counting).
11
+ - `Dialog` registers as `type: 'modal'`, with a no-op `onClose`, as there is no current use case
12
+ for programmatic close of modals via the open layer observer.
13
+ - `Popover` registers as `type: 'popup'` for interactive overlay roles (`dialog`, `alertdialog`,
14
+ `menu`, `listbox`, `tree`, `grid`) and omits `type` for other roles (e.g. `tooltip`).
15
+ - A new `programmatic` value has been added to `TPopoverCloseReason` to distinguish programmatic
16
+ closes, such as those from the open layer observer's `closeLayers()` calls.
17
+
18
+ ## 0.8.0
19
+
20
+ ### Minor Changes
21
+
22
+ - [`cce485619197c`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/cce485619197c) -
23
+ Remove arrow() implementation, as there are currently no consumers of it.
24
+
3
25
  ## 0.7.1
4
26
 
5
27
  ### Patch Changes
@@ -104,6 +104,7 @@ var FADE_CSS = "\n[data-ds-popover-fade] {\n opacity: 0;\n transition:\n op
104
104
  * <Popup.Content animate={fade()} />
105
105
  * ```
106
106
  */
107
+ // eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports
107
108
  function fade() {
108
109
  return {
109
110
  name: 'fade',
@@ -128,6 +129,7 @@ var SCALE_AND_FADE_CSS = "\n[data-ds-popover-scale-and-fade] {\n opacity: 0;\n
128
129
  * <Popup.Content animate={scaleAndFade()} />
129
130
  * ```
130
131
  */
132
+ // eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports
131
133
  function scaleAndFade() {
132
134
  return {
133
135
  name: 'scale-and-fade',
@@ -162,6 +164,7 @@ var DIALOG_SLIDE_UP_AND_FADE_CSS = "\n[data-ds-dialog-slide-up-and-fade] {\n op
162
164
  * </Dialog>
163
165
  * ```
164
166
  */
167
+ // eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports
165
168
  function dialogSlideUpAndFade(options) {
166
169
  var _options$distance2;
167
170
  var distance = (_options$distance2 = options === null || options === void 0 ? void 0 : options.distance) !== null && _options$distance2 !== void 0 ? _options$distance2 : 12;
@@ -190,6 +193,7 @@ var DIALOG_FADE_CSS = "\n[data-ds-dialog-fade] {\n opacity: 0;\n transition:\n
190
193
  * </Dialog>
191
194
  * ```
192
195
  */
196
+ // eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports
193
197
  function dialogFade() {
194
198
  return {
195
199
  name: 'dialog-fade',
@@ -14,6 +14,8 @@ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/de
14
14
  var _react = _interopRequireWildcard(require("react"));
15
15
  var _bindEventListener = require("bind-event-listener");
16
16
  var _mergeRefs = _interopRequireDefault(require("@atlaskit/ds-lib/merge-refs"));
17
+ var _noop = _interopRequireDefault(require("@atlaskit/ds-lib/noop"));
18
+ var _openLayerObserver = require("@atlaskit/layering/experimental/open-layer-observer");
17
19
  var _useAnimatedVisibility = require("../internal/use-animated-visibility");
18
20
  var _useFocusWrap = require("../internal/use-focus-wrap");
19
21
  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); }
@@ -71,6 +73,16 @@ var Dialog = exports.Dialog = /*#__PURE__*/(0, _react.forwardRef)(function Dialo
71
73
  role: 'dialog'
72
74
  });
73
75
 
76
+ // ── Open layer observer registration ──
77
+ // Notifies the open layer observer so app-coordination features
78
+ // (open-count subscriptions) work with top-layer dialogs.
79
+ (0, _openLayerObserver.useNotifyOpenLayerObserver)({
80
+ type: 'modal',
81
+ isOpen: isOpen,
82
+ // No-op: no current use case for programmatic close via OpenLayerObserver.
83
+ onClose: _noop.default
84
+ });
85
+
74
86
  // Show/hide the dialog in response to isOpen changes.
75
87
  (0, _react.useLayoutEffect)(function () {
76
88
  var dialog = ownRef.current;
@@ -69,6 +69,7 @@ function getFirstFocusable(_ref2) {
69
69
  /**
70
70
  * Returns the last focusable element within the container.
71
71
  */
72
+ // eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports
72
73
  function getLastFocusable(_ref3) {
73
74
  var container = _ref3.container,
74
75
  filter = _ref3.filter;
@@ -86,6 +87,7 @@ function getLastFocusable(_ref3) {
86
87
  * Returns `null` if there is no focused element within the container or if
87
88
  * the focused element is not in the list of focusable elements.
88
89
  */
90
+ // eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports
89
91
  function getNextFocusable(_ref4) {
90
92
  var _all$nextIndex;
91
93
  var container = _ref4.container,
@@ -12,7 +12,7 @@ exports.ensurePresetStyles = ensurePresetStyles;
12
12
  *
13
13
  * Note: injected `<style>` elements and the tracking Set are append-only —
14
14
  * they are never removed. This is intentional: the number of distinct
15
- * presets is bounded (handful of animation + arrow presets), so the
15
+ * presets is bounded (handful of animation presets), so the
16
16
  * memory footprint is negligible. Removing styles would risk breaking
17
17
  * other instances of the same preset that are still mounted.
18
18
  *
@@ -108,6 +108,7 @@ function placementToPositionArea(_ref) {
108
108
  * `position-try-fallbacks` do NOT update margins, so only the `flip-*`
109
109
  * tactic keywords correctly flip the gap margin along with the position.
110
110
  */
111
+ // eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports
111
112
  function placementToTryFallbacks(_ref2) {
112
113
  var placement = _ref2.placement;
113
114
  var _getPlacement2 = (0, _resolvePlacement.getPlacement)({
@@ -271,14 +272,14 @@ function isResolvedPlacementEqual(a, b) {
271
272
  * comparison is used internally so re-runs are skipped when the resolved
272
273
  * placement shape is unchanged.
273
274
  */
275
+ // eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports
274
276
  function useAnchorPosition(_ref5) {
275
277
  var anchorRef = _ref5.anchorRef,
276
278
  popoverRef = _ref5.popoverRef,
277
279
  _ref5$placement = _ref5.placement,
278
280
  placement = _ref5$placement === void 0 ? {} : _ref5$placement,
279
281
  _ref5$forceFallbackPo = _ref5.forceFallbackPositioning,
280
- forceFallbackPositioning = _ref5$forceFallbackPo === void 0 ? false : _ref5$forceFallbackPo,
281
- arrow = _ref5.arrow;
282
+ forceFallbackPositioning = _ref5$forceFallbackPo === void 0 ? false : _ref5$forceFallbackPo;
282
283
  var id = (0, _react.useId)();
283
284
  // Stabilize `placement` object so the same object literal
284
285
  // value returns an object with the same reference
@@ -315,9 +316,7 @@ function useAnchorPosition(_ref5) {
315
316
  })
316
317
  }, {
317
318
  property: 'position-try-fallbacks',
318
- value: arrow ? arrow.getTryFallbacks({
319
- placement: stablePlacement
320
- }) : placementToTryFallbacks({
319
+ value: placementToTryFallbacks({
321
320
  placement: stablePlacement
322
321
  })
323
322
  },
@@ -380,19 +379,6 @@ function useAnchorPosition(_ref5) {
380
379
  value: crossAxisShiftActive.value
381
380
  });
382
381
  }
383
- if (arrow) {
384
- // Set the arrow size variable used by the injected arrow CSS
385
- // and the @position-try rules for margin values.
386
- popoverStyles.push({
387
- property: '--ds-arrow-size',
388
- value: gapCssValue
389
- });
390
- // Mark the popover root as the arrow host. The ARROW_CSS targets
391
- // [data-ds-popover-arrow] to apply clip-path: inset(0) margin-box
392
- // and box-shadow: none. Must be on the popover root (not a child)
393
- // because that's where useAnchorPosition sets the margin gap.
394
- popover.setAttribute('data-ds-popover-arrow', '');
395
- }
396
382
 
397
383
  /**
398
384
  * **We are never cleaning up anchor names**
@@ -415,9 +401,7 @@ function useAnchorPosition(_ref5) {
415
401
  var _undoPositioning = (0, _combine.combine)((0, _setStyle.setStyle)({
416
402
  el: popover,
417
403
  styles: popoverStyles
418
- }), arrow ? function () {
419
- return popover.removeAttribute('data-ds-popover-arrow');
420
- } : function () {});
404
+ }));
421
405
  return _undoPositioning;
422
406
  }
423
407
 
@@ -566,5 +550,5 @@ function useAnchorPosition(_ref5) {
566
550
  popover.style.removeProperty('opacity');
567
551
  });
568
552
  return undoPositioning;
569
- }, [anchorRef, popoverRef, stablePlacement, forceFallbackPositioning, arrow, id]);
553
+ }, [anchorRef, popoverRef, stablePlacement, forceFallbackPositioning, id]);
570
554
  }
@@ -11,7 +11,7 @@ var _ensurePresetStyles = require("./ensure-preset-styles");
11
11
  * is injected once into `document.head`.
12
12
  *
13
13
  * Works with any preset that has `{ css, name }` — animation presets
14
- * (TAnimationPreset) and arrow presets (TArrowPreset) both satisfy this shape.
14
+ * (TAnimationPreset) satisfies this shape.
15
15
  */
16
16
  function usePresetStyles(_ref) {
17
17
  var preset = _ref.preset;
@@ -172,4 +172,5 @@ function fromLegacyPlacement(_ref) {
172
172
 
173
173
  /**
174
174
  * The full mapping record, exposed for consumers that need to iterate or introspect.
175
- */
175
+ */
176
+ // eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports
@@ -17,6 +17,7 @@ var _bindEventListener = require("bind-event-listener");
17
17
  var _mergeRefs = _interopRequireDefault(require("@atlaskit/ds-lib/merge-refs"));
18
18
  var _noop = _interopRequireDefault(require("@atlaskit/ds-lib/noop"));
19
19
  var _once = _interopRequireDefault(require("@atlaskit/ds-lib/once"));
20
+ var _openLayerObserver = require("@atlaskit/layering/experimental/open-layer-observer");
20
21
  var _useAnimatedVisibility = require("../internal/use-animated-visibility");
21
22
  var _useFocusWrap = require("../internal/use-focus-wrap");
22
23
  var _useInitialFocus = require("../internal/use-initial-focus");
@@ -40,6 +41,18 @@ var supportsPopoverHint = (0, _once.default)(function () {
40
41
  var styles = {
41
42
  root: "_19itglyw _ca0qidpf _u5f3idpf _n3tdidpf _19bvidpf _19pkidpf _2hwxidpf _otyridpf _18u0idpf _1r041wug _1reoewfl _18m9ewfl _bfhk1j28"
42
43
  };
44
+ /**
45
+ * ARIA roles on the Popover primitive that register with the open layer observer
46
+ * as LayerType 'popup'. These are interactive overlays that should be tracked
47
+ * and dismissed when closeLayers() is called (e.g. when the side nav resizes).
48
+ *
49
+ * Note on open layer observer types not included here:
50
+ * - 'modal' only ever comes from the Dialog primitive, not Popover.
51
+ * - Other layer types (e.g. 'tooltip') do not yet exist in LayerType because
52
+ * there is no current use case for distinguishing them in the observer.
53
+ */
54
+ var POPUP_ROLES = new Set(['menu', 'listbox', 'dialog', 'alertdialog', 'tree', 'grid']);
55
+
43
56
  /**
44
57
  * Unopinionated top-layer primitive.
45
58
  *
@@ -108,6 +121,24 @@ var Popover = exports.Popover = /*#__PURE__*/(0, _react.forwardRef)(function Pop
108
121
  role: role
109
122
  });
110
123
 
124
+ // ── Open layer observer registration ──
125
+ // Notifies the open layer observer so app-coordination features
126
+ // (closeLayers(), open-count subscriptions) work with top-layer popovers.
127
+ //
128
+ // Only set type: 'popup' for roles that are interactive overlay popups.
129
+ // Passive/informational roles (tooltip, note, status, alert, log) and
130
+ // no-role cases do not map to LayerType 'popup', so type is left undefined.
131
+ var handleObserverClose = (0, _react.useCallback)(function () {
132
+ onClose({
133
+ reason: 'programmatic'
134
+ });
135
+ }, [onClose]);
136
+ (0, _openLayerObserver.useNotifyOpenLayerObserver)({
137
+ type: role && POPUP_ROLES.has(role) ? 'popup' : undefined,
138
+ isOpen: isOpen,
139
+ onClose: handleObserverClose
140
+ });
141
+
111
142
  // Hint mode fallback: "hint" downgrades to "auto" if unsupported.
112
143
  //
113
144
  // Decision (2026-03-17 audit): We keep "auto" as the fallback (not "manual")
@@ -13,7 +13,6 @@ var _react = _interopRequireWildcard(require("react"));
13
13
  var _mergeRefs = _interopRequireDefault(require("@atlaskit/ds-lib/merge-refs"));
14
14
  var _roleTypes = require("../internal/role-types");
15
15
  var _useAnchorPosition = require("../internal/use-anchor-position");
16
- var _usePresetStyles = require("../internal/use-preset-styles");
17
16
  var _useWidthFromAnchor = require("../internal/use-width-from-anchor");
18
17
  var _popover = require("../popover/popover");
19
18
  var _popupContext = require("./popup-context");
@@ -32,7 +31,6 @@ var PopupContent = exports.PopupContent = /*#__PURE__*/(0, _react.forwardRef)(fu
32
31
  label = _ref.label,
33
32
  labelledBy = _ref.labelledBy,
34
33
  animate = _ref.animate,
35
- arrow = _ref.arrow,
36
34
  mode = _ref.mode,
37
35
  _ref$widthFromAnchor = _ref.widthFromAnchor,
38
36
  widthFromAnchor = _ref$widthFromAnchor === void 0 ? 'none' : _ref$widthFromAnchor,
@@ -129,17 +127,13 @@ var PopupContent = exports.PopupContent = /*#__PURE__*/(0, _react.forwardRef)(fu
129
127
  // reach the same DOM element for togglePopover). Otherwise use a local ref.
130
128
  var localRef = (0, _react.useRef)(null);
131
129
  var popoverRef = (_ctx$popoverRef = ctx === null || ctx === void 0 ? void 0 : ctx.popoverRef) !== null && _ctx$popoverRef !== void 0 ? _ctx$popoverRef : localRef;
132
- var arrowPreset = (0, _usePresetStyles.usePresetStyles)({
133
- preset: arrow
134
- });
135
130
  (0, _useAnchorPosition.useAnchorPosition)({
136
131
  anchorRef: triggerRef !== null && triggerRef !== void 0 ? triggerRef : {
137
132
  current: null
138
133
  },
139
134
  popoverRef: popoverRef,
140
135
  placement: placement,
141
- forceFallbackPositioning: forceFallbackPositioning,
142
- arrow: arrowPreset !== null && arrowPreset !== void 0 ? arrowPreset : undefined
136
+ forceFallbackPositioning: forceFallbackPositioning
143
137
  });
144
138
  (0, _useWidthFromAnchor.useWidthFromAnchor)({
145
139
  mode: widthFromAnchor,
@@ -23,6 +23,7 @@ var PopupProvider = exports.PopupProvider = PopupContext.Provider;
23
23
  *
24
24
  * Throws if called outside of a `<Popup>` compound component.
25
25
  */
26
+ // eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports
26
27
  function usePopupContext() {
27
28
  var ctx = (0, _react.useContext)(PopupContext);
28
29
  if (ctx === null) {
@@ -37,6 +38,7 @@ function usePopupContext() {
37
38
  * Used by `PopupContent` to support standalone usage (e.g. tooltip)
38
39
  * where values are passed as props instead of coming from a compound component.
39
40
  */
41
+ // eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports
40
42
  function useMaybePopupContext() {
41
43
  return (0, _react.useContext)(PopupContext);
42
44
  }
@@ -126,6 +126,7 @@ function isAtCurrentMenuLevel(element, container) {
126
126
  * });
127
127
  * ```
128
128
  */
129
+ // eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports
129
130
  function useArrowNavigation(_ref) {
130
131
  var containerRef = _ref.containerRef,
131
132
  onClose = _ref.onClose,
@@ -152,6 +152,7 @@ const FADE_CSS = `
152
152
  * <Popup.Content animate={fade()} />
153
153
  * ```
154
154
  */
155
+ // eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports
155
156
  export function fade() {
156
157
  return {
157
158
  name: 'fade',
@@ -206,6 +207,7 @@ const SCALE_AND_FADE_CSS = `
206
207
  * <Popup.Content animate={scaleAndFade()} />
207
208
  * ```
208
209
  */
210
+ // eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports
209
211
  export function scaleAndFade() {
210
212
  return {
211
213
  name: 'scale-and-fade',
@@ -291,6 +293,7 @@ const DIALOG_SLIDE_UP_AND_FADE_CSS = `
291
293
  * </Dialog>
292
294
  * ```
293
295
  */
296
+ // eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports
294
297
  export function dialogSlideUpAndFade(options) {
295
298
  var _options$distance2;
296
299
  const distance = (_options$distance2 = options === null || options === void 0 ? void 0 : options.distance) !== null && _options$distance2 !== void 0 ? _options$distance2 : 12;
@@ -366,6 +369,7 @@ const DIALOG_FADE_CSS = `
366
369
  * </Dialog>
367
370
  * ```
368
371
  */
372
+ // eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports
369
373
  export function dialogFade() {
370
374
  return {
371
375
  name: 'dialog-fade',
@@ -5,6 +5,8 @@ import { ax, ix } from "@compiled/react/runtime";
5
5
  import React, { forwardRef, useCallback, useEffect, useId, useLayoutEffect, useRef } from 'react';
6
6
  import { bind } from 'bind-event-listener';
7
7
  import mergeRefs from '@atlaskit/ds-lib/merge-refs';
8
+ import noop from '@atlaskit/ds-lib/noop';
9
+ import { useNotifyOpenLayerObserver } from '@atlaskit/layering/experimental/open-layer-observer';
8
10
  import { useAnimatedVisibility } from '../internal/use-animated-visibility';
9
11
  import { useFocusWrap } from '../internal/use-focus-wrap';
10
12
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-unsafe-values -- dialog reset requires values not in cssMap's type union
@@ -63,6 +65,16 @@ export const Dialog = /*#__PURE__*/forwardRef(function Dialog({
63
65
  role: 'dialog'
64
66
  });
65
67
 
68
+ // ── Open layer observer registration ──
69
+ // Notifies the open layer observer so app-coordination features
70
+ // (open-count subscriptions) work with top-layer dialogs.
71
+ useNotifyOpenLayerObserver({
72
+ type: 'modal',
73
+ isOpen,
74
+ // No-op: no current use case for programmatic close via OpenLayerObserver.
75
+ onClose: noop
76
+ });
77
+
66
78
  // Show/hide the dialog in response to isOpen changes.
67
79
  useLayoutEffect(() => {
68
80
  const dialog = ownRef.current;
@@ -59,6 +59,7 @@ export function getFirstFocusable({
59
59
  /**
60
60
  * Returns the last focusable element within the container.
61
61
  */
62
+ // eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports
62
63
  export function getLastFocusable({
63
64
  container,
64
65
  filter
@@ -77,6 +78,7 @@ export function getLastFocusable({
77
78
  * Returns `null` if there is no focused element within the container or if
78
79
  * the focused element is not in the list of focusable elements.
79
80
  */
81
+ // eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports
80
82
  export function getNextFocusable({
81
83
  container,
82
84
  direction,
@@ -6,7 +6,7 @@
6
6
  *
7
7
  * Note: injected `<style>` elements and the tracking Set are append-only —
8
8
  * they are never removed. This is intentional: the number of distinct
9
- * presets is bounded (handful of animation + arrow presets), so the
9
+ * presets is bounded (handful of animation presets), so the
10
10
  * memory footprint is negligible. Removing styles would risk breaking
11
11
  * other instances of the same preset that are still mounted.
12
12
  *
@@ -94,6 +94,7 @@ export function placementToPositionArea({
94
94
  * `position-try-fallbacks` do NOT update margins, so only the `flip-*`
95
95
  * tactic keywords correctly flip the gap margin along with the position.
96
96
  */
97
+ // eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports
97
98
  export function placementToTryFallbacks({
98
99
  placement
99
100
  }) {
@@ -265,12 +266,12 @@ function isResolvedPlacementEqual(a, b) {
265
266
  * comparison is used internally so re-runs are skipped when the resolved
266
267
  * placement shape is unchanged.
267
268
  */
269
+ // eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports
268
270
  export function useAnchorPosition({
269
271
  anchorRef,
270
272
  popoverRef,
271
273
  placement = {},
272
- forceFallbackPositioning = false,
273
- arrow
274
+ forceFallbackPositioning = false
274
275
  }) {
275
276
  const id = useId();
276
277
  // Stabilize `placement` object so the same object literal
@@ -308,9 +309,7 @@ export function useAnchorPosition({
308
309
  })
309
310
  }, {
310
311
  property: 'position-try-fallbacks',
311
- value: arrow ? arrow.getTryFallbacks({
312
- placement: stablePlacement
313
- }) : placementToTryFallbacks({
312
+ value: placementToTryFallbacks({
314
313
  placement: stablePlacement
315
314
  })
316
315
  },
@@ -373,19 +372,6 @@ export function useAnchorPosition({
373
372
  value: crossAxisShiftActive.value
374
373
  });
375
374
  }
376
- if (arrow) {
377
- // Set the arrow size variable used by the injected arrow CSS
378
- // and the @position-try rules for margin values.
379
- popoverStyles.push({
380
- property: '--ds-arrow-size',
381
- value: gapCssValue
382
- });
383
- // Mark the popover root as the arrow host. The ARROW_CSS targets
384
- // [data-ds-popover-arrow] to apply clip-path: inset(0) margin-box
385
- // and box-shadow: none. Must be on the popover root (not a child)
386
- // because that's where useAnchorPosition sets the margin gap.
387
- popover.setAttribute('data-ds-popover-arrow', '');
388
- }
389
375
 
390
376
  /**
391
377
  * **We are never cleaning up anchor names**
@@ -408,7 +394,7 @@ export function useAnchorPosition({
408
394
  const undoPositioning = combine(setStyle({
409
395
  el: popover,
410
396
  styles: popoverStyles
411
- }), arrow ? () => popover.removeAttribute('data-ds-popover-arrow') : () => {});
397
+ }));
412
398
  return undoPositioning;
413
399
  }
414
400
 
@@ -546,5 +532,5 @@ export function useAnchorPosition({
546
532
  popover.style.removeProperty('opacity');
547
533
  });
548
534
  return undoPositioning;
549
- }, [anchorRef, popoverRef, stablePlacement, forceFallbackPositioning, arrow, id]);
535
+ }, [anchorRef, popoverRef, stablePlacement, forceFallbackPositioning, id]);
550
536
  }
@@ -5,7 +5,7 @@ import { ensurePresetStyles } from './ensure-preset-styles';
5
5
  * is injected once into `document.head`.
6
6
  *
7
7
  * Works with any preset that has `{ css, name }` — animation presets
8
- * (TAnimationPreset) and arrow presets (TArrowPreset) both satisfy this shape.
8
+ * (TAnimationPreset) satisfies this shape.
9
9
  */
10
10
  export function usePresetStyles({
11
11
  preset
@@ -161,4 +161,5 @@ export function fromLegacyPlacement({
161
161
  /**
162
162
  * The full mapping record, exposed for consumers that need to iterate or introspect.
163
163
  */
164
+ // eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports
164
165
  export { placementMapping };
@@ -7,6 +7,7 @@ import { bind } from 'bind-event-listener';
7
7
  import mergeRefs from '@atlaskit/ds-lib/merge-refs';
8
8
  import noop from '@atlaskit/ds-lib/noop';
9
9
  import once from '@atlaskit/ds-lib/once';
10
+ import { useNotifyOpenLayerObserver } from '@atlaskit/layering/experimental/open-layer-observer';
10
11
  import { useAnimatedVisibility } from '../internal/use-animated-visibility';
11
12
  import { useFocusWrap } from '../internal/use-focus-wrap';
12
13
  import { useInitialFocus } from '../internal/use-initial-focus';
@@ -29,6 +30,18 @@ const supportsPopoverHint = once(() => {
29
30
  const styles = {
30
31
  root: "_19itglyw _ca0qidpf _u5f3idpf _n3tdidpf _19bvidpf _19pkidpf _2hwxidpf _otyridpf _18u0idpf _1r041wug _1reoewfl _18m9ewfl _bfhk1j28"
31
32
  };
33
+ /**
34
+ * ARIA roles on the Popover primitive that register with the open layer observer
35
+ * as LayerType 'popup'. These are interactive overlays that should be tracked
36
+ * and dismissed when closeLayers() is called (e.g. when the side nav resizes).
37
+ *
38
+ * Note on open layer observer types not included here:
39
+ * - 'modal' only ever comes from the Dialog primitive, not Popover.
40
+ * - Other layer types (e.g. 'tooltip') do not yet exist in LayerType because
41
+ * there is no current use case for distinguishing them in the observer.
42
+ */
43
+ const POPUP_ROLES = new Set(['menu', 'listbox', 'dialog', 'alertdialog', 'tree', 'grid']);
44
+
32
45
  /**
33
46
  * Unopinionated top-layer primitive.
34
47
  *
@@ -98,6 +111,24 @@ export const Popover = /*#__PURE__*/forwardRef(function Popover({
98
111
  role
99
112
  });
100
113
 
114
+ // ── Open layer observer registration ──
115
+ // Notifies the open layer observer so app-coordination features
116
+ // (closeLayers(), open-count subscriptions) work with top-layer popovers.
117
+ //
118
+ // Only set type: 'popup' for roles that are interactive overlay popups.
119
+ // Passive/informational roles (tooltip, note, status, alert, log) and
120
+ // no-role cases do not map to LayerType 'popup', so type is left undefined.
121
+ const handleObserverClose = useCallback(() => {
122
+ onClose({
123
+ reason: 'programmatic'
124
+ });
125
+ }, [onClose]);
126
+ useNotifyOpenLayerObserver({
127
+ type: role && POPUP_ROLES.has(role) ? 'popup' : undefined,
128
+ isOpen,
129
+ onClose: handleObserverClose
130
+ });
131
+
101
132
  // Hint mode fallback: "hint" downgrades to "auto" if unsupported.
102
133
  //
103
134
  // Decision (2026-03-17 audit): We keep "auto" as the fallback (not "manual")
@@ -5,7 +5,6 @@ import React, { forwardRef, useCallback, useLayoutEffect, useRef } from 'react';
5
5
  import mergeRefs from '@atlaskit/ds-lib/merge-refs';
6
6
  import { roleToAriaHasPopup } from '../internal/role-types';
7
7
  import { useAnchorPosition } from '../internal/use-anchor-position';
8
- import { usePresetStyles } from '../internal/use-preset-styles';
9
8
  import { useWidthFromAnchor } from '../internal/use-width-from-anchor';
10
9
  import { Popover } from '../popover/popover';
11
10
  import { useMaybePopupContext } from './popup-context';
@@ -22,7 +21,6 @@ export const PopupContent = /*#__PURE__*/forwardRef(function PopupContent({
22
21
  label,
23
22
  labelledBy,
24
23
  animate,
25
- arrow,
26
24
  mode,
27
25
  widthFromAnchor = 'none',
28
26
  xcss,
@@ -120,17 +118,13 @@ export const PopupContent = /*#__PURE__*/forwardRef(function PopupContent({
120
118
  // reach the same DOM element for togglePopover). Otherwise use a local ref.
121
119
  const localRef = useRef(null);
122
120
  const popoverRef = (_ctx$popoverRef = ctx === null || ctx === void 0 ? void 0 : ctx.popoverRef) !== null && _ctx$popoverRef !== void 0 ? _ctx$popoverRef : localRef;
123
- const arrowPreset = usePresetStyles({
124
- preset: arrow
125
- });
126
121
  useAnchorPosition({
127
122
  anchorRef: triggerRef !== null && triggerRef !== void 0 ? triggerRef : {
128
123
  current: null
129
124
  },
130
125
  popoverRef,
131
126
  placement,
132
- forceFallbackPositioning,
133
- arrow: arrowPreset !== null && arrowPreset !== void 0 ? arrowPreset : undefined
127
+ forceFallbackPositioning
134
128
  });
135
129
  useWidthFromAnchor({
136
130
  mode: widthFromAnchor,
@@ -15,6 +15,7 @@ export const PopupProvider = PopupContext.Provider;
15
15
  *
16
16
  * Throws if called outside of a `<Popup>` compound component.
17
17
  */
18
+ // eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports
18
19
  export function usePopupContext() {
19
20
  const ctx = useContext(PopupContext);
20
21
  if (ctx === null) {
@@ -29,6 +30,7 @@ export function usePopupContext() {
29
30
  * Used by `PopupContent` to support standalone usage (e.g. tooltip)
30
31
  * where values are passed as props instead of coming from a compound component.
31
32
  */
33
+ // eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports
32
34
  export function useMaybePopupContext() {
33
35
  return useContext(PopupContext);
34
36
  }
@@ -119,6 +119,7 @@ export function isAtCurrentMenuLevel(element, container) {
119
119
  * });
120
120
  * ```
121
121
  */
122
+ // eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports
122
123
  export function useArrowNavigation({
123
124
  containerRef,
124
125
  onClose,
@@ -95,6 +95,7 @@ var FADE_CSS = "\n[data-ds-popover-fade] {\n opacity: 0;\n transition:\n op
95
95
  * <Popup.Content animate={fade()} />
96
96
  * ```
97
97
  */
98
+ // eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports
98
99
  export function fade() {
99
100
  return {
100
101
  name: 'fade',
@@ -119,6 +120,7 @@ var SCALE_AND_FADE_CSS = "\n[data-ds-popover-scale-and-fade] {\n opacity: 0;\n
119
120
  * <Popup.Content animate={scaleAndFade()} />
120
121
  * ```
121
122
  */
123
+ // eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports
122
124
  export function scaleAndFade() {
123
125
  return {
124
126
  name: 'scale-and-fade',
@@ -153,6 +155,7 @@ var DIALOG_SLIDE_UP_AND_FADE_CSS = "\n[data-ds-dialog-slide-up-and-fade] {\n op
153
155
  * </Dialog>
154
156
  * ```
155
157
  */
158
+ // eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports
156
159
  export function dialogSlideUpAndFade(options) {
157
160
  var _options$distance2;
158
161
  var distance = (_options$distance2 = options === null || options === void 0 ? void 0 : options.distance) !== null && _options$distance2 !== void 0 ? _options$distance2 : 12;
@@ -181,6 +184,7 @@ var DIALOG_FADE_CSS = "\n[data-ds-dialog-fade] {\n opacity: 0;\n transition:\n
181
184
  * </Dialog>
182
185
  * ```
183
186
  */
187
+ // eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports
184
188
  export function dialogFade() {
185
189
  return {
186
190
  name: 'dialog-fade',