Socket
Socket
Sign inDemoInstall

nuclide-commons-ui

Package Overview
Dependencies
84
Maintainers
4
Versions
21
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 0.4.0 to 0.5.0

BoundSettingsControl.js

26

addTooltip.js

@@ -40,12 +40,12 @@ 'use strict';

/**
* Adds a self-disposing Atom's tooltip to a react element.
*
* Typical usage:
* <div ref={addTooltip({title: 'My awesome tooltip', delay: 100, placement: 'top'})} />
* or, if the ref needs to be preserved:
* <div ref={c => {
* addTooltip({title: 'My awesome tooltip', delay: 100, placement: 'top'})(c);
* _myDiv = c;
* }} />
*/
* Adds a self-disposing Atom's tooltip to a react element.
*
* Typical usage:
* <div ref={addTooltip({title: 'My awesome tooltip', delay: 100, placement: 'top'})} />
* or, if the ref needs to be preserved:
* <div ref={c => {
* addTooltip({title: 'My awesome tooltip', delay: 100, placement: 'top'})(c);
* _myDiv = c;
* }} />
*/
function addTooltip(options) {

@@ -59,3 +59,7 @@ let node;

if (node != null) {
_toDispose.add(node);
if (_tooltipRequests.has(node)) {
_tooltipRequests.delete(node);
} else {
_toDispose.add(node);
}
}

@@ -62,0 +66,0 @@

@@ -8,2 +8,4 @@ 'use strict';

var _react = _interopRequireWildcard(require('react'));
var _classnames;

@@ -15,6 +17,2 @@

var _atom = require('atom');
var _react = _interopRequireWildcard(require('react'));
var _string;

@@ -26,10 +24,25 @@

function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
var _observable;
function _load_observable() {
return _observable = require('nuclide-commons/observable');
}
var _debounce;
function _load_debounce() {
return _debounce = _interopRequireDefault(require('nuclide-commons/debounce'));
}
var _UniversalDisposable;
function _load_UniversalDisposable() {
return _UniversalDisposable = _interopRequireDefault(require('nuclide-commons/UniversalDisposable'));
}
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
/**
* An input field rendered as an <atom-text-editor mini />.
*/
/**
* Copyright (c) 2017-present, Facebook, Inc.

@@ -46,2 +59,7 @@ * All rights reserved.

const BLUR_FOCUS_DEBOUNCE_DELAY = 100;
/**
* An input field rendered as an <atom-text-editor mini />.
*/
class AtomInput extends _react.Component {

@@ -51,2 +69,17 @@

super(props);
this._onEditorFocus = () => {
if (this.isFocused() && !this._isFocused) {
this._isFocused = true;
this.props.onFocus && this.props.onFocus();
}
};
this._onEditorBlur = blurEvent => {
if (!this.isFocused() && this._isFocused) {
this._isFocused = false;
this.props.onBlur && this.props.onBlur(blurEvent);
}
};
const value = props.value == null ? props.initialValue : props.value;

@@ -56,6 +89,8 @@ this.state = {

};
this._debouncedEditorFocus = (0, (_debounce || _load_debounce()).default)(this._onEditorFocus, BLUR_FOCUS_DEBOUNCE_DELAY);
this._debouncedEditorBlur = (0, (_debounce || _load_debounce()).default)(this._onEditorBlur, BLUR_FOCUS_DEBOUNCE_DELAY);
}
componentDidMount() {
const disposables = this._disposables = new _atom.CompositeDisposable();
const disposables = this._disposables = new (_UniversalDisposable || _load_UniversalDisposable()).default();

@@ -70,19 +105,35 @@ // There does not appear to be any sort of infinite loop where calling

}
if (!!(this.props.startSelected && this.props.startSelectedRange != null)) {
throw new Error('cannot have both startSelected (all) and startSelectedRange');
}
if (this.props.startSelected) {
// For some reason, selectAll() has no effect if called right now.
process.nextTick(() => {
disposables.add((_observable || _load_observable()).microtask.subscribe(() => {
if (!textEditor.isDestroyed()) {
textEditor.selectAll();
}
});
}));
}
const startSelectedRange = this.props.startSelectedRange;
if (startSelectedRange != null) {
// For some reason, selectAll() has no effect if called right now.
disposables.add((_observable || _load_observable()).microtask.subscribe(() => {
if (!textEditor.isDestroyed()) {
textEditor.setSelectedBufferRange([[0, startSelectedRange[0]], [0, startSelectedRange[1]]]);
}
}));
}
disposables.add(atom.commands.add(textEditorElement, {
'core:confirm': () => {
'core:confirm': event => {
if (this.props.onConfirm != null) {
this.props.onConfirm();
this.props.onConfirm(event);
}
},
'core:cancel': () => {
'core:cancel': event => {
if (this.props.onCancel != null) {
this.props.onCancel();
this.props.onCancel(event);
}

@@ -141,3 +192,4 @@ }

// Note that destroy() is not part of TextEditor's public API.
this.getTextEditor().destroy();
const editor = this.getTextEditor();
process.nextTick(() => editor.destroy());

@@ -159,6 +211,11 @@ if (this._disposables) {

isFocused() {
return this._rootNode != null && this._rootNode.contains(document.activeElement);
}
render() {
const className = (0, (_classnames || _load_classnames()).default)(this.props.className, {
'atom-text-editor-unstyled': this.props.unstyled,
[`atom-text-editor-${(0, (_string || _load_string()).maybeToString)(this.props.size)}`]: this.props.size != null
[`atom-text-editor-${(0, (_string || _load_string()).maybeToString)(this.props.size)}`]: this.props.size != null,
'atom-text-editor-invalid': this.props.invalid
});

@@ -176,4 +233,4 @@

onClick: this.props.onClick,
onFocus: this.props.onFocus,
onBlur: this.props.onBlur,
onFocus: this._debouncedEditorFocus,
onBlur: this._debouncedEditorBlur,
style: this.props.style

@@ -197,3 +254,3 @@ })

onDidChange(callback) {
return this.getTextEditor().onDidChange(callback);
return this.getTextEditor().getBuffer().onDidChangeText(callback);
}

@@ -200,0 +257,0 @@

@@ -16,2 +16,8 @@ 'use strict';

var _semver;
function _load_semver() {
return _semver = _interopRequireDefault(require('semver'));
}
var _atom = require('atom');

@@ -35,15 +41,15 @@

/**
* Copyright (c) 2017-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
*
* @format
*/
const doNothing = () => {}; /**
* Copyright (c) 2017-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
*
* @format
*/
const doNothing = () => {};
const ATOM_VERSION_CHECK_FOR_SET_GRAMMAR = '1.24.0-beta0';

@@ -60,3 +66,3 @@ function setupTextEditor(props) {

if (props.onDidTextBufferChange != null) {
disposables.add(textBuffer.onDidChange(props.onDidTextBufferChange));
disposables.add(textBuffer.onDidChangeText(props.onDidTextBufferChange));
}

@@ -71,5 +77,6 @@

disposables.add(() => textEditor.destroy());
if (props.grammar != null) {
textEditor.setGrammar(props.grammar);
} else if ((_semver || _load_semver()).default.gte(atom.getVersion(), ATOM_VERSION_CHECK_FOR_SET_GRAMMAR)) {
atom.grammars.autoAssignLanguageMode(textBuffer);
}

@@ -91,3 +98,2 @@ disposables.add((0, (_textEditor || _load_textEditor()).enforceSoftWrap)(textEditor, props.softWrapped));

}
return {

@@ -157,2 +163,6 @@ disposables,

}
if (this.props.onInitialized != null) {
this._editorDisposables.add(this.props.onInitialized(textEditor));
}
}

@@ -256,3 +266,3 @@

componentWillUnmount() {
this._editorDisposables.dispose();
process.nextTick(() => this._editorDisposables.dispose());
}

@@ -259,0 +269,0 @@ }

@@ -44,6 +44,2 @@ 'use strict';

getWrappedComponent() {
return this._wrappedComponent;
}
componentDidMount() {

@@ -67,7 +63,5 @@ this._subscription = stream.subscribe(newState => {

const props = Object.assign({}, this.props, this.state);
return _react.createElement(ComposedComponent, Object.assign({
ref: component => this._wrappedComponent = component
}, props));
return _react.createElement(ComposedComponent, props);
}
};
}

@@ -102,3 +102,4 @@ 'use strict';

const buttonTypeClassname = buttonType == null ? '' : ButtonTypeClassnames[buttonType] || '';
const ref = tooltip ? (0, (_addTooltip || _load_addTooltip()).default)(tooltip) : null;
const ref = tooltip && !this.props.disabled ? (0, (_addTooltip || _load_addTooltip()).default)(tooltip) : null;
const titleToolTip = tooltip && this.props.disabled ? tooltip.title : null;
const newClassName = (0, (_classnames || _load_classnames()).default)(className, 'btn', {

@@ -115,3 +116,7 @@ [`icon icon-${(0, (_string || _load_string()).maybeToString)(icon)}`]: icon != null,

Wrapper,
Object.assign({ className: newClassName, ref: ref }, remainingProps),
Object.assign({
className: newClassName,
ref: ref
}, remainingProps, {
title: titleToolTip }),
children

@@ -118,0 +123,0 @@ )

@@ -75,3 +75,6 @@ 'use strict';

_setIndeterminate() {
this.refs.input.indeterminate = this.props.indeterminate;
if (this._input == null) {
return;
}
this._input.indeterminate = this.props.indeterminate;
}

@@ -115,3 +118,5 @@

onMouseDown: onMouseDown,
ref: 'input',
ref: el => {
this._input = el;
},
type: 'checkbox'

@@ -118,0 +123,0 @@ }),

@@ -31,4 +31,9 @@ 'use strict';

class CodeSnippet extends _react.Component {
componentDidMount() {
const editor = this.refs.editor.getTextEditor();
if (!(this._editor != null)) {
throw new Error('Invariant violation: "this._editor != null"');
}
const editor = this._editor.getTextEditor();
const { grammar, highlights, startLine } = this.props;

@@ -77,3 +82,5 @@

_react.createElement((_AtomInput || _load_AtomInput()).AtomInput, {
ref: 'editor',
ref: input => {
this._editor = input;
},
initialValue: this.props.text,

@@ -80,0 +87,0 @@ disabled: true,

'use strict';
var _atom = require('atom');
var _nuclideUri;
function _load_nuclideUri() {
return _nuclideUri = _interopRequireDefault(require('nuclide-commons/nuclideUri'));
}
var _UniversalDisposable;
function _load_UniversalDisposable() {
return _UniversalDisposable = _interopRequireDefault(require('nuclide-commons/UniversalDisposable'));
}
var _dedent;
function _load_dedent() {
return _dedent = _interopRequireDefault(require('dedent'));
}
var _fs = _interopRequireDefault(require('fs'));
var _nullthrows;
function _load_nullthrows() {
return _nullthrows = _interopRequireDefault(require('nullthrows'));
}
var _path = _interopRequireDefault(require('path'));

@@ -11,4 +33,2 @@

const styleDir = _path.default.join(__dirname, 'styles');
// eslint-disable-next-line rulesdir/prefer-nuclide-uri
/**

@@ -29,4 +49,19 @@ * Copyright (c) 2017-present, Facebook, Inc.

const styleDisposables = new _atom.CompositeDisposable(..._fs.default.readdirSync(styleDir).filter(file => _path.default.extname(file) === '.less').map(file => atom.themes.requireStylesheet(_path.default.join(styleDir, file))));
const ttfUri = (_nuclideUri || _load_nuclideUri()).default.nuclideUriToUri(_path.default.join(__dirname, 'styles', 'nuclicons.ttf'));
// eslint-disable-next-line rulesdir/prefer-nuclide-uri
const newStyle = document.createElement('style');
newStyle.appendChild(document.createTextNode((_dedent || _load_dedent()).default`
@font-face {
font-family: 'nuclicons';
src: url('${ttfUri}') format('truetype');
font-weight: normal;
font-style: normal;
}
`));
(0, (_nullthrows || _load_nullthrows()).default)(document.head).appendChild(newStyle);
const styleDir = _path.default.join(__dirname, 'styles');
const styleDisposables = new (_UniversalDisposable || _load_UniversalDisposable()).default(..._fs.default.readdirSync(styleDir).filter(file => ['.less', '.css'].includes(_path.default.extname(file))).map(file => atom.themes.requireStylesheet(_path.default.join(styleDir, file))), () => newStyle.remove());
module.exports = styleDisposables; // eslint-disable-line rulesdir/no-commonjs

@@ -8,2 +8,4 @@ 'use strict';

var _os = _interopRequireDefault(require('os'));
var _rxjsBundlesRxMinJs = require('rxjs/bundles/Rx.min.js');

@@ -79,2 +81,18 @@

// $FlowFixMe(>=0.55.0) Flow suppress
/**
* Copyright (c) 2017-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
*
* @format
*/
/* eslint-env browser */
/* global IntersectionObserver, PerformanceObserver, ResizeObserver, DOMRect */
class DOMObserverObservable extends _rxjsBundlesRxMinJs.Observable {

@@ -173,17 +191,4 @@

}
} /**
* Copyright (c) 2017-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
*
* @format
*/
}
/* eslint-env browser */
/* global IntersectionObserver, PerformanceObserver, ResizeObserver */
const _DOMObserverObservable = exports._DOMObserverObservable = DOMObserverObservable;

@@ -201,3 +206,5 @@

}
// $FlowFixMe(>=0.55.0) Flow suppress
super(IntersectionObserver, target);

@@ -218,3 +225,5 @@ }

}
// $FlowFixMe(>=0.55.0) Flow suppress
super(MutationObserver, target);

@@ -235,3 +244,5 @@ }

}
// $FlowFixMe(>=0.55.0) Flow suppress
super(PerformanceObserver, options);

