@cloudscape-design/components 3.0.609 → 3.0.610
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/annotation-context/annotation/styles.css.js +24 -24
- package/annotation-context/annotation/styles.scoped.css +33 -29
- package/annotation-context/annotation/styles.selectors.js +24 -24
- package/button-dropdown/category-elements/styles.css.js +14 -14
- package/button-dropdown/category-elements/styles.scoped.css +25 -22
- package/button-dropdown/category-elements/styles.selectors.js +14 -14
- package/internal/components/chart-popover/index.d.ts +1 -1
- package/internal/components/chart-popover/index.d.ts.map +1 -1
- package/internal/components/chart-popover/index.js.map +1 -1
- package/internal/components/dropdown/dropdown-fit-handler.d.ts +12 -12
- package/internal/components/dropdown/dropdown-fit-handler.d.ts.map +1 -1
- package/internal/components/dropdown/dropdown-fit-handler.js +103 -83
- package/internal/components/dropdown/dropdown-fit-handler.js.map +1 -1
- package/internal/components/dropdown/index.d.ts.map +1 -1
- package/internal/components/dropdown/index.js +30 -29
- package/internal/components/dropdown/index.js.map +1 -1
- package/internal/components/tooltip/index.d.ts +1 -1
- package/internal/components/tooltip/index.d.ts.map +1 -1
- package/internal/components/tooltip/index.js.map +1 -1
- package/internal/direction.d.ts +14 -0
- package/internal/direction.d.ts.map +1 -1
- package/internal/direction.js +25 -0
- package/internal/direction.js.map +1 -1
- package/internal/environment.js +1 -1
- package/internal/environment.json +1 -1
- package/internal/manifest.json +1 -1
- package/internal/utils/scrollable-containers.d.ts +5 -5
- package/internal/utils/scrollable-containers.d.ts.map +1 -1
- package/internal/utils/scrollable-containers.js +19 -19
- package/internal/utils/scrollable-containers.js.map +1 -1
- package/package.json +1 -1
- package/popover/container.d.ts +1 -1
- package/popover/container.d.ts.map +1 -1
- package/popover/container.js.map +1 -1
- package/popover/interfaces.d.ts +4 -4
- package/popover/interfaces.d.ts.map +1 -1
- package/popover/interfaces.js.map +1 -1
- package/popover/styles.css.js +50 -50
- package/popover/styles.scoped.css +76 -64
- package/popover/styles.selectors.js +50 -50
- package/popover/use-popover-position.d.ts +1 -1
- package/popover/use-popover-position.d.ts.map +1 -1
- package/popover/use-popover-position.js +32 -29
- package/popover/use-popover-position.js.map +1 -1
- package/popover/utils/positions.d.ts +2 -2
- package/popover/utils/positions.d.ts.map +1 -1
- package/popover/utils/positions.js +74 -74
- package/popover/utils/positions.js.map +1 -1
|
@@ -5,6 +5,7 @@ import { calculatePosition, getDimensions, getOffsetDimensions } from './utils/p
|
|
|
5
5
|
import { nodeContains } from '@cloudscape-design/component-toolkit/dom';
|
|
6
6
|
import { calculateScroll, getFirstScrollableParent, scrollRectangleIntoView, } from '../internal/utils/scrollable-containers';
|
|
7
7
|
import { getContainingBlock } from '../internal/utils/dom';
|
|
8
|
+
import { getLogicalBoundingClientRect } from '../internal/direction';
|
|
8
9
|
export default function usePopoverPosition({ popoverRef, bodyRef, arrowRef, trackRef, contentRef, allowScrollToFit, allowVerticalOverflow, preferredPosition, renderWithPortal, keepPosition, }) {
|
|
9
10
|
const previousInternalPositionRef = useRef(null);
|
|
10
11
|
const [popoverStyle, setPopoverStyle] = useState({});
|
|
@@ -31,26 +32,26 @@ export default function usePopoverPosition({ popoverRef, bodyRef, arrowRef, trac
|
|
|
31
32
|
// Imperatively move body off-screen to give it room to expand.
|
|
32
33
|
// Not doing this in React because this recalculation should happen
|
|
33
34
|
// in the span of a single frame without rerendering anything.
|
|
34
|
-
const
|
|
35
|
-
const
|
|
36
|
-
popover.style.
|
|
37
|
-
popover.style.
|
|
35
|
+
const prevInsetBlockStart = popover.style.insetBlockStart;
|
|
36
|
+
const prevInsetInlineStart = popover.style.insetInlineStart;
|
|
37
|
+
popover.style.insetBlockStart = '0';
|
|
38
|
+
popover.style.insetInlineStart = '0';
|
|
38
39
|
// Imperatively remove body styles that can remain from the previous computation.
|
|
39
|
-
body.style.
|
|
40
|
+
body.style.maxBlockSize = '';
|
|
40
41
|
body.style.overflowX = '';
|
|
41
42
|
body.style.overflowY = '';
|
|
42
43
|
// Get rects representing key elements
|
|
43
44
|
// Use getComputedStyle for arrowRect to avoid modifications made by transform
|
|
44
45
|
const viewportRect = getViewportRect(document.defaultView);
|
|
45
|
-
const trackRect = track
|
|
46
|
+
const trackRect = getLogicalBoundingClientRect(track);
|
|
46
47
|
const arrowRect = getDimensions(arrow);
|
|
47
48
|
const containingBlock = getContainingBlock(popover);
|
|
48
|
-
const containingBlockRect = containingBlock ? containingBlock
|
|
49
|
+
const containingBlockRect = containingBlock ? getLogicalBoundingClientRect(containingBlock) : viewportRect;
|
|
49
50
|
const bodyBorderWidth = getBorderWidth(body);
|
|
50
|
-
const contentRect = contentRef.current
|
|
51
|
+
const contentRect = getLogicalBoundingClientRect(contentRef.current);
|
|
51
52
|
const contentBoundingBox = {
|
|
52
|
-
|
|
53
|
-
|
|
53
|
+
inlineSize: contentRect.inlineSize + 2 * bodyBorderWidth,
|
|
54
|
+
blockSize: contentRect.blockSize + 2 * bodyBorderWidth,
|
|
54
55
|
};
|
|
55
56
|
// When keepPosition is true and the recalculation was triggered by a resize of the popover content,
|
|
56
57
|
// we maintain the previously defined internal position,
|
|
@@ -75,11 +76,11 @@ export default function usePopoverPosition({ popoverRef, bodyRef, arrowRef, trac
|
|
|
75
76
|
// and use that to recalculate the new popover position.
|
|
76
77
|
const trackRelativeOffset = toRelativePosition(popoverOffset, toRelativePosition(trackRect, containingBlockRect));
|
|
77
78
|
// Bring back the container to its original position to prevent any flashing.
|
|
78
|
-
popover.style.
|
|
79
|
-
popover.style.
|
|
79
|
+
popover.style.insetBlockStart = prevInsetBlockStart;
|
|
80
|
+
popover.style.insetInlineStart = prevInsetInlineStart;
|
|
80
81
|
// Allow popover body to scroll if can't fit the popover into the container/viewport otherwise.
|
|
81
82
|
if (scrollable) {
|
|
82
|
-
body.style.
|
|
83
|
+
body.style.maxBlockSize = rect.blockSize + 'px';
|
|
83
84
|
body.style.overflowX = 'hidden';
|
|
84
85
|
body.style.overflowY = 'auto';
|
|
85
86
|
}
|
|
@@ -88,18 +89,20 @@ export default function usePopoverPosition({ popoverRef, bodyRef, arrowRef, trac
|
|
|
88
89
|
setInternalPosition(newInternalPosition);
|
|
89
90
|
const shouldScroll = allowScrollToFit && !shouldKeepPosition;
|
|
90
91
|
// Position the popover
|
|
91
|
-
const
|
|
92
|
-
|
|
92
|
+
const insetBlockStart = shouldScroll
|
|
93
|
+
? popoverOffset.insetBlockStart + calculateScroll(rect)
|
|
94
|
+
: popoverOffset.insetBlockStart;
|
|
95
|
+
setPopoverStyle({ insetBlockStart, insetInlineStart: popoverOffset.insetInlineStart });
|
|
93
96
|
// Scroll if necessary
|
|
94
97
|
if (shouldScroll) {
|
|
95
98
|
const scrollableParent = getFirstScrollableParent(popover);
|
|
96
99
|
scrollRectangleIntoView(rect, scrollableParent);
|
|
97
100
|
}
|
|
98
101
|
positionHandlerRef.current = () => {
|
|
99
|
-
const newTrackOffset = toRelativePosition(track
|
|
102
|
+
const newTrackOffset = toRelativePosition(getLogicalBoundingClientRect(track), containingBlock ? getLogicalBoundingClientRect(containingBlock) : viewportRect);
|
|
100
103
|
setPopoverStyle({
|
|
101
|
-
|
|
102
|
-
|
|
104
|
+
insetBlockStart: newTrackOffset.insetBlockStart + trackRelativeOffset.insetBlockStart,
|
|
105
|
+
insetInlineStart: newTrackOffset.insetInlineStart + trackRelativeOffset.insetInlineStart,
|
|
103
106
|
});
|
|
104
107
|
};
|
|
105
108
|
}, [
|
|
@@ -124,8 +127,8 @@ function getBorderWidth(element) {
|
|
|
124
127
|
*/
|
|
125
128
|
function toRelativePosition(element, parent) {
|
|
126
129
|
return {
|
|
127
|
-
|
|
128
|
-
|
|
130
|
+
insetBlockStart: element.insetBlockStart - parent.insetBlockStart,
|
|
131
|
+
insetInlineStart: element.insetInlineStart - parent.insetInlineStart,
|
|
129
132
|
};
|
|
130
133
|
}
|
|
131
134
|
/**
|
|
@@ -133,19 +136,19 @@ function toRelativePosition(element, parent) {
|
|
|
133
136
|
*/
|
|
134
137
|
function getViewportRect(window) {
|
|
135
138
|
return {
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
139
|
+
insetBlockStart: 0,
|
|
140
|
+
insetInlineStart: 0,
|
|
141
|
+
inlineSize: window.innerWidth,
|
|
142
|
+
blockSize: window.innerHeight,
|
|
140
143
|
};
|
|
141
144
|
}
|
|
142
145
|
function getDocumentRect(document) {
|
|
143
|
-
const {
|
|
146
|
+
const { insetBlockStart, insetInlineStart } = getLogicalBoundingClientRect(document.documentElement);
|
|
144
147
|
return {
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
148
|
+
insetBlockStart,
|
|
149
|
+
insetInlineStart,
|
|
150
|
+
inlineSize: document.documentElement.scrollWidth,
|
|
151
|
+
blockSize: document.documentElement.scrollHeight,
|
|
149
152
|
};
|
|
150
153
|
}
|
|
151
154
|
//# sourceMappingURL=use-popover-position.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-popover-position.js","sourceRoot":"","sources":["../../../src/popover/use-popover-position.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n// SPDX-License-Identifier: Apache-2.0\n\nimport React, { useCallback, useRef, useState } from 'react';\nimport { BoundingBox, InternalPosition, Offset, PopoverProps } from './interfaces';\nimport { calculatePosition, getDimensions, getOffsetDimensions } from './utils/positions';\nimport { nodeContains } from '@cloudscape-design/component-toolkit/dom';\nimport {\n calculateScroll,\n getFirstScrollableParent,\n scrollRectangleIntoView,\n} from '../internal/utils/scrollable-containers';\nimport { getContainingBlock } from '../internal/utils/dom';\n\nexport default function usePopoverPosition({\n popoverRef,\n bodyRef,\n arrowRef,\n trackRef,\n contentRef,\n allowScrollToFit,\n allowVerticalOverflow,\n preferredPosition,\n renderWithPortal,\n keepPosition,\n}: {\n popoverRef: React.RefObject<HTMLDivElement | null>;\n bodyRef: React.RefObject<HTMLDivElement | null>;\n arrowRef: React.RefObject<HTMLDivElement | null>;\n trackRef: React.RefObject<Element | null>;\n contentRef: React.RefObject<HTMLDivElement | null>;\n allowScrollToFit?: boolean;\n allowVerticalOverflow?: boolean;\n preferredPosition: PopoverProps.Position;\n renderWithPortal?: boolean;\n keepPosition?: boolean;\n}) {\n const previousInternalPositionRef = useRef<InternalPosition | null>(null);\n const [popoverStyle, setPopoverStyle] = useState<Partial<Offset>>({});\n const [internalPosition, setInternalPosition] = useState<InternalPosition | null>(null);\n\n // Store the handler in a ref so that it can still be replaced from outside of the listener closure.\n const positionHandlerRef = useRef<() => void>(() => {});\n\n const updatePositionHandler = useCallback(\n (onContentResize = false) => {\n if (!trackRef.current || !popoverRef.current || !bodyRef.current || !contentRef.current || !arrowRef.current) {\n return;\n }\n\n // Get important elements\n const popover = popoverRef.current;\n const body = bodyRef.current;\n const arrow = arrowRef.current;\n const document = popover.ownerDocument;\n const track = trackRef.current;\n\n // If the popover body isn't being rendered for whatever reason (e.g. \"display: none\" or JSDOM),\n // or track does not belong to the document - bail on calculating dimensions.\n const { offsetWidth, offsetHeight } = getOffsetDimensions(popover);\n if (offsetWidth === 0 || offsetHeight === 0 || !nodeContains(document.body, track)) {\n return;\n }\n\n // Imperatively move body off-screen to give it room to expand.\n // Not doing this in React because this recalculation should happen\n // in the span of a single frame without rerendering anything.\n const prevTop = popover.style.top;\n const prevLeft = popover.style.left;\n\n popover.style.top = '0';\n popover.style.left = '0';\n // Imperatively remove body styles that can remain from the previous computation.\n body.style.maxHeight = '';\n body.style.overflowX = '';\n body.style.overflowY = '';\n\n // Get rects representing key elements\n // Use getComputedStyle for arrowRect to avoid modifications made by transform\n const viewportRect = getViewportRect(document.defaultView!);\n const trackRect = track.getBoundingClientRect();\n const arrowRect = getDimensions(arrow);\n const containingBlock = getContainingBlock(popover);\n const containingBlockRect = containingBlock ? containingBlock.getBoundingClientRect() : viewportRect;\n\n const bodyBorderWidth = getBorderWidth(body);\n const contentRect = contentRef.current.getBoundingClientRect();\n const contentBoundingBox = {\n width: contentRect.width + 2 * bodyBorderWidth,\n height: contentRect.height + 2 * bodyBorderWidth,\n };\n\n // When keepPosition is true and the recalculation was triggered by a resize of the popover content,\n // we maintain the previously defined internal position,\n // but we still call calculatePosition to know if the popover should be scrollable.\n const shouldKeepPosition = keepPosition && onContentResize && !!previousInternalPositionRef.current;\n const fixedInternalPosition = (shouldKeepPosition && previousInternalPositionRef.current) ?? undefined;\n\n // Calculate the arrow direction and viewport-relative position of the popover.\n const {\n scrollable,\n internalPosition: newInternalPosition,\n rect,\n } = calculatePosition({\n preferredPosition,\n fixedInternalPosition,\n trigger: trackRect,\n arrow: arrowRect,\n body: contentBoundingBox,\n container: containingBlock ? containingBlockRect : getDocumentRect(document),\n viewport: viewportRect,\n renderWithPortal,\n allowVerticalOverflow,\n });\n\n // Get the position of the popover relative to the offset parent.\n const popoverOffset = toRelativePosition(rect, containingBlockRect);\n\n // Cache the distance between the trigger and the popover (which stays the same as you scroll),\n // and use that to recalculate the new popover position.\n const trackRelativeOffset = toRelativePosition(popoverOffset, toRelativePosition(trackRect, containingBlockRect));\n\n // Bring back the container to its original position to prevent any flashing.\n popover.style.top = prevTop;\n popover.style.left = prevLeft;\n\n // Allow popover body to scroll if can't fit the popover into the container/viewport otherwise.\n if (scrollable) {\n body.style.maxHeight = rect.height + 'px';\n body.style.overflowX = 'hidden';\n body.style.overflowY = 'auto';\n }\n\n // Remember the internal position in case we want to keep it later.\n previousInternalPositionRef.current = newInternalPosition;\n setInternalPosition(newInternalPosition);\n\n const shouldScroll = allowScrollToFit && !shouldKeepPosition;\n\n // Position the popover\n const top = shouldScroll ? popoverOffset.top + calculateScroll(rect) : popoverOffset.top;\n setPopoverStyle({ top, left: popoverOffset.left });\n\n // Scroll if necessary\n if (shouldScroll) {\n const scrollableParent = getFirstScrollableParent(popover);\n scrollRectangleIntoView(rect, scrollableParent);\n }\n\n positionHandlerRef.current = () => {\n const newTrackOffset = toRelativePosition(\n track.getBoundingClientRect(),\n containingBlock ? containingBlock.getBoundingClientRect() : viewportRect\n );\n setPopoverStyle({\n top: newTrackOffset.top + trackRelativeOffset.top,\n left: newTrackOffset.left + trackRelativeOffset.left,\n });\n };\n },\n [\n trackRef,\n popoverRef,\n bodyRef,\n contentRef,\n arrowRef,\n keepPosition,\n allowScrollToFit,\n preferredPosition,\n renderWithPortal,\n allowVerticalOverflow,\n ]\n );\n return { updatePositionHandler, popoverStyle, internalPosition, positionHandlerRef };\n}\n\nfunction getBorderWidth(element: HTMLElement) {\n return parseInt(getComputedStyle(element).borderWidth) || 0;\n}\n\n/**\n * Convert a viewport-relative offset to an element-relative offset.\n */\nfunction toRelativePosition(element: Offset, parent: Offset): Offset {\n return {\n top: element.top - parent.top,\n left: element.left - parent.left,\n };\n}\n\n/**\n * Get a BoundingBox that represents the visible viewport.\n */\nfunction getViewportRect(window: Window): BoundingBox {\n return {\n top: 0,\n left: 0,\n width: window.innerWidth,\n height: window.innerHeight,\n };\n}\n\nfunction getDocumentRect(document: Document): BoundingBox {\n const { top, left } = document.documentElement.getBoundingClientRect();\n return {\n top,\n left,\n width: document.documentElement.scrollWidth,\n height: document.documentElement.scrollHeight,\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"use-popover-position.js","sourceRoot":"","sources":["../../../src/popover/use-popover-position.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n// SPDX-License-Identifier: Apache-2.0\n\nimport React, { useCallback, useRef, useState } from 'react';\nimport { BoundingBox, InternalPosition, Offset, PopoverProps } from './interfaces';\nimport { calculatePosition, getDimensions, getOffsetDimensions } from './utils/positions';\nimport { nodeContains } from '@cloudscape-design/component-toolkit/dom';\nimport {\n calculateScroll,\n getFirstScrollableParent,\n scrollRectangleIntoView,\n} from '../internal/utils/scrollable-containers';\nimport { getContainingBlock } from '../internal/utils/dom';\nimport { getLogicalBoundingClientRect } from '../internal/direction';\n\nexport default function usePopoverPosition({\n popoverRef,\n bodyRef,\n arrowRef,\n trackRef,\n contentRef,\n allowScrollToFit,\n allowVerticalOverflow,\n preferredPosition,\n renderWithPortal,\n keepPosition,\n}: {\n popoverRef: React.RefObject<HTMLDivElement | null>;\n bodyRef: React.RefObject<HTMLDivElement | null>;\n arrowRef: React.RefObject<HTMLDivElement | null>;\n trackRef: React.RefObject<HTMLElement | SVGElement | null>;\n contentRef: React.RefObject<HTMLDivElement | null>;\n allowScrollToFit?: boolean;\n allowVerticalOverflow?: boolean;\n preferredPosition: PopoverProps.Position;\n renderWithPortal?: boolean;\n keepPosition?: boolean;\n}) {\n const previousInternalPositionRef = useRef<InternalPosition | null>(null);\n const [popoverStyle, setPopoverStyle] = useState<Partial<Offset>>({});\n const [internalPosition, setInternalPosition] = useState<InternalPosition | null>(null);\n\n // Store the handler in a ref so that it can still be replaced from outside of the listener closure.\n const positionHandlerRef = useRef<() => void>(() => {});\n\n const updatePositionHandler = useCallback(\n (onContentResize = false) => {\n if (!trackRef.current || !popoverRef.current || !bodyRef.current || !contentRef.current || !arrowRef.current) {\n return;\n }\n\n // Get important elements\n const popover = popoverRef.current;\n const body = bodyRef.current;\n const arrow = arrowRef.current;\n const document = popover.ownerDocument;\n const track = trackRef.current;\n\n // If the popover body isn't being rendered for whatever reason (e.g. \"display: none\" or JSDOM),\n // or track does not belong to the document - bail on calculating dimensions.\n const { offsetWidth, offsetHeight } = getOffsetDimensions(popover);\n if (offsetWidth === 0 || offsetHeight === 0 || !nodeContains(document.body, track)) {\n return;\n }\n\n // Imperatively move body off-screen to give it room to expand.\n // Not doing this in React because this recalculation should happen\n // in the span of a single frame without rerendering anything.\n const prevInsetBlockStart = popover.style.insetBlockStart;\n const prevInsetInlineStart = popover.style.insetInlineStart;\n\n popover.style.insetBlockStart = '0';\n popover.style.insetInlineStart = '0';\n // Imperatively remove body styles that can remain from the previous computation.\n body.style.maxBlockSize = '';\n body.style.overflowX = '';\n body.style.overflowY = '';\n\n // Get rects representing key elements\n // Use getComputedStyle for arrowRect to avoid modifications made by transform\n const viewportRect = getViewportRect(document.defaultView!);\n const trackRect = getLogicalBoundingClientRect(track);\n const arrowRect = getDimensions(arrow);\n const containingBlock = getContainingBlock(popover);\n const containingBlockRect = containingBlock ? getLogicalBoundingClientRect(containingBlock) : viewportRect;\n\n const bodyBorderWidth = getBorderWidth(body);\n const contentRect = getLogicalBoundingClientRect(contentRef.current);\n const contentBoundingBox = {\n inlineSize: contentRect.inlineSize + 2 * bodyBorderWidth,\n blockSize: contentRect.blockSize + 2 * bodyBorderWidth,\n };\n\n // When keepPosition is true and the recalculation was triggered by a resize of the popover content,\n // we maintain the previously defined internal position,\n // but we still call calculatePosition to know if the popover should be scrollable.\n const shouldKeepPosition = keepPosition && onContentResize && !!previousInternalPositionRef.current;\n const fixedInternalPosition = (shouldKeepPosition && previousInternalPositionRef.current) ?? undefined;\n\n // Calculate the arrow direction and viewport-relative position of the popover.\n const {\n scrollable,\n internalPosition: newInternalPosition,\n rect,\n } = calculatePosition({\n preferredPosition,\n fixedInternalPosition,\n trigger: trackRect,\n arrow: arrowRect,\n body: contentBoundingBox,\n container: containingBlock ? containingBlockRect : getDocumentRect(document),\n viewport: viewportRect,\n renderWithPortal,\n allowVerticalOverflow,\n });\n\n // Get the position of the popover relative to the offset parent.\n const popoverOffset = toRelativePosition(rect, containingBlockRect);\n\n // Cache the distance between the trigger and the popover (which stays the same as you scroll),\n // and use that to recalculate the new popover position.\n const trackRelativeOffset = toRelativePosition(popoverOffset, toRelativePosition(trackRect, containingBlockRect));\n\n // Bring back the container to its original position to prevent any flashing.\n popover.style.insetBlockStart = prevInsetBlockStart;\n popover.style.insetInlineStart = prevInsetInlineStart;\n\n // Allow popover body to scroll if can't fit the popover into the container/viewport otherwise.\n if (scrollable) {\n body.style.maxBlockSize = rect.blockSize + 'px';\n body.style.overflowX = 'hidden';\n body.style.overflowY = 'auto';\n }\n\n // Remember the internal position in case we want to keep it later.\n previousInternalPositionRef.current = newInternalPosition;\n setInternalPosition(newInternalPosition);\n\n const shouldScroll = allowScrollToFit && !shouldKeepPosition;\n\n // Position the popover\n const insetBlockStart = shouldScroll\n ? popoverOffset.insetBlockStart + calculateScroll(rect)\n : popoverOffset.insetBlockStart;\n setPopoverStyle({ insetBlockStart, insetInlineStart: popoverOffset.insetInlineStart });\n\n // Scroll if necessary\n if (shouldScroll) {\n const scrollableParent = getFirstScrollableParent(popover);\n scrollRectangleIntoView(rect, scrollableParent);\n }\n\n positionHandlerRef.current = () => {\n const newTrackOffset = toRelativePosition(\n getLogicalBoundingClientRect(track),\n containingBlock ? getLogicalBoundingClientRect(containingBlock) : viewportRect\n );\n setPopoverStyle({\n insetBlockStart: newTrackOffset.insetBlockStart + trackRelativeOffset.insetBlockStart,\n insetInlineStart: newTrackOffset.insetInlineStart + trackRelativeOffset.insetInlineStart,\n });\n };\n },\n [\n trackRef,\n popoverRef,\n bodyRef,\n contentRef,\n arrowRef,\n keepPosition,\n allowScrollToFit,\n preferredPosition,\n renderWithPortal,\n allowVerticalOverflow,\n ]\n );\n return { updatePositionHandler, popoverStyle, internalPosition, positionHandlerRef };\n}\n\nfunction getBorderWidth(element: HTMLElement) {\n return parseInt(getComputedStyle(element).borderWidth) || 0;\n}\n\n/**\n * Convert a viewport-relative offset to an element-relative offset.\n */\nfunction toRelativePosition(element: Offset, parent: Offset): Offset {\n return {\n insetBlockStart: element.insetBlockStart - parent.insetBlockStart,\n insetInlineStart: element.insetInlineStart - parent.insetInlineStart,\n };\n}\n\n/**\n * Get a BoundingBox that represents the visible viewport.\n */\nfunction getViewportRect(window: Window): BoundingBox {\n return {\n insetBlockStart: 0,\n insetInlineStart: 0,\n inlineSize: window.innerWidth,\n blockSize: window.innerHeight,\n };\n}\n\nfunction getDocumentRect(document: Document): BoundingBox {\n const { insetBlockStart, insetInlineStart } = getLogicalBoundingClientRect(document.documentElement);\n\n return {\n insetBlockStart,\n insetInlineStart,\n inlineSize: document.documentElement.scrollWidth,\n blockSize: document.documentElement.scrollHeight,\n };\n}\n"]}
|
|
@@ -28,8 +28,8 @@ export declare function getOffsetDimensions(element: HTMLElement): {
|
|
|
28
28
|
offsetWidth: number;
|
|
29
29
|
};
|
|
30
30
|
export declare function getDimensions(element: HTMLElement): {
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
inlineSize: number;
|
|
32
|
+
blockSize: number;
|
|
33
33
|
};
|
|
34
34
|
export {};
|
|
35
35
|
//# sourceMappingURL=positions.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"positions.d.ts","sourceRoot":"","sources":["../../../../src/popover/utils/positions.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAGxF,UAAU,kBAAkB;IAC1B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,IAAI,EAAE,WAAW,CAAC;CACnB;AAUD,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,YAAY,CAAC,QAAQ,EAAE,gBAAgB,EAAE,CAiD9E,CAAC;
|
|
1
|
+
{"version":3,"file":"positions.d.ts","sourceRoot":"","sources":["../../../../src/popover/utils/positions.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAGxF,UAAU,kBAAkB;IAC1B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,IAAI,EAAE,WAAW,CAAC;CACnB;AAUD,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,YAAY,CAAC,QAAQ,EAAE,gBAAgB,EAAE,CAiD9E,CAAC;AAqJF;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,WAAW,EAAE,GAAG,MAAM,GAAG,IAAI,CAG5E;AAID;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,EAChC,iBAAiB,EACjB,qBAAqB,EACrB,OAAO,EACP,KAAK,EACL,IAAI,EACJ,SAAS,EACT,QAAQ,EAER,gBAAgB,EAChB,qBAAqB,GACtB,EAAE;IACD,iBAAiB,EAAE,YAAY,CAAC,QAAQ,CAAC;IACzC,qBAAqB,CAAC,EAAE,gBAAgB,CAAC;IACzC,OAAO,EAAE,WAAW,CAAC;IACrB,KAAK,EAAE,UAAU,CAAC;IAClB,IAAI,EAAE,UAAU,CAAC;IACjB,SAAS,EAAE,WAAW,CAAC;IACvB,QAAQ,EAAE,WAAW,CAAC;IAEtB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,qBAAqB,CAAC,EAAE,OAAO,CAAC;CACjC,GAAG,kBAAkB,CAoDrB;AAmBD,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,WAAW;;;EAEvD;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,WAAW;;;EAMjD"}
|
|
@@ -52,109 +52,109 @@ export const PRIORITY_MAPPING = {
|
|
|
52
52
|
const RECTANGLE_CALCULATIONS = {
|
|
53
53
|
'top-center': ({ body, trigger, arrow }) => {
|
|
54
54
|
return {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
55
|
+
insetBlockStart: trigger.insetBlockStart - body.blockSize - arrow.blockSize,
|
|
56
|
+
insetInlineStart: trigger.insetInlineStart + trigger.inlineSize / 2 - body.inlineSize / 2,
|
|
57
|
+
inlineSize: body.inlineSize,
|
|
58
|
+
blockSize: body.blockSize,
|
|
59
59
|
};
|
|
60
60
|
},
|
|
61
61
|
'top-right': ({ body, trigger, arrow }) => {
|
|
62
62
|
return {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
63
|
+
insetBlockStart: trigger.insetBlockStart - body.blockSize - arrow.blockSize,
|
|
64
|
+
insetInlineStart: trigger.insetInlineStart + trigger.inlineSize / 2 - ARROW_OFFSET - arrow.inlineSize / 2,
|
|
65
|
+
inlineSize: body.inlineSize,
|
|
66
|
+
blockSize: body.blockSize,
|
|
67
67
|
};
|
|
68
68
|
},
|
|
69
69
|
'top-left': ({ body, trigger, arrow }) => {
|
|
70
70
|
return {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
71
|
+
insetBlockStart: trigger.insetBlockStart - body.blockSize - arrow.blockSize,
|
|
72
|
+
insetInlineStart: trigger.insetInlineStart + trigger.inlineSize / 2 + ARROW_OFFSET + arrow.inlineSize / 2 - body.inlineSize,
|
|
73
|
+
inlineSize: body.inlineSize,
|
|
74
|
+
blockSize: body.blockSize,
|
|
75
75
|
};
|
|
76
76
|
},
|
|
77
77
|
'bottom-center': ({ body, trigger, arrow }) => {
|
|
78
78
|
return {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
79
|
+
insetBlockStart: trigger.insetBlockStart + trigger.blockSize + arrow.blockSize,
|
|
80
|
+
insetInlineStart: trigger.insetInlineStart + trigger.inlineSize / 2 - body.inlineSize / 2,
|
|
81
|
+
inlineSize: body.inlineSize,
|
|
82
|
+
blockSize: body.blockSize,
|
|
83
83
|
};
|
|
84
84
|
},
|
|
85
85
|
'bottom-right': ({ body, trigger, arrow }) => {
|
|
86
86
|
return {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
87
|
+
insetBlockStart: trigger.insetBlockStart + trigger.blockSize + arrow.blockSize,
|
|
88
|
+
insetInlineStart: trigger.insetInlineStart + trigger.inlineSize / 2 - ARROW_OFFSET - arrow.inlineSize / 2,
|
|
89
|
+
inlineSize: body.inlineSize,
|
|
90
|
+
blockSize: body.blockSize,
|
|
91
91
|
};
|
|
92
92
|
},
|
|
93
93
|
'bottom-left': ({ body, trigger, arrow }) => {
|
|
94
94
|
return {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
95
|
+
insetBlockStart: trigger.insetBlockStart + trigger.blockSize + arrow.blockSize,
|
|
96
|
+
insetInlineStart: trigger.insetInlineStart + trigger.inlineSize / 2 + ARROW_OFFSET + arrow.inlineSize / 2 - body.inlineSize,
|
|
97
|
+
inlineSize: body.inlineSize,
|
|
98
|
+
blockSize: body.blockSize,
|
|
99
99
|
};
|
|
100
100
|
},
|
|
101
101
|
'right-top': ({ body, trigger, arrow }) => {
|
|
102
102
|
return {
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
103
|
+
insetBlockStart: trigger.insetBlockStart + trigger.blockSize / 2 - ARROW_OFFSET - arrow.blockSize,
|
|
104
|
+
insetInlineStart: trigger.insetInlineStart + trigger.inlineSize + arrow.blockSize,
|
|
105
|
+
inlineSize: body.inlineSize,
|
|
106
|
+
blockSize: body.blockSize,
|
|
107
107
|
};
|
|
108
108
|
},
|
|
109
109
|
'right-bottom': ({ body, trigger, arrow }) => {
|
|
110
110
|
return {
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
111
|
+
insetBlockStart: trigger.insetBlockStart + trigger.blockSize / 2 - body.blockSize + ARROW_OFFSET + arrow.blockSize,
|
|
112
|
+
insetInlineStart: trigger.insetInlineStart + trigger.inlineSize + arrow.blockSize,
|
|
113
|
+
inlineSize: body.inlineSize,
|
|
114
|
+
blockSize: body.blockSize,
|
|
115
115
|
};
|
|
116
116
|
},
|
|
117
117
|
'left-top': ({ body, trigger, arrow }) => {
|
|
118
118
|
return {
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
119
|
+
insetBlockStart: trigger.insetBlockStart + trigger.blockSize / 2 - ARROW_OFFSET - arrow.blockSize,
|
|
120
|
+
insetInlineStart: trigger.insetInlineStart - body.inlineSize - arrow.blockSize,
|
|
121
|
+
inlineSize: body.inlineSize,
|
|
122
|
+
blockSize: body.blockSize,
|
|
123
123
|
};
|
|
124
124
|
},
|
|
125
125
|
'left-bottom': ({ body, trigger, arrow }) => {
|
|
126
126
|
return {
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
127
|
+
insetBlockStart: trigger.insetBlockStart + trigger.blockSize / 2 - body.blockSize + ARROW_OFFSET + arrow.blockSize,
|
|
128
|
+
insetInlineStart: trigger.insetInlineStart - body.inlineSize - arrow.blockSize,
|
|
129
|
+
inlineSize: body.inlineSize,
|
|
130
|
+
blockSize: body.blockSize,
|
|
131
131
|
};
|
|
132
132
|
},
|
|
133
133
|
};
|
|
134
134
|
function fitIntoContainer(inner, outer) {
|
|
135
|
-
let {
|
|
135
|
+
let { insetInlineStart, inlineSize, insetBlockStart, blockSize } = inner;
|
|
136
136
|
// Adjust left boundary.
|
|
137
|
-
if (
|
|
138
|
-
|
|
139
|
-
|
|
137
|
+
if (insetInlineStart < outer.insetInlineStart) {
|
|
138
|
+
inlineSize = insetInlineStart + inlineSize - outer.insetInlineStart;
|
|
139
|
+
insetInlineStart = outer.insetInlineStart;
|
|
140
140
|
}
|
|
141
141
|
// Adjust right boundary.
|
|
142
|
-
else if (
|
|
143
|
-
|
|
142
|
+
else if (insetInlineStart + inlineSize > outer.insetInlineStart + outer.inlineSize) {
|
|
143
|
+
inlineSize = outer.insetInlineStart + outer.inlineSize - insetInlineStart;
|
|
144
144
|
}
|
|
145
145
|
// Adjust top boundary.
|
|
146
|
-
if (
|
|
147
|
-
|
|
148
|
-
|
|
146
|
+
if (insetBlockStart < outer.insetBlockStart) {
|
|
147
|
+
blockSize = insetBlockStart + blockSize - outer.insetBlockStart;
|
|
148
|
+
insetBlockStart = outer.insetBlockStart;
|
|
149
149
|
}
|
|
150
150
|
// Adjust bottom boundary.
|
|
151
|
-
else if (
|
|
152
|
-
|
|
151
|
+
else if (insetBlockStart + blockSize > outer.insetBlockStart + outer.blockSize) {
|
|
152
|
+
blockSize = outer.insetBlockStart + outer.blockSize - insetBlockStart;
|
|
153
153
|
}
|
|
154
|
-
return {
|
|
154
|
+
return { insetInlineStart, inlineSize, insetBlockStart, blockSize };
|
|
155
155
|
}
|
|
156
156
|
function getTallestRect(rect1, rect2) {
|
|
157
|
-
return rect1.
|
|
157
|
+
return rect1.blockSize >= rect2.blockSize ? rect1 : rect2;
|
|
158
158
|
}
|
|
159
159
|
function getIntersection(rectangles) {
|
|
160
160
|
let boundingBox = null;
|
|
@@ -163,18 +163,18 @@ function getIntersection(rectangles) {
|
|
|
163
163
|
boundingBox = currentRect;
|
|
164
164
|
continue;
|
|
165
165
|
}
|
|
166
|
-
const
|
|
167
|
-
const
|
|
168
|
-
const
|
|
169
|
-
const
|
|
170
|
-
if (
|
|
166
|
+
const insetInlineStart = Math.max(boundingBox.insetInlineStart, currentRect.insetInlineStart);
|
|
167
|
+
const insetBlockStart = Math.max(boundingBox.insetBlockStart, currentRect.insetBlockStart);
|
|
168
|
+
const insetInlineEnd = Math.min(boundingBox.insetInlineStart + boundingBox.inlineSize, currentRect.insetInlineStart + currentRect.inlineSize);
|
|
169
|
+
const insetBlockEnd = Math.min(boundingBox.insetBlockStart + boundingBox.blockSize, currentRect.insetBlockStart + currentRect.blockSize);
|
|
170
|
+
if (insetInlineEnd < insetInlineStart || insetBlockEnd < insetBlockStart) {
|
|
171
171
|
return null;
|
|
172
172
|
}
|
|
173
173
|
boundingBox = {
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
174
|
+
insetInlineStart,
|
|
175
|
+
insetBlockStart,
|
|
176
|
+
inlineSize: insetInlineEnd - insetInlineStart,
|
|
177
|
+
blockSize: insetBlockEnd - insetBlockStart,
|
|
178
178
|
};
|
|
179
179
|
}
|
|
180
180
|
return boundingBox;
|
|
@@ -184,7 +184,7 @@ function getIntersection(rectangles) {
|
|
|
184
184
|
*/
|
|
185
185
|
export function intersectRectangles(rectangles) {
|
|
186
186
|
const boundingBox = getIntersection(rectangles);
|
|
187
|
-
return boundingBox && boundingBox.
|
|
187
|
+
return boundingBox && boundingBox.blockSize * boundingBox.inlineSize;
|
|
188
188
|
}
|
|
189
189
|
/**
|
|
190
190
|
* A functions that returns the correct popover position based on screen dimensions.
|
|
@@ -203,7 +203,7 @@ renderWithPortal, allowVerticalOverflow, }) {
|
|
|
203
203
|
const visibleArea = renderWithPortal
|
|
204
204
|
? getIntersection([rect, viewport])
|
|
205
205
|
: getIntersection([rect, viewport, container]);
|
|
206
|
-
const fitsWithoutOverflow = visibleArea && visibleArea.
|
|
206
|
+
const fitsWithoutOverflow = visibleArea && visibleArea.inlineSize === body.inlineSize && visibleArea.blockSize === body.blockSize;
|
|
207
207
|
if (fitsWithoutOverflow) {
|
|
208
208
|
return { internalPosition, rect };
|
|
209
209
|
}
|
|
@@ -220,15 +220,15 @@ renderWithPortal, allowVerticalOverflow, }) {
|
|
|
220
220
|
const tallestBoundingContainer = getTallestRect(viewport, container);
|
|
221
221
|
const boundingContainer = allowVerticalOverflow && isTopOrBottom(internalPosition)
|
|
222
222
|
? {
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
223
|
+
insetBlockStart: tallestBoundingContainer.insetBlockStart,
|
|
224
|
+
blockSize: tallestBoundingContainer.blockSize,
|
|
225
|
+
insetInlineStart: viewport.insetInlineStart,
|
|
226
|
+
inlineSize: viewport.inlineSize,
|
|
227
227
|
}
|
|
228
228
|
: viewport;
|
|
229
229
|
const optimizedRect = fitIntoContainer(rect, boundingContainer);
|
|
230
230
|
// If largest possible rect is shorter than original - set body scroll.
|
|
231
|
-
const scrollable = optimizedRect.
|
|
231
|
+
const scrollable = optimizedRect.blockSize < rect.blockSize;
|
|
232
232
|
return { internalPosition, rect: optimizedRect, scrollable };
|
|
233
233
|
}
|
|
234
234
|
function getBestOption(option1, option2) {
|
|
@@ -241,11 +241,11 @@ function getBestOption(option1, option2) {
|
|
|
241
241
|
return option2;
|
|
242
242
|
}
|
|
243
243
|
// Only if none of the two options overflows horizontally, choose the best based on the visible height.
|
|
244
|
-
if (option1.visibleArea.
|
|
245
|
-
return option1.visibleArea.
|
|
244
|
+
if (option1.visibleArea.inlineSize === option2.visibleArea.inlineSize) {
|
|
245
|
+
return option1.visibleArea.blockSize > option2.visibleArea.blockSize ? option1 : option2;
|
|
246
246
|
}
|
|
247
247
|
// Otherwise, choose the option that is less cut off horizontally.
|
|
248
|
-
return option1.visibleArea.
|
|
248
|
+
return option1.visibleArea.inlineSize > option2.visibleArea.inlineSize ? option1 : option2;
|
|
249
249
|
}
|
|
250
250
|
export function getOffsetDimensions(element) {
|
|
251
251
|
return { offsetHeight: element.offsetHeight, offsetWidth: element.offsetWidth };
|
|
@@ -253,8 +253,8 @@ export function getOffsetDimensions(element) {
|
|
|
253
253
|
export function getDimensions(element) {
|
|
254
254
|
const computedStyle = getComputedStyle(element);
|
|
255
255
|
return {
|
|
256
|
-
|
|
257
|
-
|
|
256
|
+
inlineSize: parseFloat(computedStyle.inlineSize),
|
|
257
|
+
blockSize: parseFloat(computedStyle.blockSize),
|
|
258
258
|
};
|
|
259
259
|
}
|
|
260
260
|
function isTopOrBottom(internalPosition) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"positions.js","sourceRoot":"","sources":["../../../../src/popover/utils/positions.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n// SPDX-License-Identifier: Apache-2.0\nimport { PopoverProps, InternalPosition, BoundingBox, Dimensions } from '../interfaces';\n\n// A structure describing how the popover should be positioned\ninterface CalculatedPosition {\n scrollable?: boolean;\n internalPosition: InternalPosition;\n rect: BoundingBox;\n}\n\ninterface ElementGroup {\n body: Dimensions;\n trigger: BoundingBox;\n arrow: Dimensions;\n}\n\nconst ARROW_OFFSET = 12;\n\nexport const PRIORITY_MAPPING: Record<PopoverProps.Position, InternalPosition[]> = {\n top: [\n 'top-center',\n 'top-right',\n 'top-left',\n 'bottom-center',\n 'bottom-right',\n 'bottom-left',\n 'right-top',\n 'right-bottom',\n 'left-top',\n 'left-bottom',\n ],\n bottom: [\n 'bottom-center',\n 'bottom-right',\n 'bottom-left',\n 'top-center',\n 'top-right',\n 'top-left',\n 'right-top',\n 'right-bottom',\n 'left-top',\n 'left-bottom',\n ],\n left: [\n 'left-top',\n 'left-bottom',\n 'right-top',\n 'right-bottom',\n 'bottom-center',\n 'top-center',\n 'bottom-left',\n 'top-left',\n 'bottom-right',\n 'top-right',\n ],\n right: [\n 'right-top',\n 'right-bottom',\n 'left-top',\n 'left-bottom',\n 'bottom-center',\n 'top-center',\n 'bottom-right',\n 'top-right',\n 'bottom-left',\n 'top-left',\n ],\n};\n\nconst RECTANGLE_CALCULATIONS: Record<InternalPosition, (r: ElementGroup) => BoundingBox> = {\n 'top-center': ({ body, trigger, arrow }) => {\n return {\n top: trigger.top - body.height - arrow.height,\n left: trigger.left + trigger.width / 2 - body.width / 2,\n width: body.width,\n height: body.height,\n };\n },\n 'top-right': ({ body, trigger, arrow }) => {\n return {\n top: trigger.top - body.height - arrow.height,\n left: trigger.left + trigger.width / 2 - ARROW_OFFSET - arrow.width / 2,\n width: body.width,\n height: body.height,\n };\n },\n 'top-left': ({ body, trigger, arrow }) => {\n return {\n top: trigger.top - body.height - arrow.height,\n left: trigger.left + trigger.width / 2 + ARROW_OFFSET + arrow.width / 2 - body.width,\n width: body.width,\n height: body.height,\n };\n },\n 'bottom-center': ({ body, trigger, arrow }) => {\n return {\n top: trigger.top + trigger.height + arrow.height,\n left: trigger.left + trigger.width / 2 - body.width / 2,\n width: body.width,\n height: body.height,\n };\n },\n 'bottom-right': ({ body, trigger, arrow }) => {\n return {\n top: trigger.top + trigger.height + arrow.height,\n left: trigger.left + trigger.width / 2 - ARROW_OFFSET - arrow.width / 2,\n width: body.width,\n height: body.height,\n };\n },\n 'bottom-left': ({ body, trigger, arrow }) => {\n return {\n top: trigger.top + trigger.height + arrow.height,\n left: trigger.left + trigger.width / 2 + ARROW_OFFSET + arrow.width / 2 - body.width,\n width: body.width,\n height: body.height,\n };\n },\n 'right-top': ({ body, trigger, arrow }) => {\n return {\n top: trigger.top + trigger.height / 2 - ARROW_OFFSET - arrow.height,\n left: trigger.left + trigger.width + arrow.height,\n width: body.width,\n height: body.height,\n };\n },\n 'right-bottom': ({ body, trigger, arrow }) => {\n return {\n top: trigger.top + trigger.height / 2 - body.height + ARROW_OFFSET + arrow.height,\n left: trigger.left + trigger.width + arrow.height,\n width: body.width,\n height: body.height,\n };\n },\n 'left-top': ({ body, trigger, arrow }) => {\n return {\n top: trigger.top + trigger.height / 2 - ARROW_OFFSET - arrow.height,\n left: trigger.left - body.width - arrow.height,\n width: body.width,\n height: body.height,\n };\n },\n 'left-bottom': ({ body, trigger, arrow }) => {\n return {\n top: trigger.top + trigger.height / 2 - body.height + ARROW_OFFSET + arrow.height,\n left: trigger.left - body.width - arrow.height,\n width: body.width,\n height: body.height,\n };\n },\n};\n\nfunction fitIntoContainer(inner: BoundingBox, outer: BoundingBox): BoundingBox {\n let { left, width, top, height } = inner;\n\n // Adjust left boundary.\n if (left < outer.left) {\n width = left + width - outer.left;\n left = outer.left;\n }\n // Adjust right boundary.\n else if (left + width > outer.left + outer.width) {\n width = outer.left + outer.width - left;\n }\n // Adjust top boundary.\n if (top < outer.top) {\n height = top + height - outer.top;\n top = outer.top;\n }\n // Adjust bottom boundary.\n else if (top + height > outer.top + outer.height) {\n height = outer.top + outer.height - top;\n }\n\n return { left, width, top, height };\n}\n\nfunction getTallestRect(rect1: BoundingBox, rect2: BoundingBox): BoundingBox {\n return rect1.height >= rect2.height ? rect1 : rect2;\n}\n\nfunction getIntersection(rectangles: BoundingBox[]): BoundingBox | null {\n let boundingBox: BoundingBox | null = null;\n for (const currentRect of rectangles) {\n if (!boundingBox) {\n boundingBox = currentRect;\n continue;\n }\n const left = Math.max(boundingBox.left, currentRect.left);\n const top = Math.max(boundingBox.top, currentRect.top);\n const right = Math.min(boundingBox.left + boundingBox.width, currentRect.left + currentRect.width);\n const bottom = Math.min(boundingBox.top + boundingBox.height, currentRect.top + currentRect.height);\n if (right < left || bottom < top) {\n return null;\n }\n boundingBox = {\n left,\n top,\n width: right - left,\n height: bottom - top,\n };\n }\n return boundingBox;\n}\n\n/**\n * Returns the area of the intersection of passed in rectangles or a null, if there is no intersection\n */\nexport function intersectRectangles(rectangles: BoundingBox[]): number | null {\n const boundingBox: BoundingBox | null = getIntersection(rectangles);\n return boundingBox && boundingBox.height * boundingBox.width;\n}\n\ntype CandidatePosition = CalculatedPosition & { visibleArea: BoundingBox | null };\n\n/**\n * A functions that returns the correct popover position based on screen dimensions.\n */\nexport function calculatePosition({\n preferredPosition,\n fixedInternalPosition,\n trigger,\n arrow,\n body,\n container,\n viewport,\n // the popover is only bound by the viewport if it is rendered in a portal\n renderWithPortal,\n allowVerticalOverflow,\n}: {\n preferredPosition: PopoverProps.Position;\n fixedInternalPosition?: InternalPosition;\n trigger: BoundingBox;\n arrow: Dimensions;\n body: Dimensions;\n container: BoundingBox;\n viewport: BoundingBox;\n // the popover is only bound by the viewport if it is rendered in a portal\n renderWithPortal?: boolean;\n allowVerticalOverflow?: boolean;\n}): CalculatedPosition {\n let bestOption: CandidatePosition | null = null;\n\n // If a fixed internal position is passed, only consider this one.\n const preferredInternalPositions = fixedInternalPosition\n ? [fixedInternalPosition]\n : PRIORITY_MAPPING[preferredPosition];\n\n // Attempt to position the popover based on the priority list for this position.\n for (const internalPosition of preferredInternalPositions) {\n const rect = RECTANGLE_CALCULATIONS[internalPosition]({ body, trigger, arrow });\n const visibleArea = renderWithPortal\n ? getIntersection([rect, viewport])\n : getIntersection([rect, viewport, container]);\n\n const fitsWithoutOverflow = visibleArea && visibleArea.width === body.width && visibleArea.height === body.height;\n\n if (fitsWithoutOverflow) {\n return { internalPosition, rect };\n }\n\n const newOption = { rect, internalPosition, visibleArea };\n bestOption = getBestOption(newOption, bestOption);\n }\n\n // Use best possible placement.\n const internalPosition = bestOption?.internalPosition || 'right-top';\n // Get default rect for that placement.\n const rect = RECTANGLE_CALCULATIONS[internalPosition]({ body, trigger, arrow });\n\n // Get largest possible rect that fits into the viewport or container.\n\n // We allow the popover to overflow the viewport if allowVerticalOverflow is true _and_ the popover will be anchored to the top or the bottom.\n // If it is anchored to the right or left, we consider that it should have enough vertical space so that applying scroll to it is a better option.\n const tallestBoundingContainer = getTallestRect(viewport, container);\n const boundingContainer =\n allowVerticalOverflow && isTopOrBottom(internalPosition)\n ? {\n top: tallestBoundingContainer.top,\n height: tallestBoundingContainer.height,\n left: viewport.left,\n width: viewport.width,\n }\n : viewport;\n\n const optimizedRect = fitIntoContainer(rect, boundingContainer);\n\n // If largest possible rect is shorter than original - set body scroll.\n const scrollable = optimizedRect.height < rect.height;\n\n return { internalPosition, rect: optimizedRect, scrollable };\n}\n\nfunction getBestOption(option1: CandidatePosition, option2: CandidatePosition | null) {\n // Within calculatePosition, the only case where option2 will not be defined will be in the first call.\n // The only case where the visibleArea of an option will be null is when the popover is totally outside of the viewport.\n if (!option2?.visibleArea) {\n return option1;\n }\n if (!option1.visibleArea) {\n return option2;\n }\n // Only if none of the two options overflows horizontally, choose the best based on the visible height.\n if (option1.visibleArea.width === option2.visibleArea.width) {\n return option1.visibleArea.height > option2.visibleArea.height ? option1 : option2;\n }\n // Otherwise, choose the option that is less cut off horizontally.\n return option1.visibleArea.width > option2.visibleArea.width ? option1 : option2;\n}\n\nexport function getOffsetDimensions(element: HTMLElement) {\n return { offsetHeight: element.offsetHeight, offsetWidth: element.offsetWidth };\n}\n\nexport function getDimensions(element: HTMLElement) {\n const computedStyle = getComputedStyle(element);\n return {\n width: parseFloat(computedStyle.width),\n height: parseFloat(computedStyle.height),\n };\n}\n\nfunction isTopOrBottom(internalPosition: InternalPosition) {\n return ['top', 'bottom'].includes(internalPosition.split('-')[0]);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"positions.js","sourceRoot":"","sources":["../../../../src/popover/utils/positions.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n// SPDX-License-Identifier: Apache-2.0\nimport { PopoverProps, InternalPosition, BoundingBox, Dimensions } from '../interfaces';\n\n// A structure describing how the popover should be positioned\ninterface CalculatedPosition {\n scrollable?: boolean;\n internalPosition: InternalPosition;\n rect: BoundingBox;\n}\n\ninterface ElementGroup {\n body: Dimensions;\n trigger: BoundingBox;\n arrow: Dimensions;\n}\n\nconst ARROW_OFFSET = 12;\n\nexport const PRIORITY_MAPPING: Record<PopoverProps.Position, InternalPosition[]> = {\n top: [\n 'top-center',\n 'top-right',\n 'top-left',\n 'bottom-center',\n 'bottom-right',\n 'bottom-left',\n 'right-top',\n 'right-bottom',\n 'left-top',\n 'left-bottom',\n ],\n bottom: [\n 'bottom-center',\n 'bottom-right',\n 'bottom-left',\n 'top-center',\n 'top-right',\n 'top-left',\n 'right-top',\n 'right-bottom',\n 'left-top',\n 'left-bottom',\n ],\n left: [\n 'left-top',\n 'left-bottom',\n 'right-top',\n 'right-bottom',\n 'bottom-center',\n 'top-center',\n 'bottom-left',\n 'top-left',\n 'bottom-right',\n 'top-right',\n ],\n right: [\n 'right-top',\n 'right-bottom',\n 'left-top',\n 'left-bottom',\n 'bottom-center',\n 'top-center',\n 'bottom-right',\n 'top-right',\n 'bottom-left',\n 'top-left',\n ],\n};\n\nconst RECTANGLE_CALCULATIONS: Record<InternalPosition, (r: ElementGroup) => BoundingBox> = {\n 'top-center': ({ body, trigger, arrow }) => {\n return {\n insetBlockStart: trigger.insetBlockStart - body.blockSize - arrow.blockSize,\n insetInlineStart: trigger.insetInlineStart + trigger.inlineSize / 2 - body.inlineSize / 2,\n inlineSize: body.inlineSize,\n blockSize: body.blockSize,\n };\n },\n 'top-right': ({ body, trigger, arrow }) => {\n return {\n insetBlockStart: trigger.insetBlockStart - body.blockSize - arrow.blockSize,\n insetInlineStart: trigger.insetInlineStart + trigger.inlineSize / 2 - ARROW_OFFSET - arrow.inlineSize / 2,\n inlineSize: body.inlineSize,\n blockSize: body.blockSize,\n };\n },\n 'top-left': ({ body, trigger, arrow }) => {\n return {\n insetBlockStart: trigger.insetBlockStart - body.blockSize - arrow.blockSize,\n insetInlineStart:\n trigger.insetInlineStart + trigger.inlineSize / 2 + ARROW_OFFSET + arrow.inlineSize / 2 - body.inlineSize,\n inlineSize: body.inlineSize,\n blockSize: body.blockSize,\n };\n },\n 'bottom-center': ({ body, trigger, arrow }) => {\n return {\n insetBlockStart: trigger.insetBlockStart + trigger.blockSize + arrow.blockSize,\n insetInlineStart: trigger.insetInlineStart + trigger.inlineSize / 2 - body.inlineSize / 2,\n inlineSize: body.inlineSize,\n blockSize: body.blockSize,\n };\n },\n 'bottom-right': ({ body, trigger, arrow }) => {\n return {\n insetBlockStart: trigger.insetBlockStart + trigger.blockSize + arrow.blockSize,\n insetInlineStart: trigger.insetInlineStart + trigger.inlineSize / 2 - ARROW_OFFSET - arrow.inlineSize / 2,\n inlineSize: body.inlineSize,\n blockSize: body.blockSize,\n };\n },\n 'bottom-left': ({ body, trigger, arrow }) => {\n return {\n insetBlockStart: trigger.insetBlockStart + trigger.blockSize + arrow.blockSize,\n insetInlineStart:\n trigger.insetInlineStart + trigger.inlineSize / 2 + ARROW_OFFSET + arrow.inlineSize / 2 - body.inlineSize,\n inlineSize: body.inlineSize,\n blockSize: body.blockSize,\n };\n },\n 'right-top': ({ body, trigger, arrow }) => {\n return {\n insetBlockStart: trigger.insetBlockStart + trigger.blockSize / 2 - ARROW_OFFSET - arrow.blockSize,\n insetInlineStart: trigger.insetInlineStart + trigger.inlineSize + arrow.blockSize,\n inlineSize: body.inlineSize,\n blockSize: body.blockSize,\n };\n },\n 'right-bottom': ({ body, trigger, arrow }) => {\n return {\n insetBlockStart:\n trigger.insetBlockStart + trigger.blockSize / 2 - body.blockSize + ARROW_OFFSET + arrow.blockSize,\n insetInlineStart: trigger.insetInlineStart + trigger.inlineSize + arrow.blockSize,\n inlineSize: body.inlineSize,\n blockSize: body.blockSize,\n };\n },\n 'left-top': ({ body, trigger, arrow }) => {\n return {\n insetBlockStart: trigger.insetBlockStart + trigger.blockSize / 2 - ARROW_OFFSET - arrow.blockSize,\n insetInlineStart: trigger.insetInlineStart - body.inlineSize - arrow.blockSize,\n inlineSize: body.inlineSize,\n blockSize: body.blockSize,\n };\n },\n 'left-bottom': ({ body, trigger, arrow }) => {\n return {\n insetBlockStart:\n trigger.insetBlockStart + trigger.blockSize / 2 - body.blockSize + ARROW_OFFSET + arrow.blockSize,\n insetInlineStart: trigger.insetInlineStart - body.inlineSize - arrow.blockSize,\n inlineSize: body.inlineSize,\n blockSize: body.blockSize,\n };\n },\n};\n\nfunction fitIntoContainer(inner: BoundingBox, outer: BoundingBox): BoundingBox {\n let { insetInlineStart, inlineSize, insetBlockStart, blockSize } = inner;\n\n // Adjust left boundary.\n if (insetInlineStart < outer.insetInlineStart) {\n inlineSize = insetInlineStart + inlineSize - outer.insetInlineStart;\n insetInlineStart = outer.insetInlineStart;\n }\n // Adjust right boundary.\n else if (insetInlineStart + inlineSize > outer.insetInlineStart + outer.inlineSize) {\n inlineSize = outer.insetInlineStart + outer.inlineSize - insetInlineStart;\n }\n // Adjust top boundary.\n if (insetBlockStart < outer.insetBlockStart) {\n blockSize = insetBlockStart + blockSize - outer.insetBlockStart;\n insetBlockStart = outer.insetBlockStart;\n }\n // Adjust bottom boundary.\n else if (insetBlockStart + blockSize > outer.insetBlockStart + outer.blockSize) {\n blockSize = outer.insetBlockStart + outer.blockSize - insetBlockStart;\n }\n\n return { insetInlineStart, inlineSize, insetBlockStart, blockSize };\n}\n\nfunction getTallestRect(rect1: BoundingBox, rect2: BoundingBox): BoundingBox {\n return rect1.blockSize >= rect2.blockSize ? rect1 : rect2;\n}\n\nfunction getIntersection(rectangles: BoundingBox[]): BoundingBox | null {\n let boundingBox: BoundingBox | null = null;\n for (const currentRect of rectangles) {\n if (!boundingBox) {\n boundingBox = currentRect;\n continue;\n }\n const insetInlineStart = Math.max(boundingBox.insetInlineStart, currentRect.insetInlineStart);\n const insetBlockStart = Math.max(boundingBox.insetBlockStart, currentRect.insetBlockStart);\n const insetInlineEnd = Math.min(\n boundingBox.insetInlineStart + boundingBox.inlineSize,\n currentRect.insetInlineStart + currentRect.inlineSize\n );\n const insetBlockEnd = Math.min(\n boundingBox.insetBlockStart + boundingBox.blockSize,\n currentRect.insetBlockStart + currentRect.blockSize\n );\n\n if (insetInlineEnd < insetInlineStart || insetBlockEnd < insetBlockStart) {\n return null;\n }\n boundingBox = {\n insetInlineStart,\n insetBlockStart,\n inlineSize: insetInlineEnd - insetInlineStart,\n blockSize: insetBlockEnd - insetBlockStart,\n };\n }\n return boundingBox;\n}\n\n/**\n * Returns the area of the intersection of passed in rectangles or a null, if there is no intersection\n */\nexport function intersectRectangles(rectangles: BoundingBox[]): number | null {\n const boundingBox: BoundingBox | null = getIntersection(rectangles);\n return boundingBox && boundingBox.blockSize * boundingBox.inlineSize;\n}\n\ntype CandidatePosition = CalculatedPosition & { visibleArea: BoundingBox | null };\n\n/**\n * A functions that returns the correct popover position based on screen dimensions.\n */\nexport function calculatePosition({\n preferredPosition,\n fixedInternalPosition,\n trigger,\n arrow,\n body,\n container,\n viewport,\n // the popover is only bound by the viewport if it is rendered in a portal\n renderWithPortal,\n allowVerticalOverflow,\n}: {\n preferredPosition: PopoverProps.Position;\n fixedInternalPosition?: InternalPosition;\n trigger: BoundingBox;\n arrow: Dimensions;\n body: Dimensions;\n container: BoundingBox;\n viewport: BoundingBox;\n // the popover is only bound by the viewport if it is rendered in a portal\n renderWithPortal?: boolean;\n allowVerticalOverflow?: boolean;\n}): CalculatedPosition {\n let bestOption: CandidatePosition | null = null;\n\n // If a fixed internal position is passed, only consider this one.\n const preferredInternalPositions = fixedInternalPosition\n ? [fixedInternalPosition]\n : PRIORITY_MAPPING[preferredPosition];\n\n // Attempt to position the popover based on the priority list for this position.\n for (const internalPosition of preferredInternalPositions) {\n const rect = RECTANGLE_CALCULATIONS[internalPosition]({ body, trigger, arrow });\n const visibleArea = renderWithPortal\n ? getIntersection([rect, viewport])\n : getIntersection([rect, viewport, container]);\n\n const fitsWithoutOverflow =\n visibleArea && visibleArea.inlineSize === body.inlineSize && visibleArea.blockSize === body.blockSize;\n\n if (fitsWithoutOverflow) {\n return { internalPosition, rect };\n }\n\n const newOption = { rect, internalPosition, visibleArea };\n bestOption = getBestOption(newOption, bestOption);\n }\n\n // Use best possible placement.\n const internalPosition = bestOption?.internalPosition || 'right-top';\n // Get default rect for that placement.\n const rect = RECTANGLE_CALCULATIONS[internalPosition]({ body, trigger, arrow });\n\n // Get largest possible rect that fits into the viewport or container.\n\n // We allow the popover to overflow the viewport if allowVerticalOverflow is true _and_ the popover will be anchored to the top or the bottom.\n // If it is anchored to the right or left, we consider that it should have enough vertical space so that applying scroll to it is a better option.\n const tallestBoundingContainer = getTallestRect(viewport, container);\n const boundingContainer =\n allowVerticalOverflow && isTopOrBottom(internalPosition)\n ? {\n insetBlockStart: tallestBoundingContainer.insetBlockStart,\n blockSize: tallestBoundingContainer.blockSize,\n insetInlineStart: viewport.insetInlineStart,\n inlineSize: viewport.inlineSize,\n }\n : viewport;\n\n const optimizedRect = fitIntoContainer(rect, boundingContainer);\n\n // If largest possible rect is shorter than original - set body scroll.\n const scrollable = optimizedRect.blockSize < rect.blockSize;\n\n return { internalPosition, rect: optimizedRect, scrollable };\n}\n\nfunction getBestOption(option1: CandidatePosition, option2: CandidatePosition | null) {\n // Within calculatePosition, the only case where option2 will not be defined will be in the first call.\n // The only case where the visibleArea of an option will be null is when the popover is totally outside of the viewport.\n if (!option2?.visibleArea) {\n return option1;\n }\n if (!option1.visibleArea) {\n return option2;\n }\n // Only if none of the two options overflows horizontally, choose the best based on the visible height.\n if (option1.visibleArea.inlineSize === option2.visibleArea.inlineSize) {\n return option1.visibleArea.blockSize > option2.visibleArea.blockSize ? option1 : option2;\n }\n // Otherwise, choose the option that is less cut off horizontally.\n return option1.visibleArea.inlineSize > option2.visibleArea.inlineSize ? option1 : option2;\n}\n\nexport function getOffsetDimensions(element: HTMLElement) {\n return { offsetHeight: element.offsetHeight, offsetWidth: element.offsetWidth };\n}\n\nexport function getDimensions(element: HTMLElement) {\n const computedStyle = getComputedStyle(element);\n return {\n inlineSize: parseFloat(computedStyle.inlineSize),\n blockSize: parseFloat(computedStyle.blockSize),\n };\n}\n\nfunction isTopOrBottom(internalPosition: InternalPosition) {\n return ['top', 'bottom'].includes(internalPosition.split('-')[0]);\n}\n"]}
|