@atlaskit/top-layer 0.12.2 → 0.13.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 +16 -0
- package/dist/cjs/entry-points/focus.js +6 -4
- package/dist/cjs/entry-points/use-anchor-position-at-point.js +12 -0
- package/dist/cjs/focus/get-first-focusable.js +19 -0
- package/dist/cjs/focus/get-focusables.js +30 -0
- package/dist/cjs/focus/get-last-focusable.js +19 -0
- package/dist/cjs/focus/get-next-focusable.js +43 -0
- package/dist/cjs/focus/is-in-same-layer.js +23 -0
- package/dist/cjs/focus/is-nested-layer-focused.js +32 -0
- package/dist/cjs/focus/selectors.js +19 -0
- package/dist/cjs/focus/types.js +1 -0
- package/dist/cjs/internal/role-to-aria-has-popup.js +37 -0
- package/dist/cjs/internal/role-types.js +1 -97
- package/dist/cjs/internal/should-focus-into-popover.js +19 -0
- package/dist/cjs/internal/use-anchor-position-at-point.js +127 -0
- package/dist/cjs/internal/use-anchor-position.js +7 -3
- package/dist/cjs/internal/use-focus-wrap.js +8 -5
- package/dist/cjs/internal/use-initial-focus.js +4 -4
- package/dist/cjs/placement-map/index.js +2 -2
- package/dist/cjs/placement-map/legacy-placements.js +2 -101
- package/dist/cjs/placement-map/placement-mapping.js +103 -0
- package/dist/cjs/popup/popup-content.js +4 -3
- package/dist/cjs/use-arrow-navigation/use-arrow-navigation.js +7 -5
- package/dist/es2019/entry-points/focus.js +3 -1
- package/dist/es2019/entry-points/use-anchor-position-at-point.js +1 -0
- package/dist/es2019/focus/get-first-focusable.js +14 -0
- package/dist/es2019/focus/get-focusables.js +19 -0
- package/dist/es2019/focus/get-last-focusable.js +14 -0
- package/dist/es2019/focus/get-next-focusable.js +38 -0
- package/dist/es2019/focus/is-in-same-layer.js +18 -0
- package/dist/es2019/focus/is-nested-layer-focused.js +28 -0
- package/dist/es2019/focus/selectors.js +11 -0
- package/dist/es2019/focus/types.js +0 -0
- package/dist/es2019/internal/role-to-aria-has-popup.js +32 -0
- package/dist/es2019/internal/role-types.js +0 -92
- package/dist/es2019/internal/should-focus-into-popover.js +14 -0
- package/dist/es2019/internal/use-anchor-position-at-point.js +122 -0
- package/dist/es2019/internal/use-anchor-position.js +6 -3
- package/dist/es2019/internal/use-focus-wrap.js +4 -1
- package/dist/es2019/internal/use-initial-focus.js +1 -1
- package/dist/es2019/placement-map/index.js +1 -1
- package/dist/es2019/placement-map/legacy-placements.js +1 -100
- package/dist/es2019/placement-map/placement-mapping.js +97 -0
- package/dist/es2019/popup/popup-content.js +2 -1
- package/dist/es2019/use-arrow-navigation/use-arrow-navigation.js +3 -1
- package/dist/esm/entry-points/focus.js +3 -1
- package/dist/esm/entry-points/use-anchor-position-at-point.js +1 -0
- package/dist/esm/focus/get-first-focusable.js +13 -0
- package/dist/esm/focus/get-focusables.js +24 -0
- package/dist/esm/focus/get-last-focusable.js +13 -0
- package/dist/esm/focus/get-next-focusable.js +37 -0
- package/dist/esm/focus/is-in-same-layer.js +17 -0
- package/dist/esm/focus/is-nested-layer-focused.js +27 -0
- package/dist/esm/focus/selectors.js +13 -0
- package/dist/esm/focus/types.js +0 -0
- package/dist/esm/internal/role-to-aria-has-popup.js +31 -0
- package/dist/esm/internal/role-types.js +0 -90
- package/dist/esm/internal/should-focus-into-popover.js +13 -0
- package/dist/esm/internal/use-anchor-position-at-point.js +122 -0
- package/dist/esm/internal/use-anchor-position.js +7 -3
- package/dist/esm/internal/use-focus-wrap.js +4 -1
- package/dist/esm/internal/use-initial-focus.js +1 -1
- package/dist/esm/placement-map/index.js +1 -1
- package/dist/esm/placement-map/legacy-placements.js +1 -100
- package/dist/esm/placement-map/placement-mapping.js +97 -0
- package/dist/esm/popup/popup-content.js +2 -1
- package/dist/esm/use-arrow-navigation/use-arrow-navigation.js +3 -1
- package/dist/types/entry-points/focus.d.ts +4 -2
- package/dist/types/entry-points/use-anchor-position-at-point.d.ts +1 -0
- package/dist/types/focus/get-first-focusable.d.ts +8 -0
- package/dist/types/focus/get-focusables.d.ts +13 -0
- package/dist/types/focus/get-last-focusable.d.ts +8 -0
- package/dist/types/focus/get-next-focusable.d.ts +13 -0
- package/dist/types/focus/is-in-same-layer.d.ts +8 -0
- package/dist/types/focus/is-nested-layer-focused.d.ts +8 -0
- package/dist/types/focus/selectors.d.ts +4 -0
- package/dist/types/focus/types.d.ts +5 -0
- package/dist/types/internal/role-to-aria-has-popup.d.ts +13 -0
- package/dist/types/internal/role-types.d.ts +0 -19
- package/dist/types/internal/should-focus-into-popover.d.ts +8 -0
- package/dist/types/internal/use-anchor-position-at-point.d.ts +62 -0
- package/dist/types/internal/use-anchor-position.d.ts +6 -1
- package/dist/types/placement-map/index.d.ts +1 -1
- package/dist/types/placement-map/legacy-placements.d.ts +0 -12
- package/dist/types/placement-map/placement-mapping.d.ts +13 -0
- package/dist/types/use-arrow-navigation/use-arrow-navigation.d.ts +1 -1
- package/dist/types-ts4.5/entry-points/focus.d.ts +4 -2
- package/dist/types-ts4.5/entry-points/use-anchor-position-at-point.d.ts +1 -0
- package/dist/types-ts4.5/focus/get-first-focusable.d.ts +8 -0
- package/dist/types-ts4.5/focus/get-focusables.d.ts +13 -0
- package/dist/types-ts4.5/focus/get-last-focusable.d.ts +8 -0
- package/dist/types-ts4.5/focus/get-next-focusable.d.ts +13 -0
- package/dist/types-ts4.5/focus/is-in-same-layer.d.ts +8 -0
- package/dist/types-ts4.5/focus/is-nested-layer-focused.d.ts +8 -0
- package/dist/types-ts4.5/focus/selectors.d.ts +4 -0
- package/dist/types-ts4.5/focus/types.d.ts +5 -0
- package/dist/types-ts4.5/internal/role-to-aria-has-popup.d.ts +13 -0
- package/dist/types-ts4.5/internal/role-types.d.ts +0 -19
- package/dist/types-ts4.5/internal/should-focus-into-popover.d.ts +8 -0
- package/dist/types-ts4.5/internal/use-anchor-position-at-point.d.ts +62 -0
- package/dist/types-ts4.5/internal/use-anchor-position.d.ts +6 -1
- package/dist/types-ts4.5/placement-map/index.d.ts +1 -1
- package/dist/types-ts4.5/placement-map/legacy-placements.d.ts +0 -12
- package/dist/types-ts4.5/placement-map/placement-mapping.d.ts +13 -0
- package/dist/types-ts4.5/use-arrow-navigation/use-arrow-navigation.d.ts +1 -1
- package/package.json +1 -1
- package/use-anchor-position-at-point/package.json +17 -0
- package/dist/cjs/focus/focus.js +0 -169
- package/dist/cjs/focus/index.js +0 -24
- package/dist/es2019/focus/focus.js +0 -158
- package/dist/es2019/focus/index.js +0 -1
- package/dist/esm/focus/focus.js +0 -160
- package/dist/esm/focus/index.js +0 -1
- package/dist/types/focus/focus.d.ts +0 -50
- package/dist/types/focus/index.d.ts +0 -2
- package/dist/types-ts4.5/focus/focus.d.ts +0 -50
- package/dist/types-ts4.5/focus/index.d.ts +0 -2
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { type RefObject } from 'react';
|
|
2
|
+
import { type TPlacementOptions } from './resolve-placement';
|
|
3
|
+
/**
|
|
4
|
+
* A point in viewport coordinates (CSS pixels) at which the synthetic
|
|
5
|
+
* anchor should be placed.
|
|
6
|
+
*
|
|
7
|
+
* Axis-named (`x`/`y`) rather than edge-named (`left`/`top`) so the
|
|
8
|
+
* shape is unambiguous in RTL writing modes — there is no ambiguity
|
|
9
|
+
* about whether a coordinate is logical (`inline-start`/`block-start`)
|
|
10
|
+
* or physical (`left`/`top`). Viewport coordinates are always
|
|
11
|
+
* physical, so we name them with the physical axis labels.
|
|
12
|
+
*/
|
|
13
|
+
export type TAnchorPoint = {
|
|
14
|
+
x: number;
|
|
15
|
+
y: number;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Positions a popover at a consumer-supplied viewport coordinate using a
|
|
19
|
+
* hidden synthetic anchor.
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```tsx
|
|
23
|
+
* function PointPositionedPopover({ popoverRef, placement, mousePos }) {
|
|
24
|
+
* useAnchorPositionAtPoint({
|
|
25
|
+
* popoverRef,
|
|
26
|
+
* placement,
|
|
27
|
+
* isEnabled: Boolean(mousePos),
|
|
28
|
+
* getPoint: () => {
|
|
29
|
+
* if (!mousePos) return null;
|
|
30
|
+
* return { x: mousePos.clientX, y: mousePos.clientY };
|
|
31
|
+
* },
|
|
32
|
+
* });
|
|
33
|
+
* return <Popover ref={popoverRef}>...</Popover>;
|
|
34
|
+
* }
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
export declare function useAnchorPositionAtPoint({ popoverRef, placement, getPoint, isEnabled, }: {
|
|
38
|
+
/**
|
|
39
|
+
* Element being positioned. Passed to `useAnchorPosition`.
|
|
40
|
+
*/
|
|
41
|
+
popoverRef: RefObject<HTMLElement | null>;
|
|
42
|
+
/**
|
|
43
|
+
* Where the popover sits relative to the anchor.
|
|
44
|
+
*/
|
|
45
|
+
placement: TPlacementOptions;
|
|
46
|
+
/**
|
|
47
|
+
* Lazy callback returning the viewport coordinate to anchor at.
|
|
48
|
+
* Called once per activation (every `isEnabled: false → true`
|
|
49
|
+
* transition); the result is latched and not re-read.
|
|
50
|
+
*
|
|
51
|
+
* Return `null` to signal "no point yet" — the hook stays in a
|
|
52
|
+
* no-DOM state so another positioning strategy can own the popover.
|
|
53
|
+
*
|
|
54
|
+
* Read from a ref, so it does not need to be memoized.
|
|
55
|
+
*/
|
|
56
|
+
getPoint: () => TAnchorPoint | null;
|
|
57
|
+
/**
|
|
58
|
+
* When `false`, the hook is a no-op: no synthetic anchor is created
|
|
59
|
+
* and no positioning is applied. Defaults to `true`.
|
|
60
|
+
*/
|
|
61
|
+
isEnabled?: boolean;
|
|
62
|
+
}): void;
|
|
@@ -34,7 +34,7 @@ import { type TPlacementOptions } from '../internal/resolve-placement';
|
|
|
34
34
|
* comparison is used internally so re-runs are skipped when the resolved
|
|
35
35
|
* placement shape is unchanged.
|
|
36
36
|
*/
|
|
37
|
-
export declare function useAnchorPosition({ anchorRef, popoverRef, placement, forceFallbackPositioning, }: {
|
|
37
|
+
export declare function useAnchorPosition({ anchorRef, popoverRef, placement, forceFallbackPositioning, isEnabled, }: {
|
|
38
38
|
/**
|
|
39
39
|
* Element to position relative to.
|
|
40
40
|
*/
|
|
@@ -70,4 +70,9 @@ export declare function useAnchorPosition({ anchorRef, popoverRef, placement, fo
|
|
|
70
70
|
* behavior in any environment, including production.
|
|
71
71
|
*/
|
|
72
72
|
forceFallbackPositioning?: boolean;
|
|
73
|
+
/**
|
|
74
|
+
* When `false`, the hook is a no-op and applies no positioning.
|
|
75
|
+
* Defaults to `true`.
|
|
76
|
+
*/
|
|
77
|
+
isEnabled?: boolean;
|
|
73
78
|
}): void;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type TPlacementOptions } from '../internal/resolve-placement';
|
|
2
|
-
import {
|
|
2
|
+
import type { TLegacyPlacement } from './legacy-placements';
|
|
3
3
|
/**
|
|
4
4
|
* Maps legacy Popper.js placement values to the new object-based
|
|
5
5
|
* `Placement` values used by `@atlaskit/top-layer/popover`.
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { type TPlacementOptions } from '../internal/resolve-placement';
|
|
2
1
|
/**
|
|
3
2
|
* Legacy Popper.js placement values (used by `@atlaskit/popper`,
|
|
4
3
|
* `@atlaskit/popup`, `@atlaskit/tooltip`, etc.). Re-exported from
|
|
@@ -8,14 +7,3 @@ import { type TPlacementOptions } from '../internal/resolve-placement';
|
|
|
8
7
|
*/
|
|
9
8
|
export declare const LEGACY_PLACEMENTS: readonly ["auto", "auto-start", "auto-end", "top", "top-start", "top-center", "top-end", "bottom", "bottom-start", "bottom-center", "bottom-end", "right", "right-start", "right-end", "left", "left-start", "left-end"];
|
|
10
9
|
export type TLegacyPlacement = (typeof LEGACY_PLACEMENTS)[number];
|
|
11
|
-
/**
|
|
12
|
-
* The full mapping record. Internal - use `fromLegacyPlacement` from the
|
|
13
|
-
* public entry-point so the offset-tuple translation is applied consistently.
|
|
14
|
-
*
|
|
15
|
-
* Note: `auto`, `auto-start`, `auto-end` map to `block-end` placements. This
|
|
16
|
-
* is a reduction in expressiveness vs Popper.js (which picked the best
|
|
17
|
-
* placement at runtime). CSS `position-try-fallbacks` flips at the edge but
|
|
18
|
-
* the initial placement is fixed. Migration consumers who relied on Popper's
|
|
19
|
-
* dynamic auto-flip should pick an explicit placement instead.
|
|
20
|
-
*/
|
|
21
|
-
export declare const placementMapping: Record<TLegacyPlacement, TPlacementOptions>;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type TPlacementOptions } from '../internal/resolve-placement';
|
|
2
|
+
import type { TLegacyPlacement } from './legacy-placements';
|
|
3
|
+
/**
|
|
4
|
+
* The full mapping record. Internal - use `fromLegacyPlacement` from the
|
|
5
|
+
* public entry-point so the offset-tuple translation is applied consistently.
|
|
6
|
+
*
|
|
7
|
+
* Note: `auto`, `auto-start`, `auto-end` map to `block-end` placements. This
|
|
8
|
+
* is a reduction in expressiveness vs Popper.js (which picked the best
|
|
9
|
+
* placement at runtime). CSS `position-try-fallbacks` flips at the edge but
|
|
10
|
+
* the initial placement is fixed. Migration consumers who relied on Popper's
|
|
11
|
+
* dynamic auto-flip should pick an explicit placement instead.
|
|
12
|
+
*/
|
|
13
|
+
export declare const placementMapping: Record<TLegacyPlacement, TPlacementOptions>;
|
|
@@ -1,2 +1,4 @@
|
|
|
1
|
-
export {
|
|
2
|
-
export
|
|
1
|
+
export type { TFocusableFilter } from '../focus/types';
|
|
2
|
+
export { getFirstFocusable } from '../focus/get-first-focusable';
|
|
3
|
+
export { getLastFocusable } from '../focus/get-last-focusable';
|
|
4
|
+
export { getNextFocusable } from '../focus/get-next-focusable';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { useAnchorPositionAtPoint, type TAnchorPoint, } from '../internal/use-anchor-position-at-point';
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { TFocusableFilter } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Returns the first focusable element within the container.
|
|
4
|
+
*/
|
|
5
|
+
export declare function getFirstFocusable({ container, filter, }: {
|
|
6
|
+
container: HTMLElement;
|
|
7
|
+
filter?: TFocusableFilter;
|
|
8
|
+
}): HTMLElement | null;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { TFocusableFilter } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Returns all focusable HTMLElements within the container, optionally filtered.
|
|
4
|
+
*
|
|
5
|
+
* Focusables that belong to a nested top-layer scope (a `[popover]` or
|
|
6
|
+
* `<dialog>` descendant of the container) are excluded - those elements
|
|
7
|
+
* are owned by the inner layer's focus management. The container itself
|
|
8
|
+
* is allowed to be a popover/dialog; only nested ones are filtered.
|
|
9
|
+
*/
|
|
10
|
+
export declare function getFocusables({ container, filter, }: {
|
|
11
|
+
container: HTMLElement;
|
|
12
|
+
filter?: TFocusableFilter;
|
|
13
|
+
}): HTMLElement[];
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { TFocusableFilter } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Returns the last focusable element within the container.
|
|
4
|
+
*/
|
|
5
|
+
export declare function getLastFocusable({ container, filter, }: {
|
|
6
|
+
container: HTMLElement;
|
|
7
|
+
filter?: TFocusableFilter;
|
|
8
|
+
}): HTMLElement | null;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns the next focusable element in the given direction relative to the
|
|
3
|
+
* currently focused element within the container. Wraps around at both ends.
|
|
4
|
+
*
|
|
5
|
+
* Returns `null` if there is no focused element within the container or if
|
|
6
|
+
* the focused element is not in the list of focusable elements.
|
|
7
|
+
*/
|
|
8
|
+
import type { TFocusableFilter } from './types';
|
|
9
|
+
export declare function getNextFocusable({ container, direction, filter, }: {
|
|
10
|
+
container: HTMLElement;
|
|
11
|
+
direction: 'forwards' | 'backwards';
|
|
12
|
+
filter?: TFocusableFilter;
|
|
13
|
+
}): HTMLElement | null;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns true when `element` and `container` resolve to the same nearest
|
|
3
|
+
* top-layer host (or both resolve to `null`, meaning the document layer).
|
|
4
|
+
*/
|
|
5
|
+
export declare function isInSameLayer({ element, container, }: {
|
|
6
|
+
element: HTMLElement;
|
|
7
|
+
container: HTMLElement;
|
|
8
|
+
}): boolean;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns `true` when `document.activeElement` is inside a nested top-layer
|
|
3
|
+
* descendant of `container` (a `[popover]`, `<dialog>`, `[role="dialog"]` or
|
|
4
|
+
* `[role="alertdialog"]` that is itself a descendant of `container`).
|
|
5
|
+
*/
|
|
6
|
+
export declare function isNestedLayerFocused({ container }: {
|
|
7
|
+
container: HTMLElement;
|
|
8
|
+
}): boolean;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { TAriaHasPopupValue, TRoleRequiringAccessibleName, TRoleWithImplicitName } from './role-types';
|
|
2
|
+
/**
|
|
3
|
+
* Maps a popover content role to the correct `aria-haspopup` value
|
|
4
|
+
* for its trigger element.
|
|
5
|
+
*
|
|
6
|
+
* Returns `undefined` for roles that are not popups in the ARIA sense
|
|
7
|
+
* (`tooltip`, `note`, `status`, `alert`, `log`). Triggers for those roles
|
|
8
|
+
* should not announce a popup at all - emitting `aria-haspopup="dialog"`
|
|
9
|
+
* on a tooltip trigger would mislead assistive technology.
|
|
10
|
+
*/
|
|
11
|
+
export declare function roleToAriaHasPopup({ role, }: {
|
|
12
|
+
role: TRoleRequiringAccessibleName | TRoleWithImplicitName | undefined;
|
|
13
|
+
}): TAriaHasPopupValue;
|
|
@@ -61,23 +61,4 @@ export type TAriaRoleOptional = ({
|
|
|
61
61
|
} & TAccessibleNameRequired) | ({
|
|
62
62
|
role?: TRoleWithImplicitName;
|
|
63
63
|
} & TAccessibleNameOptional);
|
|
64
|
-
/**
|
|
65
|
-
* Maps a popover content role to the correct `aria-haspopup` value
|
|
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.
|
|
72
|
-
*/
|
|
73
|
-
export declare function roleToAriaHasPopup({ role, }: {
|
|
74
|
-
role: TRoleRequiringAccessibleName | TRoleWithImplicitName | undefined;
|
|
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;
|
|
83
64
|
export {};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { TRoleRequiringAccessibleName, TRoleWithImplicitName } from './role-types';
|
|
2
|
+
/**
|
|
3
|
+
* Returns `true` when the given popover role moves focus into the popover
|
|
4
|
+
* on open, and `false` otherwise (including when `role` is `undefined`).
|
|
5
|
+
*/
|
|
6
|
+
export declare function shouldFocusIntoPopover({ role, }: {
|
|
7
|
+
role: TRoleRequiringAccessibleName | TRoleWithImplicitName | undefined;
|
|
8
|
+
}): boolean;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { type RefObject } from 'react';
|
|
2
|
+
import { type TPlacementOptions } from './resolve-placement';
|
|
3
|
+
/**
|
|
4
|
+
* A point in viewport coordinates (CSS pixels) at which the synthetic
|
|
5
|
+
* anchor should be placed.
|
|
6
|
+
*
|
|
7
|
+
* Axis-named (`x`/`y`) rather than edge-named (`left`/`top`) so the
|
|
8
|
+
* shape is unambiguous in RTL writing modes — there is no ambiguity
|
|
9
|
+
* about whether a coordinate is logical (`inline-start`/`block-start`)
|
|
10
|
+
* or physical (`left`/`top`). Viewport coordinates are always
|
|
11
|
+
* physical, so we name them with the physical axis labels.
|
|
12
|
+
*/
|
|
13
|
+
export type TAnchorPoint = {
|
|
14
|
+
x: number;
|
|
15
|
+
y: number;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Positions a popover at a consumer-supplied viewport coordinate using a
|
|
19
|
+
* hidden synthetic anchor.
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```tsx
|
|
23
|
+
* function PointPositionedPopover({ popoverRef, placement, mousePos }) {
|
|
24
|
+
* useAnchorPositionAtPoint({
|
|
25
|
+
* popoverRef,
|
|
26
|
+
* placement,
|
|
27
|
+
* isEnabled: Boolean(mousePos),
|
|
28
|
+
* getPoint: () => {
|
|
29
|
+
* if (!mousePos) return null;
|
|
30
|
+
* return { x: mousePos.clientX, y: mousePos.clientY };
|
|
31
|
+
* },
|
|
32
|
+
* });
|
|
33
|
+
* return <Popover ref={popoverRef}>...</Popover>;
|
|
34
|
+
* }
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
export declare function useAnchorPositionAtPoint({ popoverRef, placement, getPoint, isEnabled, }: {
|
|
38
|
+
/**
|
|
39
|
+
* Element being positioned. Passed to `useAnchorPosition`.
|
|
40
|
+
*/
|
|
41
|
+
popoverRef: RefObject<HTMLElement | null>;
|
|
42
|
+
/**
|
|
43
|
+
* Where the popover sits relative to the anchor.
|
|
44
|
+
*/
|
|
45
|
+
placement: TPlacementOptions;
|
|
46
|
+
/**
|
|
47
|
+
* Lazy callback returning the viewport coordinate to anchor at.
|
|
48
|
+
* Called once per activation (every `isEnabled: false → true`
|
|
49
|
+
* transition); the result is latched and not re-read.
|
|
50
|
+
*
|
|
51
|
+
* Return `null` to signal "no point yet" — the hook stays in a
|
|
52
|
+
* no-DOM state so another positioning strategy can own the popover.
|
|
53
|
+
*
|
|
54
|
+
* Read from a ref, so it does not need to be memoized.
|
|
55
|
+
*/
|
|
56
|
+
getPoint: () => TAnchorPoint | null;
|
|
57
|
+
/**
|
|
58
|
+
* When `false`, the hook is a no-op: no synthetic anchor is created
|
|
59
|
+
* and no positioning is applied. Defaults to `true`.
|
|
60
|
+
*/
|
|
61
|
+
isEnabled?: boolean;
|
|
62
|
+
}): void;
|
|
@@ -34,7 +34,7 @@ import { type TPlacementOptions } from '../internal/resolve-placement';
|
|
|
34
34
|
* comparison is used internally so re-runs are skipped when the resolved
|
|
35
35
|
* placement shape is unchanged.
|
|
36
36
|
*/
|
|
37
|
-
export declare function useAnchorPosition({ anchorRef, popoverRef, placement, forceFallbackPositioning, }: {
|
|
37
|
+
export declare function useAnchorPosition({ anchorRef, popoverRef, placement, forceFallbackPositioning, isEnabled, }: {
|
|
38
38
|
/**
|
|
39
39
|
* Element to position relative to.
|
|
40
40
|
*/
|
|
@@ -70,4 +70,9 @@ export declare function useAnchorPosition({ anchorRef, popoverRef, placement, fo
|
|
|
70
70
|
* behavior in any environment, including production.
|
|
71
71
|
*/
|
|
72
72
|
forceFallbackPositioning?: boolean;
|
|
73
|
+
/**
|
|
74
|
+
* When `false`, the hook is a no-op and applies no positioning.
|
|
75
|
+
* Defaults to `true`.
|
|
76
|
+
*/
|
|
77
|
+
isEnabled?: boolean;
|
|
73
78
|
}): void;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type TPlacementOptions } from '../internal/resolve-placement';
|
|
2
|
-
import {
|
|
2
|
+
import type { TLegacyPlacement } from './legacy-placements';
|
|
3
3
|
/**
|
|
4
4
|
* Maps legacy Popper.js placement values to the new object-based
|
|
5
5
|
* `Placement` values used by `@atlaskit/top-layer/popover`.
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { type TPlacementOptions } from '../internal/resolve-placement';
|
|
2
1
|
/**
|
|
3
2
|
* Legacy Popper.js placement values (used by `@atlaskit/popper`,
|
|
4
3
|
* `@atlaskit/popup`, `@atlaskit/tooltip`, etc.). Re-exported from
|
|
@@ -26,14 +25,3 @@ export declare const LEGACY_PLACEMENTS: readonly [
|
|
|
26
25
|
"left-end"
|
|
27
26
|
];
|
|
28
27
|
export type TLegacyPlacement = (typeof LEGACY_PLACEMENTS)[number];
|
|
29
|
-
/**
|
|
30
|
-
* The full mapping record. Internal - use `fromLegacyPlacement` from the
|
|
31
|
-
* public entry-point so the offset-tuple translation is applied consistently.
|
|
32
|
-
*
|
|
33
|
-
* Note: `auto`, `auto-start`, `auto-end` map to `block-end` placements. This
|
|
34
|
-
* is a reduction in expressiveness vs Popper.js (which picked the best
|
|
35
|
-
* placement at runtime). CSS `position-try-fallbacks` flips at the edge but
|
|
36
|
-
* the initial placement is fixed. Migration consumers who relied on Popper's
|
|
37
|
-
* dynamic auto-flip should pick an explicit placement instead.
|
|
38
|
-
*/
|
|
39
|
-
export declare const placementMapping: Record<TLegacyPlacement, TPlacementOptions>;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type TPlacementOptions } from '../internal/resolve-placement';
|
|
2
|
+
import type { TLegacyPlacement } from './legacy-placements';
|
|
3
|
+
/**
|
|
4
|
+
* The full mapping record. Internal - use `fromLegacyPlacement` from the
|
|
5
|
+
* public entry-point so the offset-tuple translation is applied consistently.
|
|
6
|
+
*
|
|
7
|
+
* Note: `auto`, `auto-start`, `auto-end` map to `block-end` placements. This
|
|
8
|
+
* is a reduction in expressiveness vs Popper.js (which picked the best
|
|
9
|
+
* placement at runtime). CSS `position-try-fallbacks` flips at the edge but
|
|
10
|
+
* the initial placement is fixed. Migration consumers who relied on Popper's
|
|
11
|
+
* dynamic auto-flip should pick an explicit placement instead.
|
|
12
|
+
*/
|
|
13
|
+
export declare const placementMapping: Record<TLegacyPlacement, TPlacementOptions>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlaskit/top-layer",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.0",
|
|
4
4
|
"description": "Low-level layering primitives based on popover and dialog",
|
|
5
5
|
"homepage": "https://atlassian.design/components/top-layer",
|
|
6
6
|
"repository": "https://bitbucket.org/atlassian/atlassian-frontend-mirror",
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@atlaskit/top-layer/use-anchor-position-at-point",
|
|
3
|
+
"main": "../dist/cjs/entry-points/use-anchor-position-at-point.js",
|
|
4
|
+
"module": "../dist/esm/entry-points/use-anchor-position-at-point.js",
|
|
5
|
+
"module:es2019": "../dist/es2019/entry-points/use-anchor-position-at-point.js",
|
|
6
|
+
"sideEffects": [
|
|
7
|
+
"*.compiled.css"
|
|
8
|
+
],
|
|
9
|
+
"types": "../dist/types/entry-points/use-anchor-position-at-point.d.ts",
|
|
10
|
+
"typesVersions": {
|
|
11
|
+
">=4.5 <5.9": {
|
|
12
|
+
"*": [
|
|
13
|
+
"../dist/types-ts4.5/entry-points/use-anchor-position-at-point.d.ts"
|
|
14
|
+
]
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
package/dist/cjs/focus/focus.js
DELETED
|
@@ -1,169 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.getFirstFocusable = getFirstFocusable;
|
|
7
|
-
exports.getLastFocusable = getLastFocusable;
|
|
8
|
-
exports.getNextFocusable = getNextFocusable;
|
|
9
|
-
exports.isNestedLayerFocused = isNestedLayerFocused;
|
|
10
|
-
var _browserApis = require("@atlaskit/browser-apis");
|
|
11
|
-
/**
|
|
12
|
-
* Focusable element selectors and navigation helpers.
|
|
13
|
-
*
|
|
14
|
-
* Uses CSS selectors to discover focusable elements within a container,
|
|
15
|
-
* avoiding the need for a manual registration system. Disabled elements
|
|
16
|
-
* (both HTML `disabled` attribute and `aria-disabled="true"`) and elements
|
|
17
|
-
* with `tabindex="-1"` are excluded automatically.
|
|
18
|
-
*
|
|
19
|
-
* All public functions accept an optional `filter` callback to further
|
|
20
|
-
* restrict which focusable elements are included.
|
|
21
|
-
*/
|
|
22
|
-
|
|
23
|
-
var selectors = function () {
|
|
24
|
-
// Common exclusion filter applied to every selector.
|
|
25
|
-
var not = ':not([tabindex="-1"]):not([aria-disabled="true"]):not([aria-hidden="true"])';
|
|
26
|
-
var notDisabled = ":not([disabled])".concat(not);
|
|
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)];
|
|
28
|
-
return {
|
|
29
|
-
focusable: focusable.join(','),
|
|
30
|
-
// Build the `:focus` selector
|
|
31
|
-
focused: focusable.map(function (selector) {
|
|
32
|
-
return "".concat(selector, ":focus");
|
|
33
|
-
}).join(',')
|
|
34
|
-
};
|
|
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
|
-
}
|
|
78
|
-
|
|
79
|
-
/**
|
|
80
|
-
* An optional callback to restrict which focusable elements are included.
|
|
81
|
-
* Return `true` to include the element, `false` to skip it.
|
|
82
|
-
*/
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* Returns all focusable HTMLElements within the container, optionally filtered.
|
|
86
|
-
*
|
|
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.
|
|
91
|
-
*/
|
|
92
|
-
function getFocusables(_ref3) {
|
|
93
|
-
var container = _ref3.container,
|
|
94
|
-
filter = _ref3.filter;
|
|
95
|
-
return Array.from(container.querySelectorAll(selectors.focusable)).filter(function (element) {
|
|
96
|
-
return element instanceof HTMLElement;
|
|
97
|
-
}).filter(function (element) {
|
|
98
|
-
return isInSameLayer({
|
|
99
|
-
element: element,
|
|
100
|
-
container: container
|
|
101
|
-
});
|
|
102
|
-
}).filter(function (element) {
|
|
103
|
-
return !filter || filter(element, container);
|
|
104
|
-
});
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
/**
|
|
108
|
-
* Returns the first focusable element within the container.
|
|
109
|
-
*/
|
|
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;
|
|
114
|
-
var items = getFocusables({
|
|
115
|
-
container: container,
|
|
116
|
-
filter: filter
|
|
117
|
-
});
|
|
118
|
-
return items.length > 0 ? items[0] : null;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
/**
|
|
122
|
-
* Returns the last focusable element within the container.
|
|
123
|
-
*/
|
|
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;
|
|
128
|
-
var items = getFocusables({
|
|
129
|
-
container: container,
|
|
130
|
-
filter: filter
|
|
131
|
-
});
|
|
132
|
-
return items.length > 0 ? items[items.length - 1] : null;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
/**
|
|
136
|
-
* Returns the next focusable element in the given direction relative to the
|
|
137
|
-
* currently focused element within the container. Wraps around at both ends.
|
|
138
|
-
*
|
|
139
|
-
* Returns `null` if there is no focused element within the container or if
|
|
140
|
-
* the focused element is not in the list of focusable elements.
|
|
141
|
-
*/
|
|
142
|
-
// eslint-disable-next-line @atlaskit/volt-strict-mode/no-multiple-exports
|
|
143
|
-
function getNextFocusable(_ref6) {
|
|
144
|
-
var _all$nextIndex;
|
|
145
|
-
var container = _ref6.container,
|
|
146
|
-
direction = _ref6.direction,
|
|
147
|
-
filter = _ref6.filter;
|
|
148
|
-
var all = getFocusables({
|
|
149
|
-
container: container,
|
|
150
|
-
filter: filter
|
|
151
|
-
});
|
|
152
|
-
var current = container.querySelector(selectors.focused);
|
|
153
|
-
if (!(current instanceof HTMLElement)) {
|
|
154
|
-
return null;
|
|
155
|
-
}
|
|
156
|
-
var index = all.indexOf(current);
|
|
157
|
-
if (index === -1) {
|
|
158
|
-
return null;
|
|
159
|
-
}
|
|
160
|
-
var nextIndex = function () {
|
|
161
|
-
if (direction === 'forwards') {
|
|
162
|
-
return (index + 1) % all.length;
|
|
163
|
-
}
|
|
164
|
-
var proposed = index - 1;
|
|
165
|
-
// if going into negative numbers, loop back to the last item
|
|
166
|
-
return proposed < 0 ? all.length - 1 : proposed;
|
|
167
|
-
}();
|
|
168
|
-
return (_all$nextIndex = all[nextIndex]) !== null && _all$nextIndex !== void 0 ? _all$nextIndex : null;
|
|
169
|
-
}
|
package/dist/cjs/focus/index.js
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
Object.defineProperty(exports, "getFirstFocusable", {
|
|
7
|
-
enumerable: true,
|
|
8
|
-
get: function get() {
|
|
9
|
-
return _focus.getFirstFocusable;
|
|
10
|
-
}
|
|
11
|
-
});
|
|
12
|
-
Object.defineProperty(exports, "getLastFocusable", {
|
|
13
|
-
enumerable: true,
|
|
14
|
-
get: function get() {
|
|
15
|
-
return _focus.getLastFocusable;
|
|
16
|
-
}
|
|
17
|
-
});
|
|
18
|
-
Object.defineProperty(exports, "getNextFocusable", {
|
|
19
|
-
enumerable: true,
|
|
20
|
-
get: function get() {
|
|
21
|
-
return _focus.getNextFocusable;
|
|
22
|
-
}
|
|
23
|
-
});
|
|
24
|
-
var _focus = require("./focus");
|