ropav 0.15.0 → 0.15.1
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/dist/utils/position.d.ts +1 -1
- package/dist/utils/position.js +66 -52
- package/dist/version.js +1 -1
- package/package.json +2 -2
package/dist/utils/position.d.ts
CHANGED
|
@@ -74,7 +74,7 @@ export interface PositionResult {
|
|
|
74
74
|
/** The element's rectangle, ignoring any scale transform when asked. */
|
|
75
75
|
export declare const getRect: (node: Element, ignoreScale: boolean) => Offset;
|
|
76
76
|
/** @private Exported for tests, which drive the arithmetic without a real layout. */
|
|
77
|
-
export declare const calculatePositionInternal: (placementInput: Placement, childOffset: Offset, overlaySize: Offset, margins: Position, padding: number, flip: boolean,
|
|
77
|
+
export declare const calculatePositionInternal: (placementInput: Placement, childOffset: Offset, overlaySize: Offset, margins: Position, padding: number, flip: boolean, boundary: Offset, containerDimensions: Dimensions, viewport: Offset | null, offset: number, crossOffset: number, isContainerPositioned: boolean, userSetMaxHeight: number | undefined, arrowSize: number, arrowBoundaryOffset: number) => PositionResult;
|
|
78
78
|
/**
|
|
79
79
|
* Where to put an overlay so it sits next to its trigger and stays inside the boundary.
|
|
80
80
|
*
|
package/dist/utils/position.js
CHANGED
|
@@ -25,8 +25,15 @@ var TOTAL_SIZE = {
|
|
|
25
25
|
};
|
|
26
26
|
var clamp = (value, min, max) => Math.min(Math.max(value, min), max);
|
|
27
27
|
var getVisualViewport = () => typeof document === "undefined" ? null : window.visualViewport;
|
|
28
|
-
/** Whether
|
|
29
|
-
var
|
|
28
|
+
/** Whether a boundary element stands for the viewport, as the body and the document element do. */
|
|
29
|
+
var isViewportElement = (node) => node.tagName === "BODY" || node.tagName === "HTML";
|
|
30
|
+
/**
|
|
31
|
+
* Whether the container is the viewport. Only the document element ever is: the body is the
|
|
32
|
+
* container only once it is positioned or a containing block, and then an overlay is placed from
|
|
33
|
+
* the body's own padding box, which a body taller than the viewport, or set apart from it by its
|
|
34
|
+
* margin, does not share with the viewport.
|
|
35
|
+
*/
|
|
36
|
+
var isViewportContainer = (node) => node === document.documentElement;
|
|
30
37
|
var isWebKit = () => typeof navigator !== "undefined" && /AppleWebKit/.test(navigator.userAgent) && !/Chrome/.test(navigator.userAgent);
|
|
31
38
|
/** The element's rectangle, ignoring any scale transform when asked. */
|
|
32
39
|
var getRect = (node, ignoreScale) => {
|
|
@@ -76,7 +83,7 @@ var getPosition = (node, parent, ignoreScale, overrideRect) => {
|
|
|
76
83
|
*/
|
|
77
84
|
var isContainingBlock = (node) => {
|
|
78
85
|
const style = window.getComputedStyle(node);
|
|
79
|
-
return style.transform !== "none" || /transform|perspective/.test(style.willChange) || style.filter !== "none" || style.contain
|
|
86
|
+
return style.transform !== "none" || /transform|perspective/.test(style.willChange) || style.filter !== "none" || /\b(layout|paint|strict|content)\b/.test(style.contain) || "backdropFilter" in style && style.backdropFilter !== "none";
|
|
80
87
|
};
|
|
81
88
|
/** The element an absolutely positioned overlay is placed relative to. */
|
|
82
89
|
var getContainingBlock = (node) => {
|
|
@@ -98,26 +105,28 @@ var getContainerDimensions = (containerNode, visualViewport) => {
|
|
|
98
105
|
let left = 0;
|
|
99
106
|
const scroll = {};
|
|
100
107
|
const isPinchZoomedIn = (visualViewport?.scale ?? 1) > 1;
|
|
101
|
-
if (containerNode
|
|
108
|
+
if (isViewportContainer(containerNode)) {
|
|
102
109
|
const documentElement = document.documentElement;
|
|
103
110
|
totalWidth = documentElement.clientWidth;
|
|
104
111
|
totalHeight = documentElement.clientHeight;
|
|
105
112
|
width = visualViewport?.width ?? totalWidth;
|
|
106
113
|
height = visualViewport?.height ?? totalHeight;
|
|
107
|
-
scroll.top = documentElement.scrollTop
|
|
108
|
-
scroll.left = documentElement.scrollLeft
|
|
114
|
+
scroll.top = documentElement.scrollTop;
|
|
115
|
+
scroll.left = documentElement.scrollLeft;
|
|
109
116
|
if (visualViewport) {
|
|
110
117
|
top = visualViewport.offsetTop;
|
|
111
118
|
left = visualViewport.offsetLeft;
|
|
112
119
|
}
|
|
113
120
|
} else {
|
|
114
|
-
({
|
|
121
|
+
({left, top} = getOffset(containerNode, false));
|
|
122
|
+
width = containerNode.clientWidth;
|
|
123
|
+
height = containerNode.clientHeight;
|
|
115
124
|
scroll.top = containerNode.scrollTop;
|
|
116
125
|
scroll.left = containerNode.scrollLeft;
|
|
117
126
|
totalWidth = width;
|
|
118
127
|
totalHeight = height;
|
|
119
128
|
}
|
|
120
|
-
if (isWebKit() && (containerNode
|
|
129
|
+
if (isWebKit() && isViewportContainer(containerNode) && isPinchZoomedIn) {
|
|
121
130
|
scroll.top = 0;
|
|
122
131
|
scroll.left = 0;
|
|
123
132
|
top = visualViewport?.pageTop ?? 0;
|
|
@@ -134,13 +143,11 @@ var getContainerDimensions = (containerNode, visualViewport) => {
|
|
|
134
143
|
};
|
|
135
144
|
};
|
|
136
145
|
/** How far the overlay must shift along `axis` to stay inside the boundary. */
|
|
137
|
-
var getDelta = (axis, offset, size,
|
|
138
|
-
const
|
|
139
|
-
const
|
|
140
|
-
const
|
|
141
|
-
const
|
|
142
|
-
const boundaryEndEdge = containerOffsetWithBoundary[axis] + boundaryScroll + boundarySize - padding;
|
|
143
|
-
const startEdgeOffset = offset - containerScroll + boundaryScroll + containerOffsetWithBoundary[axis] - boundaryDimensions[AXIS[axis]];
|
|
146
|
+
var getDelta = (axis, offset, size, boundary, containerDimensions, padding) => {
|
|
147
|
+
const boundaryStart = boundary[axis] + (containerDimensions.scroll[axis] ?? 0);
|
|
148
|
+
const boundaryStartEdge = boundaryStart + padding;
|
|
149
|
+
const boundaryEndEdge = boundaryStart + boundary[AXIS_SIZE[axis]] - padding;
|
|
150
|
+
const startEdgeOffset = offset;
|
|
144
151
|
const endEdgeOffset = startEdgeOffset + size;
|
|
145
152
|
if (startEdgeOffset < boundaryStartEdge) return boundaryStartEdge - startEdgeOffset;
|
|
146
153
|
if (endEdgeOffset > boundaryEndEdge) return Math.max(boundaryEndEdge - endEdgeOffset, boundaryStartEdge - startEdgeOffset);
|
|
@@ -189,36 +196,35 @@ var computePosition = (childOffset, overlaySize, placementInfo, offset, crossOff
|
|
|
189
196
|
} else position[axis] = Math.floor(childOffset[axis] + childOffset[size] + offset);
|
|
190
197
|
return position;
|
|
191
198
|
};
|
|
192
|
-
var getMaxHeight = (position,
|
|
199
|
+
var getMaxHeight = (position, boundary, viewport, margins, padding, overlayHeight, heightGrowthDirection, containerDimensions) => {
|
|
193
200
|
const overlayTop = (position.top != null ? position.top : containerDimensions[TOTAL_SIZE.height] - (position.bottom ?? 0) - overlayHeight) - (containerDimensions.scroll.top ?? 0);
|
|
194
|
-
const
|
|
195
|
-
const viewportTop = visualViewport?.offsetTop ?? boundaryDimensions.top;
|
|
196
|
-
const viewportBottom = visualViewport ? visualViewport.offsetTop + visualViewport.height : boundaryDimensions.top + boundaryDimensions.height;
|
|
201
|
+
const visible = viewport ?? boundary;
|
|
197
202
|
const boundingRect = {
|
|
198
|
-
bottom: Math.min(
|
|
199
|
-
top: Math.max(
|
|
203
|
+
bottom: Math.min(boundary.top + boundary.height, visible.top + visible.height),
|
|
204
|
+
top: Math.max(boundary.top, visible.top)
|
|
200
205
|
};
|
|
201
206
|
const reserved = (margins.top ?? 0) + (margins.bottom ?? 0) + padding;
|
|
202
207
|
return heightGrowthDirection !== "top" ? Math.max(0, boundingRect.bottom - overlayTop - reserved) : Math.max(0, overlayTop + overlayHeight - boundingRect.top - reserved);
|
|
203
208
|
};
|
|
204
209
|
/** How much room there is on the side the overlay wants to be on. */
|
|
205
|
-
var getAvailableSpace = (
|
|
210
|
+
var getAvailableSpace = (boundary, childOffset, margins, padding, placementInfo, containerDimensions) => {
|
|
206
211
|
const { axis, placement, size } = placementInfo;
|
|
207
|
-
const
|
|
208
|
-
|
|
209
|
-
return Math.max(0,
|
|
212
|
+
const boundaryStart = boundary[axis] + (containerDimensions.scroll[axis] ?? 0);
|
|
213
|
+
const reserved = (margins[axis] ?? 0) + (margins[FLIPPED_DIRECTION[axis]] ?? 0) + padding;
|
|
214
|
+
if (placement === axis) return Math.max(0, childOffset[axis] - boundaryStart - reserved);
|
|
215
|
+
return Math.max(0, boundaryStart + boundary[size] - childOffset[axis] - childOffset[size] - reserved);
|
|
210
216
|
};
|
|
211
217
|
/** @private Exported for tests, which drive the arithmetic without a real layout. */
|
|
212
|
-
var calculatePositionInternal = (placementInput, childOffset, overlaySize, margins, padding, flip,
|
|
218
|
+
var calculatePositionInternal = (placementInput, childOffset, overlaySize, margins, padding, flip, boundary, containerDimensions, viewport, offset, crossOffset, isContainerPositioned, userSetMaxHeight, arrowSize, arrowBoundaryOffset) => {
|
|
213
219
|
let placementInfo = parsePlacement(placementInput);
|
|
214
220
|
const { crossAxis, crossSize, size } = placementInfo;
|
|
215
221
|
let { crossPlacement, placement } = placementInfo;
|
|
216
222
|
let position = computePosition(childOffset, overlaySize, placementInfo, offset, crossOffset, isContainerPositioned, arrowSize, arrowBoundaryOffset, containerDimensions);
|
|
217
|
-
const space = getAvailableSpace(
|
|
223
|
+
const space = getAvailableSpace(boundary, childOffset, margins, padding + offset, placementInfo, containerDimensions);
|
|
218
224
|
if (flip && overlaySize[size] > space) {
|
|
219
225
|
const flippedPlacementInfo = parsePlacement(`${FLIPPED_DIRECTION[placement]} ${crossPlacement}`);
|
|
220
226
|
const flippedPosition = computePosition(childOffset, overlaySize, flippedPlacementInfo, offset, crossOffset, isContainerPositioned, arrowSize, arrowBoundaryOffset, containerDimensions);
|
|
221
|
-
if (getAvailableSpace(
|
|
227
|
+
if (getAvailableSpace(boundary, childOffset, margins, padding + offset, flippedPlacementInfo, containerDimensions) > space) {
|
|
222
228
|
placementInfo = flippedPlacementInfo;
|
|
223
229
|
position = flippedPosition;
|
|
224
230
|
}
|
|
@@ -229,12 +235,12 @@ var calculatePositionInternal = (placementInput, childOffset, overlaySize, margi
|
|
|
229
235
|
} else if (placementInfo.crossAxis === "top") {
|
|
230
236
|
if (placementInfo.crossPlacement === "bottom") heightGrowthDirection = "top";
|
|
231
237
|
}
|
|
232
|
-
position[crossAxis] += getDelta(crossAxis, position[crossAxis], overlaySize[crossSize],
|
|
233
|
-
let maxHeight = getMaxHeight(position,
|
|
238
|
+
position[crossAxis] += getDelta(crossAxis, position[crossAxis], overlaySize[crossSize], boundary, containerDimensions, padding);
|
|
239
|
+
let maxHeight = getMaxHeight(position, boundary, viewport, margins, padding, overlaySize.height, heightGrowthDirection, containerDimensions);
|
|
234
240
|
if (userSetMaxHeight && userSetMaxHeight < maxHeight) maxHeight = userSetMaxHeight;
|
|
235
241
|
overlaySize.height = Math.min(overlaySize.height, maxHeight);
|
|
236
242
|
position = computePosition(childOffset, overlaySize, placementInfo, offset, crossOffset, isContainerPositioned, arrowSize, arrowBoundaryOffset, containerDimensions);
|
|
237
|
-
position[crossAxis] += getDelta(crossAxis, position[crossAxis], overlaySize[crossSize],
|
|
243
|
+
position[crossAxis] += getDelta(crossAxis, position[crossAxis], overlaySize[crossSize], boundary, containerDimensions, padding);
|
|
238
244
|
const arrowPosition = {};
|
|
239
245
|
let origin = childOffset[crossAxis] - position[crossAxis] - (margins[AXIS[crossAxis]] ?? 0);
|
|
240
246
|
const preferredArrowPosition = origin + .5 * childOffset[crossSize];
|
|
@@ -268,11 +274,11 @@ var calculatePosition = (options) => {
|
|
|
268
274
|
const { arrowBoundaryOffset = 0, arrowSize = 0, boundaryElement, crossOffset, maxHeight, offset, overlayNode, padding, placement, shouldFlip, targetNode, targetRect } = options;
|
|
269
275
|
const visualViewport = getVisualViewport();
|
|
270
276
|
const container = overlayNode instanceof HTMLElement ? getContainingBlock(overlayNode) : document.documentElement;
|
|
271
|
-
const
|
|
277
|
+
const isContainerViewport = isViewportContainer(container);
|
|
272
278
|
const containerPositionStyle = window.getComputedStyle(container).position;
|
|
273
279
|
const isContainerPositioned = Boolean(containerPositionStyle) && containerPositionStyle !== "static";
|
|
274
|
-
const childOffset =
|
|
275
|
-
if (!
|
|
280
|
+
const childOffset = isContainerViewport ? getOffset(targetNode, false, targetRect) : getPosition(targetNode, container, false, targetRect);
|
|
281
|
+
if (!isContainerViewport) {
|
|
276
282
|
const { marginLeft, marginTop } = window.getComputedStyle(targetNode);
|
|
277
283
|
childOffset.top += parseInt(marginTop, 10) || 0;
|
|
278
284
|
childOffset.left += parseInt(marginLeft, 10) || 0;
|
|
@@ -281,26 +287,34 @@ var calculatePosition = (options) => {
|
|
|
281
287
|
const margins = getMargins(overlayNode);
|
|
282
288
|
overlaySize.width += (margins.left ?? 0) + (margins.right ?? 0);
|
|
283
289
|
overlaySize.height += (margins.top ?? 0) + (margins.bottom ?? 0);
|
|
284
|
-
const boundaryDimensions = getContainerDimensions(boundaryElement, visualViewport);
|
|
285
290
|
const containerDimensions = getContainerDimensions(container, visualViewport);
|
|
286
|
-
|
|
287
|
-
const
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
left: -(containerRect.left - boundaryDimensions.left),
|
|
293
|
-
top: -(containerRect.top - boundaryDimensions.top),
|
|
294
|
-
width: 0
|
|
295
|
-
};
|
|
296
|
-
} else if (isBoundaryViewport && isViewportContainer) containerOffsetWithBoundary = {
|
|
297
|
-
height: 0,
|
|
298
|
-
left: 0,
|
|
299
|
-
top: 0,
|
|
300
|
-
width: 0
|
|
291
|
+
const { clientHeight, clientWidth } = document.documentElement;
|
|
292
|
+
const viewportRect = {
|
|
293
|
+
height: visualViewport?.height ?? clientHeight,
|
|
294
|
+
left: visualViewport?.offsetLeft ?? 0,
|
|
295
|
+
top: visualViewport?.offsetTop ?? 0,
|
|
296
|
+
width: visualViewport?.width ?? clientWidth
|
|
301
297
|
};
|
|
302
|
-
|
|
303
|
-
|
|
298
|
+
let origin;
|
|
299
|
+
if (isContainerViewport) origin = {
|
|
300
|
+
left: viewportRect.left - containerDimensions.left,
|
|
301
|
+
top: viewportRect.top - containerDimensions.top
|
|
302
|
+
};
|
|
303
|
+
else {
|
|
304
|
+
const containerRect = container.getBoundingClientRect();
|
|
305
|
+
origin = {
|
|
306
|
+
left: containerRect.left + container.clientLeft,
|
|
307
|
+
top: containerRect.top + container.clientTop
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
const toContainer = ({ height, left, top, width }) => ({
|
|
311
|
+
height,
|
|
312
|
+
left: left - origin.left,
|
|
313
|
+
top: top - origin.top,
|
|
314
|
+
width
|
|
315
|
+
});
|
|
316
|
+
const viewport = toContainer(viewportRect);
|
|
317
|
+
return calculatePositionInternal(placement, childOffset, overlaySize, margins, padding, shouldFlip, isViewportElement(boundaryElement) ? viewport : toContainer(getRect(boundaryElement, false)), containerDimensions, visualViewport ? viewport : null, offset, crossOffset, isContainerPositioned, maxHeight, arrowSize, arrowBoundaryOffset);
|
|
304
318
|
};
|
|
305
319
|
/** Resolves the logical `start`/`end` in a placement against the writing direction. */
|
|
306
320
|
var translateRTL = (placement, direction) => direction === "rtl" ? placement.replace("start", "right").replace("end", "left") : placement.replace("start", "left").replace("end", "right");
|
package/dist/version.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ropav",
|
|
3
|
-
"version": "0.15.
|
|
3
|
+
"version": "0.15.1",
|
|
4
4
|
"description": "Vapor-native Vue 3 component library — accessible by default, styled with framework-agnostic CSS.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"components",
|
|
@@ -421,7 +421,7 @@
|
|
|
421
421
|
"@internationalized/date": "3.12.4",
|
|
422
422
|
"@internationalized/number": "3.6.8",
|
|
423
423
|
"@internationalized/string": "3.2.10",
|
|
424
|
-
"@ropav/styles": "0.15.
|
|
424
|
+
"@ropav/styles": "0.15.1"
|
|
425
425
|
},
|
|
426
426
|
"peerDependencies": {
|
|
427
427
|
"vue": "^3.6.0-rc.8"
|