Skip to content

Commit

Permalink
Migrate to Ink 2 (#2)
Browse files Browse the repository at this point in the history
  • Loading branch information
Vadim Demedes authored Mar 4, 2019
1 parent 7f419e4 commit b30ce17
Show file tree
Hide file tree
Showing 6 changed files with 77 additions and 141 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
node_modules
yarn.lock
dist
build
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
language: node_js
node_js:
- '10'
- '8'
- '6'
68 changes: 22 additions & 46 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,18 @@
"email": "[email protected]",
"url": "github.com/vadimdemedes"
},
"main": "dist/index.js",
"main": "build/index.js",
"engines": {
"node": ">=6"
"node": ">=8"
},
"scripts": {
"pretest": "npm run build",
"test": "xo && ava",
"build": "babel src --out-dir=dist",
"prepublish": "npm run build"
"build": "babel src --out-dir=build",
"prepare": "npm run build"
},
"files": [
"dist"
"build"
],
"keywords": [
"ink",
Expand All @@ -32,62 +32,38 @@
"jsx",
"react"
],
"peerDependencies": {
"ink": "^0.5.0"
},
"dependencies": {
"cli-spinners": "^1.0.0",
"object.omit": "^2.0.1",
"prop-types": "^15.5.10"
},
"devDependencies": {
"ava": "^0.20.0",
"babel-cli": "^6.24.1",
"babel-plugin-transform-react-jsx": "^6.24.1",
"@babel/cli": "^7.2.3",
"@babel/core": "^7.3.3",
"@babel/plugin-proposal-class-properties": "^7.3.3",
"@babel/preset-react": "^7.0.0",
"ava": "*",
"babel-eslint": "^10.0.1",
"delay": "^4.1.0",
"eslint-config-xo-react": "^0.13.0",
"eslint-plugin-react": "^7.1.0",
"ink": "^0.5.0",
"ink": "^2.0.0",
"react": "^16.8.2",
"sinon": "^2.3.6",
"xo": "^0.18.2"
"xo": "*"
},
"babel": {
"plugins": [
[
"transform-react-jsx",
{
"pragma": "h",
"useBuiltIns": true
}
]
"@babel/plugin-proposal-class-properties"
],
"presets": [
"@ava/stage-4",
"@babel/preset-react"
]
},
"ava": {
"babel": {
"presets": [
"@ava/stage-4"
],
"plugins": [
[
"transform-react-jsx",
{
"pragma": "h",
"useBuiltIns": true
}
]
]
}
},
"xo": {
"parser": "babel-eslint",
"extends": [
"xo-react"
],
"rules": {
"react/no-unused-prop-types": 1
},
"settings": {
"react": {
"pragma": "h"
}
}
]
}
}
13 changes: 6 additions & 7 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,14 @@ $ npm install ink-spinner
## Usage

```js
const {h, render} = require('ink');
const Spinner = require('ink-spinner');
import React from 'react';
import {render, Color} from 'ink';
import Spinner from 'ink-spinner';

render((
<div>
<Spinner green/> Loading
</div>
<Color green>
<Spinner green/>{' '}Loading
</Color>
));
```

Expand All @@ -28,8 +29,6 @@ render((

## Props

All props except the own ones listed below are passed as-is to `<Color>`, which means you can easily apply any color, without wrapping `<Spinner>` in `<Color>` manually.

### type

Type: `string`<br>
Expand Down
57 changes: 22 additions & 35 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,49 +1,46 @@
'use strict';

const {h, Color, Component} = require('ink');
const PropTypes = require('prop-types');
const spinners = require('cli-spinners');
const omit = require('object.omit');

class Spinner extends Component {
constructor(props) {
super(props);

this.state = {
frame: 0
};
import React, {Component} from 'react';
import PropTypes from 'prop-types';
import {Box} from 'ink';
import spinners from 'cli-spinners';

export default class Spinner extends Component {
static propTypes = {
type: PropTypes.string
}

this.switchFrame = this.switchFrame.bind(this);
static defaultProps = {
type: 'dots'
}

getSpinner() {
return spinners[this.props.type] || spinners.dots;
state = {
frame: 0
}

render(props, {frame}) {
const colorProps = omit(props, 'type');
render() {
const spinner = this.getSpinner();

return (
<Color {...colorProps}>
{spinner.frames[frame]}
</Color>
<Box>
{spinner.frames[this.state.frame]}
</Box>
);
}

componentDidMount() {
const spinner = this.getSpinner();

this.timer = setInterval(this.switchFrame, spinner.interval);
}

componentWillUnmount() {
clearInterval(this.timer);
}

switchFrame() {
const {frame} = this.state;
getSpinner() {
return spinners[this.props.type] || spinners.dots;
}

switchFrame = () => {
const {frame} = this.state;
const spinner = this.getSpinner();
const isLastFrame = frame === spinner.frames.length - 1;
const nextFrame = isLastFrame ? 0 : frame + 1;
Expand All @@ -53,13 +50,3 @@ class Spinner extends Component {
});
}
}

Spinner.propTypes = {
type: PropTypes.string
};

Spinner.defaultProps = {
type: 'dots'
};

module.exports = Spinner;
76 changes: 25 additions & 51 deletions test.js
Original file line number Diff line number Diff line change
@@ -1,62 +1,36 @@
import {h, build, Color} from 'ink';
import renderToString from 'ink/lib/render-to-string';
import {stub} from 'sinon';
import EventEmitter from 'events';
import React from 'react';
import {render} from 'ink';
import {spy} from 'sinon';
import spinners from 'cli-spinners';
import test from 'ava';
import delay from 'delay';
import Spinner from '.';

test('render', t => {
let component;
test('render spinner', async t => {
const stdout = {
columns: 100,
write: spy()
};

function setRef(ref) {
component = ref;
}
const stdin = new EventEmitter();
stdin.setRawMode = () => {};
stdin.setEncoding = () => {};
stdin.pause = () => {};

const spinner = spinners.dots;
let tree;
const app = render(<Spinner/>, {
stdout,
stdin,
debug: true
});

for (let frame = 0; frame < spinner.frames.length; frame++) {
tree = build(<Spinner ref={setRef}/>, tree);
t.is(renderToString(tree), spinner.frames[frame]);
await delay(spinner.frames.length * spinner.interval);
app.unmount();

component.setState({
frame: frame + 1
});
}
});

test('pass props to <Color>', t => {
const spinner = spinners.dots;

const actual = build(<Spinner green/>);
const expected = build(<Color green>{spinner.frames[0]}</Color>);

t.is(renderToString(actual), renderToString(expected));
});

test('spin', t => {
stub(Spinner.prototype, 'setState');

let component;

function setRef(ref) {
component = ref;
}

build(<Spinner ref={setRef}/>);

const spinner = spinners.dots;

let frame = 1;
let i = 0;

while (i < spinner.frames.length * 2) {
component.switchFrame();

t.deepEqual(component.setState.getCall(i).args[0], {frame});
component.state = {frame};
const allFrames = stdout.write.args.map(args => args[0]);
const frames = [...new Set(allFrames)];

frame = frame === spinner.frames.length - 1 ? 0 : frame + 1;
i++;
}
t.deepEqual(frames, spinner.frames);
t.pass();
});

0 comments on commit b30ce17

Please sign in to comment.