@atlaskit/top-layer 0.8.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +41 -0
- package/README.md +5 -1
- package/dialog/create-close-event/package.json +17 -0
- package/dist/cjs/animations/presets.js +11 -4
- package/dist/cjs/arrow/index.js +131 -0
- package/dist/cjs/arrow/types.js +5 -0
- package/dist/cjs/dialog/dialog-content.js +23 -6
- package/dist/cjs/entry-points/dialog/create-close-event.js +12 -0
- package/dist/cjs/entry-points/placement-map.js +6 -5
- package/dist/cjs/entry-points/popover/create-close-event.js +12 -0
- package/dist/cjs/focus/focus.js +73 -19
- package/dist/cjs/index.js +3 -4
- package/dist/cjs/internal/resolve-css-length-to-pixels.js +61 -10
- package/dist/cjs/internal/role-types.js +40 -9
- package/dist/cjs/internal/set-style.js +23 -25
- package/dist/cjs/internal/use-anchor-position.js +109 -68
- package/dist/cjs/internal/use-focus-wrap.js +13 -2
- package/dist/cjs/internal/use-initial-focus.js +31 -10
- package/dist/cjs/placement-map/index.js +9 -110
- package/dist/cjs/placement-map/legacy-placements.js +113 -0
- package/dist/cjs/popover/popover.js +44 -11
- package/dist/cjs/popup/popup-content.js +19 -13
- package/dist/cjs/popup/popup-context.js +2 -0
- package/dist/cjs/popup/popup-surface.js +6 -0
- package/dist/cjs/popup/popup-trigger-function.js +1 -1
- package/dist/cjs/popup/popup-trigger.js +17 -37
- package/dist/cjs/popup/popup.js +21 -10
- package/dist/cjs/use-arrow-navigation/use-arrow-navigation.js +27 -10
- package/dist/es2019/animations/presets.js +10 -3
- package/dist/es2019/arrow/index.js +269 -0
- package/dist/es2019/arrow/types.js +1 -0
- package/dist/es2019/dialog/dialog-content.js +23 -6
- package/dist/es2019/entry-points/create-close-event.js +7 -0
- package/dist/es2019/entry-points/dialog/create-close-event.js +1 -0
- package/dist/es2019/entry-points/placement-map.js +2 -1
- package/dist/es2019/entry-points/popover/create-close-event.js +1 -0
- package/dist/es2019/focus/focus.js +58 -7
- package/dist/es2019/index.js +3 -4
- package/dist/es2019/internal/resolve-css-length-to-pixels.js +60 -7
- package/dist/es2019/internal/role-types.js +40 -9
- package/dist/es2019/internal/set-style.js +19 -22
- package/dist/es2019/internal/use-anchor-position.js +97 -54
- package/dist/es2019/internal/use-focus-wrap.js +14 -3
- package/dist/es2019/internal/use-initial-focus.js +32 -11
- package/dist/es2019/placement-map/index.js +8 -108
- package/dist/es2019/placement-map/legacy-placements.js +107 -0
- package/dist/es2019/popover/popover.js +44 -10
- package/dist/es2019/popup/popup-content.js +20 -14
- package/dist/es2019/popup/popup-context.js +2 -0
- package/dist/es2019/popup/popup-surface.js +6 -0
- package/dist/es2019/popup/popup-trigger-function.js +1 -1
- package/dist/es2019/popup/popup-trigger.js +17 -37
- package/dist/es2019/popup/popup.js +20 -9
- package/dist/es2019/use-arrow-navigation/use-arrow-navigation.js +27 -10
- package/dist/esm/animations/presets.js +10 -3
- package/dist/esm/arrow/index.js +124 -0
- package/dist/esm/arrow/types.js +1 -0
- package/dist/esm/dialog/dialog-content.js +23 -6
- package/dist/esm/entry-points/create-close-event.js +7 -0
- package/dist/esm/entry-points/dialog/create-close-event.js +1 -0
- package/dist/esm/entry-points/placement-map.js +2 -1
- package/dist/esm/entry-points/popover/create-close-event.js +1 -0
- package/dist/esm/focus/focus.js +72 -19
- package/dist/esm/index.js +3 -4
- package/dist/esm/internal/resolve-css-length-to-pixels.js +61 -10
- package/dist/esm/internal/role-types.js +39 -9
- package/dist/esm/internal/set-style.js +23 -25
- package/dist/esm/internal/use-anchor-position.js +110 -64
- package/dist/esm/internal/use-focus-wrap.js +14 -3
- package/dist/esm/internal/use-initial-focus.js +32 -11
- package/dist/esm/placement-map/index.js +8 -108
- package/dist/esm/placement-map/legacy-placements.js +107 -0
- package/dist/esm/popover/popover.js +44 -11
- package/dist/esm/popup/popup-content.js +20 -14
- package/dist/esm/popup/popup-context.js +2 -0
- package/dist/esm/popup/popup-surface.js +6 -0
- package/dist/esm/popup/popup-trigger-function.js +1 -1
- package/dist/esm/popup/popup-trigger.js +17 -37
- package/dist/esm/popup/popup.js +21 -10
- package/dist/esm/use-arrow-navigation/use-arrow-navigation.js +27 -10
- package/dist/types/arrow/index.d.ts +24 -0
- package/dist/types/arrow/types.d.ts +29 -0
- package/dist/types/dialog/dialog-content.d.ts +5 -1
- package/dist/types/dialog/types.d.ts +50 -24
- package/dist/types/entry-points/create-close-event.d.ts +7 -0
- package/dist/types/entry-points/dialog/create-close-event.d.ts +2 -0
- package/dist/types/entry-points/placement-map.d.ts +2 -1
- package/dist/types/entry-points/popover/create-close-event.d.ts +2 -0
- package/dist/types/focus/focus.d.ts +8 -0
- package/dist/types/internal/resolve-css-length-to-pixels.d.ts +4 -6
- package/dist/types/internal/role-types.d.ts +25 -4
- package/dist/types/internal/set-style.d.ts +2 -19
- package/dist/types/internal/use-anchor-position.d.ts +2 -3
- package/dist/types/internal/use-initial-focus.d.ts +5 -4
- package/dist/types/placement-map/index.d.ts +8 -21
- package/dist/types/placement-map/legacy-placements.d.ts +21 -0
- package/dist/types/popover/popover.d.ts +1 -1
- package/dist/types/popover/types.d.ts +20 -19
- package/dist/types/popup/popup-surface.d.ts +6 -0
- package/dist/types/popup/popup-trigger-function.d.ts +10 -6
- package/dist/types/popup/popup-trigger.d.ts +8 -17
- package/dist/types/popup/popup.d.ts +2 -2
- package/dist/types/popup/types.d.ts +68 -22
- package/dist/types/use-arrow-navigation/use-arrow-navigation.d.ts +19 -5
- package/dist/types-ts4.5/arrow/index.d.ts +24 -0
- package/dist/types-ts4.5/arrow/types.d.ts +29 -0
- package/dist/types-ts4.5/dialog/dialog-content.d.ts +5 -1
- package/dist/types-ts4.5/dialog/types.d.ts +50 -24
- package/dist/types-ts4.5/entry-points/create-close-event.d.ts +7 -0
- package/dist/types-ts4.5/entry-points/dialog/create-close-event.d.ts +2 -0
- package/dist/types-ts4.5/entry-points/placement-map.d.ts +2 -1
- package/dist/types-ts4.5/entry-points/popover/create-close-event.d.ts +2 -0
- package/dist/types-ts4.5/focus/focus.d.ts +8 -0
- package/dist/types-ts4.5/internal/resolve-css-length-to-pixels.d.ts +4 -6
- package/dist/types-ts4.5/internal/role-types.d.ts +25 -4
- package/dist/types-ts4.5/internal/set-style.d.ts +2 -19
- package/dist/types-ts4.5/internal/use-anchor-position.d.ts +2 -3
- package/dist/types-ts4.5/internal/use-initial-focus.d.ts +5 -4
- package/dist/types-ts4.5/placement-map/index.d.ts +8 -21
- package/dist/types-ts4.5/placement-map/legacy-placements.d.ts +39 -0
- package/dist/types-ts4.5/popover/popover.d.ts +1 -1
- package/dist/types-ts4.5/popover/types.d.ts +20 -19
- package/dist/types-ts4.5/popup/popup-surface.d.ts +6 -0
- package/dist/types-ts4.5/popup/popup-trigger-function.d.ts +10 -6
- package/dist/types-ts4.5/popup/popup-trigger.d.ts +8 -17
- package/dist/types-ts4.5/popup/popup.d.ts +2 -2
- package/dist/types-ts4.5/popup/types.d.ts +68 -22
- package/dist/types-ts4.5/use-arrow-navigation/use-arrow-navigation.d.ts +19 -5
- package/package.json +3 -1
- package/popover/create-close-event/package.json +17 -0
|
@@ -1,23 +1,14 @@
|
|
|
1
1
|
import { type ReactNode } from 'react';
|
|
2
2
|
import { type TPopupTriggerProps } from './types';
|
|
3
3
|
/**
|
|
4
|
-
* Wraps
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* Wraps a single trigger element via `cloneElement`. Attaches aria
|
|
5
|
+
* attributes, the toggle handler, and the anchor-name. `aria-haspopup`
|
|
6
|
+
* is derived from `Popup.Content`'s role via context.
|
|
7
7
|
*
|
|
8
|
-
*
|
|
9
|
-
* (
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* **Limitation:** Uses `cloneElement` internally (via `Slot`), which is
|
|
14
|
-
* incompatible with Compiled's `css` prop on the direct child element.
|
|
15
|
-
* The `@jsx jsx` pragma transforms the child before `cloneElement` can
|
|
16
|
-
* inject `onClick` and `ref` onto the DOM node, preventing the popover
|
|
17
|
-
* from opening.
|
|
18
|
-
*
|
|
19
|
-
* If you need Compiled `css` on the trigger, use `Popup.TriggerFunction`
|
|
20
|
-
* instead - it hands you raw props via a render-prop and avoids
|
|
21
|
-
* `cloneElement` entirely.
|
|
8
|
+
* Child constraints: must be a single ref-forwarding element. The child's
|
|
9
|
+
* `onClick` is composed (runs after); other event handlers are NOT.
|
|
10
|
+
* Children using Compiled's `css` prop swallow injected props - use
|
|
11
|
+
* `Popup.TriggerFunction` for these cases or any time you need handler
|
|
12
|
+
* composition.
|
|
22
13
|
*/
|
|
23
14
|
export declare function PopupTrigger({ children }: TPopupTriggerProps): ReactNode;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { type TPopupProps } from './types';
|
|
3
3
|
/**
|
|
4
|
-
* Popup compound
|
|
4
|
+
* Popup compound: trigger + popover content.
|
|
5
5
|
*
|
|
6
6
|
* Use when a button opens anchored content (dropdown, menu, dialog).
|
|
7
|
-
* The browser manages visibility via `togglePopover()
|
|
7
|
+
* The browser manages visibility via `togglePopover()`; the consumer
|
|
8
8
|
* never manages `isOpen`. For custom trigger lifecycles (hover, timers,
|
|
9
9
|
* external state), use `Popover` directly instead.
|
|
10
10
|
*
|
|
@@ -25,26 +25,27 @@ import { type TPopoverCloseReason, type TWidthFromAnchorMode } from '../popover/
|
|
|
25
25
|
* ```
|
|
26
26
|
*/
|
|
27
27
|
export { type TPlacementOptions } from '../internal/resolve-placement';
|
|
28
|
-
|
|
28
|
+
/**
|
|
29
|
+
* Props shared across all `Popup` modes.
|
|
30
|
+
*
|
|
31
|
+
* Mode-specific behaviour for `onClose` is encoded in the discriminated
|
|
32
|
+
* union below: `'auto'` and `'hint'` modes accept an `onClose` handler
|
|
33
|
+
* (called on light dismiss); `'manual'` mode forbids it (no light dismiss
|
|
34
|
+
* exists, so a handler would be dead code).
|
|
35
|
+
*/
|
|
36
|
+
type TPopupBaseProps = {
|
|
29
37
|
/**
|
|
30
38
|
* Position of the popup relative to the trigger. Only the Popup compound uses
|
|
31
39
|
* placement; the low-level Popover primitive does not.
|
|
40
|
+
*
|
|
41
|
+
* Defaults to `{}` which means "below the trigger, centered, with a
|
|
42
|
+
* `space.100` token gap".
|
|
32
43
|
*/
|
|
33
|
-
placement
|
|
44
|
+
placement?: TPlacementOptions;
|
|
34
45
|
/**
|
|
35
46
|
* Must contain `Popup.Trigger` and `Popup.Content`.
|
|
36
47
|
*/
|
|
37
48
|
children: ReactNode;
|
|
38
|
-
/**
|
|
39
|
-
* Called when the popup is dismissed via light dismiss.
|
|
40
|
-
*
|
|
41
|
-
* The `reason` field indicates how the dismiss occurred:
|
|
42
|
-
* - `'escape'`: the user pressed the Escape key.
|
|
43
|
-
* - `'light-dismiss'`: the user clicked outside (or another auto-dismiss).
|
|
44
|
-
*/
|
|
45
|
-
onClose: (args: {
|
|
46
|
-
reason: TPopoverCloseReason;
|
|
47
|
-
}) => void;
|
|
48
49
|
/**
|
|
49
50
|
* Called when the popup's open state changes.
|
|
50
51
|
*
|
|
@@ -67,14 +68,6 @@ export type TPopupProps = {
|
|
|
67
68
|
isOpen: boolean;
|
|
68
69
|
element: HTMLDivElement;
|
|
69
70
|
}) => void;
|
|
70
|
-
/**
|
|
71
|
-
* Native popover attribute value. Default is `'auto'`.
|
|
72
|
-
*
|
|
73
|
-
* - `'auto'`: light dismiss (Escape, click-outside). Only one `popover="auto"` can be open at a time; opening another closes the previous.
|
|
74
|
-
* - `'hint'`: allows ephemeral UI (e.g. tooltips) to open without closing other `popover="auto"` popovers. Falls back to `popover="auto"` when unsupported.
|
|
75
|
-
* - `'manual'`: no light dismiss; the consumer controls show/hide entirely. Escape and click-outside do not close the popover.
|
|
76
|
-
*/
|
|
77
|
-
mode?: 'auto' | 'hint' | 'manual';
|
|
78
71
|
/**
|
|
79
72
|
* Test ID applied to the popup content element.
|
|
80
73
|
*/
|
|
@@ -86,6 +79,49 @@ export type TPopupProps = {
|
|
|
86
79
|
*/
|
|
87
80
|
forceFallbackPositioning?: boolean;
|
|
88
81
|
};
|
|
82
|
+
/**
|
|
83
|
+
* Props for the `Popup` compound.
|
|
84
|
+
*
|
|
85
|
+
* Discriminated on `mode`:
|
|
86
|
+
* - `'auto'` (default) and `'hint'`: light dismiss is enabled; `onClose` is
|
|
87
|
+
* optional and is called when the browser dismisses the popover.
|
|
88
|
+
* - `'manual'`: no light dismiss; `onClose` is `never` since the consumer
|
|
89
|
+
* owns show/hide entirely and there is no dismiss event to handle.
|
|
90
|
+
*/
|
|
91
|
+
export type TPopupProps = TPopupBaseProps & ({
|
|
92
|
+
/**
|
|
93
|
+
* Native popover attribute value. Default is `'auto'`.
|
|
94
|
+
*
|
|
95
|
+
* - `'auto'`: light dismiss (Escape, click-outside). Only one
|
|
96
|
+
* `popover="auto"` can be open at a time; opening another closes
|
|
97
|
+
* the previous.
|
|
98
|
+
* - `'hint'`: allows ephemeral UI (e.g. tooltips) to open without
|
|
99
|
+
* closing other `popover="auto"` popovers. Falls back to
|
|
100
|
+
* `popover="auto"` when unsupported.
|
|
101
|
+
*/
|
|
102
|
+
mode?: 'auto' | 'hint';
|
|
103
|
+
/**
|
|
104
|
+
* Called when the popup is dismissed via light dismiss.
|
|
105
|
+
*
|
|
106
|
+
* The `reason` field indicates how the dismiss occurred:
|
|
107
|
+
* - `'escape'`: the user pressed the Escape key.
|
|
108
|
+
* - `'light-dismiss'`: the user clicked outside (or another auto-dismiss).
|
|
109
|
+
*/
|
|
110
|
+
onClose?: (args: {
|
|
111
|
+
reason: TPopoverCloseReason;
|
|
112
|
+
}) => void;
|
|
113
|
+
} | {
|
|
114
|
+
/**
|
|
115
|
+
* `'manual'`: no light dismiss; the consumer controls show/hide
|
|
116
|
+
* entirely. Escape and click-outside do not close the popover.
|
|
117
|
+
*/
|
|
118
|
+
mode: 'manual';
|
|
119
|
+
/**
|
|
120
|
+
* Manual mode has no dismiss event, so `onClose` is forbidden.
|
|
121
|
+
* The consumer owns show/hide via their own state.
|
|
122
|
+
*/
|
|
123
|
+
onClose?: never;
|
|
124
|
+
});
|
|
89
125
|
export type TPopupTriggerProps = {
|
|
90
126
|
/**
|
|
91
127
|
* The trigger element. Must accept a ref.
|
|
@@ -105,7 +141,7 @@ export type TPopupRole = TRoleRequiringAccessibleName | TRoleWithImplicitName;
|
|
|
105
141
|
*
|
|
106
142
|
* When used standalone (e.g. tooltip, spotlight), the consumer must provide `isOpen`
|
|
107
143
|
* to control visibility. If `animate` is provided, `isOpen` is required at the type
|
|
108
|
-
* level
|
|
144
|
+
* level. This ensures exit animations always have a controlled lifecycle.
|
|
109
145
|
*/
|
|
110
146
|
type TPopupContentBaseProps = {
|
|
111
147
|
children: ReactNode;
|
|
@@ -113,6 +149,16 @@ type TPopupContentBaseProps = {
|
|
|
113
149
|
* Ref to the underlying `<div popover>` element.
|
|
114
150
|
*/
|
|
115
151
|
ref?: Ref<HTMLDivElement>;
|
|
152
|
+
/**
|
|
153
|
+
* HTML `id` attribute for the popover element.
|
|
154
|
+
*
|
|
155
|
+
* Provide this when using `Popup.Content` standalone (outside the
|
|
156
|
+
* `<Popup>` compound). The consumer is responsible for wiring
|
|
157
|
+
* `aria-controls` on their own trigger to this same id. Inside the
|
|
158
|
+
* `<Popup>` compound, the id flows from context - passing it here is
|
|
159
|
+
* unnecessary.
|
|
160
|
+
*/
|
|
161
|
+
id?: string;
|
|
116
162
|
/**
|
|
117
163
|
* Controls the width of the popover relative to its anchor element.
|
|
118
164
|
*
|
|
@@ -197,7 +243,7 @@ type TPopupContentBaseProps = {
|
|
|
197
243
|
* Inside the `<Popup>` compound, `isOpen` is provided automatically via context
|
|
198
244
|
* (the browser manages state through `togglePopover()`).
|
|
199
245
|
*
|
|
200
|
-
* For standalone usage, provide `isOpen` to control visibility
|
|
246
|
+
* For standalone usage, provide `isOpen` to control visibility, especially
|
|
201
247
|
* when `animate` is set, so the exit animation lifecycle works correctly.
|
|
202
248
|
*
|
|
203
249
|
* @example
|
|
@@ -2,16 +2,16 @@ import { type RefObject } from 'react';
|
|
|
2
2
|
import { type TFocusableFilter } from '../focus';
|
|
3
3
|
/**
|
|
4
4
|
* Returns true if the element belongs to the current menu level of the
|
|
5
|
-
* container
|
|
5
|
+
* container, i.e. it is NOT inside a nested `role="menu"` sub-container.
|
|
6
6
|
*
|
|
7
7
|
* Uses `element.closest('[role="menu"]')` to determine the nearest menu
|
|
8
8
|
* scope. If the nearest scope is the container's own `role="menu"` element,
|
|
9
|
-
* the element belongs to this level. If it
|
|
9
|
+
* the element belongs to this level. If it is a different (nested) menu,
|
|
10
10
|
* the element belongs to a child level and should be excluded.
|
|
11
11
|
*
|
|
12
12
|
* Supports two container patterns:
|
|
13
13
|
*
|
|
14
|
-
* **1. Container has `role="menu"` directly** (preferred
|
|
14
|
+
* **1. Container has `role="menu"` directly** (preferred, used by avatar-group):
|
|
15
15
|
* ```
|
|
16
16
|
* <div ref={containerRef} role="menu">
|
|
17
17
|
* <button role="menuitem" /> ← isAtCurrentMenuLevel → true
|
|
@@ -23,7 +23,7 @@ import { type TFocusableFilter } from '../focus';
|
|
|
23
23
|
* Uses the simple check: `element.closest('[role="menu"]') === container`
|
|
24
24
|
*
|
|
25
25
|
* **2. Container is a wrapper without `role="menu"`** (used by dropdown-menu,
|
|
26
|
-
* where `MenuGroup` owns `role="menu"` but
|
|
26
|
+
* where `MenuGroup` owns `role="menu"` but does not accept a ref):
|
|
27
27
|
* ```
|
|
28
28
|
* <div ref={containerRef}> ← wrapper (no role="menu")
|
|
29
29
|
* <MenuGroup role="menu">
|
|
@@ -48,6 +48,20 @@ import { type TFocusableFilter } from '../focus';
|
|
|
48
48
|
* belong to a nested menu.
|
|
49
49
|
*/
|
|
50
50
|
export declare function isAtCurrentMenuLevel(element: Element, container: HTMLElement): boolean;
|
|
51
|
+
/**
|
|
52
|
+
* Args for `useArrowNavigation`.
|
|
53
|
+
*
|
|
54
|
+
* Keyboard contract:
|
|
55
|
+
* - `ArrowDown` / `ArrowUp` move within the current menu level.
|
|
56
|
+
* - `Home` / `End` jump to first / last.
|
|
57
|
+
* - `ArrowRight` / `ArrowLeft` opens / closes nested submenus.
|
|
58
|
+
* - `Tab` / `Shift+Tab` dismiss the menu (matching the ARIA APG menu pattern,
|
|
59
|
+
* plus Radix UI / Headless UI / React Aria / Floating UI conventions).
|
|
60
|
+
* Symmetric in both directions: there is no special-case for the last
|
|
61
|
+
* item that lets Tab leave the menu without dismissing it.
|
|
62
|
+
* - `Page Up` / `Page Down`: NOT handled - extend via your own listener if
|
|
63
|
+
* your menu needs page-style scrolling.
|
|
64
|
+
*/
|
|
51
65
|
export type TUseArrowNavigationArgs = {
|
|
52
66
|
/**
|
|
53
67
|
* Ref to the container element that holds the focusable items.
|
|
@@ -89,7 +103,7 @@ export type TUseArrowNavigationArgs = {
|
|
|
89
103
|
* When provided, only elements that pass the filter will be focused.
|
|
90
104
|
*
|
|
91
105
|
* The filter is also used as a guard on the currently focused element:
|
|
92
|
-
* if the focused element
|
|
106
|
+
* if the focused element does not pass the filter, the handler bails out.
|
|
93
107
|
* This prevents parent menu handlers from acting on events that belong
|
|
94
108
|
* to a nested menu.
|
|
95
109
|
*
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { type TArrowPreset } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Creates an arrow preset for popover content.
|
|
4
|
+
*
|
|
5
|
+
* The returned object is passed to `PopoverContent`'s `arrow` prop.
|
|
6
|
+
* It carries the CSS string and fallback logic so that consumers who
|
|
7
|
+
* do not use arrows pay no bundle cost.
|
|
8
|
+
*
|
|
9
|
+
* The arrows inherit their background from the popover element.
|
|
10
|
+
* When `arrow` is active, `PopoverContent` does not reset `background`
|
|
11
|
+
* to `transparent`, allowing the UA default (`canvas`) or a consumer-set
|
|
12
|
+
* background to show through.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```tsx
|
|
16
|
+
* import { arrow } from '@atlaskit/top-layer/arrow';
|
|
17
|
+
*
|
|
18
|
+
* const myArrow = arrow();
|
|
19
|
+
*
|
|
20
|
+
* <Popup.Content arrow={myArrow} />
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export declare const arrow: () => TArrowPreset;
|
|
24
|
+
export type { TArrowPreset } from './types';
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { TPlacementOptions } from '../popup/types';
|
|
2
|
+
/**
|
|
3
|
+
* A self-contained arrow preset for PopoverContent.
|
|
4
|
+
*
|
|
5
|
+
* Contains the CSS rules (injected once into `<head>`), a data-attribute name
|
|
6
|
+
* for CSS targeting, and a function to compute `position-try-fallbacks` values
|
|
7
|
+
* that change both `position-area` and `margin` when the popover flips.
|
|
8
|
+
*
|
|
9
|
+
* Imported from `@atlaskit/top-layer/arrow` so that consumers who do not use
|
|
10
|
+
* arrows pay no bundle cost for the CSS string or fallback logic.
|
|
11
|
+
*/
|
|
12
|
+
export type TArrowPreset = {
|
|
13
|
+
/**
|
|
14
|
+
* CSS to inject once into `document.head`, scoped to `[data-ds-popover-{name}]`.
|
|
15
|
+
*/
|
|
16
|
+
css: string;
|
|
17
|
+
/**
|
|
18
|
+
* Data attribute suffix for CSS targeting (e.g. `'arrow'`).
|
|
19
|
+
*/
|
|
20
|
+
name: string;
|
|
21
|
+
/**
|
|
22
|
+
* Returns the `position-try-fallbacks` value for a given placement.
|
|
23
|
+
* Uses named `@position-try` rules that update both `position-area`
|
|
24
|
+
* and `margin` so the correct arrow is revealed after a flip.
|
|
25
|
+
*/
|
|
26
|
+
getTryFallbacks: (args: {
|
|
27
|
+
placement: TPlacementOptions;
|
|
28
|
+
}) => string;
|
|
29
|
+
};
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
import React from 'react';
|
|
6
6
|
import { type TDialogProps } from './types';
|
|
7
7
|
/**
|
|
8
|
-
* Low-level `<dialog>` primitive. No visual opinions
|
|
8
|
+
* Low-level `<dialog>` primitive. No visual opinions - no width, height,
|
|
9
9
|
* background, border-radius, or layout. Consumers provide their own styling.
|
|
10
10
|
*
|
|
11
11
|
* Visibility is controlled declaratively via `isOpen`:
|
|
@@ -16,5 +16,9 @@ import { type TDialogProps } from './types';
|
|
|
16
16
|
*
|
|
17
17
|
* Close flow: we never call `dialog.close()` from event handlers. We always call
|
|
18
18
|
* `onClose`; the consumer decides whether to set `isOpen={false}`.
|
|
19
|
+
*
|
|
20
|
+
* Accessibility: render at least one focusable element (typically a close
|
|
21
|
+
* button) when `isOpen` becomes `true`. Tab is always trapped inside the
|
|
22
|
+
* dialog, so keyboard users need somewhere to land.
|
|
19
23
|
*/
|
|
20
24
|
export declare const Dialog: React.ForwardRefExoticComponent<TDialogProps & React.RefAttributes<HTMLDialogElement>>;
|
|
@@ -3,23 +3,21 @@ import { type TAnimationPreset } from '../animations/types';
|
|
|
3
3
|
/**
|
|
4
4
|
* Close reasons produced by the Dialog primitive.
|
|
5
5
|
*
|
|
6
|
-
* - `'escape'
|
|
7
|
-
* - `'overlay-click'
|
|
6
|
+
* - `'escape'`: user pressed Escape (native `cancel` event on `<dialog>`).
|
|
7
|
+
* - `'overlay-click'`: user clicked the backdrop / overlay area.
|
|
8
8
|
*
|
|
9
9
|
* Consumer-initiated ("programmatic") close is not a reason the primitive
|
|
10
|
-
* produces
|
|
10
|
+
* produces. The consumer simply sets `isOpen={false}`.
|
|
11
11
|
*/
|
|
12
12
|
export type TDialogCloseReason = 'escape' | 'overlay-click';
|
|
13
13
|
/**
|
|
14
|
-
* Props
|
|
14
|
+
* Props shared across `TDialogProps` variants.
|
|
15
15
|
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
* background, border-radius, or layout. Consumers (e.g. `@atlaskit/modal-dialog`)
|
|
20
|
-
* provide their own visual styling.
|
|
16
|
+
* The accessible-name requirement (one of `label` or `labelledBy`) is encoded
|
|
17
|
+
* in the discriminated union below - WCAG 4.1.2 violations are caught at
|
|
18
|
+
* compile time instead of in production audit reports.
|
|
21
19
|
*/
|
|
22
|
-
|
|
20
|
+
type TDialogBaseProps = {
|
|
23
21
|
children: ReactNode;
|
|
24
22
|
/**
|
|
25
23
|
* Whether the dialog is open.
|
|
@@ -28,13 +26,13 @@ export type TDialogProps = {
|
|
|
28
26
|
* - `false`: calls `close()`. When an `animate` preset is provided, the exit
|
|
29
27
|
* animation plays (via `allow-discrete`) before the dialog becomes logically closed.
|
|
30
28
|
*
|
|
31
|
-
* The element stays mounted in the DOM
|
|
29
|
+
* The element stays mounted in the DOM. Visibility is controlled declaratively.
|
|
32
30
|
*/
|
|
33
31
|
isOpen: boolean;
|
|
34
32
|
/**
|
|
35
33
|
* Called when the user triggers close via Escape or backdrop click.
|
|
36
34
|
*
|
|
37
|
-
* The dialog does **not** close itself
|
|
35
|
+
* The dialog does **not** close itself. The consumer decides whether to
|
|
38
36
|
* set `isOpen={false}` (e.g. gate by reason).
|
|
39
37
|
*/
|
|
40
38
|
onClose: (args: {
|
|
@@ -61,32 +59,60 @@ export type TDialogProps = {
|
|
|
61
59
|
* HTML `id` attribute for the `<dialog>` element.
|
|
62
60
|
*/
|
|
63
61
|
id?: string;
|
|
62
|
+
/**
|
|
63
|
+
* When true, the `::backdrop` pseudo-element is rendered transparent.
|
|
64
|
+
*
|
|
65
|
+
* Useful for stacked dialogs where only the foreground dialog should
|
|
66
|
+
* show a visible backdrop, or when the consumer wants no overlay.
|
|
67
|
+
*/
|
|
68
|
+
shouldHideBackdrop?: boolean;
|
|
69
|
+
/**
|
|
70
|
+
* Called after the exit animation completes (or immediately on close when
|
|
71
|
+
* there is no animation or reduced motion is active).
|
|
72
|
+
*
|
|
73
|
+
* Use this for external lifecycle coordination, e.g. firing an
|
|
74
|
+
* `onCloseComplete` callback or notifying ExitingPersistence.
|
|
75
|
+
*/
|
|
76
|
+
onExitFinish?: () => void;
|
|
77
|
+
};
|
|
78
|
+
/**
|
|
79
|
+
* Props for the `Dialog` primitive.
|
|
80
|
+
*
|
|
81
|
+
* Low-level wrapper around the native `<dialog>` element.
|
|
82
|
+
* Manages visibility (`showModal()` / `close()`), animation, Escape handling,
|
|
83
|
+
* and backdrop-click detection. Has no visual opinions - no width, height,
|
|
84
|
+
* background, border-radius, or layout. Consumers (e.g. `@atlaskit/modal-dialog`)
|
|
85
|
+
* provide their own visual styling.
|
|
86
|
+
*
|
|
87
|
+
* Discriminated on the accessible-name source: at least one of `label`
|
|
88
|
+
* (aria-label) or `labelledBy` (aria-labelledby) must be provided. This
|
|
89
|
+
* enforces WCAG 4.1.2 at the type level - an unlabelled dialog landmark
|
|
90
|
+
* is not constructible. Mirrors the pattern used by `TPopupContentProps`.
|
|
91
|
+
*/
|
|
92
|
+
export type TDialogProps = TDialogBaseProps & ({
|
|
64
93
|
/**
|
|
65
94
|
* Accessible label (`aria-label`).
|
|
66
95
|
*
|
|
67
96
|
* When provided, `aria-labelledby` is not set.
|
|
68
97
|
* Use when there is no visible title element to reference.
|
|
69
98
|
*/
|
|
70
|
-
label
|
|
99
|
+
label: string;
|
|
71
100
|
/**
|
|
72
101
|
* ID of the element that labels the dialog (`aria-labelledby`).
|
|
73
102
|
*
|
|
74
103
|
* Ignored when `label` is provided.
|
|
75
104
|
*/
|
|
76
105
|
labelledBy?: string;
|
|
106
|
+
} | {
|
|
77
107
|
/**
|
|
78
|
-
*
|
|
108
|
+
* Accessible label (`aria-label`).
|
|
79
109
|
*
|
|
80
|
-
*
|
|
81
|
-
* show a visible backdrop, or when the consumer wants no overlay.
|
|
110
|
+
* Optional when `labelledBy` is provided.
|
|
82
111
|
*/
|
|
83
|
-
|
|
112
|
+
label?: string;
|
|
84
113
|
/**
|
|
85
|
-
*
|
|
86
|
-
* there is no animation or reduced motion is active).
|
|
87
|
-
*
|
|
88
|
-
* Use this for external lifecycle coordination — e.g. firing an
|
|
89
|
-
* `onCloseComplete` callback or notifying ExitingPersistence.
|
|
114
|
+
* ID of the element that labels the dialog (`aria-labelledby`).
|
|
90
115
|
*/
|
|
91
|
-
|
|
92
|
-
};
|
|
116
|
+
labelledBy: string;
|
|
117
|
+
});
|
|
118
|
+
export {};
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @deprecated Combined entry-point retained for backwards-compatibility.
|
|
3
|
+
* Prefer the disjoint subpaths so that bundle analysis attributes the cost
|
|
4
|
+
* to the right consumer:
|
|
5
|
+
* - `@atlaskit/top-layer/dialog/create-close-event` for `createCloseEvent`
|
|
6
|
+
* - `@atlaskit/top-layer/popover/create-close-event` for `createPopoverCloseEvent`
|
|
7
|
+
*/
|
|
1
8
|
export { createCloseEvent } from '../dialog';
|
|
2
9
|
export { createPopoverCloseEvent } from '../popover/create-close-event';
|
|
3
10
|
export type { TDialogCloseReason } from '../dialog';
|
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
export { fromLegacyPlacement
|
|
1
|
+
export { fromLegacyPlacement } from '../placement-map';
|
|
2
|
+
export { LEGACY_PLACEMENTS } from '../placement-map/legacy-placements';
|
|
2
3
|
export type { TLegacyPlacement, TPlacementOptions } from '../placement-map';
|
|
@@ -9,6 +9,14 @@
|
|
|
9
9
|
* All public functions accept an optional `filter` callback to further
|
|
10
10
|
* restrict which focusable elements are included.
|
|
11
11
|
*/
|
|
12
|
+
/**
|
|
13
|
+
* Returns `true` when `document.activeElement` is inside a nested top-layer
|
|
14
|
+
* descendant of `container` (a `[popover]`, `<dialog>`, `[role="dialog"]` or
|
|
15
|
+
* `[role="alertdialog"]` that is itself a descendant of `container`).
|
|
16
|
+
*/
|
|
17
|
+
export declare function isNestedLayerFocused({ container }: {
|
|
18
|
+
container: HTMLElement;
|
|
19
|
+
}): boolean;
|
|
12
20
|
/**
|
|
13
21
|
* An optional callback to restrict which focusable elements are included.
|
|
14
22
|
* Return `true` to include the element, `false` to skip it.
|
|
@@ -8,13 +8,11 @@
|
|
|
8
8
|
* the browser do the math.
|
|
9
9
|
*
|
|
10
10
|
* The probe is appended to `container` so it inherits the same containing
|
|
11
|
-
* block, font size, and custom-property scope as the popover.
|
|
12
|
-
* because it accepts any CSS length, including negative `calc()` results
|
|
13
|
-
* (negative widths are clamped to 0 — see note below).
|
|
11
|
+
* block, font size, and custom-property scope as the popover.
|
|
14
12
|
*
|
|
15
|
-
* Cost: one synchronous reflow
|
|
16
|
-
*
|
|
17
|
-
*
|
|
13
|
+
* Cost: one synchronous reflow on first cacheable resolution per
|
|
14
|
+
* (container, value) pair, then a `WeakMap` lookup. Resolutions involving
|
|
15
|
+
* `var(` are intentionally not cached.
|
|
18
16
|
*/
|
|
19
17
|
export declare function resolveCssLengthToPixels({ value, container, }: {
|
|
20
18
|
value: number | string;
|
|
@@ -1,8 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Valid values for the `aria-haspopup` attribute.
|
|
3
|
-
*
|
|
3
|
+
*
|
|
4
|
+
* Derived from the HTML spec - maps popover roles to what the trigger
|
|
5
|
+
* announces. `undefined` means the attribute is omitted entirely (used for
|
|
6
|
+
* non-popup roles like `tooltip`/`status`/`alert`/`note`/`log` where
|
|
7
|
+
* `aria-haspopup` would be misleading).
|
|
8
|
+
*
|
|
9
|
+
* `true` is intentionally NOT in the union - the runtime only ever produces
|
|
10
|
+
* the explicit string forms, so widening the type would invite consumers to
|
|
11
|
+
* pass `true` and get an `aria-haspopup="true"` serialisation that the
|
|
12
|
+
* runtime no longer emits.
|
|
4
13
|
*/
|
|
5
|
-
export type TAriaHasPopupValue = 'dialog' | 'menu' | 'listbox' | 'tree' | 'grid' |
|
|
14
|
+
export type TAriaHasPopupValue = 'dialog' | 'menu' | 'listbox' | 'tree' | 'grid' | undefined;
|
|
6
15
|
/**
|
|
7
16
|
* Roles that require an accessible name (`label` or `labelledBy`) per WCAG 4.1.2.
|
|
8
17
|
* Without a name, assistive technology cannot identify these landmarks.
|
|
@@ -33,7 +42,7 @@ type TAccessibleNameOptional = {
|
|
|
33
42
|
/**
|
|
34
43
|
* ARIA role props where a role is always required.
|
|
35
44
|
*
|
|
36
|
-
* Used by `TPopupContentProps
|
|
45
|
+
* Used by `TPopupContentProps`. Popup content must always declare
|
|
37
46
|
* its role so assistive technology can identify the layer.
|
|
38
47
|
*/
|
|
39
48
|
export type TAriaRoleRequired = ({
|
|
@@ -44,7 +53,7 @@ export type TAriaRoleRequired = ({
|
|
|
44
53
|
/**
|
|
45
54
|
* ARIA role props where a role is optional.
|
|
46
55
|
*
|
|
47
|
-
* Used by `TPopoverProps
|
|
56
|
+
* Used by `TPopoverProps`. The low-level primitive allows omitting
|
|
48
57
|
* the role for cases where it is set externally or not needed.
|
|
49
58
|
*/
|
|
50
59
|
export type TAriaRoleOptional = ({
|
|
@@ -55,8 +64,20 @@ export type TAriaRoleOptional = ({
|
|
|
55
64
|
/**
|
|
56
65
|
* Maps a popover content role to the correct `aria-haspopup` value
|
|
57
66
|
* for its trigger element.
|
|
67
|
+
*
|
|
68
|
+
* Returns `undefined` for roles that are not popups in the ARIA sense
|
|
69
|
+
* (`tooltip`, `note`, `status`, `alert`, `log`). Triggers for those roles
|
|
70
|
+
* should not announce a popup at all - emitting `aria-haspopup="dialog"`
|
|
71
|
+
* on a tooltip trigger would mislead assistive technology.
|
|
58
72
|
*/
|
|
59
73
|
export declare function roleToAriaHasPopup({ role, }: {
|
|
60
74
|
role: TRoleRequiringAccessibleName | TRoleWithImplicitName | undefined;
|
|
61
75
|
}): TAriaHasPopupValue;
|
|
76
|
+
/**
|
|
77
|
+
* Returns `true` when the given popover role moves focus into the popover
|
|
78
|
+
* on open, and `false` otherwise (including when `role` is `undefined`).
|
|
79
|
+
*/
|
|
80
|
+
export declare function shouldFocusIntoPopover({ role, }: {
|
|
81
|
+
role: TRoleRequiringAccessibleName | TRoleWithImplicitName | undefined;
|
|
82
|
+
}): boolean;
|
|
62
83
|
export {};
|
|
@@ -1,23 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Sets inline styles on an element and returns a cleanup function
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* Uses `style.setProperty()` / `style.removeProperty()` so that
|
|
6
|
-
* hyphenated CSS property names (e.g. `position-area`, `anchor-name`)
|
|
7
|
-
* work correctly. These newer properties do not have camelCase
|
|
8
|
-
* mappings in `CSSStyleDeclaration` yet.
|
|
9
|
-
*
|
|
10
|
-
* @example
|
|
11
|
-
* ```ts
|
|
12
|
-
* const cleanup = setStyle({ el: popover, styles: [
|
|
13
|
-
* { property: 'position-anchor', value: '--my-anchor' },
|
|
14
|
-
* { property: 'position-area', value: 'block-end' },
|
|
15
|
-
* { property: 'margin', value: '0' },
|
|
16
|
-
* ] });
|
|
17
|
-
*
|
|
18
|
-
* // Later: removes all three properties
|
|
19
|
-
* cleanup();
|
|
20
|
-
* ```
|
|
2
|
+
* Sets inline styles on an element and returns a cleanup function that
|
|
3
|
+
* restores the prior inline values (so we do not stomp consumer styles).
|
|
21
4
|
*/
|
|
22
5
|
export declare function setStyle({ el, styles, }: {
|
|
23
6
|
el: HTMLElement;
|
|
@@ -14,7 +14,6 @@
|
|
|
14
14
|
*/
|
|
15
15
|
import { type RefObject } from 'react';
|
|
16
16
|
import { type TPlacementOptions } from '../internal/resolve-placement';
|
|
17
|
-
export { getPlacement } from './resolve-placement';
|
|
18
17
|
/**
|
|
19
18
|
* Resolves placement options to CSS `position-area` syntax.
|
|
20
19
|
*
|
|
@@ -59,7 +58,7 @@ export declare function placementToPositionArea({ placement }: {
|
|
|
59
58
|
* top-right), flipping only the primary axis (`flip-inline`) moves the popup
|
|
60
59
|
* to the left but keeps the same cross-axis span direction (e.g. upward),
|
|
61
60
|
* which is still off-screen. The combined keyword `flip-inline flip-block`
|
|
62
|
-
* mirrors the popup diagonally
|
|
61
|
+
* mirrors the popup diagonally. It flips BOTH the position-area AND both
|
|
63
62
|
* inline and block margins simultaneously, placing the popup at the
|
|
64
63
|
* diagonally opposite corner where there is always space.
|
|
65
64
|
*
|
|
@@ -74,7 +73,7 @@ export declare function placementToTryFallbacks({ placement }: {
|
|
|
74
73
|
* Hook that positions an element relative to an anchor element using
|
|
75
74
|
* CSS Anchor Positioning (with a JS fallback for older browsers).
|
|
76
75
|
*
|
|
77
|
-
* This hook is the positioning primitive
|
|
76
|
+
* This hook is the positioning primitive. It has no knowledge of popovers,
|
|
78
77
|
* visibility, or animation. Compose it with `Popover` for anchor-positioned
|
|
79
78
|
* top-layer content.
|
|
80
79
|
*
|
|
@@ -2,14 +2,15 @@ import { type RefObject } from 'react';
|
|
|
2
2
|
/**
|
|
3
3
|
* Moves focus into a popover element when it opens, based on its ARIA role.
|
|
4
4
|
*
|
|
5
|
-
*
|
|
5
|
+
* Follows the WAI-ARIA APG initial-focus patterns for each role:
|
|
6
6
|
* - `dialog` / `alertdialog` → focus first focusable (or `[autofocus]`)
|
|
7
7
|
* - `menu` → focus first menu item
|
|
8
8
|
* - `listbox` → focus selected or first option
|
|
9
|
-
* - `tooltip` / no role → no focus movement
|
|
9
|
+
* - `tooltip` / no role → no focus movement (focus must remain on trigger;
|
|
10
|
+
* moving focus into the tooltip would dismiss it)
|
|
10
11
|
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
12
|
+
* Role is taken from the typed `role` prop - this is the consumer's contract
|
|
13
|
+
* and is not subject to drift from a directly-mutated DOM attribute.
|
|
13
14
|
*
|
|
14
15
|
* Always call this hook unconditionally. Focus is only moved when `isOpen`
|
|
15
16
|
* transitions to `true` and the role requires it.
|