Skip to content
3 changes: 2 additions & 1 deletion .babelrc
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
{
"presets": ["es2015", "react"]
"presets": ["es2015", "react", "stage-0"],
"plugins": ["transform-decorators-legacy"],
}
67 changes: 67 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
NODE_BIN = node_modules/.bin
EXAMPLE_DIST = example/dist
EXAMPLE_SRC = example/src
STANDALONE = standalone
SRC = src
DIST = dist
TEST = test/*.test.js
MOCHA_OPTS = --compilers js:babel-core/register --require test/setup.js -b --timeout 20000 --reporter spec

lint:
@echo Linting...
@$(NODE_BIN)/standard --verbose | $(NODE_BIN)/snazzy src/index.js

test: lint
@echo Start testing...
@$(NODE_BIN)/mocha $(MOCHA_OPTS) $(TEST)

convertCSS:
@echo Converting css...
@node bin/transferSass.js

genStand:
@echo Generating standard...
@rm -rf $(STANDALONE) && mkdir $(STANDALONE)
@$(NODE_BIN)/browserify -t babelify -t browserify-shim $(SRC)/index.js --standalone ReactTooltip -o $(STANDALONE)/react-tooltip.js
@$(NODE_BIN)/browserify -t babelify -t browserify-shim $(SRC)/index.js --standalone ReactTooltip | $(NODE_BIN)/uglifyjs > $(STANDALONE)/react-tooltip.min.js
@cp $(DIST)/style.js $(STANDALONE)/style.js

devJS:
@$(NODE_BIN)/watchify -t babelify $(EXAMPLE_SRC)/index.js -o $(EXAMPLE_DIST)/index.js -dv

devCSS:
@$(NODE_BIN)/node-sass $(EXAMPLE_SRC)/index.scss $(EXAMPLE_DIST)/index.css
@$(NODE_BIN)/node-sass -w $(EXAMPLE_SRC)/index.scss $(EXAMPLE_DIST)/index.css

devServer:
@echo Listening 8888...
@$(NODE_BIN)/http-server example -p 8888 -s

dev:
@echo starting dev server...
@rm -rf $(EXAMPLE_DIST)
@mkdir -p $(EXAMPLE_DIST)
@make convertCSS
@$(NODE_BIN)/concurrently --kill-others "make devJS" "make devCSS" "make devServer"

deployJS:
@echo Generating deploy JS files...
@$(NODE_BIN)/babel $(SRC)/index.js -o $(DIST)/react-tooltip.js
@$(NODE_BIN)/babel $(SRC)/style.js -o $(DIST)/style.js
@$(NODE_BIN)/babel $(SRC)/index.js | $(NODE_BIN)/uglifyjs > $(DIST)/react-tooltip.min.js

deployCSS:
@echo Generating deploy CSS files...
@cp $(SRC)/index.scss $(DIST)/react-tooltip.scss
@$(NODE_BIN)/node-sass --output-style compressed $(SRC)/index.scss $(DIST)/react-tooltip.min.css

deploy: lint
@echo Deploy...
@rm -rf dist && mkdir dist
@make convertCSS
@make deployCSS
@make deployJS
@make genStand
@echo success!

.PHONY: lint convertCSS genStand devJS devCSS devServer dev deployJS deployCSS deploy
1 change: 1 addition & 0 deletions bin/transferSass.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ function transferSass () {
console.error(err)
}
console.log('css file has been transformed successful')
process.exit()
})
})
}
Expand Down
2 changes: 1 addition & 1 deletion circle.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
machine:
node:
version: 0.12.0
version: 4.2.1

dependencies:
override:
Expand Down
65 changes: 61 additions & 4 deletions example/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import React from 'react'
import {render} from 'react-dom'
import ReactTooltip from '../../src/index'
import ReactTooltip from '../../src'

const Test = React.createClass({

Expand Down Expand Up @@ -152,18 +152,75 @@ const Test = React.createClass({

<div className="example-jsx">
<div className="side">
<a data-for='customer-event' data-tip='customer event' data-event='click' data-type='info'>( •̀д•́)</a>
<ReactTooltip id='customer-event' />
<a data-for='customer-event' data-tip='customer show' data-event='click focus'>( •̀д•́)</a>
<ReactTooltip id='customer-event' globalEventOff='click'/>
</div>

<div className="side">
<a data-for='customer-off-event' data-tip='custom show and hide' data-event='click' data-event-off='dblclick'>( •̀д•́)</a>
<ReactTooltip id='customer-off-event'/>
</div>
</div>
<br />
<pre className='example-pre'>
<div>
<p>{"<a data-tip='customer event' data-event='click' data-type='info'>( •̀д•́)</a>\n" +
<p>{"<a data-tip='customer show' data-event='click focus'>( •̀д•́)</a>\n" +
"<ReactTooltip globalEventOff='click' />"}</p>
</div>
<div>
<p>{"<a data-tip='custom show and hide' data-event='click' data-event-off='dblclick'>( •̀д•́)</a>\n" +
"<ReactTooltip/>"}</p>
</div>
</pre>
</div>

<div className="section">
<h4 className='title'>Theme and delay</h4>
<p className="sub-title"></p>

<div className="example-jsx">
<div className="side">
<a data-for='customer-class' data-tip='hover on me will keep the tootlip'>(・ω´・ )</a>
<ReactTooltip id='customer-class' class='extraClass' delayHide={1000} effect='solid'/>
</div>

<div className="side">
<a data-for='customer-theme' data-tip='custom theme'>(・ω´・ )</a>
<ReactTooltip id='customer-theme' class='customeTheme'/>
</div>
</div>
<br />
<pre className='example-pre'>
<div>
<p>{"<a data-tip='hover on me will keep the tootlip'>(・ω´・ )́)</a>\n" +
"<ReactTooltip class='extraClass' delayHide={1000} effect='solid'/>\n" +
".extraClass {\n" +
" font-size: 20px !important;\n" +
" pointer-events: auto !important;\n" +
" &:hover {\n" +
"visibility: visible !important;\n" +
"opacity: 1 !important;\n" +
" }\n" +
"}"}</p>
</div>

<div>
<p>{"<a data-tip='custom theme'>(・ω´・ )́)</a>\n" +
"<ReactTooltip class='customeTheme'/>\n" +
" .customeTheme {\n" +
" color: #ff6e00 !important;\n" +
" background-color: orange !important;\n" +
" &.place-top {\n" +
" &:after {\n" +
" border-top-color: orange !important;\n" +
" border-top-style: solid !important;\n" +
" border-top-width: 6px !important;\n" +
" }\n" +
" }\n" +
"}"}</p>
</div>
</pre>
</div>
</section>
</div>
)
Expand Down
22 changes: 22 additions & 0 deletions example/src/index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -206,3 +206,25 @@ html, body{
line-height: 30px;
}
}

// Extra class for demonstration
.extraClass {
font-size: 20px !important;
pointer-events: auto !important;
&:hover {
visibility: visible !important;
opacity: 1 !important;
}
}

.customeTheme {
color: #ff6e00 !important;
background-color: orange !important;
&.place-top {
&:after {
border-top-color: orange !important;
border-top-style: solid !important;
border-top-width: 6px !important;
}
}
}
35 changes: 17 additions & 18 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,25 +1,12 @@
{
"name": "react-tooltip",
"version": "2.0.3",
"version": "3.0.0",
"description": "react tooltip component",
"main": "index.js",
"scripts": {
"check": "standard --verbose | snazzy src/index.js",
"test": "npm run check",
"devjs": "node bin/transferSass.js & watchify -t babelify ./example/src/index.js -o ./example/dist/index.js -dv",
"devcss": "node-sass example/src/index.scss example/dist/index.css & node-sass -w example/src/index.scss example/dist/index.css",
"predev": "rm -rf example/dist",
"dev": "mkdir -p ./example/dist & npm run devjs & npm run devcss & http-server example -p 8888 -s -o",
"deployjs": "babel src/index.js -o dist/react-tooltip.js && babel src/style.js -o dist/style.js && npm run deployminjs",
"deployminjs": "babel src/index.js | uglifyjs > dist/react-tooltip.min.js",
"predeploycss": "cp src/index.scss dist/react-tooltip.scss",
"deploycss": "node-sass --output-style compressed src/index.scss dist/react-tooltip.min.css",
"predeploy": "rm -rf dist",
"deploy": "mkdir dist & npm run deployjs & npm run deploycss & npm run standjs",
"prestandjs": "rm -rf standalone",
"standjs": "mkdir standalone && browserify -t babelify -t browserify-shim src/index.js --standalone ReactTooltip -o standalone/react-tooltip.js & npm run standminjs",
"standminjs": "browserify -t babelify -t browserify-shim src/index.js --standalone ReactTooltip | uglifyjs > standalone/react-tooltip.min.js",
"poststandjs": "cp ./dist/style.js ./standalone/style.js"
"test": "make test",
"dev": "make start",
"deploy": "make deploy"
},
"standard": {
"parser": "babel-eslint",
Expand Down Expand Up @@ -59,15 +46,27 @@
},
"devDependencies": {
"babel-cli": "^6.5.1",
"babel-core": "^6.9.1",
"babel-eslint": "^4.1.1",
"babel-plugin-transform-decorators-legacy": "^1.3.4",
"babel-plugin-transform-runtime": "^6.5.0",
"babel-preset-es2015": "^6.5.0",
"babel-preset-react": "^6.5.0",
"babel-preset-stage-0": "^6.5.0",
"babelify": "^7.2.0",
"browserify": "^13.0.0",
"browserify-shim": "^3.8.12",
"chai": "^3.5.0",
"chai-enzyme": "^0.5.0",
"cheerio": "^0.20.0",
"concurrently": "^2.1.0",
"enzyme": "^2.3.0",
"http-server": "^0.8.0",
"node-sass": "^3.3.2",
"jsdom": "^9.2.1",
"mocha": "^2.5.3",
"node-sass": "^3.7.0",
"react-addons-test-utils": "^15.1.0",
"sinon": "^1.17.4",
"snazzy": "^2.0.1",
"standard": "^5.2.2",
"tape": "^4.2.0",
Expand Down
8 changes: 8 additions & 0 deletions src/constant.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export default {

GLOBAL: {
HIDE: '__react_tooltip_hide_event',
REBUILD: '__react_tooltip_rebuild_event',
SHOW: '__react_tooltip_show_event'
}
}
68 changes: 68 additions & 0 deletions src/decorators/customEvent.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/**
* Custom events to control showing and hiding of tooltip
*
* @attributes
* - `event` {String}
* - `eventOff` {String}
*/

