@atlaskit/top-layer 0.13.0 → 0.14.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 (141) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/README.md +61 -34
  3. package/dist/cjs/animations/presets.js +4 -4
  4. package/dist/cjs/entry-points/get-aria-for-trigger.js +12 -0
  5. package/dist/cjs/entry-points/popover-surface.js +12 -0
  6. package/dist/cjs/entry-points/use-popover-id.js +21 -0
  7. package/dist/cjs/internal/get-aria-for-trigger.js +88 -0
  8. package/dist/cjs/internal/role-types.js +64 -1
  9. package/dist/cjs/internal/slot.js +1 -1
  10. package/dist/cjs/internal/use-anchor-position.js +30 -14
  11. package/dist/cjs/popover/popover.js +79 -80
  12. package/dist/cjs/popover-surface/index.js +12 -0
  13. package/dist/cjs/{popup/popup-surface.js → popover-surface/popover-surface.js} +9 -12
  14. package/dist/cjs/testing/polyfill.js +9 -6
  15. package/dist/es2019/animations/presets.js +4 -4
  16. package/dist/es2019/entry-points/get-aria-for-trigger.js +1 -0
  17. package/dist/es2019/entry-points/popover-surface.js +1 -0
  18. package/dist/es2019/entry-points/use-popover-id.js +15 -0
  19. package/dist/es2019/internal/get-aria-for-trigger.js +84 -0
  20. package/dist/es2019/internal/role-types.js +59 -0
  21. package/dist/es2019/internal/slot.js +1 -1
  22. package/dist/es2019/internal/use-anchor-position.js +16 -12
  23. package/dist/es2019/popover/popover.js +79 -80
  24. package/dist/es2019/popover-surface/index.js +1 -0
  25. package/dist/es2019/popover-surface/popover-surface.js +27 -0
  26. package/dist/es2019/testing/polyfill.js +9 -6
  27. package/dist/esm/animations/presets.js +4 -4
  28. package/dist/esm/entry-points/get-aria-for-trigger.js +1 -0
  29. package/dist/esm/entry-points/popover-surface.js +1 -0
  30. package/dist/esm/entry-points/use-popover-id.js +15 -0
  31. package/dist/esm/internal/get-aria-for-trigger.js +83 -0
  32. package/dist/esm/internal/role-types.js +58 -0
  33. package/dist/esm/internal/slot.js +1 -1
  34. package/dist/esm/internal/use-anchor-position.js +30 -14
  35. package/dist/esm/popover/popover.js +79 -80
  36. package/dist/esm/popover-surface/index.js +1 -0
  37. package/dist/esm/popover-surface/popover-surface.js +26 -0
  38. package/dist/esm/testing/polyfill.js +9 -6
  39. package/dist/types/animations/presets.d.ts +4 -4
  40. package/dist/types/animations/types.d.ts +1 -1
  41. package/dist/types/dialog/types.d.ts +0 -8
  42. package/dist/types/entry-points/get-aria-for-trigger.d.ts +1 -0
  43. package/dist/types/entry-points/popover-surface.d.ts +2 -0
  44. package/dist/types/entry-points/popover.d.ts +1 -1
  45. package/dist/types/entry-points/use-popover-id.d.ts +11 -0
  46. package/dist/types/internal/get-aria-for-trigger.d.ts +86 -0
  47. package/dist/types/internal/role-types.d.ts +7 -0
  48. package/dist/types/internal/slot.d.ts +2 -2
  49. package/dist/types/popover/index.d.ts +1 -1
  50. package/dist/types/popover/popover.d.ts +6 -13
  51. package/dist/types/popover/types.d.ts +6 -5
  52. package/dist/types/popover-surface/index.d.ts +2 -0
  53. package/dist/types/popover-surface/popover-surface.d.ts +21 -0
  54. package/dist/types-ts4.5/animations/presets.d.ts +4 -4
  55. package/dist/types-ts4.5/animations/types.d.ts +1 -1
  56. package/dist/types-ts4.5/dialog/types.d.ts +0 -8
  57. package/dist/types-ts4.5/entry-points/get-aria-for-trigger.d.ts +1 -0
  58. package/dist/types-ts4.5/entry-points/popover-surface.d.ts +2 -0
  59. package/dist/types-ts4.5/entry-points/popover.d.ts +1 -1
  60. package/dist/types-ts4.5/entry-points/use-popover-id.d.ts +11 -0
  61. package/dist/types-ts4.5/internal/get-aria-for-trigger.d.ts +86 -0
  62. package/dist/types-ts4.5/internal/role-types.d.ts +7 -0
  63. package/dist/types-ts4.5/internal/slot.d.ts +2 -2
  64. package/dist/types-ts4.5/popover/index.d.ts +1 -1
  65. package/dist/types-ts4.5/popover/popover.d.ts +6 -13
  66. package/dist/types-ts4.5/popover/types.d.ts +6 -5
  67. package/dist/types-ts4.5/popover-surface/index.d.ts +2 -0
  68. package/dist/types-ts4.5/popover-surface/popover-surface.d.ts +21 -0
  69. package/get-aria-for-trigger/package.json +17 -0
  70. package/package.json +3 -3
  71. package/popover-surface/package.json +17 -0
  72. package/use-popover-id/package.json +17 -0
  73. package/dist/cjs/entry-points/popup-surface.js +0 -12
  74. package/dist/cjs/entry-points/popup.js +0 -12
  75. package/dist/cjs/popup/index.js +0 -37
  76. package/dist/cjs/popup/popup-content.js +0 -215
  77. package/dist/cjs/popup/popup-context.js +0 -25
  78. package/dist/cjs/popup/popup-provider.js +0 -15
  79. package/dist/cjs/popup/popup-trigger-function.js +0 -80
  80. package/dist/cjs/popup/popup-trigger.js +0 -66
  81. package/dist/cjs/popup/popup.js +0 -81
  82. package/dist/cjs/popup/types.js +0 -5
  83. package/dist/cjs/popup/use-maybe-popup-context.js +0 -17
  84. package/dist/cjs/popup/use-popup-context.js +0 -20
  85. package/dist/es2019/entry-points/popup-surface.js +0 -1
  86. package/dist/es2019/entry-points/popup.js +0 -1
  87. package/dist/es2019/popup/index.js +0 -33
  88. package/dist/es2019/popup/popup-content.js +0 -207
  89. package/dist/es2019/popup/popup-context.js +0 -20
  90. package/dist/es2019/popup/popup-provider.js +0 -10
  91. package/dist/es2019/popup/popup-surface.js +0 -30
  92. package/dist/es2019/popup/popup-trigger-function.js +0 -75
  93. package/dist/es2019/popup/popup-trigger.js +0 -61
  94. package/dist/es2019/popup/popup.js +0 -67
  95. package/dist/es2019/popup/types.js +0 -1
  96. package/dist/es2019/popup/use-maybe-popup-context.js +0 -12
  97. package/dist/es2019/popup/use-popup-context.js +0 -15
  98. package/dist/esm/entry-points/popup-surface.js +0 -1
  99. package/dist/esm/entry-points/popup.js +0 -1
  100. package/dist/esm/popup/index.js +0 -33
  101. package/dist/esm/popup/popup-content.js +0 -207
  102. package/dist/esm/popup/popup-context.js +0 -20
  103. package/dist/esm/popup/popup-provider.js +0 -10
  104. package/dist/esm/popup/popup-surface.js +0 -29
  105. package/dist/esm/popup/popup-trigger-function.js +0 -75
  106. package/dist/esm/popup/popup-trigger.js +0 -59
  107. package/dist/esm/popup/popup.js +0 -72
  108. package/dist/esm/popup/types.js +0 -1
  109. package/dist/esm/popup/use-maybe-popup-context.js +0 -12
  110. package/dist/esm/popup/use-popup-context.js +0 -15
  111. package/dist/types/entry-points/popup-surface.d.ts +0 -2
  112. package/dist/types/entry-points/popup.d.ts +0 -2
  113. package/dist/types/popup/index.d.ts +0 -34
  114. package/dist/types/popup/popup-content.d.ts +0 -14
  115. package/dist/types/popup/popup-context.d.ts +0 -96
  116. package/dist/types/popup/popup-provider.d.ts +0 -10
  117. package/dist/types/popup/popup-surface.d.ts +0 -22
  118. package/dist/types/popup/popup-trigger-function.d.ts +0 -112
  119. package/dist/types/popup/popup-trigger.d.ts +0 -14
  120. package/dist/types/popup/popup.d.ts +0 -14
  121. package/dist/types/popup/types.d.ts +0 -321
  122. package/dist/types/popup/use-maybe-popup-context.d.ts +0 -8
  123. package/dist/types/popup/use-popup-context.d.ts +0 -7
  124. package/dist/types-ts4.5/entry-points/popup-surface.d.ts +0 -2
  125. package/dist/types-ts4.5/entry-points/popup.d.ts +0 -2
  126. package/dist/types-ts4.5/popup/index.d.ts +0 -34
  127. package/dist/types-ts4.5/popup/popup-content.d.ts +0 -14
  128. package/dist/types-ts4.5/popup/popup-context.d.ts +0 -96
  129. package/dist/types-ts4.5/popup/popup-provider.d.ts +0 -10
  130. package/dist/types-ts4.5/popup/popup-surface.d.ts +0 -22
  131. package/dist/types-ts4.5/popup/popup-trigger-function.d.ts +0 -112
  132. package/dist/types-ts4.5/popup/popup-trigger.d.ts +0 -14
  133. package/dist/types-ts4.5/popup/popup.d.ts +0 -14
  134. package/dist/types-ts4.5/popup/types.d.ts +0 -321
  135. package/dist/types-ts4.5/popup/use-maybe-popup-context.d.ts +0 -8
  136. package/dist/types-ts4.5/popup/use-popup-context.d.ts +0 -7
  137. package/popup/package.json +0 -17
  138. package/popup-surface/package.json +0 -17
  139. /package/dist/cjs/{popup/popup-surface.compiled.css → popover-surface/popover-surface.compiled.css} +0 -0
  140. /package/dist/es2019/{popup/popup-surface.compiled.css → popover-surface/popover-surface.compiled.css} +0 -0
  141. /package/dist/esm/{popup/popup-surface.compiled.css → popover-surface/popover-surface.compiled.css} +0 -0
