UNPKG

react-resizable-panels

Version:

<img src="https://react-resizable-panels.vercel.app/og.png" alt="react-resizable-panels logo" width="400" height="210" />

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