react-native-popover-view
Advanced tools
Comparing version 5.0.2 to 5.1.0
@@ -271,3 +271,3 @@ var __extends = (this && this.__extends) || (function () { | ||
horizontalOffset = -displayAreaOffset.x; | ||
this.debug('calculateRectFromRef - waiting for ref to move'); | ||
this.debug('calculateRectFromRef - waiting for ref to move from', initialRect); | ||
count = 0; | ||
@@ -279,10 +279,15 @@ _c.label = 4; | ||
rect = new Rect(rect.x + horizontalOffset, rect.y + verticalOffset, rect.width, rect.height); | ||
return [4 /*yield*/, new Promise(function (resolve) { | ||
setTimeout(resolve, 100); | ||
})]; | ||
case 6: | ||
_c.sent(); | ||
// Timeout after 2 seconds | ||
if (count++ > 20) | ||
return [2 /*return*/]; | ||
_c.label = 6; | ||
case 6: | ||
if (rect.equals(initialRect) || rect.y < 0 || rect.x < 0) return [3 /*break*/, 4]; | ||
_c.label = 7; | ||
case 7: | ||
if (rect.equals(initialRect) || rect.y < -1000 || rect.x < -1000) return [3 /*break*/, 4]; | ||
_c.label = 8; | ||
case 8: | ||
this.debug('calculateRectFromRef - calculated Rect', rect); | ||
@@ -289,0 +294,0 @@ if (this._isMounted) |
@@ -10,3 +10,3 @@ import { StyleProp, ViewStyle } from 'react-native'; | ||
declare type ComputeGeometryProps = ComputeGeometryBaseProps & { | ||
placement?: Placement; | ||
placement?: Placement | Array<Placement>; | ||
previousPlacement?: Placement; | ||
@@ -13,0 +13,0 @@ fromRect: Rect | null; |
@@ -37,3 +37,3 @@ var __assign = (this && this.__assign) || function () { | ||
export function computeGeometry(options) { | ||
var requestedContentSize = options.requestedContentSize, placement = options.placement, displayArea = options.displayArea, debug = options.debug, popoverStyle = options.popoverStyle, arrowShift = options.arrowShift, popoverShift = options.popoverShift; | ||
var requestedContentSize = options.requestedContentSize, placement = options.placement, displayArea = options.displayArea, debug = options.debug, popoverStyle = options.popoverStyle, arrowShift = options.arrowShift, popoverShift = options.popoverShift, arrowSize = options.arrowSize; | ||
var newGeom = null; | ||
@@ -46,3 +46,14 @@ // Make copy so doesn't modify original | ||
var borderRadius = getBorderRadius(popoverStyle); | ||
switch (placement) { | ||
// Default to first option if given list of placements | ||
var selectedPlacement = Array.isArray(placement) ? placement[0] : placement; | ||
// If we can find a placement in the list that is better, use that | ||
if (Array.isArray(placement)) { | ||
var spaceList = generateSpaceList({ fromRect: fromRect, displayArea: displayArea, requestedContentSize: requestedContentSize, arrowSize: arrowSize }); | ||
var bestPlacements_1 = calculateBestPlacements(spaceList); | ||
var bestProvidedPlacement = placement. | ||
filter(function (p) { return p === Placement.AUTO || p === Placement.FLOATING || bestPlacements_1.includes(p); })[0]; | ||
if (bestProvidedPlacement) | ||
selectedPlacement = bestProvidedPlacement; | ||
} | ||
switch (selectedPlacement) { | ||
case Placement.TOP: | ||
@@ -289,4 +300,28 @@ newGeom = computeTopGeometry(__assign(__assign({}, options), { fromRect: fromRect, borderRadius: borderRadius })); | ||
} | ||
function generateSpaceList(_a) { | ||
var _b; | ||
var fromRect = _a.fromRect, displayArea = _a.displayArea, arrowSize = _a.arrowSize, requestedContentSize = _a.requestedContentSize; | ||
function generateOption(props) { | ||
return __assign(__assign({}, props), { fits: props.sizeAvailable >= props.sizeRequested, extraSpace: props.sizeAvailable - props.sizeRequested }); | ||
} | ||
return _b = {}, | ||
_b[Placement.LEFT] = generateOption({ | ||
sizeAvailable: fromRect.x - displayArea.x - arrowSize.width, | ||
sizeRequested: requestedContentSize.width | ||
}), | ||
_b[Placement.RIGHT] = generateOption({ | ||
sizeAvailable: displayArea.x + displayArea.width - (fromRect.x + fromRect.width) - arrowSize.width, | ||
sizeRequested: requestedContentSize.width | ||
}), | ||
_b[Placement.TOP] = generateOption({ | ||
sizeAvailable: fromRect.y - displayArea.y - arrowSize.width, | ||
sizeRequested: requestedContentSize.height | ||
}), | ||
_b[Placement.BOTTOM] = generateOption({ | ||
sizeAvailable: displayArea.y + displayArea.height - (fromRect.y + fromRect.height) - arrowSize.width, | ||
sizeRequested: requestedContentSize.height | ||
}), | ||
_b; | ||
} | ||
function computeAutoGeometry(options) { | ||
var _a; | ||
var displayArea = options.displayArea, requestedContentSize = options.requestedContentSize, fromRect = options.fromRect, previousPlacement = options.previousPlacement, debug = options.debug, arrowSize = options.arrowSize; | ||
@@ -318,22 +353,5 @@ // Keep same placement if possible (left/right) | ||
debug('computeAutoGeometry - fromRect', fromRect); | ||
var spaceList = (_a = {}, | ||
_a[Placement.LEFT] = { | ||
sizeAvailable: fromRect.x - displayArea.x - arrowSize.width, | ||
sizeRequested: requestedContentSize.width | ||
}, | ||
_a[Placement.RIGHT] = { | ||
sizeAvailable: displayArea.x + displayArea.width - (fromRect.x + fromRect.width) - arrowSize.width, | ||
sizeRequested: requestedContentSize.width | ||
}, | ||
_a[Placement.TOP] = { | ||
sizeAvailable: fromRect.y - displayArea.y - arrowSize.width, | ||
sizeRequested: requestedContentSize.height | ||
}, | ||
_a[Placement.BOTTOM] = { | ||
sizeAvailable: displayArea.y + displayArea.height - (fromRect.y + fromRect.height) - arrowSize.width, | ||
sizeRequested: requestedContentSize.height | ||
}, | ||
_a); | ||
debug('computeAutoGeometry - List of availabe space', spaceList); | ||
var bestPlacementPosition = findBestPlacement(spaceList); | ||
var spaceList = generateSpaceList({ fromRect: fromRect, displayArea: displayArea, arrowSize: arrowSize, requestedContentSize: requestedContentSize }); | ||
debug('computeAutoGeometry - List of available space', spaceList); | ||
var bestPlacementPosition = calculateBestPlacements(spaceList)[0]; | ||
debug('computeAutoGeometry - Found best postition for placement', bestPlacementPosition); | ||
@@ -349,11 +367,5 @@ switch (bestPlacementPosition) { | ||
} | ||
function findBestPlacement(spaceList) { | ||
return Object.keys(spaceList).reduce(function (bestPlacement, placement) { return ( | ||
// If it can fit, and is the first one or fits better than the last one, use this placement | ||
spaceList[placement].sizeRequested <= spaceList[placement].sizeAvailable && | ||
(!bestPlacement || | ||
spaceList[placement].sizeAvailable > spaceList[bestPlacement].sizeAvailable) | ||
? placement | ||
: bestPlacement); }, null); | ||
function calculateBestPlacements(spaceList) { | ||
return Object.keys(spaceList).filter(function (o) { var _a; return (_a = spaceList[o]) === null || _a === void 0 ? void 0 : _a.fits; }).sort(function (a, b) { var _a, _b, _c, _d; return ((_b = (_a = spaceList[b]) === null || _a === void 0 ? void 0 : _a.extraSpace) !== null && _b !== void 0 ? _b : 0) - ((_d = (_c = spaceList[a]) === null || _c === void 0 ? void 0 : _c.extraSpace) !== null && _d !== void 0 ? _d : 0); }); | ||
} | ||
//# sourceMappingURL=Geometry.js.map |
@@ -30,3 +30,3 @@ import { Component, RefObject, ReactNode } from 'react'; | ||
}>>; | ||
placement: PropTypes.Requireable<Placement>; | ||
placement: PropTypes.Requireable<Placement | (Placement | null | undefined)[]>; | ||
animationConfig: PropTypes.Requireable<object>; | ||
@@ -33,0 +33,0 @@ verticalOffset: PropTypes.Requireable<number>; |
@@ -144,10 +144,21 @@ var __extends = (this && this.__extends) || (function () { | ||
}), | ||
placement: PropTypes.oneOf([ | ||
Placement.LEFT, | ||
Placement.RIGHT, | ||
Placement.TOP, | ||
Placement.BOTTOM, | ||
Placement.AUTO, | ||
Placement.FLOATING, | ||
Placement.CENTER | ||
placement: PropTypes.oneOfType([ | ||
PropTypes.oneOf([ | ||
Placement.LEFT, | ||
Placement.RIGHT, | ||
Placement.TOP, | ||
Placement.BOTTOM, | ||
Placement.AUTO, | ||
Placement.FLOATING, | ||
Placement.CENTER | ||
]), | ||
PropTypes.arrayOf(PropTypes.oneOf([ | ||
Placement.LEFT, | ||
Placement.RIGHT, | ||
Placement.TOP, | ||
Placement.BOTTOM, | ||
Placement.AUTO, | ||
Placement.FLOATING, | ||
Placement.CENTER | ||
])) | ||
]), | ||
@@ -154,0 +165,0 @@ animationConfig: PropTypes.object, |
@@ -27,3 +27,3 @@ import { Animated, StyleProp, ViewStyle } from 'react-native'; | ||
isVisible?: boolean; | ||
placement?: Placement; | ||
placement?: Placement | Array<Placement>; | ||
animationConfig?: Partial<Animated.TimingAnimationConfig>; | ||
@@ -30,0 +30,0 @@ offset?: number; |
{ | ||
"name": "react-native-popover-view", | ||
"version": "5.0.2", | ||
"version": "5.1.0", | ||
"description": "A <Popover /> component for react-native iOS, Android, and Web", | ||
@@ -5,0 +5,0 @@ "main": "dist/index.js", |
@@ -293,3 +293,3 @@ ## react-native-popover-view | ||
mode | string | 'rn-modal' | One of: 'rn-modal', 'js-modal', 'tooltip'. See [Mode](#mode) section below for details. | ||
placement | string | 'auto' | How to position the popover, one of 'top', 'bottom', 'left', 'right', 'floating', or 'auto'. When 'auto' is specified, it will try to determine the best placement so that the popover is fully visible within `displayArea`. | ||
placement | string OR string list | 'auto' | How to position the popover, one of 'top', 'bottom', 'left', 'right', 'floating', or 'auto'. When 'auto' is specified, it will try to determine the best placement so that the popover is fully visible within `displayArea`. If an array of options is passed in, it will pick the first option that can accommodate the content. | ||
offset | number | 0 | The amount to shift the popover away from the source. Does not apply if the popover is centered. | ||
@@ -296,0 +296,0 @@ popoverStyle | object | | The style of the popover itself. You can override the `borderRadius`, `backgroundColor`, or any other [`style` prop for a `View`](https://facebook.github.io/react-native/docs/view-style-props.html). |
@@ -14,3 +14,3 @@ import { StyleProp, ViewStyle } from 'react-native'; | ||
type ComputeGeometryProps = ComputeGeometryBaseProps & { | ||
placement?: Placement; | ||
placement?: Placement | Array<Placement>; | ||
previousPlacement?: Placement; | ||
@@ -81,3 +81,4 @@ fromRect: Rect | null; | ||
arrowShift, | ||
popoverShift | ||
popoverShift, | ||
arrowSize | ||
} = options; | ||
@@ -95,3 +96,16 @@ | ||
switch (placement) { | ||
// Default to first option if given list of placements | ||
let selectedPlacement = Array.isArray(placement) ? placement[0] : placement; | ||
// If we can find a placement in the list that is better, use that | ||
if (Array.isArray(placement)) { | ||
const spaceList = | ||
generateSpaceList({ fromRect, displayArea, requestedContentSize, arrowSize }); | ||
const bestPlacements = calculateBestPlacements(spaceList); | ||
const [bestProvidedPlacement] = placement. | ||
filter(p => p === Placement.AUTO || p === Placement.FLOATING || bestPlacements.includes(p)); | ||
if (bestProvidedPlacement) selectedPlacement = bestProvidedPlacement; | ||
} | ||
switch (selectedPlacement) { | ||
case Placement.TOP: | ||
@@ -494,2 +508,45 @@ newGeom = computeTopGeometry({ ...options, fromRect, borderRadius }); | ||
type PlacementOption = { | ||
sizeRequested: number; | ||
sizeAvailable: number; | ||
fits: boolean; | ||
extraSpace: number; | ||
} | ||
type SpaceList = Partial<Record<Placement, PlacementOption>> | ||
type SpaceListProps = Pick<ComputeGeometryDirectionProps, 'fromRect' | 'displayArea' | 'arrowSize' | 'requestedContentSize'>; | ||
function generateSpaceList({ | ||
fromRect, | ||
displayArea, | ||
arrowSize, | ||
requestedContentSize | ||
}: SpaceListProps): SpaceList { | ||
function generateOption(props: Pick<PlacementOption, 'sizeRequested' | 'sizeAvailable'>): PlacementOption { | ||
return { | ||
...props, | ||
fits: props.sizeAvailable >= props.sizeRequested, | ||
extraSpace: props.sizeAvailable - props.sizeRequested | ||
}; | ||
} | ||
return { | ||
[Placement.LEFT]: generateOption({ | ||
sizeAvailable: fromRect.x - displayArea.x - arrowSize.width, | ||
sizeRequested: requestedContentSize.width | ||
}), | ||
[Placement.RIGHT]: generateOption({ | ||
sizeAvailable: | ||
displayArea.x + displayArea.width - (fromRect.x + fromRect.width) - arrowSize.width, | ||
sizeRequested: requestedContentSize.width | ||
}), | ||
[Placement.TOP]: generateOption({ | ||
sizeAvailable: fromRect.y - displayArea.y - arrowSize.width, | ||
sizeRequested: requestedContentSize.height | ||
}), | ||
[Placement.BOTTOM]: generateOption({ | ||
sizeAvailable: | ||
displayArea.y + displayArea.height - (fromRect.y + fromRect.height) - arrowSize.width, | ||
sizeRequested: requestedContentSize.height | ||
}) | ||
}; | ||
} | ||
function computeAutoGeometry(options: ComputeGeometryAutoProps): Geometry | null { | ||
@@ -531,27 +588,7 @@ const { | ||
debug('computeAutoGeometry - fromRect', fromRect); | ||
const spaceList: SpaceList = { | ||
[Placement.LEFT]: { | ||
sizeAvailable: fromRect.x - displayArea.x - arrowSize.width, | ||
sizeRequested: requestedContentSize.width | ||
}, | ||
[Placement.RIGHT]: { | ||
sizeAvailable: | ||
displayArea.x + displayArea.width - (fromRect.x + fromRect.width) - arrowSize.width, | ||
sizeRequested: requestedContentSize.width | ||
}, | ||
[Placement.TOP]: { | ||
sizeAvailable: fromRect.y - displayArea.y - arrowSize.width, | ||
sizeRequested: requestedContentSize.height | ||
}, | ||
[Placement.BOTTOM]: { | ||
sizeAvailable: | ||
displayArea.y + displayArea.height - (fromRect.y + fromRect.height) - arrowSize.width, | ||
sizeRequested: requestedContentSize.height | ||
} | ||
}; | ||
debug('computeAutoGeometry - List of availabe space', spaceList); | ||
const spaceList = generateSpaceList({ fromRect, displayArea, arrowSize, requestedContentSize }); | ||
debug('computeAutoGeometry - List of available space', spaceList); | ||
const bestPlacementPosition = findBestPlacement(spaceList); | ||
const [bestPlacementPosition] = calculateBestPlacements(spaceList); | ||
debug('computeAutoGeometry - Found best postition for placement', bestPlacementPosition); | ||
@@ -569,24 +606,6 @@ | ||
type SpaceList = Record< | ||
Placement.LEFT | Placement.RIGHT | Placement.TOP | Placement.BOTTOM, | ||
PlacementOption | ||
> | ||
type PlacementOption = { | ||
sizeRequested: number; | ||
sizeAvailable: number; | ||
function calculateBestPlacements(spaceList: SpaceList): Placement[] { | ||
return (Object.keys(spaceList) as Placement[]).filter( | ||
o => spaceList[o]?.fits | ||
).sort((a, b) => (spaceList[b]?.extraSpace ?? 0) - (spaceList[a]?.extraSpace ?? 0)); | ||
} | ||
function findBestPlacement(spaceList: SpaceList): Placement | null { | ||
return Object.keys(spaceList).reduce( | ||
(bestPlacement, placement) => ( | ||
// If it can fit, and is the first one or fits better than the last one, use this placement | ||
spaceList[placement].sizeRequested <= spaceList[placement].sizeAvailable && | ||
( | ||
!bestPlacement || | ||
spaceList[placement].sizeAvailable > spaceList[bestPlacement].sizeAvailable | ||
) | ||
? placement as Placement | ||
: bestPlacement | ||
), | ||
null as Placement | null | ||
); | ||
} |
@@ -37,3 +37,3 @@ import { Animated, StyleProp, ViewStyle } from 'react-native'; | ||
// config | ||
placement?: Placement; | ||
placement?: Placement | Array<Placement>; | ||
animationConfig?: Partial<Animated.TimingAnimationConfig>; | ||
@@ -40,0 +40,0 @@ offset?: number; |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
275539
4331