const checkStatus = function (dataEventOff, e) {
const {show} = this.state
const dataIsCapture = e.currentTarget.getAttribute('data-iscapture')
const isCapture = dataIsCapture && dataIsCapture === 'true' || this.props.isCapture
const currentItem = e.currentTarget.getAttribute('currentItem')

if (!isCapture) e.stopPropagation()
if (show && currentItem === 'true') {
if (!dataEventOff) this.hideTooltip(e)
} else {
e.currentTarget.setAttribute('currentItem', 'true')
setUntargetItems(e.currentTarget, this.getTargetArray())
this.showTooltip(e)
}
}

const setUntargetItems = function (currentTarget, targetArray) {
for (let i = 0; i < targetArray.length; i++) {
if (currentTarget !== targetArray[i]) {
targetArray[i].setAttribute('currentItem', 'false')
} else {
targetArray[i].setAttribute('currentItem', 'true')
}
}
}

export default function (target) {
target.prototype.isCustomEvent = function (ele) {
const {event} = this.state
return event || ele.getAttribute('data-event')
}

/* Bind listener for custom event */
target.prototype.customBindListener = function (ele) {
const {event, eventOff} = this.state
const dataEvent = ele.getAttribute('data-event') || event
const dataEventOff = ele.getAttribute('data-event-off') || eventOff

dataEvent.split(' ').forEach(event => {
ele.removeEventListener(event, checkStatus)
ele.addEventListener(event, checkStatus.bind(this, dataEventOff), false)
})
if (dataEventOff) {
dataEventOff.split(' ').forEach(event => {
ele.removeEventListener(event, this.hideTooltip)
ele.addEventListener(event, ::this.hideTooltip, false)
})
}
}

/* Unbind listener for custom event */
target.prototype.customUnbindListener = function (ele) {
const {event, eventOff} = this.state
const dataEvent = event || ele.getAttribute('data-event')
const dataEventOff = eventOff || ele.getAttribute('data-event-off')

ele.removeEventListener(dataEvent, checkStatus)
if (dataEventOff) ele.removeEventListener(dataEventOff, this.hideTooltip)
}
}
10 changes: 10 additions & 0 deletions src/decorators/isCapture.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/**
* Util method to judge if it should follow capture model
*/

