@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
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,46 @@
|
|
|
1
1
|
# @atlaskit/top-layer
|
|
2
2
|
|
|
3
|
+
## 0.10.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [`dec4f3444bce8`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/dec4f3444bce8) -
|
|
8
|
+
Hardens Popup, Popover, and Dialog through stricter typed contracts, focus-management fixes, and
|
|
9
|
+
clearer entry points.
|
|
10
|
+
- **Stricter API contracts.** Popup, Popover, and Dialog props are now discriminated unions, so
|
|
11
|
+
misuse (manual mode with `onClose`, dialogs without a label, popovers without an accessible name
|
|
12
|
+
for their role) fails at compile time.
|
|
13
|
+
- **Better defaults.** `Popup`'s `placement` prop now defaults to "below trigger, centered, with
|
|
14
|
+
`space.100` gap", removing the awkward `placement={{}}` boilerplate.
|
|
15
|
+
- **Focus-management fixes.** Empty/loading dialogs no longer trap Tab on `<body>`; rapid
|
|
16
|
+
open/close/open sequences no longer focus a torn-down popover; nested top-layer popovers stay in
|
|
17
|
+
their own focus scope.
|
|
18
|
+
- **Cleaner entry points.** `createCloseEvent` is now available as per-primitive subpaths
|
|
19
|
+
(`@atlaskit/top-layer/dialog/create-close-event` and
|
|
20
|
+
`@atlaskit/top-layer/popover/create-close-event`); the combined entry point is deprecated. The
|
|
21
|
+
placement-map entry point now exposes a public `LEGACY_PLACEMENTS` const for migration
|
|
22
|
+
consumers.
|
|
23
|
+
- **Per-primitive data attributes.** Animation hooks now emit `data-ds-popover-*` for Popover and
|
|
24
|
+
`data-ds-dialog-*` for Dialog, preventing cross-primitive selector collisions.
|
|
25
|
+
- **Performance and internal correctness.** `setStyle` snapshots and restores prior inline values;
|
|
26
|
+
CSS-length resolution is memoised and probes inside the popover for correct token scope;
|
|
27
|
+
placement resolution is stable across renders.
|
|
28
|
+
|
|
29
|
+
## 0.9.0
|
|
30
|
+
|
|
31
|
+
### Minor Changes
|
|
32
|
+
|
|
33
|
+
- [`8e9ab10567283`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/8e9ab10567283) -
|
|
34
|
+
When `platform-dst-top-layer` is enabled, the open layer observer registration now happens inside
|
|
35
|
+
the `Dialog` and `Popover` primitives directly, so `popup`, `modal-dialog`, and `tooltip` no
|
|
36
|
+
longer register with the open layer observer separately (avoiding double-counting).
|
|
37
|
+
- `Dialog` registers as `type: 'modal'`, with a no-op `onClose`, as there is no current use case
|
|
38
|
+
for programmatic close of modals via the open layer observer.
|
|
39
|
+
- `Popover` registers as `type: 'popup'` for interactive overlay roles (`dialog`, `alertdialog`,
|
|
40
|
+
`menu`, `listbox`, `tree`, `grid`) and omits `type` for other roles (e.g. `tooltip`).
|
|
41
|
+
- A new `programmatic` value has been added to `TPopoverCloseReason` to distinguish programmatic
|
|
42
|
+
closes, such as those from the open layer observer's `closeLayers()` calls.
|
|
43
|
+
|
|
3
44
|
## 0.8.0
|
|
4
45
|
|
|
5
46
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -11,7 +11,7 @@ Placement is owned by this compound: root provides it via context, Content appli
|
|
|
11
11
|
Positioning or JS fallback).
|
|
12
12
|
|
|
13
13
|
```tsx
|
|
14
|
-
<Popup
|
|
14
|
+
<Popup onClose={handleClose}>
|
|
15
15
|
<Popup.Trigger>
|
|
16
16
|
<button>Open</button>
|
|
17
17
|
</Popup.Trigger>
|
|
@@ -21,6 +21,10 @@ Positioning or JS fallback).
|
|
|
21
21
|
</Popup>
|
|
22
22
|
```
|
|
23
23
|
|
|
24
|
+
`placement` defaults to `{}` - "below trigger, centered, with `space.100` gap".
|
|
25
|
+
Pass an explicit object to override (e.g. `placement={{ axis: 'inline', edge: 'end' }}`
|
|
26
|
+
for a popover anchored to the trigger's right edge).
|
|
27
|
+
|
|
24
28
|
For default overlay styling (background, shadow, border-radius), see `PopupSurface` in the package
|
|
25
29
|
examples (not currently a public API; we may expose it in a future release).
|
|
26
30
|
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@atlaskit/top-layer/dialog/create-close-event",
|
|
3
|
+
"main": "../../dist/cjs/entry-points/dialog/create-close-event.js",
|
|
4
|
+
"module": "../../dist/esm/entry-points/dialog/create-close-event.js",
|
|
5
|
+
"module:es2019": "../../dist/es2019/entry-points/dialog/create-close-event.js",
|
|
6
|
+
"sideEffects": [
|
|
7
|
+
"*.compiled.css"
|
|
8
|
+
],
|
|
9
|
+
"types": "../../dist/types/entry-points/dialog/create-close-event.d.ts",
|
|
10
|
+
"typesVersions": {
|
|
11
|
+
">=4.5 <5.9": {
|
|
12
|
+
"*": [
|
|
13
|
+
"../../dist/types-ts4.5/entry-points/dialog/create-close-event.d.ts"
|
|
14
|
+
]
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -8,7 +8,7 @@ exports.dialogSlideUpAndFade = dialogSlideUpAndFade;
|
|
|
8
8
|
exports.fade = fade;
|
|
9
9
|
exports.scaleAndFade = scaleAndFade;
|
|
10
10
|
exports.slideAndFade = slideAndFade;
|
|
11
|
-
var
|
|
11
|
+
var _resolvePlacement = require("../internal/resolve-placement");
|
|
12
12
|
// ── slideAndFade ──
|
|
13
13
|
|
|
14
14
|
function getSlideAndFadeProperties(_ref) {
|
|
@@ -16,7 +16,7 @@ function getSlideAndFadeProperties(_ref) {
|
|
|
16
16
|
distance = _ref.distance;
|
|
17
17
|
var pos = "".concat(distance, "px");
|
|
18
18
|
var neg = "-".concat(distance, "px");
|
|
19
|
-
var _getPlacement = (0,
|
|
19
|
+
var _getPlacement = (0, _resolvePlacement.getPlacement)({
|
|
20
20
|
placement: placement
|
|
21
21
|
}),
|
|
22
22
|
axis = _getPlacement.axis,
|
|
@@ -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,11 +164,14 @@ 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;
|
|
171
|
+
|
|
172
|
+
// Bare preset name; `Dialog` prefixes it via `data-ds-dialog-{name}`.
|
|
168
173
|
return {
|
|
169
|
-
name: distance === 12 ? '
|
|
174
|
+
name: distance === 12 ? 'slide-up-and-fade' : "slide-up-and-fade-".concat(distance),
|
|
170
175
|
css: distance === 12 ? DIALOG_SLIDE_UP_AND_FADE_CSS : DIALOG_SLIDE_UP_AND_FADE_CSS.replace(/12px/g, "".concat(distance, "px")),
|
|
171
176
|
exitDurationMs: 175
|
|
172
177
|
};
|
|
@@ -190,9 +195,11 @@ var DIALOG_FADE_CSS = "\n[data-ds-dialog-fade] {\n opacity: 0;\n transition:\n
|
|
|
190
195
|
* </Dialog>
|
|
191
196
|
* ```
|
|
192
197
|
*/
|
|
198
|
+
// eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports
|
|
193
199
|
function dialogFade() {
|
|
200
|
+
// Bare preset name; `Dialog` prefixes it via `data-ds-dialog-{name}`.
|
|
194
201
|
return {
|
|
195
|
-
name: '
|
|
202
|
+
name: 'fade',
|
|
196
203
|
css: DIALOG_FADE_CSS,
|
|
197
204
|
exitDurationMs: 175
|
|
198
205
|
};
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports.arrow = void 0;
|
|
8
|
+
var _once = _interopRequireDefault(require("@atlaskit/ds-lib/once"));
|
|
9
|
+
var _resolvePlacement = require("../internal/resolve-placement");
|
|
10
|
+
var _useAnchorPosition = require("../internal/use-anchor-position");
|
|
11
|
+
/**
|
|
12
|
+
* CSS for popover arrows using the `clip-path: inset() margin-box` technique.
|
|
13
|
+
*
|
|
14
|
+
* How it works:
|
|
15
|
+
* 1. Four arrow shapes exist simultaneously as `::before` (top/bottom) and
|
|
16
|
+
* `::after` (left/right) hexagonal pseudo-elements.
|
|
17
|
+
* 2. `clip-path: inset(0) margin-box` clips the popover to its margin-box.
|
|
18
|
+
* 3. Margin on the anchor-facing side pushes the popover away, creating space
|
|
19
|
+
* where one arrow "escapes" the clip boundary and becomes visible.
|
|
20
|
+
* 4. `@position-try` rules change both `position-area` and `margin` when
|
|
21
|
+
* flipping, ensuring the correct arrow is always shown.
|
|
22
|
+
*
|
|
23
|
+
* Constraints:
|
|
24
|
+
* - `box-shadow` must be `none` (interferes with `clip-path: inset() margin-box`)
|
|
25
|
+
* - `::before` and `::after` are consumed - consumers cannot use them
|
|
26
|
+
* - Arrow pseudo-elements use `background: inherit` from the popover element
|
|
27
|
+
*
|
|
28
|
+
* @see https://goulet.dev/posts/tooltip-with-popover-and-anchor-positioning/
|
|
29
|
+
*/
|
|
30
|
+
var ARROW_CSS = "\n[data-ds-popover-arrow] {\n clip-path: inset(var(--ds-arrow-offset, 0px)) margin-box;\n box-shadow: none;\n}\n\n/* Top and Bottom arrows (vertical hexagon) */\n[data-ds-popover-arrow]::before {\n content: \"\";\n position: absolute;\n z-index: -1;\n background: inherit;\n left: 50%;\n transform: translateX(-50%);\n width: calc(var(--ds-arrow-size, 8px) * 2);\n height: calc(100% + var(--ds-arrow-size, 8px) * 2);\n top: calc(var(--ds-arrow-size, 8px) * -1);\n clip-path: polygon(\n 0 var(--ds-arrow-size, 8px),\n 50% 0,\n 100% var(--ds-arrow-size, 8px),\n 100% calc(100% - var(--ds-arrow-size, 8px)),\n 50% 100%,\n 0 calc(100% - var(--ds-arrow-size, 8px))\n );\n}\n\n/* Left and Right arrows (horizontal hexagon) */\n[data-ds-popover-arrow]::after {\n content: \"\";\n position: absolute;\n z-index: -1;\n background: inherit;\n top: 50%;\n transform: translateY(-50%);\n height: calc(var(--ds-arrow-size, 8px) * 2);\n width: calc(100% + var(--ds-arrow-size, 8px) * 2);\n left: calc(var(--ds-arrow-size, 8px) * -1);\n clip-path: polygon(\n var(--ds-arrow-size, 8px) 0,\n calc(100% - var(--ds-arrow-size, 8px)) 0,\n 100% 50%,\n calc(100% - var(--ds-arrow-size, 8px)) 100%,\n var(--ds-arrow-size, 8px) 100%,\n 0 50%\n );\n}\n\n/* \u2500\u2500 @position-try rules \u2500\u2500\n * One rule per possible position-area value.\n * Each sets the position-area and the correct margin direction\n * so the arrow on the anchor-facing side is revealed.\n *\n * Margin direction per edge:\n * block-start (above anchor) \u2192 margin-block-end (bottom, facing anchor)\n * block-end (below anchor) \u2192 margin-block-start (top, facing anchor)\n * inline-start (left of anchor) \u2192 margin-inline-end (right, facing anchor)\n * inline-end (right of anchor) \u2192 margin-inline-start (left, facing anchor)\n */\n\n/* Each rule sets two margins: the anchor-facing margin for the gap\n (via --ds-arrow-size) and one cross-axis margin for the shift\n (via one of --ds-cross-axis-shift-margin-start, --ds-cross-axis-shift-margin-end,\n --ds-cross-axis-shift-margin-block-start, or --ds-cross-axis-shift-margin-block-end). The\n side matches the popover's anchored cross-axis edge per align. Only\n one of the four properties is non-zero at a time; useAnchorPosition\n picks it. See notes/architecture/positioning.md for details. */\n/* Single-axis centered (align: center) */\n@position-try --ds-arrow-block-start {\n position-area: block-start;\n margin: 0;\n margin-block-end: var(--ds-arrow-size, 8px);\n margin-inline-start: var(--ds-cross-axis-shift-margin-start, 0px);\n}\n@position-try --ds-arrow-block-end {\n position-area: block-end;\n margin: 0;\n margin-block-start: var(--ds-arrow-size, 8px);\n margin-inline-start: var(--ds-cross-axis-shift-margin-start, 0px);\n}\n@position-try --ds-arrow-inline-start {\n position-area: inline-start;\n margin: 0;\n margin-inline-end: var(--ds-arrow-size, 8px);\n margin-block-start: var(--ds-cross-axis-shift-margin-block-start, 0px);\n}\n@position-try --ds-arrow-inline-end {\n position-area: inline-end;\n margin: 0;\n margin-inline-start: var(--ds-arrow-size, 8px);\n margin-block-start: var(--ds-cross-axis-shift-margin-block-start, 0px);\n}\n\n/* Block edge + inline span (align: start uses span-inline-end; align: end uses span-inline-start) */\n@position-try --ds-arrow-block-start-span-inline-start {\n position-area: block-start span-inline-start;\n margin: 0;\n margin-block-end: var(--ds-arrow-size, 8px);\n margin-inline-end: var(--ds-cross-axis-shift-margin-end, 0px);\n}\n@position-try --ds-arrow-block-start-span-inline-end {\n position-area: block-start span-inline-end;\n margin: 0;\n margin-block-end: var(--ds-arrow-size, 8px);\n margin-inline-start: var(--ds-cross-axis-shift-margin-start, 0px);\n}\n@position-try --ds-arrow-block-end-span-inline-start {\n position-area: block-end span-inline-start;\n margin: 0;\n margin-block-start: var(--ds-arrow-size, 8px);\n margin-inline-end: var(--ds-cross-axis-shift-margin-end, 0px);\n}\n@position-try --ds-arrow-block-end-span-inline-end {\n position-area: block-end span-inline-end;\n margin: 0;\n margin-block-start: var(--ds-arrow-size, 8px);\n margin-inline-start: var(--ds-cross-axis-shift-margin-start, 0px);\n}\n\n/* Inline edge + block span (align: start uses span-block-end; align: end uses span-block-start) */\n@position-try --ds-arrow-inline-start-span-block-start {\n position-area: inline-start span-block-start;\n margin: 0;\n margin-inline-end: var(--ds-arrow-size, 8px);\n margin-block-end: var(--ds-cross-axis-shift-margin-block-end, 0px);\n}\n@position-try --ds-arrow-inline-start-span-block-end {\n position-area: inline-start span-block-end;\n margin: 0;\n margin-inline-end: var(--ds-arrow-size, 8px);\n margin-block-start: var(--ds-cross-axis-shift-margin-block-start, 0px);\n}\n@position-try --ds-arrow-inline-end-span-block-start {\n position-area: inline-end span-block-start;\n margin: 0;\n margin-inline-start: var(--ds-arrow-size, 8px);\n margin-block-end: var(--ds-cross-axis-shift-margin-block-end, 0px);\n}\n@position-try --ds-arrow-inline-end-span-block-end {\n position-area: inline-end span-block-end;\n margin: 0;\n margin-inline-start: var(--ds-arrow-size, 8px);\n margin-block-start: var(--ds-cross-axis-shift-margin-block-start, 0px);\n}\n";
|
|
31
|
+
|
|
32
|
+
// ── Placement utilities ──
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Converts a `position-area` value to a CSS rule name by replacing spaces with hyphens
|
|
36
|
+
* and prepending `--ds-arrow-`.
|
|
37
|
+
*
|
|
38
|
+
* @example positionAreaToRuleName('block-end span-inline-start') → '--ds-arrow-block-end-span-inline-start'
|
|
39
|
+
*/
|
|
40
|
+
function positionAreaToRuleName(_ref) {
|
|
41
|
+
var positionArea = _ref.positionArea;
|
|
42
|
+
return "--ds-arrow-".concat(positionArea.replace(/ /g, '-'));
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Returns `position-try-fallbacks` using named `@position-try` rules
|
|
47
|
+
* that change both `position-area` and `margin` when flipping.
|
|
48
|
+
*
|
|
49
|
+
* This is required for the arrow technique because built-in keywords
|
|
50
|
+
* (`flip-block`, `flip-inline`) only flip `position-area` - they do
|
|
51
|
+
* not update the margin direction needed to reveal the correct arrow.
|
|
52
|
+
*/
|
|
53
|
+
function getTryFallbacks(_ref2) {
|
|
54
|
+
var placement = _ref2.placement;
|
|
55
|
+
var _getPlacement = (0, _resolvePlacement.getPlacement)({
|
|
56
|
+
placement: placement
|
|
57
|
+
}),
|
|
58
|
+
axis = _getPlacement.axis,
|
|
59
|
+
edge = _getPlacement.edge,
|
|
60
|
+
align = _getPlacement.align;
|
|
61
|
+
if (align === 'center') {
|
|
62
|
+
// Single-axis: only flip the edge
|
|
63
|
+
var _flippedEdge = edge === 'start' ? 'end' : 'start';
|
|
64
|
+
return positionAreaToRuleName({
|
|
65
|
+
positionArea: (0, _useAnchorPosition.placementToPositionArea)({
|
|
66
|
+
placement: {
|
|
67
|
+
axis: axis,
|
|
68
|
+
edge: _flippedEdge
|
|
69
|
+
}
|
|
70
|
+
})
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Compound placement: try flipping edge, alignment, and both
|
|
75
|
+
var flippedEdge = edge === 'start' ? 'end' : 'start';
|
|
76
|
+
var flippedAlign = align === 'start' ? 'end' : 'start';
|
|
77
|
+
return [positionAreaToRuleName({
|
|
78
|
+
positionArea: (0, _useAnchorPosition.placementToPositionArea)({
|
|
79
|
+
placement: {
|
|
80
|
+
axis: axis,
|
|
81
|
+
edge: flippedEdge,
|
|
82
|
+
align: align
|
|
83
|
+
}
|
|
84
|
+
})
|
|
85
|
+
}), positionAreaToRuleName({
|
|
86
|
+
positionArea: (0, _useAnchorPosition.placementToPositionArea)({
|
|
87
|
+
placement: {
|
|
88
|
+
axis: axis,
|
|
89
|
+
edge: edge,
|
|
90
|
+
align: flippedAlign
|
|
91
|
+
}
|
|
92
|
+
})
|
|
93
|
+
}), positionAreaToRuleName({
|
|
94
|
+
positionArea: (0, _useAnchorPosition.placementToPositionArea)({
|
|
95
|
+
placement: {
|
|
96
|
+
axis: axis,
|
|
97
|
+
edge: flippedEdge,
|
|
98
|
+
align: flippedAlign
|
|
99
|
+
}
|
|
100
|
+
})
|
|
101
|
+
})].join(', ');
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Creates an arrow preset for popover content.
|
|
106
|
+
*
|
|
107
|
+
* The returned object is passed to `PopoverContent`'s `arrow` prop.
|
|
108
|
+
* It carries the CSS string and fallback logic so that consumers who
|
|
109
|
+
* do not use arrows pay no bundle cost.
|
|
110
|
+
*
|
|
111
|
+
* The arrows inherit their background from the popover element.
|
|
112
|
+
* When `arrow` is active, `PopoverContent` does not reset `background`
|
|
113
|
+
* to `transparent`, allowing the UA default (`canvas`) or a consumer-set
|
|
114
|
+
* background to show through.
|
|
115
|
+
*
|
|
116
|
+
* @example
|
|
117
|
+
* ```tsx
|
|
118
|
+
* import { arrow } from '@atlaskit/top-layer/arrow';
|
|
119
|
+
*
|
|
120
|
+
* const myArrow = arrow();
|
|
121
|
+
*
|
|
122
|
+
* <Popup.Content arrow={myArrow} />
|
|
123
|
+
* ```
|
|
124
|
+
*/
|
|
125
|
+
var arrow = exports.arrow = (0, _once.default)(function () {
|
|
126
|
+
return {
|
|
127
|
+
name: 'arrow',
|
|
128
|
+
css: ARROW_CSS,
|
|
129
|
+
getTryFallbacks: getTryFallbacks
|
|
130
|
+
};
|
|
131
|
+
});
|
|
@@ -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); }
|
|
@@ -23,7 +25,7 @@ var styles = {
|
|
|
23
25
|
};
|
|
24
26
|
|
|
25
27
|
/**
|
|
26
|
-
* Low-level `<dialog>` primitive. No visual opinions
|
|
28
|
+
* Low-level `<dialog>` primitive. No visual opinions - no width, height,
|
|
27
29
|
* background, border-radius, or layout. Consumers provide their own styling.
|
|
28
30
|
*
|
|
29
31
|
* Visibility is controlled declaratively via `isOpen`:
|
|
@@ -34,6 +36,10 @@ var styles = {
|
|
|
34
36
|
*
|
|
35
37
|
* Close flow: we never call `dialog.close()` from event handlers. We always call
|
|
36
38
|
* `onClose`; the consumer decides whether to set `isOpen={false}`.
|
|
39
|
+
*
|
|
40
|
+
* Accessibility: render at least one focusable element (typically a close
|
|
41
|
+
* button) when `isOpen` becomes `true`. Tab is always trapped inside the
|
|
42
|
+
* dialog, so keyboard users need somewhere to land.
|
|
37
43
|
*/
|
|
38
44
|
var Dialog = exports.Dialog = /*#__PURE__*/(0, _react.forwardRef)(function Dialog(_ref, ref) {
|
|
39
45
|
var children = _ref.children,
|
|
@@ -71,6 +77,16 @@ var Dialog = exports.Dialog = /*#__PURE__*/(0, _react.forwardRef)(function Dialo
|
|
|
71
77
|
role: 'dialog'
|
|
72
78
|
});
|
|
73
79
|
|
|
80
|
+
// ── Open layer observer registration ──
|
|
81
|
+
// Notifies the open layer observer so app-coordination features
|
|
82
|
+
// (open-count subscriptions) work with top-layer dialogs.
|
|
83
|
+
(0, _openLayerObserver.useNotifyOpenLayerObserver)({
|
|
84
|
+
type: 'modal',
|
|
85
|
+
isOpen: isOpen,
|
|
86
|
+
// No-op: no current use case for programmatic close via OpenLayerObserver.
|
|
87
|
+
onClose: _noop.default
|
|
88
|
+
});
|
|
89
|
+
|
|
74
90
|
// Show/hide the dialog in response to isOpen changes.
|
|
75
91
|
(0, _react.useLayoutEffect)(function () {
|
|
76
92
|
var dialog = ownRef.current;
|
|
@@ -129,18 +145,19 @@ var Dialog = exports.Dialog = /*#__PURE__*/(0, _react.forwardRef)(function Dialo
|
|
|
129
145
|
return /*#__PURE__*/_react.default.createElement("dialog", (0, _extends2.default)({
|
|
130
146
|
ref: combinedRef,
|
|
131
147
|
id: dialogId
|
|
132
|
-
//
|
|
133
|
-
//
|
|
134
|
-
// it
|
|
148
|
+
// `aria-modal` is intentionally NOT set: native `<dialog>.showModal()`
|
|
149
|
+
// already conveys modal semantics to assistive tech, and double-
|
|
150
|
+
// declaring it forecloses non-modal use cases (consumers calling
|
|
151
|
+
// `.show()` would still appear modal). Modern AT (NVDA / JAWS /
|
|
152
|
+
// VoiceOver) infer modality from the platform accessibility API.
|
|
135
153
|
,
|
|
136
|
-
"aria-modal": "true",
|
|
137
154
|
"aria-label": label,
|
|
138
155
|
"aria-labelledby": label ? undefined : labelledBy,
|
|
139
156
|
// eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop
|
|
140
157
|
style: style,
|
|
141
158
|
onCancel: handleCancel,
|
|
142
159
|
"data-testid": testId
|
|
143
|
-
}, preset ? (0, _defineProperty2.default)({}, "data-ds-".concat(preset.name), '') : undefined, {
|
|
160
|
+
}, preset ? (0, _defineProperty2.default)({}, "data-ds-dialog-".concat(preset.name), '') : undefined, {
|
|
144
161
|
className: (0, _runtime.ax)([styles.dialog])
|
|
145
162
|
}), shouldHideBackdrop &&
|
|
146
163
|
/*#__PURE__*/
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
Object.defineProperty(exports, "createCloseEvent", {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: function get() {
|
|
9
|
+
return _createCloseEvent.createCloseEvent;
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
var _createCloseEvent = require("../../dialog/create-close-event");
|
|
@@ -3,16 +3,17 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
Object.defineProperty(exports, "
|
|
6
|
+
Object.defineProperty(exports, "LEGACY_PLACEMENTS", {
|
|
7
7
|
enumerable: true,
|
|
8
8
|
get: function get() {
|
|
9
|
-
return
|
|
9
|
+
return _legacyPlacements.LEGACY_PLACEMENTS;
|
|
10
10
|
}
|
|
11
11
|
});
|
|
12
|
-
Object.defineProperty(exports, "
|
|
12
|
+
Object.defineProperty(exports, "fromLegacyPlacement", {
|
|
13
13
|
enumerable: true,
|
|
14
14
|
get: function get() {
|
|
15
|
-
return _placementMap.
|
|
15
|
+
return _placementMap.fromLegacyPlacement;
|
|
16
16
|
}
|
|
17
17
|
});
|
|
18
|
-
var _placementMap = require("../placement-map");
|
|
18
|
+
var _placementMap = require("../placement-map");
|
|
19
|
+
var _legacyPlacements = require("../placement-map/legacy-placements");
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
Object.defineProperty(exports, "createPopoverCloseEvent", {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: function get() {
|
|
9
|
+
return _createCloseEvent.createPopoverCloseEvent;
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
var _createCloseEvent = require("../../popover/create-close-event");
|
package/dist/cjs/focus/focus.js
CHANGED
|
@@ -6,6 +6,8 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
exports.getFirstFocusable = getFirstFocusable;
|
|
7
7
|
exports.getLastFocusable = getLastFocusable;
|
|
8
8
|
exports.getNextFocusable = getNextFocusable;
|
|
9
|
+
exports.isNestedLayerFocused = isNestedLayerFocused;
|
|
10
|
+
var _browserApis = require("@atlaskit/browser-apis");
|
|
9
11
|
/**
|
|
10
12
|
* Focusable element selectors and navigation helpers.
|
|
11
13
|
*
|
|
@@ -25,9 +27,54 @@ var selectors = function () {
|
|
|
25
27
|
var focusable = ["a[href]".concat(not), "area[href]".concat(not), "input".concat(notDisabled, ":not([type=\"hidden\"])"), "select".concat(notDisabled), "textarea".concat(notDisabled), "button".concat(notDisabled), "iframe".concat(not), "audio[controls]".concat(not), "video[controls]".concat(not), "[contenteditable]:not([contenteditable=\"false\"])".concat(not), "[tabindex]".concat(notDisabled).concat(not)];
|
|
26
28
|
return {
|
|
27
29
|
focusable: focusable.join(','),
|
|
28
|
-
|
|
30
|
+
// Build the `:focus` selector
|
|
31
|
+
focused: focusable.map(function (selector) {
|
|
32
|
+
return "".concat(selector, ":focus");
|
|
33
|
+
}).join(',')
|
|
29
34
|
};
|
|
30
35
|
}();
|
|
36
|
+
var topLayerSelector = '[popover], dialog, [role="dialog"], [role="alertdialog"]';
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Returns true when `element` and `container` resolve to the same nearest
|
|
40
|
+
* top-layer host (or both resolve to `null`, meaning the document layer).
|
|
41
|
+
*/
|
|
42
|
+
function isInSameLayer(_ref) {
|
|
43
|
+
var element = _ref.element,
|
|
44
|
+
container = _ref.container;
|
|
45
|
+
var elementLayer = element.closest(topLayerSelector);
|
|
46
|
+
var containerLayer = container.closest(topLayerSelector);
|
|
47
|
+
// Both elements are in the "document" layer
|
|
48
|
+
if (!elementLayer && !containerLayer) {
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
return elementLayer === containerLayer;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Returns `true` when `document.activeElement` is inside a nested top-layer
|
|
56
|
+
* descendant of `container` (a `[popover]`, `<dialog>`, `[role="dialog"]` or
|
|
57
|
+
* `[role="alertdialog"]` that is itself a descendant of `container`).
|
|
58
|
+
*/
|
|
59
|
+
function isNestedLayerFocused(_ref2) {
|
|
60
|
+
var _getDocument;
|
|
61
|
+
var container = _ref2.container;
|
|
62
|
+
var focused = (_getDocument = (0, _browserApis.getDocument)()) === null || _getDocument === void 0 ? void 0 : _getDocument.activeElement;
|
|
63
|
+
if (!(focused instanceof HTMLElement)) {
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Cannot be in a nested layer if it is not in the container
|
|
68
|
+
if (!container.contains(focused)) {
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// If not in the same layer, must be in a nested layer
|
|
73
|
+
return !isInSameLayer({
|
|
74
|
+
element: focused,
|
|
75
|
+
container: container
|
|
76
|
+
});
|
|
77
|
+
}
|
|
31
78
|
|
|
32
79
|
/**
|
|
33
80
|
* An optional callback to restrict which focusable elements are included.
|
|
@@ -37,17 +84,21 @@ var selectors = function () {
|
|
|
37
84
|
/**
|
|
38
85
|
* Returns all focusable HTMLElements within the container, optionally filtered.
|
|
39
86
|
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
* is
|
|
44
|
-
* assumption changes, this would need to be scoped to the current layer.
|
|
87
|
+
* Focusables that belong to a nested top-layer scope (a `[popover]` or
|
|
88
|
+
* `<dialog>` descendant of the container) are excluded - those elements
|
|
89
|
+
* are owned by the inner layer's focus management. The container itself
|
|
90
|
+
* is allowed to be a popover/dialog; only nested ones are filtered.
|
|
45
91
|
*/
|
|
46
|
-
function getFocusables(
|
|
47
|
-
var container =
|
|
48
|
-
filter =
|
|
92
|
+
function getFocusables(_ref3) {
|
|
93
|
+
var container = _ref3.container,
|
|
94
|
+
filter = _ref3.filter;
|
|
49
95
|
return Array.from(container.querySelectorAll(selectors.focusable)).filter(function (element) {
|
|
50
96
|
return element instanceof HTMLElement;
|
|
97
|
+
}).filter(function (element) {
|
|
98
|
+
return isInSameLayer({
|
|
99
|
+
element: element,
|
|
100
|
+
container: container
|
|
101
|
+
});
|
|
51
102
|
}).filter(function (element) {
|
|
52
103
|
return !filter || filter(element, container);
|
|
53
104
|
});
|
|
@@ -56,9 +107,10 @@ function getFocusables(_ref) {
|
|
|
56
107
|
/**
|
|
57
108
|
* Returns the first focusable element within the container.
|
|
58
109
|
*/
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
110
|
+
// eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports
|
|
111
|
+
function getFirstFocusable(_ref4) {
|
|
112
|
+
var container = _ref4.container,
|
|
113
|
+
filter = _ref4.filter;
|
|
62
114
|
var items = getFocusables({
|
|
63
115
|
container: container,
|
|
64
116
|
filter: filter
|
|
@@ -69,9 +121,10 @@ function getFirstFocusable(_ref2) {
|
|
|
69
121
|
/**
|
|
70
122
|
* Returns the last focusable element within the container.
|
|
71
123
|
*/
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
124
|
+
// eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports
|
|
125
|
+
function getLastFocusable(_ref5) {
|
|
126
|
+
var container = _ref5.container,
|
|
127
|
+
filter = _ref5.filter;
|
|
75
128
|
var items = getFocusables({
|
|
76
129
|
container: container,
|
|
77
130
|
filter: filter
|
|
@@ -86,11 +139,12 @@ function getLastFocusable(_ref3) {
|
|
|
86
139
|
* Returns `null` if there is no focused element within the container or if
|
|
87
140
|
* the focused element is not in the list of focusable elements.
|
|
88
141
|
*/
|
|
89
|
-
|
|
142
|
+
// eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports
|
|
143
|
+
function getNextFocusable(_ref6) {
|
|
90
144
|
var _all$nextIndex;
|
|
91
|
-
var container =
|
|
92
|
-
direction =
|
|
93
|
-
filter =
|
|
145
|
+
var container = _ref6.container,
|
|
146
|
+
direction = _ref6.direction,
|
|
147
|
+
filter = _ref6.filter;
|
|
94
148
|
var all = getFocusables({
|
|
95
149
|
container: container,
|
|
96
150
|
filter: filter
|
package/dist/cjs/index.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
// This file exists for module resolution purposes.
|
|
2
2
|
// Not exporting anything from the root entry point.
|
|
3
|
-
// Please use individual entry points for minimum bundle size:
|
|
4
3
|
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
4
|
+
// Use individual entry points for minimum bundle size - the full list of
|
|
5
|
+
// available subpaths is the `"exports"` field in this package's
|
|
6
|
+
// `package.json`. The README documents the most common ones.
|
|
8
7
|
"use strict";
|