ink 2.4.0 → 2.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/apply-styles.js +5 -9
- package/build/components/App.js +2 -1
- package/build/components/Box.js +1 -1
- package/build/components/Static.js +2 -2
- package/build/components/Text.js +4 -0
- package/build/experimental/output.js +5 -1
- package/build/experimental/renderer.js +7 -2
- package/build/hooks/use-app.js +16 -0
- package/build/hooks/use-stdin.js +16 -0
- package/build/hooks/use-stdout.js +16 -0
- package/build/index.js +24 -0
- package/build/instance.js +27 -16
- package/build/output.js +4 -0
- package/build/reconciler.js +2 -2
- package/build/render-node-to-output.js +13 -1
- package/build/render.js +3 -2
- package/build/renderer.js +1 -0
- package/index.d.ts +51 -11
- package/package.json +47 -32
- package/readme.md +170 -136
package/build/apply-styles.js
CHANGED
|
@@ -9,10 +9,6 @@ var _yogaLayoutPrebuilt = _interopRequireDefault(require("yoga-layout-prebuilt")
|
|
|
9
9
|
|
|
10
10
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
11
11
|
|
|
12
|
-
const hasOwnProperty = (obj, prop) => {
|
|
13
|
-
return {}.hasOwnProperty.call(obj, prop);
|
|
14
|
-
};
|
|
15
|
-
|
|
16
12
|
const applyMarginStyles = (node, style) => {
|
|
17
13
|
if (style.margin) {
|
|
18
14
|
node.setMargin(_yogaLayoutPrebuilt.default.EDGE_TOP, style.margin);
|
|
@@ -110,7 +106,7 @@ const applyFlexStyles = (node, style) => {
|
|
|
110
106
|
}
|
|
111
107
|
}
|
|
112
108
|
|
|
113
|
-
if (
|
|
109
|
+
if (style.flexBasis !== undefined) {
|
|
114
110
|
node.setFlexBasis(style.flexBasis);
|
|
115
111
|
}
|
|
116
112
|
|
|
@@ -152,19 +148,19 @@ const applyFlexStyles = (node, style) => {
|
|
|
152
148
|
};
|
|
153
149
|
|
|
154
150
|
const applyDimensionStyles = (node, style) => {
|
|
155
|
-
if (
|
|
151
|
+
if (style.width !== undefined) {
|
|
156
152
|
node.setWidth(style.width);
|
|
157
153
|
}
|
|
158
154
|
|
|
159
|
-
if (
|
|
155
|
+
if (style.height !== undefined) {
|
|
160
156
|
node.setHeight(style.height);
|
|
161
157
|
}
|
|
162
158
|
|
|
163
|
-
if (
|
|
159
|
+
if (style.minWidth !== undefined) {
|
|
164
160
|
node.setMinWidth(style.minWidth);
|
|
165
161
|
}
|
|
166
162
|
|
|
167
|
-
if (
|
|
163
|
+
if (style.minHeight !== undefined) {
|
|
168
164
|
node.setMinHeight(style.minHeight);
|
|
169
165
|
}
|
|
170
166
|
};
|
package/build/components/App.js
CHANGED
|
@@ -21,7 +21,7 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
|
|
|
21
21
|
|
|
22
22
|
function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }
|
|
23
23
|
|
|
24
|
-
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {};
|
|
24
|
+
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
|
25
25
|
|
|
26
26
|
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
27
27
|
|
|
@@ -136,5 +136,6 @@ _defineProperty(App, "propTypes", {
|
|
|
136
136
|
stdin: _propTypes.default.object.isRequired,
|
|
137
137
|
stdout: _propTypes.default.object.isRequired,
|
|
138
138
|
exitOnCtrlC: _propTypes.default.bool.isRequired,
|
|
139
|
+
// eslint-disable-line react/boolean-prop-naming
|
|
139
140
|
onExit: _propTypes.default.func.isRequired
|
|
140
141
|
});
|
package/build/components/Box.js
CHANGED
|
@@ -13,7 +13,7 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
|
|
|
13
13
|
|
|
14
14
|
function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }
|
|
15
15
|
|
|
16
|
-
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {};
|
|
16
|
+
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
|
17
17
|
|
|
18
18
|
function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }
|
|
19
19
|
|
|
@@ -13,11 +13,11 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
|
|
|
13
13
|
|
|
14
14
|
function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }
|
|
15
15
|
|
|
16
|
-
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {};
|
|
16
|
+
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
|
17
17
|
|
|
18
18
|
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
|
|
19
19
|
|
|
20
|
-
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
|
|
20
|
+
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
|
|
21
21
|
|
|
22
22
|
function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }
|
|
23
23
|
|
package/build/components/Text.js
CHANGED
|
@@ -53,6 +53,8 @@ const Text = ({
|
|
|
53
53
|
unstable__transformChildren: transformChildren
|
|
54
54
|
}, children);
|
|
55
55
|
};
|
|
56
|
+
/* eslint-disable react/boolean-prop-naming */
|
|
57
|
+
|
|
56
58
|
|
|
57
59
|
Text.propTypes = {
|
|
58
60
|
bold: _propTypes.default.bool,
|
|
@@ -62,6 +64,8 @@ Text.propTypes = {
|
|
|
62
64
|
children: _propTypes.default.node.isRequired,
|
|
63
65
|
unstable__transformChildren: _propTypes.default.func
|
|
64
66
|
};
|
|
67
|
+
/* eslint-enable react/boolean-prop-naming */
|
|
68
|
+
|
|
65
69
|
Text.defaultProps = {
|
|
66
70
|
bold: false,
|
|
67
71
|
italic: false,
|
|
@@ -64,11 +64,16 @@ var _default = ({
|
|
|
64
64
|
});
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
+
const {
|
|
68
|
+
output: generatedOutput,
|
|
69
|
+
height: outputHeight
|
|
70
|
+
} = output.get();
|
|
67
71
|
return {
|
|
68
|
-
output:
|
|
72
|
+
output: generatedOutput,
|
|
73
|
+
outputHeight,
|
|
69
74
|
// Newline at the end is needed, because static output doesn't have one, so
|
|
70
75
|
// interactive output will override last line of static output
|
|
71
|
-
staticOutput: staticOutput ? `${staticOutput.get()}\n` : undefined
|
|
76
|
+
staticOutput: staticOutput ? `${staticOutput.get().output}\n` : undefined
|
|
72
77
|
};
|
|
73
78
|
};
|
|
74
79
|
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
|
|
8
|
+
var _react = require("react");
|
|
9
|
+
|
|
10
|
+
var _AppContext = _interopRequireDefault(require("../components/AppContext"));
|
|
11
|
+
|
|
12
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
13
|
+
|
|
14
|
+
var _default = () => (0, _react.useContext)(_AppContext.default);
|
|
15
|
+
|
|
16
|
+
exports.default = _default;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
|
|
8
|
+
var _react = require("react");
|
|
9
|
+
|
|
10
|
+
var _StdinContext = _interopRequireDefault(require("../components/StdinContext"));
|
|
11
|
+
|
|
12
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
13
|
+
|
|
14
|
+
var _default = () => (0, _react.useContext)(_StdinContext.default);
|
|
15
|
+
|
|
16
|
+
exports.default = _default;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
|
|
8
|
+
var _react = require("react");
|
|
9
|
+
|
|
10
|
+
var _StdoutContext = _interopRequireDefault(require("../components/StdoutContext"));
|
|
11
|
+
|
|
12
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
13
|
+
|
|
14
|
+
var _default = () => (0, _react.useContext)(_StdoutContext.default);
|
|
15
|
+
|
|
16
|
+
exports.default = _default;
|
package/build/index.js
CHANGED
|
@@ -57,6 +57,24 @@ Object.defineProperty(exports, "useInput", {
|
|
|
57
57
|
return _useInput.default;
|
|
58
58
|
}
|
|
59
59
|
});
|
|
60
|
+
Object.defineProperty(exports, "useApp", {
|
|
61
|
+
enumerable: true,
|
|
62
|
+
get: function () {
|
|
63
|
+
return _useApp.default;
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
Object.defineProperty(exports, "useStdin", {
|
|
67
|
+
enumerable: true,
|
|
68
|
+
get: function () {
|
|
69
|
+
return _useStdin.default;
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
Object.defineProperty(exports, "useStdout", {
|
|
73
|
+
enumerable: true,
|
|
74
|
+
get: function () {
|
|
75
|
+
return _useStdout.default;
|
|
76
|
+
}
|
|
77
|
+
});
|
|
60
78
|
|
|
61
79
|
var _render = _interopRequireDefault(require("./render"));
|
|
62
80
|
|
|
@@ -76,4 +94,10 @@ var _Static = _interopRequireDefault(require("./components/Static"));
|
|
|
76
94
|
|
|
77
95
|
var _useInput = _interopRequireDefault(require("./hooks/use-input"));
|
|
78
96
|
|
|
97
|
+
var _useApp = _interopRequireDefault(require("./hooks/use-app"));
|
|
98
|
+
|
|
99
|
+
var _useStdin = _interopRequireDefault(require("./hooks/use-stdin"));
|
|
100
|
+
|
|
101
|
+
var _useStdout = _interopRequireDefault(require("./hooks/use-stdout"));
|
|
102
|
+
|
|
79
103
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
package/build/instance.js
CHANGED
|
@@ -17,6 +17,8 @@ var _isCi = _interopRequireDefault(require("is-ci"));
|
|
|
17
17
|
|
|
18
18
|
var _signalExit = _interopRequireDefault(require("signal-exit"));
|
|
19
19
|
|
|
20
|
+
var _ansiEscapes = _interopRequireDefault(require("ansi-escapes"));
|
|
21
|
+
|
|
20
22
|
var _reconciler = _interopRequireDefault(require("./reconciler"));
|
|
21
23
|
|
|
22
24
|
var _reconciler2 = _interopRequireDefault(require("./experimental/reconciler"));
|
|
@@ -35,7 +37,7 @@ var _App = _interopRequireDefault(require("./components/App"));
|
|
|
35
37
|
|
|
36
38
|
function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }
|
|
37
39
|
|
|
38
|
-
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {};
|
|
40
|
+
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
|
39
41
|
|
|
40
42
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
41
43
|
|
|
@@ -98,6 +100,7 @@ class Instance {
|
|
|
98
100
|
|
|
99
101
|
const {
|
|
100
102
|
output,
|
|
103
|
+
outputHeight,
|
|
101
104
|
staticOutput
|
|
102
105
|
} = this.renderer(this.rootNode); // If <Static> output isn't empty, it means new children have been added to it
|
|
103
106
|
|
|
@@ -110,31 +113,39 @@ class Instance {
|
|
|
110
113
|
|
|
111
114
|
this.options.stdout.write(this.fullStaticOutput + output);
|
|
112
115
|
return;
|
|
113
|
-
}
|
|
116
|
+
}
|
|
114
117
|
|
|
118
|
+
if (_isCi.default) {
|
|
119
|
+
if (hasStaticOutput) {
|
|
120
|
+
this.options.stdout.write(staticOutput);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
this.lastOutput = output;
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
115
126
|
|
|
116
127
|
if (hasStaticOutput) {
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
}
|
|
128
|
+
this.fullStaticOutput += staticOutput;
|
|
129
|
+
}
|
|
120
130
|
|
|
121
|
-
|
|
131
|
+
if (this.options.experimental && outputHeight >= this.options.stdout.rows) {
|
|
132
|
+
this.options.stdout.write(_ansiEscapes.default.clearTerminal + this.fullStaticOutput + output);
|
|
133
|
+
this.lastOutput = output;
|
|
134
|
+
return;
|
|
135
|
+
} // To ensure static output is cleanly rendered before main output, clear main output first
|
|
122
136
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
this.log(output);
|
|
128
|
-
}
|
|
129
|
-
}
|
|
137
|
+
|
|
138
|
+
if (hasStaticOutput) {
|
|
139
|
+
this.log.clear();
|
|
140
|
+
this.options.stdout.write(staticOutput);
|
|
130
141
|
}
|
|
131
142
|
|
|
132
143
|
if (output !== this.lastOutput) {
|
|
133
|
-
if (
|
|
144
|
+
if (this.options.experimental) {
|
|
145
|
+
this.throttledLog(output);
|
|
146
|
+
} else {
|
|
134
147
|
this.log(output);
|
|
135
148
|
}
|
|
136
|
-
|
|
137
|
-
this.lastOutput = output;
|
|
138
149
|
}
|
|
139
150
|
}
|
|
140
151
|
|
package/build/output.js
CHANGED
package/build/reconciler.js
CHANGED
|
@@ -45,7 +45,7 @@ const hostConfig = {
|
|
|
45
45
|
}
|
|
46
46
|
}
|
|
47
47
|
} else if (key === 'style') {
|
|
48
|
-
|
|
48
|
+
node.style = value;
|
|
49
49
|
} else if (key === 'unstable__transformChildren') {
|
|
50
50
|
node.unstable__transformChildren = value; // eslint-disable-line camelcase
|
|
51
51
|
} else if (key === 'unstable__static') {
|
|
@@ -101,7 +101,7 @@ const hostConfig = {
|
|
|
101
101
|
}
|
|
102
102
|
}
|
|
103
103
|
} else if (key === 'style') {
|
|
104
|
-
|
|
104
|
+
node.style = value;
|
|
105
105
|
} else if (key === 'unstable__transformChildren') {
|
|
106
106
|
node.unstable__transformChildren = value; // eslint-disable-line camelcase
|
|
107
107
|
} else if (key === 'unstable__static') {
|
|
@@ -38,7 +38,19 @@ const isAllTextNodes = node => {
|
|
|
38
38
|
|
|
39
39
|
|
|
40
40
|
const squashTextNodes = node => {
|
|
41
|
-
|
|
41
|
+
if (node.childNodes.length === 0) {
|
|
42
|
+
return '';
|
|
43
|
+
} // If parent container is `<Box>`, text nodes will be treated as separate nodes in
|
|
44
|
+
// the tree and will have their own coordinates in the layout.
|
|
45
|
+
// To ensure text nodes are aligned correctly, take X and Y of the first text node
|
|
46
|
+
// and use them as offset for the rest of the nodes
|
|
47
|
+
// Only first node is taken into account, because other text nodes can't have margin or padding,
|
|
48
|
+
// so their coordinates will be relative to the first node anyway
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
const offsetX = node.childNodes[0].yogaNode.getComputedLeft();
|
|
52
|
+
const offsetY = node.childNodes[0].yogaNode.getComputedTop();
|
|
53
|
+
let text = '\n'.repeat(offsetY) + ' '.repeat(offsetX);
|
|
42
54
|
|
|
43
55
|
for (const childNode of node.childNodes) {
|
|
44
56
|
let nodeText;
|
package/build/render.js
CHANGED
|
@@ -13,7 +13,7 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
|
|
|
13
13
|
|
|
14
14
|
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
|
|
15
15
|
|
|
16
|
-
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
|
|
16
|
+
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
|
|
17
17
|
|
|
18
18
|
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
19
19
|
|
|
@@ -30,7 +30,8 @@ var _default = (node, options = {}) => {
|
|
|
30
30
|
stdout: process.stdout,
|
|
31
31
|
stdin: process.stdin,
|
|
32
32
|
debug: false,
|
|
33
|
-
exitOnCtrlC: true
|
|
33
|
+
exitOnCtrlC: true,
|
|
34
|
+
experimental: false
|
|
34
35
|
}, options);
|
|
35
36
|
let instance;
|
|
36
37
|
|
package/build/renderer.js
CHANGED
package/index.d.ts
CHANGED
|
@@ -228,20 +228,41 @@ export const Text: React.FC<TextProps>;
|
|
|
228
228
|
*/
|
|
229
229
|
export const Static: React.FC<{children: React.ReactNodeArray}>;
|
|
230
230
|
|
|
231
|
-
|
|
232
|
-
* `<AppContext>` is a React context, which exposes a method to manually exit the app (unmount).
|
|
233
|
-
*/
|
|
234
|
-
export const AppContext: React.Context<{
|
|
231
|
+
interface AppProps {
|
|
235
232
|
/**
|
|
236
233
|
* Exit (unmount) the whole Ink app.
|
|
237
234
|
*/
|
|
238
235
|
readonly exit: (error?: Error) => void;
|
|
239
|
-
}
|
|
236
|
+
}
|
|
240
237
|
|
|
241
238
|
/**
|
|
242
|
-
*
|
|
239
|
+
* `AppContext` is a React context, which exposes a method to manually exit the app (unmount).
|
|
243
240
|
*/
|
|
244
|
-
export const
|
|
241
|
+
export const AppContext: React.Context<AppProps>;
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* `useApp` is a React hook, which exposes props of `AppContext`.
|
|
245
|
+
* ```js
|
|
246
|
+
* import {useApp} from 'ink';
|
|
247
|
+
*
|
|
248
|
+
* const MyApp = () => {
|
|
249
|
+
* const {exit} = useApp();
|
|
250
|
+
* };
|
|
251
|
+
* ```
|
|
252
|
+
*
|
|
253
|
+
* It's equivalent to consuming `AppContext` props via `AppContext.Consumer`:
|
|
254
|
+
*
|
|
255
|
+
* ```jsx
|
|
256
|
+
* <AppContext.Consumer>
|
|
257
|
+
* {({exit}) => {
|
|
258
|
+
* // …
|
|
259
|
+
* }}
|
|
260
|
+
* </AppContext.Consumer>
|
|
261
|
+
* ```
|
|
262
|
+
*/
|
|
263
|
+
export function useApp(): AppProps;
|
|
264
|
+
|
|
265
|
+
interface StdinProps {
|
|
245
266
|
/**
|
|
246
267
|
* Stdin stream passed to `render()` in `options.stdin` or `process.stdin` by default. Useful if your app needs to handle user input.
|
|
247
268
|
*/
|
|
@@ -257,14 +278,33 @@ export const StdinContext: React.Context<{
|
|
|
257
278
|
* If the `stdin` stream passed to Ink does not support setRawMode, this function does nothing.
|
|
258
279
|
*/
|
|
259
280
|
readonly setRawMode: NodeJS.ReadStream['setRawMode'];
|
|
260
|
-
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* `StdinContext` is a React context, which exposes input stream.
|
|
285
|
+
*/
|
|
286
|
+
export const StdinContext: React.Context<StdinProps>;
|
|
261
287
|
|
|
262
288
|
/**
|
|
263
|
-
*
|
|
289
|
+
* `useStdin` is a React hook, which exposes props of `StdinContext`.
|
|
290
|
+
* Similar to `useApp`, it's equivalent to consuming `StdinContext` directly.
|
|
264
291
|
*/
|
|
265
|
-
export
|
|
292
|
+
export function useStdin(): StdinProps;
|
|
293
|
+
|
|
294
|
+
interface StdoutProps {
|
|
266
295
|
/**
|
|
267
296
|
* Stdout stream passed to `render()` in `options.stdout` or `process.stdout` by default.
|
|
268
297
|
*/
|
|
269
298
|
readonly stdout: NodeJS.WriteStream;
|
|
270
|
-
}
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
/**
|
|
302
|
+
* `StdoutContext` is a React context, which exposes stdout stream, where Ink renders your app.
|
|
303
|
+
*/
|
|
304
|
+
export const StdoutContext: React.Context<StdoutProps>;
|
|
305
|
+
|
|
306
|
+
/**
|
|
307
|
+
* `useStdout` is a React hook, which exposes props of `StdoutContext`.
|
|
308
|
+
* Similar to `useStdout`, it's equivalent to consuming `StdoutContext` directly.
|
|
309
|
+
*/
|
|
310
|
+
export function useStdout(): StdoutProps;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ink",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.7.1",
|
|
4
4
|
"description": "React for CLI",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": "vadimdemedes/ink",
|
|
@@ -40,51 +40,58 @@
|
|
|
40
40
|
"text"
|
|
41
41
|
],
|
|
42
42
|
"dependencies": {
|
|
43
|
-
"
|
|
44
|
-
"arrify": "^
|
|
45
|
-
"auto-bind": "^
|
|
46
|
-
"chalk": "^
|
|
47
|
-
"cli-cursor": "^
|
|
48
|
-
"cli-truncate": "^
|
|
43
|
+
"ansi-escapes": "^4.2.1",
|
|
44
|
+
"arrify": "^2.0.1",
|
|
45
|
+
"auto-bind": "^4.0.0",
|
|
46
|
+
"chalk": "^3.0.0",
|
|
47
|
+
"cli-cursor": "^3.1.0",
|
|
48
|
+
"cli-truncate": "^2.1.0",
|
|
49
49
|
"is-ci": "^2.0.0",
|
|
50
50
|
"lodash.throttle": "^4.1.1",
|
|
51
51
|
"log-update": "^3.0.0",
|
|
52
52
|
"prop-types": "^15.6.2",
|
|
53
|
-
"react-reconciler": "^0.
|
|
54
|
-
"scheduler": "^0.
|
|
53
|
+
"react-reconciler": "^0.24.0",
|
|
54
|
+
"scheduler": "^0.18.0",
|
|
55
55
|
"signal-exit": "^3.0.2",
|
|
56
|
-
"slice-ansi": "^
|
|
57
|
-
"string-length": "^
|
|
58
|
-
"widest-line": "^
|
|
59
|
-
"wrap-ansi": "^
|
|
56
|
+
"slice-ansi": "^3.0.0",
|
|
57
|
+
"string-length": "^3.1.0",
|
|
58
|
+
"widest-line": "^3.1.0",
|
|
59
|
+
"wrap-ansi": "^6.2.0",
|
|
60
60
|
"yoga-layout-prebuilt": "^1.9.3"
|
|
61
61
|
},
|
|
62
62
|
"devDependencies": {
|
|
63
|
-
"@babel/cli": "^7.
|
|
64
|
-
"@babel/core": "^7.
|
|
65
|
-
"@babel/plugin-proposal-class-properties": "^7.
|
|
66
|
-
"@babel/plugin-proposal-object-rest-spread": "^7.
|
|
67
|
-
"@babel/preset-react": "^7.
|
|
68
|
-
"
|
|
63
|
+
"@babel/cli": "^7.8.3",
|
|
64
|
+
"@babel/core": "^7.8.3",
|
|
65
|
+
"@babel/plugin-proposal-class-properties": "^7.8.3",
|
|
66
|
+
"@babel/plugin-proposal-object-rest-spread": "^7.8.3",
|
|
67
|
+
"@babel/preset-react": "^7.8.3",
|
|
68
|
+
"@types/react": "^16.9.19",
|
|
69
|
+
"ava": "^2.4.0",
|
|
69
70
|
"babel-eslint": "^10.0.1",
|
|
70
71
|
"delay": "^4.1.0",
|
|
71
|
-
"eslint-config-xo-react": "^0.
|
|
72
|
-
"eslint-plugin-react": "^7.
|
|
73
|
-
"eslint-plugin-react-hooks": "^
|
|
74
|
-
"import-jsx": "^1.
|
|
72
|
+
"eslint-config-xo-react": "^0.22.0",
|
|
73
|
+
"eslint-plugin-react": "^7.18.0",
|
|
74
|
+
"eslint-plugin-react-hooks": "^2.3.0",
|
|
75
|
+
"import-jsx": "^3.1.0",
|
|
75
76
|
"ms": "^2.1.1",
|
|
76
|
-
"node-pty": "^0.
|
|
77
|
-
"p-queue": "^
|
|
77
|
+
"node-pty": "^0.9.0",
|
|
78
|
+
"p-queue": "^6.2.1",
|
|
78
79
|
"react": "^16.9.0",
|
|
79
|
-
"sinon": "^
|
|
80
|
-
"strip-ansi": "^
|
|
80
|
+
"sinon": "^8.1.1",
|
|
81
|
+
"strip-ansi": "^6.0.0",
|
|
81
82
|
"svg-term-cli": "^2.1.1",
|
|
82
|
-
"tsd": "^0.
|
|
83
|
-
"xo": "^0.
|
|
83
|
+
"tsd": "^0.11.0",
|
|
84
|
+
"xo": "^0.25.3"
|
|
84
85
|
},
|
|
85
86
|
"peerDependencies": {
|
|
87
|
+
"@types/react": ">=16.8.0",
|
|
86
88
|
"react": ">=16.8.0"
|
|
87
89
|
},
|
|
90
|
+
"peerDependenciesMeta": {
|
|
91
|
+
"@types/react": {
|
|
92
|
+
"optional": true
|
|
93
|
+
}
|
|
94
|
+
},
|
|
88
95
|
"babel": {
|
|
89
96
|
"plugins": [
|
|
90
97
|
"@babel/plugin-proposal-class-properties",
|
|
@@ -107,7 +114,13 @@
|
|
|
107
114
|
"@babel/preset-react"
|
|
108
115
|
]
|
|
109
116
|
}
|
|
110
|
-
}
|
|
117
|
+
},
|
|
118
|
+
"files": [
|
|
119
|
+
"test/*.js"
|
|
120
|
+
],
|
|
121
|
+
"helpers": [
|
|
122
|
+
"test/helpers/*.js"
|
|
123
|
+
]
|
|
111
124
|
},
|
|
112
125
|
"xo": {
|
|
113
126
|
"parser": "babel-eslint",
|
|
@@ -118,7 +131,9 @@
|
|
|
118
131
|
"react"
|
|
119
132
|
],
|
|
120
133
|
"rules": {
|
|
121
|
-
"react/no-unescaped-entities": "off"
|
|
134
|
+
"react/no-unescaped-entities": "off",
|
|
135
|
+
"react/state-in-constructor": "off",
|
|
136
|
+
"react/jsx-indent": "off"
|
|
122
137
|
},
|
|
123
138
|
"overrides": [
|
|
124
139
|
{
|
|
@@ -128,7 +143,7 @@
|
|
|
128
143
|
],
|
|
129
144
|
"rules": {
|
|
130
145
|
"unicorn/filename-case": "off",
|
|
131
|
-
"react/require-default-props": "
|
|
146
|
+
"react/require-default-props": "warn"
|
|
132
147
|
}
|
|
133
148
|
}
|
|
134
149
|
]
|
package/readme.md
CHANGED
|
@@ -11,19 +11,17 @@
|
|
|
11
11
|
|
|
12
12
|

|
|
13
13
|
|
|
14
|
-
|
|
15
14
|
## Install
|
|
16
15
|
|
|
17
16
|
```
|
|
18
17
|
$ npm install ink react
|
|
19
18
|
```
|
|
20
19
|
|
|
21
|
-
|
|
22
20
|
## Usage
|
|
23
21
|
|
|
24
22
|
```jsx
|
|
25
|
-
import React, {Component} from
|
|
26
|
-
import {render, Color} from
|
|
23
|
+
import React, { Component } from "react";
|
|
24
|
+
import { render, Color } from "ink";
|
|
27
25
|
|
|
28
26
|
class Counter extends Component {
|
|
29
27
|
constructor() {
|
|
@@ -35,11 +33,7 @@ class Counter extends Component {
|
|
|
35
33
|
}
|
|
36
34
|
|
|
37
35
|
render() {
|
|
38
|
-
return
|
|
39
|
-
<Color green>
|
|
40
|
-
{this.state.i} tests passed
|
|
41
|
-
</Color>
|
|
42
|
-
);
|
|
36
|
+
return <Color green>{this.state.i} tests passed</Color>;
|
|
43
37
|
}
|
|
44
38
|
|
|
45
39
|
componentDidMount() {
|
|
@@ -55,7 +49,7 @@ class Counter extends Component {
|
|
|
55
49
|
}
|
|
56
50
|
}
|
|
57
51
|
|
|
58
|
-
render(<Counter/>);
|
|
52
|
+
render(<Counter />);
|
|
59
53
|
```
|
|
60
54
|
|
|
61
55
|
<img src="media/demo.svg" width="600">
|
|
@@ -63,33 +57,39 @@ render(<Counter/>);
|
|
|
63
57
|
You can also check it out live on [repl.it sandbox](https://ink-counter-demo.vadimdemedes.repl.run/).
|
|
64
58
|
Feel free to play around with the code and fork this repl at [https://repl.it/@vadimdemedes/ink-counter-demo](https://repl.it/@vadimdemedes/ink-counter-demo).
|
|
65
59
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
-
|
|
70
|
-
-
|
|
71
|
-
-
|
|
72
|
-
-
|
|
73
|
-
-
|
|
74
|
-
-
|
|
75
|
-
-
|
|
76
|
-
-
|
|
77
|
-
-
|
|
78
|
-
-
|
|
79
|
-
|
|
60
|
+
## Who's Using Ink?
|
|
61
|
+
|
|
62
|
+
- [Gatsby](https://www.gatsbyjs.org) - Gatsby is a modern web framework for blazing fast websites.
|
|
63
|
+
- [Parcel](https://parceljs.org) - Blazing fast, zero configuration web application bundler.
|
|
64
|
+
- [tap](https://node-tap.org) - A Test-Anything-Protocol library for JavaScript.
|
|
65
|
+
- [Typewriter](https://github.com/segmentio/typewriter) - Generates strongly-typed [Segment](https://segment.com) analytics clients from arbitrary JSON Schema.
|
|
66
|
+
- [Prisma](https://www.prisma.io) - The unified data layer for modern applications.
|
|
67
|
+
- [Wallace](https://www.projectwallace.com) - Pretty CSS analytics on the CLI.
|
|
68
|
+
- [tink](https://github.com/npm/tink) - Next-generation runtime and package manager.
|
|
69
|
+
- [Splash](https://github.com/Shopify/polaris-react/tree/master/scripts/splash) - Observe the splash zone of a change across the Shopify's [Polaris](https://polaris.shopify.com) component library.
|
|
70
|
+
- [emoj](https://github.com/sindresorhus/emoj) - Find relevant emoji on the command-line.
|
|
71
|
+
- [emma](https://github.com/maticzav/emma-cli) - Terminal assistant to find and install npm packages.
|
|
72
|
+
- [sindresorhus](https://github.com/sindresorhus/sindresorhus) - The Sindre Sorhus CLI.
|
|
73
|
+
- [swiff](https://github.com/simple-integrated-marketing/swiff) - Multi-environment command line tools for time-saving web developers.
|
|
74
|
+
- [share](https://github.com/marionebl/share-cli) - Quickly share files from your command line.
|
|
75
|
+
- [Kubelive](https://github.com/ameerthehacker/kubelive) - CLI for Kubernetes to provide live data about the cluster and its resources.
|
|
76
|
+
- [changelog-view](https://github.com/jdeniau/changelog-view) - Tool view changelog in console.
|
|
77
|
+
- [gomoku-terminal](https://github.com/acrazing/gomoku-terminal) - Play online Gomoku in the terminal.
|
|
78
|
+
- [cfpush](https://github.com/mamachanko/cfpush) - An interactive Cloud Foundry tutorial in your terminal.
|
|
79
|
+
- [startd](https://github.com/mgrip/startd) - Turn your React component into a web app from the command-line.
|
|
80
|
+
- [wiki-cli](https://github.com/hexrcs/wiki-cli) - Search Wikipedia and read summaries directly in your terminal.
|
|
80
81
|
|
|
81
82
|
## Contents
|
|
82
83
|
|
|
83
|
-
-
|
|
84
|
-
-
|
|
85
|
-
-
|
|
86
|
-
-
|
|
87
|
-
-
|
|
88
|
-
-
|
|
89
|
-
-
|
|
90
|
-
-
|
|
91
|
-
-
|
|
92
|
-
|
|
84
|
+
- [Getting Started](#getting-started)
|
|
85
|
+
- [Examples](#examples)
|
|
86
|
+
- [API](#api)
|
|
87
|
+
- [Building Layouts](#building-layouts)
|
|
88
|
+
- [Built-in Components](#built-in-components)
|
|
89
|
+
- [Hooks](#hooks)
|
|
90
|
+
- [Useful Components](#useful-components)
|
|
91
|
+
- [Testing](#testing)
|
|
92
|
+
- [Experimental mode](#experimental-mode)
|
|
93
93
|
|
|
94
94
|
## Getting Started
|
|
95
95
|
|
|
@@ -120,25 +120,19 @@ To get started with Ink quickly, use [create-ink-app](https://github.com/vadimde
|
|
|
120
120
|
Don't forget to import `React` into every file that contains JSX:
|
|
121
121
|
|
|
122
122
|
```jsx
|
|
123
|
-
import React from
|
|
124
|
-
import {render, Box} from
|
|
123
|
+
import React from "react";
|
|
124
|
+
import { render, Box } from "ink";
|
|
125
125
|
|
|
126
|
-
const Demo = () =>
|
|
127
|
-
<Box>
|
|
128
|
-
Hello World
|
|
129
|
-
</Box>
|
|
130
|
-
);
|
|
126
|
+
const Demo = () => <Box>Hello World</Box>;
|
|
131
127
|
|
|
132
|
-
render(<Demo/>);
|
|
128
|
+
render(<Demo />);
|
|
133
129
|
```
|
|
134
130
|
|
|
135
|
-
|
|
136
131
|
## Examples
|
|
137
132
|
|
|
138
|
-
-
|
|
139
|
-
-
|
|
140
|
-
-
|
|
141
|
-
|
|
133
|
+
- [Jest](examples/jest/jest.js) - Implementation of basic Jest UI [(live demo)](https://ink-jest-demo.vadimdemedes.repl.run/).
|
|
134
|
+
- [Counter](examples/counter/counter.js) - Simple counter that increments every 100ms [(live demo)](https://ink-counter-demo.vadimdemedes.repl.run/).
|
|
135
|
+
- [Form with Validation](https://github.com/final-form/rff-cli-example) - Using framework agnostic form library, [🏁 Final Form](https://github.com/final-form/final-form#-final-form) to manage input state.
|
|
142
136
|
|
|
143
137
|
## API
|
|
144
138
|
|
|
@@ -197,8 +191,8 @@ Default: `false`
|
|
|
197
191
|
Enables [experimental mode](#experimental-mode).
|
|
198
192
|
|
|
199
193
|
```jsx
|
|
200
|
-
import React, {Component} from
|
|
201
|
-
import {render, Box} from
|
|
194
|
+
import React, { Component } from "react";
|
|
195
|
+
import { render, Box } from "ink";
|
|
202
196
|
|
|
203
197
|
class Counter extends Component {
|
|
204
198
|
constructor() {
|
|
@@ -210,11 +204,7 @@ class Counter extends Component {
|
|
|
210
204
|
}
|
|
211
205
|
|
|
212
206
|
render() {
|
|
213
|
-
return
|
|
214
|
-
<Box>
|
|
215
|
-
Iteration #{this.state.i}
|
|
216
|
-
</Box>
|
|
217
|
-
);
|
|
207
|
+
return <Box>Iteration #{this.state.i}</Box>;
|
|
218
208
|
}
|
|
219
209
|
|
|
220
210
|
componentDidMount() {
|
|
@@ -230,7 +220,7 @@ class Counter extends Component {
|
|
|
230
220
|
}
|
|
231
221
|
}
|
|
232
222
|
|
|
233
|
-
const app = render(<Counter/>);
|
|
223
|
+
const app = render(<Counter />);
|
|
234
224
|
|
|
235
225
|
setTimeout(() => {
|
|
236
226
|
// Enough counting
|
|
@@ -254,12 +244,12 @@ Replace previous root node with a new one or update props of the current root no
|
|
|
254
244
|
|
|
255
245
|
```jsx
|
|
256
246
|
// Update props of the root node
|
|
257
|
-
const {rerender} = render(<Counter count={1}/>);
|
|
258
|
-
rerender(<Counter count={2}/>);
|
|
247
|
+
const { rerender } = render(<Counter count={1} />);
|
|
248
|
+
rerender(<Counter count={2} />);
|
|
259
249
|
|
|
260
250
|
// Replace root node
|
|
261
|
-
const {rerender} = render(<OldCounter/>);
|
|
262
|
-
rerender(<NewCounter/>);
|
|
251
|
+
const { rerender } = render(<OldCounter />);
|
|
252
|
+
rerender(<NewCounter />);
|
|
263
253
|
```
|
|
264
254
|
|
|
265
255
|
##### unmount
|
|
@@ -267,7 +257,7 @@ rerender(<NewCounter/>);
|
|
|
267
257
|
Manually unmount the whole Ink app.
|
|
268
258
|
|
|
269
259
|
```jsx
|
|
270
|
-
const {unmount} = render(<MyApp/>);
|
|
260
|
+
const { unmount } = render(<MyApp />);
|
|
271
261
|
unmount();
|
|
272
262
|
```
|
|
273
263
|
|
|
@@ -276,7 +266,7 @@ unmount();
|
|
|
276
266
|
Returns a promise, which resolves when app is unmounted.
|
|
277
267
|
|
|
278
268
|
```jsx
|
|
279
|
-
const {unmount, waitUntilExit} = render(<MyApp/>);
|
|
269
|
+
const { unmount, waitUntilExit } = render(<MyApp />);
|
|
280
270
|
|
|
281
271
|
setTimeout(unmount, 1000);
|
|
282
272
|
|
|
@@ -290,7 +280,6 @@ It's important to remember that each element is a Flexbox container.
|
|
|
290
280
|
Think of it as if each `<div>` in the browser had `display: flex`.
|
|
291
281
|
See `<Box>` built-in component below for documentation on how to use Flexbox layouts in Ink.
|
|
292
282
|
|
|
293
|
-
|
|
294
283
|
### Built-in Components
|
|
295
284
|
|
|
296
285
|
#### `<Box>`
|
|
@@ -300,7 +289,7 @@ See `<Box>` built-in component below for documentation on how to use Flexbox lay
|
|
|
300
289
|
Import:
|
|
301
290
|
|
|
302
291
|
```js
|
|
303
|
-
import {Box} from
|
|
292
|
+
import { Box } from "ink";
|
|
304
293
|
```
|
|
305
294
|
|
|
306
295
|
##### Dimensions
|
|
@@ -317,8 +306,7 @@ Width of the element in spaces. You can also set it in percent, which will calcu
|
|
|
317
306
|
|
|
318
307
|
```jsx
|
|
319
308
|
<Box width={10}>
|
|
320
|
-
<Box width="50%">X</Box>
|
|
321
|
-
Y
|
|
309
|
+
<Box width="50%">X</Box>Y
|
|
322
310
|
</Box> //=> 'X Y'
|
|
323
311
|
```
|
|
324
312
|
|
|
@@ -334,8 +322,7 @@ Height of the element in lines (rows). You can also set it in percent, which wil
|
|
|
334
322
|
|
|
335
323
|
```jsx
|
|
336
324
|
<Box height={6} flexDirection="column">
|
|
337
|
-
<Box height="50%">X</Box>
|
|
338
|
-
Y
|
|
325
|
+
<Box height="50%">X</Box>Y
|
|
339
326
|
</Box> //=> 'X\n\n\nY\n\n'
|
|
340
327
|
```
|
|
341
328
|
|
|
@@ -360,7 +347,7 @@ Values: `wrap` `truncate` `truncate-start` `truncate-middle` `truncate-end`
|
|
|
360
347
|
|
|
361
348
|
This property tells Ink to wrap or truncate text content of `<Box>` if its width is larger than container. If `wrap` is passed, Ink will wrap text and split it into multiple lines. If `truncate-*` is passed, Ink will truncate text instead, which will result in one line of text with the rest cut off.
|
|
362
349
|
|
|
363
|
-
|
|
350
|
+
_Note:_ Ink doesn't wrap text by default.
|
|
364
351
|
|
|
365
352
|
```jsx
|
|
366
353
|
<Box textWrap="wrap">Hello World</Box>
|
|
@@ -483,9 +470,7 @@ See [flex-grow](https://css-tricks.com/almanac/properties/f/flex-grow/).
|
|
|
483
470
|
```jsx
|
|
484
471
|
<Box>
|
|
485
472
|
Label:
|
|
486
|
-
<Box flexGrow={1}>
|
|
487
|
-
Fills all remaining space
|
|
488
|
-
</Box>
|
|
473
|
+
<Box flexGrow={1}>Fills all remaining space</Box>
|
|
489
474
|
</Box>
|
|
490
475
|
```
|
|
491
476
|
|
|
@@ -501,9 +486,7 @@ See [flex-shrink](https://css-tricks.com/almanac/properties/f/flex-shrink/).
|
|
|
501
486
|
<Box flexShrink={2} width={10}>
|
|
502
487
|
Will be 1/4
|
|
503
488
|
</Box>
|
|
504
|
-
<Box width={10}>
|
|
505
|
-
Will be 3/4
|
|
506
|
-
</Box>
|
|
489
|
+
<Box width={10}>Will be 3/4</Box>
|
|
507
490
|
</Box>
|
|
508
491
|
```
|
|
509
492
|
|
|
@@ -515,15 +498,13 @@ See [flex-basis](https://css-tricks.com/almanac/properties/f/flex-basis/).
|
|
|
515
498
|
|
|
516
499
|
```jsx
|
|
517
500
|
<Box width={6}>
|
|
518
|
-
<Box flexBasis={3}>X</Box>
|
|
519
|
-
Y
|
|
501
|
+
<Box flexBasis={3}>X</Box>Y
|
|
520
502
|
</Box> //=> 'X Y'
|
|
521
503
|
```
|
|
522
504
|
|
|
523
505
|
```jsx
|
|
524
506
|
<Box width={6}>
|
|
525
|
-
<Box flexBasis="50%">X</Box>
|
|
526
|
-
Y
|
|
507
|
+
<Box flexBasis="50%">X</Box>Y
|
|
527
508
|
</Box> //=> 'X Y'
|
|
528
509
|
```
|
|
529
510
|
|
|
@@ -631,7 +612,6 @@ See [justify-content](https://css-tricks.com/almanac/properties/f/justify-conten
|
|
|
631
612
|
// [ X Y ]
|
|
632
613
|
```
|
|
633
614
|
|
|
634
|
-
|
|
635
615
|
#### `<Color>`
|
|
636
616
|
|
|
637
617
|
The `<Color>` component is a simple wrapper around [the `chalk` API](https://github.com/chalk/chalk#api).
|
|
@@ -640,7 +620,7 @@ It supports all of the chalk's methods as `props`.
|
|
|
640
620
|
Import:
|
|
641
621
|
|
|
642
622
|
```js
|
|
643
|
-
import {Color} from
|
|
623
|
+
import { Color } from "ink";
|
|
644
624
|
```
|
|
645
625
|
|
|
646
626
|
Usage:
|
|
@@ -666,7 +646,7 @@ This component can change the style of the text, make it bold, underline, italic
|
|
|
666
646
|
Import:
|
|
667
647
|
|
|
668
648
|
```js
|
|
669
|
-
import {Text} from
|
|
649
|
+
import { Text } from "ink";
|
|
670
650
|
```
|
|
671
651
|
|
|
672
652
|
##### bold
|
|
@@ -717,12 +697,12 @@ Jest continuously writes the list of completed tests to the output, while updati
|
|
|
717
697
|
<>
|
|
718
698
|
<Static>
|
|
719
699
|
{tests.map(test => (
|
|
720
|
-
<Test key={test.id} title={test.title}/>
|
|
700
|
+
<Test key={test.id} title={test.title} />
|
|
721
701
|
))}
|
|
722
702
|
</Static>
|
|
723
703
|
|
|
724
704
|
<Box marginTop={1}>
|
|
725
|
-
<TestResults passed={results.passed} failed={results.failed}/>
|
|
705
|
+
<TestResults passed={results.passed} failed={results.failed} />
|
|
726
706
|
</Box>
|
|
727
707
|
</>
|
|
728
708
|
```
|
|
@@ -736,7 +716,7 @@ See [examples/jest](examples/jest/jest.js) for a basic implementation of Jest's
|
|
|
736
716
|
Import:
|
|
737
717
|
|
|
738
718
|
```js
|
|
739
|
-
import {AppContext} from
|
|
719
|
+
import { AppContext } from "ink";
|
|
740
720
|
```
|
|
741
721
|
|
|
742
722
|
##### exit
|
|
@@ -765,7 +745,7 @@ If `exit` is called with an Error, `waitUntilExit` will reject with that error.
|
|
|
765
745
|
Import:
|
|
766
746
|
|
|
767
747
|
```js
|
|
768
|
-
import {StdinContext} from
|
|
748
|
+
import { StdinContext } from "ink";
|
|
769
749
|
```
|
|
770
750
|
|
|
771
751
|
##### stdin
|
|
@@ -780,9 +760,7 @@ Usage:
|
|
|
780
760
|
|
|
781
761
|
```jsx
|
|
782
762
|
<StdinContext.Consumer>
|
|
783
|
-
{({ stdin }) =>
|
|
784
|
-
<MyComponent stdin={stdin}/>
|
|
785
|
-
)}
|
|
763
|
+
{({ stdin }) => <MyComponent stdin={stdin} />}
|
|
786
764
|
</StdinContext.Consumer>
|
|
787
765
|
```
|
|
788
766
|
|
|
@@ -797,9 +775,13 @@ Usage:
|
|
|
797
775
|
|
|
798
776
|
```jsx
|
|
799
777
|
<StdinContext.Consumer>
|
|
800
|
-
{({ isRawModeSupported, setRawMode, stdin }) =>
|
|
801
|
-
isRawModeSupported ?
|
|
802
|
-
|
|
778
|
+
{({ isRawModeSupported, setRawMode, stdin }) =>
|
|
779
|
+
isRawModeSupported ? (
|
|
780
|
+
<MyInputComponent setRawMode={setRawMode} stdin={stdin} />
|
|
781
|
+
) : (
|
|
782
|
+
<MyComponentThatDoesntUseInput />
|
|
783
|
+
)
|
|
784
|
+
}
|
|
803
785
|
</StdinContext.Consumer>
|
|
804
786
|
```
|
|
805
787
|
|
|
@@ -808,7 +790,7 @@ Usage:
|
|
|
808
790
|
Type: `function`<br>
|
|
809
791
|
|
|
810
792
|
See [`setRawMode`](https://nodejs.org/api/tty.html#tty_readstream_setrawmode_mode).
|
|
811
|
-
Ink exposes this function via own `<StdinContext>` to be able to handle <kbd>Ctrl</kbd>+<kbd>C</kbd>, that's why you should use Ink's `setRawMode` instead of `process.stdin.setRawMode`.
|
|
793
|
+
Ink exposes this function via own `<StdinContext>` to be able to handle <kbd>Ctrl</kbd>+<kbd>C</kbd>, that's why you should use Ink's `setRawMode` instead of `process.stdin.setRawMode`.
|
|
812
794
|
|
|
813
795
|
**Warning:** This function will throw unless the current `stdin` supports `setRawMode`. Use [`isRawModeSupported`](#israwmodesupported) to detect `setRawMode` support.
|
|
814
796
|
|
|
@@ -816,9 +798,7 @@ Usage:
|
|
|
816
798
|
|
|
817
799
|
```jsx
|
|
818
800
|
<StdinContext.Consumer>
|
|
819
|
-
{({ setRawMode }) =>
|
|
820
|
-
<MyComponent setRawMode={setRawMode}/>
|
|
821
|
-
)}
|
|
801
|
+
{({ setRawMode }) => <MyComponent setRawMode={setRawMode} />}
|
|
822
802
|
</StdinContext.Consumer>
|
|
823
803
|
```
|
|
824
804
|
|
|
@@ -829,7 +809,7 @@ Usage:
|
|
|
829
809
|
Import:
|
|
830
810
|
|
|
831
811
|
```js
|
|
832
|
-
import {StdoutContext} from
|
|
812
|
+
import { StdoutContext } from "ink";
|
|
833
813
|
```
|
|
834
814
|
|
|
835
815
|
##### stdout
|
|
@@ -841,9 +821,7 @@ Usage:
|
|
|
841
821
|
|
|
842
822
|
```jsx
|
|
843
823
|
<StdoutContext.Consumer>
|
|
844
|
-
{({ stdout }) =>
|
|
845
|
-
<MyComponent stdout={stdout}/>
|
|
846
|
-
)}
|
|
824
|
+
{({ stdout }) => <MyComponent stdout={stdout} />}
|
|
847
825
|
</StdoutContext.Consumer>
|
|
848
826
|
```
|
|
849
827
|
|
|
@@ -890,8 +868,11 @@ Type: `object`
|
|
|
890
868
|
Handy information about a key that was pressed.
|
|
891
869
|
|
|
892
870
|
##### key.leftArrow
|
|
871
|
+
|
|
893
872
|
##### key.rightArrow
|
|
873
|
+
|
|
894
874
|
##### key.upArrow
|
|
875
|
+
|
|
895
876
|
##### key.downArrow
|
|
896
877
|
|
|
897
878
|
Type: `boolean`<br>
|
|
@@ -928,40 +909,76 @@ Default: `false`
|
|
|
928
909
|
|
|
929
910
|
[Meta key](https://en.wikipedia.org/wiki/Meta_key) was pressed.
|
|
930
911
|
|
|
912
|
+
### useApp
|
|
913
|
+
|
|
914
|
+
`useApp` is a React hook, which exposes props of [`AppContext`](#appcontext).
|
|
915
|
+
|
|
916
|
+
```js
|
|
917
|
+
import { useApp } from "ink";
|
|
918
|
+
|
|
919
|
+
const MyApp = () => {
|
|
920
|
+
const { exit } = useApp();
|
|
921
|
+
};
|
|
922
|
+
```
|
|
923
|
+
|
|
924
|
+
It's equivalent to consuming `AppContext` props via `AppContext.Consumer`:
|
|
925
|
+
|
|
926
|
+
```jsx
|
|
927
|
+
<AppContext.Consumer>
|
|
928
|
+
{({ exit }) => {
|
|
929
|
+
// …
|
|
930
|
+
}}
|
|
931
|
+
</AppContext.Consumer>
|
|
932
|
+
```
|
|
933
|
+
|
|
934
|
+
### useStdin
|
|
935
|
+
|
|
936
|
+
`useStdin` is a React hook, which exposes props of [`StdinContext`](#stdincontext).
|
|
937
|
+
Similar to `useApp`, it's equivalent to consuming `StdinContext` directly.
|
|
938
|
+
|
|
939
|
+
### useStdout
|
|
940
|
+
|
|
941
|
+
`useStdout` is a React hook, which exposes props of [`StdoutContext`](#stdoutcontext).
|
|
942
|
+
Similar to `useApp`, it's equivalent to consuming `StdoutContext` directly.
|
|
943
|
+
|
|
944
|
+
## Useful Hooks
|
|
945
|
+
|
|
946
|
+
- [ink-use-stdout-dimensions](https://github.com/cameronhunter/ink-monorepo/tree/master/packages/ink-use-stdout-dimensions) - Subscribe to stdout dimensions.
|
|
931
947
|
|
|
932
948
|
## Useful Components
|
|
933
949
|
|
|
934
|
-
-
|
|
935
|
-
-
|
|
936
|
-
-
|
|
937
|
-
-
|
|
938
|
-
-
|
|
939
|
-
-
|
|
940
|
-
-
|
|
941
|
-
-
|
|
942
|
-
-
|
|
943
|
-
-
|
|
944
|
-
-
|
|
945
|
-
-
|
|
946
|
-
-
|
|
947
|
-
-
|
|
950
|
+
- [ink-text-input](https://github.com/vadimdemedes/ink-text-input) - Text input.
|
|
951
|
+
- [ink-spinner](https://github.com/vadimdemedes/ink-spinner) - Spinner.
|
|
952
|
+
- [ink-select-input](https://github.com/vadimdemedes/ink-select-input) - Select (dropdown) input.
|
|
953
|
+
- [ink-link](https://github.com/sindresorhus/ink-link) - Link component.
|
|
954
|
+
- [ink-box](https://github.com/sindresorhus/ink-box) - Styled box component.
|
|
955
|
+
- [ink-gradient](https://github.com/sindresorhus/ink-gradient) - Gradient color component.
|
|
956
|
+
- [ink-big-text](https://github.com/sindresorhus/ink-big-text) - Awesome text component.
|
|
957
|
+
- [ink-image](https://github.com/kevva/ink-image) - Display images inside the terminal.
|
|
958
|
+
- [ink-tab](https://github.com/jdeniau/ink-tab) - Tab component.
|
|
959
|
+
- [ink-color-pipe](https://github.com/LitoMore/ink-color-pipe) - Create color text with simpler style strings in Ink.
|
|
960
|
+
- [ink-multi-select](https://github.com/karaggeorge/ink-multi-select) - Select one or more values from a list
|
|
961
|
+
- [ink-divider](https://github.com/JureSotosek/ink-divider) - A divider component.
|
|
962
|
+
- [ink-progress-bar](https://github.com/brigand/ink-progress-bar) - Configurable component for rendering progress bars.
|
|
963
|
+
- [ink-table](https://github.com/maticzav/ink-table) - Table component.
|
|
964
|
+
- [ink-ascii](https://github.com/hexrcs/ink-ascii) - Awesome text component with more font choices, based on Figlet.
|
|
965
|
+
- [ink-markdown](https://github.com/cameronhunter/ink-markdown) - Render syntax highlighted Markdown.
|
|
948
966
|
|
|
949
967
|
### Incompatible components
|
|
950
968
|
|
|
951
969
|
These are components that haven't migrated to Ink 2 yet:
|
|
952
970
|
|
|
953
|
-
-
|
|
954
|
-
-
|
|
955
|
-
-
|
|
956
|
-
-
|
|
957
|
-
-
|
|
958
|
-
-
|
|
959
|
-
-
|
|
960
|
-
-
|
|
961
|
-
-
|
|
962
|
-
-
|
|
963
|
-
-
|
|
964
|
-
|
|
971
|
+
- [ink-console](https://github.com/ForbesLindesay/ink-console) - Render output from `console[method]` calls in a scrollable panel.
|
|
972
|
+
- [ink-confirm-input](https://github.com/kevva/ink-confirm-input) - Yes/No confirmation input.
|
|
973
|
+
- [ink-checkbox-list](https://github.com/MaxMEllon/ink-checkbox-list) - Checkbox.
|
|
974
|
+
- [ink-quicksearch](https://github.com/aicioara/ink-quicksearch) - Select Component with fast quicksearch-like navigation
|
|
975
|
+
- [ink-autocomplete](https://github.com/maticzav/ink-autocomplete) - Autocomplete.
|
|
976
|
+
- [ink-broadcast](https://github.com/jimmed/ink-broadcast) - Implementation of react-broadcast for Ink.
|
|
977
|
+
- [ink-router](https://github.com/jimmed/ink-router) - Implementation of react-router for Ink.
|
|
978
|
+
- [ink-select](https://github.com/karaggeorge/ink-select) - Select component.
|
|
979
|
+
- [ink-scrollbar](https://github.com/karaggeorge/ink-scrollbar) - Scrollbar component.
|
|
980
|
+
- [ink-text-animation](https://github.com/yardnsm/ink-text-animation) - Text animation component.
|
|
981
|
+
- [ink-figlet](https://github.com/KimotoYanke/ink-figlet) - Large text component with Figlet fonts.
|
|
965
982
|
|
|
966
983
|
## Testing
|
|
967
984
|
|
|
@@ -969,34 +986,51 @@ Ink components are simple to test with [ink-testing-library](https://github.com/
|
|
|
969
986
|
Here's a simple example that checks how component is rendered:
|
|
970
987
|
|
|
971
988
|
```jsx
|
|
972
|
-
import React from
|
|
973
|
-
import {Text} from
|
|
974
|
-
import {render} from
|
|
989
|
+
import React from "react";
|
|
990
|
+
import { Text } from "ink";
|
|
991
|
+
import { render } from "ink-testing-library";
|
|
975
992
|
|
|
976
993
|
const Test = () => <Text>Hello World</Text>;
|
|
977
|
-
const {lastFrame} = render(<Test/>);
|
|
994
|
+
const { lastFrame } = render(<Test />);
|
|
978
995
|
|
|
979
|
-
lastFrame() ===
|
|
996
|
+
lastFrame() === "Hello World"; //=> true
|
|
980
997
|
```
|
|
981
998
|
|
|
982
999
|
Visit [ink-testing-library](https://github.com/vadimdemedes/ink-testing-library) for more examples and full documentation.
|
|
983
1000
|
|
|
984
1001
|
## Experimental Mode
|
|
985
1002
|
|
|
986
|
-
Ink has experimental mode, which
|
|
1003
|
+
Ink has experimental mode, which includes stable new features behind a flag.
|
|
1004
|
+
They're exposed behind a flag, because I want to be extra sure that it doesn't introduce regressions before shipping this new code for everyone and making it a default.
|
|
1005
|
+
|
|
987
1006
|
Instead of shipping it under `next` tag or something similar, Ink ships it as part of a regular release.
|
|
988
1007
|
It can be enabled simply by passing `experimental` parameter to `render()` function:
|
|
989
1008
|
|
|
990
1009
|
```jsx
|
|
991
|
-
render(<App/>, {experimental: true});
|
|
1010
|
+
render(<App />, { experimental: true });
|
|
992
1011
|
```
|
|
993
1012
|
|
|
994
|
-
Experimental mode actually includes stable features, but I want to be extra sure that it doesn't introduce regressions before shipping this new code for everyone and making it a default.
|
|
995
|
-
|
|
996
1013
|
Feel free to use experimental mode in development and I would appreciate if you reported any regressions you might see.
|
|
997
1014
|
|
|
1015
|
+
### More efficient reconciler and renderer
|
|
1016
|
+
|
|
1017
|
+
Experimental mode enables a new reconciler and renderer, which should significantly improve the rendering performance of your Ink apps.
|
|
1018
|
+
Ink rebuilds the entire layout and output on every update, which can be taxing if there's a high frequency of updates.
|
|
1019
|
+
Experimental mode ensures only necessary parts of the layout are updated and limits the number of renders to 60 frames per second.
|
|
1020
|
+
|
|
1021
|
+
### Automatic handling of oversized output
|
|
1022
|
+
|
|
1023
|
+
Unfortunately, terminals can't rerender output that is taller than terminal window.
|
|
1024
|
+
So if your app output has a height of 60 rows, but user resized terminal window to 50 rows, first 10 rows won't be rerendered, because they're out of viewport.
|
|
1025
|
+
|
|
1026
|
+
Experimental mode adopts the same workaround that Jest does, it erases the entire terminal content if output is taller than terminal window. It comes with tradeoffs though:
|
|
1027
|
+
|
|
1028
|
+
- Output can become janky, since erasing terminal is not a "cheap" operation.
|
|
1029
|
+
- Entire scrollback history in that terminal session will be lost.
|
|
1030
|
+
|
|
1031
|
+
It is, however, the only way known now to handle this.
|
|
998
1032
|
|
|
999
1033
|
## Maintainers
|
|
1000
1034
|
|
|
1001
|
-
-
|
|
1002
|
-
-
|
|
1035
|
+
- [Vadim Demedes](https://github.com/vadimdemedes)
|
|
1036
|
+
- [Sindre Sorhus](https://github.com/sindresorhus)
|