Skip to content

Instantly share code, notes, and snippets.

@ulrikstrid
Created December 19, 2017 15:34
Show Gist options
  • Save ulrikstrid/b3b082d4ba8b912c556e51bc0cc900a3 to your computer and use it in GitHub Desktop.
Save ulrikstrid/b3b082d4ba8b912c556e51bc0cc900a3 to your computer and use it in GitHub Desktop.
import "rxjs/add/observable/fromEvent";
import "rxjs/add/observable/merge";
import * as classnames from "classnames";
import { css } from "emotion";
import { add } from "ramda";
import * as React from "react";
import { Observable } from "rxjs/Observable";
import { filter, flatMap, map, scan, takeUntil } from "rxjs/operators";
import { Subscription } from "rxjs/Subscription";
import { FieldMetadata } from "../../models/metadata";
import hoverToDirection from "../../utils/hoverToDirection";
interface Props {
column: FieldMetadata;
onClick: React.MouseEventHandler<HTMLDivElement>;
className?: string;
setWidth: (column: FieldMetadata, newWidth: number) => void;
}
const textAreaStyle = css`
width: calc(100% - 10px);
height: 100%;
display: inline-block;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
font-weight: 700;
line-height: 30px;
padding-left: 2px;
padding-right: 2px;
`;
const hoverAreaStyle = css`
width: 10px;
height: 100%;
display: inline-block;
&:hover {
cursor: col-resize;
}
`;
class GridHeaderColumn extends React.Component<Props> {
cellEle: HTMLDivElement | null;
widthSubscribtion: Subscription;
startSubscription = () => {
if (this.cellEle != null) {
const endObservable = Observable.merge(
Observable.fromEvent(this.cellEle, "mouseup"),
Observable.fromEvent(this.cellEle, "mouseleave")
);
const width = this.cellEle.offsetWidth;
let finalWidth = width;
this.widthSubscribtion = Observable.fromEvent(this.cellEle, "mousedown")
.pipe(
map((e: MouseEvent) =>
hoverToDirection(e.layerX, (e.target as HTMLDivElement).offsetWidth)
),
filter(x => x === "right"),
flatMap(() => {
if (this.cellEle) {
return Observable.fromEvent(this.cellEle, "mousemove");
}
throw new Error("cell element does not exist");
}),
map((dragEvent: MouseEvent) => dragEvent.movementX),
scan<number>(add, width),
takeUntil(endObservable)
)
.subscribe(
newWidth => {
if (this.cellEle) {
this.cellEle.setAttribute(
"style",
`width: ${newWidth}px; z-index: 1; border-right: 1px solid black; background: white;`
);
finalWidth = newWidth;
}
},
console.error,
() => {
if (this.cellEle) {
this.cellEle.setAttribute("style", "");
this.props.setWidth(this.props.column, finalWidth);
}
}
);
}
};
componentWillUnmount() {
this.widthSubscribtion.unsubscribe();
}
componentWillUpdate() {
this.widthSubscribtion.unsubscribe();
}
componentDidMount() {
this.startSubscription();
}
componentDidUpdate() {
this.startSubscription();
}
render() {
return (
<div className={this.props.className} ref={ele => (this.cellEle = ele)}>
<div className={textAreaStyle} onClick={this.props.onClick}>
{this.props.column.shortDisplayName || this.props.column.displayName}
{this.props.children}
</div>
<div className={classnames(hoverAreaStyle, "qa-grid-header-hover")}>
{" "}
</div>
</div>
);
}
}
export default GridHeaderColumn;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment