@atlaskit/top-layer 0.1.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 +44 -0
- package/README.md +151 -0
- package/animations/package.json +17 -0
- package/arrow/package.json +17 -0
- package/create-close-event/package.json +17 -0
- package/dialog/package.json +17 -0
- package/dialog-scroll-lock/package.json +17 -0
- package/dist/cjs/animations/presets.js +199 -0
- package/dist/cjs/animations/types.js +5 -0
- package/dist/cjs/arrow/index.js +130 -0
- package/dist/cjs/arrow/types.js +5 -0
- package/dist/cjs/dialog/create-close-event.js +39 -0
- package/dist/cjs/dialog/dialog-content.compiled.css +14 -0
- package/dist/cjs/dialog/dialog-content.js +144 -0
- package/dist/cjs/dialog/index.js +19 -0
- package/dist/cjs/dialog/types.js +5 -0
- package/dist/cjs/dialog-scroll-lock/index.js +46 -0
- package/dist/cjs/entry-points/animations.js +36 -0
- package/dist/cjs/entry-points/arrow.js +12 -0
- package/dist/cjs/entry-points/create-close-event.js +19 -0
- package/dist/cjs/entry-points/dialog-scroll-lock.js +12 -0
- package/dist/cjs/entry-points/dialog.js +12 -0
- package/dist/cjs/entry-points/focus.js +24 -0
- package/dist/cjs/entry-points/placement-map.js +18 -0
- package/dist/cjs/entry-points/popover.js +12 -0
- package/dist/cjs/entry-points/popup-surface.js +12 -0
- package/dist/cjs/entry-points/popup.js +12 -0
- package/dist/cjs/entry-points/use-anchor-position.js +12 -0
- package/dist/cjs/entry-points/use-arrow-navigation.js +18 -0
- package/dist/cjs/entry-points/use-simple-light-dismiss.js +12 -0
- package/dist/cjs/focus/focus.js +115 -0
- package/dist/cjs/focus/index.js +24 -0
- package/dist/cjs/index.js +8 -0
- package/dist/cjs/internal/anchor-positioning-fallback.js +154 -0
- package/dist/cjs/internal/combine.js +29 -0
- package/dist/cjs/internal/ensure-preset-styles.js +34 -0
- package/dist/cjs/internal/reduced-motion.js +27 -0
- package/dist/cjs/internal/resolve-placement.js +24 -0
- package/dist/cjs/internal/role-types.js +66 -0
- package/dist/cjs/internal/set-style.js +42 -0
- package/dist/cjs/internal/slot.js +65 -0
- package/dist/cjs/internal/use-anchor-positioning.js +336 -0
- package/dist/cjs/internal/use-animated-visibility.js +169 -0
- package/dist/cjs/internal/use-animation-preset.js +24 -0
- package/dist/cjs/internal/use-focus-wrap.js +94 -0
- package/dist/cjs/internal/use-initial-focus.js +112 -0
- package/dist/cjs/internal/use-preset-styles.js +27 -0
- package/dist/cjs/placement-map/index.js +147 -0
- package/dist/cjs/popover/create-close-event.js +44 -0
- package/dist/cjs/popover/index.js +19 -0
- package/dist/cjs/popover/popover.compiled.css +13 -0
- package/dist/cjs/popover/popover.js +251 -0
- package/dist/cjs/popover/types.js +5 -0
- package/dist/cjs/popup/index.js +37 -0
- package/dist/cjs/popup/popup-content.js +201 -0
- package/dist/cjs/popup/popup-context.js +42 -0
- package/dist/cjs/popup/popup-surface.compiled.css +5 -0
- package/dist/cjs/popup/popup-surface.js +30 -0
- package/dist/cjs/popup/popup-trigger-function.js +74 -0
- package/dist/cjs/popup/popup-trigger.js +82 -0
- package/dist/cjs/popup/popup.js +70 -0
- package/dist/cjs/popup/types.js +5 -0
- package/dist/cjs/use-arrow-navigation/index.js +18 -0
- package/dist/cjs/use-arrow-navigation/use-arrow-navigation.js +245 -0
- package/dist/cjs/use-simple-light-dismiss/index.js +84 -0
- package/dist/es2019/animations/presets.js +375 -0
- package/dist/es2019/animations/types.js +1 -0
- package/dist/es2019/arrow/index.js +249 -0
- package/dist/es2019/arrow/types.js +1 -0
- package/dist/es2019/dialog/create-close-event.js +34 -0
- package/dist/es2019/dialog/dialog-content.compiled.css +14 -0
- package/dist/es2019/dialog/dialog-content.js +138 -0
- package/dist/es2019/dialog/index.js +2 -0
- package/dist/es2019/dialog/types.js +1 -0
- package/dist/es2019/dialog-scroll-lock/index.js +41 -0
- package/dist/es2019/entry-points/animations.js +1 -0
- package/dist/es2019/entry-points/arrow.js +1 -0
- package/dist/es2019/entry-points/create-close-event.js +2 -0
- package/dist/es2019/entry-points/dialog-scroll-lock.js +1 -0
- package/dist/es2019/entry-points/dialog.js +1 -0
- package/dist/es2019/entry-points/focus.js +1 -0
- package/dist/es2019/entry-points/placement-map.js +1 -0
- package/dist/es2019/entry-points/popover.js +1 -0
- package/dist/es2019/entry-points/popup-surface.js +1 -0
- package/dist/es2019/entry-points/popup.js +1 -0
- package/dist/es2019/entry-points/use-anchor-position.js +1 -0
- package/dist/es2019/entry-points/use-arrow-navigation.js +1 -0
- package/dist/es2019/entry-points/use-simple-light-dismiss.js +1 -0
- package/dist/es2019/focus/focus.js +107 -0
- package/dist/es2019/focus/index.js +1 -0
- package/dist/es2019/index.js +7 -0
- package/dist/es2019/internal/anchor-positioning-fallback.js +153 -0
- package/dist/es2019/internal/combine.js +18 -0
- package/dist/es2019/internal/ensure-preset-styles.js +29 -0
- package/dist/es2019/internal/reduced-motion.js +21 -0
- package/dist/es2019/internal/resolve-placement.js +19 -0
- package/dist/es2019/internal/role-types.js +61 -0
- package/dist/es2019/internal/set-style.js +39 -0
- package/dist/es2019/internal/slot.js +57 -0
- package/dist/es2019/internal/use-anchor-positioning.js +330 -0
- package/dist/es2019/internal/use-animated-visibility.js +159 -0
- package/dist/es2019/internal/use-animation-preset.js +18 -0
- package/dist/es2019/internal/use-focus-wrap.js +90 -0
- package/dist/es2019/internal/use-initial-focus.js +109 -0
- package/dist/es2019/internal/use-preset-styles.js +22 -0
- package/dist/es2019/placement-map/index.js +142 -0
- package/dist/es2019/popover/create-close-event.js +39 -0
- package/dist/es2019/popover/index.js +2 -0
- package/dist/es2019/popover/popover.compiled.css +13 -0
- package/dist/es2019/popover/popover.js +240 -0
- package/dist/es2019/popover/types.js +1 -0
- package/dist/es2019/popup/index.js +33 -0
- package/dist/es2019/popup/popup-content.js +192 -0
- package/dist/es2019/popup/popup-context.js +34 -0
- package/dist/es2019/popup/popup-surface.compiled.css +5 -0
- package/dist/es2019/popup/popup-surface.js +24 -0
- package/dist/es2019/popup/popup-trigger-function.js +69 -0
- package/dist/es2019/popup/popup-trigger.js +76 -0
- package/dist/es2019/popup/popup.js +56 -0
- package/dist/es2019/popup/types.js +1 -0
- package/dist/es2019/use-arrow-navigation/index.js +1 -0
- package/dist/es2019/use-arrow-navigation/use-arrow-navigation.js +238 -0
- package/dist/es2019/use-simple-light-dismiss/index.js +79 -0
- package/dist/esm/animations/presets.js +190 -0
- package/dist/esm/animations/types.js +1 -0
- package/dist/esm/arrow/index.js +123 -0
- package/dist/esm/arrow/types.js +1 -0
- package/dist/esm/dialog/create-close-event.js +33 -0
- package/dist/esm/dialog/dialog-content.compiled.css +14 -0
- package/dist/esm/dialog/dialog-content.js +135 -0
- package/dist/esm/dialog/index.js +2 -0
- package/dist/esm/dialog/types.js +1 -0
- package/dist/esm/dialog-scroll-lock/index.js +41 -0
- package/dist/esm/entry-points/animations.js +1 -0
- package/dist/esm/entry-points/arrow.js +1 -0
- package/dist/esm/entry-points/create-close-event.js +2 -0
- package/dist/esm/entry-points/dialog-scroll-lock.js +1 -0
- package/dist/esm/entry-points/dialog.js +1 -0
- package/dist/esm/entry-points/focus.js +1 -0
- package/dist/esm/entry-points/placement-map.js +1 -0
- package/dist/esm/entry-points/popover.js +1 -0
- package/dist/esm/entry-points/popup-surface.js +1 -0
- package/dist/esm/entry-points/popup.js +1 -0
- package/dist/esm/entry-points/use-anchor-position.js +1 -0
- package/dist/esm/entry-points/use-arrow-navigation.js +1 -0
- package/dist/esm/entry-points/use-simple-light-dismiss.js +1 -0
- package/dist/esm/focus/focus.js +107 -0
- package/dist/esm/focus/index.js +1 -0
- package/dist/esm/index.js +7 -0
- package/dist/esm/internal/anchor-positioning-fallback.js +147 -0
- package/dist/esm/internal/combine.js +23 -0
- package/dist/esm/internal/ensure-preset-styles.js +28 -0
- package/dist/esm/internal/reduced-motion.js +21 -0
- package/dist/esm/internal/resolve-placement.js +18 -0
- package/dist/esm/internal/role-types.js +60 -0
- package/dist/esm/internal/set-style.js +36 -0
- package/dist/esm/internal/slot.js +59 -0
- package/dist/esm/internal/use-anchor-positioning.js +323 -0
- package/dist/esm/internal/use-animated-visibility.js +162 -0
- package/dist/esm/internal/use-animation-preset.js +18 -0
- package/dist/esm/internal/use-focus-wrap.js +89 -0
- package/dist/esm/internal/use-initial-focus.js +107 -0
- package/dist/esm/internal/use-preset-styles.js +21 -0
- package/dist/esm/placement-map/index.js +141 -0
- package/dist/esm/popover/create-close-event.js +38 -0
- package/dist/esm/popover/index.js +2 -0
- package/dist/esm/popover/popover.compiled.css +13 -0
- package/dist/esm/popover/popover.js +242 -0
- package/dist/esm/popover/types.js +1 -0
- package/dist/esm/popup/index.js +33 -0
- package/dist/esm/popup/popup-content.js +192 -0
- package/dist/esm/popup/popup-context.js +34 -0
- package/dist/esm/popup/popup-surface.compiled.css +5 -0
- package/dist/esm/popup/popup-surface.js +23 -0
- package/dist/esm/popup/popup-trigger-function.js +69 -0
- package/dist/esm/popup/popup-trigger.js +74 -0
- package/dist/esm/popup/popup.js +61 -0
- package/dist/esm/popup/types.js +1 -0
- package/dist/esm/use-arrow-navigation/index.js +1 -0
- package/dist/esm/use-arrow-navigation/use-arrow-navigation.js +238 -0
- package/dist/esm/use-simple-light-dismiss/index.js +78 -0
- package/dist/types/animations/presets.d.ts +94 -0
- package/dist/types/animations/types.d.ts +42 -0
- package/dist/types/arrow/index.d.ts +24 -0
- package/dist/types/arrow/types.d.ts +29 -0
- package/dist/types/dialog/create-close-event.d.ts +24 -0
- package/dist/types/dialog/dialog-content.d.ts +20 -0
- package/dist/types/dialog/index.d.ts +3 -0
- package/dist/types/dialog/types.d.ts +92 -0
- package/dist/types/dialog-scroll-lock/index.d.ts +24 -0
- package/dist/types/entry-points/animations.d.ts +2 -0
- package/dist/types/entry-points/arrow.d.ts +2 -0
- package/dist/types/entry-points/create-close-event.d.ts +4 -0
- package/dist/types/entry-points/dialog-scroll-lock.d.ts +1 -0
- package/dist/types/entry-points/dialog.d.ts +2 -0
- package/dist/types/entry-points/focus.d.ts +2 -0
- package/dist/types/entry-points/placement-map.d.ts +2 -0
- package/dist/types/entry-points/popover.d.ts +2 -0
- package/dist/types/entry-points/popup-surface.d.ts +2 -0
- package/dist/types/entry-points/popup.d.ts +2 -0
- package/dist/types/entry-points/use-anchor-position.d.ts +1 -0
- package/dist/types/entry-points/use-arrow-navigation.d.ts +2 -0
- package/dist/types/entry-points/use-simple-light-dismiss.d.ts +2 -0
- package/dist/types/focus/focus.d.ts +42 -0
- package/dist/types/focus/index.d.ts +2 -0
- package/dist/types/index.d.ts +0 -0
- package/dist/types/internal/anchor-positioning-fallback.d.ts +24 -0
- package/dist/types/internal/combine.d.ts +14 -0
- package/dist/types/internal/ensure-preset-styles.d.ts +6 -0
- package/dist/types/internal/reduced-motion.d.ts +14 -0
- package/dist/types/internal/resolve-placement.d.ts +16 -0
- package/dist/types/internal/role-types.d.ts +62 -0
- package/dist/types/internal/set-style.d.ts +28 -0
- package/dist/types/internal/slot.d.ts +29 -0
- package/dist/types/internal/use-anchor-positioning.d.ts +95 -0
- package/dist/types/internal/use-animated-visibility.d.ts +74 -0
- package/dist/types/internal/use-animation-preset.d.ts +11 -0
- package/dist/types/internal/use-focus-wrap.d.ts +20 -0
- package/dist/types/internal/use-initial-focus.d.ts +21 -0
- package/dist/types/internal/use-preset-styles.d.ts +15 -0
- package/dist/types/placement-map/index.d.ts +55 -0
- package/dist/types/popover/create-close-event.d.ts +26 -0
- package/dist/types/popover/index.d.ts +3 -0
- package/dist/types/popover/popover.d.ts +22 -0
- package/dist/types/popover/types.d.ts +153 -0
- package/dist/types/popup/index.d.ts +34 -0
- package/dist/types/popup/popup-content.d.ts +14 -0
- package/dist/types/popup/popup-context.d.ts +96 -0
- package/dist/types/popup/popup-surface.d.ts +16 -0
- package/dist/types/popup/popup-trigger-function.d.ts +108 -0
- package/dist/types/popup/popup-trigger.d.ts +23 -0
- package/dist/types/popup/popup.d.ts +14 -0
- package/dist/types/popup/types.d.ts +289 -0
- package/dist/types/use-arrow-navigation/index.d.ts +2 -0
- package/dist/types/use-arrow-navigation/use-arrow-navigation.d.ts +136 -0
- package/dist/types/use-simple-light-dismiss/index.d.ts +45 -0
- package/dist/types-ts4.5/animations/presets.d.ts +94 -0
- package/dist/types-ts4.5/animations/types.d.ts +42 -0
- 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/create-close-event.d.ts +24 -0
- package/dist/types-ts4.5/dialog/dialog-content.d.ts +20 -0
- package/dist/types-ts4.5/dialog/index.d.ts +3 -0
- package/dist/types-ts4.5/dialog/types.d.ts +92 -0
- package/dist/types-ts4.5/dialog-scroll-lock/index.d.ts +24 -0
- package/dist/types-ts4.5/entry-points/animations.d.ts +2 -0
- package/dist/types-ts4.5/entry-points/arrow.d.ts +2 -0
- package/dist/types-ts4.5/entry-points/create-close-event.d.ts +4 -0
- package/dist/types-ts4.5/entry-points/dialog-scroll-lock.d.ts +1 -0
- package/dist/types-ts4.5/entry-points/dialog.d.ts +2 -0
- package/dist/types-ts4.5/entry-points/focus.d.ts +2 -0
- package/dist/types-ts4.5/entry-points/placement-map.d.ts +2 -0
- package/dist/types-ts4.5/entry-points/popover.d.ts +2 -0
- package/dist/types-ts4.5/entry-points/popup-surface.d.ts +2 -0
- package/dist/types-ts4.5/entry-points/popup.d.ts +2 -0
- package/dist/types-ts4.5/entry-points/use-anchor-position.d.ts +1 -0
- package/dist/types-ts4.5/entry-points/use-arrow-navigation.d.ts +2 -0
- package/dist/types-ts4.5/entry-points/use-simple-light-dismiss.d.ts +2 -0
- package/dist/types-ts4.5/focus/focus.d.ts +42 -0
- package/dist/types-ts4.5/focus/index.d.ts +2 -0
- package/dist/types-ts4.5/index.d.ts +0 -0
- package/dist/types-ts4.5/internal/anchor-positioning-fallback.d.ts +24 -0
- package/dist/types-ts4.5/internal/combine.d.ts +14 -0
- package/dist/types-ts4.5/internal/ensure-preset-styles.d.ts +6 -0
- package/dist/types-ts4.5/internal/reduced-motion.d.ts +14 -0
- package/dist/types-ts4.5/internal/resolve-placement.d.ts +16 -0
- package/dist/types-ts4.5/internal/role-types.d.ts +62 -0
- package/dist/types-ts4.5/internal/set-style.d.ts +28 -0
- package/dist/types-ts4.5/internal/slot.d.ts +29 -0
- package/dist/types-ts4.5/internal/use-anchor-positioning.d.ts +95 -0
- package/dist/types-ts4.5/internal/use-animated-visibility.d.ts +74 -0
- package/dist/types-ts4.5/internal/use-animation-preset.d.ts +11 -0
- package/dist/types-ts4.5/internal/use-focus-wrap.d.ts +20 -0
- package/dist/types-ts4.5/internal/use-initial-focus.d.ts +21 -0
- package/dist/types-ts4.5/internal/use-preset-styles.d.ts +15 -0
- package/dist/types-ts4.5/placement-map/index.d.ts +55 -0
- package/dist/types-ts4.5/popover/create-close-event.d.ts +26 -0
- package/dist/types-ts4.5/popover/index.d.ts +3 -0
- package/dist/types-ts4.5/popover/popover.d.ts +22 -0
- package/dist/types-ts4.5/popover/types.d.ts +153 -0
- package/dist/types-ts4.5/popup/index.d.ts +34 -0
- package/dist/types-ts4.5/popup/popup-content.d.ts +14 -0
- package/dist/types-ts4.5/popup/popup-context.d.ts +96 -0
- package/dist/types-ts4.5/popup/popup-surface.d.ts +16 -0
- package/dist/types-ts4.5/popup/popup-trigger-function.d.ts +108 -0
- package/dist/types-ts4.5/popup/popup-trigger.d.ts +23 -0
- package/dist/types-ts4.5/popup/popup.d.ts +14 -0
- package/dist/types-ts4.5/popup/types.d.ts +289 -0
- package/dist/types-ts4.5/use-arrow-navigation/index.d.ts +2 -0
- package/dist/types-ts4.5/use-arrow-navigation/use-arrow-navigation.d.ts +136 -0
- package/dist/types-ts4.5/use-simple-light-dismiss/index.d.ts +45 -0
- package/focus/package.json +17 -0
- package/package.json +95 -0
- package/placement-map/package.json +17 -0
- package/popover/package.json +17 -0
- package/popup/package.json +17 -0
- package/popup-surface/package.json +17 -0
- package/use-anchor-position/package.json +17 -0
- package/use-arrow-navigation/package.json +17 -0
- package/use-simple-light-dismiss/package.json +17 -0
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Computes the base {top, left} position based on the primary edge,
|
|
3
|
+
* flipping to the opposite side when there is not enough space.
|
|
4
|
+
*/
|
|
5
|
+
function computeEdgePosition({
|
|
6
|
+
axis,
|
|
7
|
+
edge,
|
|
8
|
+
triggerRect,
|
|
9
|
+
popoverWidth,
|
|
10
|
+
popoverHeight,
|
|
11
|
+
viewport,
|
|
12
|
+
offset
|
|
13
|
+
}) {
|
|
14
|
+
if (axis === 'block' && edge === 'end') {
|
|
15
|
+
// Below trigger
|
|
16
|
+
const spaceBelow = viewport.height - triggerRect.bottom;
|
|
17
|
+
const spaceAbove = triggerRect.top;
|
|
18
|
+
return {
|
|
19
|
+
top: spaceBelow >= popoverHeight + offset || spaceBelow >= spaceAbove ? triggerRect.bottom + offset : triggerRect.top - popoverHeight - offset,
|
|
20
|
+
left: triggerRect.left + triggerRect.width / 2 - popoverWidth / 2
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
if (axis === 'block' && edge === 'start') {
|
|
24
|
+
// Above trigger
|
|
25
|
+
const spaceAbove = triggerRect.top;
|
|
26
|
+
const spaceBelow = viewport.height - triggerRect.bottom;
|
|
27
|
+
return {
|
|
28
|
+
top: spaceAbove >= popoverHeight + offset || spaceAbove >= spaceBelow ? triggerRect.top - popoverHeight - offset : triggerRect.bottom + offset,
|
|
29
|
+
left: triggerRect.left + triggerRect.width / 2 - popoverWidth / 2
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
if (axis === 'inline' && edge === 'end') {
|
|
33
|
+
// Right of trigger
|
|
34
|
+
const spaceRight = viewport.width - triggerRect.right;
|
|
35
|
+
const spaceLeft = triggerRect.left;
|
|
36
|
+
return {
|
|
37
|
+
top: triggerRect.top + triggerRect.height / 2 - popoverHeight / 2,
|
|
38
|
+
left: spaceRight >= popoverWidth + offset || spaceRight >= spaceLeft ? triggerRect.right + offset : triggerRect.left - popoverWidth - offset
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
if (axis === 'inline' && edge === 'start') {
|
|
42
|
+
// Left of trigger
|
|
43
|
+
const spaceLeft = triggerRect.left;
|
|
44
|
+
const spaceRight = viewport.width - triggerRect.right;
|
|
45
|
+
return {
|
|
46
|
+
top: triggerRect.top + triggerRect.height / 2 - popoverHeight / 2,
|
|
47
|
+
left: spaceLeft >= popoverWidth + offset || spaceLeft >= spaceRight ? triggerRect.left - popoverWidth - offset : triggerRect.right + offset
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Unreachable for valid placements; defaults to below trigger
|
|
52
|
+
return {
|
|
53
|
+
top: triggerRect.bottom + offset,
|
|
54
|
+
left: triggerRect.left + triggerRect.width / 2 - popoverWidth / 2
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Adjusts the base (centered) position for non-center alignments.
|
|
60
|
+
*
|
|
61
|
+
* `align: 'start'` → popover start edge at trigger start edge
|
|
62
|
+
* `align: 'end'` → popover end edge at trigger end edge
|
|
63
|
+
*/
|
|
64
|
+
function applyAlignment({
|
|
65
|
+
position,
|
|
66
|
+
axis,
|
|
67
|
+
align,
|
|
68
|
+
triggerRect,
|
|
69
|
+
popoverWidth,
|
|
70
|
+
popoverHeight
|
|
71
|
+
}) {
|
|
72
|
+
if (align === 'center') {
|
|
73
|
+
return position;
|
|
74
|
+
}
|
|
75
|
+
if (axis === 'block') {
|
|
76
|
+
// Block-axis placement → cross-axis is inline (left/right)
|
|
77
|
+
if (align === 'start') {
|
|
78
|
+
return {
|
|
79
|
+
...position,
|
|
80
|
+
left: triggerRect.left
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
// align === 'end'
|
|
84
|
+
return {
|
|
85
|
+
...position,
|
|
86
|
+
left: triggerRect.right - popoverWidth
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Inline-axis placement → cross-axis is block (top/bottom)
|
|
91
|
+
if (align === 'start') {
|
|
92
|
+
return {
|
|
93
|
+
...position,
|
|
94
|
+
top: triggerRect.top
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
// align === 'end'
|
|
98
|
+
return {
|
|
99
|
+
...position,
|
|
100
|
+
top: triggerRect.bottom - popoverHeight
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* JS fallback: compute popover position from trigger rect and viewport.
|
|
106
|
+
*
|
|
107
|
+
* Placement algorithm (from the document):
|
|
108
|
+
* - "block" placement: show above/below, picking the side with more space if flipping needed
|
|
109
|
+
* - "inline" placement: show left/right, picking the side with more space if flipping needed
|
|
110
|
+
* - "auto" placement: show on the edge with the most available space
|
|
111
|
+
*
|
|
112
|
+
* Re-runs on scroll (capture on window) and resize events.
|
|
113
|
+
*/
|
|
114
|
+
export function computeFallbackPosition({
|
|
115
|
+
triggerRect,
|
|
116
|
+
popoverEl,
|
|
117
|
+
placement,
|
|
118
|
+
viewport,
|
|
119
|
+
offset
|
|
120
|
+
}) {
|
|
121
|
+
const {
|
|
122
|
+
axis,
|
|
123
|
+
edge,
|
|
124
|
+
align
|
|
125
|
+
} = placement;
|
|
126
|
+
|
|
127
|
+
// Measure popover dimensions (it might not have layout yet if just shown)
|
|
128
|
+
const popoverWidth = popoverEl.offsetWidth;
|
|
129
|
+
const popoverHeight = popoverEl.offsetHeight;
|
|
130
|
+
const basePosition = computeEdgePosition({
|
|
131
|
+
axis,
|
|
132
|
+
edge,
|
|
133
|
+
triggerRect,
|
|
134
|
+
popoverWidth,
|
|
135
|
+
popoverHeight,
|
|
136
|
+
viewport,
|
|
137
|
+
offset
|
|
138
|
+
});
|
|
139
|
+
const alignedPosition = applyAlignment({
|
|
140
|
+
position: basePosition,
|
|
141
|
+
axis,
|
|
142
|
+
align,
|
|
143
|
+
triggerRect,
|
|
144
|
+
popoverWidth,
|
|
145
|
+
popoverHeight
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
// Clamp to viewport so the popover is never offscreen
|
|
149
|
+
return {
|
|
150
|
+
top: Math.max(0, Math.min(alignedPosition.top, viewport.height - popoverHeight)),
|
|
151
|
+
left: Math.max(0, Math.min(alignedPosition.left, viewport.width - popoverWidth))
|
|
152
|
+
};
|
|
153
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Combine multiple cleanup functions into a single cleanup function.
|
|
3
|
+
*
|
|
4
|
+
* @example
|
|
5
|
+
* ```ts
|
|
6
|
+
* useEffect(() => {
|
|
7
|
+
* return combine(
|
|
8
|
+
* bind(window, { type: 'resize', listener: onResize }),
|
|
9
|
+
* bind(window, { type: 'scroll', listener: onScroll, options: { capture: true } }),
|
|
10
|
+
* );
|
|
11
|
+
* }, []);
|
|
12
|
+
* ```
|
|
13
|
+
*/
|
|
14
|
+
export function combine(...cleanupFns) {
|
|
15
|
+
return function cleanup() {
|
|
16
|
+
cleanupFns.forEach(fn => fn === null || fn === void 0 ? void 0 : fn());
|
|
17
|
+
};
|
|
18
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-preset CSS injection.
|
|
3
|
+
*
|
|
4
|
+
* Each preset's CSS is injected at most once into `<head>`.
|
|
5
|
+
* Shared by both PopoverContent and DialogContent.
|
|
6
|
+
*
|
|
7
|
+
* Note: injected `<style>` elements and the tracking Set are append-only —
|
|
8
|
+
* they are never removed. This is intentional: the number of distinct
|
|
9
|
+
* presets is bounded (handful of animation + arrow presets), so the
|
|
10
|
+
* memory footprint is negligible. Removing styles would risk breaking
|
|
11
|
+
* other instances of the same preset that are still mounted.
|
|
12
|
+
*
|
|
13
|
+
* Decision (2026-03-17 audit): Accepted as a non-issue. The bounded
|
|
14
|
+
* preset count (~5 presets) makes cleanup unnecessary. We plan to move
|
|
15
|
+
* to a Compiled-based solution which will handle style injection and
|
|
16
|
+
* deduplication natively.
|
|
17
|
+
*/
|
|
18
|
+
const injectedPresets = new Set();
|
|
19
|
+
export function ensurePresetStyles({
|
|
20
|
+
preset
|
|
21
|
+
}) {
|
|
22
|
+
if (injectedPresets.has(preset.name) || typeof document === 'undefined') {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
injectedPresets.add(preset.name);
|
|
26
|
+
const style = document.createElement('style');
|
|
27
|
+
style.textContent = preset.css;
|
|
28
|
+
document.head.appendChild(style);
|
|
29
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import once from '@atlaskit/ds-lib/once';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Returns `true` when the user prefers reduced motion.
|
|
5
|
+
*
|
|
6
|
+
* Safe for SSR (returns `false` when `window` is unavailable).
|
|
7
|
+
*
|
|
8
|
+
* The result is cached after the first call via `once`. This avoids
|
|
9
|
+
* calling `matchMedia` on every render. The trade-off is that if a user
|
|
10
|
+
* toggles the OS reduced-motion setting mid-session, the change won't
|
|
11
|
+
* take effect until the next page load. This is acceptable because
|
|
12
|
+
* toggling this system-level preference mid-session is extremely rare,
|
|
13
|
+
* and a page refresh is a reasonable expectation for system accessibility
|
|
14
|
+
* settings to take effect.
|
|
15
|
+
*/
|
|
16
|
+
export const prefersReducedMotion = once(() => {
|
|
17
|
+
if (typeof window === 'undefined' || !('matchMedia' in window)) {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
return window.matchMedia('(prefers-reduced-motion: reduce)').matches;
|
|
21
|
+
});
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fully-resolved placement (internal). All fields are required.
|
|
3
|
+
* Use getPlacement({ placement: partial }) to obtain from partial input.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Resolves a partial placement to its fully-specified form.
|
|
8
|
+
* Defaults: `axis: 'block'`, `edge: 'end'`, `align: 'center'`.
|
|
9
|
+
*/
|
|
10
|
+
export function getPlacement({
|
|
11
|
+
placement
|
|
12
|
+
}) {
|
|
13
|
+
var _placement$axis, _placement$edge, _placement$align;
|
|
14
|
+
return {
|
|
15
|
+
axis: (_placement$axis = placement.axis) !== null && _placement$axis !== void 0 ? _placement$axis : 'block',
|
|
16
|
+
edge: (_placement$edge = placement.edge) !== null && _placement$edge !== void 0 ? _placement$edge : 'end',
|
|
17
|
+
align: (_placement$align = placement.align) !== null && _placement$align !== void 0 ? _placement$align : 'center'
|
|
18
|
+
};
|
|
19
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Valid values for the `aria-haspopup` attribute.
|
|
3
|
+
* Derived from the HTML spec — maps popover roles to what the trigger announces.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Roles that require an accessible name (`label` or `labelledBy`) per WCAG 4.1.2.
|
|
8
|
+
* Without a name, assistive technology cannot identify these landmarks.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Roles where the accessible name is derived from content or provided externally
|
|
13
|
+
* (e.g. a combobox labels its listbox, tooltip content IS the accessible name).
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
// ── Shared ARIA role discrimination types ──
|
|
17
|
+
//
|
|
18
|
+
// These encode the WCAG 4.1.2 constraint: roles like `dialog`, `alertdialog`,
|
|
19
|
+
// and `menu` MUST have an accessible name (either `label` or `labelledBy`).
|
|
20
|
+
// TypeScript enforces this at compile time via discriminated unions.
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* ARIA role props where a role is always required.
|
|
24
|
+
*
|
|
25
|
+
* Used by `TPopupContentProps` — popup content must always declare
|
|
26
|
+
* its role so assistive technology can identify the layer.
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* ARIA role props where a role is optional.
|
|
31
|
+
*
|
|
32
|
+
* Used by `TPopoverProps` — the low-level primitive allows omitting
|
|
33
|
+
* the role for cases where it is set externally or not needed.
|
|
34
|
+
*/
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Maps a popover content role to the correct `aria-haspopup` value
|
|
38
|
+
* for its trigger element.
|
|
39
|
+
*/
|
|
40
|
+
export function roleToAriaHasPopup({
|
|
41
|
+
role
|
|
42
|
+
}) {
|
|
43
|
+
if (role === 'menu') {
|
|
44
|
+
return 'menu';
|
|
45
|
+
}
|
|
46
|
+
if (role === 'listbox') {
|
|
47
|
+
return 'listbox';
|
|
48
|
+
}
|
|
49
|
+
if (role === 'tree') {
|
|
50
|
+
return 'tree';
|
|
51
|
+
}
|
|
52
|
+
if (role === 'grid') {
|
|
53
|
+
return 'grid';
|
|
54
|
+
}
|
|
55
|
+
// Default: return 'dialog' for all unmapped roles (tooltip, alertdialog,
|
|
56
|
+
// note, status, alert, log, etc). This is a kinder API — rather than
|
|
57
|
+
// throwing on unknown roles, we fall back to the most common popup type.
|
|
58
|
+
// New roles that need specific aria-haspopup values should be added
|
|
59
|
+
// as explicit cases above.
|
|
60
|
+
return 'dialog';
|
|
61
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sets inline styles on an element and returns a cleanup function
|
|
3
|
+
* that removes only the styles that were applied.
|
|
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
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export function setStyle({
|
|
23
|
+
el,
|
|
24
|
+
styles
|
|
25
|
+
}) {
|
|
26
|
+
styles.forEach(({
|
|
27
|
+
property,
|
|
28
|
+
value
|
|
29
|
+
}) => {
|
|
30
|
+
el.style.setProperty(property, value);
|
|
31
|
+
});
|
|
32
|
+
return function cleanup() {
|
|
33
|
+
styles.forEach(({
|
|
34
|
+
property
|
|
35
|
+
}) => {
|
|
36
|
+
el.style.removeProperty(property);
|
|
37
|
+
});
|
|
38
|
+
};
|
|
39
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { cloneElement, forwardRef, isValidElement } from 'react';
|
|
2
|
+
import mergeRefs from '@atlaskit/ds-lib/merge-refs';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Extra DOM/event props are passed through to the cloned child.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Single element child: merge the caller ref with `child.ref`.
|
|
10
|
+
*
|
|
11
|
+
* Do not read `child.props.ref`: React keeps a `ref` key on `props` for
|
|
12
|
+
* host elements but accessing it logs a warning and returns `undefined`
|
|
13
|
+
* (ref lives on the element as `child.ref`).
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
function isSlotChild(child) {
|
|
17
|
+
return /*#__PURE__*/isValidElement(child);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Merges props (including ref) onto a single React element child.
|
|
22
|
+
*
|
|
23
|
+
* A safer alternative to raw `cloneElement` that:
|
|
24
|
+
* 1. Guards with `isValidElement` — non-element children (strings,
|
|
25
|
+
* fragments, null) are returned as-is instead of crashing.
|
|
26
|
+
* 2. Merges refs via `mergeRefs` so both the caller's ref and the
|
|
27
|
+
* child's existing ref are honoured.
|
|
28
|
+
* 3. Spreads any additional props (ARIA attributes, event handlers, etc.)
|
|
29
|
+
* onto the child element.
|
|
30
|
+
*
|
|
31
|
+
* Event handlers (e.g. `onClick`) are **not** auto-merged — the caller's
|
|
32
|
+
* handler replaces the child's. Compose handlers before passing them in.
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* ```tsx
|
|
36
|
+
* <Slot ref={triggerRef} onClick={handleClick} aria-expanded={isOpen}>
|
|
37
|
+
* <button>Open</button>
|
|
38
|
+
* </Slot>
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
export const Slot = /*#__PURE__*/forwardRef(function Slot(slotProps, ref) {
|
|
42
|
+
const {
|
|
43
|
+
children: rawChildren,
|
|
44
|
+
...props
|
|
45
|
+
} = slotProps;
|
|
46
|
+
// `SlotProps` intersects `Record<string, unknown>`, so `children` is typed as `unknown`.
|
|
47
|
+
const children = rawChildren;
|
|
48
|
+
if (!isSlotChild(children)) {
|
|
49
|
+
return children;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// eslint-disable-next-line @repo/internal/react/no-clone-element -- Slot is a controlled wrapper around cloneElement with isValidElement guard
|
|
53
|
+
return /*#__PURE__*/cloneElement(children, {
|
|
54
|
+
...props,
|
|
55
|
+
ref: mergeRefs([ref, children.ref])
|
|
56
|
+
});
|
|
57
|
+
});
|