react-mosaic-component2
Version:
A React Tiling Window Manager
147 lines (145 loc) • 6.06 kB
JavaScript
"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/Split.tsx
var Split_exports = {};
__export(Split_exports, {
Split: () => Split
});
module.exports = __toCommonJS(Split_exports);
var import_classnames = __toESM(require("classnames"), 1);
var import_lodash_es = require("lodash-es");
var import_lodash_es2 = require("lodash-es");
var import_react = __toESM(require("react"), 1);
var import_BoundingBox = require("./util/BoundingBox.cjs");
var RESIZE_THROTTLE_MS = 1e3 / 30;
var TOUCH_EVENT_OPTIONS = {
capture: true,
passive: false
};
var Split = class extends import_react.default.PureComponent {
rootElement = import_react.default.createRef();
listenersBound = false;
static defaultProps = {
onChange: () => void 0,
onRelease: () => void 0,
minimumPaneSizePercentage: 20
};
render() {
const { direction } = this.props;
return /* @__PURE__ */ import_react.default.createElement(
"div",
{
className: (0, import_classnames.default)("mosaic-split", {
"-row": direction === "row",
"-column": direction === "column"
}),
ref: this.rootElement,
onMouseDown: this.onMouseDown,
style: this.computeStyle()
},
/* @__PURE__ */ import_react.default.createElement("div", { className: "mosaic-split-line" })
);
}
componentDidMount() {
this.rootElement.current.addEventListener("touchstart", this.onMouseDown, TOUCH_EVENT_OPTIONS);
}
componentWillUnmount() {
this.unbindListeners();
if (this.rootElement.current) {
this.rootElement.current.ownerDocument.removeEventListener("touchstart", this.onMouseDown, TOUCH_EVENT_OPTIONS);
}
}
bindListeners() {
if (!this.listenersBound) {
this.rootElement.current.ownerDocument.addEventListener("mousemove", this.onMouseMove, true);
this.rootElement.current.ownerDocument.addEventListener("touchmove", this.onMouseMove, TOUCH_EVENT_OPTIONS);
this.rootElement.current.ownerDocument.addEventListener("mouseup", this.onMouseUp, true);
this.rootElement.current.ownerDocument.addEventListener("touchend", this.onMouseUp, true);
this.listenersBound = true;
}
}
unbindListeners() {
if (this.rootElement.current) {
this.rootElement.current.ownerDocument.removeEventListener("mousemove", this.onMouseMove, true);
this.rootElement.current.ownerDocument.removeEventListener("touchmove", this.onMouseMove, TOUCH_EVENT_OPTIONS);
this.rootElement.current.ownerDocument.removeEventListener("mouseup", this.onMouseUp, true);
this.rootElement.current.ownerDocument.removeEventListener("touchend", this.onMouseUp, true);
this.listenersBound = false;
}
}
computeStyle() {
const { boundingBox, direction, splitPercentage } = this.props;
const positionStyle = direction === "column" ? "top" : "left";
const absolutePercentage = import_BoundingBox.BoundingBox.getAbsoluteSplitPercentage(boundingBox, splitPercentage, direction);
return {
...import_BoundingBox.BoundingBox.asStyles(boundingBox),
[positionStyle]: `${absolutePercentage}%`
};
}
onMouseDown = (event) => {
if (!isTouchEvent(event)) {
if (event.button !== 0) {
return;
}
}
event.preventDefault();
this.bindListeners();
};
onMouseUp = (event) => {
this.unbindListeners();
const percentage = this.calculateRelativePercentage(event);
this.props.onRelease(percentage);
};
onMouseMove = (event) => {
event.preventDefault();
this.throttledUpdatePercentage(event);
};
throttledUpdatePercentage = (0, import_lodash_es2.throttle)((event) => {
const percentage = this.calculateRelativePercentage(event);
if (percentage !== this.props.splitPercentage) {
this.props.onChange(percentage);
}
}, RESIZE_THROTTLE_MS);
calculateRelativePercentage(event) {
const { minimumPaneSizePercentage, direction, boundingBox } = this.props;
const parentBBox = this.rootElement.current.parentElement.getBoundingClientRect();
const location = isTouchEvent(event) ? event.changedTouches[0] : event;
let absolutePercentage;
if (direction === "column") {
absolutePercentage = (location.clientY - parentBBox.top) / parentBBox.height * 100;
} else {
absolutePercentage = (location.clientX - parentBBox.left) / parentBBox.width * 100;
}
const relativePercentage = import_BoundingBox.BoundingBox.getRelativeSplitPercentage(boundingBox, absolutePercentage, direction);
return (0, import_lodash_es.clamp)(relativePercentage, minimumPaneSizePercentage, 100 - minimumPaneSizePercentage);
}
};
function isTouchEvent(event) {
return event.changedTouches != null;
}