export default function (target) {
target.prototype.isCapture = function (currentTarget) {
const dataIsCapture = currentTarget.getAttribute('data-iscapture')
return dataIsCapture && dataIsCapture === 'true' || this.props.isCapture || false
}
}
44 changes: 44 additions & 0 deletions src/decorators/staticMethods.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/**
* Static methods for react-tooltip
*/
import CONSTANT from '../constant'

const dispatchGlobalEvent = (eventName) => {
// Compatibale with IE
// @see http://stackoverflow.com/questions/26596123/internet-explorer-9-10-11-event-constructor-doesnt-work
let event

if (typeof window.Event === 'function') {
event = new window.Event(eventName)
} else {
event = document.createEvent('Event')
event.initEvent(eventName, false, true)
}

window.dispatchEvent(event)
}

export default function (target) {
/**
* Hide all tooltip
* @trigger ReactTooltip.hide()
*/
target.hide = () => {
dispatchGlobalEvent(CONSTANT.GLOBAL.HIDE)
}

/**
* Rebuild all tooltip
* @trigger ReactTooltip.rebuild()
*/
target.rebuild = () => {
dispatchGlobalEvent(CONSTANT.GLOBAL.REBUILD)
}

target.prototype.globalRebuild = function () {
if (this.mount) {
this.unbindListener()
this.bindListener()
}
}
}
Loading