mirror of
https://github.com/quine-global/hyper.git
synced 2026-01-15 21:28:40 -09:00
port notification and split-pane component to ts
This commit is contained in:
parent
b0002bbe01
commit
6801460912
5 changed files with 57 additions and 25 deletions
|
|
@ -1,8 +1,10 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import {NotificationProps} from '../hyper';
|
||||||
|
|
||||||
export default class Notification extends React.PureComponent {
|
export default class Notification extends React.PureComponent<NotificationProps, {dismissing: boolean}> {
|
||||||
constructor() {
|
dismissTimer!: NodeJS.Timeout;
|
||||||
super();
|
constructor(props: NotificationProps) {
|
||||||
|
super(props);
|
||||||
this.state = {
|
this.state = {
|
||||||
dismissing: false
|
dismissing: false
|
||||||
};
|
};
|
||||||
|
|
@ -14,7 +16,7 @@ export default class Notification extends React.PureComponent {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//TODO: Remove usage of legacy and soon deprecated lifecycle methods
|
//TODO: Remove usage of legacy and soon deprecated lifecycle methods
|
||||||
UNSAFE_componentWillReceiveProps(next) {
|
UNSAFE_componentWillReceiveProps(next: NotificationProps) {
|
||||||
// if we have a timer going and the notification text
|
// if we have a timer going and the notification text
|
||||||
// changed we reset the timer
|
// changed we reset the timer
|
||||||
if (next.text !== this.props.text) {
|
if (next.text !== this.props.text) {
|
||||||
|
|
@ -31,7 +33,7 @@ export default class Notification extends React.PureComponent {
|
||||||
this.setState({dismissing: true});
|
this.setState({dismissing: true});
|
||||||
};
|
};
|
||||||
|
|
||||||
onElement = el => {
|
onElement = (el: HTMLDivElement | null) => {
|
||||||
if (el) {
|
if (el) {
|
||||||
el.addEventListener('webkitTransitionEnd', () => {
|
el.addEventListener('webkitTransitionEnd', () => {
|
||||||
if (this.state.dismissing) {
|
if (this.state.dismissing) {
|
||||||
|
|
@ -48,7 +50,7 @@ export default class Notification extends React.PureComponent {
|
||||||
setDismissTimer() {
|
setDismissTimer() {
|
||||||
this.dismissTimer = setTimeout(() => {
|
this.dismissTimer = setTimeout(() => {
|
||||||
this.handleDismiss();
|
this.handleDismiss();
|
||||||
}, this.props.dismissAfter);
|
}, this.props.dismissAfter!);
|
||||||
}
|
}
|
||||||
|
|
||||||
resetDismissTimer() {
|
resetDismissTimer() {
|
||||||
|
|
@ -1,26 +1,36 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
|
import {SplitPaneProps} from '../hyper';
|
||||||
|
|
||||||
export default class SplitPane extends React.PureComponent {
|
export default class SplitPane extends React.PureComponent<SplitPaneProps, {dragging: boolean}> {
|
||||||
constructor(props) {
|
dragPanePosition!: number;
|
||||||
|
dragTarget!: Element;
|
||||||
|
panes!: Element[];
|
||||||
|
paneIndex!: number;
|
||||||
|
d1!: 'height' | 'width';
|
||||||
|
d2!: 'top' | 'left';
|
||||||
|
d3!: 'clientX' | 'clientY';
|
||||||
|
panesSize!: number;
|
||||||
|
dragging!: boolean;
|
||||||
|
constructor(props: SplitPaneProps) {
|
||||||
super(props);
|
super(props);
|
||||||
this.state = {dragging: false};
|
this.state = {dragging: false};
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidUpdate(prevProps) {
|
componentDidUpdate(prevProps: SplitPaneProps) {
|
||||||
if (this.state.dragging && prevProps.sizes !== this.props.sizes) {
|
if (this.state.dragging && prevProps.sizes !== this.props.sizes) {
|
||||||
// recompute positions for ongoing dragging
|
// recompute positions for ongoing dragging
|
||||||
this.dragPanePosition = this.dragTarget.getBoundingClientRect()[this.d2];
|
this.dragPanePosition = this.dragTarget.getBoundingClientRect()[this.d2];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setupPanes(ev) {
|
setupPanes(ev: any) {
|
||||||
this.panes = Array.from(ev.target.parentNode.childNodes);
|
this.panes = Array.from(ev.target.parentNode.childNodes);
|
||||||
this.paneIndex = this.panes.indexOf(ev.target);
|
this.paneIndex = this.panes.indexOf(ev.target);
|
||||||
this.paneIndex -= Math.ceil(this.paneIndex / 2);
|
this.paneIndex -= Math.ceil(this.paneIndex / 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleAutoResize = ev => {
|
handleAutoResize = (ev: React.MouseEvent) => {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
|
|
||||||
this.setupPanes(ev);
|
this.setupPanes(ev);
|
||||||
|
|
@ -36,7 +46,7 @@ export default class SplitPane extends React.PureComponent {
|
||||||
this.props.onResize(sizes_);
|
this.props.onResize(sizes_);
|
||||||
};
|
};
|
||||||
|
|
||||||
handleDragStart = ev => {
|
handleDragStart = (ev: any) => {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
this.setState({dragging: true});
|
this.setState({dragging: true});
|
||||||
window.addEventListener('mousemove', this.onDrag);
|
window.addEventListener('mousemove', this.onDrag);
|
||||||
|
|
@ -61,20 +71,20 @@ export default class SplitPane extends React.PureComponent {
|
||||||
|
|
||||||
getSizes() {
|
getSizes() {
|
||||||
const {sizes} = this.props;
|
const {sizes} = this.props;
|
||||||
let sizes_;
|
let sizes_: number[];
|
||||||
|
|
||||||
if (sizes) {
|
if (sizes) {
|
||||||
sizes_ = [].concat(sizes);
|
sizes_ = [...sizes.asMutable()];
|
||||||
} else {
|
} else {
|
||||||
const total = this.props.children.length;
|
const total = (this.props.children as React.ReactNodeArray).length;
|
||||||
const count = new Array(total).fill(1 / total);
|
const count = new Array<number>(total).fill(1 / total);
|
||||||
|
|
||||||
sizes_ = count;
|
sizes_ = count;
|
||||||
}
|
}
|
||||||
return sizes_;
|
return sizes_;
|
||||||
}
|
}
|
||||||
|
|
||||||
onDrag = ev => {
|
onDrag = (ev: MouseEvent) => {
|
||||||
const sizes_ = this.getSizes();
|
const sizes_ = this.getSizes();
|
||||||
|
|
||||||
const i = this.paneIndex;
|
const i = this.paneIndex;
|
||||||
|
|
@ -99,16 +109,13 @@ export default class SplitPane extends React.PureComponent {
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const children = this.props.children;
|
const children = this.props.children as React.ReactNodeArray;
|
||||||
const {direction, borderColor} = this.props;
|
const {direction, borderColor} = this.props;
|
||||||
const sizeProperty = direction === 'horizontal' ? 'height' : 'width';
|
const sizeProperty = direction === 'horizontal' ? 'height' : 'width';
|
||||||
let {sizes} = this.props;
|
// workaround for the fact that if we don't specify
|
||||||
if (!sizes) {
|
// sizes, sometimes flex fails to calculate the
|
||||||
// workaround for the fact that if we don't specify
|
// right height for the horizontal panes
|
||||||
// sizes, sometimes flex fails to calculate the
|
const sizes = this.props.sizes || new Array<number>(children.length).fill(1 / children.length);
|
||||||
// right height for the horizontal panes
|
|
||||||
sizes = new Array(children.length).fill(1 / children.length);
|
|
||||||
}
|
|
||||||
return (
|
return (
|
||||||
<div className={`splitpane_panes splitpane_panes_${direction}`}>
|
<div className={`splitpane_panes splitpane_panes_${direction}`}>
|
||||||
{React.Children.map(children, (child, i) => {
|
{React.Children.map(children, (child, i) => {
|
||||||
17
lib/hyper.d.ts
vendored
17
lib/hyper.d.ts
vendored
|
|
@ -241,3 +241,20 @@ export type TabsProps = {
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
fullScreen: boolean;
|
fullScreen: boolean;
|
||||||
} & extensionProps;
|
} & extensionProps;
|
||||||
|
|
||||||
|
export type NotificationProps = {
|
||||||
|
backgroundColor: string;
|
||||||
|
color?: string;
|
||||||
|
dismissAfter?: number;
|
||||||
|
onDismiss: Function;
|
||||||
|
text?: string | null;
|
||||||
|
userDismissable?: boolean | null;
|
||||||
|
userDismissColor?: string;
|
||||||
|
} & extensionProps;
|
||||||
|
|
||||||
|
export type SplitPaneProps = {
|
||||||
|
borderColor: string;
|
||||||
|
direction: 'horizontal' | 'vertical';
|
||||||
|
onResize: Function;
|
||||||
|
sizes?: Immutable<number[]> | null;
|
||||||
|
};
|
||||||
|
|
|
||||||
|
|
@ -74,6 +74,7 @@
|
||||||
"@types/copy-webpack-plugin": "5.0.0",
|
"@types/copy-webpack-plugin": "5.0.0",
|
||||||
"@types/electron-devtools-installer": "2.2.0",
|
"@types/electron-devtools-installer": "2.2.0",
|
||||||
"@types/fs-extra": "8.1.0",
|
"@types/fs-extra": "8.1.0",
|
||||||
|
"@types/lodash": "^4.14.149",
|
||||||
"@types/mkdirp": "1.0.0",
|
"@types/mkdirp": "1.0.0",
|
||||||
"@types/mousetrap": "^1.6.3",
|
"@types/mousetrap": "^1.6.3",
|
||||||
"@types/ms": "0.7.31",
|
"@types/ms": "0.7.31",
|
||||||
|
|
|
||||||
|
|
@ -649,6 +649,11 @@
|
||||||
dependencies:
|
dependencies:
|
||||||
"@types/node" "*"
|
"@types/node" "*"
|
||||||
|
|
||||||
|
"@types/lodash@^4.14.149":
|
||||||
|
version "4.14.149"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.149.tgz#1342d63d948c6062838fbf961012f74d4e638440"
|
||||||
|
integrity sha512-ijGqzZt/b7BfzcK9vTrS6MFljQRPn5BFWOx8oE0GYxribu6uV+aA9zZuXI1zc/etK9E8nrgdoF2+LgUw7+9tJQ==
|
||||||
|
|
||||||
"@types/minimatch@*":
|
"@types/minimatch@*":
|
||||||
version "3.0.3"
|
version "3.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d"
|
resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d"
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue