Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

ink

Package Overview
Dependencies
Maintainers
2
Versions
76
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

ink - npm Package Compare versions

Comparing version 2.0.6 to 2.1.0

build/calculate-wrapped-text.js

27

build/apply-styles.js

@@ -12,2 +12,6 @@ "use strict";

const hasOwnProperty = (obj, prop) => {
return {}.hasOwnProperty.call(obj, prop);
};
const applyMarginStyles = (node, style) => {

@@ -110,2 +114,6 @@ if (style.margin) {

if (hasOwnProperty(style, 'flexBasis')) {
node.setFlexBasis(style.flexBasis);
}
if (style.alignItems) {

@@ -148,2 +156,20 @@ if (style.alignItems === 'flex-start') {

const applyDimensionStyles = (node, style) => {
if (hasOwnProperty(style, 'width')) {
node.setWidth(style.width);
}
if (hasOwnProperty(style, 'height')) {
node.setHeight(style.height);
}
if (hasOwnProperty(style, 'minWidth')) {
node.setMinWidth(style.minWidth);
}
if (hasOwnProperty(style, 'minHeight')) {
node.setMinHeight(style.minHeight);
}
};
var _default = (node, style = {}) => {

@@ -153,4 +179,5 @@ applyMarginStyles(node, style);

applyFlexStyles(node, style);
applyDimensionStyles(node, style);
};
exports.default = _default;

39

build/build-layout.js

@@ -10,18 +10,9 @@ "use strict";

var _widestLine = _interopRequireDefault(require("widest-line"));
var _applyStyles = _interopRequireDefault(require("./apply-styles"));
var _measureText = _interopRequireDefault(require("./measure-text"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
const measureText = text => {
const width = (0, _widestLine.default)(text);
const height = text.split('\n').length;
return {
width,
height
};
}; // Traverse the node tree, create Yoga nodes and assign styles to each Yoga node
// Traverse the node tree, create Yoga nodes and assign styles to each Yoga node
const buildLayout = (node, options) => {

@@ -60,32 +51,12 @@ const {

if (node.textContent) {
if (node.textContent || node.nodeValue) {
const {
width,
height
} = measureText(node.textContent);
} = (0, _measureText.default)(node.textContent || node.nodeValue);
yogaNode.setWidth(style.width || width);
yogaNode.setHeight(style.height || height);
return node;
} // Text node
if (node.nodeValue) {
const {
width,
height
} = measureText(node.nodeValue);
yogaNode.setWidth(width);
yogaNode.setHeight(height);
return node;
} // Nodes with other nodes as children
if (style.width) {
yogaNode.setWidth(style.width);
}
if (style.height) {
yogaNode.setHeight(style.height);
}
if (Array.isArray(node.childNodes) && node.childNodes.length > 0) {

@@ -92,0 +63,0 @@ const childNodes = node.childNodes.filter(childNode => {

@@ -72,5 +72,5 @@ "use strict";

_defineProperty(this, "handleExit", () => {
_defineProperty(this, "handleExit", error => {
this.handleSetRawMode(false);
this.props.onExit();
this.props.onExit(error);
});

@@ -108,2 +108,6 @@

componentDidCatch(error) {
this.handleExit(error);
}
}

@@ -110,0 +114,0 @@

@@ -66,9 +66,13 @@ "use strict";

paddingRight: _propTypes.default.number,
width: _propTypes.default.number,
height: _propTypes.default.number,
width: _propTypes.default.oneOfType([_propTypes.default.number, _propTypes.default.string]),
minWidth: _propTypes.default.number,
height: _propTypes.default.oneOfType([_propTypes.default.number, _propTypes.default.string]),
minHeight: _propTypes.default.number,
flexGrow: _propTypes.default.number,
flexShrink: _propTypes.default.number,
flexDirection: _propTypes.default.oneOf(['row', 'row-reverse', 'column', 'column-reverse']),
flexBasis: _propTypes.default.oneOfType([_propTypes.default.number, _propTypes.default.string]),
alignItems: _propTypes.default.oneOf(['flex-start', 'center', 'flex-end']),
justifyContent: _propTypes.default.oneOf(['flex-start', 'center', 'flex-end', 'space-between', 'space-around']),
textWrap: _propTypes.default.oneOf(['wrap', 'truncate', 'truncate-start', 'truncate-middle', 'truncate-end']),
unstable__transformChildren: _propTypes.default.func,

@@ -75,0 +79,0 @@ children: _propTypes.default.node

@@ -67,6 +67,2 @@ "use strict";

shouldComponentUpdate(nextProps, nextState) {
return this.state.ignoreKeys === nextState.ignoreKeys;
}
saveRenderedKeys() {

@@ -73,0 +69,0 @@ this.setState(prevState => {

@@ -16,2 +16,6 @@ "use strict";

var _isCi = _interopRequireDefault(require("is-ci"));
var _signalExit = _interopRequireDefault(require("signal-exit"));
var _reconciler = _interopRequireDefault(require("./reconciler"));

@@ -32,2 +36,3 @@

this.rootNode = (0, _dom.createNode)('root');
this.rootNode.onRender = this.onRender;
this.renderer = (0, _renderer.default)({

@@ -42,13 +47,16 @@ terminalWidth: options.stdout.columns

this.ignoreRender = false; // Store last output to only rerender when needed
this.isUnmounted = false; // Store last output to only rerender when needed
this.lastOutput = '';
this.lastStaticOutput = ''; // This variable is used only in debug mode to store full static output
this.lastOutput = ''; // This variable is used only in debug mode to store full static output
// so that it's rerendered every time, not just new static parts, like in non-debug mode
this.fullStaticOutput = '';
this.reconciler = (0, _reconciler.default)(this.onRender);
this.container = this.reconciler.createContainer(this.rootNode, false);
this.exitPromise = new Promise(resolve => {
this.container = _reconciler.default.createContainer(this.rootNode, false, false);
this.exitPromise = new Promise((resolve, reject) => {
this.resolveExitPromise = resolve;
this.rejectExitPromise = reject;
}); // Unmount when process exits
this.unsubscribeExit = (0, _signalExit.default)(this.unmount, {
alwaysLast: false
});

@@ -58,3 +66,3 @@ }

onRender() {
if (this.ignoreRender) {
if (this.isUnmounted) {
return;

@@ -68,8 +76,7 @@ }

const hasNewStaticOutput = staticOutput && staticOutput !== '\n' && staticOutput !== this.lastStaticOutput;
const hasStaticOutput = staticOutput && staticOutput !== '\n';
if (this.options.debug) {
if (hasNewStaticOutput) {
if (hasStaticOutput) {
this.fullStaticOutput += staticOutput;
this.lastStaticOutput = staticOutput;
}

@@ -82,11 +89,19 @@

if (hasNewStaticOutput) {
this.log.clear();
if (hasStaticOutput) {
if (!_isCi.default) {
this.log.clear();
}
this.options.stdout.write(staticOutput);
this.log(output);
this.lastStaticOutput = staticOutput;
if (!_isCi.default) {
this.log(output);
}
}
if (output !== this.lastOutput) {
this.throttledLog(output);
if (!_isCi.default) {
this.throttledLog(output);
}
this.lastOutput = output;

@@ -104,11 +119,29 @@ }

this.reconciler.updateContainer(tree, this.container);
_reconciler.default.updateContainer(tree, this.container);
}
unmount() {
unmount(error) {
if (this.isUnmounted) {
return;
}
this.onRender();
this.log.done();
this.ignoreRender = true;
this.reconciler.updateContainer(null, this.container);
this.resolveExitPromise();
this.unsubscribeExit(); // CIs don't handle erasing ansi escapes well, so it's better to
// only render last frame of non-static output
if (_isCi.default) {
this.options.stdout.write(this.lastOutput + '\n');
} else if (!this.options.debug) {
this.log.done();
}
this.isUnmounted = true;
_reconciler.default.updateContainer(null, this.container);
if (error instanceof Error) {
this.rejectExitPromise(error);
} else {
this.resolveExitPromise();
}
}

@@ -115,0 +148,0 @@

@@ -16,112 +16,113 @@ "use strict";

var _default = onRender => {
const rootHostContext = {};
const childHostContext = {};
const hostConfig = {
schedulePassiveEffects: _scheduler.unstable_scheduleCallback,
cancelPassiveEffects: _scheduler.unstable_cancelCallback,
now: Date.now,
getRootHostContext: () => rootHostContext,
prepareForCommit: () => {},
resetAfterCommit: onRender,
getChildHostContext: () => childHostContext,
shouldSetTextContent: (type, props) => {
return typeof props.children === 'string' || typeof props.children === 'number';
},
createInstance: (type, newProps) => {
const node = (0, _dom.createNode)(type);
const NO_CONTEXT = true;
const hostConfig = {
schedulePassiveEffects: _scheduler.unstable_scheduleCallback,
cancelPassiveEffects: _scheduler.unstable_cancelCallback,
now: Date.now,
getRootHostContext: () => NO_CONTEXT,
prepareForCommit: () => {},
resetAfterCommit: rootNode => {
rootNode.onRender();
},
getChildHostContext: () => NO_CONTEXT,
shouldSetTextContent: (type, props) => {
return typeof props.children === 'string' || typeof props.children === 'number';
},
createInstance: (type, newProps) => {
const node = (0, _dom.createNode)(type);
for (const [key, value] of Object.entries(newProps)) {
if (key === 'children') {
if (typeof value === 'string' || typeof value === 'number') {
if (type === 'div') {
// Text node must be wrapped in another node, so that text can be aligned within container
const textElement = (0, _dom.createNode)('div');
textElement.textContent = String(value);
(0, _dom.appendChildNode)(node, textElement);
}
for (const [key, value] of Object.entries(newProps)) {
if (key === 'children') {
if (typeof value === 'string' || typeof value === 'number') {
if (type === 'div') {
// Text node must be wrapped in another node, so that text can be aligned within container
const textElement = (0, _dom.createNode)('div');
textElement.textContent = String(value);
(0, _dom.appendChildNode)(node, textElement);
}
if (type === 'span') {
node.textContent = String(value);
}
if (type === 'span') {
node.textContent = String(value);
}
} else if (key === 'style') {
Object.assign(node.style, value);
} else if (key === 'unstable__transformChildren') {
node.unstable__transformChildren = value; // eslint-disable-line camelcase
} else if (key === 'unstable__static') {
node.unstable__static = true; // eslint-disable-line camelcase
} else {
(0, _dom.setAttribute)(node, key, value);
}
} else if (key === 'style') {
Object.assign(node.style, value);
} else if (key === 'unstable__transformChildren') {
node.unstable__transformChildren = value; // eslint-disable-line camelcase
} else if (key === 'unstable__static') {
node.unstable__static = true; // eslint-disable-line camelcase
} else {
(0, _dom.setAttribute)(node, key, value);
}
}
return node;
},
createTextInstance: _dom.createTextNode,
resetTextContent: node => {
if (node.textContent) {
node.textContent = '';
}
return node;
},
createTextInstance: _dom.createTextNode,
resetTextContent: node => {
if (node.textContent) {
node.textContent = '';
}
if (node.childNodes.length > 0) {
for (const childNode of node.childNodes) {
childNode.yogaNode.free();
(0, _dom.removeChildNode)(node, childNode);
}
if (node.childNodes.length > 0) {
for (const childNode of node.childNodes) {
childNode.yogaNode.free();
(0, _dom.removeChildNode)(node, childNode);
}
},
getPublicInstance: instance => instance,
appendInitialChild: _dom.appendChildNode,
appendChild: _dom.appendChildNode,
insertBefore: _dom.insertBeforeNode,
finalizeInitialChildren: () => {},
supportsMutation: true,
appendChildToContainer: _dom.appendChildNode,
insertInContainerBefore: _dom.insertBeforeNode,
removeChildFromContainer: _dom.removeChildNode,
prepareUpdate: () => true,
commitUpdate: (node, updatePayload, type, oldProps, newProps) => {
for (const [key, value] of Object.entries(newProps)) {
if (key === 'children') {
if (typeof value === 'string' || typeof value === 'number') {
if (type === 'div') {
// Text node must be wrapped in another node, so that text can be aligned within container
// If there's no such node, a new one must be created
if (node.childNodes.length === 0) {
const textElement = (0, _dom.createNode)('div');
textElement.textContent = String(value);
(0, _dom.appendChildNode)(node, textElement);
} else {
node.childNodes[0].textContent = String(value);
}
}
},
getPublicInstance: instance => instance,
appendInitialChild: _dom.appendChildNode,
appendChild: _dom.appendChildNode,
insertBefore: _dom.insertBeforeNode,
finalizeInitialChildren: () => {},
supportsMutation: true,
appendChildToContainer: _dom.appendChildNode,
insertInContainerBefore: _dom.insertBeforeNode,
removeChildFromContainer: _dom.removeChildNode,
prepareUpdate: () => true,
commitUpdate: (node, updatePayload, type, oldProps, newProps) => {
for (const [key, value] of Object.entries(newProps)) {
if (key === 'children') {
if (typeof value === 'string' || typeof value === 'number') {
if (type === 'div') {
// Text node must be wrapped in another node, so that text can be aligned within container
// If there's no such node, a new one must be created
if (node.childNodes.length === 0) {
const textElement = (0, _dom.createNode)('div');
textElement.textContent = String(value);
(0, _dom.appendChildNode)(node, textElement);
} else {
node.childNodes[0].textContent = String(value);
}
}
if (type === 'span') {
node.textContent = String(value);
}
if (type === 'span') {
node.textContent = String(value);
}
} else if (key === 'style') {
Object.assign(node.style, value);
} else if (key === 'unstable__transformChildren') {
node.unstable__transformChildren = value; // eslint-disable-line camelcase
} else if (key === 'unstable__static') {
node.unstable__static = true; // eslint-disable-line camelcase
} else {
(0, _dom.setAttribute)(node, key, value);
}
}
},
commitTextUpdate: (node, oldText, newText) => {
if (node.nodeName === '#text') {
node.nodeValue = newText;
} else if (key === 'style') {
Object.assign(node.style, value);
} else if (key === 'unstable__transformChildren') {
node.unstable__transformChildren = value; // eslint-disable-line camelcase
} else if (key === 'unstable__static') {
node.unstable__static = true; // eslint-disable-line camelcase
} else {
node.textContent = newText;
(0, _dom.setAttribute)(node, key, value);
}
},
removeChild: _dom.removeChildNode
};
return (0, _reactReconciler.default)(hostConfig); // eslint-disable-line new-cap
}
},
commitTextUpdate: (node, oldText, newText) => {
if (node.nodeName === '#text') {
node.nodeValue = newText;
} else {
node.textContent = newText;
}
},
removeChild: _dom.removeChildNode
};
var _default = (0, _reactReconciler.default)(hostConfig); // eslint-disable-line new-cap
exports.default = _default;

@@ -8,3 +8,61 @@ "use strict";

// After nodes are laid out, render each to output object, which later gets rendered to terminal
var _widestLine = _interopRequireDefault(require("widest-line"));
var _wrapText = _interopRequireDefault(require("./wrap-text"));
var _getMaxWidth = _interopRequireDefault(require("./get-max-width"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
const isAllTextNodes = node => {
if (node.nodeName === '#text') {
return true;
}
if (node.nodeName === 'SPAN') {
if (node.textContent) {
return true;
}
if (Array.isArray(node.childNodes)) {
return node.childNodes.every(isAllTextNodes);
}
}
return false;
}; // Squashing text nodes allows to combine multiple text nodes into one and write
// to `Output` instance only once. For example, <Text>hello{' '}world</Text>
// is actually 3 text nodes, which would result 3 writes to `Output`.
//
// Also, this is necessary for libraries like ink-link (https://github.com/sindresorhus/ink-link),
// which need to wrap all children at once, instead of wrapping 3 text nodes separately.
const squashTextNodes = node => {
let text = '';
for (const childNode of node.childNodes) {
let nodeText;
if (childNode.nodeName === '#text') {
nodeText = childNode.nodeValue;
}
if (childNode.nodeName === 'SPAN') {
nodeText = childNode.textContent || squashTextNodes(childNode);
} // Since these text nodes are being concatenated, `Output` instance won't be able to
// apply children transform, so we have to do it manually here for each text node
if (childNode.unstable__transformChildren) {
nodeText = childNode.unstable__transformChildren(nodeText);
}
text += nodeText;
}
return text;
}; // After nodes are laid out, render each to output object, which later gets rendered to terminal
const renderNodeToOutput = (node, output, {

@@ -32,8 +90,20 @@ offsetX = 0,

newTransformers = [node.unstable__transformChildren, ...transformers];
} // Text nodes
} // Nodes with only text inside
const text = node.textContent || node.nodeValue;
if (node.textContent) {
let text = node.textContent; // Since text nodes are always wrapped in an additional node, parent node
// is where we should look for attributes
if (text) {
if (node.parentNode.style.textWrap) {
const currentWidth = (0, _widestLine.default)(text);
const maxWidth = (0, _getMaxWidth.default)(node.parentNode.yogaNode);
if (currentWidth > maxWidth) {
text = (0, _wrapText.default)(text, maxWidth, {
textWrap: node.parentNode.style.textWrap
});
}
}
output.write(x, y, text, {

@@ -43,2 +113,10 @@ transformers: newTransformers

return;
} // Text nodes
if (node.nodeName === '#text') {
output.write(x, y, node.nodeValue, {
transformers: newTransformers
});
return;
} // Nodes that have other nodes as children

@@ -48,25 +126,16 @@

if (Array.isArray(node.childNodes) && node.childNodes.length > 0) {
// Squashing text nodes allows to combine multiple text nodes into one and write
// to `Output` instance only once. For example, <Text>hello{' '}world</Text>
// is actually 3 text nodes, which would result 3 writes to `Output`.
//
// Also, this is necessary for libraries like ink-link (https://github.com/sindresorhus/ink-link),
// which need to wrap all children at once, instead of wrapping 3 text nodes separately.
const isFlexDirectionColumn = node.style.flexDirection === 'column';
const isAllTextNodes = node.childNodes.every(childNode => {
return Boolean(childNode.nodeValue) || childNode.nodeName === 'SPAN' && Boolean(childNode.textContent);
});
const isFlexDirectionRow = node.style.flexDirection === 'row';
if (!isFlexDirectionColumn && isAllTextNodes) {
let text = '';
if (isFlexDirectionRow && node.childNodes.every(isAllTextNodes)) {
let text = squashTextNodes(node);
for (const childNode of node.childNodes) {
let nodeText = childNode.nodeValue || childNode.textContent; // Since these text nodes are being concatenated, `Output` instance won't be able to
// apply children transform, so we have to do it manually here for each text node
if (node.style.textWrap) {
const currentWidth = (0, _widestLine.default)(text);
const maxWidth = (0, _getMaxWidth.default)(yogaNode);
if (childNode.unstable__transformChildren) {
nodeText = childNode.unstable__transformChildren(nodeText);
if (currentWidth > maxWidth) {
text = (0, _wrapText.default)(text, maxWidth, {
textWrap: node.style.textWrap
});
}
text += nodeText;
}

@@ -73,0 +142,0 @@

@@ -45,3 +45,3 @@ "use strict";

rerender: instance.render,
unmount: instance.unmount,
unmount: () => instance.unmount(),
waitUntilExit: instance.waitUntilExit,

@@ -48,0 +48,0 @@ cleanup: () => instances.delete(options.stdout)

@@ -18,5 +18,47 @@ "use strict";

var _measureText = _interopRequireDefault(require("./measure-text"));
var _wrapText = _interopRequireDefault(require("./wrap-text"));
var _getMaxWidth = _interopRequireDefault(require("./get-max-width"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
// Since <Static> components can be placed anywhere in the tree, this helper finds and returns them
// Since we need to know the width of text container to wrap text, we have to calculate layout twice
// This function is executed after first layout calculation to reassign width and height of text nodes
const calculateWrappedText = node => {
if (node.textContent && typeof node.parentNode.style.textWrap === 'string') {
const {
yogaNode
} = node;
const parentYogaNode = node.parentNode.yogaNode;
const maxWidth = (0, _getMaxWidth.default)(parentYogaNode);
const currentWidth = yogaNode.getComputedWidth();
if (currentWidth > maxWidth) {
const {
textWrap
} = node.parentNode.style;
const wrappedText = (0, _wrapText.default)(node.textContent, maxWidth, {
textWrap
});
const {
width,
height
} = (0, _measureText.default)(wrappedText);
yogaNode.setWidth(width);
yogaNode.setHeight(height);
}
return;
}
if (Array.isArray(node.childNodes) && node.childNodes.length > 0) {
for (const childNode of node.childNodes) {
calculateWrappedText(childNode);
}
}
}; // Since <Static> components can be placed anywhere in the tree, this helper finds and returns them
const getStaticNodes = element => {

@@ -69,5 +111,3 @@ const staticNodes = [];

const rootNode = (0, _dom.createNode)('root');
(0, _dom.appendStaticNode)(rootNode, staticElements[0], {
woot: true
});
(0, _dom.appendStaticNode)(rootNode, staticElements[0]);
const {

@@ -80,2 +120,4 @@ yogaNode: staticYogaNode

});
staticYogaNode.calculateLayout(_yogaLayoutPrebuilt.default.UNDEFINED, _yogaLayoutPrebuilt.default.UNDEFINED, _yogaLayoutPrebuilt.default.DIRECTION_LTR);
calculateWrappedText(rootNode);
staticYogaNode.calculateLayout(_yogaLayoutPrebuilt.default.UNDEFINED, _yogaLayoutPrebuilt.default.UNDEFINED, _yogaLayoutPrebuilt.default.DIRECTION_LTR); // Save current Yoga node tree to free up memory later

@@ -100,2 +142,4 @@

});
yogaNode.calculateLayout(_yogaLayoutPrebuilt.default.UNDEFINED, _yogaLayoutPrebuilt.default.UNDEFINED, _yogaLayoutPrebuilt.default.DIRECTION_LTR);
calculateWrappedText(node);
yogaNode.calculateLayout(_yogaLayoutPrebuilt.default.UNDEFINED, _yogaLayoutPrebuilt.default.UNDEFINED, _yogaLayoutPrebuilt.default.DIRECTION_LTR); // Save current node tree to free up memory later

@@ -102,0 +146,0 @@

@@ -123,4 +123,6 @@ import * as React from "react";

export interface BoxProps {
readonly width?: number;
readonly height?: number;
readonly width?: number | string;
readonly height?: number | string;
readonly minWidth?: number;
readonly minHeight?: number;
readonly paddingTop?: number;

@@ -143,2 +145,3 @@ readonly paddingBottom?: number;

readonly flexDirection?: "row" | "row-reverse" | "column" | "column-reverse";
readonly flexBasis?: string | number;
readonly alignItems?: "flex-start" | "center" | "flex-end";

@@ -151,2 +154,8 @@ readonly justifyContent?:

| "space-around";
readonly textWrap?:
| "wrap"
| "truncate"
| "truncate-start"
| "truncate-middle"
| "truncate-end";
}

@@ -185,3 +194,3 @@

*/
readonly exit: () => void;
readonly exit: (error?: Error) => void;
}>;

@@ -188,0 +197,0 @@

{
"name": "ink",
"version": "2.0.6",
"version": "2.1.0",
"description": "React for CLI",

@@ -48,2 +48,4 @@ "license": "MIT",

"cli-cursor": "^2.1.0",
"cli-truncate": "^1.1.0",
"is-ci": "^2.0.0",
"lodash.throttle": "^4.1.1",

@@ -54,5 +56,7 @@ "log-update": "^3.0.0",

"scheduler": "^0.13.2",
"signal-exit": "^3.0.2",
"slice-ansi": "^1.0.0",
"string-length": "^2.0.0",
"widest-line": "^2.0.0",
"wrap-ansi": "^5.0.0",
"yoga-layout-prebuilt": "^1.9.3"

@@ -78,2 +82,3 @@ },

"sinon": "^7.2.7",
"strip-ansi": "^5.2.0",
"svg-term-cli": "^2.1.1",

@@ -80,0 +85,0 @@ "xo": "^0.24.0"

@@ -282,2 +282,76 @@ <h1 align="center">

##### Dimensions
###### width
Type: `number`, `string`
Width of the element in spaces. You can also set it in percent, which will calculate the width based on the width of parent element.
```jsx
<Box width={4}>X</Box> //=> 'X '
```
```jsx
<Box width={10}>
<Box width="50%">X</Box>
Y
</Box> //=> 'X Y'
```
###### height
Type: `number`, `string`
Height of the element in lines (rows). You can also set it in percent, which will calculate the height based on the height of parent element.
```jsx
<Box height={4}>X</Box> //=> 'X\n\n\n'
```
```jsx
<Box height={6} flexDirection="column">
<Box height="50%">X</Box>
Y
</Box> //=> 'X\n\n\nY\n\n'
```
###### minWidth
Type: `number`
Sets a minimum width of the element. Percentages aren't supported yet, see https://github.com/facebook/yoga/issues/872.
###### minHeight
Type: `number`
Sets a minimum height of the element. Percentages aren't supported yet, see https://github.com/facebook/yoga/issues/872.
##### Wrapping
###### textWrap
Type: `string`<br>
Values: `wrap` `truncate` `truncate-start` `truncate-middle` `truncate-end`
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.
*Note:* Ink doesn't wrap text by default.
```jsx
<Box textWrap="wrap">Hello World</Box>
//=> 'Hello\nWorld'
// `truncate` is an alias to `truncate-end`
<Box textWrap="truncate">Hello World</Box>
//=> 'Hello…'
<Box textWrap="truncate-middle">Hello World</Box>
//=> 'He…ld'
<Box textWrap="truncate-start">Hello World</Box>
//=> '…World'
```
##### Padding

@@ -413,2 +487,22 @@

###### flexBasis
Type: `number`, `string`<br>
See [flex-basis](https://css-tricks.com/almanac/properties/f/flex-basis/).
```jsx
<Box width={6}>
<Box flexBasis={3}>X</Box>
Y
</Box> //=> 'X Y'
```
```jsx
<Box width={6}>
<Box flexBasis="50%">X</Box>
Y
</Box> //=> 'X Y'
```
###### flexDirection

@@ -643,2 +737,4 @@

If `exit` is called with an Error, `waitUntilExit` will reject with that error.
#### `<StdinContext>`

@@ -645,0 +741,0 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc