react-resizable-panels
Version:
<img src="https://react-resizable-panels.vercel.app/og.png" alt="react-resizable-panels logo" width="400" height="210" />
1,972 lines • 52.2 kB
JavaScript
"use client";
import { jsx as te } from "react/jsx-runtime";
import { useState as ne, useCallback as Q, useId as rt, useLayoutEffect as Ae, useEffect as ue, useRef as O, createContext as st, useImperativeHandle as Ne, useMemo as _e, useSyncExternalStore as Fe, useContext as at } from "react";
function lt(e, t) {
const n = getComputedStyle(e), o = parseFloat(n.fontSize);
return t * o;
}
function ut(e, t) {
const n = getComputedStyle(e.ownerDocument.body), o = parseFloat(n.fontSize);
return t * o;
}
function ct(e) {
return e / 100 * window.innerHeight;
}
function ft(e) {
return e / 100 * window.innerWidth;
}
function dt(e) {
switch (typeof e) {
case "number":
return [e, "px"];
case "string": {
const t = parseFloat(e);
return e.endsWith("%") ? [t, "%"] : e.endsWith("px") ? [t, "px"] : e.endsWith("rem") ? [t, "rem"] : e.endsWith("em") ? [t, "em"] : e.endsWith("vh") ? [t, "vh"] : e.endsWith("vw") ? [t, "vw"] : [t, "%"];
}
}
}
function re({
groupSize: e,
panelElement: t,
styleProp: n
}) {
let o;
const [i, s] = dt(n);
switch (s) {
case "%": {
o = i / 100 * e;
break;
}
case "px": {
o = i;
break;
}
case "rem": {
o = ut(t, i);
break;
}
case "em": {
o = lt(t, i);
break;
}
case "vh": {
o = ct(i);
break;
}
case "vw": {
o = ft(i);
break;
}
}
return o;
}
function _(e) {
return parseFloat(e.toFixed(3));
}
function J({
group: e
}) {
const { orientation: t, panels: n } = e;
return n.reduce((o, i) => (o += t === "horizontal" ? i.element.offsetWidth : i.element.offsetHeight, o), 0);
}
function pe(e) {
const { panels: t } = e, n = J({ group: e });
return n === 0 ? t.map((o) => ({
collapsedSize: 0,
collapsible: o.panelConstraints.collapsible === !0,
defaultSize: void 0,
disabled: o.panelConstraints.disabled,
minSize: 0,
maxSize: 100,
panelId: o.id
})) : t.map((o) => {
const { element: i, panelConstraints: s } = o;
let l = 0;
if (s.collapsedSize !== void 0) {
const c = re({
groupSize: n,
panelElement: i,
styleProp: s.collapsedSize
});
l = _(c / n * 100);
}
let r;
if (s.defaultSize !== void 0) {
const c = re({
groupSize: n,
panelElement: i,
styleProp: s.defaultSize
});
r = _(c / n * 100);
}
let a = 0;
if (s.minSize !== void 0) {
const c = re({
groupSize: n,
panelElement: i,
styleProp: s.minSize
});
a = _(c / n * 100);
}
let u = 100;
if (s.maxSize !== void 0) {
const c = re({
groupSize: n,
panelElement: i,
styleProp: s.maxSize
});
u = _(c / n * 100);
}
return {
collapsedSize: l,
collapsible: s.collapsible === !0,
defaultSize: r,
disabled: s.disabled,
minSize: a,
maxSize: u,
panelId: o.id
};
});
}
function P(e, t = "Assertion error") {
if (!e)
throw Error(t);
}
function he(e, t) {
return Array.from(t).sort(
e === "horizontal" ? pt : ht
);
}
function pt(e, t) {
const n = e.element.offsetLeft - t.element.offsetLeft;
return n !== 0 ? n : e.element.offsetWidth - t.element.offsetWidth;
}
function ht(e, t) {
const n = e.element.offsetTop - t.element.offsetTop;
return n !== 0 ? n : e.element.offsetHeight - t.element.offsetHeight;
}
function $e(e) {
return e !== null && typeof e == "object" && "nodeType" in e && e.nodeType === Node.ELEMENT_NODE;
}
function He(e, t) {
return {
x: e.x >= t.left && e.x <= t.right ? 0 : Math.min(
Math.abs(e.x - t.left),
Math.abs(e.x - t.right)
),
y: e.y >= t.top && e.y <= t.bottom ? 0 : Math.min(
Math.abs(e.y - t.top),
Math.abs(e.y - t.bottom)
)
};
}
function mt({
orientation: e,
rects: t,
targetRect: n
}) {
const o = {
x: n.x + n.width / 2,
y: n.y + n.height / 2
};
let i, s = Number.MAX_VALUE;
for (const l of t) {
const { x: r, y: a } = He(o, l), u = e === "horizontal" ? r : a;
u < s && (s = u, i = l);
}
return P(i, "No rect found"), i;
}
let se;
function gt() {
return se === void 0 && (typeof matchMedia == "function" ? se = !!matchMedia("(pointer:coarse)").matches : se = !1), se;
}
function Ve(e) {
const { element: t, orientation: n, panels: o, separators: i } = e, s = he(
n,
Array.from(t.children).filter($e).map((m) => ({ element: m }))
).map(({ element: m }) => m), l = [];
let r = !1, a = !1, u = -1, c = -1, g = 0, b, S = [];
{
let m = -1;
for (const d of s)
d.hasAttribute("data-panel") && (m++, d.ariaDisabled === null && (g++, u === -1 && (u = m), c = m));
}
if (g > 1) {
let m = -1;
for (const d of s)
if (d.hasAttribute("data-panel")) {
m++;
const f = o.find(
(h) => h.element === d
);
if (f) {
if (b) {
const h = b.element.getBoundingClientRect(), v = d.getBoundingClientRect();
let x;
if (a) {
const y = n === "horizontal" ? new DOMRect(
h.right,
h.top,
0,
h.height
) : new DOMRect(
h.left,
h.bottom,
h.width,
0
), p = n === "horizontal" ? new DOMRect(v.left, v.top, 0, v.height) : new DOMRect(v.left, v.top, v.width, 0);
switch (S.length) {
case 0: {
x = [
y,
p
];
break;
}
case 1: {
const w = S[0], C = mt({
orientation: n,
rects: [h, v],
targetRect: w.element.getBoundingClientRect()
});
x = [
w,
C === h ? p : y
];
break;
}
default: {
x = S;
break;
}
}
} else
S.length ? x = S : x = [
n === "horizontal" ? new DOMRect(
h.right,
v.top,
v.left - h.right,
v.height
) : new DOMRect(
v.left,
h.bottom,
v.width,
v.top - h.bottom
)
];
for (const y of x) {
let p = "width" in y ? y : y.element.getBoundingClientRect();
const w = gt() ? e.resizeTargetMinimumSize.coarse : e.resizeTargetMinimumSize.fine;
if (p.width < w) {
const R = w - p.width;
p = new DOMRect(
p.x - R / 2,
p.y,
p.width + R,
p.height
);
}
if (p.height < w) {
const R = w - p.height;
p = new DOMRect(
p.x,
p.y - R / 2,
p.width,
p.height + R
);
}
const C = m <= u || m > c;
!r && !C && l.push({
group: e,
groupSize: J({ group: e }),
panels: [b, f],
separator: "width" in y ? void 0 : y,
rect: p
}), r = !1;
}
}
a = !1, b = f, S = [];
}
} else if (d.hasAttribute("data-separator")) {
d.ariaDisabled !== null && (r = !0);
const f = i.find(
(h) => h.element === d
);
f ? S.push(f) : (b = void 0, S = []);
} else
a = !0;
}
return l;
}
class yt {
#e = {};
addListener(t, n) {
const o = this.#e[t];
return o === void 0 ? this.#e[t] = [n] : o.includes(n) || o.push(n), () => {
this.removeListener(t, n);
};
}
emit(t, n) {
const o = this.#e[t];
if (o !== void 0)
if (o.length === 1)
o[0].call(null, n);
else {
let i = !1, s = null;
const l = Array.from(o);
for (let r = 0; r < l.length; r++) {
const a = l[r];
try {
a.call(null, n);
} catch (u) {
s === null && (i = !0, s = u);
}
}
if (i)
throw s;
}
}
removeAllListeners() {
this.#e = {};
}
removeListener(t, n) {
const o = this.#e[t];
if (o !== void 0) {
const i = o.indexOf(n);
i >= 0 && o.splice(i, 1);
}
}
}
function k(e, t, n = 0) {
return Math.abs(_(e) - _(t)) <= n;
}
let A = {
cursorFlags: 0,
interactionState: {
state: "inactive"
},
mountedGroups: /* @__PURE__ */ new Map()
};
const $ = new yt();
function G() {
return A;
}
function I(e) {
const t = typeof e == "function" ? e(A) : e;
if (A === t)
return A;
const n = A;
return A = {
...A,
...t
}, t.cursorFlags !== void 0 && $.emit("cursorFlagsChange", A.cursorFlags), t.interactionState !== void 0 && $.emit("interactionStateChange", A.interactionState), t.mountedGroups !== void 0 && (A.mountedGroups.forEach((o, i) => {
o.derivedPanelConstraints.forEach((s) => {
if (s.collapsible) {
const { layout: l } = n.mountedGroups.get(i) ?? {};
if (l) {
const r = k(
s.collapsedSize,
o.layout[s.panelId]
), a = k(
s.collapsedSize,
l[s.panelId]
);
r && !a && (i.inMemoryLastExpandedPanelSizes[s.panelId] = l[s.panelId]);
}
}
});
}), $.emit("mountedGroupsChange", A.mountedGroups)), A;
}
function St(e, t, n) {
let o, i = {
x: 1 / 0,
y: 1 / 0
};
for (const s of t) {
const l = He(n, s.rect);
switch (e) {
case "horizontal": {
l.x <= i.x && (o = s, i = l);
break;
}
case "vertical": {
l.y <= i.y && (o = s, i = l);
break;
}
}
}
return o ? {
distance: i,
hitRegion: o
} : void 0;
}
function vt(e) {
return e !== null && typeof e == "object" && "nodeType" in e && e.nodeType === Node.DOCUMENT_FRAGMENT_NODE;
}
function xt(e, t) {
if (e === t) throw new Error("Cannot compare node with itself");
const n = {
a: we(e),
b: we(t)
};
let o;
for (; n.a.at(-1) === n.b.at(-1); )
o = n.a.pop(), n.b.pop();
P(
o,
"Stacking order can only be calculated for elements with a common ancestor"
);
const i = {
a: be(ze(n.a)),
b: be(ze(n.b))
};
if (i.a === i.b) {
const s = o.childNodes, l = {
a: n.a.at(-1),
b: n.b.at(-1)
};
let r = s.length;
for (; r--; ) {
const a = s[r];
if (a === l.a) return 1;
if (a === l.b) return -1;
}
}
return Math.sign(i.a - i.b);
}
const zt = /\b(?:position|zIndex|opacity|transform|webkitTransform|mixBlendMode|filter|webkitFilter|isolation)\b/;
function bt(e) {
const t = getComputedStyle(je(e) ?? e).display;
return t === "flex" || t === "inline-flex";
}
function wt(e) {
const t = getComputedStyle(e);
return !!(t.position === "fixed" || t.zIndex !== "auto" && (t.position !== "static" || bt(e)) || +t.opacity < 1 || "transform" in t && t.transform !== "none" || "webkitTransform" in t && t.webkitTransform !== "none" || "mixBlendMode" in t && t.mixBlendMode !== "normal" || "filter" in t && t.filter !== "none" || "webkitFilter" in t && t.webkitFilter !== "none" || "isolation" in t && t.isolation === "isolate" || zt.test(t.willChange) || t.webkitOverflowScrolling === "touch");
}
function ze(e) {
let t = e.length;
for (; t--; ) {
const n = e[t];
if (P(n, "Missing node"), wt(n)) return n;
}
return null;
}
function be(e) {
return e && Number(getComputedStyle(e).zIndex) || 0;
}
function we(e) {
const t = [];
for (; e; )
t.push(e), e = je(e);
return t;
}
function je(e) {
const { parentNode: t } = e;
return vt(t) ? t.host : t;
}
function Lt(e, t) {
return e.x < t.x + t.width && e.x + e.width > t.x && e.y < t.y + t.height && e.y + e.height > t.y;
}
function Pt({
groupElement: e,
hitRegion: t,
pointerEventTarget: n
}) {
if (!$e(n) || n.contains(e) || e.contains(n))
return !0;
if (xt(n, e) > 0) {
let o = n;
for (; o; ) {
if (o.contains(e))
return !0;
if (Lt(o.getBoundingClientRect(), t))
return !1;
o = o.parentElement;
}
}
return !0;
}
function me(e, t) {
const n = [];
return t.forEach((o, i) => {
if (i.disabled)
return;
const s = Ve(i), l = St(i.orientation, s, {
x: e.clientX,
y: e.clientY
});
l && l.distance.x <= 0 && l.distance.y <= 0 && Pt({
groupElement: i.element,
hitRegion: l.hitRegion.rect,
pointerEventTarget: e.target
}) && n.push(l.hitRegion);
}), n;
}
function Ct(e, t) {
if (e.length !== t.length)
return !1;
for (let n = 0; n < e.length; n++)
if (e[n] != t[n])
return !1;
return !0;
}
function F(e, t) {
return k(e, t) ? 0 : e > t ? 1 : -1;
}
function Y({
overrideDisabledPanels: e,
panelConstraints: t,
prevSize: n,
size: o
}) {
const {
collapsedSize: i = 0,
collapsible: s,
disabled: l,
maxSize: r = 100,
minSize: a = 0
} = t;
if (l && !e)
return n;
if (F(o, a) < 0)
if (s) {
const u = (i + a) / 2;
F(o, u) < 0 ? o = i : o = a;
} else
o = a;
return o = Math.min(r, o), o = _(o), o;
}
function oe({
delta: e,
initialLayout: t,
panelConstraints: n,
pivotIndices: o,
prevLayout: i,
trigger: s
}) {
if (k(e, 0))
return t;
const l = s === "imperative-api", r = Object.values(t), a = Object.values(i), u = [...r], [c, g] = o;
P(c != null, "Invalid first pivot index"), P(g != null, "Invalid second pivot index");
let b = 0;
switch (s) {
case "keyboard": {
{
const d = e < 0 ? g : c, f = n[d];
P(
f,
`Panel constraints not found for index ${d}`
);
const {
collapsedSize: h = 0,
collapsible: v,
minSize: x = 0
} = f;
if (v) {
const y = r[d];
if (P(
y != null,
`Previous layout not found for panel index ${d}`
), k(y, h)) {
const p = x - y;
F(p, Math.abs(e)) > 0 && (e = e < 0 ? 0 - p : p);
}
}
}
{
const d = e < 0 ? c : g, f = n[d];
P(
f,
`No panel constraints found for index ${d}`
);
const {
collapsedSize: h = 0,
collapsible: v,
minSize: x = 0
} = f;
if (v) {
const y = r[d];
if (P(
y != null,
`Previous layout not found for panel index ${d}`
), k(y, x)) {
const p = y - h;
F(p, Math.abs(e)) > 0 && (e = e < 0 ? 0 - p : p);
}
}
}
break;
}
default: {
const d = e < 0 ? g : c, f = n[d];
P(
f,
`Panel constraints not found for index ${d}`
);
const h = r[d], { collapsible: v, collapsedSize: x, minSize: y } = f;
if (v && F(h, y) < 0)
if (e > 0) {
const p = y - x, w = p / 2, C = h + e;
F(C, y) < 0 && (e = F(e, w) <= 0 ? 0 : p);
} else {
const p = y - x, w = 100 - p / 2, C = h - e;
F(C, y) < 0 && (e = F(100 + e, w) > 0 ? 0 : -p);
}
break;
}
}
{
const d = e < 0 ? 1 : -1;
let f = e < 0 ? g : c, h = 0;
for (; ; ) {
const x = r[f];
P(
x != null,
`Previous layout not found for panel index ${f}`
);
const p = Y({
overrideDisabledPanels: l,
panelConstraints: n[f],
prevSize: x,
size: 100
}) - x;
if (h += p, f += d, f < 0 || f >= n.length)
break;
}
const v = Math.min(Math.abs(e), Math.abs(h));
e = e < 0 ? 0 - v : v;
}
{
let f = e < 0 ? c : g;
for (; f >= 0 && f < n.length; ) {
const h = Math.abs(e) - Math.abs(b), v = r[f];
P(
v != null,
`Previous layout not found for panel index ${f}`
);
const x = v - h, y = Y({
overrideDisabledPanels: l,
panelConstraints: n[f],
prevSize: v,
size: x
});
if (!k(v, y) && (b += v - y, u[f] = y, b.toFixed(3).localeCompare(Math.abs(e).toFixed(3), void 0, {
numeric: !0
}) >= 0))
break;
e < 0 ? f-- : f++;
}
}
if (Ct(a, u))
return i;
{
const d = e < 0 ? g : c, f = r[d];
P(
f != null,
`Previous layout not found for panel index ${d}`
);
const h = f + b, v = Y({
overrideDisabledPanels: l,
panelConstraints: n[d],
prevSize: f,
size: h
});
if (u[d] = v, !k(v, h)) {
let x = h - v, p = e < 0 ? g : c;
for (; p >= 0 && p < n.length; ) {
const w = u[p];
P(
w != null,
`Previous layout not found for panel index ${p}`
);
const C = w + x, R = Y({
overrideDisabledPanels: l,
panelConstraints: n[p],
prevSize: w,
size: C
});
if (k(w, R) || (x -= R - w, u[p] = R), k(x, 0))
break;
e > 0 ? p-- : p++;
}
}
}
const S = Object.values(u).reduce(
(d, f) => f + d,
0
);
if (!k(S, 100, 0.1))
return i;
const m = Object.keys(i);
return u.reduce((d, f, h) => (d[m[h]] = f, d), {});
}
function U(e, t) {
if (Object.keys(e).length !== Object.keys(t).length)
return !1;
for (const n in e)
if (t[n] === void 0 || F(e[n], t[n]) !== 0)
return !1;
return !0;
}
function B({
layout: e,
panelConstraints: t
}) {
const n = Object.values(e), o = [...n], i = o.reduce(
(r, a) => r + a,
0
);
if (o.length !== t.length)
throw Error(
`Invalid ${t.length} panel layout: ${o.map((r) => `${r}%`).join(", ")}`
);
if (!k(i, 100) && o.length > 0)
for (let r = 0; r < t.length; r++) {
const a = o[r];
P(a != null, `No layout data found for index ${r}`);
const u = 100 / i * a;
o[r] = u;
}
let s = 0;
for (let r = 0; r < t.length; r++) {
const a = n[r];
P(a != null, `No layout data found for index ${r}`);
const u = o[r];
P(u != null, `No layout data found for index ${r}`);
const c = Y({
overrideDisabledPanels: !0,
panelConstraints: t[r],
prevSize: a,
size: u
});
u != c && (s += u - c, o[r] = c);
}
if (!k(s, 0))
for (let r = 0; r < t.length; r++) {
const a = o[r];
P(a != null, `No layout data found for index ${r}`);
const u = a + s, c = Y({
overrideDisabledPanels: !0,
panelConstraints: t[r],
prevSize: a,
size: u
});
if (a !== c && (s -= c - a, o[r] = c, k(s, 0)))
break;
}
const l = Object.keys(e);
return o.reduce((r, a, u) => (r[l[u]] = a, r), {});
}
function We({
groupId: e,
panelId: t
}) {
const n = () => {
const { mountedGroups: r } = G();
for (const [
a,
{
defaultLayoutDeferred: u,
derivedPanelConstraints: c,
layout: g,
separatorToPanels: b
}
] of r)
if (a.id === e)
return {
defaultLayoutDeferred: u,
derivedPanelConstraints: c,
group: a,
layout: g,
separatorToPanels: b
};
throw Error(`Group ${e} not found`);
}, o = () => {
const r = n().derivedPanelConstraints.find(
(a) => a.panelId === t
);
if (r !== void 0)
return r;
throw Error(`Panel constraints not found for Panel ${t}`);
}, i = () => {
const r = n().group.panels.find((a) => a.id === t);
if (r !== void 0)
return r;
throw Error(`Layout not found for Panel ${t}`);
}, s = () => {
const r = n().layout[t];
if (r !== void 0)
return r;
throw Error(`Layout not found for Panel ${t}`);
}, l = (r) => {
const a = s();
if (r === a)
return;
const {
defaultLayoutDeferred: u,
derivedPanelConstraints: c,
group: g,
layout: b,
separatorToPanels: S
} = n(), m = g.panels.findIndex((v) => v.id === t), d = m === g.panels.length - 1, f = oe({
delta: d ? a - r : r - a,
initialLayout: b,
panelConstraints: c,
pivotIndices: d ? [m - 1, m] : [m, m + 1],
prevLayout: b,
trigger: "imperative-api"
}), h = B({
layout: f,
panelConstraints: c
});
U(b, h) || I((v) => ({
mountedGroups: new Map(v.mountedGroups).set(g, {
defaultLayoutDeferred: u,
derivedPanelConstraints: c,
layout: h,
separatorToPanels: S
})
}));
};
return {
collapse: () => {
const { collapsible: r, collapsedSize: a } = o(), { mutableValues: u } = i(), c = s();
r && c !== a && (u.expandToSize = c, l(a));
},
expand: () => {
const { collapsible: r, collapsedSize: a, minSize: u } = o(), { mutableValues: c } = i(), g = s();
if (r && g === a) {
let b = c.expandToSize ?? u;
b === 0 && (b = 1), l(b);
}
},
getSize: () => {
const { group: r } = n(), a = s(), { element: u } = i(), c = r.orientation === "horizontal" ? u.offsetWidth : u.offsetHeight;
return {
asPercentage: a,
inPixels: c
};
},
isCollapsed: () => {
const { collapsible: r, collapsedSize: a } = o(), u = s();
return r && k(a, u);
},
resize: (r) => {
if (s() !== r) {
let u;
switch (typeof r) {
case "number": {
const { group: c } = n(), g = J({ group: c });
u = _(r / g * 100);
break;
}
case "string": {
u = parseFloat(r);
break;
}
}
l(u);
}
}
};
}
function Le(e) {
if (e.defaultPrevented)
return;
const { mountedGroups: t } = G();
me(e, t).forEach((o) => {
if (o.separator) {
const i = o.panels.find(
(s) => s.panelConstraints.defaultSize !== void 0
);
if (i) {
const s = i.panelConstraints.defaultSize, l = We({
groupId: o.group.id,
panelId: i.id
});
l && s !== void 0 && (l.resize(s), e.preventDefault());
}
}
});
}
function le(e) {
const { mountedGroups: t } = G();
for (const [n] of t)
if (n.separators.some(
(o) => o.element === e
))
return n;
throw Error("Could not find parent Group for separator element");
}
function Ue({
groupId: e
}) {
const t = () => {
const { mountedGroups: n } = G();
for (const [o, i] of n)
if (o.id === e)
return { group: o, ...i };
throw Error(`Could not find Group with id "${e}"`);
};
return {
getLayout() {
const { defaultLayoutDeferred: n, layout: o } = t();
return n ? {} : o;
},
setLayout(n) {
const {
defaultLayoutDeferred: o,
derivedPanelConstraints: i,
group: s,
layout: l,
separatorToPanels: r
} = t(), a = B({
layout: n,
panelConstraints: i
});
return o ? l : (U(l, a) || I((u) => ({
mountedGroups: new Map(u.mountedGroups).set(s, {
defaultLayoutDeferred: o,
derivedPanelConstraints: i,
layout: a,
separatorToPanels: r
})
})), a);
}
};
}
function Be(e) {
const { mountedGroups: t } = G(), n = t.get(e);
return P(n, `Mounted Group ${e.id} not found`), n;
}
function W(e, t) {
const n = le(e), o = Be(n), i = n.separators.find(
(g) => g.element === e
);
P(i, "Matching separator not found");
const s = o.separatorToPanels.get(i);
P(s, "Matching panels not found");
const l = s.map((g) => n.panels.indexOf(g)), a = Ue({ groupId: n.id }).getLayout(), u = oe({
delta: t,
initialLayout: a,
panelConstraints: o.derivedPanelConstraints,
pivotIndices: l,
prevLayout: a,
trigger: "keyboard"
}), c = B({
layout: u,
panelConstraints: o.derivedPanelConstraints
});
U(a, c) || I((g) => ({
mountedGroups: new Map(g.mountedGroups).set(n, {
defaultLayoutDeferred: o.defaultLayoutDeferred,
derivedPanelConstraints: o.derivedPanelConstraints,
layout: c,
separatorToPanels: o.separatorToPanels
})
}));
}
function Pe(e) {
if (e.defaultPrevented)
return;
const t = e.currentTarget, n = le(t);
if (!n.disabled)
switch (e.key) {
case "ArrowDown": {
e.preventDefault(), n.orientation === "vertical" && W(t, 5);
break;
}
case "ArrowLeft": {
e.preventDefault(), n.orientation === "horizontal" && W(t, -5);
break;
}
case "ArrowRight": {
e.preventDefault(), n.orientation === "horizontal" && W(t, 5);
break;
}
case "ArrowUp": {
e.preventDefault(), n.orientation === "vertical" && W(t, -5);
break;
}
case "End": {
e.preventDefault(), W(t, 100);
break;
}
case "Enter": {
e.preventDefault();
const o = le(t), { derivedPanelConstraints: i, layout: s, separatorToPanels: l } = Be(o), r = o.separators.find(
(g) => g.element === t
);
P(r, "Matching separator not found");
const a = l.get(r);
P(a, "Matching panels not found");
const u = a[0], c = i.find(
(g) => g.panelId === u.id
);
if (P(c, "Panel metadata not found"), c.collapsible) {
const g = s[u.id], b = c.collapsedSize === g ? o.inMemoryLastExpandedPanelSizes[u.id] ?? c.minSize : c.collapsedSize;
W(t, b - g);
}
break;
}
case "F6": {
e.preventDefault();
const i = le(t).separators.map(
(a) => a.element
), s = Array.from(i).findIndex(
(a) => a === e.currentTarget
);
P(s !== null, "Index not found");
const l = e.shiftKey ? s > 0 ? s - 1 : i.length - 1 : s + 1 < i.length ? s + 1 : 0;
i[l].focus();
break;
}
case "Home": {
e.preventDefault(), W(t, -100);
break;
}
}
}
function Ce(e) {
if (e.defaultPrevented)
return;
if (e.pointerType === "mouse" && e.button > 0)
return;
const { mountedGroups: t } = G(), n = me(e, t), o = /* @__PURE__ */ new Map();
let i = !1;
n.forEach((s) => {
s.separator && (i || (i = !0, s.separator.element.focus()));
const l = t.get(s.group);
l && o.set(s.group, l.layout);
}), I({
interactionState: {
hitRegions: n,
initialLayoutMap: o,
pointerDownAtPoint: { x: e.clientX, y: e.clientY },
state: "active"
}
}), n.length && e.preventDefault();
}
const Rt = (e) => e, fe = () => {
}, Ke = 1, Xe = 2, qe = 4, Ye = 8, Re = 3, Me = 12;
let ae;
function Ee() {
return ae === void 0 && (ae = !1, typeof window < "u" && (window.navigator.userAgent.includes("Chrome") || window.navigator.userAgent.includes("Firefox")) && (ae = !0)), ae;
}
function Mt({
cursorFlags: e,
groups: t,
state: n
}) {
let o = 0, i = 0;
switch (n) {
case "active":
case "hover":
t.forEach((s) => {
if (!s.disableCursor)
switch (s.orientation) {
case "horizontal": {
o++;
break;
}
case "vertical": {
i++;
break;
}
}
});
}
if (!(o === 0 && i === 0)) {
switch (n) {
case "active": {
if (e && Ee()) {
const s = (e & Ke) !== 0, l = (e & Xe) !== 0, r = (e & qe) !== 0, a = (e & Ye) !== 0;
if (s)
return r ? "se-resize" : a ? "ne-resize" : "e-resize";
if (l)
return r ? "sw-resize" : a ? "nw-resize" : "w-resize";
if (r)
return "s-resize";
if (a)
return "n-resize";
}
break;
}
}
return Ee() ? o > 0 && i > 0 ? "move" : o > 0 ? "ew-resize" : "ns-resize" : o > 0 && i > 0 ? "grab" : o > 0 ? "col-resize" : "row-resize";
}
}
const ke = /* @__PURE__ */ new WeakMap();
function ge(e) {
if (e.defaultView === null || e.defaultView === void 0)
return;
let { prevStyle: t, styleSheet: n } = ke.get(e) ?? {};
n === void 0 && (n = new e.defaultView.CSSStyleSheet(), e.adoptedStyleSheets && e.adoptedStyleSheets.push(n));
const { cursorFlags: o, interactionState: i } = G();
switch (i.state) {
case "active":
case "hover": {
const s = Mt({
cursorFlags: o,
groups: i.hitRegions.map((r) => r.group),
state: i.state
}), l = `*, *:hover {cursor: ${s} !important; }`;
if (t === l)
return;
t = l, s ? n.cssRules.length === 0 ? n.insertRule(l) : n.replaceSync(l) : n.cssRules.length === 1 && n.deleteRule(0);
break;
}
case "inactive": {
t = void 0, n.cssRules.length === 1 && n.deleteRule(0);
break;
}
}
ke.set(e, {
prevStyle: t,
styleSheet: n
});
}
function Je({
document: e,
event: t,
hitRegions: n,
initialLayoutMap: o,
mountedGroups: i,
pointerDownAtPoint: s,
prevCursorFlags: l
}) {
let r = 0;
const a = new Map(i);
n.forEach((c) => {
const { group: g, groupSize: b } = c, { disableCursor: S, orientation: m, panels: d } = g;
let f = 0;
s ? m === "horizontal" ? f = (t.clientX - s.x) / b * 100 : f = (t.clientY - s.y) / b * 100 : m === "horizontal" ? f = t.clientX < 0 ? -100 : 100 : f = t.clientY < 0 ? -100 : 100;
const h = o.get(g), {
defaultLayoutDeferred: v,
derivedPanelConstraints: x,
layout: y,
separatorToPanels: p
} = i.get(g) ?? { defaultLayoutDeferred: !1 };
if (x && h && y && p) {
const w = oe({
delta: f,
initialLayout: h,
panelConstraints: x,
pivotIndices: c.panels.map((C) => d.indexOf(C)),
prevLayout: y,
trigger: "mouse-or-touch"
});
if (U(w, y)) {
if (f !== 0 && !S)
switch (m) {
case "horizontal": {
r |= f < 0 ? Ke : Xe;
break;
}
case "vertical": {
r |= f < 0 ? qe : Ye;
break;
}
}
} else
a.set(c.group, {
defaultLayoutDeferred: v,
derivedPanelConstraints: x,
layout: w,
separatorToPanels: p
});
}
});
let u = 0;
t.movementX === 0 ? u |= l & Re : u |= r & Re, t.movementY === 0 ? u |= l & Me : u |= r & Me, I({
cursorFlags: u,
mountedGroups: a
}), ge(e);
}
function Ge(e) {
const { cursorFlags: t, interactionState: n, mountedGroups: o } = G();
switch (n.state) {
case "active":
Je({
document: e.currentTarget,
event: e,
hitRegions: n.hitRegions,
initialLayoutMap: n.initialLayoutMap,
mountedGroups: o,
prevCursorFlags: t
});
}
}
function Ie(e) {
if (e.defaultPrevented)
return;
const { cursorFlags: t, interactionState: n, mountedGroups: o } = G();
switch (n.state) {
case "active": {
if (
// Skip this check for "pointerleave" events, else Firefox triggers a false positive (see #514)
e.buttons === 0
) {
I(
(i) => i.interactionState.state === "inactive" ? i : {
cursorFlags: 0,
interactionState: { state: "inactive" }
}
), I((i) => ({
mountedGroups: new Map(i.mountedGroups)
}));
return;
}
Je({
document: e.currentTarget,
event: e,
hitRegions: n.hitRegions,
initialLayoutMap: n.initialLayoutMap,
mountedGroups: o,
pointerDownAtPoint: n.pointerDownAtPoint,
prevCursorFlags: t
});
break;
}
default: {
const i = me(e, o);
i.length === 0 ? n.state !== "inactive" && I({
interactionState: {
state: "inactive"
}
}) : I({
interactionState: {
hitRegions: i,
state: "hover"
}
}), ge(e.currentTarget);
break;
}
}
}
function De(e) {
if (e.relatedTarget instanceof HTMLIFrameElement) {
const { interactionState: t } = G();
switch (t.state) {
case "hover":
I({
interactionState: {
state: "inactive"
}
});
}
}
}
function Oe(e) {
if (e.defaultPrevented)
return;
if (e.pointerType === "mouse" && e.button > 0)
return;
const { interactionState: t } = G();
switch (t.state) {
case "active":
I({
cursorFlags: 0,
interactionState: {
state: "inactive"
}
}), t.hitRegions.length > 0 && (ge(e.currentTarget), I((n) => ({
mountedGroups: new Map(n.mountedGroups)
})), e.preventDefault());
}
}
function Te(e) {
let t = 0, n = 0;
const o = {};
for (const s of e)
if (s.defaultSize !== void 0) {
t++;
const l = _(s.defaultSize);
n += l, o[s.panelId] = l;
} else
o[s.panelId] = void 0;
const i = e.length - t;
if (i !== 0) {
const s = _((100 - n) / i);
for (const l of e)
l.defaultSize === void 0 && (o[l.panelId] = s);
}
return o;
}
function Et(e, t, n) {
if (!n[0])
return;
const i = e.panels.find((u) => u.element === t);
if (!i || !i.onResize)
return;
const s = J({ group: e }), l = e.orientation === "horizontal" ? i.element.offsetWidth : i.element.offsetHeight, r = i.mutableValues.prevSize, a = {
asPercentage: _(l / s * 100),
inPixels: l
};
i.mutableValues.prevSize = a, i.onResize(a, i.id, r);
}
function kt(e, t) {
if (Object.keys(e).length !== Object.keys(t).length)
return !1;
for (const o in e)
if (e[o] !== t[o])
return !1;
return !0;
}
function Gt(e, t) {
const n = e.map((i) => i.id), o = Object.keys(t);
if (n.length !== o.length)
return !1;
for (const i of n)
if (!o.includes(i))
return !1;
return !0;
}
const q = /* @__PURE__ */ new Map();
function It(e) {
let t = !0;
P(
e.element.ownerDocument.defaultView,
"Cannot register an unmounted Group"
);
const n = e.element.ownerDocument.defaultView.ResizeObserver, o = /* @__PURE__ */ new Set(), i = /* @__PURE__ */ new Set(), s = new n((m) => {
for (const d of m) {
const { borderBoxSize: f, target: h } = d;
if (h === e.element) {
if (t) {
if (J({ group: e }) === 0)
return;
I((x) => {
const y = x.mountedGroups.get(e);
if (y) {
const p = pe(e), w = y.defaultLayoutDeferred ? Te(p) : y.layout, C = B({
layout: w,
panelConstraints: p
});
return !y.defaultLayoutDeferred && U(w, C) && kt(
y.derivedPanelConstraints,
p
) ? x : {
mountedGroups: new Map(x.mountedGroups).set(e, {
defaultLayoutDeferred: !1,
derivedPanelConstraints: p,
layout: C,
separatorToPanels: y.separatorToPanels
})
};
}
return x;
});
}
} else
Et(e, h, f);
}
});
s.observe(e.element), e.panels.forEach((m) => {
P(
!o.has(m.id),
`Panel ids must be unique; id "${m.id}" was used more than once`
), o.add(m.id), m.onResize && s.observe(m.element);
});
const l = J({ group: e }), r = pe(e), a = e.panels.map(({ id: m }) => m).join(",");
let u = e.defaultLayout;
u && (Gt(e.panels, u) || (u = void 0));
const c = e.inMemoryLayouts[a] ?? u ?? Te(r), g = B({
layout: c,
panelConstraints: r
}), b = Ve(e), S = e.element.ownerDocument;
return I((m) => {
const d = /* @__PURE__ */ new Map();
return q.set(
S,
(q.get(S) ?? 0) + 1
), b.forEach((f) => {
f.separator && d.set(f.separator, f.panels);
}), {
mountedGroups: new Map(m.mountedGroups).set(e, {
defaultLayoutDeferred: l === 0,
derivedPanelConstraints: r,
layout: g,
separatorToPanels: d
})
};
}), e.separators.forEach((m) => {
P(
!i.has(m.id),
`Separator ids must be unique; id "${m.id}" was used more than once`
), i.add(m.id), m.element.addEventListener("keydown", Pe);
}), q.get(S) === 1 && (S.addEventListener("dblclick", Le, !0), S.addEventListener("pointerdown", Ce, !0), S.addEventListener("pointerleave", Ge), S.addEventListener("pointermove", Ie), S.addEventListener("pointerout", De), S.addEventListener("pointerup", Oe, !0)), function() {
t = !1, q.set(
S,
Math.max(0, (q.get(S) ?? 0) - 1)
), I((d) => {
const f = new Map(d.mountedGroups);
return f.delete(e), { mountedGroups: f };
}), e.separators.forEach((d) => {
d.element.removeEventListener("keydown", Pe);
}), q.get(S) || (S.removeEventListener(
"dblclick",
Le,
!0
), S.removeEventListener(
"pointerdown",
Ce,
!0
), S.removeEventListener("pointerleave", Ge), S.removeEventListener("pointermove", Ie), S.removeEventListener("pointerout", De), S.removeEventListener("pointerup", Oe, !0)), s.disconnect();
};
}
function Dt() {
const [e, t] = ne({}), n = Q(() => t({}), []);
return [e, n];
}
function ye(e) {
const t = rt();
return `${e ?? t}`;
}
const K = typeof window < "u" ? Ae : ue;
function ee(e) {
const t = O(e);
return K(() => {
t.current = e;
}, [e]), Q(
(...n) => t.current?.(...n),
[t]
);
}
function Se(...e) {
return ee((t) => {
e.forEach((n) => {
if (n)
switch (typeof n) {
case "function": {
n(t);
break;
}
case "object": {
n.current = t;
break;
}
}
});
});
}
function ve(e) {
const t = O({ ...e });
return K(() => {
for (const n in e)
t.current[n] = e[n];
}, [e]), t.current;
}
const Ze = st(null);
function Ot(e, t) {
const n = O({
getLayout: () => ({}),
setLayout: Rt
});
Ne(t, () => n.current, []), K(() => {
Object.assign(
n.current,
Ue({ groupId: e })
);
});
}
function Tt({
children: e,
className: t,
defaultLayout: n,
disableCursor: o,
disabled: i,
elementRef: s,
groupRef: l,
id: r,
onLayoutChange: a,
onLayoutChanged: u,
orientation: c = "horizontal",
resizeTargetMinimumSize: g = {
coarse: 20,
fine: 10
},
style: b,
...S
}) {
const m = O({
onLayoutChange: {},
onLayoutChanged: {}
}), d = ee((z) => {
U(m.current.onLayoutChange, z) || (m.current.onLayoutChange = z, a?.(z));
}), f = ee((z) => {
U(m.current.onLayoutChanged, z) || (m.current.onLayoutChanged = z, u?.(z));
}), h = ye(r), v = O(null), [x, y] = Dt(), p = O({
lastExpandedPanelSizes: {},
layouts: {},
panels: [],
resizeTargetMinimumSize: g,
separators: []
}), w = Se(v, s);
Ot(h, l);
const C = ee(
(z, L) => {
const { interactionState: E, mountedGroups: M } = G();
for (const D of M.keys())
if (D.id === z) {
const T = M.get(D);
if (T) {
let N = !1;
switch (E.state) {
case "active": {
N = E.hitRegions.some(
(Z) => Z.group === D
);
break;
}
}
return {
flexGrow: T.layout[L] ?? 1,
pointerEvents: N ? "none" : void 0
};
}
}
return {
flexGrow: n?.[L] ?? 1
};
}
), R = ve({
defaultLayout: n,
disableCursor: o
}), X = _e(
() => ({
get disableCursor() {
return !!R.disableCursor;
},
getPanelStyles: C,
id: h,
orientation: c,
registerPanel: (z) => {
const L = p.current;
return L.panels = he(c, [
...L.panels,
z
]), y(), () => {
L.panels = L.panels.filter(
(E) => E !== z
), y();
};
},
registerSeparator: (z) => {
const L = p.current;
return L.separators = he(c, [
...L.separators,
z
]), y(), () => {
L.separators = L.separators.filter(
(E) => E !== z
), y();
};
},
togglePanelDisabled: (z, L) => {
const M = p.current.panels.find(
(T) => T.id === z
);
M && (M.panelConstraints.disabled = L);
const { mountedGroups: D } = G();
for (const T of D.keys())
if (T.id === h) {
const N = D.get(T);
N && (N.derivedPanelConstraints = pe(T));
}
},
toggleSeparatorDisabled: (z, L) => {
const M = p.current.separators.find(
(D) => D.id === z
);
M && (M.disabled = L);
}
}),
[C, h, y, c, R]
), V = O(null);
return K(() => {
const z = v.current;
if (z === null)
return;
const L = p.current;
let E;
if (R.defaultLayout !== void 0 && Object.keys(R.defaultLayout).length === L.panels.length) {
E = {};
for (const H of L.panels) {
const j = R.defaultLayout[H.id];
j !== void 0 && (E[H.id] = j);
}
}
const M = {
defaultLayout: E,
disableCursor: !!R.disableCursor,
disabled: !!i,
element: z,
id: h,
inMemoryLastExpandedPanelSizes: p.current.lastExpandedPanelSizes,
inMemoryLayouts: p.current.layouts,
orientation: c,
panels: L.panels,
resizeTargetMinimumSize: L.resizeTargetMinimumSize,
separators: L.separators
};
V.current = M;
const D = It(M), N = G().mountedGroups.get(M);
if (N) {
const { defaultLayoutDeferred: H, derivedPanelConstraints: j, layout: ie } = N;
!H && j.length > 0 && (d(ie), f(ie));
}
const Z = $.addListener(
"interactionStateChange",
(H) => {
H.state;
}
), Qe = $.addListener(
"mountedGroupsChange",
(H) => {
const j = H.get(M);
if (j) {
const { defaultLayoutDeferred: ie, derivedPanelConstraints: et, layout: ce } = j;
if (ie || et.length === 0)
return;
const tt = M.panels.map(({ id: it }) => it).join(",");
M.inMemoryLayouts[tt] = ce;
const { interactionState: nt } = G(), ot = nt.state !== "active";
d(ce), ot && f(ce);
}
}
);
return () => {
V.current = null, D(), Z(), Qe();
};
}, [
i,
h,
f,
d,
c,
x,
R
]), ue(() => {
const z = V.current;
z && (z.defaultLayout = n, z.disableCursor = !!o);
}), /* @__PURE__ */ te(Ze.Provider, { value: X, children: /* @__PURE__ */ te(
"div",
{
...S,
className: t,
"data-group": !0,
"data-testid": h,
id: h,
ref: w,
style: {
height: "100%",
width: "100%",
overflow: "hidden",
...b,
display: "flex",
flexDirection: c === "horizontal" ? "row" : "column",
flexWrap: "nowrap",
// Inform the browser that the library is handling touch events for this element
// but still allow users to scroll content within panels in the non-resizing direction
// NOTE This is not an inherited style
// See github.com/bvaughn/react-resizable-panels/issues/662
touchAction: c === "horizontal" ? "pan-y" : "pan-x"
},
children: e
}
) });
}
Tt.displayName = "Group";
function de(e, t) {
return `react-resizable-panels:${[e, ...t].join(":")}`;
}
function Wt({
debounceSaveMs: e = 100,
panelIds: t,
storage: n = localStorage,
...o
}) {
const i = t !== void 0, s = "id" in o ? o.id : o.groupId, l = de(s, t ?? []), r = Fe(
At,
() => n.getItem(l),
() => n.getItem(l)
), a = _e(
() => r ? JSON.parse(r) : void 0,
[r]
), u = O(null), c = Q(() => {
const S = u.current;
S && (u.current = null, clearTimeout(S));
}, []);
Ae(() => () => {
c();
}, [c]);
const g = Q(
(S) => {
c();
let m;
i ? m = de(s, Object.keys(S)) : m = de(s, []);
try {
n.setItem(m, JSON.stringify(S));
} catch (d) {
console.error(d);
}
},
[c, i, s, n]
), b = Q(
(S) => {
c(), e === 0 ? g(S) : u.current = setTimeout(() => {
g(S);
}, e);
},
[c, e, g]
);
return {
/**
* Pass this value to `Group` as the `defaultLayout` prop.
*/
defaultLayout: a,
/**
* Attach this callback on the `Group` as the `onLayoutChange` prop.
*
* @deprecated Use the {@link onLayoutChanged} prop instead.
*/
onLayoutChange: b,
/**
* Attach this callback on the `Group` as the `onLayoutChanged` prop.
*/
onLayoutChanged: g
};
}
function At() {
return function() {
};
}
function Ut() {
return ne(null);
}
function Bt() {
return O(null);
}
function xe() {
const e = at(Ze);
return P(
e,
"Group Context not found; did you render a Panel or Separator outside of a Group?"
), e;
}
function Nt(e, t) {
const { id: n } = xe(), o = O({
collapse: fe,
expand: fe,
getSize: () => ({
asPercentage: 0,
inPixels: 0
}),
isCollapsed: () => !1,
resize: fe
});
Ne(t, () => o.current, []), K(() => {
Object.assign(
o.current,
We({ groupId: n, panelId: e })
);
});
}
function _t({
children: e,
className: t,
collapsedSize: n = "0%",
collapsible: o = !1,
defaultSize: i,
disabled: s,
elementRef: l,
id: r,
maxSize: a = "100%",
minSize: u = "0%",
onResize: c,
panelRef: g,
style: b,
...S
}) {
const m = !!r, d = ye(r), f = ve({
disabled: s
}), h = O(null), v = Se(h, l), {
getPanelStyles: x,
id: y,
orientation: p,
registerPanel: w,
togglePanelDisabled: C
} = xe(), R = c !== null, X = ee(
(z, L, E) => {
c?.(z, r, E);
}
);
K(() => {
const z = h.current;
if (z !== null) {
const L = {
element: z,
id: d,
idIsStable: m,
mutableValues: {
expandToSize: void 0,
prevSize: void 0
},
onResize: R ? X : void 0,
panelConstraints: {
collapsedSize: n,
collapsible: o,
defaultSize: i,
disabled: f.disabled,
maxSize: a,
minSize: u
}
};
return w(L);
}
}, [
n,
o,
i,
R,
d,
m,
a,
u,
X,
w,
f
]), ue(() => {
C(d, !!s);
}, [s, d, C]), Nt(d, g);
const V = Fe(
(z) => ($.addListener("mountedGroupsChange", z), () => {
$.removeListener("mountedGroupsChange", z);
}),
// useSyncExternalStore does not support a custom equality check
// stringify avoids re-rendering when the style value hasn't changed
() => JSON.stringify(x(y, d)),
() => JSON.stringify(x(y, d))
);
return /* @__PURE__ */ te(
"div",
{
...S,
"aria-disabled": s || void 0,
"data-panel": !0,
"data-testid": d,
id: d,
ref: v,
style: {
...Ft,
display: "flex",
flexBasis: 0,
flexShrink: 1,
// Prevent Panel content from interfering with panel size
overflow: "hidden",
...JSON.parse(V)
},
children: /* @__PURE__ */ te(
"div",
{
className: t,
style: {
maxHeight: "100%",
maxWidth: "100%",
flexGrow: 1,
...b,
// Inform the browser that the library is handling touch events for this element
// but still allow users to scroll content within panels in the non-resizing direction
// NOTE This is not an inherited style
// See github.com/bvaughn/react-resizable-panels/issues/662
touchAction: p === "horizontal" ? "pan-y" : "pan-x"
},
children: e
}
)
}
);
}
_t.displayName = "Panel";
const Ft = {
minHeight: 0,
maxHeight: "100%",
height: "auto",
minWidth: 0,
maxWidth: "100%",
width: "auto",
border: "none",
borderWidth: 0,
padding: 0,
margin: 0
};
function Kt() {
return ne(null);
}
function Xt() {
return O(null);
}
function $t({
layout: e,
panelConstraints: t,
panelId: n,
panelIndex: o
}) {
let i, s;
const l = e[n], r = t.find(
(a) => a.panelId === n
);
if (r) {
const a = r.maxSize, u = r.collapsible ? r.collapsedSize : r.minSize, c = [o, o + 1];
s = B({
layout: oe({
delta: u - l,
initialLayout: e,
panelConstraints: t,
pivotIndices: c,
prevLayout: e
}),
panelConstraints: t
})[n], i = B({
layout: oe({
delta: a - l,
initialLayout: e,
panelConstraints: t,
pivotIndices: c,
prevLayout: e
}),
panelConstraints: t
})[n];
}
return {
valueControls: n,
valueMax: i,
valueMin: s,
valueNow: l
};
}
function Ht({
children: e,
className: t,
disabled: n,
elementRef: o,
id: i,
style: s,
...l
}) {
const r = ye(i), a = ve({
disabled: n
}), [u, c] = ne({}), [g, b] = ne("inactive"), S = O(null), m = Se(S, o), {
disableCursor: d,
id: f,
orientation: h,
registerSeparator: v,
toggleSeparatorDisabled: x
} = xe(), y = h === "horizontal" ? "vertical" : "horizontal";
K(() => {
const w = S.current;
if (w !== null) {
const C = {
disabled: a.disabled,
element