@@ -253,5 +264,71 @@ }

super(ResizeObserver, target);
if (_os.default.platform() === 'win32') {
super(WindowsResizeMeasurementPatchingObserver, target);
} else {
// $FlowFixMe(>=0.55.0) Flow suppress
super(ResizeObserver, target);
}
}
}
exports.ResizeObservable = ResizeObservable;
exports.ResizeObservable = ResizeObservable;
function lastRectPerTarget(entries) {
const rectMap = new Map();
entries.forEach(entry => rectMap.set(entry.target, entry.contentRect));
return rectMap;
}
function remeasureContentRect(element, contentRect) {
const { clientHeight, clientWidth } = element;
// Client height/width include padding
// https://developer.mozilla.org/en-US/docs/Web/API/Element/clientWidth
// We have to strip it to obtain result similar to what the original computed style provided
const computedStyle = window.getComputedStyle(element);
const { paddingLeft, paddingRight, paddingTop, paddingBottom } = computedStyle;
const height = clientHeight - parseFloat(paddingTop) - parseFloat(paddingBottom);
const width = clientWidth - parseFloat(paddingLeft) - parseFloat(paddingRight);
return new DOMRect(contentRect.x, contentRect.y, width, height);
}
/*
* The values provided by the ResizeOverver on Windows do not seem to reflect the actual size
* of the element (!!!), so we need to "fix" them before passing on to the downstream subscriber
* We're wrapping the ResizeObserver instance and are patching the last result of the array with
* a set of custom measured values
*/
class WindowsResizeMeasurementPatchingObserver {
constructor(callback, ...rest) {
const remeasuringCallback = entries => {
const rebuiltEntries = [];
const mappedRects = lastRectPerTarget(entries);
mappedRects.forEach((originalRect, target) => {
const contentRect = remeasureContentRect(target, originalRect);
rebuiltEntries.push({ target, contentRect });
});
callback(rebuiltEntries);
};
this._resizeObserver = new ResizeObserver(remeasuringCallback, ...rest);
// To make flow happy
return this;
}
observe(...observeArgs) {
this._resizeObserver.observe(...observeArgs);
}
disconnect() {
this._resizeObserver.disconnect();
}
unobserve(...unobserveArgs) {
if (typeof this._resizeObserver.unobserve === 'function') {
this._resizeObserver.unobserve(...unobserveArgs);
}
}
}
{
"name": "nuclide-commons-ui",
"version": "0.4.0",
"version": "0.5.0",
"description": "Common Nuclide UI components.",
"author": "Nuclide: Core UI",
"license": "BSD-3-Clause",

@@ -16,13 +17,16 @@ "homepage": "https://nuclide.io/",

"classnames": "2.2.5",
"dedent": "0.6.0",
"escape-string-regexp": "1.0.5",
"idx": "1.2.0",
"invariant": "2.2.2",
"nuclide-commons": "0.4.0",
"nuclide-commons-atom": "0.4.0",
"nuclide-commons": "0.5.0",
"nuclide-commons-atom": "0.5.0",
"nullthrows": "1.0.0",
"react": "16.0.0",
"react-dom": "16.0.0",
"rxjs": "5.3.1",
"shallowequal": "0.2.2"
"react": "16.2.0",
"react-dom": "16.2.0",
"rxjs": "5.5.5",
"semver": "5.3.0",
"shallowequal": "0.2.2",
"tabbable": "1.1.0"
}
}

