rkgk/static/resize-handle.js
リキ萌 0ddc42c00f sidebar layout
switch the app from floating panels to a static sidebar on the right with resizable tools
expect more layout bugs from now on
2025-06-27 23:24:09 +02:00

96 lines
3.2 KiB
JavaScript

import { listen, SaveData } from "rkgk/framework.js";
export class ResizeHandle extends HTMLElement {
saveData = new SaveData("resizeHandle");
constructor(props) {
super();
this.props = props;
}
connectedCallback() {
let props = this.props ?? this.dataset;
this.direction = this.dataset.direction = props.direction;
this.targetProperty = props.targetProperty;
this.initSize = parseInt(props.initSize);
this.minSize = parseInt(props.minSize);
this.inverse = props.inverse != null;
if (props.targetElement != null) {
// In case you want to construct the resize handle programatically:
// pass in the target element via targetElement.
// Don't forget to set its id.
this.target = props.targetElement;
this.targetId = this.target.id;
} else {
// Else use data-target.
this.targetId = props.target;
this.target = document.getElementById(this.targetId);
}
this.saveData.elementId = this.targetId;
// NOTE(localStorage): Migration from old local storage key.
let oldSizeKey = `rkgk.resizeHandle.size.${this.targetId}`;
this.#setSize(
this.saveData.get("size") ?? localStorage.getItem(oldSizeKey) ?? this.initSize,
);
this.#saveSize();
this.#updateTargetProperty();
this.visual = this.appendChild(document.createElement("div"));
this.visual.classList.add("visual");
this.#draggingBehaviour();
// NOTE(localStorage): Migration from old local storage key.
localStorage.removeItem(oldSizeKey);
}
#setSize(newSize) {
if (newSize != newSize) {
newSize = this.initSize;
}
this.size = Math.max(this.minSize, newSize);
}
#saveSize() {
this.saveData.set("size", this.size);
}
#updateTargetProperty() {
this.target.style.setProperty(this.targetProperty, `${this.size}px`);
}
async #draggingBehaviour() {
while (true) {
let mouseDown = await listen([this, "mousedown"]);
let startingSize = this.size;
if (mouseDown.button == 0) {
mouseDown.preventDefault();
this.classList.add("dragging");
while (true) {
let event = await listen([window, "mousemove"], [window, "mouseup"]);
if (event.type == "mousemove") {
let delta =
this.direction == "vertical"
? event.clientX - mouseDown.clientX
: event.clientY - mouseDown.clientY;
if (this.inverse) delta = -delta;
this.#setSize(startingSize + delta);
this.#updateTargetProperty();
} else if (event.type == "mouseup") {
this.classList.remove("dragging");
this.#saveSize();
break;
}
}
}
}
}
}
customElements.define("rkgk-resize-handle", ResizeHandle);