@@ -1,207 +0,0 @@
1
- /* popup-content.tsx generated by @compiled/babel-plugin v0.39.1 */
2
- import _extends from "@babel/runtime/helpers/extends";
3
- import { ax, ix } from "@compiled/react/runtime";
4
- import React, { forwardRef, useCallback, useLayoutEffect, useRef } from 'react';
5
- import mergeRefs from '@atlaskit/ds-lib/merge-refs';
6
- import { prefersReducedMotion } from '../internal/reduced-motion';
7
- import { roleToAriaHasPopup } from '../internal/role-to-aria-has-popup';
8
- import { shouldFocusIntoPopover } from '../internal/should-focus-into-popover';
9
- import { useAnchorPosition } from '../internal/use-anchor-position';
10
- import { useWidthFromAnchor } from '../internal/use-width-from-anchor';
11
- import { Popover } from '../popover/popover';
12
- import { useMaybePopupContext } from './use-maybe-popup-context';
13
-
14
- /**
15
- * Thin context wrapper that composes `Popover` + `useAnchorPosition`.
16
- *
17
- * Used inside the `<Popup>` compound - reads triggerRef, placement, isOpen,
18
- * and onClose from context. For standalone usage (tooltip, spotlight, flag),
19
- * use `Popover` + `useAnchorPosition` directly.
20
- */
21
- export var PopupContent = /*#__PURE__*/forwardRef(function PopupContent(_ref, ref) {
22
- var _ref2, _ctx$popoverRef;
23
- var children = _ref.children,
24
- role = _ref.role,
25
- label = _ref.label,
26
- labelledBy = _ref.labelledBy,
27
- animate = _ref.animate,
28
- mode = _ref.mode,
29
- _ref$widthFromAnchor = _ref.widthFromAnchor,
30
- widthFromAnchor = _ref$widthFromAnchor === void 0 ? 'none' : _ref$widthFromAnchor,
31
- xcss = _ref.xcss,
32
- isOpenProp = _ref.isOpen,
33
- triggerRefProp = _ref.triggerRef,
34
- placementProp = _ref.placement,
35
- onCloseProp = _ref.onClose,
36
- testIdProp = _ref.testId,
37
- forceFallbackPositioningProp = _ref.forceFallbackPositioning,
38
- idProp = _ref.id,
39
- onEnterFinish = _ref.onEnterFinish,
40
- onExitFinish = _ref.onExitFinish;
41
- // When inside <Popup>, context provides defaults. Props always win.
42
- var ctx = useMaybePopupContext();
43
- var triggerRef = triggerRefProp !== null && triggerRefProp !== void 0 ? triggerRefProp : ctx === null || ctx === void 0 ? void 0 : ctx.triggerRef;
44
- var placement = (_ref2 = placementProp !== null && placementProp !== void 0 ? placementProp : ctx === null || ctx === void 0 ? void 0 : ctx.placement) !== null && _ref2 !== void 0 ? _ref2 : {};
45
- var onClose = onCloseProp !== null && onCloseProp !== void 0 ? onCloseProp : ctx === null || ctx === void 0 ? void 0 : ctx.onClose;
46
- var testId = testIdProp !== null && testIdProp !== void 0 ? testIdProp : ctx === null || ctx === void 0 ? void 0 : ctx.testId;
47
- var forceFallbackPositioning = forceFallbackPositioningProp !== null && forceFallbackPositioningProp !== void 0 ? forceFallbackPositioningProp : ctx === null || ctx === void 0 ? void 0 : ctx.forceFallbackPositioning;
48
-
49
- // isOpen: prop wins, otherwise derive from context popupState.
50
- // 'animating-open' counts as open so <Popover> stays visible during entry animation.
51
- var isOpen = isOpenProp !== null && isOpenProp !== void 0 ? isOpenProp : ctx !== null ? ctx.popupState === 'open' || ctx.popupState === 'animating-open' : false;
52
- var setPopupState = ctx === null || ctx === void 0 ? void 0 : ctx.setPopupState;
53
- var consumerOnOpenChange = ctx === null || ctx === void 0 ? void 0 : ctx.onOpenChange;
54
-
55
- // ── TPopupState ──
56
- //
57
- // popupState is driven by handleOpenChange (below), which fires on every browser
58
- // toggle event (showPopover / hidePopover / light-dismiss).
59
- //
60
- // Exception — initial mount with isOpen=true (prop-controlled usage):
61
- // handleOpenChange only fires from the Popover's toggle event listener, which
62
- // is registered in a useEffect. On the first render, useEffect hasn't run yet,
63
- // so handleOpenChange never fires. We sync popupState here instead.
64
- //
65
- // Transitions when animations are active:
66
- // closed → animating-open → open (enter)
67
- // open → animating-closed → closed (exit, via onExitFinish)
68
- //
69
- // Without animation: closed ↔ open directly.
70
- var willAnimate = Boolean(animate) && !prefersReducedMotion();
71
- var hasMountedRef = useRef(false);
72
- useLayoutEffect(function () {
73
- if (hasMountedRef.current) {
74
- return;
75
- }
76
- hasMountedRef.current = true;
77
- if (isOpen) {
78
- setPopupState === null || setPopupState === void 0 || setPopupState(willAnimate ? 'animating-open' : 'open');
79
- }
80
- }, [isOpen, setPopupState, willAnimate]);
81
- var handleEnterFinish = useCallback(function () {
82
- setPopupState === null || setPopupState === void 0 || setPopupState('open');
83
- onEnterFinish === null || onEnterFinish === void 0 || onEnterFinish();
84
- }, [setPopupState, onEnterFinish]);
85
- var handleExitFinish = useCallback(function () {
86
- setPopupState === null || setPopupState === void 0 || setPopupState('closed');
87
- onExitFinish === null || onExitFinish === void 0 || onExitFinish();
88
- }, [setPopupState, onExitFinish]);
89
-
90
- // Note: onOpenChange composition is handled by handleOpenChange below,
91
- // which also adds nested-popover focus restoration.
92
-
93
- // Sync aria-haspopup on the trigger with the content's role
94
- var setAriaHasPopup = ctx === null || ctx === void 0 ? void 0 : ctx.setAriaHasPopup;
95
- useLayoutEffect(function () {
96
- setAriaHasPopup === null || setAriaHasPopup === void 0 || setAriaHasPopup(roleToAriaHasPopup({
97
- role: role
98
- }));
99
- }, [role, setAriaHasPopup]);
100
-
101
- // Focus restoration
102
- // The native Popover API handles focus restoration automatically for
103
- // popover="auto" and popover="hint":
104
- // - Escape → restores focus to the previously focused element (the trigger)
105
- // - Click-outside → does NOT restore (correct: the user clicked deliberately)
106
- // - hidePopover() → restores focus to the previously focused element
107
- //
108
- // However, for **nested** popover="auto" popovers, the browser only captures
109
- // `previouslyFocusedElement` for the outermost popover in the auto stack.
110
- // Inner popovers have `shouldRestoreFocus=false` per the spec, so the browser
111
- // does not restore focus when they close.
112
- //
113
- // To handle this, we listen for the close transition via `onOpenChange` and
114
- // restore focus to the trigger if the browser did not. This runs after the
115
- // browser's native restoration (which happens synchronously during hidePopover),
116
- // so it only takes effect when the browser skipped restoration (nested case).
117
- //
118
- // See: notes/architecture/focus-restoration.md
119
- var handleOpenChange = useCallback(function (args) {
120
- // Sync compound state
121
- if (args.isOpen) {
122
- setPopupState === null || setPopupState === void 0 || setPopupState(willAnimate ? 'animating-open' : 'open');
123
- } else {
124
- setPopupState === null || setPopupState === void 0 || setPopupState(willAnimate ? 'animating-closed' : 'closed');
125
- }
126
- consumerOnOpenChange === null || consumerOnOpenChange === void 0 || consumerOnOpenChange(args);
127
-
128
- // Nested popover focus restoration fallback
129
- // The browser only captures `previouslyFocusedElement` for the
130
- // outermost popover="auto" in the stack. Inner (nested) popovers
131
- // have shouldRestoreFocus=false, so the browser will not restore
132
- // focus when they close.
133
- //
134
- // We detect this case by checking if focus is still inside the
135
- // closing popover element. If it is, the browser did not restore,
136
- // and we need to move focus to the trigger ourselves.
137
- //
138
- // This does NOT fire for:
139
- // - Outermost popovers (browser already restored to trigger)
140
- // - Click-outside (focus is on the clicked element, not in popover)
141
- if (!args.isOpen) {
142
- var trigger = triggerRef === null || triggerRef === void 0 ? void 0 : triggerRef.current;
143
- var focusStillInPopover = trigger && args.element.contains(document.activeElement);
144
- // Single source of truth for "this role moves focus on open
145
- // and therefore needs to be restored on close" - see
146
- // `shouldFocusIntoPopover` in `internal/role-types.tsx`.
147
- if (focusStillInPopover && shouldFocusIntoPopover({
148
- role: role
149
- })) {
150
- trigger.focus({
151
- preventScroll: true
152
- });
153
- }
154
- }
155
- }, [consumerOnOpenChange, triggerRef, role, setPopupState, willAnimate]);
156
-
157
- // Anchor positioning
158
- // Compose useAnchorPosition with Popover. The hook positions the popover
159
- // relative to the trigger element via CSS Anchor Positioning (with JS fallback).
160
- // Use ctx.popoverRef when inside the compound (so the trigger can also
161
- // reach the same DOM element for togglePopover). Otherwise use a local ref.
162
- var localRef = useRef(null);
163
- var popoverRef = (_ctx$popoverRef = ctx === null || ctx === void 0 ? void 0 : ctx.popoverRef) !== null && _ctx$popoverRef !== void 0 ? _ctx$popoverRef : localRef;
164
- useAnchorPosition({
165
- anchorRef: triggerRef !== null && triggerRef !== void 0 ? triggerRef : {
166
- current: null
167
- },
168
- popoverRef: popoverRef,
169
- placement: placement,
170
- forceFallbackPositioning: forceFallbackPositioning
171
- });
172
- useWidthFromAnchor({
173
- mode: widthFromAnchor,
174
- popoverRef: popoverRef,
175
- anchorRef: triggerRef
176
- });
177
-
178
- // Merge: the popoverRef (shared with trigger + positioning) and the forwarded ref.
179
- var combinedRef = mergeRefs([popoverRef, ref]);
180
-
181
- // TPopupContentProps already validates the discriminated union (role + label,
182
- // mode + onClose) at its API boundary. Popover accepts TPopoverForwardedProps
183
- // internally so individual prop forwarding does not need to re-prove the union.
184
- var popoverProps = {
185
- isOpen: isOpen,
186
- animate: animate,
187
- placement: placement,
188
- mode: mode,
189
- role: role,
190
- label: label,
191
- labelledBy: labelledBy,
192
- onClose: onClose !== null && onClose !== void 0 ? onClose : undefined,
193
- onOpenChange: handleOpenChange,
194
- onEnterFinish: handleEnterFinish,
195
- onExitFinish: handleExitFinish,
196
- testId: testId,
197
- children: children,
198
- // Standalone consumers can pass an explicit `id` - used by their own
199
- // trigger to wire `aria-controls`. Inside the `<Popup>` compound, the
200
- // id flows from context (`ctx.popoverId`).
201
- id: idProp !== null && idProp !== void 0 ? idProp : ctx === null || ctx === void 0 ? void 0 : ctx.popoverId,
202
- xcss: xcss
203
- };
204
- return /*#__PURE__*/React.createElement(Popover, _extends({
205
- ref: combinedRef
206
- }, popoverProps));
207
- });
@@ -1,20 +0,0 @@
1
- import { createContext } from 'react';
2
-
3
- /**
4
- * Represents the lifecycle state of the popup.
5
- *
6
- * - `'closed'`: fully closed, not visible, no animation playing.
7
- * - `'animating-open'`: entry animation is playing (popup is opening but not yet settled).
8
- * - `'open'`: fully open, browser popover is showing, entry animation complete.
9
- * - `'animating-closed'`: exit animation is playing (popup is closing but still visible).
10
- *
11
- * Used to derive `aria-expanded` on the trigger:
12
- * - `aria-expanded` is `true` in `'animating-open'`, `'open'`, and `'animating-closed'`.
13
- *
14
- * This avoids screen readers announcing the popup as closed while it is
15
- * still visually present on screen during animations, and prevents consumers
16
- * that conditionally show/hide trigger UI based on `aria-expanded` from hiding
17
- * the trigger (and thus the popup anchor) mid-animation.
18
- */
19
-
20
- export var PopupContext = /*#__PURE__*/createContext(null);
@@ -1,10 +0,0 @@
1
- import { PopupContext } from './popup-context';
2
-
3
- /**
4
- * __Popup provider__
5
- *
6
- * Provides shared popup state (placement, popoverId, triggerRef,
7
- * isOpen, onClose) to compound child components such as `Popup.Trigger` and
8
- * `Popup.Content`.
9
- */
10
- export var PopupProvider = PopupContext.Provider;
@@ -1,29 +0,0 @@
1
- /* popup-surface.tsx generated by @compiled/babel-plugin v0.39.1 */
2
- import "./popup-surface.compiled.css";
3
- import { ax, ix } from "@compiled/react/runtime";
4
- import React from 'react';
5
- var styles = {
6
- root: "_2rkofajl _1reo1wug _18m91wug _bfhk1bhr _16qs130s"
7
- };
8
-
9
- /**
10
- * Optional styled wrapper for popup content.
11
- *
12
- * Adds default visual styling (background, border-radius, box-shadow)
13
- * using design tokens. Consumers who want fully custom styling
14
- * should use `Popup.Content` without wrapping in `PopupSurface`.
15
- *
16
- * Exposed as `Popup.Surface` on the compound component.
17
- *
18
- * **Presentational primitive - `children`-only by design.** This component
19
- * intentionally exposes no `style`, `className`, `xcss`, `id`, or `ref`
20
- * props. If you need any of those, render your own wrapper element inside
21
- * `Popup.Content` instead - `PopupSurface` is the no-config "give me the
22
- * default ADS overlay look" surface, nothing more.
23
- */
24
- export function PopupSurface(_ref) {
25
- var children = _ref.children;
26
- return /*#__PURE__*/React.createElement("div", {
27
- className: ax([styles.root])
28
- }, children);
29
- }
@@ -1,75 +0,0 @@
1
- import { useCallback, useMemo } from 'react';
2
- import { usePopupContext } from './use-popup-context';
3
-
4
- /**
5
- * Props passed to the `TriggerFunction` render-prop child.
6
- */
7
-
8
- /**
9
- * Render-prop alternative to `Popup.Trigger`.
10
- *
11
- * Use when you need full control over the trigger element. For example,
12
- * to compose your own trigger with custom event handlers, wrap a third-party
13
- * component, or build a trigger from multiple elements.
14
- *
15
- * `Popup.Trigger` uses `cloneElement` internally, which limits composability.
16
- * `Popup.TriggerFunction` hands you the raw props and lets you wire them up.
17
- *
18
- * **Note:** This sub-component uses a render-prop pattern and is not
19
- * compatible with React Server Components (RSC). It must be used inside
20
- * a client component boundary (`'use client'`).
21
- *
22
- * @example
23
- * ```tsx
24
- * <Popup placement={{ edge: 'end' }} onClose={handleClose}>
25
- * <Popup.TriggerFunction>
26
- * {({ ref, toggle, ariaAttributes }) => (
27
- * <button ref={ref} onClick={toggle} {...ariaAttributes}>
28
- * Open
29
- * </button>
30
- * )}
31
- * </Popup.TriggerFunction>
32
- * <Popup.Content role="dialog" label="My popup">
33
- * Content
34
- * </Popup.Content>
35
- * </Popup>
36
- * ```
37
- */
38
- export function PopupTriggerFunction(_ref) {
39
- var children = _ref.children;
40
- var _usePopupContext = usePopupContext(),
41
- triggerRef = _usePopupContext.triggerRef,
42
- popoverRef = _usePopupContext.popoverRef,
43
- popoverId = _usePopupContext.popoverId,
44
- popupState = _usePopupContext.popupState,
45
- ariaHasPopup = _usePopupContext.ariaHasPopup;
46
- var ref = useCallback(function (node) {
47
- triggerRef.current = node;
48
- }, [triggerRef]);
49
- var toggle = useCallback(function () {
50
- var popoverEl = popoverRef.current;
51
- if (popoverEl) {
52
- // Defensive: element may be disconnected or in an unexpected state.
53
- try {
54
- popoverEl.togglePopover();
55
- } catch (_unused) {}
56
- }
57
- }, [popoverRef]);
58
- var ariaAttributes = useMemo(function () {
59
- return {
60
- // aria-expanded stays true throughout entry and exit animations so screen readers
61
- // don't announce the popup as closed while it's still visible, and consumers
62
- // relying on aria-expanded to show/hide trigger UI don't lose the anchor mid-animation.
63
- 'aria-expanded': popupState === 'open' || popupState === 'animating-open' || popupState === 'animating-closed',
64
- 'aria-controls': popoverId,
65
- 'aria-haspopup': ariaHasPopup
66
- };
67
- }, [popupState, popoverId, ariaHasPopup]);
68
- return children({
69
- ref: ref,
70
- isOpen: popupState === 'open' || popupState === 'animating-open',
71
- popoverId: popoverId,
72
- toggle: toggle,
73
- ariaAttributes: ariaAttributes
74
- });
75
- }
@@ -1,59 +0,0 @@
1
- import React, { isValidElement, useCallback } from 'react';
2
- import { Slot } from '../internal/slot';
3
- import { usePopupContext } from './use-popup-context';
4
-
5
- /**
6
- * Wraps a single trigger element via `cloneElement`. Attaches aria
7
- * attributes, the toggle handler, and the anchor-name. `aria-haspopup`
8
- * is derived from `Popup.Content`'s role via context.
9
- *
10
- * Child constraints: must be a single ref-forwarding element. The child's
11
- * `onClick` is composed (runs after); other event handlers are NOT.
12
- * Children using Compiled's `css` prop swallow injected props - use
13
- * `Popup.TriggerFunction` for these cases or any time you need handler
14
- * composition.
15
- */
16
- export function PopupTrigger(_ref) {
17
- var children = _ref.children;
18
- var _usePopupContext = usePopupContext(),
19
- triggerRef = _usePopupContext.triggerRef,
20
- popoverRef = _usePopupContext.popoverRef,
21
- popoverId = _usePopupContext.popoverId,
22
- popupState = _usePopupContext.popupState,
23
- ariaHasPopup = _usePopupContext.ariaHasPopup;
24
- var childOnClick = /*#__PURE__*/isValidElement(children) ? children.props.onClick : undefined;
25
-
26
- // Use a ref to track the latest isOpen value so the click handler
27
- // does not need isOpen in its dependency array (which would recreate
28
- // the handler on every open/close, breaking cloneElement identity).
29
- var isOpenRef = React.useRef(popupState === 'open' || popupState === 'animating-open');
30
- isOpenRef.current = popupState === 'open' || popupState === 'animating-open';
31
- var handleClick = useCallback(function (event) {
32
- var popoverEl = popoverRef.current;
33
- if (popoverEl) {
34
- // `popover="auto"` light-dismiss can close the popover BEFORE
35
- // our click handler runs, so trust React's isOpen rather than
36
- // DOM state. If React still thinks it is closed, open it; if
37
- // it was open, the browser already closed it.
38
- if (!isOpenRef.current) {
39
- try {
40
- popoverEl.showPopover();
41
- } catch (_unused) {
42
- // Element may be disconnected; ignore.
43
- }
44
- }
45
- }
46
- childOnClick === null || childOnClick === void 0 || childOnClick(event);
47
- }, [popoverRef, childOnClick]);
48
- return /*#__PURE__*/React.createElement(Slot, {
49
- ref: triggerRef,
50
- onClick: handleClick
51
- // aria-expanded stays true throughout entry and exit animations so screen readers
52
- // don't announce the popup as closed while it's still visible, and consumers
53
- // relying on aria-expanded to show/hide trigger UI don't lose the anchor mid-animation.
54
- ,
55
- "aria-expanded": popupState === 'open' || popupState === 'animating-open' || popupState === 'animating-closed',
56
- "aria-controls": popoverId,
57
- "aria-haspopup": ariaHasPopup
58
- }, children);
59
- }
@@ -1,72 +0,0 @@
1
- import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
2
- import React, { useCallback, useId, useRef, useState } from 'react';
3
- import { PopupProvider } from './popup-provider';
4
- /**
5
- * Popup compound: trigger + popover content.
6
- *
7
- * Use when a button opens anchored content (dropdown, menu, dialog).
8
- * The browser manages visibility via `togglePopover()`; the consumer
9
- * never manages `isOpen`. For custom trigger lifecycles (hover, timers,
10
- * external state), use `Popover` directly instead.
11
- *
12
- * Provides context (triggerRef, placement, isOpen, onClose, mode) that
13
- * `Popup.Content` reads and forwards to the underlying `Popover`.
14
- */
15
- export function PopupRoot(props) {
16
- var _props$placement, _props$mode;
17
- var children = props.children,
18
- testId = props.testId,
19
- forceFallbackPositioning = props.forceFallbackPositioning,
20
- onOpenChange = props.onOpenChange;
21
- // `{}` resolves to "below the trigger, centered, with `space.100` gap"
22
- // inside `useAnchorPosition`, which is the common case.
23
- var placement = (_props$placement = props.placement) !== null && _props$placement !== void 0 ? _props$placement : {};
24
- var mode = (_props$mode = props.mode) !== null && _props$mode !== void 0 ? _props$mode : 'auto';
25
-
26
- // `TPopupProps` discriminates on `mode`: `manual` types `onClose` as
27
- // `never`, so for manual consumers `props.onClose` is always `undefined`
28
- // here. No runtime guard needed; the type contract carries the rule.
29
- var onClose = props.onClose;
30
- var id = useId();
31
- // `useId()` returns IDs containing colons (`:r1:`), which are invalid
32
- // in CSS selectors and `popover` target attributes. `replaceAll` is
33
- // not in our browser matrix.
34
- var sanitizedId = id.replace(/:/g, '');
35
- var popoverId = "popover-".concat(sanitizedId);
36
- var triggerRef = useRef(null);
37
- var popoverRef = useRef(null);
38
- var _useState = useState('closed'),
39
- _useState2 = _slicedToArray(_useState, 2),
40
- popupState = _useState2[0],
41
- setPopupState = _useState2[1];
42
- // Initial seed before `Popup.Content`'s layout effect resolves the
43
- // real role on first paint.
44
- var _useState3 = useState('dialog'),
45
- _useState4 = _slicedToArray(_useState3, 2),
46
- ariaHasPopup = _useState4[0],
47
- setAriaHasPopup = _useState4[1];
48
- var handleClose = useCallback(function (args) {
49
- onClose === null || onClose === void 0 || onClose(args);
50
- }, [onClose]);
51
- var contextValue = {
52
- popoverId: popoverId,
53
- placement: placement,
54
- // `null` when the consumer did not supply a handler (manual mode, or
55
- // auto/hint without a light-dismiss handler). `Popup.Content` reads
56
- // this to decide whether to forward an `onClose` to `Popover`.
57
- onClose: onClose ? handleClose : null,
58
- triggerRef: triggerRef,
59
- popoverRef: popoverRef,
60
- popupState: popupState,
61
- setPopupState: setPopupState,
62
- onOpenChange: onOpenChange,
63
- mode: mode,
64
- ariaHasPopup: ariaHasPopup,
65
- setAriaHasPopup: setAriaHasPopup,
66
- testId: testId,
67
- forceFallbackPositioning: forceFallbackPositioning
68
- };
69
- return /*#__PURE__*/React.createElement(PopupProvider, {
70
- value: contextValue
71
- }, children);
72
- }
@@ -1 +0,0 @@
1
- export {};
@@ -1,12 +0,0 @@
1
- import { useContext } from 'react';
2
- import { PopupContext } from './popup-context';
3
-
4
- /**
5
- * Returns the popup context if available, or `null` when used outside `<Popup>`.
6
- *
7
- * Used by `PopupContent` to support standalone usage (e.g. tooltip)
8
- * where values are passed as props instead of coming from a compound component.
9
- */
10
- export function useMaybePopupContext() {
11
- return useContext(PopupContext);
12
- }
@@ -1,15 +0,0 @@
1
- import { useContext } from 'react';
2
- import { PopupContext } from './popup-context';
3
-
4
- /**
5
- * Returns the nearest `Popup` context value.
6
- *
7
- * Throws if called outside of a `<Popup>` compound component.
8
- */
9
- export function usePopupContext() {
10
- var ctx = useContext(PopupContext);
11
- if (ctx === null) {
12
- throw new Error('@atlaskit/top-layer: Popup compound components must be used within <Popup>.');
13
- }
14
- return ctx;
15
- }
@@ -1,2 +0,0 @@
1
- export { PopupSurface } from '../popup/popup-surface';
2
- export type { TPopupSurfaceProps } from '../popup/types';
@@ -1,2 +0,0 @@
1
- export { Popup } from '../popup';
2
- export type { TPlacementOptions, TPopupProps, TPopupContentProps, TPopupRole, TPopupTriggerProps, TTriggerFunctionRenderProps, } from '../popup';
@@ -1,34 +0,0 @@
1
- import { PopupRoot } from './popup';
2
- import { PopupContent } from './popup-content';
3
- import { PopupSurface } from './popup-surface';
4
- import { PopupTrigger } from './popup-trigger';
5
- import { PopupTriggerFunction } from './popup-trigger-function';
6
- /**
7
- * Compound component for rendering content in the browser's top layer
8
- * using the native Popover API (`popover="auto"`).
9
- * Placement is owned by this compound: root provides it via context, Content applies it
10
- * (CSS Anchor Positioning or JS fallback).
11
- *
12
- * For default overlay styling (background, shadow, border-radius), see `PopupSurface` in the package examples.
13
- *
14
- * @example
15
- * ```tsx
16
- * <Popup placement={{ edge: 'end' }} onClose={handleClose}>
17
- * <Popup.Trigger>
18
- * <button>Open</button>
19
- * </Popup.Trigger>
20
- * <Popup.Content role="dialog" label="My popup">
21
- * Content goes here
22
- * </Popup.Content>
23
- * </Popup>
24
- * ```
25
- */
26
- declare const Popup: typeof PopupRoot & {
27
- Trigger: typeof PopupTrigger;
28
- TriggerFunction: typeof PopupTriggerFunction;
29
- Content: typeof PopupContent;
30
- Surface: typeof PopupSurface;
31
- };
32
- export { Popup };
33
- export type { TPlacementOptions, TPopupProps, TPopupContentProps, TPopupRole, TPopupSurfaceProps, TPopupTriggerProps, } from './types';
34
- export type { TTriggerFunctionRenderProps } from './popup-trigger-function';
@@ -1,14 +0,0 @@
1
- /**
2
- * @jsxRuntime classic
3
- * @jsx jsx
4
- */
5
- import React from 'react';
6
- import { type TPopupContentProps } from './types';
7
- /**
8
- * Thin context wrapper that composes `Popover` + `useAnchorPosition`.
9
- *
10
- * Used inside the `<Popup>` compound - reads triggerRef, placement, isOpen,
11
- * and onClose from context. For standalone usage (tooltip, spotlight, flag),
12
- * use `Popover` + `useAnchorPosition` directly.
13
- */
14
- export declare const PopupContent: React.ForwardRefExoticComponent<TPopupContentProps & React.RefAttributes<HTMLDivElement>>;
@@ -1,96 +0,0 @@
1
- import React, { type MutableRefObject, type RefObject } from 'react';
2
- import { type TAriaHasPopupValue } from '../internal/role-types';
3
- import { type TPopoverCloseReason } from '../popover/types';
4
- import { type TPlacementOptions } from './types';
5
- /**
6
- * Represents the lifecycle state of the popup.
7
- *
8
- * - `'closed'`: fully closed, not visible, no animation playing.
9
- * - `'animating-open'`: entry animation is playing (popup is opening but not yet settled).
10
- * - `'open'`: fully open, browser popover is showing, entry animation complete.
11
- * - `'animating-closed'`: exit animation is playing (popup is closing but still visible).
12
- *
13
- * Used to derive `aria-expanded` on the trigger:
14
- * - `aria-expanded` is `true` in `'animating-open'`, `'open'`, and `'animating-closed'`.
15
- *
16
- * This avoids screen readers announcing the popup as closed while it is
17
- * still visually present on screen during animations, and prevents consumers
18
- * that conditionally show/hide trigger UI based on `aria-expanded` from hiding
19
- * the trigger (and thus the popup anchor) mid-animation.
20
- */
21
- export type TPopupState = 'closed' | 'animating-open' | 'open' | 'animating-closed';
22
- export type TPopupContextValue = {
23
- /**
24
- * Auto-generated ID for the popover content element (used for aria-controls).
25
- */
26
- popoverId: string;
27
- /**
28
- * Requested placement.
29
- */
30
- placement: TPlacementOptions;
31
- /**
32
- * Called when the popover is dismissed via light dismiss.
33
- * `null` when mode is 'manual' (no light dismiss).
34
- */
35
- onClose: ((args: {
36
- reason: TPopoverCloseReason;
37
- }) => void) | null;
38
- /**
39
- * Mutable ref to the trigger element (set by Popup.Trigger / Popup.TriggerFunction).
40
- */
41
- triggerRef: MutableRefObject<HTMLElement | null>;
42
- /**
43
- * Ref to the popover content element (set by Popup.Content).
44
- */
45
- popoverRef: RefObject<HTMLDivElement | null>;
46
- /**
47
- * The full lifecycle state of the popup.
48
- *
49
- * See `TPopupState` for the full state machine description.
50
- */
51
- popupState: TPopupState;
52
- /**
53
- * Updates the popup lifecycle state. Called by `PopupContent` as animations
54
- * begin and complete.
55
- */
56
- setPopupState: (state: TPopupState) => void;
57
- /**
58
- * Consumer's onOpenChange callback, forwarded to the Popover.
59
- */
60
- onOpenChange?: (args: {
61
- isOpen: boolean;
62
- element: HTMLDivElement;
63
- }) => void;
64
- /**
65
- * Native popover mode. Flows from the Popup root to Content via context.
66
- */
67
- mode: 'auto' | 'hint' | 'manual';
68
- /**
69
- * The `aria-haspopup` value derived from the content's role.
70
- *
71
- * Set by `Popup.Content` via `setAriaHasPopup` when it renders.
72
- * Read by `Popup.Trigger` / `Popup.TriggerFunction` to set
73
- * the correct `aria-haspopup` on the trigger element.
74
- *
75
- * This flows the content's role to the trigger without requiring
76
- * the consumer to specify the role in two places. The trigger
77
- * renders with the default ('dialog') on first paint; Content's
78
- * layout effect updates it before the browser paints.
79
- */
80
- ariaHasPopup: TAriaHasPopupValue;
81
- /**
82
- * Updates `ariaHasPopup` - called by Content on mount/role change.
83
- */
84
- setAriaHasPopup: (value: TAriaHasPopupValue) => void;
85
- /**
86
- * Test ID prefix.
87
- */
88
- testId?: string;
89
- /**
90
- * Forces the JavaScript positioning fallback even when the browser
91
- * supports CSS Anchor Positioning. Useful for testing fallback
92
- * behavior in any environment, including production.
93
- */
94
- forceFallbackPositioning?: boolean;
95
- };
96
- export declare const PopupContext: React.Context<TPopupContextValue | null>;