@furo/layout
Version:
Layout components for furo
209 lines (204 loc) • 6.1 kB
JavaScript
import { __decorate } from "tslib";
import { LitFBP } from '@furo/fbp/dist/LitFBP';
import { css, html, LitElement } from 'lit';
import { property } from "lit/decorators.js";
/**
* `furo-resizer`
* container which let you resize its width.
*
* Double-click on the handler to reset the width.
* You need a counter part which flexes.
*
*
*```html
* <furo-horizontal-flex>
* <div flex> the flexible part </div>
* <!-- you have to set at leas one handle to resize the content -->
* <furo-resizer righthandle remember="logv" minwidth="280" maxwidth="780">
* <some-content></some-content>
* </furo-resizer>
* </furo-horizontal-flex>
*```
*
* @attribute {void} righthandle - add a handle to the right side.
* @attribute {void} lefthandle - add a handle to the left side.
* @slot {HTMLElement [0..n]} - default slot to add content.
* @summary resizable box
* @demo demo-furo-resizer Basic usage
* @customElement
* @appliesMixin FBP
*/
export class FuroResizer extends LitFBP(LitElement) {
constructor() {
super(...arguments);
this._positions = { x: 0 };
/**
* remove the listeners
*/
this._unregister = () => {
window.removeEventListener('mousemove', this._movementHandler);
window.removeEventListener('mouseup', this._unregister);
// set cursor to avoid flickering
this.parentNode.style.cursor = '';
};
/**
* capture the mouse movement and resize the width
* @param e MouseEvent
* @private
*/
this._movementHandler = (e) => {
const delta = (e.screenX - this._positions.x) * this._handleLRM;
// todo request animation frame
let width = this._startwidth + delta;
if (this.minwidth && width + 3 < this.minwidth) {
width = this.minwidth;
this._unregister();
}
if (this.maxwidth && width - 3 > this.maxwidth) {
width = this.maxwidth;
this._unregister();
}
this.style.width = `${width}px`;
if (this.remember) {
sessionStorage.setItem(this.remember, `${width}`);
}
};
/**
* Start mouse move tracking
* @param e
* @private
*/
this._startTracking = (e) => {
e.preventDefault();
window.addEventListener('mousemove', this._movementHandler);
window.addEventListener('mouseup', this._unregister);
this._positions.x = e.screenX;
this._startwidth = this.getBoundingClientRect().width;
// set cursor to avoid flickering
this.parentNode.style.cursor = 'col-resize';
};
this._startwidth = 0;
this._handleLRM = 1;
}
/**
* register the left handler
* @param e
* @private
*/
_startTrackingLeft(e) {
this._handleLRM = -1;
this._startTracking(e);
}
/**
* register the right handler
* @param e
* @private
*/
_startTrackingRight(e) {
this._handleLRM = 1;
this._startTracking(e);
}
/**
* removes remember and set to the initial size
*/
resetSize() {
if (this.initialWidthSetByStyle) {
this.style.width = `${this.initialWidthSetByStyle}`;
}
else {
this.style.removeProperty('width');
}
if (this.remember) {
sessionStorage.removeItem(this.remember);
}
}
/**
* flow is ready lifecycle method
* @private
*/
_FBPReady() {
super._FBPReady();
// this._FBPTraceWires()
this.leftHandle = this.shadowRoot.getElementById('lefthandle');
this.leftHandle.addEventListener('mousedown', this._startTrackingLeft.bind(this));
this.leftHandle.addEventListener('dblclick', this.resetSize.bind(this));
this.rightHandle = this.shadowRoot.getElementById('righthandle');
this.rightHandle.addEventListener('mousedown', this._startTrackingRight.bind(this));
this.rightHandle.addEventListener('dblclick', this.resetSize.bind(this));
this.initialWidthSetByStyle = this.style.width;
if (this.minwidth) {
this.style.minWidth = `${this.minwidth}px`;
}
// restore remembered value
if (this.remember) {
const width = sessionStorage.getItem(this.remember);
if (width) {
this.style.width = `${width}px`;
}
}
}
/**
* Themable Styles
* @private
* @return {CSSResult}
*/
static get styles() {
// language=CSS
return (css `
:host {
display: block;
position: relative;
}
:host([hidden]) {
display: none;
}
#lefthandle {
position: absolute;
left: -3px;
width: 6px;
top: 0;
bottom: 0;
cursor: col-resize;
display: none;
}
#righthandle {
position: absolute;
right: -3px;
width: 6px;
top: 0;
bottom: 0;
cursor: col-resize;
display: none;
}
:host([lefthandle]) #lefthandle {
display: block;
}
:host([righthandle]) #righthandle {
display: block;
}
`);
}
/**
* @private
* @returns {TemplateResult}
* @private
*/
render() {
// language=HTML
return html `
<div id="lefthandle" ></div>
<slot></slot>
<div id="righthandle"></div>
`;
}
}
__decorate([
property({ type: String, attribute: 'remember' })
], FuroResizer.prototype, "remember", void 0);
__decorate([
property({ type: Number })
], FuroResizer.prototype, "maxwidth", void 0);
__decorate([
property({ type: Number })
], FuroResizer.prototype, "minwidth", void 0);
//# sourceMappingURL=FuroResizer.js.map