@@ -44,18 +44,18 @@ 'use strict';

class Example extends _react.Component {
constructor() {
super();
constructor(...args) {
var _temp;
this._handleChange = change => {
const { invalid } = (0, (_RegExpFilter2 || _load_RegExpFilter2()).getFilterPattern)(change.text, change.isRegExp);
this.setState(Object.assign({}, change, { invalid }));
};
this.state = {
return _temp = super(...args), this.state = {
text: '',
isRegExp: false,
invalid: false
};
}, this._handleChange = change => {
const { invalid } = (0, (_RegExpFilter2 || _load_RegExpFilter2()).getFilterPattern)(change.text, change.isRegExp);
this.setState(Object.assign({}, change, { invalid }));
}, _temp;
}
render() {
const { text, isRegExp, invalid } = this.state;
return _react.createElement(

@@ -67,3 +67,6 @@ 'div',

null,
_react.createElement((_RegExpFilter || _load_RegExpFilter()).default, { value: this.state, onChange: this._handleChange })
_react.createElement((_RegExpFilter || _load_RegExpFilter()).default, {
value: { text, isRegExp, invalid },
onChange: this._handleChange
})
)

@@ -70,0 +73,0 @@ );

@@ -79,3 +79,3 @@ 'use strict';

const inputWidth = this.props.inputWidth == null ? 200 : this.props.inputWidth;
const inputClassName = (0, (_classnames || _load_classnames()).default)('nuclide-ui-regexp-filter-input', this.props.inputClassName, { invalid });
const inputClassName = (0, (_classnames || _load_classnames()).default)('nuclide-ui-regexp-filter-input', this.props.inputClassName);

@@ -89,2 +89,3 @@ return _react.createElement(

},
invalid: invalid,
className: inputClassName,

@@ -91,0 +92,0 @@ size: size,

@@ -52,21 +52,19 @@ 'use strict';

function scrollIntoView(el, alignToTop) {
const scrollTops = getOverflowHiddenScrollTops(el);
const scrollTops = getScrollTops(el);
el.scrollIntoView(alignToTop); // eslint-disable-line rulesdir/dom-apis
restoreScrollTops(scrollTops);
restoreOverflowHiddenScrollTops(scrollTops);
}
function scrollIntoViewIfNeeded(el, center) {
const scrollTops = getOverflowHiddenScrollTops(el);
const scrollTops = getScrollTops(el);
// $FlowIgnore: This should be added to the element type.
el.scrollIntoViewIfNeeded(center); // eslint-disable-line rulesdir/dom-apis
restoreScrollTops(scrollTops);
restoreOverflowHiddenScrollTops(scrollTops);
}
function getOverflowHiddenScrollTops(el_) {
function getScrollTops(el_) {
let el = el_;
const scrollTops = new Map();
while (el != null) {
if (getComputedStyle(el).overflow === 'hidden') {
scrollTops.set(el, el.scrollTop);
}
scrollTops.set(el, el.scrollTop);
el = el.parentElement;

@@ -77,6 +75,14 @@ }

function restoreScrollTops(scrollTops) {
function restoreOverflowHiddenScrollTops(scrollTops) {
scrollTops.forEach((scrollTop, el) => {
el.scrollTop = scrollTop;
if (el.scrollTop !== scrollTop && isOverflowHidden(el)) {
el.scrollTop = scrollTop;
}
});
}
function isOverflowHidden(el) {
const overflowStyle = el.style == null ? null : el.style.overflow;
const overflow = overflowStyle || getComputedStyle(el).overflow;
return overflow === 'hidden';
}

@@ -7,2 +7,4 @@ 'use strict';

exports.Table = undefined;
exports._calculateColumnWidths = _calculateColumnWidths;
exports._calculatePreferredColumnWidths = _calculatePreferredColumnWidths;

@@ -21,8 +23,2 @@ var _nullthrows;

var _idx;
function _load_idx() {
return _idx = _interopRequireDefault(require('idx'));
}
var _react = _interopRequireWildcard(require('react'));

@@ -32,2 +28,8 @@

var _shallowequal;
function _load_shallowequal() {
return _shallowequal = _interopRequireDefault(require('shallowequal'));
}
var _Icon;

@@ -39,2 +41,8 @@

var _collection;
function _load_collection() {
return _collection = require('nuclide-commons/collection');
}
var _UniversalDisposable;

@@ -62,16 +70,14 @@

/**
* Copyright (c) 2017-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
*
* @format
*/
const DEFAULT_MIN_COLUMN_WIDTH = 40; /**
* Copyright (c) 2017-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
*
* @format
*/
const DEFAULT_MIN_COLUMN_WIDTH = 40;
const DefaultEmptyComponent = () => _react.createElement(

@@ -82,3 +88,6 @@ 'div',

);
// Same shape; the separate type is just used for documentation--Flow doesn't recognize a
// difference.
/**

@@ -112,46 +121,10 @@ * Design concerns:

class Table extends _react.Component {
// Active while resizing.
constructor(props) {
super(props);
this._handleResizerGlobalMouseMove = (event, startX, startWidths, location, tableWidth) => {
const pxToRatio = px => px / tableWidth;
const delta = pxToRatio(event.pageX - startX);
const { leftColumnKey, rightColumnKey } = location;
// Determine which column is shrinking and which is growing. This will allow us to apply the min
// width limitations correctly.
let shrinkingColumnKey;
let growingColumnKey;
if (delta < 0) {
[shrinkingColumnKey, growingColumnKey] = [leftColumnKey, rightColumnKey];
} else {
[shrinkingColumnKey, growingColumnKey] = [rightColumnKey, leftColumnKey];
}
const prevShrinkingColumnWidth = startWidths[shrinkingColumnKey];
const prevGrowingColumnWidth = startWidths[growingColumnKey];
const shrinkingColumn = this.props.columns.find(column => column.key === shrinkingColumnKey);
if (!(shrinkingColumn != null)) {
throw new Error('Invariant violation: "shrinkingColumn != null"');
}
const shrinkingColumnMinWidth = pxToRatio(shrinkingColumn.minWidth == null ? DEFAULT_MIN_COLUMN_WIDTH : shrinkingColumn.minWidth);
const nextShrinkingColumnWidth = Math.max(shrinkingColumnMinWidth, prevShrinkingColumnWidth - Math.abs(delta));
const actualChange = nextShrinkingColumnWidth - prevShrinkingColumnWidth;
const nextGrowingColumnWidth = prevGrowingColumnWidth - actualChange;
this.setState({
columnWidths: Object.assign({}, this.state.columnWidths, {
[shrinkingColumnKey]: nextShrinkingColumnWidth,
[growingColumnKey]: nextGrowingColumnWidth
})
});
};
this._resizingDisposable = null;
this._resizeStarts = new _rxjsBundlesRxMinJs.Subject();
this.state = {
columnWidths: null,
preferredColumnWidths: getInitialPreferredColumnWidths(props.columns),
resizeOffset: null,
tableWidth: 0,
usingKeyboard: false

@@ -161,32 +134,21 @@ };

_handleResizerMouseDown(event, resizerLocation) {
if (this._resizingDisposable != null) {
this._stopResizing();
shouldComponentUpdate(nextProps, nextState) {
// If the state changed, we need to re-render.
if (!(0, (_shallowequal || _load_shallowequal()).default)(nextState, this.state)) {
return true;
}
// Prevent browser from initiating drag events on accidentally selected elements.
const selection = document.getSelection();
if (selection != null) {
selection.removeAllRanges();
if (!(0, (_shallowequal || _load_shallowequal()).default)(nextProps, this.props, compareCheapProps)) {
return true;
}
const tableWidth = this.refs.table.getBoundingClientRect().width;
const startX = event.pageX;
const startWidths = this.state.columnWidths;
if (!(startWidths != null)) {
throw new Error('Invariant violation: "startWidths != null"');
if (!(0, (_collection || _load_collection()).arrayEqual)(nextProps.columns, this.props.columns, (_shallowequal || _load_shallowequal()).default)) {
return true;
}
this._resizingDisposable = new (_UniversalDisposable || _load_UniversalDisposable()).default(_rxjsBundlesRxMinJs.Observable.fromEvent(document, 'mousemove').subscribe(evt => {
this._handleResizerGlobalMouseMove(evt, startX, startWidths, resizerLocation, tableWidth);
}), _rxjsBundlesRxMinJs.Observable.fromEvent(document, 'mouseup').subscribe(() => {
this._stopResizing();
}));
}
if (!(0, (_collection || _load_collection()).arrayEqual)(nextProps.rows, this.props.rows)) {
return true;
}
_stopResizing() {
if (this._resizingDisposable == null) {
return;
}
this._resizingDisposable.dispose();
this._resizingDisposable = null;
return false;
}

@@ -197,16 +159,31 @@

this._disposables = new (_UniversalDisposable || _load_UniversalDisposable()).default(new (_observableDom || _load_observableDom()).ResizeObservable(el).startWith(null).map(() => el.offsetWidth).filter(tableWidth => tableWidth > 0).subscribe(tableWidth => {
// Update the column widths to account for minimum widths. This logic could definitely be
// improved. As it is now, if you resize the table to be very small and then make it large
// again, the proportions from when it was at its smallest will be preserved. If no
// columns have min widths, then this is what you want. But if a minimum width prevented
// one or more of the columns from shrinking, you'll probably consider them too wide when
// the table's expanded.
const preferredColumnWidths = this.state.columnWidths || getInitialPercentageWidths(this.props.columns);
this.setState({
columnWidths: ensureMinWidths(preferredColumnWidths, this._getMinWidths(), tableWidth, this.props.columns.map(c => c.key))
});
}), () => {
this._stopResizing();
}, atom.commands.add(el, {
this._disposables = new (_UniversalDisposable || _load_UniversalDisposable()).default(
// Update the column widths when the table is resized.
new (_observableDom || _load_observableDom()).ResizeObservable(el).startWith(null).map(() => el.offsetWidth).filter(tableWidth => tableWidth > 0).subscribe(tableWidth => {
this.setState({ tableWidth });
}), this._resizeStarts.switchMap(({ event: startEvent, resizerLocation }) => {
const startX = startEvent.pageX;
return _rxjsBundlesRxMinJs.Observable.fromEvent(document, 'mousemove').takeUntil(_rxjsBundlesRxMinJs.Observable.fromEvent(document, 'mouseup')).map(event => ({
deltaPx: event.pageX - startX,
resizerLocation
})).concat(_rxjsBundlesRxMinJs.Observable.of(null));
}).subscribe(resizeOffset => {
if (resizeOffset == null) {
// Finalize the resize by updating the user's preferred column widths to account for
// their action. Note that these preferences are only updated when columns are resized
// (NOT when the table is). This is important so that, if the user resizes the table
// such that a column is at its minimum width and then resizes the table back to its
// orignal size, their original column widths are restored.
const preferredColumnWidths = _calculatePreferredColumnWidths({
currentWidths: this._calculateColumnWidths(),
tableWidth: this.state.tableWidth,
minWidths: getMinWidths(this.props.columns)
});
// Update the preferred distributions and end the resize.
this.setState({ preferredColumnWidths, resizeOffset: null });
} else {
this.setState({ resizeOffset });
}
}), atom.commands.add(el, {
'core:move-up': event => {

@@ -243,10 +220,2 @@ this.setState({ usingKeyboard: true });

_getMinWidths() {
const minWidths = {};
this.props.columns.forEach(column => {
minWidths[column.key] = column.minWidth;
});
return minWidths;
}
componentDidUpdate(prevProps, prevState) {

@@ -286,2 +255,15 @@ if (this._tableBody != null && this.props.selectedIndex != null && this.props.selectedIndex !== prevProps.selectedIndex) {

componentWillReceiveProps(nextProps) {
// Did the columns change? If so, we need to recalculate the widths.
const currentColumns = this.props.columns;
const nextColumns = nextProps.columns;
if (nextColumns.length !== currentColumns.length ||
// If the columns just changed order, we want to keep their widths.
!(0, (_collection || _load_collection()).areSetsEqual)(new Set(currentColumns.map(column => column.key)), new Set(nextColumns.map(column => column.key)))) {
this.setState({
preferredColumnWidths: getInitialPreferredColumnWidths(nextColumns)
});
}
}
_moveSelection(offset, event) {

@@ -292,4 +274,4 @@ const { selectedIndex } = this.props;

}
const nextSelectedIndex = selectedIndex + offset;
if (nextSelectedIndex < 0 || nextSelectedIndex >= this.props.rows.length || nextSelectedIndex === selectedIndex) {
const nextSelectedIndex = Math.max(0, Math.min(this.props.rows.length - 1, selectedIndex + offset));
if (nextSelectedIndex === selectedIndex) {
return;

@@ -327,2 +309,13 @@ }

// Just a bound version of the `_calculateColumnWidths` function for convenience.
_calculateColumnWidths() {
return _calculateColumnWidths({
preferredWidths: this.state.preferredColumnWidths,
minWidths: getMinWidths(this.props.columns),
tableWidth: this.state.tableWidth,
columnOrder: this.props.columns.map(column => column.key),
resizeOffset: this.state.resizeOffset
});
}
_renderEmptyCellContent() {

@@ -343,4 +336,3 @@ return _react.createElement('div', null);

_renderContents() {
const { columnWidths } = this.state;
if (columnWidths == null) {
if (this.state.tableWidth === 0) {
// We don't have the table width yet so we can't render the columns.

@@ -353,2 +345,3 @@ return null;

columns,
headerElement,
headerTitle,

@@ -363,21 +356,17 @@ maxBodyHeight,

} = this.props;
const header = headerTitle != null ? _react.createElement(
const columnWidths = this._calculateColumnWidths();
const header = headerElement != null || headerTitle != null ? _react.createElement(
'div',
{ className: 'nuclide-ui-table-header-cell nuclide-ui-table-full-header' },
headerTitle
headerElement != null ? headerElement : headerTitle
) : columns.map((column, i) => {
var _ref;
const { title, key, shouldRightAlign, cellClassName } = column;
const leftColumnKey = column.key;
const rightColumnKey = (_ref = columns[i + 1]) != null ? _ref.key : _ref;
let resizer;
if (leftColumnKey != null && rightColumnKey != null) {
if (i < columns.length - 1) {
resizer = _react.createElement('div', {
className: 'nuclide-ui-table-header-resize-handle',
onMouseDown: event => {
this._handleResizerMouseDown(event, {
leftColumnKey,
rightColumnKey
});
this._resizeStarts.next({ event, resizerLocation: i });
},

@@ -463,6 +452,18 @@ onClick: e => {

onClick: event => {
this._selectRow({ index: i, event });
},
onDoubleClick: event => {
this._selectRow({ index: i, event, confirm: true });
switch (event.detail) {
// This (`event.detail === 0`) shouldn't happen normally but does when the click is
// triggered by the integration test.
case 0:
case 1:
this._selectRow({ index: i, event });
return;
case 2:
// We need to check `event.detail` (instead of using `onDoubleClick`) because
// (for some reason) `onDoubleClick` is only firing sporadically.
// TODO: Figure out why. Repros in the diagnostic table with React 16.0.0 and
// Atom 1.22.0-beta1 (Chrome 56.0.2924.87). This may be because we're swapping out
// the component on the click so a different one is receiving the second?
this._selectRow({ index: i, event, confirm: true });
return;
}
}

@@ -482,2 +483,3 @@ } : {};

}),
'data-row-index': i,
key: i

@@ -497,8 +499,12 @@ }, rowProps),

}
const bodyClassNames = (0, (_classnames || _load_classnames()).default)('nuclide-ui-table', 'nuclide-ui-table-body',
// Using native-key-bindings prevents the up and down arrows from being captured.
{ 'native-key-bindings': !this.props.enableKeyboardNavigation });
const bodyClassNames = (0, (_classnames || _load_classnames()).default)('nuclide-ui-table', 'nuclide-ui-table-body', {
// Using native-key-bindings prevents the up and down arrows from being captured.
'native-key-bindings': !this.props.enableKeyboardNavigation,
// Only enable text selection if the rows aren't selectable as these two things conflict.
// TODO: Add the ability to copy text that doesn't involve text selection within selections.
'nuclide-ui-table-body-selectable-text': !this.props.selectable
});
return [_react.createElement(
'div',
{ key: 'header', className: 'nuclide-ui-table', ref: 'table' },
{ key: 'header', className: 'nuclide-ui-table' },
_react.createElement(

@@ -511,3 +517,15 @@ 'div',

'div',
{ key: 'body', style: scrollableBodyStyle },
{
key: 'body',
style: scrollableBodyStyle,
onFocus: event => {
if (this.props.onBodyFocus != null) {
this.props.onBodyFocus(event);
}
},
onBlur: event => {
if (this.props.onBodyBlur != null) {
this.props.onBodyBlur(event);
}
} },
_react.createElement(

@@ -531,3 +549,3 @@ 'div',

function getInitialPercentageWidths(columns) {
function getInitialPreferredColumnWidths(columns) {
const columnWidthRatios = {};

@@ -552,17 +570,177 @@ let assignedWidth = 0;

function getMinWidths(columns) {
const minWidths = {};
columns.forEach(column => {
minWidths[column.key] = column.minWidth == null ? DEFAULT_MIN_COLUMN_WIDTH : column.minWidth;
});
return minWidths;
}
/**
* Convert percentage widths into actual pixel widths, taking into account minimum widths.
* Calculate widths, taking into account the preferred and minimum widths. Exported for testing
* only.
*/
function ensureMinWidths(preferredWidths, minWidths, tableWidth, columnOrder) {
const adjusted = {};
let remainingWidth = 1;
columnOrder.forEach(columnName => {
const minWidth = minWidths[columnName] || DEFAULT_MIN_COLUMN_WIDTH;
const minWidthRatio = minWidth / tableWidth;
const preferredWidth = preferredWidths[columnName];
const width = Math.min(remainingWidth, Math.max(minWidthRatio, preferredWidth));
adjusted[columnName] = width;
remainingWidth -= width;
function _calculateColumnWidths(options) {
const {
preferredWidths,
minWidths: minWidthsPx,
tableWidth,
columnOrder,
resizeOffset: resizeOffset_
} = options;
const resizeOffset = resizeOffset_ || { deltaPx: 0, resizerLocation: 0 };
const widthsPx = {};
// Calculate the pixel widths of each column given its desired percentage width and minimum pixel
// width.
{
// Figure out how many pixels each column wants, given the current available width.
let widthToAllocate = tableWidth;
let columnsToAllocate = columnOrder;
while (columnsToAllocate.length > 0 && widthToAllocate > 0) {
const remainingPct = columnsToAllocate.map(columnName => preferredWidths[columnName]).reduce((a, b) => a + b, 0);
const desiredWidthsPx = (0, (_collection || _load_collection()).objectFromPairs)(columnsToAllocate.map(columnName => {
const desiredPct = preferredWidths[columnName] / remainingPct;
const desiredPx = Math.round(desiredPct * widthToAllocate);
return [columnName, desiredPx];
}));
// Allocate widths for the columns who want less than their minimum width.
let remainingPx = widthToAllocate;
let remainingColumns = [];
columnsToAllocate.forEach(columnName => {
const desiredPx = desiredWidthsPx[columnName];
const minPx = minWidthsPx[columnName];
if (minPx >= desiredPx) {
widthsPx[columnName] = Math.min(minPx, remainingPx);
remainingPx -= widthsPx[columnName];
} else {
remainingColumns.push(columnName);
}
});
// If we didn't need to truncate any of the columns, give them all their desired width.
if (columnsToAllocate.length === remainingColumns.length) {
Object.assign(widthsPx, desiredWidthsPx);
remainingColumns = [];
}
// If we had to truncate any of the columns, that changes the calculations for how big the
// remaining columns want to be, so make another pass.
widthToAllocate = remainingPx;
columnsToAllocate = remainingColumns;
}
}
{
// Adjust the column widths according to the resized column.
const { deltaPx, resizerLocation } = resizeOffset;
const leftColumns = columnOrder.slice(0, resizerLocation + 1);
const rightColumns = columnOrder.slice(resizerLocation + 1);
const [shrinkingColumns, growingColumn] = deltaPx < 0 ? [leftColumns.reverse(), rightColumns[0]] : [rightColumns, leftColumns[leftColumns.length - 1]];
const targetChange = Math.abs(deltaPx);
let cumulativeChange = 0;
for (const columnName of shrinkingColumns) {
const startWidth = widthsPx[columnName];
const minWidth = minWidthsPx[columnName];
const remainingWidth = targetChange - cumulativeChange;
const newWidth = Math.max(minWidth, startWidth - remainingWidth);
const change = Math.abs(startWidth - newWidth);
cumulativeChange += change;
widthsPx[columnName] = newWidth;
if (cumulativeChange >= targetChange) {
break;
}
}
widthsPx[growingColumn] += cumulativeChange;
}
// Convert all the widths from pixels to percentages.
const widths = {};
{
let remainingWidth = 1;
columnOrder.forEach((columnName, i) => {
const isLastColumn = i === columnOrder.length - 1;
if (isLastColumn) {
// Give the last column all the remaining to account for rounding issues.
widths[columnName] = remainingWidth;
} else {
widths[columnName] = widthsPx[columnName] / tableWidth;
remainingWidth -= widths[columnName];
}
});
}
return widths;
}
/**
* Given the current (percentage) widths of each column, determines what user-preferred distribution
* this represents. Exported for testing only.
*/
function _calculatePreferredColumnWidths(options) {
const { currentWidths, tableWidth, minWidths: minWidthsPx } = options;
const currentWidthsPx = (0, (_collection || _load_collection()).objectMapValues)(currentWidths, w => w * tableWidth);
// If any column is at its minimum width, we take that to mean that the user wants the column
// remain at its minimum if the table is resized (as opposed to maintaining the same percentage).
// Accordingly, we make that column's preferred width 0.
const preferredColumnWidths = {};
// Figure out which columns are at their minimum widths.
let remainingPx = 0; // The width that isn't accounted for after minWidth.
const columnsNotAtMinimum = [];
for (const [columnName, widthPx] of Object.entries(currentWidthsPx)) {
if (!(typeof widthPx === 'number')) {
throw new Error('Invariant violation: "typeof widthPx === \'number\'"');
}
const minWidthPx = minWidthsPx[columnName];
if (Math.floor(widthPx) <= minWidthPx) {
// Keep it at its min-width.
preferredColumnWidths[columnName] = 0;
} else {
remainingPx += widthPx;
columnsNotAtMinimum.push([columnName, widthPx]);
}
}
// Now distribute the widths of the other columns.
let remainingPct = 1;
columnsNotAtMinimum.forEach(([columnName, width], index) => {
const isLastColumn = index === columnsNotAtMinimum.length - 1;
if (isLastColumn) {
// We give the last column the remaining width just to be certain they all add up to 1.
preferredColumnWidths[columnName] = remainingPct;
} else {
preferredColumnWidths[columnName] = width / remainingPx;
remainingPct -= preferredColumnWidths[columnName];
}
});
return adjusted;
return preferredColumnWidths;
}
/**
* An equality check for comparing Props using `shallowEqual()`. This only performs the cheap
* checks and assumes that the rows and columns are equal. (They can be checked separatedly iff
* necessary.)
*/
function compareCheapProps(a, b, key) {
switch (key) {
case undefined:
// This is a magic way of telling `shallowEqual()` to use the default comparison for the
// props objects (inspect its members).
return undefined;
case 'rows':
case 'columns':
// We'll check these later iff we need to since they're more expensive.
return true;
default:
return a === b;
}
}

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

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

Packages

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc