Skip to content
Permalink
Browse files

setup for major refactor

  • Loading branch information...
Justin Rhodes
Justin Rhodes committed Oct 29, 2018
1 parent 2bbd110 commit 87458f38caf19618954b1246b8e2867b51a19dbd
Showing with 183 additions and 61 deletions.
  1. +1 −1 LICENSE
  2. +11 −54 README.md
  3. +8 −3 src/lib/Tooltip/Arrow/Arrow.js
  4. +80 −0 src/lib/Tooltip/TextBox/TextBox.js
  5. +83 −3 src/lib/Tooltip/index.js
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2018 Markus Englund
Copyright (c) 2018 Justin Rhodes

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@@ -1,64 +1,21 @@
# React component boilerplate
# Title 1

This is a simple boilerplate project for building a react component package for npm. It is suitable for building any type of UI component or library (like for example a dropdown menu or a toggle-switch). The project contains a correctly transpiled folder for the component library (easy to get wrong) as well as a demo page for showcasing it. The demo can easily be uploaded to _GitHub Pages_. This boilerplate project is meant to be minimal and easy to understand. Linting, testing, prettier etc have been purposefully left out. It does not include a UMD build, as those aren't really used anymore.
Intro

If you are new to building React components for npm you should check out [this guide](https://medium.com/@markus.s.englund/a-guide-to-building-a-react-component-for-npm-68f03b314753).
For a more detailed documentation and demos check out the documentation [here](https://somelink/).

## How it is structured
## Title 2

The source code has two separate parts – the library and the documentation (demo) page. Both are written in ES6 and JSX, and therefore have to be transpiled by Babel but in different ways.
Some text

### Component library transpilation
### Title 3

The library source code, which is located in `src/lib`, is transpiled with Babel but is _not_ bundled with Webpack. Bundling is completely unnecessary, since the developer who will in the end use your library for their application will bundle their entire codebase, which includes your library. More importantly, if your library has any dependencies, bundling them together with your code would be a disaster since it could cause duplication and therefore larger final bundle size. The components still have to be transpiled since many developers have Webpack configured to not transpile their node_modules folder. Some may not be using JSX or ES6 at all, and would therefore be unable to transpile your component.
Some inline code `src/lib`, some italics _not_

### Demo app transpilation
Some bullet points:

The demo app source code lives inside the `src/docs` folder. It is transpiled, bundled and minified by Webpack and Babel into the `docs` folder in the root directory (by running `npm run docs:prod`). This is a completely normal react app with minimal configuration that imports the component library. It has two purposes: 1. To have a way of inspecting your components while you develop the library, and 2. As a demo to showcase to people who try to figure out what your library does.

The reason that the folder doesn't have a logical name like `demo` is that GitHub Pages requires it to be called `docs` for some reason...

## Getting started

Follow these steps to get started developing your own react component:

* `git clone https://github.com/yogaboll/react-npm-component-starter.git`
* `git clone https://github.com/myrepo/react-custom-tooltip.git`
* `npm install`
* `npm run dev` to transpile both the lib and docs folder in watch mode and serve the docs page for you.
* Go to http://127.0.0.1:8000 to see the demo in action. Whenever you change the code in either src/lib or src/docs, the page will automatically update.

Remember to reset the git history:

* `rm -rf .git`
* `git init`
* `git add .`
* `git commit -m "setup project"`

When you have completed development and want to publish to npm:

* Change the "name" field in the package.json file (the npm package will get this name), as well "description", "author" and any other fields that need to change.
* `npm publish`
* Go to npmjs.com/package/[YOUR COMPONENT NAME]/ to confirm that it has been published.

Host demo on GitHub Pages:

* `npm run docs:prod` - Make a production bundle of the demo app.
* Commit your changes to git and push to your GitHub repository.
* On your GitHub repo page, click the **settings** tab and scroll down to the **GitHub Pages** heading. Pick `master branch /docs folder` in the **source** dropdown, And BOOM, your demo page is already live on the internet for free.
* Note: Sometimes it might take about an hour for the page to actually start hosting. Adding /index.html after the url works instantly for whatever reason.

## What about CSS?

### Inline styles

The easiest option is to use the style attribute. Like this for example:

`<button style={{background: "blue", width: 20 }} >test</button>`

This is a clean approach since the user of your package doesn't have to separately import a css file. The downside is that you can't use a bunch of css features: pseudo-selectors like `:focus` and `:hover`, media-queries and some prefixed css-properties, which can be a deal breaker.

### Separate CSS file

Your other option is to create a css file inside the `src/lib` folder. It will be automatically copied to the generated `lib` folder. Then you have to ask your users to import it into their app with something like `import "../node_modules/[NAME_OF_YOUR_LIBRARY]/lib/styles.css";` or to manually copy it. Your css class names might be global for the developers entire app so make the class names are unique.
* `npm run dev` some text
* Some link http://127.0.0.1:8000.

Keep in mind that it is a bad idea to import the css directly into your component file. This requires the webpack style-loader to work, so any user of your package that does not use this loader will be screwed.
@@ -2,18 +2,18 @@ import React from 'react';
import './arrow.css';

const Arrow = ({
moveDown,
// moveDown,
moveRight,
moveLeft,
moveUp,
// moveUp,
isHovered,
hoverBackground,
backgroundColor,
flat,
zIndex,
arrow }) => {

let left = '';
// let left = '';
backgroundColor = isHovered ?
hoverBackground : backgroundColor;

@@ -22,6 +22,11 @@ const Arrow = ({
let marginLeft;
let marginRight;

// if (position.isSide('top') || position.isSide('bottom')) {
// marginLeft = `${moveRight}px`;
// marginRight = `${moveLeft}px`;
// }

if (arrow.side('top') || arrow.side('bottom')) {
marginLeft = `${moveRight}px`;
marginRight = `${moveLeft}px`;
@@ -15,6 +15,21 @@ class TextBox extends Component {
}

//Set & unset hover state
//TODO: exchange with below
// onSpanHover = (index, lastIndex, numChildren) => {
// this.setState({ hoverIndex: index });
// const { static: rctStatic, arrow, position, hoverArrow } = this.props;
// if (!rctStatic
// && ((index === 0
// && (position.isSide('top') || arrow.isAlign('top')))
// || (index === lastIndex
// && (position.isSide('bottom') || arrow.isSide('bottom')))
// || numChildren === 1)) {
// return hoverArrow(true);
// }
// return hoverArrow(false);
// }

onSpanHover = (index, lastIndex, numChildren) => {
this.setState({ hoverIndex: index });
const { static: tpStatic, arrow, hoverArrow } = this.props;
@@ -46,6 +61,7 @@ class TextBox extends Component {
const {
arrow,
align,
//position,
static: tpStatic,
textBoxWidth: width,
moveDown,
@@ -71,6 +87,24 @@ class TextBox extends Component {
lastH
} = this.state;

//TODO: align.is('top/bottom/center/left/right')
// arrow.position
// const calcHPos = (left, center, right) => {
// return position.isAlign('center') ? center : position.isAlign('left') ? left : right;
// }
// const calcVPos = (perc, elHeight, divider, adjMove, totHeight) => {
// return `calc(${perc}% - ${totHeight || 0}px - ${elHeight}px/${divider} + ${adjMove || 0}px)`
// }
// const calcTopPos = (elHeight, totHeight) => {
// if (position.isAlign('center')) {
// return calcVPos(50, elHeight, 2, null, totHeight);
// } else if (position.isAlign('bottom')) {
// return calcVPos(100, elHeight, 2, -12, totHeight);
// }
// return calcVPos(0, elHeight, 2, 12, totHeight);
// }


const calcHPos = (left, center, right) => {
return align.is('center') ? center : align.is('left') ? left : right;
}
@@ -127,6 +161,52 @@ class TextBox extends Component {
let hRightPos =
calcHPos('0% - 30px', '50% - 40px', '100% - 50px');


//TODO: use below
// if (arrow.isAlign('center') && (position.isSide('top') || position.isSide('bottom'))) {
// arrow.position === 'hCenter';
// } else if (arrow.isAlign('center')) {
// arrow.position === 'vCenter';
// }

// switch (arrow.position) {
// case 'left':
// right = `calc(${hLeftPos})`;
// break;
// case 'right':
// left = `calc(${hRightPos})`;
// break;
// case 'top':
// top = calcTopPos(firstH, null);
// break;
// case 'bottom':
// top = calcTopPos(lineSeparated ? -lastH + 1 : -lastH, totH);
// break;
// case 'vCenter':
// top = calcTopPos(totH, null);
// break;
// case 'hCenter':
// break;
// default:
// break;
// }

// switch (position.side) {
// case 'bottom':
// break;
// case 'top':
// top = calcVPos(0, totH, 1, 11);
// break;
// case 'left':
// right = '8px';
// break;
// case 'right':
// left = '8px';
// break;
// }



switch (arrow.position) {
case 'topLeft':
right = `calc(${hLeftPos})`;
@@ -1,9 +1,7 @@
import React, { Component } from 'react';

import delayUnmount from './HOC/delayUnmount';
import TextBox from './TextBox/TextBox';
import Arrow from './Arrow/Arrow';
// import delayUnmounting from './HOC/old/delayUnmount';
import delayUnmount from './HOC/delayUnmount';

import './style.css';
import './animation.css';
@@ -31,6 +29,8 @@ class Tooltip extends Component {
moveRight: this.props.moveRight || '0px',
moveLeft: this.props.moveLeft || '0px',
moveUp: this.props.moveUp || '0px',
align: this.props.align || 'right center',
arrow: this.props.arrow || 'top'
}

this.props.lineSeparated = typeof (this.props.lineSeparated) == typeof (true)
@@ -50,7 +50,9 @@ class Tooltip extends Component {
fontSize = 'inherit',
color = 'inherit',
animation = '',
// TODO: change to just arrow,
arrow: position,
// TODO: change to position,
align,
moveDown,
moveRight,
@@ -59,18 +61,44 @@ class Tooltip extends Component {
show
} = this.props;

//TODO: remove below functions instead.

function is(pos1, pos2, pos3) {
return this.position === pos1
|| this.position === pos2
|| this.position === pos3;
}

// function isAlign(pos) {
// return this.align ?
// this.align === pos : this.position === ps;
// }

// function isSide(pos) {
// return this.side === pos;
// }

function side(pos) {
if (pos === 'left' || pos === 'right')
return this.is(`${pos}Center`, `${pos}Top`, `${pos}Bottom`);
return this.is(`${pos}Center`, `${pos}Left`, `${pos}Right`);
}

// //TODO: Use below instead
// // align = 'left top' | 'top left' | 'bottom center' | 'left center'
// this.props.position = {
// side: this.props.position.split(' ')[0],
// align: this.props.position.split(' ')[1],
// isAlign,
// isSide
// }

// this.props.arrow = {
// isAlign,
// position: arrow
// };


this.props.align = {
is,
position: align
@@ -93,6 +121,58 @@ class Tooltip extends Component {
let { arrow, align: algn } = this.props;
let bottom;

//TODO: use below code instead

// switch (side) {
// case 'top':
// arrange('100%', 'tpArrowTop', '0px', '', '', '100%');
// break;
// case 'bottom':
// arrange('', 'tpArrowBottom', '0px', '', '', '100%');
// bottom = '100%';
// case 'left':
// arrange('0px', 'tpArrowLeft', '100%', '', '100%', '');
// default:
// arrange('0px', 'tpArrowRight', '', '100%', '100%', '');
// break;
// }

//TODO: exchange let with const declarations
// let onAxis = {
// y: side('top') || side('bottom'),
// x: side('left') || side('right')
// }

// let pushRight = moveRight;
// let pushDown = moveDown;
// let pushLeft = moveLeft;
// let pushUp = moveUp;

// switch (align) {
// case 'left':
// if (onAxis.y) classes.push('tpArrowLeft');
// break;
// case 'right':
// if (onAxis.y) classes.push('tpArrowRight');
// break;
// case 'center':
// if (onAxis.x) {
// classes.push('tpAlignCenter');
// pushDown = pushDown * 2;
// pushUp = pushUp * 2;
// };
// if (onAxis.y) {
// pushRight = pushRight * 2;
// pushLeft = pushLeft * 2;
// }
// break;
// case 'bottom':
// if (onAxis.x) classes.push('tpAlignBottom');
// break;
// default:
// break;
// }

if (arrow.side('top')) {
arrange('100%', 'tpArrowTop', '0px', '', '', '100%');
} else if (arrow.side('bottom')) {

0 comments on commit 87458f3

Please sign in to comment.
You can’t perform that action at this time.