mirror of
https://github.com/quine-global/hyper.git
synced 2026-01-12 20:18:41 -09:00
port remaining js components to ts
This commit is contained in:
parent
4a3132b8e7
commit
78ec88d1e8
8 changed files with 170 additions and 83 deletions
|
|
@ -1,6 +1,7 @@
|
|||
import React from 'react';
|
||||
import {SearchBoxProps} from '../hyper';
|
||||
|
||||
const searchBoxStyling = {
|
||||
const searchBoxStyling: React.CSSProperties = {
|
||||
float: 'right',
|
||||
height: '28px',
|
||||
backgroundColor: 'white',
|
||||
|
|
@ -8,21 +9,22 @@ const searchBoxStyling = {
|
|||
right: '10px',
|
||||
top: '25px',
|
||||
width: '224px',
|
||||
zIndex: '9999'
|
||||
zIndex: 9999
|
||||
};
|
||||
|
||||
const enterKey = 13;
|
||||
|
||||
export default class SearchBox extends React.PureComponent {
|
||||
constructor(props) {
|
||||
export default class SearchBox extends React.PureComponent<SearchBoxProps> {
|
||||
searchTerm: string;
|
||||
constructor(props: SearchBoxProps) {
|
||||
super(props);
|
||||
this.searchTerm = '';
|
||||
}
|
||||
|
||||
handleChange = event => {
|
||||
this.searchTerm = event.target.value;
|
||||
handleChange = (event: React.KeyboardEvent<HTMLInputElement>) => {
|
||||
this.searchTerm = event.currentTarget.value;
|
||||
if (event.keyCode === enterKey) {
|
||||
this.props.search(event.target.value);
|
||||
this.props.search(event.currentTarget.value);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -1,15 +1,18 @@
|
|||
import React from 'react';
|
||||
import {Terminal} from 'xterm';
|
||||
import {Terminal, ITerminalOptions, IDisposable} from 'xterm';
|
||||
import {FitAddon} from 'xterm-addon-fit';
|
||||
import {WebLinksAddon} from 'xterm-addon-web-links';
|
||||
import {SearchAddon} from 'xterm-addon-search';
|
||||
import {WebglAddon} from 'xterm-addon-webgl';
|
||||
import {LigaturesAddon} from 'xterm-addon-ligatures';
|
||||
import {clipboard} from 'electron';
|
||||
import * as Color from 'color';
|
||||
import Color from 'color';
|
||||
import terms from '../terms';
|
||||
import processClipboard from '../utils/paste';
|
||||
import SearchBox from './searchBox';
|
||||
import ResizeObserver from 'resize-observer-polyfill';
|
||||
import {TermProps} from '../hyper';
|
||||
import {ObjectTypedKeys} from '../utils/object';
|
||||
|
||||
const isWindows = ['Windows', 'Win16', 'Win32', 'WinCE'].includes(navigator.platform);
|
||||
|
||||
|
|
@ -18,7 +21,7 @@ const CURSOR_STYLES = {
|
|||
BEAM: 'bar',
|
||||
UNDERLINE: 'underline',
|
||||
BLOCK: 'block'
|
||||
};
|
||||
} as const;
|
||||
|
||||
const isWebgl2Supported = (() => {
|
||||
let isSupported = window.WebGL2RenderingContext ? undefined : false;
|
||||
|
|
@ -32,7 +35,7 @@ const isWebgl2Supported = (() => {
|
|||
};
|
||||
})();
|
||||
|
||||
const getTermOptions = props => {
|
||||
const getTermOptions = (props: TermProps): ITerminalOptions => {
|
||||
// Set a background color only if it is opaque
|
||||
const needTransparency = Color(props.backgroundColor).alpha() < 1;
|
||||
const backgroundColor = needTransparency ? 'transparent' : props.backgroundColor;
|
||||
|
|
@ -78,13 +81,23 @@ const getTermOptions = props => {
|
|||
};
|
||||
};
|
||||
|
||||
export default class Term extends React.PureComponent {
|
||||
constructor(props) {
|
||||
export default class Term extends React.PureComponent<TermProps> {
|
||||
termRef: HTMLElement | null;
|
||||
termWrapperRef: HTMLElement | null;
|
||||
termOptions: ITerminalOptions;
|
||||
disposableListeners: IDisposable[];
|
||||
termDefaultBellSound: string | null;
|
||||
fitAddon: FitAddon;
|
||||
searchAddon: SearchAddon;
|
||||
static rendererTypes: Record<string, string>;
|
||||
term!: Terminal;
|
||||
resizeObserver!: ResizeObserver;
|
||||
resizeTimeout!: NodeJS.Timeout;
|
||||
constructor(props: TermProps) {
|
||||
super(props);
|
||||
props.ref_(props.uid, this);
|
||||
this.termRef = null;
|
||||
this.termWrapperRef = null;
|
||||
this.termRect = null;
|
||||
this.termOptions = {};
|
||||
this.disposableListeners = [];
|
||||
this.termDefaultBellSound = null;
|
||||
|
|
@ -93,7 +106,7 @@ export default class Term extends React.PureComponent {
|
|||
}
|
||||
|
||||
// The main process shows this in the About dialog
|
||||
static reportRenderer(uid, type) {
|
||||
static reportRenderer(uid: string, type: string) {
|
||||
const rendererTypes = Term.rendererTypes || {};
|
||||
if (rendererTypes[uid] !== type) {
|
||||
rendererTypes[uid] = type;
|
||||
|
|
@ -111,14 +124,14 @@ export default class Term extends React.PureComponent {
|
|||
|
||||
// The parent element for the terminal is attached and removed manually so
|
||||
// that we can preserve it across mounts and unmounts of the component
|
||||
this.termRef = props.term ? props.term.element.parentElement : document.createElement('div');
|
||||
this.termRef = props.term ? props.term.element!.parentElement! : document.createElement('div');
|
||||
this.termRef.className = 'term_fit term_term';
|
||||
|
||||
this.termWrapperRef.appendChild(this.termRef);
|
||||
this.termWrapperRef?.appendChild(this.termRef);
|
||||
|
||||
if (!props.term) {
|
||||
let needTransparency = Color(props.backgroundColor).alpha() < 1;
|
||||
let useWebGL = false;
|
||||
const needTransparency = Color(props.backgroundColor).alpha() < 1;
|
||||
const useWebGL = false;
|
||||
if (props.webGLRenderer) {
|
||||
if (needTransparency) {
|
||||
console.warn(
|
||||
|
|
@ -148,8 +161,8 @@ export default class Term extends React.PureComponent {
|
|||
}
|
||||
} else {
|
||||
// get the cached plugins
|
||||
this.fitAddon = props.fitAddon;
|
||||
this.searchAddon = props.searchAddon;
|
||||
this.fitAddon = props.fitAddon!;
|
||||
this.searchAddon = props.searchAddon!;
|
||||
}
|
||||
|
||||
this.fitAddon.fit();
|
||||
|
|
@ -163,9 +176,9 @@ export default class Term extends React.PureComponent {
|
|||
}
|
||||
|
||||
if (props.onActive) {
|
||||
this.term.textarea.addEventListener('focus', props.onActive);
|
||||
this.term.textarea?.addEventListener('focus', props.onActive);
|
||||
this.disposableListeners.push({
|
||||
dispose: () => this.term.textarea.removeEventListener('focus', this.props.onActive)
|
||||
dispose: () => this.term.textarea?.removeEventListener('focus', this.props.onActive)
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -188,14 +201,14 @@ export default class Term extends React.PureComponent {
|
|||
this.disposableListeners.push(
|
||||
this.term.onCursorMove(() => {
|
||||
const cursorFrame = {
|
||||
x: this.term.buffer.cursorX * this.term._core._renderService.dimensions.actualCellWidth,
|
||||
y: this.term.buffer.cursorY * this.term._core._renderService.dimensions.actualCellHeight,
|
||||
width: this.term._core._renderService.dimensions.actualCellWidth,
|
||||
height: this.term._core._renderService.dimensions.actualCellHeight,
|
||||
x: this.term.buffer.cursorX * (this.term as any)._core._renderService.dimensions.actualCellWidth,
|
||||
y: this.term.buffer.cursorY * (this.term as any)._core._renderService.dimensions.actualCellHeight,
|
||||
width: (this.term as any)._core._renderService.dimensions.actualCellWidth,
|
||||
height: (this.term as any)._core._renderService.dimensions.actualCellHeight,
|
||||
col: this.term.buffer.cursorX,
|
||||
row: this.term.buffer.cursorY
|
||||
};
|
||||
props.onCursorMove(cursorFrame);
|
||||
props.onCursorMove?.(cursorFrame);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
|
@ -220,18 +233,18 @@ export default class Term extends React.PureComponent {
|
|||
|
||||
// intercepting paste event for any necessary processing of
|
||||
// clipboard data, if result is falsy, paste event continues
|
||||
onWindowPaste = e => {
|
||||
onWindowPaste = (e: any) => {
|
||||
if (!this.props.isTermActive) return;
|
||||
|
||||
const processed = processClipboard();
|
||||
if (processed) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
this.term._core.handler(processed);
|
||||
(this.term as any)._core.handler(processed);
|
||||
}
|
||||
};
|
||||
|
||||
onMouseUp = e => {
|
||||
onMouseUp = (e: React.MouseEvent) => {
|
||||
if (this.props.quickEdit && e.button === 2) {
|
||||
if (this.term.hasSelection()) {
|
||||
clipboard.writeText(this.term.getSelection());
|
||||
|
|
@ -244,7 +257,7 @@ export default class Term extends React.PureComponent {
|
|||
}
|
||||
};
|
||||
|
||||
write(data) {
|
||||
write(data: string | Uint8Array) {
|
||||
this.term.write(data);
|
||||
}
|
||||
|
||||
|
|
@ -260,15 +273,15 @@ export default class Term extends React.PureComponent {
|
|||
this.term.reset();
|
||||
}
|
||||
|
||||
search = searchTerm => {
|
||||
search = (searchTerm = '') => {
|
||||
this.searchAddon.findNext(searchTerm);
|
||||
};
|
||||
|
||||
searchNext = searchTerm => {
|
||||
searchNext = (searchTerm: string) => {
|
||||
this.searchAddon.findNext(searchTerm);
|
||||
};
|
||||
|
||||
searchPrevious = searchTerm => {
|
||||
searchPrevious = (searchTerm: string) => {
|
||||
this.searchAddon.findPrevious(searchTerm);
|
||||
};
|
||||
|
||||
|
|
@ -276,7 +289,7 @@ export default class Term extends React.PureComponent {
|
|||
this.props.toggleSearch();
|
||||
};
|
||||
|
||||
resize(cols, rows) {
|
||||
resize(cols: number, rows: number) {
|
||||
this.term.resize(cols, rows);
|
||||
}
|
||||
|
||||
|
|
@ -291,12 +304,12 @@ export default class Term extends React.PureComponent {
|
|||
this.fitAddon.fit();
|
||||
}
|
||||
|
||||
keyboardHandler(e) {
|
||||
keyboardHandler(e: any) {
|
||||
// Has Mousetrap flagged this event as a command?
|
||||
return !e.catched;
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
componentDidUpdate(prevProps: TermProps) {
|
||||
if (!prevProps.cleared && this.props.cleared) {
|
||||
this.clear();
|
||||
}
|
||||
|
|
@ -305,14 +318,14 @@ export default class Term extends React.PureComponent {
|
|||
|
||||
// Use bellSound in nextProps if it exists
|
||||
// otherwise use the default sound found in xterm.
|
||||
nextTermOptions.bellSound = this.props.bellSound || this.termDefaultBellSound;
|
||||
nextTermOptions.bellSound = this.props.bellSound || this.termDefaultBellSound!;
|
||||
|
||||
if (!prevProps.search && this.props.search) {
|
||||
this.search();
|
||||
}
|
||||
|
||||
// Update only options that have changed.
|
||||
Object.keys(nextTermOptions)
|
||||
ObjectTypedKeys(nextTermOptions)
|
||||
.filter(option => option !== 'theme' && nextTermOptions[option] !== this.termOptions[option])
|
||||
.forEach(option => {
|
||||
try {
|
||||
|
|
@ -330,8 +343,8 @@ export default class Term extends React.PureComponent {
|
|||
const shouldUpdateTheme =
|
||||
!this.termOptions.theme ||
|
||||
nextTermOptions.rendererType !== this.termOptions.rendererType ||
|
||||
Object.keys(nextTermOptions.theme).some(
|
||||
option => nextTermOptions.theme[option] !== this.termOptions.theme[option]
|
||||
ObjectTypedKeys(nextTermOptions.theme!).some(
|
||||
option => nextTermOptions.theme![option] !== this.termOptions.theme![option]
|
||||
);
|
||||
if (shouldUpdateTheme) {
|
||||
this.term.setOption('theme', nextTermOptions.theme);
|
||||
|
|
@ -350,11 +363,11 @@ export default class Term extends React.PureComponent {
|
|||
}
|
||||
|
||||
if (prevProps.rows !== this.props.rows || prevProps.cols !== this.props.cols) {
|
||||
this.resize(this.props.cols, this.props.rows);
|
||||
this.resize(this.props.cols!, this.props.rows!);
|
||||
}
|
||||
}
|
||||
|
||||
onTermWrapperRef = component => {
|
||||
onTermWrapperRef = (component: HTMLElement | null) => {
|
||||
this.termWrapperRef = component;
|
||||
|
||||
if (component) {
|
||||
|
|
@ -372,7 +385,7 @@ export default class Term extends React.PureComponent {
|
|||
|
||||
componentWillUnmount() {
|
||||
terms[this.props.uid] = null;
|
||||
this.termWrapperRef.removeChild(this.termRef);
|
||||
this.termWrapperRef?.removeChild(this.termRef!);
|
||||
this.props.ref_(this.props.uid, null);
|
||||
|
||||
// to clean up the terminal, we remove the listeners
|
||||
|
|
@ -3,62 +3,53 @@ import {decorate, getTermGroupProps} from '../utils/plugins';
|
|||
import {registerCommandHandlers} from '../command-registry';
|
||||
import TermGroup_ from './term-group';
|
||||
import StyleSheet_ from './style-sheet';
|
||||
import {TermsProps} from '../hyper';
|
||||
import Term from './term';
|
||||
import {ObjectTypedKeys} from '../utils/object';
|
||||
|
||||
const TermGroup = decorate(TermGroup_, 'TermGroup');
|
||||
const StyleSheet = decorate(StyleSheet_, 'StyleSheet');
|
||||
|
||||
const isMac = /Mac/.test(navigator.userAgent);
|
||||
|
||||
export default class Terms extends React.Component {
|
||||
constructor(props, context) {
|
||||
export default class Terms extends React.Component<TermsProps> {
|
||||
terms: Record<string, Term>;
|
||||
registerCommands: (cmds: Record<string, (...args: any[]) => void>) => void;
|
||||
constructor(props: TermsProps, context: any) {
|
||||
super(props, context);
|
||||
this.terms = {};
|
||||
this.bound = new WeakMap();
|
||||
this.registerCommands = registerCommandHandlers;
|
||||
props.ref_(this);
|
||||
}
|
||||
|
||||
shouldComponentUpdate(nextProps) {
|
||||
for (const i in nextProps) {
|
||||
if (i === 'write') {
|
||||
continue;
|
||||
}
|
||||
if (this.props[i] !== nextProps[i]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
for (const i in this.props) {
|
||||
if (i === 'write') {
|
||||
continue;
|
||||
}
|
||||
if (this.props[i] !== nextProps[i]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
shouldComponentUpdate(nextProps: TermsProps & {children: any}) {
|
||||
return (
|
||||
ObjectTypedKeys(nextProps).some(i => i !== 'write' && this.props[i] !== nextProps[i]) ||
|
||||
ObjectTypedKeys(this.props).some(i => i !== 'write' && this.props[i] !== nextProps[i])
|
||||
);
|
||||
}
|
||||
|
||||
onRef = (uid, term) => {
|
||||
onRef = (uid: string, term: Term) => {
|
||||
if (term) {
|
||||
this.terms[uid] = term;
|
||||
}
|
||||
};
|
||||
|
||||
getTermByUid(uid) {
|
||||
getTermByUid(uid: string) {
|
||||
return this.terms[uid];
|
||||
}
|
||||
|
||||
getActiveTerm() {
|
||||
return this.getTermByUid(this.props.activeSession);
|
||||
return this.getTermByUid(this.props.activeSession!);
|
||||
}
|
||||
|
||||
onTerminal(uid, term) {
|
||||
onTerminal(uid: string, term: Term) {
|
||||
this.terms[uid] = term;
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
window.addEventListener('contextmenu', () => {
|
||||
const selection = window.getSelection().toString();
|
||||
const selection = window.getSelection()!.toString();
|
||||
const {
|
||||
props: {uid}
|
||||
} = this.getActiveTerm();
|
||||
|
|
@ -66,8 +57,8 @@ export default class Terms extends React.Component {
|
|||
});
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
for (let uid in prevProps.sessions) {
|
||||
componentDidUpdate(prevProps: TermsProps) {
|
||||
for (const uid in prevProps.sessions) {
|
||||
if (!this.props.sessions[uid]) {
|
||||
this.terms[uid].term.dispose();
|
||||
delete this.terms[uid];
|
||||
67
lib/hyper.d.ts
vendored
67
lib/hyper.d.ts
vendored
|
|
@ -26,7 +26,7 @@ export type ITermState = {
|
|||
};
|
||||
|
||||
export type cursorShapes = 'BEAM' | 'UNDERLINE' | 'BLOCK';
|
||||
import {FontWeight} from 'xterm';
|
||||
import {FontWeight, Terminal} from 'xterm';
|
||||
|
||||
export type uiState = {
|
||||
_lastUpdate: number | null;
|
||||
|
|
@ -221,7 +221,7 @@ export type TabProps = {
|
|||
isActive: boolean;
|
||||
isFirst: boolean;
|
||||
isLast: boolean;
|
||||
onClick: (event: React.MouseEvent<HTMLElement, MouseEvent>) => void;
|
||||
onClick?: (event: React.MouseEvent<HTMLElement, MouseEvent>) => void;
|
||||
onClose: () => void;
|
||||
onSelect: () => void;
|
||||
text: string;
|
||||
|
|
@ -237,8 +237,8 @@ export type ITab = {
|
|||
export type TabsProps = {
|
||||
tabs: ITab[];
|
||||
borderColor: string;
|
||||
onChange: () => void;
|
||||
onClose: () => void;
|
||||
onChange: (uid: string) => void;
|
||||
onClose: (uid: string) => void;
|
||||
fullScreen: boolean;
|
||||
} & extensionProps;
|
||||
|
||||
|
|
@ -312,3 +312,62 @@ export type TermGroupOwnProps = {
|
|||
|
||||
import {TermGroupConnectedProps} from './components/term-group';
|
||||
export type TermGroupProps = TermGroupConnectedProps & TermGroupOwnProps;
|
||||
|
||||
export type SearchBoxProps = {
|
||||
search: (searchTerm: string) => void;
|
||||
next: (searchTerm: string) => void;
|
||||
prev: (searchTerm: string) => void;
|
||||
close: () => void;
|
||||
};
|
||||
|
||||
import {FitAddon} from 'xterm-addon-fit';
|
||||
import {SearchAddon} from 'xterm-addon-search';
|
||||
export type TermProps = {
|
||||
backgroundColor: string;
|
||||
bell: string;
|
||||
bellSound: string | null;
|
||||
bellSoundURL: string | null;
|
||||
borderColor: string;
|
||||
cleared: boolean;
|
||||
colors: uiState['colors'];
|
||||
cols: number | null;
|
||||
copyOnSelect: boolean;
|
||||
cursorAccentColor?: string;
|
||||
cursorBlink: boolean;
|
||||
cursorColor: string;
|
||||
cursorShape: cursorShapes;
|
||||
disableLigatures: boolean;
|
||||
fitAddon: FitAddon | null;
|
||||
fontFamily: string;
|
||||
fontSize: number;
|
||||
fontSmoothing?: string;
|
||||
fontWeight: FontWeight;
|
||||
fontWeightBold: FontWeight;
|
||||
foregroundColor: string;
|
||||
isTermActive: boolean;
|
||||
letterSpacing: number;
|
||||
lineHeight: number;
|
||||
macOptionSelectionMode: string;
|
||||
modifierKeys: Immutable<{altIsMeta: boolean; cmdIsMeta: boolean}>;
|
||||
onActive: () => void;
|
||||
onContextMenu: (selection: any) => void;
|
||||
onCursorMove?: (cursorFrame: {x: number; y: number; width: number; height: number; col: number; row: number}) => void;
|
||||
onData: (data: any) => void;
|
||||
onResize: (cols: number, rows: number) => void;
|
||||
onTitle: (title: string) => void;
|
||||
padding: string;
|
||||
quickEdit: boolean;
|
||||
rows: number | null;
|
||||
scrollback: number;
|
||||
search: boolean;
|
||||
searchAddon: SearchAddon | null;
|
||||
selectionColor: string;
|
||||
term: Terminal | null;
|
||||
toggleSearch: () => void;
|
||||
uid: string;
|
||||
uiFontFamily: string;
|
||||
url: string | null;
|
||||
webGLRenderer: boolean;
|
||||
} & extensionProps & {ref_?: any};
|
||||
|
||||
export type Assignable<T, U> = {[k in keyof U]: k extends keyof T ? T[k] : U[k]} & Partial<T>;
|
||||
|
|
|
|||
|
|
@ -7,5 +7,5 @@ import Term from './components/term';
|
|||
// optimization for the most common action
|
||||
// within the system
|
||||
|
||||
const terms: Record<string, Term> = {};
|
||||
const terms: Record<string, Term | null> = {};
|
||||
export default terms;
|
||||
|
|
|
|||
|
|
@ -11,7 +11,19 @@ import React, {PureComponent} from 'react';
|
|||
import ReactDOM from 'react-dom';
|
||||
import Notification from '../components/notification';
|
||||
import notify from './notify';
|
||||
import {hyperPlugin, IUiReducer, ISessionReducer, ITermGroupReducer, HyperState, HyperDispatch} from '../hyper';
|
||||
import {
|
||||
hyperPlugin,
|
||||
IUiReducer,
|
||||
ISessionReducer,
|
||||
ITermGroupReducer,
|
||||
HyperState,
|
||||
HyperDispatch,
|
||||
TabProps,
|
||||
TabsProps,
|
||||
TermGroupOwnProps,
|
||||
TermProps,
|
||||
Assignable
|
||||
} from '../hyper';
|
||||
import {Middleware} from 'redux';
|
||||
import {ObjectTypedKeys} from './object';
|
||||
|
||||
|
|
@ -402,19 +414,23 @@ function getProps(name: keyof typeof propsDecorators, props: any, ...fnArgs: any
|
|||
return props_ || props;
|
||||
}
|
||||
|
||||
export function getTermGroupProps(uid: string, parentProps: any, props: any) {
|
||||
export function getTermGroupProps<T extends Assignable<TermGroupOwnProps, T>>(
|
||||
uid: string,
|
||||
parentProps: any,
|
||||
props: T
|
||||
): T {
|
||||
return getProps('getTermGroupProps', props, uid, parentProps);
|
||||
}
|
||||
|
||||
export function getTermProps(uid: string, parentProps: any, props: any) {
|
||||
export function getTermProps<T extends Assignable<TermProps, T>>(uid: string, parentProps: any, props: T): T {
|
||||
return getProps('getTermProps', props, uid, parentProps);
|
||||
}
|
||||
|
||||
export function getTabsProps(parentProps: any, props: any) {
|
||||
export function getTabsProps<T extends Assignable<TabsProps, T>>(parentProps: any, props: T): T {
|
||||
return getProps('getTabsProps', props, parentProps);
|
||||
}
|
||||
|
||||
export function getTabProps(tab: any, parentProps: any, props: any) {
|
||||
export function getTabProps<T extends Assignable<TabProps, T>>(tab: any, parentProps: any, props: T): T {
|
||||
return getProps('getTabProps', props, tab, parentProps);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -116,6 +116,7 @@
|
|||
"prettier": "1.19.1",
|
||||
"proxyquire": "2.1.3",
|
||||
"redux-devtools-extension": "2.13.8",
|
||||
"resize-observer-polyfill": "1.5.1",
|
||||
"spectron": "10.0.1",
|
||||
"style-loader": "1.1.3",
|
||||
"terser": "4.6.6",
|
||||
|
|
|
|||
|
|
@ -7049,6 +7049,11 @@ reselect@4.0.0:
|
|||
resolved "https://registry.yarnpkg.com/reselect/-/reselect-4.0.0.tgz#f2529830e5d3d0e021408b246a206ef4ea4437f7"
|
||||
integrity sha512-qUgANli03jjAyGlnbYVAV5vvnOmJnODyABz51RdBN7M4WaVu8mecZWgyQNkG8Yqe3KRGRt0l4K4B3XVEULC4CA==
|
||||
|
||||
resize-observer-polyfill@1.5.1:
|
||||
version "1.5.1"
|
||||
resolved "https://registry.yarnpkg.com/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz#0e9020dd3d21024458d4ebd27e23e40269810464"
|
||||
integrity sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==
|
||||
|
||||
resolve-cwd@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-2.0.0.tgz#00a9f7387556e27038eae232caa372a6a59b665a"
|
||||
|
|
|
|||
Loading…
Reference in a new issue