import { bindGlobalStyle, CssProps } from 'lupine.web';
import { stopPropagation } from '../lib';
/**
How to use:
// getSplitter's first parameter is the container's selector where the Splitter will be in.
// the second parameter is whether it's Vertical
// then the third parameter is it's RightOrTop or not
const locationLeft = false;
const splitter = ResizableSplitter.getSplitter('.body .side', true, locationLeft);
const container = (
{splitter}
{designPanel}
...
*/
export class ResizableSplitter {
static hostNode: HTMLElement;
static isVertical = true;
static isRightOrTop = true;
private static initialized = false;
private static startXorY = 0;
private static startWidthOrHeight = 0;
private static pressed = false;
static init() {
/* styles for resizable splitter */
const css: CssProps = {
'.resizable-splitter-v-left, .resizable-splitter-v-right': {
position: 'absolute',
top: 0,
bottom: 0,
left: 0,
width: '2px',
cursor: 'col-resize',
},
'.resizable-splitter-v-right': {
left: 'unset',
right: 0,
},
'.resizable-splitter-v-left:hover, .resizable-splitter-v-right:hover': {
width: '4px',
backgroundColor: 'var(--primary-accent-color, #1890ff)',
},
'.resizable-splitter-h-top, .resizable-splitter-h-bottom': {
position: 'absolute',
top: 0,
left: 0,
right: 0,
height: '2px',
cursor: 'row-resize',
},
'.resizable-splitter-h-bottom': {
top: 'unset',
bottom: 0,
},
'.resizable-splitter-h-top:hover, .resizable-splitter-h-bottom:hover': {
height: '4px',
backgroundColor: 'var(--primary-accent-color, #1890ff)',
},
};
bindGlobalStyle('resizable-splitter', css, false, true);
window.addEventListener('mousemove', ResizableSplitter.onMousemove.bind(ResizableSplitter), false);
document.documentElement.addEventListener('mouseup', ResizableSplitter.onMouseup.bind(ResizableSplitter), false);
}
static getSplitterClassName(isVertical: boolean, isRightOrTop: boolean): string {
const className =
'resizable-splitter-' +
(isVertical ? (isRightOrTop ? 'v-right' : 'v-left') : isRightOrTop ? 'h-top' : 'h-bottom');
return className;
}
static onMousedown(event: any) {
if (event.buttons !== 1 || event.button !== 0) return;
this.pressed = true;
this.startXorY = this.isVertical ? event.clientX : event.clientY;
const startPosition = document.defaultView!.getComputedStyle(this.hostNode)[this.isVertical ? 'width' : 'height'];
this.startWidthOrHeight = parseInt(startPosition, 10);
}
static onMousemove(event: any) {
if (!this.pressed || event.buttons !== 1 || event.button !== 0) {
return;
}
// prevent text/element selection when drag
stopPropagation(event);
if (this.isVertical) {
const movedXorY = this.startWidthOrHeight + (event.clientX - this.startXorY) * (this.isRightOrTop ? 1 : -1);
this.hostNode.style.width = movedXorY + 'px';
} else {
const movedXorY = this.startWidthOrHeight + (event.clientY - this.startXorY) * (this.isRightOrTop ? -1 : 1);
this.hostNode.style.height = movedXorY + 'px';
}
}
static onMouseup() {
if (this.pressed) this.pressed = false;
}
static getSplitter(selector: string, isVertical: boolean, isRightOrTop: boolean) {
if (!this.initialized) {
this.initialized = true;
this.init();
}
const className = this.getSplitterClassName(isVertical, isRightOrTop);
const onMousedown = (event: any) => {
ResizableSplitter.hostNode = document.querySelector(selector)!;
if (!ResizableSplitter.hostNode) {
console.error(`Can't find element: ${selector}`);
return;
}
ResizableSplitter.isVertical = isVertical;
ResizableSplitter.isRightOrTop = isRightOrTop;
ResizableSplitter.onMousedown.bind(ResizableSplitter)(event);
};
return
;
}
}