Skip to content

Commit c716d71

Browse files
committed
Bump 0.4.0
1 parent 07c1ed8 commit c716d71

File tree

5 files changed

+196
-10
lines changed

5 files changed

+196
-10
lines changed

README.md

-1
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,6 @@ npm run test:feature:ci
157157
### TODO
158158

159159
+ Options to change offsets
160-
+ Supports auto placement
161160
+ Supports custom themes
162161
+ Introduce ESLint
163162
+ API documentation using ESDoc

lib/reducer.js

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ var initial = {
1919
show: false,
2020
place: 'top',
2121
el: null,
22+
auto: true,
2223
content: null,
2324
timeout: null
2425
};

lib/tooltip.js

+11-6
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,11 @@ var Tooltip = function (_Component) {
4848
return {
4949
// Props from state tree
5050
show: _react.PropTypes.bool.isRequired,
51-
place: _react.PropTypes.string.isRequired,
51+
place: _react.PropTypes.oneOfType([_react.PropTypes.string, _react.PropTypes.array]).isRequired,
5252
el: _react.PropTypes.object,
5353
content: _react.PropTypes.string,
54+
auto: _react.PropTypes.bool.isRequired,
55+
within: _react.PropTypes.func,
5456

5557
// Props from wrapper props
5658
name: _react.PropTypes.string,
@@ -63,7 +65,8 @@ var Tooltip = function (_Component) {
6365
get: function get() {
6466
return {
6567
show: false,
66-
place: 'top'
68+
place: 'top',
69+
auto: true
6770
};
6871
}
6972
}]);
@@ -99,21 +102,23 @@ var Tooltip = function (_Component) {
99102
}, {
100103
key: 'updatePosition',
101104
value: function updatePosition(props) {
102-
var offset = (0, _utils.placement)(props.place, this.refs.tooltip, props.el);
103-
this.setState(offset);
105+
var state = (0, _utils.adjust)(this.refs.tooltip, props);
106+
this.setState(state);
104107
}
105108
}, {
106109
key: 'render',
107110
value: function render() {
108111
var _props = this.props;
109112
var content = _props.content;
110-
var place = _props.place;
111113
var onHover = _props.onHover;
112114
var onLeave = _props.onLeave;
115+
var _state = this.state;
116+
var place = _state.place;
117+
var offset = _state.offset;
113118

114119
var visibility = this.props.el && this.props.show ? 'visible' : 'hidden';
115120
var style = {
116-
base: _extends({}, styles.base, themes.simple.base, { visibility: visibility }, this.state),
121+
base: _extends({}, styles.base, themes.simple.base, { visibility: visibility }, offset),
117122
content: _extends({}, styles.content, themes.simple.content),
118123
arrow: _extends({}, styles.arrow),
119124
border: _extends({}, styles.border.base, styles.border[place], themes.simple.border)

lib/utils.js

+183-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,24 @@
11
'use strict';
22

3+
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; };
4+
5+
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; };
6+
37
Object.defineProperty(exports, "__esModule", {
48
value: true
59
});
610
exports.position = position;
711
exports.placement = placement;
12+
exports.opposite = opposite;
13+
exports.intersection = intersection;
14+
exports.strip = strip;
15+
exports.amend = amend;
16+
exports.overDirs = overDirs;
17+
exports.adjust = adjust;
818
exports.resolve = resolve;
19+
20+
function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
21+
922
/**
1023
* Returns a position of given DOM element.
1124
*
@@ -42,14 +55,14 @@ function position(el) {
4255
* @param {string} place - 'top', 'right', 'bottom', or 'left'.
4356
* @param {Object} tooltip - DOM element.
4457
* @param {Object} origin - DOM element.
45-
* @return {Object} contains 'top' and 'left' keys.
58+
* @return {Object} contains 'top', 'left', and extra keys.
4659
*/
4760
function placement(place, tooltip, origin) {
4861
var gap = 12;
4962
var tip = position(tooltip);
5063
var pos = position(origin);
5164

52-
var offset = {};
65+
var offset = { width: tip.width, height: tip.height };
5366

5467
switch (place) {
5568
case 'top':case 'bottom':
@@ -78,6 +91,174 @@ function placement(place, tooltip, origin) {
7891
return offset;
7992
}
8093

94+
/**
95+
* Returns an opposite direction based on the given.
96+
*
97+
* @param {string|Array} dir - 'top', 'right', 'bottom', or 'left'.
98+
* @return {string} an opposite direction.
99+
* @throw
100+
*/
101+
function opposite(dir) {
102+
var place = dir;
103+
104+
// Alrays use first direction if Array is passed
105+
if ((typeof place === 'undefined' ? 'undefined' : _typeof(place)) === 'object' && typeof place.length === 'number' && 0 < place.length) {
106+
place = place[0];
107+
}
108+
109+
switch (place) {
110+
case 'top':
111+
return 'bottom';
112+
case 'bottom':
113+
return 'top';
114+
case 'right':
115+
return 'left';
116+
case 'left':
117+
return 'right';
118+
}
119+
120+
throw new Error('Unknown direction: "' + dir + '"');
121+
}
122+
123+
/**
124+
* Calculates an intersection of two areas.
125+
*
126+
* @param {Object} area1
127+
* @param {Object} area2
128+
* @return {Object} an intersection.
129+
*/
130+
function intersection(area1, area2) {
131+
var area = {};
132+
area.top = Math.max(area1.top, area2.top);
133+
area.right = Math.min(area1.left + area1.width, area2.left + area2.width);
134+
area.bottom = Math.min(area1.top + area1.height, area2.top + area2.height);
135+
area.left = Math.max(area1.left, area2.left);
136+
area.height = area.bottom - area.top;
137+
area.width = area.right - area.left;
138+
return area;
139+
}
140+
141+
function scrollOffset() {
142+
var list = [document.documentElement, document.body.parentNode, document.body];
143+
return {
144+
top: list.map(function (el) {
145+
return el.scrollTop;
146+
}).reduce(function (p, v) {
147+
return p || v;
148+
}),
149+
left: list.map(function (el) {
150+
return el.scrollLeft;
151+
}).reduce(function (p, v) {
152+
return p || v;
153+
})
154+
};
155+
}
156+
157+
// Returns current content area
158+
function contentArea() {
159+
return _extends({}, scrollOffset(), {
160+
height: window.innerHeight,
161+
width: window.innerWidth
162+
});
163+
}
164+
165+
// Strip unit string from property values and convert to float
166+
var STRIP_FOR = ['top', 'left', 'right', 'bottom', 'width', 'height'];
167+
function strip(obj) {
168+
var data = _extends({}, obj);
169+
STRIP_FOR.forEach(function (prop) {
170+
if (typeof data[prop] === 'string') {
171+
data[prop] = parseFloat(data[prop].replace('px', ''));
172+
}
173+
});
174+
return data;
175+
}
176+
177+
// Make full area data from minimum data
178+
function amend(area) {
179+
var data = strip(area);
180+
if (typeof data.top !== 'number') {
181+
data.top = 0;
182+
}
183+
if (typeof data.left !== 'number') {
184+
data.left = 0;
185+
}
186+
if (typeof data.right !== 'number' && typeof data.width === 'number') {
187+
data.right = data.left + data.width;
188+
}
189+
if (typeof data.bottom !== 'number' && typeof data.height === 'number') {
190+
data.bottom = data.top + data.height;
191+
}
192+
return data;
193+
}
194+
195+
// Returns directions which are not in target rectangle
196+
function overDirs(tip, el) {
197+
tip = amend(tip);
198+
var area = amend(contentArea());
199+
if (el && (typeof el === 'undefined' ? 'undefined' : _typeof(el)) === 'object') {
200+
area = intersection(area, position(el));
201+
}
202+
203+
var dirs = [];
204+
if (tip.top < area.top) {
205+
dirs.push('top');
206+
}
207+
if (area.right < tip.right) {
208+
dirs.push('right');
209+
}
210+
if (area.bottom < tip.bottom) {
211+
dirs.push('bottom');
212+
}
213+
if (tip.left < area.left) {
214+
dirs.push('left');
215+
}
216+
217+
return dirs;
218+
}
219+
220+
/**
221+
* Places and adjusts a tooltip.
222+
*
223+
* @param {Object} tooltip - DOM element.
224+
* @param {string|Array} place
225+
* @param {Object} origin - DOM element.
226+
* @return {Object} 'offset': style data to locate, 'place': final direction of the tooltip
227+
*/
228+
function adjust(tooltip, props) {
229+
var origin = props.el;
230+
var auto = props.auto;
231+
var within = props.within;
232+
var place = props.place;
233+
234+
if (auto && typeof place === 'string') {
235+
place = place.split(',').map(function (p) {
236+
return p.trim();
237+
});
238+
}
239+
if (place.length === 1) {
240+
place.push(opposite(place));
241+
}
242+
243+
var pos = undefined,
244+
dirs = undefined,
245+
current = undefined,
246+
first = undefined;
247+
var tries = [].concat(_toConsumableArray(place));
248+
while (0 < tries.length) {
249+
current = tries.shift();
250+
pos = placement(current, tooltip, origin);
251+
if (typeof first === 'undefined') {
252+
first = { offset: pos, place: current };
253+
}
254+
dirs = overDirs(pos, within && within());
255+
if (dirs.length === 0) {
256+
return { offset: pos, place: current };
257+
}
258+
}
259+
return first;
260+
}
261+
81262
/**
82263
* Resolves names of target tooltip from action or props.
83264
*

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "redux-tooltip",
3-
"version": "0.3.1",
3+
"version": "0.4.0",
44
"description": "A tooltip React component for Redux",
55
"main": "./lib/index.js",
66
"repository": {

0 commit comments

Comments
 (0)