@zag-js/splitter
Version:
Core logic for the splitter widget implemented as a state machine
151 lines (149 loc) • 4.46 kB
JavaScript
import "../chunk-QZ7TP4HQ.mjs";
// src/utils/panel.ts
import { ensure } from "@zag-js/utils";
import { toCssPanelSize } from "./size.mjs";
function getPanelById(panels, id) {
const panel = panels.find((panel2) => panel2.id === id);
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 ? toCssPanelSize(panel.minSize) : void 0;
const maxSize = panel ? toCssPanelSize(panel.maxSize) : void 0;
const layoutCssSize = 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];
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];
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;
}
export {
findPanelDataIndex,
findPanelIndex,
getPanelById,
getPanelFlexBoxStyle,
getPanelLayout,
getUnsafeDefaultSize,
panelDataHelper,
serializePanels,
sortPanels
};