@zag-js/splitter
Version:
Core logic for the splitter widget implemented as a state machine
182 lines (180 loc) • 5.89 kB
JavaScript
;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
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 __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/utils/panel.ts
var panel_exports = {};
__export(panel_exports, {
findPanelDataIndex: () => findPanelDataIndex,
findPanelIndex: () => findPanelIndex,
getPanelById: () => getPanelById,
getPanelFlexBoxStyle: () => getPanelFlexBoxStyle,
getPanelLayout: () => getPanelLayout,
getUnsafeDefaultSize: () => getUnsafeDefaultSize,
panelDataHelper: () => panelDataHelper,
serializePanels: () => serializePanels,
sortPanels: () => sortPanels
});
module.exports = __toCommonJS(panel_exports);
var import_utils = require("@zag-js/utils");
var import_size = require("./size.js");
function getPanelById(panels, id) {
const panel = panels.find((panel2) => panel2.id === id);
(0, import_utils.ensure)(panel, () => `Panel data not found for id "${id}"`);
return panel;
}
function findPanelDataIndex(panels, panel) {
return panels.findIndex((prevPanel) => prevPanel === panel || prevPanel.id === panel.id);
}
function findPanelIndex(panels, id) {
return panels.findIndex((panel) => panel.id === id);
}
function panelDataHelper(panels, panel, sizes) {
const index = findPanelIndex(panels, panel.id);
const pivotIndices = index === panels.length - 1 ? [index - 1, index] : [index, index + 1];
const panelSize = sizes[index];
return { ...panel, panelSize, pivotIndices };
}
function sortPanels(panels) {
return panels.sort((panelA, panelB) => {
const orderA = panelA.order;
const orderB = panelB.order;
if (orderA == null && orderB == null) {
return 0;
} else if (orderA == null) {
return -1;
} else if (orderB == null) {
return 1;
} else {
return orderA - orderB;
}
});
}
function getPanelLayout(panels) {
return panels.map((panel) => panel.id).sort().join(":");
}
function serializePanels(panels) {
const keys = panels.map((panel) => panel.id);
const sortedKeys = keys.sort();
const serialized = sortedKeys.map((key) => {
const panel = panels.find((panel2) => panel2.id === key);
return JSON.stringify(panel);
});
return serialized.join(",");
}
function getPanelFlexBoxStyle({
size,
defaultSize,
dragState,
resolvedSizes,
panels,
panelIndex,
horizontal,
precision = 3
}) {
const resolvedSize = resolvedSizes[panelIndex];
const layoutSize = size ?? defaultSize;
const panel = panels[panelIndex];
let flexGrow;
let flexBasis;
let flexShrink = 1;
const constraintAxis = horizontal ? "Width" : "Height";
const minSize = panel ? (0, import_size.toCssPanelSize)(panel.minSize) : void 0;
const maxSize = panel ? (0, import_size.toCssPanelSize)(panel.maxSize) : void 0;
const layoutCssSize = (0, import_size.toCssPanelSize)(layoutSize);
if (resolvedSize == null) {
if (layoutCssSize != null) {
if (layoutCssSize.endsWith("%")) {
flexGrow = Number.parseFloat(layoutCssSize).toPrecision(precision);
} else {
flexBasis = getClampedFlexBasis({
basis: layoutCssSize,
minSize,
maxSize
});
flexGrow = "0";
flexShrink = 0;
}
} else {
flexGrow = "1";
}
} else if (panels.length === 1) {
flexGrow = "1";
} else {
flexGrow = resolvedSize.toPrecision(precision);
}
return {
flexBasis: flexBasis ?? 0,
flexGrow,
flexShrink,
...minSize ? { [`min${constraintAxis}`]: minSize } : {},
...maxSize ? { [`max${constraintAxis}`]: maxSize } : {},
// Without this, Panel sizes may be unintentionally overridden by their content
overflow: "hidden",
// Disable pointer events inside of a panel during resize
// This avoid edge cases like nested iframes
pointerEvents: dragState !== null ? "none" : void 0
};
}
function getClampedFlexBasis({
basis,
minSize,
maxSize
}) {
return `clamp(${minSize ?? "0%"}, ${basis}, ${maxSize ?? "100%"})`;
}
function getUnsafeDefaultSize({ panels, size: sizes }) {
const finalSizes = Array(panels.length);
let numPanelsWithSizes = 0;
let remainingSize = 100;
for (let index = 0; index < panels.length; index++) {
const panel = panels[index];
(0, import_utils.ensure)(panel, () => `Panel data not found for index ${index}`);
const defaultSize = sizes[index];
if (defaultSize != null) {
numPanelsWithSizes++;
finalSizes[index] = defaultSize;
remainingSize -= defaultSize;
}
}
for (let index = 0; index < panels.length; index++) {
const panel = panels[index];
(0, import_utils.ensure)(panel, () => `Panel data not found for index ${index}`);
const defaultSize = sizes[index];
if (defaultSize != null) {
continue;
}
const numRemainingPanels = panels.length - numPanelsWithSizes;
const size = remainingSize / numRemainingPanels;
numPanelsWithSizes++;
finalSizes[index] = size;
remainingSize -= size;
}
return finalSizes;
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
findPanelDataIndex,
findPanelIndex,
getPanelById,
getPanelFlexBoxStyle,
getPanelLayout,
getUnsafeDefaultSize,
panelDataHelper,
serializePanels,
sortPanels
});