react-tiny-popover
Advanced tools
Comparing version 5.0.1 to 5.1.0
@@ -24,3 +24,3 @@ import * as React from 'react'; | ||
export declare interface PopoverProps { | ||
children(ref: React.Ref<any>): JSX.Element; | ||
children: JSX.Element | ((ref: React.Ref<any>) => JSX.Element); | ||
isOpen: boolean; | ||
@@ -27,0 +27,0 @@ content: ContentRenderer | JSX.Element; |
@@ -36,3 +36,3 @@ "use strict"; | ||
var _this = _super.call(this, props) || this; | ||
_this.target = react_1.default.createRef(); | ||
_this.targetRef = react_1.default.createRef(); | ||
_this.targetRect = undefined; | ||
@@ -49,3 +49,3 @@ _this.targetPositionIntervalHandler = undefined; | ||
!_this.popoverDiv.contains(e.target) && | ||
!_this.target.current.contains(e.target) && | ||
!_this.targetRef.current.contains(e.target) && | ||
onClickOutside && | ||
@@ -203,3 +203,3 @@ isOpen) { | ||
Popover.prototype.updatePopover = function (isOpen) { | ||
if (isOpen && this.target) { | ||
if (isOpen && this.targetRef) { | ||
if (!this.popoverDiv || !this.popoverDiv.parentNode) { | ||
@@ -223,3 +223,3 @@ var transitionDuration = this.props.transitionDuration; | ||
this.targetPositionIntervalHandler = window.setInterval(function () { | ||
var newTargetRect = _this.target.current.getBoundingClientRect(); | ||
var newTargetRect = _this.targetRef.current.getBoundingClientRect(); | ||
if (util_1.targetPositionHasChanged(_this.targetRect, newTargetRect)) { | ||
@@ -263,3 +263,3 @@ _this.renderPopover(); | ||
position: this.positionOrder[positionIndex], | ||
targetRect: this.target.current.getBoundingClientRect(), | ||
targetRect: this.targetRef.current.getBoundingClientRect(), | ||
}, function (violation, rect) { | ||
@@ -280,3 +280,3 @@ var _a; | ||
if (contentLocation_1) { | ||
var targetRect = _this.target.current.getBoundingClientRect(); | ||
var targetRect = _this.targetRef.current.getBoundingClientRect(); | ||
var popoverRect = _this.popoverDiv.getBoundingClientRect(); | ||
@@ -317,3 +317,3 @@ (_a = typeof contentLocation_1 === 'function' | ||
nudgedLeft: nudgedLeft - rect.left, | ||
targetRect: _this.target.current.getBoundingClientRect(), | ||
targetRect: _this.targetRef.current.getBoundingClientRect(), | ||
popoverRect: _this.popoverDiv.getBoundingClientRect(), | ||
@@ -329,2 +329,21 @@ }, function () { | ||
}; | ||
Popover.prototype.renderPopoverContent = function () { | ||
var _a = this.props, content = _a.content, isOpen = _a.isOpen, contentDestination = _a.contentDestination; | ||
var _b = this.state, popoverInfo = _b.popoverInfo, isTransitioningToClosed = _b.isTransitioningToClosed; | ||
if ((isOpen || isTransitioningToClosed) && this.popoverDiv && popoverInfo) { | ||
var getContent = function (args) { | ||
return typeof content === 'function' ? content(args) : content; | ||
}; | ||
return (react_1.default.createElement(PopoverPortal_1.PopoverPortal, { element: this.popoverDiv, container: contentDestination || window.document.body }, getContent(popoverInfo))); | ||
} | ||
return null; | ||
}; | ||
Popover.prototype.renderChildContent = function () { | ||
var children = this.props.children; | ||
return typeof children === 'function' | ||
? children(this.targetRef) | ||
: react_1.default.cloneElement(children, { | ||
ref: this.targetRef, | ||
}); | ||
}; | ||
Popover.prototype.renderWithPosition = function (_a, callback) { | ||
@@ -341,3 +360,3 @@ var _this = this; | ||
} | ||
targetRect = _this.target.current.getBoundingClientRect(); | ||
targetRect = _this.targetRef.current.getBoundingClientRect(); | ||
popoverRect = _this.popoverDiv.getBoundingClientRect(); | ||
@@ -353,14 +372,5 @@ var _a = _this.getLocationForPosition(position, targetRect, popoverRect), top = _a.top, left = _a.left; | ||
Popover.prototype.render = function () { | ||
var _a = this.props, content = _a.content, children = _a.children, isOpen = _a.isOpen, contentDestination = _a.contentDestination; | ||
var _b = this.state, popoverInfo = _b.popoverInfo, isTransitioningToClosed = _b.isTransitioningToClosed; | ||
var popoverContent; | ||
if ((isOpen || isTransitioningToClosed) && this.popoverDiv && popoverInfo) { | ||
var getContent = function (args) { | ||
return typeof content === 'function' ? content(args) : content; | ||
}; | ||
popoverContent = (react_1.default.createElement(PopoverPortal_1.PopoverPortal, { element: this.popoverDiv, container: contentDestination || window.document.body }, getContent(popoverInfo))); | ||
} | ||
return (react_1.default.createElement(react_1.default.Fragment, null, | ||
children(this.target), | ||
popoverContent)); | ||
this.renderChildContent(), | ||
this.renderPopoverContent())); | ||
}; | ||
@@ -367,0 +377,0 @@ Popover.defaultProps = { |
{ | ||
"name": "react-tiny-popover", | ||
"version": "5.0.1", | ||
"version": "5.1.0", | ||
"description": "A simple and highly customizable popover react higher order component with no other dependencies! Typescript friendly.", | ||
@@ -5,0 +5,0 @@ "keywords": [ |
@@ -0,1 +1,8 @@ | ||
- [Intro](#react-tiny-popover) | ||
- [Installation](#install) | ||
- [Demo](#demo) | ||
- [Examples](#examples) | ||
- [Migrating from versions 3 and 4](#migrating-from-versions-3-and-4) | ||
- [API](#api) | ||
# react-tiny-popover | ||
@@ -41,7 +48,5 @@ | ||
> | ||
{ref => ( | ||
<div ref={ref} onClick={() => setIsPopoverOpen(!isPopoverOpen)}> | ||
Click me! | ||
</div> | ||
)} | ||
<div onClick={() => setIsPopoverOpen(!isPopoverOpen)}> | ||
Click me! | ||
</div> | ||
</Popover>; | ||
@@ -69,5 +74,3 @@ ``` | ||
> | ||
{ref => ( | ||
<div onClick={() => setIsPopoverOpen(!isPopoverOpen)}>Click me!</div> | ||
)} | ||
<div onClick={() => setIsPopoverOpen(!isPopoverOpen)}>Click me!</div> | ||
</Popover>; | ||
@@ -104,3 +107,3 @@ ``` | ||
> | ||
{ref => ( | ||
{ref => ( // if you'd like access to the ref itself for some reason, you can provide a function as a child into which the ref will be injected | ||
<div ref={ref} onClick={() => setIsPopoverOpen(!isPopoverOpen)}> | ||
@@ -134,7 +137,5 @@ Click me! | ||
<Popover isOpen={isPopoverOpen} content={<div>hey from popover content</div>}> | ||
{ref => ( | ||
<CustomComponent ref={ref} onClick={() => setIsPopoverOpen(!isPopoverOpen)}> | ||
hey from a custom target component | ||
</CustomComponent> | ||
)} | ||
<CustomComponent onClick={() => setIsPopoverOpen(!isPopoverOpen)}> | ||
hey from a custom target component | ||
</CustomComponent> | ||
</Popover> | ||
@@ -148,2 +149,44 @@ </div> | ||
## Migrating from versions 3 and 4 | ||
`react-tiny-popover 5.x.x` has abandoned use of `findDOMNode` to gain a reference to `Popover`'s target DOM node, and now explicitly relies on a ref. Since React has deprecated `findDOMNode` in `StrictMode`, now seems like an appropriate time to shift away from this under-the-hood logic toward a clearer and more declarative API. | ||
If your code looked this way, it can stay this way. React elements handle refs out of the box with no issues: | ||
```JSX | ||
<Popover | ||
isOpen={isPopoverOpen} | ||
content={<div>Hi! I'm popover content.</div>} | ||
> | ||
<div onClick={() => setIsPopoverOpen(!isPopoverOpen)}> | ||
Click me! | ||
</div> | ||
</Popover>; | ||
``` | ||
However, if you use a custom component as a your `Popover`'s child, you'll have to implement ref forwarding. Without ref forwarding, `Popover` will not be able to inject a reference into you component and refer to it. | ||
For example: | ||
```JSX | ||
interface Props extends React.ComponentPropsWithoutRef<'div'> { | ||
onClick(): void; | ||
} | ||
// this component will no longer work as a Popover child | ||
const CustomComponent: React.FC<Props> = props => ( | ||
<div onClick={props.onClick}> | ||
{props.children} | ||
</div> | ||
) | ||
// instead, you'll simply implement ref forwarding, as so: | ||
const CustomComponent = React.forwardRef<HTMLDivElement, Props>((props, ref) => ( | ||
<div ref={ref} onClick={props.onClick}> | ||
{props.children} | ||
</div> | ||
)); | ||
``` | ||
Check out [React's ref forwarding API](https://reactjs.org/docs/forwarding-refs.html) for more info, and see the examples above. | ||
## API | ||
@@ -155,3 +198,3 @@ | ||
| ------------------- | -------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | ||
| children | `Function` | ✔️ | This function, of form `(ref: React.Ref) => JSX.Element`, will return the JSX.Element target that you'd like the popover content to track. In order to track that element, however, you must attach the provided `ref`. If you're using a custom React component, you'll have to employ React's ref forwarding. See the examples above, or read more about that over at [React's ref forwarding docs](https://reactjs.org/docs/forwarding-refs.html). Sweet. | | ||
| children | `JSX.Element` or `Function` | ✔️ | If the `JSX.Element` you provide is a custom component, it should [forward refs](https://reactjs.org/docs/forwarding-refs.html). If you provide a function of form `(ref: React.Ref) => JSX.Element`, it'll return from it the JSX.Element target that you'd like the popover content to track. Don't forget to attach that `ref` to it, though. | | ||
| isOpen | `boolean` | ✔️ | When this boolean is set to true, the popover is visible and tracks the target. When the boolean is false, the popover content is neither visible nor present on the DOM. | | ||
@@ -158,0 +201,0 @@ | content | `JSX.Element` or `Function` | ✔️ | Here, you'll provide the content that will appear as the popover. Rather than a JSX element like a `<div>`, you may supply a function that returns a JSX.Element, which will look like this: `({ position, targetRect, popoverRect, align, nudgedLeft, nudgedTop }) => JSX.Element`. Here, `position` is of type `'top', 'bottom', 'left', 'right'`. `align` is of type `start`, `center`, or `end`. Both `targetRect` and `popoverRect` are `ClientRect` objects of format `{ height: number, width: number, top: number, left: number, right: number, bottom: number }`, and represent the popover content and target `div`'s coordinates within your browser's window. `nudgedLeft` and `nudgedTop` specify the X and Y offset the popover content is shifted by to keep it within the window's bounds during a boundary collision. You may want to use these values to adjust your content depending on its location in relation to the window and the target, especially if you have repositioning disabled. Sweet. | |
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
56301
220
7
560