Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

progress bar (WIP) #3

Closed
wants to merge 12 commits into from
Closed
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions docs/ProgressBar.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# ProgressBar

The ProgressBar component represents progress. See examples/progress.js for an example app.

## Usage

```js
const {h, Text, ProgressBar} = require('ink');

<ProgressBar
char="x"
progress={0.5}
left={5}
right={0}
green
/>
```

## Props

### char
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

char => character

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed


The character to use for each item in the ProgressBar. Defaults to █ (block).

### progress

The percentage (between 0 and 1) of progress in the ProgressBar.

### left/right

The number of characters to subtract from each side of the ProgressBar. examples/progress.js demonstrates this. Commonly used if you want text before/after the progress bar on the same line.


### {color}

Pass any chalk colors (e.g. `green`, `bgBlue`), similar to Text.

### ...

Any other props are passed to Text as-is.


49 changes: 49 additions & 0 deletions examples/progress.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/* @jsx h */
const {h, mount, Component, Text, ProgressBar} = require('../');

const delay = ms => new Promise(resolve => setTimeout(resolve, ms));

const TASKS = 30;

class ProgressApp extends Component {
constructor() {
super();

this.state = {
done: 0
};
}

render() {
const text = `Running `;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would just inline this. Everything else is inline.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's used in two places, should I hard code the length?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops, didn't notice that. Would be nice if the bar just calculated the left thing automatically. Feels weird having to manually specify it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It'd have to know what else is on the line, or take the other content as a prop and render it itself, and it couldn't be custom components, and it might be a with multiple to have different colors.

It could have you either pass leftText (string) or leftSize (number), and if you pass leftText it'd render it. This seems confusing though.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think Ink should handle that for us. That's the behavior I expected. That would mean Ink would provide us the available screen space instead of us using process.stdout.columns directly. Let's wait and see what @vadimdemedes thinks.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very good idea, I'd want that to be implemented natively too. Although I've been thinking and didn't come up with a way to solve this properly. Opened #5 to discuss this.

return (
<div>
<Text green>
{text}
</Text>
<ProgressBar
blue
left={text.length}
percent={this.state.done / TASKS}
/>
</div>
);
}

componentDidMount() {
const promises = Array.from({length: TASKS}, () =>
delay(Math.floor(Math.random() * 1500))
.then(() => {
this.setState(state => ({done: state.done + 1}));
})
);

Promise.all(promises)
.then(() => delay(50))
// eslint-disable-next-line unicorn/no-process-exit
.then(() => process.exit(0));
}
}

mount(<ProgressApp/>, process.stdout);

4 changes: 4 additions & 0 deletions examples/run
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/bin/bash

./node_modules/.bin/babel-node examples/$1.js

2 changes: 2 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const Newline = require('./lib/components/newline');
const Indent = require('./lib/components/indent');
const Group = require('./lib/components/group');
const Text = require('./lib/components/text');
const ProgressBar = require('./lib/components/progress-bar');

exports.StringComponent = StringComponent;
exports.Component = Component;
Expand All @@ -19,6 +20,7 @@ exports.Newline = Newline;
exports.Indent = Indent;
exports.Group = Group;
exports.Text = Text;
exports.ProgressBar = ProgressBar;

const noop = () => {};

Expand Down
31 changes: 31 additions & 0 deletions lib/components/progress-bar.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
'use strict';

const blacklist = require('blacklist');
const Component = require('../component');
const h = require('../h');
const Text = require('./text');

const PROPS = ['percent', 'left', 'right', 'columns', 'char'];

class Bar extends Component {
getString() {
const {
percent = 1,
left = 0,
right = 0,
char = '█'
} = this.props;
const screen = this.props.columns || process.stdout.columns || 80;
const space = screen - right - left;
const max = Math.min(Math.floor(space * percent), space);
return char.repeat(max);
}

render() {
const props = blacklist(this.props, PROPS);
return h(Text, props, this.getString());
}
}

module.exports = Bar;

18 changes: 17 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
"node": ">= 4"
},
"scripts": {
"test": "xo && ava"
"test": "xo && ava",
"example:progress": "babel-node examples/progress.js"
},
"files": [
"lib",
Expand All @@ -25,6 +26,7 @@
],
"dependencies": {
"arrify": "^1.0.1",
"blacklist": "^1.1.4",
"chalk": "^2.0.1",
"indent-string": "^3.1.0",
"lodash.flattendeep": "^4.4.0",
Expand All @@ -33,7 +35,10 @@
},
"devDependencies": {
"ava": "^0.19.1",
"babel-cli": "^6.24.1",
"babel-core": "^6.25.0",
"babel-plugin-transform-react-jsx": "^6.24.1",
"babel-preset-react": "^6.24.1",
"babel-register": "^6.24.1",
"eslint-config-xo-react": "^0.12.0",
"eslint-plugin-react": "^7.1.0",
Expand Down Expand Up @@ -73,5 +78,16 @@
"pragma": "h"
}
}
},
"babel": {
"presets": ["babel-preset-react"],
"plugins": [
[
"transform-react-jsx",
{
"pragma": "h"
}
]
]
}
}
16 changes: 16 additions & 0 deletions test/progress-bar.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import test from 'ava';

const ProgressBar = require('../lib/components/progress-bar.js');

const run = (columns, left, right) => ProgressBar.prototype.getString.call({
props: {columns, left, right, char: 'x'}
});

test(`has correct length`, t => {
const str = run(50, 0, 0);
t.is(str.length, 50);

const str2 = run(60, 10, 9);
t.is(str2.length, 41);
});