react-stick
Advanced tools
Comparing version 2.2.5 to 2.3.0
import React from 'react' | ||
import PositionAlignOverview from './PositionAlignOverview' | ||
import Regressions from './regressions' | ||
import PositionAlignOverview from './PositionAlignOverview' | ||
import AutoAlignment from './AutoAlignment' | ||
export default function Demo() { | ||
@@ -19,2 +21,4 @@ return ( | ||
<AutoAlignment /> | ||
<Regressions /> | ||
@@ -21,0 +25,0 @@ </div> |
'use strict'; | ||
exports.__esModule = true; | ||
exports.positions = undefined; | ||
require('./flowTypes'); | ||
var DEFAULT_POSITION = 'bottom left'; | ||
exports.default = DEFAULT_POSITION; | ||
module.exports = exports['default']; | ||
var positions = exports.positions = ['bottom left', 'bottom center', 'bottom right', 'middle left', 'middle center', 'middle right', 'top left', 'top center', 'top right']; |
@@ -5,9 +5,13 @@ 'use strict'; | ||
var _Stick = require('./Stick'); | ||
var _AutoFlipStick = require('./AutoFlipStick'); | ||
var _Stick2 = _interopRequireDefault(_Stick); | ||
Object.defineProperty(exports, 'default', { | ||
enumerable: true, | ||
get: function get() { | ||
return _interopRequireDefault(_AutoFlipStick).default; | ||
} | ||
}); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
exports.default = _Stick2.default; | ||
module.exports = exports['default']; |
139
lib/Stick.js
@@ -5,2 +5,6 @@ 'use strict'; | ||
var _includes2 = require('lodash/includes'); | ||
var _includes3 = _interopRequireDefault(_includes2); | ||
var _some2 = require('lodash/some'); | ||
@@ -22,6 +26,2 @@ | ||
var _includes2 = require('lodash/includes'); | ||
var _includes3 = _interopRequireDefault(_includes2); | ||
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; | ||
@@ -45,10 +45,6 @@ | ||
var _getModifiers = require('./getModifiers'); | ||
var _utils = require('./utils'); | ||
var _getModifiers2 = _interopRequireDefault(_getModifiers); | ||
require('./flowTypes'); | ||
var _getDefaultAlign = require('./getDefaultAlign'); | ||
var _getDefaultAlign2 = _interopRequireDefault(_getDefaultAlign); | ||
var _StickPortal = require('./StickPortal'); | ||
@@ -62,12 +58,2 @@ | ||
var _defaultPosition = require('./defaultPosition'); | ||
var _defaultPosition2 = _interopRequireDefault(_defaultPosition); | ||
var _scroll = require('./scroll'); | ||
var _getBoundingClientRect = require('./getBoundingClientRect'); | ||
var _getBoundingClientRect2 = _interopRequireDefault(_getBoundingClientRect); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
@@ -92,11 +78,7 @@ | ||
function Stick() { | ||
function Stick(props) { | ||
_classCallCheck(this, Stick); | ||
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { | ||
args[_key] = arguments[_key]; | ||
} | ||
var _this = _possibleConstructorReturn(this, _Component.call(this, props)); | ||
var _this = _possibleConstructorReturn(this, _Component.call.apply(_Component, [this].concat(args))); | ||
_this.setContainerRef = function (ref) { | ||
@@ -121,2 +103,3 @@ _this.containerNode = ref; | ||
_this.containerNestingKeyExtension = (0, _uniqueId3.default)(); | ||
_this.state = { | ||
@@ -130,2 +113,3 @@ width: 0 | ||
document.addEventListener('click', this.handleClickOutside, true); | ||
this.startTracking(); | ||
@@ -136,2 +120,3 @@ }; | ||
document.removeEventListener('click', this.handleClickOutside, true); | ||
this.stopTracking(); | ||
@@ -147,2 +132,4 @@ }; | ||
Stick.prototype.render = function render() { | ||
var _this2 = this; | ||
var _props = this.props, | ||
@@ -152,6 +139,8 @@ inline = _props.inline, | ||
style = _props.style, | ||
align = _props.align, | ||
sameWidth = _props.sameWidth, | ||
rest = _objectWithoutProperties(_props, ['inline', 'node', 'style', 'align', 'sameWidth']); | ||
children = _props.children, | ||
rest = _objectWithoutProperties(_props, ['inline', 'node', 'style', 'sameWidth', 'children']); | ||
var width = this.state.width; | ||
var SpecificStick = inline ? _StickInline2.default : _StickPortal2.default; | ||
@@ -164,20 +153,26 @@ | ||
return _react2.default.createElement(SpecificStick, _extends({}, (0, _omit3.default)(rest, 'onClickOutside'), { | ||
node: node && _react2.default.createElement( | ||
'div', | ||
_extends({}, wrapperStylingProps, { | ||
style: _extends({}, wrapperStyle, { | ||
width: wrapperStyle.width ? wrapperStyle.width : this.state.width | ||
}) | ||
}), | ||
_react2.default.createElement( | ||
return _react2.default.createElement( | ||
SpecificStick, | ||
_extends({}, (0, _omit3.default)(rest, 'onClickOutside', 'onReposition'), { | ||
node: node && _react2.default.createElement( | ||
'div', | ||
style('nodeContent'), | ||
node | ||
) | ||
), | ||
style: style, | ||
nestingKey: this.getNestingKey(), | ||
containerRef: this.setContainerRef | ||
})); | ||
_extends({}, wrapperStylingProps, { | ||
style: _extends({}, wrapperStyle, { | ||
width: wrapperStyle.width ? wrapperStyle.width : width | ||
}) | ||
}), | ||
_react2.default.createElement( | ||
'div', | ||
_extends({}, style('nodeContent'), { ref: function ref(_ref2) { | ||
return _this2.nodeRef = _ref2; | ||
} }), | ||
node | ||
) | ||
), | ||
style: style, | ||
nestingKey: this.getNestingKey(), | ||
containerRef: this.setContainerRef | ||
}), | ||
children | ||
); | ||
}; | ||
@@ -210,3 +205,3 @@ | ||
Stick.prototype.startTracking = function startTracking() { | ||
var _this2 = this; | ||
var _this3 = this; | ||
@@ -217,3 +212,3 @@ // do not track in node | ||
var callback = function callback() { | ||
return _this2.startTracking(); | ||
return _this3.startTracking(); | ||
}; | ||
@@ -242,18 +237,33 @@ if (this.props.updateOnAnimationFrame) { | ||
Stick.prototype.measure = function measure() { | ||
var boundingRect = (0, _getBoundingClientRect2.default)(this); | ||
var _props2 = this.props, | ||
position = _props2.position, | ||
align = _props2.align, | ||
sameWidth = _props2.sameWidth, | ||
onReposition = _props2.onReposition; | ||
var width = this.state.width; | ||
var width = this.props.sameWidth ? boundingRect.width : calculateWidth(this.props.position, this.props.align || (0, _getDefaultAlign2.default)(this.props.position), boundingRect); | ||
if (width !== this.state.width) { | ||
this.setState({ width: width }); | ||
var boundingRect = (0, _utils.getBoundingClientRect)(this); | ||
var newWidth = sameWidth ? boundingRect.width : calculateWidth(position, align, boundingRect); | ||
if (newWidth !== width) { | ||
this.setState({ width: newWidth }); | ||
} | ||
var anchorRef = (0, _reactDom.findDOMNode)(this); | ||
if (!this.nodeRef || !anchorRef) { | ||
return; | ||
} | ||
if (anchorRef instanceof HTMLElement) { | ||
onReposition(this.nodeRef, anchorRef); | ||
} | ||
}; | ||
return Stick; | ||
}(_react.Component), _class.contextTypes = ContextTypes, _class.childContextTypes = ContextTypes, _class.defaultProps = { | ||
position: _defaultPosition2.default | ||
}, _temp); | ||
}(_react.Component), _class.contextTypes = ContextTypes, _class.childContextTypes = ContextTypes, _temp); | ||
Stick.propTypes = process.env.NODE_ENV !== "production" ? { | ||
node: _propTypes2.default.node, | ||
children: _propTypes2.default.node, | ||
position: PositionPropType, | ||
@@ -264,15 +274,14 @@ align: PositionPropType, | ||
updateOnAnimationFrame: _propTypes2.default.bool, | ||
onClickOutside: _propTypes2.default.func, | ||
transportTo: _propTypes2.default.instanceOf(HTMLElement) | ||
onClickOutside: _propTypes2.default.func | ||
} : {}; | ||
function calculateWidth(position, align, _ref2) { | ||
var left = _ref2.left, | ||
width = _ref2.width, | ||
right = _ref2.right; | ||
function calculateWidth(position, align, _ref3) { | ||
var left = _ref3.left, | ||
width = _ref3.width, | ||
right = _ref3.right; | ||
var scrollWidth = document.documentElement ? document.documentElement.scrollWidth : right; // this should never be used in a browser env where documentElement will be available | ||
var absLeft = (0, _scroll.scrollX)() + { | ||
var absLeft = (0, _utils.scrollX)() + { | ||
left: left, | ||
@@ -357,5 +366,7 @@ center: left + width / 2, | ||
} | ||
}, _getModifiers2.default); | ||
}, _utils.getModifiers); | ||
exports.default = styled(Stick); | ||
var StyledStick = styled(Stick); | ||
exports.default = StyledStick; | ||
module.exports = exports['default']; |
@@ -17,5 +17,5 @@ 'use strict'; | ||
var _getModifiers = require('./getModifiers'); | ||
var _utils = require('./utils'); | ||
var _getModifiers2 = _interopRequireDefault(_getModifiers); | ||
require('./flowTypes'); | ||
@@ -87,5 +87,5 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
} | ||
}, _getModifiers2.default); | ||
}, _utils.getModifiers); | ||
exports.default = styled(StickInline); | ||
module.exports = exports['default']; |
@@ -29,8 +29,4 @@ 'use strict'; | ||
var _scroll = require('./scroll'); | ||
var _utils = require('./utils'); | ||
var _getBoundingClientRect = require('./getBoundingClientRect'); | ||
var _getBoundingClientRect2 = _interopRequireDefault(_getBoundingClientRect); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
@@ -144,5 +140,5 @@ | ||
children = _props2.children, | ||
component = _props2.component, | ||
style = _props2.style, | ||
component = _props2.component, | ||
rest = _objectWithoutProperties(_props2, ['children', 'style', 'component']); | ||
rest = _objectWithoutProperties(_props2, ['children', 'component', 'style']); | ||
@@ -152,3 +148,3 @@ var Comp = component || 'div'; | ||
Comp, | ||
_extends({}, (0, _omit3.default)(rest, 'node', 'position', 'updateOnAnimationFrame', 'transportTo', 'containerRef', 'nestingKey'), style), | ||
_extends({}, (0, _omit3.default)(rest, 'node', 'position', 'align', 'updateOnAnimationFrame', 'transportTo', 'containerRef', 'nestingKey'), style), | ||
children, | ||
@@ -235,3 +231,3 @@ this.renderNode() | ||
StickPortal.prototype.measure = function measure() { | ||
var boundingRect = (0, _getBoundingClientRect2.default)(this); | ||
var boundingRect = (0, _utils.getBoundingClientRect)(this); | ||
var isFixed = hasFixedPosition(this.host); | ||
@@ -269,3 +265,3 @@ | ||
} | ||
return result + (isFixed ? 0 : (0, _scroll.scrollY)()); | ||
return result + (isFixed ? 0 : (0, _utils.scrollY)()); | ||
} | ||
@@ -288,3 +284,3 @@ | ||
} | ||
return result + (isFixed ? 0 : (0, _scroll.scrollX)()); | ||
return result + (isFixed ? 0 : (0, _utils.scrollX)()); | ||
} | ||
@@ -291,0 +287,0 @@ |
{ | ||
"name": "react-stick", | ||
"version": "2.2.5", | ||
"version": "2.3.0", | ||
"description": "React component to stick a portaled node to an anchor node", | ||
@@ -44,3 +44,3 @@ "main": "lib/index.js", | ||
"eslint-plugin-react": "^7.1.0", | ||
"flow-bin": "^0.77.0", | ||
"flow-bin": "^0.82.0", | ||
"flow-copy-source": "^1.3.0", | ||
@@ -62,2 +62,5 @@ "gh-pages": "^1.1.0", | ||
}, | ||
"resolutions": { | ||
"upath": "1.1.0" | ||
}, | ||
"release": { | ||
@@ -64,0 +67,0 @@ "analyzeCommits": "semantic-release-github-pr", |
@@ -33,2 +33,4 @@ # react-stick | ||
| `sameWidth` | boolean | If set to `true`, the container of the stick node will have the same width as the anchor node. This enforces a maximum width on the content of the stick node. | | ||
| `autoFlipVertically` | boolean | If a node has been attached to the bottom but there isn't enough space on the screen it will automatically be positioned to the top. | | ||
| `autoFlipHorizontally` | boolean | If a node has been attached to the left but there isn't enough space on the screen it will automatically be positioned to the right. | | ||
| `onClickOutside` | function: (event: Event) => void | A handler that is called on every click on any element outside of the anchor element and the stick node. | | ||
@@ -35,0 +37,0 @@ | `inline` | boolean | If set to `true`, the stick node will not be rendered detached but inside the same container as the anchor node. | |
// @flow | ||
import { type PositionT } from './flowTypes' | ||
const DEFAULT_POSITION = 'bottom left' | ||
export default DEFAULT_POSITION | ||
export const positions: Array<PositionT> = [ | ||
'bottom left', | ||
'bottom center', | ||
'bottom right', | ||
'middle left', | ||
'middle center', | ||
'middle right', | ||
'top left', | ||
'top center', | ||
'top right', | ||
] |
@@ -5,2 +5,5 @@ // @flow | ||
export type VerticalTargetT = 'bottom' | 'middle' | 'top' | ||
export type HorizontalTargetT = 'left' | 'center' | 'right' | ||
export type PositionT = | ||
@@ -17,2 +20,4 @@ | 'bottom left' | ||
export type AlignT = PositionT | ||
type SharedPropsT = { | ||
@@ -31,25 +36,2 @@ node?: Node, | ||
type StickBasePropsT = SharedPropsT & { | ||
align?: PositionT, | ||
sameWidth?: boolean, | ||
onClickOutside?: (ev: MouseEvent) => void, | ||
} | ||
// the props we are dealing with in Stick | ||
export type StickPropsT = StickBasePropsT & { | ||
// props handled by Stick and not passed further down to specific stick components | ||
style: Substyle, | ||
position: PositionT, | ||
} | ||
// the props the user has to pass to the Stick | ||
export type PublicPropsT = StickBasePropsT & { | ||
// position is optional, but has a default value | ||
position?: PositionT, | ||
// style is optional, but will be injected by substyle | ||
style?: Substyle, | ||
} | ||
type SpecificStickBasePropsT = SharedPropsT & { | ||
@@ -59,2 +41,3 @@ style: Substyle, | ||
position: PositionT, | ||
align: AlignT, | ||
} | ||
@@ -61,0 +44,0 @@ |
// @flow | ||
import Stick from './Stick' | ||
import type { PublicPropsT } from './flowTypes' | ||
export default Stick | ||
export type Props = PublicPropsT | ||
export { default } from './AutoFlipStick' |
112
src/Stick.js
// @flow | ||
import 'requestidlecallback' | ||
import React, { Component } from 'react' | ||
import React, { Component, type Node, type ComponentType } from 'react' | ||
import { findDOMNode } from 'react-dom' | ||
import { includes } from 'lodash' | ||
import { omit, uniqueId, compact, some, includes } from 'lodash' | ||
import PropTypes from 'prop-types' | ||
import { defaultStyle } from 'substyle' | ||
import { omit, uniqueId, compact, some } from 'lodash' | ||
import { defaultStyle, type Substyle } from 'substyle' | ||
import getModifiers from './getModifiers' | ||
import getDefaultAlign from './getDefaultAlign' | ||
import { getModifiers, getBoundingClientRect, scrollX } from './utils' | ||
import { type PositionT, type AlignT } from './flowTypes' | ||
import StickPortal from './StickPortal' | ||
import StickInline from './StickInline' | ||
import DEFAULT_POSITION from './defaultPosition' | ||
import { scrollX } from './scroll' | ||
import getBoundingClientRect from './getBoundingClientRect' | ||
import type { StickPropsT, PositionT } from './flowTypes' | ||
@@ -41,5 +38,33 @@ const PARENT_STICK_NESTING_KEY = 'react-stick__parentStickNestingKey' | ||
class Stick extends Component<StickPropsT, StateT> { | ||
type StickBasePropsT = { | ||
sameWidth?: boolean, | ||
inline?: boolean, | ||
updateOnAnimationFrame?: boolean, | ||
node: Node, | ||
children: Node, | ||
onClickOutside?: (ev: MouseEvent) => void, | ||
onReposition: (nodeRef: HTMLElement, anchorRef: HTMLElement) => void, | ||
} | ||
type ApiPropsT = StickBasePropsT & { | ||
position?: PositionT, | ||
align?: AlignT, | ||
style?: Substyle, | ||
} | ||
type PropsT = StickBasePropsT & { | ||
position: PositionT, | ||
align: AlignT, | ||
style: Substyle, | ||
} | ||
class Stick extends Component<PropsT, StateT> { | ||
containerNestingKeyExtension: string | ||
containerNode: ?HTMLElement | ||
nodeRef: ?HTMLElement | ||
@@ -51,3 +76,2 @@ animationFrameId: ?AnimationFrameID | ||
node: PropTypes.node, | ||
children: PropTypes.node, | ||
position: PositionPropType, | ||
@@ -59,3 +83,2 @@ align: PositionPropType, | ||
onClickOutside: PropTypes.func, | ||
transportTo: PropTypes.instanceOf(HTMLElement), | ||
} | ||
@@ -66,9 +89,6 @@ | ||
static defaultProps = { | ||
position: DEFAULT_POSITION, | ||
} | ||
constructor(props) { | ||
super(props) | ||
this.containerNestingKeyExtension = uniqueId() | ||
constructor(...args) { | ||
super(...args) | ||
this.containerNestingKeyExtension = uniqueId() | ||
this.state = { | ||
@@ -81,2 +101,3 @@ width: 0, | ||
document.addEventListener('click', this.handleClickOutside, true) | ||
this.startTracking() | ||
@@ -87,2 +108,3 @@ } | ||
document.removeEventListener('click', this.handleClickOutside, true) | ||
this.stopTracking() | ||
@@ -98,10 +120,13 @@ } | ||
render() { | ||
const { inline, node, style, align, sameWidth, ...rest } = this.props | ||
const { inline, node, style, sameWidth, children, ...rest } = this.props | ||
const { width } = this.state | ||
const SpecificStick = inline ? StickInline : StickPortal | ||
const { style: wrapperStyle = {}, ...wrapperStylingProps } = style( | ||
'nodeWrapper' | ||
) | ||
return ( | ||
<SpecificStick | ||
{...omit(rest, 'onClickOutside')} | ||
{...omit(rest, 'onClickOutside', 'onReposition')} | ||
node={ | ||
@@ -113,8 +138,8 @@ node && ( | ||
...wrapperStyle, | ||
width: wrapperStyle.width | ||
? wrapperStyle.width | ||
: this.state.width, | ||
width: wrapperStyle.width ? wrapperStyle.width : width, | ||
}} | ||
> | ||
<div {...style('nodeContent')}>{node}</div> | ||
<div {...style('nodeContent')} ref={ref => (this.nodeRef = ref)}> | ||
{node} | ||
</div> | ||
</div> | ||
@@ -126,7 +151,9 @@ ) | ||
containerRef={this.setContainerRef} | ||
/> | ||
> | ||
{children} | ||
</SpecificStick> | ||
) | ||
} | ||
setContainerRef = (ref: HTMLElement | null) => { | ||
setContainerRef = (ref: ?HTMLElement) => { | ||
this.containerNode = ref | ||
@@ -203,15 +230,24 @@ } | ||
measure() { | ||
const { position, align, sameWidth, onReposition } = this.props | ||
const { width } = this.state | ||
const boundingRect = getBoundingClientRect(this) | ||
const width = this.props.sameWidth | ||
const newWidth = sameWidth | ||
? boundingRect.width | ||
: calculateWidth( | ||
this.props.position, | ||
this.props.align || getDefaultAlign(this.props.position), | ||
boundingRect | ||
) | ||
: calculateWidth(position, align, boundingRect) | ||
if (width !== this.state.width) { | ||
this.setState({ width }) | ||
if (newWidth !== width) { | ||
this.setState({ width: newWidth }) | ||
} | ||
const anchorRef = findDOMNode(this) | ||
if (!this.nodeRef || !anchorRef) { | ||
return | ||
} | ||
if (anchorRef instanceof HTMLElement) { | ||
onReposition(this.nodeRef, anchorRef) | ||
} | ||
} | ||
@@ -222,3 +258,3 @@ } | ||
position: PositionT, | ||
align: PositionT, | ||
align: AlignT, | ||
{ left, width, right }: ClientRect | ||
@@ -317,2 +353,4 @@ ) { | ||
export default styled(Stick) | ||
const StyledStick: ComponentType<ApiPropsT> = styled(Stick) | ||
export default StyledStick |
@@ -7,4 +7,4 @@ // @flow | ||
import getModifiers from './getModifiers' | ||
import type { StickInlinePropsT } from './flowTypes' | ||
import { getModifiers } from './utils' | ||
import { type StickInlinePropsT } from './flowTypes' | ||
@@ -11,0 +11,0 @@ const StickInline = ({ |
@@ -8,4 +8,4 @@ // @flow | ||
import { scrollX, scrollY } from './scroll' | ||
import getBoundingClientRect from './getBoundingClientRect' | ||
import { scrollX, scrollY, getBoundingClientRect } from './utils' | ||
import type { PositionT, StickPortalPropsT } from './flowTypes' | ||
@@ -96,3 +96,3 @@ | ||
render() { | ||
const { children, style, component, ...rest } = this.props | ||
const { children, component, style, ...rest } = this.props | ||
const Comp = component || 'div' | ||
@@ -105,2 +105,3 @@ return ( | ||
'position', | ||
'align', | ||
'updateOnAnimationFrame', | ||
@@ -107,0 +108,0 @@ 'transportTo', |
@@ -41,3 +41,3 @@ import expect from 'expect' | ||
it('should work if the node is only provided after the initial mount', done => { | ||
render(<Stick>{anchor}</Stick>, host) | ||
render(<Stick position="middle right">{anchor}</Stick>, host) | ||
render( | ||
@@ -44,0 +44,0 @@ <Stick position="middle right" node={node}> |
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
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
760443
76
8844
46