From 57fd125b5ce89cc954b4af8ec1f2fe10377864ac Mon Sep 17 00:00:00 2001 From: Labhansh Agrawal Date: Mon, 16 Mar 2020 20:02:04 +0530 Subject: [PATCH] port term-group component to ts --- .../{term-group.js => term-group.tsx} | 52 +++++++++++-------- lib/hyper.d.ts | 50 ++++++++++++++++++ lib/utils/plugins.ts | 6 +-- 3 files changed, 83 insertions(+), 25 deletions(-) rename lib/components/{term-group.js => term-group.tsx} (72%) diff --git a/lib/components/term-group.js b/lib/components/term-group.tsx similarity index 72% rename from lib/components/term-group.js rename to lib/components/term-group.tsx index c04f42d8..1c1f6f10 100644 --- a/lib/components/term-group.js +++ b/lib/components/term-group.tsx @@ -4,35 +4,42 @@ import {decorate, getTermProps, getTermGroupProps} from '../utils/plugins'; import {resizeTermGroup} from '../actions/term-groups'; import Term_ from './term'; import SplitPane_ from './split-pane'; +import {HyperState, HyperDispatch, TermGroupProps, TermGroupOwnProps} from '../hyper'; const Term = decorate(Term_, 'Term'); const SplitPane = decorate(SplitPane_, 'SplitPane'); -class TermGroup_ extends React.PureComponent { - constructor(props, context) { +// eslint-disable-next-line @typescript-eslint/class-name-casing +class TermGroup_ extends React.PureComponent { + bound: WeakMap<(uid: string, ...args: any[]) => any, Record any>>; + term?: Term_; + constructor(props: TermGroupProps, context: any) { super(props, context); this.bound = new WeakMap(); - this.termRefs = {}; } - bind(fn, thisObj, uid) { + bind any>( + fn: T, + thisObj: any, + uid: string + ): (...args: T extends (uid: string, ...args: infer I) => any ? I : never) => ReturnType { if (!this.bound.has(fn)) { this.bound.set(fn, {}); } - const map = this.bound.get(fn); + const map = this.bound.get(fn)!; if (!map[uid]) { map[uid] = fn.bind(thisObj, uid); } return map[uid]; } - renderSplit(groups) { + renderSplit(groups: JSX.Element[]) { const [first, ...rest] = groups; if (rest.length === 0) { return first; } - const direction = this.props.termGroup.direction.toLowerCase(); + const direction = this.props.termGroup.direction!.toLowerCase() as 'horizontal' | 'vertical'; return ( { + onTermRef = (uid: string, term: Term_) => { this.term = term; this.props.ref_(uid, term); }; - renderTerm(uid) { + renderTerm(uid: string) { const session = this.props.sessions[uid]; const termRef = this.props.terms[uid]; const props = getTermProps(uid, this.props, { @@ -112,7 +119,7 @@ class TermGroup_ extends React.PureComponent { return this.renderTerm(termGroup.sessionUid); } - const groups = childGroups.map(child => { + const groups = childGroups.asMutable().map(child => { const props = getTermGroupProps( child.uid, this.props.parentProps, @@ -126,19 +133,20 @@ class TermGroup_ extends React.PureComponent { } } -const TermGroup = connect( - (state, ownProps) => ({ - childGroups: ownProps.termGroup.children.map(uid => state.termGroups.termGroups[uid]) - }), - (dispatch, ownProps) => ({ - onTermGroupResize(splitSizes) { - dispatch(resizeTermGroup(ownProps.termGroup.uid, splitSizes)); - } - }), - null, - {forwardRef: true} -)(TermGroup_); +const mapStateToProps = (state: HyperState, ownProps: TermGroupOwnProps) => ({ + childGroups: ownProps.termGroup.children.map(uid => state.termGroups.termGroups[uid]) +}); + +const mapDispatchToProps = (dispatch: HyperDispatch, ownProps: TermGroupOwnProps) => ({ + onTermGroupResize(splitSizes: number[]) { + dispatch(resizeTermGroup(ownProps.termGroup.uid, splitSizes)); + } +}); + +const TermGroup = connect(mapStateToProps, mapDispatchToProps, null, {forwardRef: true})(TermGroup_); const DecoratedTermGroup = decorate(TermGroup, 'TermGroup'); export default TermGroup; + +export type TermGroupConnectedProps = ReturnType & ReturnType; diff --git a/lib/hyper.d.ts b/lib/hyper.d.ts index d5c273f7..0d0cc3ac 100644 --- a/lib/hyper.d.ts +++ b/lib/hyper.d.ts @@ -262,3 +262,53 @@ export type SplitPaneProps = { onResize: Function; sizes?: Immutable | null; }; + +import Term from './components/term'; + +export type TermGroupOwnProps = { + cursorAccentColor?: string; + fontSmoothing?: string; + parentProps: TermsProps; + ref_: (uid: string, term: Term) => void; + termGroup: Immutable; + terms: Record; +} & Pick< + TermsProps, + | 'activeSession' + | 'backgroundColor' + | 'bell' + | 'bellSound' + | 'bellSoundURL' + | 'borderColor' + | 'colors' + | 'copyOnSelect' + | 'cursorBlink' + | 'cursorColor' + | 'cursorShape' + | 'disableLigatures' + | 'fontFamily' + | 'fontSize' + | 'fontWeight' + | 'fontWeightBold' + | 'foregroundColor' + | 'letterSpacing' + | 'lineHeight' + | 'macOptionSelectionMode' + | 'modifierKeys' + | 'onActive' + | 'onContextMenu' + | 'onData' + | 'onResize' + | 'onTitle' + | 'padding' + | 'quickEdit' + | 'scrollback' + | 'selectionColor' + | 'sessions' + | 'toggleSearch' + | 'uiFontFamily' + | 'webGLRenderer' +>; + +import {TermGroupConnectedProps} from './components/term-group'; +export type TermGroupProps = TermGroupConnectedProps & TermGroupOwnProps; diff --git a/lib/utils/plugins.ts b/lib/utils/plugins.ts index 16b7075b..8393a5a5 100644 --- a/lib/utils/plugins.ts +++ b/lib/utils/plugins.ts @@ -52,7 +52,7 @@ let reducersDecorators: { }; // expose decorated component instance to the higher-order components -function exposeDecorated

(Component_: React.ComponentClass

): React.ComponentClass { +function exposeDecorated

(Component_: React.ComponentType

): React.ComponentClass { return class DecoratedComponent extends React.Component

{ constructor(props: P, context: any) { super(props, context); @@ -72,7 +72,7 @@ function exposeDecorated

(Component_: React.ComponentClass

): Re }; } -function getDecorated

(parent: React.ComponentClass

, name: string): React.ComponentClass

{ +function getDecorated

(parent: React.ComponentType

, name: string): React.ComponentClass

{ if (!decorated[name]) { let class_ = exposeDecorated(parent); (class_ as any).displayName = `_exposeDecorated(${name})`; @@ -118,7 +118,7 @@ function getDecorated

(parent: React.ComponentClass

, name: string): React.C // that wraps with the higher-order components // exposed by plugins export function decorate

( - Component_: React.ComponentClass

, + Component_: React.ComponentType

, name: string ): React.ComponentClass { return class DecoratedComponent extends React.Component {