You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@beam.apache.org by pa...@apache.org on 2020/10/01 18:03:58 UTC
[beam] branch master updated: [BEAM-10545] Add 2 show options
This is an automated email from the ASF dual-hosted git repository.
pabloem pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/beam.git
The following commit(s) were added to refs/heads/master by this push:
new 98bb062 [BEAM-10545] Add 2 show options
new 5626c8a Merge pull request #12979 from [BEAM-10545] Add 2 show options
98bb062 is described below
commit 98bb062fbeb8bd165ce3fb657fa72987d813c557
Author: Ning Kang <ni...@google.com>
AuthorDate: Wed Sep 30 14:32:50 2020 -0700
[BEAM-10545] Add 2 show options
1. Added 2 show API options in the side panel: duration and n.
2. Added an `apply` button to alter the behavior of setting show API
options: now the configuration change only takes effect after
clicking the button; previously, the configuration is automatically
applied when clicking a checkbox, but this behavior does not apply
when the configuration now has text inputs.
3. Added `interruptKernelIfNotDone` to the InspectableViewModel and
always execute it when querying the kernel from such model. This made
switching selected item and applying new show API options very
snappy.
---
.../apache-beam-jupyterlab-sidepanel/package.json | 2 +
.../__tests__/inspector/InspectableView.test.tsx | 19 +-
.../inspector/InspectableViewModel.test.ts | 114 ++++++++-
.../src/inspector/InspectableView.tsx | 120 ++++++++-
.../src/inspector/InspectableViewModel.ts | 33 +++
.../style/mdc-theme.css | 9 +
.../apache-beam-jupyterlab-sidepanel/yarn.lock | 270 ++++++++++++++++++++-
7 files changed, 547 insertions(+), 20 deletions(-)
diff --git a/sdks/python/apache_beam/runners/interactive/extensions/apache-beam-jupyterlab-sidepanel/package.json b/sdks/python/apache_beam/runners/interactive/extensions/apache-beam-jupyterlab-sidepanel/package.json
index c70eb79..193e5be 100644
--- a/sdks/python/apache_beam/runners/interactive/extensions/apache-beam-jupyterlab-sidepanel/package.json
+++ b/sdks/python/apache_beam/runners/interactive/extensions/apache-beam-jupyterlab-sidepanel/package.json
@@ -40,6 +40,8 @@
"@rmwc/checkbox": "^6.1.3",
"@rmwc/drawer": "^6.0.14",
"@rmwc/list": "^6.1.3",
+ "@rmwc/textfield": "^6.1.4",
+ "@rmwc/tooltip": "^6.1.4",
"@rmwc/top-app-bar": "^6.1.3",
"material-design-icons": "^3.0.1"
},
diff --git a/sdks/python/apache_beam/runners/interactive/extensions/apache-beam-jupyterlab-sidepanel/src/__tests__/inspector/InspectableView.test.tsx b/sdks/python/apache_beam/runners/interactive/extensions/apache-beam-jupyterlab-sidepanel/src/__tests__/inspector/InspectableView.test.tsx
index 473cfe6..1309ebb 100644
--- a/sdks/python/apache_beam/runners/interactive/extensions/apache-beam-jupyterlab-sidepanel/src/__tests__/inspector/InspectableView.test.tsx
+++ b/sdks/python/apache_beam/runners/interactive/extensions/apache-beam-jupyterlab-sidepanel/src/__tests__/inspector/InspectableView.test.tsx
@@ -73,26 +73,39 @@ it('renders options if inspecting a pcollection', () => {
);
const inspectableView = inspectableViewRef.current;
if (inspectableView) {
- inspectableView.updateRender();
+ inspectableView.setState({
+ options: fakeModel.options
+ });
}
});
const inspectableViewElement: Element = container.firstElementChild;
const optionsElement: Element = inspectableViewElement.firstElementChild;
expect(optionsElement.tagName).toBe('DIV');
- const includeWindowInfoCheckbox: Element = optionsElement.firstElementChild;
+ const includeWindowInfoCheckbox: Element =
+ optionsElement.firstElementChild.firstElementChild;
expect(
includeWindowInfoCheckbox.firstElementChild.getAttribute('class')
).toContain('mdc-checkbox');
expect(
includeWindowInfoCheckbox.firstElementChild.getAttribute('class')
).not.toContain('mdc-checkbox--selected');
- const visualizeInFacetsCheckbox: Element = optionsElement.children[1];
+ const visualizeInFacetsCheckbox: Element =
+ optionsElement.firstElementChild.children[1];
expect(
visualizeInFacetsCheckbox.firstElementChild.getAttribute('class')
).toContain('mdc-checkbox');
expect(
visualizeInFacetsCheckbox.firstElementChild.getAttribute('class')
).toContain('mdc-checkbox--selected');
+ const durationTextField: Element =
+ optionsElement.firstElementChild.children[2];
+ expect(durationTextField.getAttribute('class')).toContain(
+ 'mdc-text-field--outlined'
+ );
+ const nTextField: Element = optionsElement.firstElementChild.children[3];
+ expect(nTextField.getAttribute('class')).toContain(
+ 'mdc-text-field--outlined'
+ );
});
it('renders an html view', () => {
diff --git a/sdks/python/apache_beam/runners/interactive/extensions/apache-beam-jupyterlab-sidepanel/src/__tests__/inspector/InspectableViewModel.test.ts b/sdks/python/apache_beam/runners/interactive/extensions/apache-beam-jupyterlab-sidepanel/src/__tests__/inspector/InspectableViewModel.test.ts
index 540e746..fe624b7 100644
--- a/sdks/python/apache_beam/runners/interactive/extensions/apache-beam-jupyterlab-sidepanel/src/__tests__/inspector/InspectableViewModel.test.ts
+++ b/sdks/python/apache_beam/runners/interactive/extensions/apache-beam-jupyterlab-sidepanel/src/__tests__/inspector/InspectableViewModel.test.ts
@@ -42,18 +42,128 @@ it('builds show_graph query correctly', () => {
);
});
-it('builds show query correctly', () => {
+it('builds show query correctly with default values', () => {
+ const inspectableViewModel = new InspectableViewModel(
+ fakeSessionContext as any
+ );
+ inspectableViewModel.queryKernel('pcollection', 'id');
+ expect(inspectableViewModel.buildShowQuery({} as IShowOptions)).toBe(
+ "ib.show(ie.current_env().inspector.get_val('id')," +
+ 'include_window_info=False, visualize_data=False, ' +
+ "duration='inf', n='inf')"
+ );
+});
+
+it('builds show query with given checkbox values correctly', () => {
const inspectableViewModel = new InspectableViewModel(
fakeSessionContext as any
);
inspectableViewModel.queryKernel('pcollection', 'id');
expect(
inspectableViewModel.buildShowQuery({
+ includeWindowInfo: true,
visualizeInFacets: true
} as IShowOptions)
).toBe(
"ib.show(ie.current_env().inspector.get_val('id')," +
- 'include_window_info=False, visualize_data=True)'
+ 'include_window_info=True, visualize_data=True, ' +
+ "duration='inf', n='inf')"
+ );
+});
+
+it('builds show query with string duration', () => {
+ const inspectableViewModel = new InspectableViewModel(
+ fakeSessionContext as any
+ );
+ inspectableViewModel.queryKernel('pcollection', 'id');
+ expect(
+ inspectableViewModel.buildShowQuery({
+ duration: '60s'
+ } as IShowOptions)
+ ).toBe(
+ "ib.show(ie.current_env().inspector.get_val('id')," +
+ 'include_window_info=False, visualize_data=False, ' +
+ "duration='60s', n='inf')"
+ );
+});
+
+it('builds show query with negative duration as inf', () => {
+ const inspectableViewModel = new InspectableViewModel(
+ fakeSessionContext as any
+ );
+ inspectableViewModel.queryKernel('pcollection', 'id');
+ expect(
+ inspectableViewModel.buildShowQuery({
+ duration: '-1'
+ } as IShowOptions)
+ ).toBe(
+ "ib.show(ie.current_env().inspector.get_val('id')," +
+ 'include_window_info=False, visualize_data=False, ' +
+ "duration='inf', n='inf')"
+ );
+});
+
+it('builds show query with positive duration as int', () => {
+ const inspectableViewModel = new InspectableViewModel(
+ fakeSessionContext as any
+ );
+ inspectableViewModel.queryKernel('pcollection', 'id');
+ expect(
+ inspectableViewModel.buildShowQuery({
+ duration: '5.5'
+ } as IShowOptions)
+ ).toBe(
+ "ib.show(ie.current_env().inspector.get_val('id')," +
+ 'include_window_info=False, visualize_data=False, ' +
+ "duration=5, n='inf')"
+ );
+});
+
+it('builds show query with string n as inf', () => {
+ const inspectableViewModel = new InspectableViewModel(
+ fakeSessionContext as any
+ );
+ inspectableViewModel.queryKernel('pcollection', 'id');
+ expect(
+ inspectableViewModel.buildShowQuery({
+ n: 'abcd'
+ } as IShowOptions)
+ ).toBe(
+ "ib.show(ie.current_env().inspector.get_val('id')," +
+ 'include_window_info=False, visualize_data=False, ' +
+ "duration='inf', n='inf')"
+ );
+});
+
+it('builds show query with negative n as inf', () => {
+ const inspectableViewModel = new InspectableViewModel(
+ fakeSessionContext as any
+ );
+ inspectableViewModel.queryKernel('pcollection', 'id');
+ expect(
+ inspectableViewModel.buildShowQuery({
+ n: '-1'
+ } as IShowOptions)
+ ).toBe(
+ "ib.show(ie.current_env().inspector.get_val('id')," +
+ 'include_window_info=False, visualize_data=False, ' +
+ "duration='inf', n='inf')"
+ );
+});
+
+it('builds show query with positive n as int', () => {
+ const inspectableViewModel = new InspectableViewModel(
+ fakeSessionContext as any
+ );
+ inspectableViewModel.queryKernel('pcollection', 'id');
+ expect(
+ inspectableViewModel.buildShowQuery({
+ n: '5.5'
+ } as IShowOptions)
+ ).toBe(
+ "ib.show(ie.current_env().inspector.get_val('id')," +
+ 'include_window_info=False, visualize_data=False, ' +
+ "duration='inf', n=5)"
);
});
diff --git a/sdks/python/apache_beam/runners/interactive/extensions/apache-beam-jupyterlab-sidepanel/src/inspector/InspectableView.tsx b/sdks/python/apache_beam/runners/interactive/extensions/apache-beam-jupyterlab-sidepanel/src/inspector/InspectableView.tsx
index aead0e7..c04c457 100644
--- a/sdks/python/apache_beam/runners/interactive/extensions/apache-beam-jupyterlab-sidepanel/src/inspector/InspectableView.tsx
+++ b/sdks/python/apache_beam/runners/interactive/extensions/apache-beam-jupyterlab-sidepanel/src/inspector/InspectableView.tsx
@@ -12,7 +12,10 @@
import * as React from 'react';
+import { Button } from '@rmwc/button';
import { Checkbox } from '@rmwc/checkbox';
+import { TextField } from '@rmwc/textfield';
+import { Tooltip } from '@rmwc/tooltip';
import {
InspectableViewModel,
@@ -23,7 +26,10 @@ import { HtmlView } from '../common/HtmlView';
import { IHtmlProvider } from '../common/HtmlView';
import { InterruptKernelButton } from '../kernel/InterruptKernelButton';
+import '@rmwc/button/styles';
import '@rmwc/checkbox/styles';
+import '@rmwc/textfield/styles';
+import '@rmwc/tooltip/styles';
interface IInspectableViewProps {
model: InspectableViewModel;
@@ -31,6 +37,7 @@ interface IInspectableViewProps {
interface IInspectableViewState {
inspectableType: string;
+ identifier: string;
// options used in kernel messaging.
options: IOptions;
}
@@ -38,9 +45,9 @@ interface IInspectableViewState {
/**
* The display area of the InteractiveInspector parent component.
*
- * The react component is composed with a top checkbox section of display
- * options and a main HtmlView area that displays HTML from IOPub messaging of
- * its kernel model.
+ * The react component is composed with a top section of display options and a
+ * main HtmlView area that displays HTML from IOPub messaging of its kernel
+ * model.
*/
export class InspectableView extends React.Component<
IInspectableViewProps,
@@ -49,13 +56,15 @@ export class InspectableView extends React.Component<
constructor(props: IInspectableViewProps) {
super(props);
this.state = {
- inspectableType: 'pipeline',
+ inspectableType: props.model.inspectableType,
+ identifier: props.model.identifier,
options: props.model.options
};
+ this.applyShowOptions = this.applyShowOptions.bind(this);
}
componentDidMount(): void {
- this._updateRenderTimerId = setInterval(() => this.updateRender(), 1500);
+ this._updateRenderTimerId = setInterval(() => this.updateRender(), 1000);
}
componentWillUnmount(): void {
@@ -63,14 +72,20 @@ export class InspectableView extends React.Component<
}
updateRender(): void {
+ // Only self update when there is change in the selected item.
+ if (this.props.model.identifier === this.state.identifier) {
+ return;
+ }
if (this.props.model.inspectableType === 'pcollection') {
this.setState({
inspectableType: 'pcollection',
+ identifier: this.props.model.identifier,
options: this._buildShowOptions(this.props.model.options)
});
} else {
this.setState({
inspectableType: 'pipeline',
+ identifier: this.props.model.identifier,
options: {}
});
}
@@ -81,28 +96,105 @@ export class InspectableView extends React.Component<
return <span />;
}
const showOptions = this._buildShowOptions(this.state.options);
+ const includeWindowInfo = this._renderIncludeWindowInfo(showOptions);
+ const visualizeInFacets = this._renderVisualizeInFacets(showOptions);
+ const duration = this._renderDuration(showOptions);
+ const n = this._renderN(showOptions);
+ return (
+ <div
+ style={{
+ padding: '5px'
+ }}
+ >
+ {includeWindowInfo}
+ {visualizeInFacets}
+ {duration}
+ {n}
+ <Button
+ label="apply"
+ onClick={(): void => this.applyShowOptions(showOptions)}
+ raised
+ />
+ </div>
+ );
+ }
+
+ applyShowOptions(showOptions: IShowOptions): void {
+ this.setState({ options: showOptions });
+ // Back store the new state to the model.
+ this.props.model.options = showOptions;
+ }
+
+ private _renderIncludeWindowInfo(showOptions: IShowOptions): React.ReactNode {
return (
- <React.Fragment>
+ <Tooltip content="Whether to include window info.">
<Checkbox
- label="window info"
+ label="Include Window Info"
checked={showOptions.includeWindowInfo}
onChange={(e): void => {
showOptions.includeWindowInfo = !!e.currentTarget.checked;
this.setState({ options: showOptions });
- // Back store the new state to the model.
- this.props.model.options = showOptions;
}}
/>
+ </Tooltip>
+ );
+ }
+
+ private _renderVisualizeInFacets(showOptions: IShowOptions): React.ReactNode {
+ return (
+ <Tooltip content="Whether to visualize the data in Facets.">
<Checkbox
- label="facets"
+ label="Visualize in Facets"
checked={showOptions.visualizeInFacets}
onChange={(e): void => {
showOptions.visualizeInFacets = !!e.currentTarget.checked;
this.setState({ options: showOptions });
- this.props.model.options = showOptions;
}}
/>
- </React.Fragment>
+ </Tooltip>
+ );
+ }
+
+ private _renderDuration(showOptions: IShowOptions): React.ReactNode {
+ const tooltip =
+ 'Max duration of elements to read in integer seconds or ' +
+ 'a string duration that is parsable by pandas.to_timedelta, such as 1m ' +
+ 'or 60s. Otherwise, default value `inf` is used: the visualization ' +
+ 'will never end until manually stopped by interrupting the kernel or ' +
+ 'reaches a hard cap set by ib.options.capture_size_limit.';
+ return (
+ <Tooltip content={tooltip}>
+ <TextField
+ outlined
+ label="Duration"
+ floatLabel
+ placeholder={showOptions.duration}
+ onChange={(e): void => {
+ showOptions.duration = e.currentTarget.value;
+ }}
+ />
+ </Tooltip>
+ );
+ }
+
+ private _renderN(showOptions: IShowOptions): React.ReactNode {
+ const tooltip =
+ 'Max number of elements to visualize. Please fill in a ' +
+ 'positive integer. Otherwise, default value `inf` is used: the ' +
+ 'visualization will never end until manually stopped by interrupting ' +
+ 'the kernel or reaches a hard cap set by ib.options.capture_duration.';
+ return (
+ <Tooltip content={tooltip}>
+ <TextField
+ outlined
+ label="Element Number"
+ floatLabel
+ placeholder={showOptions.n}
+ onChange={(e): void => {
+ showOptions.n = e.currentTarget.value;
+ }}
+ />
+ </Tooltip>
);
}
@@ -122,7 +214,9 @@ export class InspectableView extends React.Component<
const optionsInput = options as IShowOptions;
return {
includeWindowInfo: !!optionsInput?.includeWindowInfo,
- visualizeInFacets: !!optionsInput?.visualizeInFacets
+ visualizeInFacets: !!optionsInput?.visualizeInFacets,
+ duration: optionsInput?.duration,
+ n: optionsInput?.n
} as IShowOptions;
}
diff --git a/sdks/python/apache_beam/runners/interactive/extensions/apache-beam-jupyterlab-sidepanel/src/inspector/InspectableViewModel.ts b/sdks/python/apache_beam/runners/interactive/extensions/apache-beam-jupyterlab-sidepanel/src/inspector/InspectableViewModel.ts
index fea9720..4dd115b 100644
--- a/sdks/python/apache_beam/runners/interactive/extensions/apache-beam-jupyterlab-sidepanel/src/inspector/InspectableViewModel.ts
+++ b/sdks/python/apache_beam/runners/interactive/extensions/apache-beam-jupyterlab-sidepanel/src/inspector/InspectableViewModel.ts
@@ -19,6 +19,8 @@ import { KernelModel } from '../kernel/KernelModel';
export interface IShowOptions {
includeWindowInfo?: boolean;
visualizeInFacets?: boolean;
+ duration?: string;
+ n?: string;
}
// Options depend on the inspectableType. Currently only one variation of
@@ -63,6 +65,30 @@ export class InspectableViewModel implements IHtmlProvider {
} else {
optionsAsString += 'visualize_data=False';
}
+ optionsAsString += ', ';
+ if (!options.duration) {
+ options.duration = 'inf';
+ }
+ const durationNum = Number(options.duration);
+ if (isNaN(durationNum)) {
+ optionsAsString += `duration='${options.duration}'`;
+ } else if (durationNum <= 0) {
+ options.duration = 'inf';
+ optionsAsString += "duration='inf'";
+ } else {
+ options.duration = Math.floor(durationNum).toString(10);
+ optionsAsString += 'duration=' + Math.floor(durationNum);
+ }
+ optionsAsString += ', ';
+ const nNum = Number(options.n);
+ const nInt = Math.floor(nNum);
+ if (isNaN(nNum) || nInt <= 0) {
+ options.n = 'inf';
+ optionsAsString += "n='inf'";
+ } else {
+ options.n = nInt.toString(10);
+ optionsAsString += 'n=' + nInt;
+ }
return (
'ib.show(' +
`ie.current_env().inspector.get_val('${this._identifier}'),` +
@@ -75,11 +101,18 @@ export class InspectableViewModel implements IHtmlProvider {
return this._model;
}
+ interruptKernelIfNotDone(): void {
+ if (!this._model.isDone) {
+ this._model.interruptKernel();
+ }
+ }
+
queryKernel(
inspectableType: string,
identifier: string,
options: IOptions = {}
): void {
+ this.interruptKernelIfNotDone();
this._inspectableType = inspectableType.toLowerCase();
this._identifier = identifier;
this._options = options;
diff --git a/sdks/python/apache_beam/runners/interactive/extensions/apache-beam-jupyterlab-sidepanel/style/mdc-theme.css b/sdks/python/apache_beam/runners/interactive/extensions/apache-beam-jupyterlab-sidepanel/style/mdc-theme.css
index f3f009c..b6383f9 100644
--- a/sdks/python/apache_beam/runners/interactive/extensions/apache-beam-jupyterlab-sidepanel/style/mdc-theme.css
+++ b/sdks/python/apache_beam/runners/interactive/extensions/apache-beam-jupyterlab-sidepanel/style/mdc-theme.css
@@ -48,3 +48,12 @@
.mdc-drawer li.mdc-list-item--activated {
color: var(--jp-ui-font-color1);
}
+
+.mdc-form-field > label {
+ margin-bottom: 0;
+}
+
+.mdc-text-field {
+ margin-left: 4px;
+ margin-right: 4px;
+}
diff --git a/sdks/python/apache_beam/runners/interactive/extensions/apache-beam-jupyterlab-sidepanel/yarn.lock b/sdks/python/apache_beam/runners/interactive/extensions/apache-beam-jupyterlab-sidepanel/yarn.lock
index 277ed70..7e4f530 100644
--- a/sdks/python/apache_beam/runners/interactive/extensions/apache-beam-jupyterlab-sidepanel/yarn.lock
+++ b/sdks/python/apache_beam/runners/interactive/extensions/apache-beam-jupyterlab-sidepanel/yarn.lock
@@ -1105,6 +1105,20 @@
resolved "https://registry.yarnpkg.com/@material/feature-targeting/-/feature-targeting-5.1.0.tgz#49265bbd4ff59b1cd20a385b5547f7c246cb1955"
integrity sha512-z3JNWF7lP9WOzw1xBwul/HAOu4qC6EpK/8MkhjLNI9APvdYML82PWS1V0k0MiqA6Jk6uxm8DiVAk9VUqBa9/YA==
+"@material/floating-label@^5.1.0":
+ version "5.1.0"
+ resolved "https://registry.yarnpkg.com/@material/floating-label/-/floating-label-5.1.0.tgz#8d654b3f2ca98248e5a73a63feec8f4523c5ab4f"
+ integrity sha512-5EwPiBa5A4Q678tNWdkkBGDdSCDzudhVgBtRiA/7xRo4dHXiBxX5bhE+RHrF3ZQyEf6fsShspqwAFkTA1EaplQ==
+ dependencies:
+ "@material/animation" "^5.1.0"
+ "@material/base" "^5.1.0"
+ "@material/dom" "^5.1.0"
+ "@material/feature-targeting" "^5.1.0"
+ "@material/rtl" "^5.1.0"
+ "@material/theme" "^5.1.0"
+ "@material/typography" "^5.1.0"
+ tslib "^1.9.3"
+
"@material/form-field@^5.1.0":
version "5.1.0"
resolved "https://registry.yarnpkg.com/@material/form-field/-/form-field-5.1.0.tgz#91bf81cb4647d655b7459df0aa19060189f55564"
@@ -1130,6 +1144,17 @@
"@material/theme" "^5.1.0"
tslib "^1.9.3"
+"@material/line-ripple@^5.1.0":
+ version "5.1.0"
+ resolved "https://registry.yarnpkg.com/@material/line-ripple/-/line-ripple-5.1.0.tgz#86cb1b8a91bf010231109211b8eb38ad059f5f23"
+ integrity sha512-esf2/ROZl1eVpyGCWPvxMSGVkuIOG5Fm6qufOLp7XIx5IL1O0bsm+bV6cVC4JCCtmNOag4GOBgkKKbkOvp/R6g==
+ dependencies:
+ "@material/animation" "^5.1.0"
+ "@material/base" "^5.1.0"
+ "@material/feature-targeting" "^5.1.0"
+ "@material/theme" "^5.1.0"
+ tslib "^1.9.3"
+
"@material/list@^5.1.0":
version "5.1.0"
resolved "https://registry.yarnpkg.com/@material/list/-/list-5.1.0.tgz#04c010e393c88c7da2091426fd12b8206585c37e"
@@ -1146,6 +1171,19 @@
"@material/typography" "^5.1.0"
tslib "^1.9.3"
+"@material/notched-outline@^5.1.0":
+ version "5.1.0"
+ resolved "https://registry.yarnpkg.com/@material/notched-outline/-/notched-outline-5.1.0.tgz#4ec97001ed6bbb66f04100b7745ae99d19a4d16e"
+ integrity sha512-mQ3NjJR1jLXnJi6jhs20ftTf0yU1gWpYlyx1GizU0f7pLEqcIrFnw6G+pavcnKqP+JXNkzAQeGbmZvYBQnxokA==
+ dependencies:
+ "@material/base" "^5.1.0"
+ "@material/feature-targeting" "^5.1.0"
+ "@material/floating-label" "^5.1.0"
+ "@material/rtl" "^5.1.0"
+ "@material/shape" "^5.1.0"
+ "@material/theme" "^5.1.0"
+ tslib "^1.9.3"
+
"@material/ripple@^5.1.0":
version "5.1.0"
resolved "https://registry.yarnpkg.com/@material/ripple/-/ripple-5.1.0.tgz#6624e0ff7718d6bfa65fecd0bca4c03d2696c07b"
@@ -1171,6 +1209,26 @@
"@material/feature-targeting" "^5.1.0"
"@material/rtl" "^5.1.0"
+"@material/textfield@^5.1.0":
+ version "5.1.0"
+ resolved "https://registry.yarnpkg.com/@material/textfield/-/textfield-5.1.0.tgz#75f68c62dc916116330a4c958ba3866c87bd6002"
+ integrity sha512-Vipvw75AXj4G/BGXv3DyrGozbvHxGtcNGig1e5pz1ERvcmZN5epLyGStznxEIZYNf0Q+6O/NwSRxZGgrdI2w8w==
+ dependencies:
+ "@material/animation" "^5.1.0"
+ "@material/base" "^5.1.0"
+ "@material/density" "^5.1.0"
+ "@material/dom" "^5.1.0"
+ "@material/feature-targeting" "^5.1.0"
+ "@material/floating-label" "^5.1.0"
+ "@material/line-ripple" "^5.1.0"
+ "@material/notched-outline" "^5.1.0"
+ "@material/ripple" "^5.1.0"
+ "@material/rtl" "^5.1.0"
+ "@material/shape" "^5.1.0"
+ "@material/theme" "^5.1.0"
+ "@material/typography" "^5.1.0"
+ tslib "^1.9.3"
+
"@material/theme@^5.1.0":
version "5.1.0"
resolved "https://registry.yarnpkg.com/@material/theme/-/theme-5.1.0.tgz#013c37d055afc5d4045c77e44c9fd1f940ff865b"
@@ -1222,6 +1280,19 @@
mutation-observer "^1.0.3"
tslib "^1.10.0"
+"@rmwc/base@^6.1.4":
+ version "6.1.4"
+ resolved "https://registry.yarnpkg.com/@rmwc/base/-/base-6.1.4.tgz#0e6a132eee28e0f0e1dd409fc917b8b035754a02"
+ integrity sha512-8HOKn+Dt+lVCat0Ug9aY0EorshuvM2gG1tQqT6+/m2IzqGhCL0mN5swxnOMWH0RD0K/XVa2CM1NyEd558/RvTA==
+ dependencies:
+ "@material/dom" "^5.1.0"
+ "@rmwc/types" "^6.0.5"
+ "@types/classnames" "^2.2.7"
+ classnames "^2.2.6"
+ hyperform "^0.11.0"
+ mutation-observer "^1.0.3"
+ tslib "^1.10.0"
+
"@rmwc/button@^6.1.3":
version "6.1.3"
resolved "https://registry.yarnpkg.com/@rmwc/button/-/button-6.1.3.tgz#87e84b32e706dd986b1b56f32c19beac09aab06c"
@@ -1256,6 +1327,15 @@
"@rmwc/base" "^6.0.14"
"@rmwc/types" "^6.0.5"
+"@rmwc/floating-label@^6.1.4":
+ version "6.1.4"
+ resolved "https://registry.yarnpkg.com/@rmwc/floating-label/-/floating-label-6.1.4.tgz#02976c4685f8425e72c8a1725a5343ca2cde934a"
+ integrity sha512-X0FZGlh81VetIdiDapdSdB6JAhZRPBGXfHIzBd6F4y7ta4/V0kQo+Nv1kaq88jRMY/ROr6XwG7sMWDiM2joRrQ==
+ dependencies:
+ "@material/floating-label" "^5.1.0"
+ "@rmwc/base" "^6.1.4"
+ "@rmwc/types" "^6.0.5"
+
"@rmwc/formfield@^6.0.14":
version "6.0.14"
resolved "https://registry.yarnpkg.com/@rmwc/formfield/-/formfield-6.0.14.tgz#0ce4a091b1b2851f60340874793e5336de8d1ab5"
@@ -1285,6 +1365,24 @@
"@rmwc/provider" "^6.1.3"
"@rmwc/types" "^6.0.5"
+"@rmwc/icon@^6.1.4":
+ version "6.1.4"
+ resolved "https://registry.yarnpkg.com/@rmwc/icon/-/icon-6.1.4.tgz#59ecfe641228b2f5d5d3ada7f22ff255bb9f9418"
+ integrity sha512-y+qhbXqHsuXYa1kQPrkSlMG/0S6GIlEpT/nQwKpGjz2FXiwxikeiYZ6siXLVK6Y3uFiOCA7gbGGsd9BMDWljxg==
+ dependencies:
+ "@rmwc/base" "^6.1.4"
+ "@rmwc/provider" "^6.1.4"
+ "@rmwc/types" "^6.0.5"
+
+"@rmwc/line-ripple@^6.1.4":
+ version "6.1.4"
+ resolved "https://registry.yarnpkg.com/@rmwc/line-ripple/-/line-ripple-6.1.4.tgz#fa8cf24207aa1e45360ce9a36c20f644d7b0479b"
+ integrity sha512-lynjPp436hDrhspPFGzzqzUidsMS+D+zwSnH6G527Le7wEYjx13r2x3zCJ2tHVJWx6oxmJti+Y0QyvtPu0ehbQ==
+ dependencies:
+ "@material/line-ripple" "^5.1.0"
+ "@rmwc/base" "^6.1.4"
+ "@rmwc/types" "^6.0.5"
+
"@rmwc/list@^6.1.3":
version "6.1.3"
resolved "https://registry.yarnpkg.com/@rmwc/list/-/list-6.1.3.tgz#854abdc83cf4ccbd6b476b43711e0454e068eca8"
@@ -1297,6 +1395,15 @@
"@rmwc/ripple" "^6.1.3"
"@rmwc/types" "^6.0.5"
+"@rmwc/notched-outline@^6.1.4":
+ version "6.1.4"
+ resolved "https://registry.yarnpkg.com/@rmwc/notched-outline/-/notched-outline-6.1.4.tgz#479d77b698a2cd060b8802d9be0e50d864fe42b8"
+ integrity sha512-Q5INGaSwBu6ceARw/kLIBzsWKN99LICFPDVYL02eJaeOwgCRfuL1Y7ot3m7BA0Dnh7ggWFHkTXeIH8T5kqXEXw==
+ dependencies:
+ "@material/notched-outline" "^5.1.0"
+ "@rmwc/base" "^6.1.4"
+ "@rmwc/types" "^6.0.5"
+
"@rmwc/provider@^6.1.3":
version "6.1.3"
resolved "https://registry.yarnpkg.com/@rmwc/provider/-/provider-6.1.3.tgz#5f31f8413ba688a91d140d7a6afbadc3d1c0ca84"
@@ -1305,6 +1412,14 @@
"@rmwc/base" "^6.0.14"
"@rmwc/types" "^6.0.5"
+"@rmwc/provider@^6.1.4":
+ version "6.1.4"
+ resolved "https://registry.yarnpkg.com/@rmwc/provider/-/provider-6.1.4.tgz#8af9d629df4fc045a68e94d019bbcb5cf7f9120e"
+ integrity sha512-883PclFrzv6KL/2R613/zdBDZe2d5nAWkT8PEU5z9ddWhOG95sJVj2/uuTc2M/l/vnstOI5YtmkbFvYYVd4XBQ==
+ dependencies:
+ "@rmwc/base" "^6.1.4"
+ "@rmwc/types" "^6.0.5"
+
"@rmwc/ripple@^6.1.3":
version "6.1.3"
resolved "https://registry.yarnpkg.com/@rmwc/ripple/-/ripple-6.1.3.tgz#a91ef5422f34a563d6024cc21f98abaadf819261"
@@ -1315,6 +1430,30 @@
"@rmwc/provider" "^6.1.3"
"@rmwc/types" "^6.0.5"
+"@rmwc/ripple@^6.1.4":
+ version "6.1.4"
+ resolved "https://registry.yarnpkg.com/@rmwc/ripple/-/ripple-6.1.4.tgz#cf25b93ef141de26cf643bcaf589a345615c4021"
+ integrity sha512-bWir1kCOC8h0Dr7/wk89vkZ2icfMbObYk+/1cznukRy7m5QmUvFHFKrUFANT1Qk1w6yFxXG9qZrbnXI22c23MA==
+ dependencies:
+ "@material/ripple" "^5.1.0"
+ "@rmwc/base" "^6.1.4"
+ "@rmwc/provider" "^6.1.4"
+ "@rmwc/types" "^6.0.5"
+
+"@rmwc/textfield@^6.1.4":
+ version "6.1.4"
+ resolved "https://registry.yarnpkg.com/@rmwc/textfield/-/textfield-6.1.4.tgz#158ab1e599f83b64d1a821228749e360c14b21f4"
+ integrity sha512-K3b/exjDnHe5Lw8y8gzZ8u6O1EKOFv3Xiz4vy47TzchzOaQRHT6n0D87nACz30K1jROuaFirsUFI5z1i1Nk+Lw==
+ dependencies:
+ "@material/textfield" "^5.1.0"
+ "@rmwc/base" "^6.1.4"
+ "@rmwc/floating-label" "^6.1.4"
+ "@rmwc/icon" "^6.1.4"
+ "@rmwc/line-ripple" "^6.1.4"
+ "@rmwc/notched-outline" "^6.1.4"
+ "@rmwc/ripple" "^6.1.4"
+ "@rmwc/types" "^6.0.5"
+
"@rmwc/toggleable@^6.0.14":
version "6.0.14"
resolved "https://registry.yarnpkg.com/@rmwc/toggleable/-/toggleable-6.0.14.tgz#1eca45f278aa2e808190be385ac29d494057a554"
@@ -1324,6 +1463,15 @@
"@rmwc/formfield" "^6.0.14"
"@rmwc/types" "^6.0.5"
+"@rmwc/tooltip@^6.1.4":
+ version "6.1.4"
+ resolved "https://registry.yarnpkg.com/@rmwc/tooltip/-/tooltip-6.1.4.tgz#f228c61145e4502c12aae64198ea70145ae3fb28"
+ integrity sha512-HPgEw2vqvJpHXefx+IuTHA6+MlrRV8M8NQAVWUJlc7PG3anF62Bg01Xy0FqWJ9D1FbDSYGE05DSmbTEbd3nboA==
+ dependencies:
+ "@rmwc/base" "^6.1.4"
+ "@rmwc/provider" "^6.1.4"
+ rc-tooltip "3.7.3"
+
"@rmwc/top-app-bar@^6.1.3":
version "6.1.3"
resolved "https://registry.yarnpkg.com/@rmwc/top-app-bar/-/top-app-bar-6.1.3.tgz#235434cfaa2a9af72642e8d834712b2abfb87787"
@@ -1570,6 +1718,13 @@ acorn@^7.1.1:
resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.3.1.tgz#85010754db53c3fbaf3b9ea3e083aa5c5d147ffd"
integrity sha512-tLc0wSnatxAQHVHUapaHdz72pi9KUyHjq5KyHjGg9Y8Ifdc79pTh2XvI6I1/chZbnM7QtNKzh66ooDogPZSleA==
+add-dom-event-listener@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/add-dom-event-listener/-/add-dom-event-listener-1.1.0.tgz#6a92db3a0dd0abc254e095c0f1dc14acbbaae310"
+ integrity sha512-WCxx1ixHT0GQU9hb0KI/mhgRQhnU+U3GvwY6ZvVjYq8rsihIGoaIOUbY0yMPBxLH5MDtr0kz3fisWGNcbWW7Jw==
+ dependencies:
+ object-assign "4.x"
+
ajv@^6.10.0, ajv@^6.10.2, ajv@^6.5.5:
version "6.12.3"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.3.tgz#18c5af38a111ddeb4f2697bd78d68abc1cabd706"
@@ -1780,6 +1935,14 @@ babel-preset-jest@^26.1.0:
babel-plugin-jest-hoist "^26.1.0"
babel-preset-current-node-syntax "^0.1.2"
+babel-runtime@6.x, babel-runtime@^6.26.0:
+ version "6.26.0"
+ resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe"
+ integrity sha1-llxwWGaOgrVde/4E/yM3vItWR/4=
+ dependencies:
+ core-js "^2.4.0"
+ regenerator-runtime "^0.11.0"
+
balanced-match@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
@@ -2032,11 +2195,23 @@ combined-stream@^1.0.6, combined-stream@~1.0.6:
dependencies:
delayed-stream "~1.0.0"
+component-classes@^1.2.5:
+ version "1.2.6"
+ resolved "https://registry.yarnpkg.com/component-classes/-/component-classes-1.2.6.tgz#c642394c3618a4d8b0b8919efccbbd930e5cd691"
+ integrity sha1-xkI5TDYYpNiwuJGe/Mu9kw5c1pE=
+ dependencies:
+ component-indexof "0.0.3"
+
component-emitter@^1.2.1:
version "1.3.0"
resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0"
integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==
+component-indexof@0.0.3:
+ version "0.0.3"
+ resolved "https://registry.yarnpkg.com/component-indexof/-/component-indexof-0.0.3.tgz#11d091312239eb8f32c8f25ae9cb002ffe8d3c24"
+ integrity sha1-EdCRMSI5648yyPJa6csAL/6NPCQ=
+
concat-map@0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
@@ -2054,6 +2229,11 @@ copy-descriptor@^0.1.0:
resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d"
integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=
+core-js@^2.4.0:
+ version "2.6.11"
+ resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.11.tgz#38831469f9922bded8ee21c9dc46985e0399308c"
+ integrity sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg==
+
core-util-is@1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
@@ -2087,6 +2267,14 @@ cross-spawn@^7.0.0:
shebang-command "^2.0.0"
which "^2.0.1"
+css-animation@^1.3.2:
+ version "1.6.1"
+ resolved "https://registry.yarnpkg.com/css-animation/-/css-animation-1.6.1.tgz#162064a3b0d51f958b7ff37b3d6d4de18e17039e"
+ integrity sha512-/48+/BaEaHRY6kNQ2OIPzKf9A6g8WjZYjhiNDNuIVbsm5tXCGIAsHDjB4Xu1C4vXJtUWZo26O68OQkDpNBaPog==
+ dependencies:
+ babel-runtime "6.x"
+ component-classes "^1.2.5"
+
cssom@^0.4.4:
version "0.4.4"
resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.4.4.tgz#5a66cf93d2d0b661d80bf6a44fb65f5c2e4e0a10"
@@ -2244,6 +2432,11 @@ doctrine@^3.0.0:
dependencies:
esutils "^2.0.2"
+dom-align@^1.7.0:
+ version "1.12.0"
+ resolved "https://registry.yarnpkg.com/dom-align/-/dom-align-1.12.0.tgz#56fb7156df0b91099830364d2d48f88963f5a29c"
+ integrity sha512-YkoezQuhp3SLFGdOlr5xkqZ640iXrnHAwVYcDg8ZKRUtO7mSzSC2BA5V0VuyAwPSJA4CLIc6EDDJh4bEsD2+zA==
+
dom-helpers@^3.4.0:
version "3.4.0"
resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-3.4.0.tgz#e9b369700f959f62ecde5a6babde4bccd9169af8"
@@ -4177,7 +4370,7 @@ oauth-sign@~0.9.0:
resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455"
integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==
-object-assign@^4.1.1:
+object-assign@4.x, object-assign@^4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=
@@ -4472,7 +4665,7 @@ prompts@^2.0.1:
kleur "^3.0.3"
sisteransi "^1.0.4"
-prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2:
+prop-types@15.x, prop-types@^15.5.10, prop-types@^15.5.8, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2:
version "15.7.2"
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5"
integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==
@@ -4509,6 +4702,69 @@ querystringify@^2.1.1:
resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.1.1.tgz#60e5a5fd64a7f8bfa4d2ab2ed6fdf4c85bad154e"
integrity sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA==
+raf@^3.4.0:
+ version "3.4.1"
+ resolved "https://registry.yarnpkg.com/raf/-/raf-3.4.1.tgz#0742e99a4a6552f445d73e3ee0328af0ff1ede39"
+ integrity sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==
+ dependencies:
+ performance-now "^2.1.0"
+
+rc-align@^2.4.0:
+ version "2.4.5"
+ resolved "https://registry.yarnpkg.com/rc-align/-/rc-align-2.4.5.tgz#c941a586f59d1017f23a428f0b468663fb7102ab"
+ integrity sha512-nv9wYUYdfyfK+qskThf4BQUSIadeI/dCsfaMZfNEoxm9HwOIioQ+LyqmMK6jWHAZQgOzMLaqawhuBXlF63vgjw==
+ dependencies:
+ babel-runtime "^6.26.0"
+ dom-align "^1.7.0"
+ prop-types "^15.5.8"
+ rc-util "^4.0.4"
+
+rc-animate@2.x:
+ version "2.11.1"
+ resolved "https://registry.yarnpkg.com/rc-animate/-/rc-animate-2.11.1.tgz#2666eeb6f1f2a495a13b2af09e236712278fdb2c"
+ integrity sha512-1NyuCGFJG/0Y+9RKh5y/i/AalUCA51opyyS/jO2seELpgymZm2u9QV3xwODwEuzkmeQ1BDPxMLmYLcTJedPlkQ==
+ dependencies:
+ babel-runtime "6.x"
+ classnames "^2.2.6"
+ css-animation "^1.3.2"
+ prop-types "15.x"
+ raf "^3.4.0"
+ rc-util "^4.15.3"
+ react-lifecycles-compat "^3.0.4"
+
+rc-tooltip@3.7.3:
+ version "3.7.3"
+ resolved "https://registry.yarnpkg.com/rc-tooltip/-/rc-tooltip-3.7.3.tgz#280aec6afcaa44e8dff0480fbaff9e87fc00aecc"
+ integrity sha512-dE2ibukxxkrde7wH9W8ozHKUO4aQnPZ6qBHtrTH9LoO836PjDdiaWO73fgPB05VfJs9FbZdmGPVEbXCeOP99Ww==
+ dependencies:
+ babel-runtime "6.x"
+ prop-types "^15.5.8"
+ rc-trigger "^2.2.2"
+
+rc-trigger@^2.2.2:
+ version "2.6.5"
+ resolved "https://registry.yarnpkg.com/rc-trigger/-/rc-trigger-2.6.5.tgz#140a857cf28bd0fa01b9aecb1e26a50a700e9885"
+ integrity sha512-m6Cts9hLeZWsTvWnuMm7oElhf+03GOjOLfTuU0QmdB9ZrW7jR2IpI5rpNM7i9MvAAlMAmTx5Zr7g3uu/aMvZAw==
+ dependencies:
+ babel-runtime "6.x"
+ classnames "^2.2.6"
+ prop-types "15.x"
+ rc-align "^2.4.0"
+ rc-animate "2.x"
+ rc-util "^4.4.0"
+ react-lifecycles-compat "^3.0.4"
+
+rc-util@^4.0.4, rc-util@^4.15.3, rc-util@^4.4.0:
+ version "4.21.1"
+ resolved "https://registry.yarnpkg.com/rc-util/-/rc-util-4.21.1.tgz#88602d0c3185020aa1053d9a1e70eac161becb05"
+ integrity sha512-Z+vlkSQVc1l8O2UjR3WQ+XdWlhj5q9BMQNLk2iOBch75CqPfrJyGtcWMcnhRlNuDu0Ndtt4kLVO8JI8BrABobg==
+ dependencies:
+ add-dom-event-listener "^1.1.0"
+ prop-types "^15.5.10"
+ react-is "^16.12.0"
+ react-lifecycles-compat "^3.0.4"
+ shallowequal "^1.1.0"
+
react-dom@^16.13.1:
version "16.13.1"
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.13.1.tgz#c1bd37331a0486c078ee54c4740720993b2e0e7f"
@@ -4599,6 +4855,11 @@ readable-stream@^3.1.1:
string_decoder "^1.1.1"
util-deprecate "^1.0.1"
+regenerator-runtime@^0.11.0:
+ version "0.11.1"
+ resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9"
+ integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==
+
regenerator-runtime@^0.13.4:
version "0.13.5"
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz#d878a1d094b4306d10b9096484b33ebd55e26697"
@@ -4893,6 +5154,11 @@ set-value@^2.0.0, set-value@^2.0.1:
is-plain-object "^2.0.3"
split-string "^3.0.1"
+shallowequal@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/shallowequal/-/shallowequal-1.1.0.tgz#188d521de95b9087404fd4dcb68b13df0ae4e7f8"
+ integrity sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==
+
shebang-command@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea"