Comparing version 2.0.0-3 to 2.0.0-4
@@ -39,2 +39,4 @@ "use strict"; | ||
element.unstable__transformChildren = value; // eslint-disable-line camelcase | ||
} else if (key === 'static') { | ||
element.static = true; | ||
} else { | ||
@@ -48,2 +50,14 @@ element.setAttribute(key, value); | ||
createTextInstance: text => document.createTextNode(text), | ||
resetTextContent: element => { | ||
if (element.textContent) { | ||
element.textContent = ''; | ||
} | ||
if (element.childNodes.length > 0) { | ||
for (const childNode of element.childNodes) { | ||
childNode.yogaNode.free(); | ||
element.removeChild(childNode); | ||
} | ||
} | ||
}, | ||
getPublicInstance: instance => instance, | ||
@@ -74,2 +88,4 @@ appendInitialChild: (parent, child) => parent.appendChild(child), | ||
element.unstable__transformChildren = value; // eslint-disable-line camelcase | ||
} else if (key === 'static') { | ||
element.static = true; | ||
} else { | ||
@@ -76,0 +92,0 @@ element.setAttribute(key, value); |
@@ -12,2 +12,4 @@ "use strict"; | ||
var _undom = _interopRequireDefault(require("undom")); | ||
var _applyStyles = _interopRequireDefault(require("./apply-styles")); | ||
@@ -17,2 +19,4 @@ | ||
var _cloneElement = _interopRequireDefault(require("./clone-element")); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
@@ -22,3 +26,4 @@ | ||
config, | ||
terminalWidth | ||
terminalWidth, | ||
skipStaticElements | ||
}) => { | ||
@@ -34,3 +39,7 @@ const node = _yogaLayoutPrebuilt.default.Node.create(config); | ||
if (element.childNodes.length > 0) { | ||
for (const [index, childNode] of Object.entries(element.childNodes)) { | ||
const childNodes = element.childNodes.filter(childNode => { | ||
return skipStaticElements ? !childNode.static : true; | ||
}); | ||
for (const [index, childNode] of Object.entries(childNodes)) { | ||
const { | ||
@@ -81,3 +90,7 @@ yogaNode | ||
if (element.childNodes.length > 0) { | ||
for (const [index, childNode] of Object.entries(element.childNodes)) { | ||
const childNodes = element.childNodes.filter(childNode => { | ||
return skipStaticElements ? !childNode.static : true; | ||
}); | ||
for (const [index, childNode] of Object.entries(childNodes)) { | ||
const { | ||
@@ -97,4 +110,9 @@ yogaNode | ||
const renderElement = (element, output, offsetX = 0, offsetY = 0, { | ||
transformers | ||
transformers, | ||
skipStaticElements | ||
}) => { | ||
if (element.static && skipStaticElements) { | ||
return; | ||
} | ||
const node = element.yogaNode; | ||
@@ -112,3 +130,4 @@ const x = offsetX + node.getComputedLeft(); | ||
output.write(x, y, element.textContent, { | ||
transformers: newTransformers | ||
transformers: newTransformers, | ||
skipStaticElements | ||
}); | ||
@@ -121,3 +140,4 @@ return; | ||
output.write(x, y, element.nodeValue, { | ||
transformers: newTransformers | ||
transformers: newTransformers, | ||
skipStaticElements | ||
}); | ||
@@ -130,3 +150,4 @@ return; | ||
renderElement(childElement, output, x, y, { | ||
transformers: newTransformers | ||
transformers: newTransformers, | ||
skipStaticElements | ||
}); | ||
@@ -136,2 +157,18 @@ } | ||
const getStaticElements = element => { | ||
const staticElements = []; | ||
for (const childNode of element.childNodes) { | ||
if (childNode.static) { | ||
staticElements.push(childNode); | ||
} | ||
if (childNode.childNodes.length > 0) { | ||
staticElements.push(...getStaticElements(childNode)); | ||
} | ||
} | ||
return staticElements; | ||
}; | ||
var _default = ({ | ||
@@ -144,2 +181,3 @@ terminalWidth | ||
let lastNode; | ||
let lastStaticNode; | ||
return element => { | ||
@@ -150,5 +188,38 @@ if (lastNode) { | ||
if (lastStaticNode) { | ||
lastStaticNode.freeRecursive(); | ||
} | ||
const staticElements = getStaticElements(element); | ||
if (staticElements.length > 1) { | ||
console.error('Warning: There can only be one <Static> component'); | ||
} | ||
let staticOutput; | ||
if (staticElements.length === 1) { | ||
const document = (0, _undom.default)(); | ||
document.body.appendChild((0, _cloneElement.default)(document, staticElements[0])); | ||
const staticNode = buildElement(document.body, { | ||
config, | ||
terminalWidth, | ||
skipStaticElements: false | ||
}).yogaNode; | ||
staticNode.calculateLayout(_yogaLayoutPrebuilt.default.UNDEFINED, _yogaLayoutPrebuilt.default.UNDEFINED, _yogaLayoutPrebuilt.default.DIRECTION_LTR); // Save current node tree to free up memory later | ||
lastStaticNode = staticNode; | ||
staticOutput = new _output.default({ | ||
height: staticNode.getComputedHeight() | ||
}); | ||
renderElement(document.body, staticOutput, 0, 0, { | ||
transformers: [], | ||
skipStaticElements: false | ||
}); | ||
} | ||
const node = buildElement(element, { | ||
config, | ||
terminalWidth | ||
terminalWidth, | ||
skipStaticElements: true | ||
}).yogaNode; | ||
@@ -162,5 +233,9 @@ node.calculateLayout(_yogaLayoutPrebuilt.default.UNDEFINED, _yogaLayoutPrebuilt.default.UNDEFINED, _yogaLayoutPrebuilt.default.DIRECTION_LTR); // Save current node tree to free up memory later | ||
renderElement(element, output, 0, 0, { | ||
transformers: [] | ||
transformers: [], | ||
skipStaticElements: true | ||
}); | ||
return output.get(); | ||
return { | ||
output: output.get(), | ||
staticOutput: staticOutput ? staticOutput.get() : undefined | ||
}; | ||
}; | ||
@@ -167,0 +242,0 @@ }; |
@@ -6,2 +6,14 @@ "use strict"; | ||
}); | ||
Object.defineProperty(exports, "render", { | ||
enumerable: true, | ||
get: function () { | ||
return _render.default; | ||
} | ||
}); | ||
Object.defineProperty(exports, "renderToString", { | ||
enumerable: true, | ||
get: function () { | ||
return _renderToString.default; | ||
} | ||
}); | ||
Object.defineProperty(exports, "Box", { | ||
@@ -37,18 +49,13 @@ enumerable: true, | ||
}); | ||
exports.render = void 0; | ||
Object.defineProperty(exports, "Static", { | ||
enumerable: true, | ||
get: function () { | ||
return _Static.default; | ||
} | ||
}); | ||
var _react = _interopRequireDefault(require("react")); | ||
var _render = _interopRequireDefault(require("./render")); | ||
var _undom = _interopRequireDefault(require("undom")); | ||
var _renderToString = _interopRequireDefault(require("./render-to-string")); | ||
var _logUpdate = _interopRequireDefault(require("log-update")); | ||
var _debounceFn = _interopRequireDefault(require("debounce-fn")); | ||
var _createReconciler = _interopRequireDefault(require("./create-reconciler")); | ||
var _createRenderer = _interopRequireDefault(require("./create-renderer")); | ||
var _App = _interopRequireDefault(require("./components/App")); | ||
var _Box = _interopRequireDefault(require("./components/Box")); | ||
@@ -64,71 +71,4 @@ | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
var _Static = _interopRequireDefault(require("./components/Static")); | ||
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; } | ||
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; } | ||
const render = (node, options = {}) => { | ||
if (typeof options.write === 'function') { | ||
options = { | ||
stdout: options, | ||
stdin: process.stdin | ||
}; | ||
} | ||
options = _objectSpread({ | ||
stdout: process.stdout, | ||
stdin: process.stdin, | ||
debug: false | ||
}, options); | ||
const document = (0, _undom.default)(); | ||
const render = (0, _createRenderer.default)({ | ||
terminalWidth: options.stdout.columns | ||
}); | ||
const log = _logUpdate.default.create(options.stdout); // Ignore last render after unmounting a tree to prevent empty output before exit | ||
let ignoreRender = false; | ||
const onRender = () => { | ||
if (ignoreRender) { | ||
return; | ||
} | ||
const output = render(document.body); | ||
if (options.debug) { | ||
options.stdout.write(output); | ||
return; | ||
} | ||
log(output); | ||
}; | ||
const debouncedRender = options.debug ? onRender : (0, _debounceFn.default)(onRender); | ||
const reconciler = (0, _createReconciler.default)(document, debouncedRender); | ||
if (!options.stdout._inkContainer) { | ||
options.stdout._inkContainer = reconciler.createContainer(document.body, false); | ||
} | ||
const tree = _react.default.createElement(_App.default, { | ||
stdin: options.stdin, | ||
stdout: options.stdout | ||
}, node); | ||
reconciler.updateContainer(tree, options.stdout._inkContainer); | ||
return () => { | ||
if (typeof debouncedRender.cancel === 'function') { | ||
debouncedRender.cancel(); | ||
onRender(); | ||
log.done(); | ||
} | ||
ignoreRender = true; | ||
reconciler.updateContainer(null, options.stdout._inkContainer); | ||
}; | ||
}; | ||
exports.render = render; | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } |
{ | ||
"name": "ink", | ||
"version": "2.0.0-3", | ||
"version": "2.0.0-4", | ||
"description": "React for CLI", | ||
@@ -5,0 +5,0 @@ "license": "MIT", |
@@ -189,3 +189,3 @@ <h1 align="center"> | ||
<Box> | ||
Iteration #${this.state.i} | ||
Iteration #{this.state.i} | ||
</Box> | ||
@@ -197,4 +197,4 @@ ); | ||
this.timer = setInterval(() => { | ||
this.setState({ | ||
i: this.state.i + 1 | ||
this.setState(prevState => ({ | ||
i: prevState.i + 1 | ||
}); | ||
@@ -234,3 +234,3 @@ }, 100); | ||
#### <Box> | ||
#### <Box> | ||
@@ -477,3 +477,3 @@ `<Box>` it's an essential Ink component to build your layout. It's like a `<div>` in a browser. | ||
#### <Color> | ||
#### <Color> | ||
@@ -505,3 +505,3 @@ The `<Color>` compoment is a simple wrapper around [the `chalk` API](https://github.com/chalk/chalk#api). | ||
#### <Text> | ||
#### <Text> | ||
@@ -545,4 +545,31 @@ This component can change the style of the text, make it bold, underline, italic or strikethrough. | ||
#### <StdinContext> | ||
#### <Static> | ||
`<Static>` component allows permanently rendering output to stdout and preserving it across renders. | ||
Components passed to `<Static>` as children will be written to stdout only once and will never be rerendered. | ||
`<Static>` output comes first, before any other output from your components, no matter where it is in the tree. | ||
In order for this mechanism to work properly, at most one `<Static>` component must be present in your node tree and components that were rendered must never update their output. Ink will detect new children appended to `<Static>` and render them to stdout. | ||
Example use case for this component is Jest's output: | ||
![](https://jestjs.io/img/content/feature-fast.png) | ||
Jest continuosuly writes the list of completed tests to the output, while updating test results at the bottom of the output in real-time. Here's how this user interface could be implemented with Ink: | ||
```jsx | ||
<Fragment> | ||
<Static> | ||
{tests.map(test => ( | ||
<Test key={test.id} title={test.title}/> | ||
))} | ||
</Static> | ||
<Box marginTop={1}> | ||
<TestResults passed={results.passed} failed={results.failed}/> | ||
</Box> | ||
</Fragment> | ||
``` | ||
#### <StdinContext> | ||
`<StdinContext>` is a [React context](https://reactjs.org/docs/context.html#reactcreatecontext), which exposes several props. | ||
@@ -591,3 +618,3 @@ | ||
#### <StdoutContext> | ||
#### <StdoutContext> | ||
@@ -594,0 +621,0 @@ `<StdoutContext>` is a [React context](https://reactjs.org/docs/context.html#reactcreatecontext), which exposes stdout stream, where Ink renders your app. |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
54254
21
949
640