@aster-ui/prefixed 0.12.50 → 0.12.51
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1,116 +1,116 @@
|
|
|
1
1
|
import { jsx as a, jsxs as W } from "react/jsx-runtime";
|
|
2
|
-
import { useState as
|
|
3
|
-
const
|
|
4
|
-
const o = Z(
|
|
2
|
+
import { useState as R, useRef as V, useCallback as y, useEffect as $, createContext as X, useContext as Z } from "react";
|
|
3
|
+
const C = X(null), _ = () => {
|
|
4
|
+
const o = Z(C);
|
|
5
5
|
if (!o)
|
|
6
6
|
throw new Error("Anchor.Link must be used within an Anchor");
|
|
7
7
|
return o;
|
|
8
8
|
}, Y = ({
|
|
9
9
|
href: o,
|
|
10
10
|
title: h,
|
|
11
|
-
children:
|
|
12
|
-
className:
|
|
11
|
+
children: c,
|
|
12
|
+
className: f = ""
|
|
13
13
|
}) => {
|
|
14
|
-
const { activeLink:
|
|
15
|
-
|
|
16
|
-
const v =
|
|
14
|
+
const { activeLink: r, direction: k, registerLink: l, unregisterLink: w, handleClick: x } = _();
|
|
15
|
+
$(() => (l(o), () => w(o)), [o, l, w]);
|
|
16
|
+
const v = r === o, d = k === "vertical";
|
|
17
17
|
return /* @__PURE__ */ W("div", { className: d ? "" : "inline-block", children: [
|
|
18
18
|
/* @__PURE__ */ a(
|
|
19
19
|
"a",
|
|
20
20
|
{
|
|
21
21
|
href: `#${o}`,
|
|
22
|
-
onClick: (b) =>
|
|
22
|
+
onClick: (b) => x(b, o, h),
|
|
23
23
|
className: `
|
|
24
24
|
block text-sm transition-colors
|
|
25
25
|
${d ? "py-1 pl-3 border-l-2" : "px-3 py-1 border-b-2"}
|
|
26
|
-
${v ?
|
|
27
|
-
${
|
|
26
|
+
${v ? "text-primary border-primary font-medium" : "text-base-content/70 border-transparent hover:text-base-content hover:border-base-content/30"}
|
|
27
|
+
${f}
|
|
28
28
|
`.trim(),
|
|
29
29
|
children: h
|
|
30
30
|
}
|
|
31
31
|
),
|
|
32
|
-
|
|
32
|
+
c && /* @__PURE__ */ a("div", { className: d ? "pl-3" : "inline-flex", children: c })
|
|
33
33
|
] });
|
|
34
|
-
},
|
|
34
|
+
}, O = ({
|
|
35
35
|
items: o,
|
|
36
36
|
direction: h = "vertical",
|
|
37
|
-
offsetTop:
|
|
38
|
-
bounds:
|
|
39
|
-
getContainer:
|
|
40
|
-
getCurrentAnchor:
|
|
37
|
+
offsetTop: c = 0,
|
|
38
|
+
bounds: f = 5,
|
|
39
|
+
getContainer: r,
|
|
40
|
+
getCurrentAnchor: k,
|
|
41
41
|
onChange: l,
|
|
42
42
|
onClick: w,
|
|
43
|
-
activeLink:
|
|
43
|
+
activeLink: x,
|
|
44
44
|
affix: v = !1,
|
|
45
45
|
affixOffsetTop: d = 0,
|
|
46
46
|
replace: b = !1,
|
|
47
47
|
className: D = "",
|
|
48
48
|
children: q
|
|
49
49
|
}) => {
|
|
50
|
-
const [F,
|
|
51
|
-
|
|
52
|
-
}, []), M =
|
|
53
|
-
|
|
54
|
-
}, []),
|
|
55
|
-
const t = document.getElementById(
|
|
50
|
+
const [F, H] = R(""), [i, N] = R([]), [m, G] = R(!1), p = V(null), B = V(null), g = x !== void 0, L = g ? x : F, J = k ? k(L) : L, K = y((n) => {
|
|
51
|
+
N((t) => t.includes(n) ? t : [...t, n]);
|
|
52
|
+
}, []), M = y((n) => {
|
|
53
|
+
N((t) => t.filter((e) => e !== n));
|
|
54
|
+
}, []), T = y((n) => {
|
|
55
|
+
const t = document.getElementById(n);
|
|
56
56
|
if (t) {
|
|
57
|
-
const
|
|
58
|
-
|
|
57
|
+
const e = r?.() ?? window, s = t.getBoundingClientRect().top, u = e === window ? 0 : e.getBoundingClientRect().top, E = e === window ? window.scrollY : e.scrollTop, A = s - u + E - c;
|
|
58
|
+
e === window ? window.scrollTo({ top: A, behavior: "smooth" }) : e.scrollTo({ top: A, behavior: "smooth" }), b ? window.history.replaceState(null, "", `#${n}`) : window.history.pushState(null, "", `#${n}`);
|
|
59
59
|
}
|
|
60
|
-
}, [
|
|
61
|
-
|
|
62
|
-
}, [w,
|
|
63
|
-
|
|
60
|
+
}, [r, c, b]), Q = y((n, t, e) => {
|
|
61
|
+
n.preventDefault(), w?.(n, { href: t, title: e }), T(t), g || H(t), l?.(t);
|
|
62
|
+
}, [w, T, g, l]);
|
|
63
|
+
$(() => {
|
|
64
64
|
if (!v || !p.current) return;
|
|
65
|
-
const
|
|
66
|
-
if (!p.current || !
|
|
67
|
-
const
|
|
65
|
+
const n = r?.() ?? window, t = () => {
|
|
66
|
+
if (!p.current || !B.current) return;
|
|
67
|
+
const e = B.current.getBoundingClientRect(), s = n === window ? 0 : n.getBoundingClientRect().top, u = e.top - s <= d;
|
|
68
68
|
u !== m && G(u);
|
|
69
69
|
};
|
|
70
|
-
return
|
|
71
|
-
}, [v, d,
|
|
70
|
+
return n.addEventListener("scroll", t, { passive: !0 }), t(), () => n.removeEventListener("scroll", t);
|
|
71
|
+
}, [v, d, r, m]), $(() => {
|
|
72
72
|
if (i.length === 0) return;
|
|
73
|
-
const
|
|
74
|
-
let
|
|
75
|
-
const s =
|
|
76
|
-
if (
|
|
77
|
-
|
|
73
|
+
const n = r?.() ?? window, t = () => {
|
|
74
|
+
let e = "";
|
|
75
|
+
const s = n === window ? document.documentElement : n, u = n === window ? 0 : s.getBoundingClientRect().top, E = n === window ? window.scrollY : s.scrollTop, A = s.scrollHeight, U = n === window ? window.innerHeight : s.clientHeight;
|
|
76
|
+
if (E + U >= A - 10 && i.length > 0)
|
|
77
|
+
e = i[i.length - 1];
|
|
78
78
|
else {
|
|
79
|
-
for (const
|
|
80
|
-
const
|
|
81
|
-
|
|
79
|
+
for (const z of i) {
|
|
80
|
+
const P = document.getElementById(z);
|
|
81
|
+
P && P.getBoundingClientRect().top - u - c <= f && (e = z);
|
|
82
82
|
}
|
|
83
|
-
!
|
|
83
|
+
!e && i.length > 0 && (e = i[0]);
|
|
84
84
|
}
|
|
85
|
-
|
|
85
|
+
e && e !== L && (g || H(e), l?.(e));
|
|
86
86
|
};
|
|
87
|
-
return
|
|
88
|
-
}, [i,
|
|
87
|
+
return n.addEventListener("scroll", t, { passive: !0 }), t(), () => n.removeEventListener("scroll", t);
|
|
88
|
+
}, [i, r, c, f, L, g, l]);
|
|
89
89
|
const I = {
|
|
90
90
|
activeLink: J,
|
|
91
91
|
direction: h,
|
|
92
|
-
offsetTop:
|
|
92
|
+
offsetTop: c,
|
|
93
93
|
registerLink: K,
|
|
94
94
|
unregisterLink: M,
|
|
95
95
|
handleClick: Q
|
|
96
|
-
}, S = (
|
|
96
|
+
}, S = (n) => n.map((t) => /* @__PURE__ */ a(Y, { href: t.href, title: t.title, children: t.children && S(t.children) }, t.href)), j = /* @__PURE__ */ a(
|
|
97
97
|
"nav",
|
|
98
98
|
{
|
|
99
99
|
ref: p,
|
|
100
100
|
className: `
|
|
101
101
|
${h === "horizontal" ? "flex items-center" : "flex flex-col"}
|
|
102
|
-
${m ?
|
|
102
|
+
${m ? "fixed bg-base-100 shadow-sm z-10" : ""}
|
|
103
103
|
${D}
|
|
104
104
|
`.trim(),
|
|
105
105
|
style: m ? { top: d } : void 0,
|
|
106
106
|
children: o ? S(o) : q
|
|
107
107
|
}
|
|
108
108
|
);
|
|
109
|
-
return v ? /* @__PURE__ */ a(
|
|
110
|
-
},
|
|
109
|
+
return v ? /* @__PURE__ */ a(C.Provider, { value: I, children: /* @__PURE__ */ a("div", { ref: B, style: m && p.current ? { height: p.current.offsetHeight } : void 0, children: j }) }) : /* @__PURE__ */ a(C.Provider, { value: I, children: j });
|
|
110
|
+
}, rt = Object.assign(O, {
|
|
111
111
|
Link: Y
|
|
112
112
|
});
|
|
113
113
|
export {
|
|
114
|
-
|
|
114
|
+
rt as Anchor
|
|
115
115
|
};
|
|
116
116
|
//# sourceMappingURL=Anchor.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Anchor.js","sources":["../../src/components/Anchor.tsx"],"sourcesContent":["import React, { useState, useEffect, useCallback, createContext, useContext, useRef } from 'react'\n\n// DaisyUI classes\nconst dTextPrimary = 'd-text-primary'\nconst dBorderPrimary = 'd-border-primary'\nconst dTextBaseContent = 'd-text-base-content'\nconst dHoverTextBaseContent = 'd-hover:text-base-content'\nconst dHoverBorderBaseContent = 'd-hover:border-base-content'\nconst dBgBase100 = 'd-bg-base-100'\n\nexport interface AnchorLinkItem {\n /** Target element id (without #) */\n href: string\n /** Link title */\n title: React.ReactNode\n /** Nested links */\n children?: AnchorLinkItem[]\n}\n\nexport interface AnchorProps {\n /** Anchor links (alternative to Anchor.Link children) */\n items?: AnchorLinkItem[]\n /** Layout direction */\n direction?: 'horizontal' | 'vertical'\n /** Offset from top when calculating scroll position */\n offsetTop?: number\n /** Bounding distance of anchor area */\n bounds?: number\n /** Target scroll container (default: window) */\n getContainer?: () => HTMLElement | Window\n /** Customize the anchor highlight */\n getCurrentAnchor?: (activeLink: string) => string\n /** Callback when active link changes */\n onChange?: (activeLink: string) => void\n /** Callback when link is clicked */\n onClick?: (e: React.MouseEvent, link: { href: string; title: React.ReactNode }) => void\n /** Currently active link (controlled) */\n activeLink?: string\n /** Whether to fix the anchor when scrolling */\n affix?: boolean\n /** Pixels to offset from top when affix is true */\n affixOffsetTop?: number\n /** Replace history instead of push */\n replace?: boolean\n /** Custom class name */\n className?: string\n /** Anchor.Link children */\n children?: React.ReactNode\n}\n\nexport interface AnchorLinkProps {\n /** Target element id (without #) */\n href: string\n /** Link title */\n title: React.ReactNode\n /** Nested links */\n children?: React.ReactNode\n /** Custom class name */\n className?: string\n}\n\ninterface AnchorContextValue {\n activeLink: string\n direction: 'horizontal' | 'vertical'\n offsetTop: number\n registerLink: (href: string) => void\n unregisterLink: (href: string) => void\n handleClick: (e: React.MouseEvent, href: string, title: React.ReactNode) => void\n}\n\nconst AnchorContext = createContext<AnchorContextValue | null>(null)\n\nconst useAnchorContext = () => {\n const context = useContext(AnchorContext)\n if (!context) {\n throw new Error('Anchor.Link must be used within an Anchor')\n }\n return context\n}\n\nconst AnchorLink: React.FC<AnchorLinkProps> = ({\n href,\n title,\n children,\n className = '',\n}) => {\n const { activeLink, direction, registerLink, unregisterLink, handleClick } = useAnchorContext()\n\n useEffect(() => {\n registerLink(href)\n return () => unregisterLink(href)\n }, [href, registerLink, unregisterLink])\n\n const isActive = activeLink === href\n const isVertical = direction === 'vertical'\n\n return (\n <div className={isVertical ? '' : 'inline-block'}>\n <a\n href={`#${href}`}\n onClick={(e) => handleClick(e, href, title)}\n className={`\n block text-sm transition-colors\n ${isVertical ? 'py-1 pl-3 border-l-2' : 'px-3 py-1 border-b-2'}\n ${isActive\n ? `${dTextPrimary} ${dBorderPrimary} font-medium`\n : `${dTextBaseContent}/70 border-transparent ${dHoverTextBaseContent} ${dHoverBorderBaseContent}/30`\n }\n ${className}\n `.trim()}\n >\n {title}\n </a>\n {children && (\n <div className={isVertical ? 'pl-3' : 'inline-flex'}>\n {children}\n </div>\n )}\n </div>\n )\n}\n\nconst AnchorComponent: React.FC<AnchorProps> = ({\n items,\n direction = 'vertical',\n offsetTop = 0,\n bounds = 5,\n getContainer,\n getCurrentAnchor,\n onChange,\n onClick,\n activeLink: controlledActiveLink,\n affix = false,\n affixOffsetTop = 0,\n replace = false,\n className = '',\n children,\n}) => {\n const [internalActiveLink, setInternalActiveLink] = useState('')\n const [links, setLinks] = useState<string[]>([])\n const [isAffixed, setIsAffixed] = useState(false)\n const anchorRef = useRef<HTMLDivElement>(null)\n const placeholderRef = useRef<HTMLDivElement>(null)\n\n const isControlled = controlledActiveLink !== undefined\n const rawActiveLink = isControlled ? controlledActiveLink : internalActiveLink\n const activeLink = getCurrentAnchor ? getCurrentAnchor(rawActiveLink) : rawActiveLink\n\n const registerLink = useCallback((href: string) => {\n setLinks((prev) => (prev.includes(href) ? prev : [...prev, href]))\n }, [])\n\n const unregisterLink = useCallback((href: string) => {\n setLinks((prev) => prev.filter((link) => link !== href))\n }, [])\n\n const scrollToTarget = useCallback((href: string) => {\n const target = document.getElementById(href)\n if (target) {\n const container = getContainer?.() ?? window\n const targetTop = target.getBoundingClientRect().top\n const containerTop = container === window\n ? 0\n : (container as HTMLElement).getBoundingClientRect().top\n const scrollTop = container === window\n ? window.scrollY\n : (container as HTMLElement).scrollTop\n\n const top = targetTop - containerTop + scrollTop - offsetTop\n\n if (container === window) {\n window.scrollTo({ top, behavior: 'smooth' })\n } else {\n (container as HTMLElement).scrollTo({ top, behavior: 'smooth' })\n }\n\n // Update URL hash\n if (replace) {\n window.history.replaceState(null, '', `#${href}`)\n } else {\n window.history.pushState(null, '', `#${href}`)\n }\n }\n }, [getContainer, offsetTop, replace])\n\n const handleClick = useCallback((\n e: React.MouseEvent,\n href: string,\n title: React.ReactNode\n ) => {\n e.preventDefault()\n onClick?.(e, { href, title })\n scrollToTarget(href)\n\n if (!isControlled) {\n setInternalActiveLink(href)\n }\n onChange?.(href)\n }, [onClick, scrollToTarget, isControlled, onChange])\n\n // Affix logic\n useEffect(() => {\n if (!affix || !anchorRef.current) return\n\n const container = getContainer?.() ?? window\n\n const handleScroll = () => {\n if (!anchorRef.current || !placeholderRef.current) return\n\n const placeholderRect = placeholderRef.current.getBoundingClientRect()\n const containerTop = container === window\n ? 0\n : (container as HTMLElement).getBoundingClientRect().top\n\n const shouldAffix = placeholderRect.top - containerTop <= affixOffsetTop\n\n if (shouldAffix !== isAffixed) {\n setIsAffixed(shouldAffix)\n }\n }\n\n container.addEventListener('scroll', handleScroll, { passive: true })\n handleScroll()\n\n return () => container.removeEventListener('scroll', handleScroll)\n }, [affix, affixOffsetTop, getContainer, isAffixed])\n\n // Scroll spy\n useEffect(() => {\n if (links.length === 0) return\n\n const container = getContainer?.() ?? window\n\n const handleScroll = () => {\n let currentActive = ''\n const containerEl = container === window ? document.documentElement : container as HTMLElement\n const containerTop = container === window\n ? 0\n : containerEl.getBoundingClientRect().top\n\n // Check if scrolled to near the bottom\n const scrollTop = container === window ? window.scrollY : containerEl.scrollTop\n const scrollHeight = containerEl.scrollHeight\n const clientHeight = container === window ? window.innerHeight : containerEl.clientHeight\n const isNearBottom = scrollTop + clientHeight >= scrollHeight - 10\n\n // If near bottom, use the last link\n if (isNearBottom && links.length > 0) {\n currentActive = links[links.length - 1]\n } else {\n // Find the last element that has scrolled past the top (standard scroll spy behavior)\n for (const href of links) {\n const element = document.getElementById(href)\n if (element) {\n const rect = element.getBoundingClientRect()\n const distance = rect.top - containerTop - offsetTop\n\n // If element's top is within bounds of the threshold, it's the current section\n if (distance <= bounds) {\n currentActive = href\n }\n }\n }\n\n // If nothing matched, use the first link\n if (!currentActive && links.length > 0) {\n currentActive = links[0]\n }\n }\n\n if (currentActive && currentActive !== rawActiveLink) {\n if (!isControlled) {\n setInternalActiveLink(currentActive)\n }\n onChange?.(currentActive)\n }\n }\n\n container.addEventListener('scroll', handleScroll, { passive: true })\n handleScroll() // Initial check\n\n return () => container.removeEventListener('scroll', handleScroll)\n }, [links, getContainer, offsetTop, bounds, rawActiveLink, isControlled, onChange])\n\n const contextValue: AnchorContextValue = {\n activeLink,\n direction,\n offsetTop,\n registerLink,\n unregisterLink,\n handleClick,\n }\n\n const renderItems = (linkItems: AnchorLinkItem[]): React.ReactNode => {\n return linkItems.map((item) => (\n <AnchorLink key={item.href} href={item.href} title={item.title}>\n {item.children && renderItems(item.children)}\n </AnchorLink>\n ))\n }\n\n const anchorContent = (\n <nav\n ref={anchorRef}\n className={`\n ${direction === 'horizontal' ? 'flex items-center' : 'flex flex-col'}\n ${isAffixed ? `fixed ${dBgBase100} shadow-sm z-10` : ''}\n ${className}\n `.trim()}\n style={isAffixed ? { top: affixOffsetTop } : undefined}\n >\n {items ? renderItems(items) : children}\n </nav>\n )\n\n if (affix) {\n return (\n <AnchorContext.Provider value={contextValue}>\n <div ref={placeholderRef} style={isAffixed && anchorRef.current ? { height: anchorRef.current.offsetHeight } : undefined}>\n {anchorContent}\n </div>\n </AnchorContext.Provider>\n )\n }\n\n return (\n <AnchorContext.Provider value={contextValue}>\n {anchorContent}\n </AnchorContext.Provider>\n )\n}\n\nexport const Anchor = Object.assign(AnchorComponent, {\n Link: AnchorLink,\n})\n"],"names":["dTextPrimary","dBorderPrimary","dTextBaseContent","dHoverTextBaseContent","dHoverBorderBaseContent","dBgBase100","AnchorContext","createContext","useAnchorContext","context","useContext","AnchorLink","href","title","children","className","activeLink","direction","registerLink","unregisterLink","handleClick","useEffect","isActive","isVertical","jsxs","jsx","e","AnchorComponent","items","offsetTop","bounds","getContainer","getCurrentAnchor","onChange","onClick","controlledActiveLink","affix","affixOffsetTop","replace","internalActiveLink","setInternalActiveLink","useState","links","setLinks","isAffixed","setIsAffixed","anchorRef","useRef","placeholderRef","isControlled","rawActiveLink","useCallback","prev","link","scrollToTarget","target","container","targetTop","containerTop","scrollTop","top","handleScroll","placeholderRect","shouldAffix","currentActive","containerEl","scrollHeight","clientHeight","element","contextValue","renderItems","linkItems","item","anchorContent","Anchor"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Anchor.js","sources":["../../src/components/Anchor.tsx"],"sourcesContent":["import React, { useState, useEffect, useCallback, createContext, useContext, useRef } from 'react'\n\nexport interface AnchorLinkItem {\n /** Target element id (without #) */\n href: string\n /** Link title */\n title: React.ReactNode\n /** Nested links */\n children?: AnchorLinkItem[]\n}\n\nexport interface AnchorProps {\n /** Anchor links (alternative to Anchor.Link children) */\n items?: AnchorLinkItem[]\n /** Layout direction */\n direction?: 'horizontal' | 'vertical'\n /** Offset from top when calculating scroll position */\n offsetTop?: number\n /** Bounding distance of anchor area */\n bounds?: number\n /** Target scroll container (default: window) */\n getContainer?: () => HTMLElement | Window\n /** Customize the anchor highlight */\n getCurrentAnchor?: (activeLink: string) => string\n /** Callback when active link changes */\n onChange?: (activeLink: string) => void\n /** Callback when link is clicked */\n onClick?: (e: React.MouseEvent, link: { href: string; title: React.ReactNode }) => void\n /** Currently active link (controlled) */\n activeLink?: string\n /** Whether to fix the anchor when scrolling */\n affix?: boolean\n /** Pixels to offset from top when affix is true */\n affixOffsetTop?: number\n /** Replace history instead of push */\n replace?: boolean\n /** Custom class name */\n className?: string\n /** Anchor.Link children */\n children?: React.ReactNode\n}\n\nexport interface AnchorLinkProps {\n /** Target element id (without #) */\n href: string\n /** Link title */\n title: React.ReactNode\n /** Nested links */\n children?: React.ReactNode\n /** Custom class name */\n className?: string\n}\n\ninterface AnchorContextValue {\n activeLink: string\n direction: 'horizontal' | 'vertical'\n offsetTop: number\n registerLink: (href: string) => void\n unregisterLink: (href: string) => void\n handleClick: (e: React.MouseEvent, href: string, title: React.ReactNode) => void\n}\n\nconst AnchorContext = createContext<AnchorContextValue | null>(null)\n\nconst useAnchorContext = () => {\n const context = useContext(AnchorContext)\n if (!context) {\n throw new Error('Anchor.Link must be used within an Anchor')\n }\n return context\n}\n\nconst AnchorLink: React.FC<AnchorLinkProps> = ({\n href,\n title,\n children,\n className = '',\n}) => {\n const { activeLink, direction, registerLink, unregisterLink, handleClick } = useAnchorContext()\n\n useEffect(() => {\n registerLink(href)\n return () => unregisterLink(href)\n }, [href, registerLink, unregisterLink])\n\n const isActive = activeLink === href\n const isVertical = direction === 'vertical'\n\n return (\n <div className={isVertical ? '' : 'inline-block'}>\n <a\n href={`#${href}`}\n onClick={(e) => handleClick(e, href, title)}\n className={`\n block text-sm transition-colors\n ${isVertical ? 'py-1 pl-3 border-l-2' : 'px-3 py-1 border-b-2'}\n ${isActive\n ? 'text-primary border-primary font-medium'\n : 'text-base-content/70 border-transparent hover:text-base-content hover:border-base-content/30'\n }\n ${className}\n `.trim()}\n >\n {title}\n </a>\n {children && (\n <div className={isVertical ? 'pl-3' : 'inline-flex'}>\n {children}\n </div>\n )}\n </div>\n )\n}\n\nconst AnchorComponent: React.FC<AnchorProps> = ({\n items,\n direction = 'vertical',\n offsetTop = 0,\n bounds = 5,\n getContainer,\n getCurrentAnchor,\n onChange,\n onClick,\n activeLink: controlledActiveLink,\n affix = false,\n affixOffsetTop = 0,\n replace = false,\n className = '',\n children,\n}) => {\n const [internalActiveLink, setInternalActiveLink] = useState('')\n const [links, setLinks] = useState<string[]>([])\n const [isAffixed, setIsAffixed] = useState(false)\n const anchorRef = useRef<HTMLDivElement>(null)\n const placeholderRef = useRef<HTMLDivElement>(null)\n\n const isControlled = controlledActiveLink !== undefined\n const rawActiveLink = isControlled ? controlledActiveLink : internalActiveLink\n const activeLink = getCurrentAnchor ? getCurrentAnchor(rawActiveLink) : rawActiveLink\n\n const registerLink = useCallback((href: string) => {\n setLinks((prev) => (prev.includes(href) ? prev : [...prev, href]))\n }, [])\n\n const unregisterLink = useCallback((href: string) => {\n setLinks((prev) => prev.filter((link) => link !== href))\n }, [])\n\n const scrollToTarget = useCallback((href: string) => {\n const target = document.getElementById(href)\n if (target) {\n const container = getContainer?.() ?? window\n const targetTop = target.getBoundingClientRect().top\n const containerTop = container === window\n ? 0\n : (container as HTMLElement).getBoundingClientRect().top\n const scrollTop = container === window\n ? window.scrollY\n : (container as HTMLElement).scrollTop\n\n const top = targetTop - containerTop + scrollTop - offsetTop\n\n if (container === window) {\n window.scrollTo({ top, behavior: 'smooth' })\n } else {\n (container as HTMLElement).scrollTo({ top, behavior: 'smooth' })\n }\n\n // Update URL hash\n if (replace) {\n window.history.replaceState(null, '', `#${href}`)\n } else {\n window.history.pushState(null, '', `#${href}`)\n }\n }\n }, [getContainer, offsetTop, replace])\n\n const handleClick = useCallback((\n e: React.MouseEvent,\n href: string,\n title: React.ReactNode\n ) => {\n e.preventDefault()\n onClick?.(e, { href, title })\n scrollToTarget(href)\n\n if (!isControlled) {\n setInternalActiveLink(href)\n }\n onChange?.(href)\n }, [onClick, scrollToTarget, isControlled, onChange])\n\n // Affix logic\n useEffect(() => {\n if (!affix || !anchorRef.current) return\n\n const container = getContainer?.() ?? window\n\n const handleScroll = () => {\n if (!anchorRef.current || !placeholderRef.current) return\n\n const placeholderRect = placeholderRef.current.getBoundingClientRect()\n const containerTop = container === window\n ? 0\n : (container as HTMLElement).getBoundingClientRect().top\n\n const shouldAffix = placeholderRect.top - containerTop <= affixOffsetTop\n\n if (shouldAffix !== isAffixed) {\n setIsAffixed(shouldAffix)\n }\n }\n\n container.addEventListener('scroll', handleScroll, { passive: true })\n handleScroll()\n\n return () => container.removeEventListener('scroll', handleScroll)\n }, [affix, affixOffsetTop, getContainer, isAffixed])\n\n // Scroll spy\n useEffect(() => {\n if (links.length === 0) return\n\n const container = getContainer?.() ?? window\n\n const handleScroll = () => {\n let currentActive = ''\n const containerEl = container === window ? document.documentElement : container as HTMLElement\n const containerTop = container === window\n ? 0\n : containerEl.getBoundingClientRect().top\n\n // Check if scrolled to near the bottom\n const scrollTop = container === window ? window.scrollY : containerEl.scrollTop\n const scrollHeight = containerEl.scrollHeight\n const clientHeight = container === window ? window.innerHeight : containerEl.clientHeight\n const isNearBottom = scrollTop + clientHeight >= scrollHeight - 10\n\n // If near bottom, use the last link\n if (isNearBottom && links.length > 0) {\n currentActive = links[links.length - 1]\n } else {\n // Find the last element that has scrolled past the top (standard scroll spy behavior)\n for (const href of links) {\n const element = document.getElementById(href)\n if (element) {\n const rect = element.getBoundingClientRect()\n const distance = rect.top - containerTop - offsetTop\n\n // If element's top is within bounds of the threshold, it's the current section\n if (distance <= bounds) {\n currentActive = href\n }\n }\n }\n\n // If nothing matched, use the first link\n if (!currentActive && links.length > 0) {\n currentActive = links[0]\n }\n }\n\n if (currentActive && currentActive !== rawActiveLink) {\n if (!isControlled) {\n setInternalActiveLink(currentActive)\n }\n onChange?.(currentActive)\n }\n }\n\n container.addEventListener('scroll', handleScroll, { passive: true })\n handleScroll() // Initial check\n\n return () => container.removeEventListener('scroll', handleScroll)\n }, [links, getContainer, offsetTop, bounds, rawActiveLink, isControlled, onChange])\n\n const contextValue: AnchorContextValue = {\n activeLink,\n direction,\n offsetTop,\n registerLink,\n unregisterLink,\n handleClick,\n }\n\n const renderItems = (linkItems: AnchorLinkItem[]): React.ReactNode => {\n return linkItems.map((item) => (\n <AnchorLink key={item.href} href={item.href} title={item.title}>\n {item.children && renderItems(item.children)}\n </AnchorLink>\n ))\n }\n\n const anchorContent = (\n <nav\n ref={anchorRef}\n className={`\n ${direction === 'horizontal' ? 'flex items-center' : 'flex flex-col'}\n ${isAffixed ? 'fixed bg-base-100 shadow-sm z-10' : ''}\n ${className}\n `.trim()}\n style={isAffixed ? { top: affixOffsetTop } : undefined}\n >\n {items ? renderItems(items) : children}\n </nav>\n )\n\n if (affix) {\n return (\n <AnchorContext.Provider value={contextValue}>\n <div ref={placeholderRef} style={isAffixed && anchorRef.current ? { height: anchorRef.current.offsetHeight } : undefined}>\n {anchorContent}\n </div>\n </AnchorContext.Provider>\n )\n }\n\n return (\n <AnchorContext.Provider value={contextValue}>\n {anchorContent}\n </AnchorContext.Provider>\n )\n}\n\nexport const Anchor = Object.assign(AnchorComponent, {\n Link: AnchorLink,\n})\n"],"names":["AnchorContext","createContext","useAnchorContext","context","useContext","AnchorLink","href","title","children","className","activeLink","direction","registerLink","unregisterLink","handleClick","useEffect","isActive","isVertical","jsxs","jsx","e","AnchorComponent","items","offsetTop","bounds","getContainer","getCurrentAnchor","onChange","onClick","controlledActiveLink","affix","affixOffsetTop","replace","internalActiveLink","setInternalActiveLink","useState","links","setLinks","isAffixed","setIsAffixed","anchorRef","useRef","placeholderRef","isControlled","rawActiveLink","useCallback","prev","link","scrollToTarget","target","container","targetTop","containerTop","scrollTop","top","handleScroll","placeholderRect","shouldAffix","currentActive","containerEl","scrollHeight","clientHeight","element","contextValue","renderItems","linkItems","item","anchorContent","Anchor"],"mappings":"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"}
|
|
@@ -1,54 +1,54 @@
|
|
|
1
|
-
import { jsx as a, jsxs as
|
|
2
|
-
import
|
|
3
|
-
const
|
|
4
|
-
function
|
|
5
|
-
return
|
|
1
|
+
import { jsx as a, jsxs as Q } from "react/jsx-runtime";
|
|
2
|
+
import N, { forwardRef as y, useContext as Z, createContext as _, useState as S, useEffect as q, useCallback as G } from "react";
|
|
3
|
+
const B = _(null);
|
|
4
|
+
function I() {
|
|
5
|
+
return Z(B);
|
|
6
6
|
}
|
|
7
|
-
const
|
|
7
|
+
const v = y(
|
|
8
8
|
({ children: s, hasSider: o, className: n = "", "data-testid": e, ...l }, r) => {
|
|
9
|
-
const d =
|
|
10
|
-
(t) =>
|
|
9
|
+
const d = N.Children.toArray(s), f = d.some(
|
|
10
|
+
(t) => N.isValidElement(t) && t.type.displayName === "LayoutSider"
|
|
11
11
|
), c = o ?? f, p = [
|
|
12
12
|
"flex",
|
|
13
13
|
"min-h-0",
|
|
14
14
|
c ? "flex-row" : "flex-col",
|
|
15
15
|
n
|
|
16
|
-
].filter(Boolean).join(" "),
|
|
17
|
-
if (
|
|
18
|
-
const
|
|
19
|
-
if (!
|
|
20
|
-
return
|
|
21
|
-
className: `flex-1 ${
|
|
16
|
+
].filter(Boolean).join(" "), b = c ? d.map((t) => {
|
|
17
|
+
if (N.isValidElement(t) && (t.type === v || t.type.displayName === "LayoutRoot") && t.type.displayName !== "LayoutSider") {
|
|
18
|
+
const g = t.props.className || "";
|
|
19
|
+
if (!g.includes("flex-1"))
|
|
20
|
+
return N.cloneElement(t, {
|
|
21
|
+
className: `flex-1 ${g}`.trim()
|
|
22
22
|
});
|
|
23
23
|
}
|
|
24
24
|
return t;
|
|
25
25
|
}) : s;
|
|
26
|
-
return /* @__PURE__ */ a("div", { ref: r, className: p, "data-testid": e, ...l, children:
|
|
26
|
+
return /* @__PURE__ */ a("div", { ref: r, className: p, "data-testid": e, ...l, children: b });
|
|
27
27
|
}
|
|
28
28
|
);
|
|
29
|
-
|
|
30
|
-
const
|
|
29
|
+
v.displayName = "LayoutRoot";
|
|
30
|
+
const E = y(
|
|
31
31
|
({ children: s, className: o = "", "data-testid": n, ...e }, l) => {
|
|
32
32
|
const r = [
|
|
33
33
|
"flex",
|
|
34
34
|
"items-center",
|
|
35
35
|
"px-6",
|
|
36
36
|
"h-16",
|
|
37
|
-
|
|
37
|
+
"bg-base-300",
|
|
38
38
|
"flex-shrink-0",
|
|
39
39
|
o
|
|
40
40
|
].filter(Boolean).join(" ");
|
|
41
41
|
return /* @__PURE__ */ a("header", { ref: l, className: r, "data-testid": n, ...e, children: s });
|
|
42
42
|
}
|
|
43
43
|
);
|
|
44
|
-
|
|
44
|
+
E.displayName = "LayoutHeader";
|
|
45
45
|
const R = y(
|
|
46
46
|
({ children: s, className: o = "", "data-testid": n, ...e }, l) => {
|
|
47
47
|
const r = [
|
|
48
48
|
"px-6",
|
|
49
49
|
"py-4",
|
|
50
50
|
"text-center",
|
|
51
|
-
|
|
51
|
+
"bg-base-300",
|
|
52
52
|
"flex-shrink-0",
|
|
53
53
|
o
|
|
54
54
|
].filter(Boolean).join(" ");
|
|
@@ -56,20 +56,20 @@ const R = y(
|
|
|
56
56
|
}
|
|
57
57
|
);
|
|
58
58
|
R.displayName = "LayoutFooter";
|
|
59
|
-
const
|
|
59
|
+
const $ = y(
|
|
60
60
|
({ children: s, className: o = "", "data-testid": n, ...e }, l) => {
|
|
61
61
|
const r = ["flex-1", "min-h-0", "overflow-auto", o].filter(Boolean).join(" ");
|
|
62
62
|
return /* @__PURE__ */ a("main", { ref: l, className: r, "data-testid": n, ...e, children: s });
|
|
63
63
|
}
|
|
64
64
|
);
|
|
65
|
-
|
|
66
|
-
const
|
|
65
|
+
$.displayName = "LayoutContent";
|
|
66
|
+
const J = {
|
|
67
67
|
sm: "(max-width: 639px)",
|
|
68
68
|
md: "(max-width: 767px)",
|
|
69
69
|
lg: "(max-width: 1023px)",
|
|
70
70
|
xl: "(max-width: 1279px)",
|
|
71
71
|
"2xl": "(max-width: 1535px)"
|
|
72
|
-
},
|
|
72
|
+
}, A = y(
|
|
73
73
|
({
|
|
74
74
|
children: s,
|
|
75
75
|
width: o = 200,
|
|
@@ -81,49 +81,49 @@ const Y = {
|
|
|
81
81
|
trigger: f,
|
|
82
82
|
breakpoint: c,
|
|
83
83
|
onBreakpoint: p,
|
|
84
|
-
reverseArrow:
|
|
84
|
+
reverseArrow: b = !1,
|
|
85
85
|
theme: t = "dark",
|
|
86
|
-
zeroWidthTriggerStyle:
|
|
87
|
-
className:
|
|
88
|
-
style:
|
|
86
|
+
zeroWidthTriggerStyle: g,
|
|
87
|
+
className: M = "",
|
|
88
|
+
style: T,
|
|
89
89
|
"data-testid": x,
|
|
90
|
-
...
|
|
91
|
-
},
|
|
92
|
-
const [
|
|
93
|
-
|
|
90
|
+
...W
|
|
91
|
+
}, z) => {
|
|
92
|
+
const [F, L] = S(l), [w, H] = S(!1), i = e ?? F;
|
|
93
|
+
q(() => {
|
|
94
94
|
if (!c) return;
|
|
95
|
-
const m = window.matchMedia(
|
|
96
|
-
const h =
|
|
97
|
-
|
|
95
|
+
const m = window.matchMedia(J[c]), C = (K) => {
|
|
96
|
+
const h = K.matches;
|
|
97
|
+
H(h), p?.(h), e === void 0 && L(h), h !== w && d?.(h, "responsive");
|
|
98
98
|
};
|
|
99
|
-
return
|
|
100
|
-
}, [c, p, e, d,
|
|
101
|
-
const
|
|
99
|
+
return C(m), m.addEventListener("change", C), () => m.removeEventListener("change", C);
|
|
100
|
+
}, [c, p, e, d, w]);
|
|
101
|
+
const k = G(() => {
|
|
102
102
|
const m = !i;
|
|
103
|
-
e === void 0 &&
|
|
104
|
-
}, [i, e, d]), u = i ? n : o, j = u === 0 || u === "0" || u === "0px",
|
|
103
|
+
e === void 0 && L(m), d?.(m, "clickTrigger");
|
|
104
|
+
}, [i, e, d]), u = i ? n : o, j = u === 0 || u === "0" || u === "0px", P = [
|
|
105
105
|
"flex",
|
|
106
106
|
"flex-col",
|
|
107
107
|
{
|
|
108
|
-
light:
|
|
109
|
-
dark:
|
|
108
|
+
light: "bg-base-100",
|
|
109
|
+
dark: "bg-base-200"
|
|
110
110
|
}[t],
|
|
111
111
|
"flex-shrink-0",
|
|
112
112
|
"transition-all",
|
|
113
113
|
"duration-200",
|
|
114
114
|
"relative",
|
|
115
|
-
|
|
116
|
-
].filter(Boolean).join(" "),
|
|
115
|
+
M
|
|
116
|
+
].filter(Boolean).join(" "), O = () => b ? i ? "" : "rotate-180" : i ? "rotate-180" : "", V = r && f !== null && /* @__PURE__ */ a(
|
|
117
117
|
"button",
|
|
118
118
|
{
|
|
119
|
-
onClick:
|
|
120
|
-
className:
|
|
119
|
+
onClick: k,
|
|
120
|
+
className: "flex items-center justify-center h-10 w-full bg-base-300 hover:bg-base-content/10 transition-colors",
|
|
121
121
|
"aria-label": i ? "Expand sidebar" : "Collapse sidebar",
|
|
122
122
|
"data-testid": x ? `${x}-trigger` : void 0,
|
|
123
123
|
children: /* @__PURE__ */ a(
|
|
124
124
|
"svg",
|
|
125
125
|
{
|
|
126
|
-
className: `w-4 h-4 transition-transform ${
|
|
126
|
+
className: `w-4 h-4 transition-transform ${O()}`,
|
|
127
127
|
fill: "none",
|
|
128
128
|
viewBox: "0 0 24 24",
|
|
129
129
|
stroke: "currentColor",
|
|
@@ -131,18 +131,18 @@ const Y = {
|
|
|
131
131
|
}
|
|
132
132
|
)
|
|
133
133
|
}
|
|
134
|
-
),
|
|
134
|
+
), D = r && j && i && /* @__PURE__ */ a(
|
|
135
135
|
"button",
|
|
136
136
|
{
|
|
137
|
-
onClick:
|
|
138
|
-
className:
|
|
137
|
+
onClick: k,
|
|
138
|
+
className: "absolute top-1/2 -translate-y-1/2 right-0 translate-x-full w-6 h-12 flex items-center justify-center bg-base-300 hover:bg-base-content/10 transition-colors rounded-r z-10",
|
|
139
139
|
"aria-label": "Expand sidebar",
|
|
140
|
-
style:
|
|
140
|
+
style: g,
|
|
141
141
|
"data-testid": x ? `${x}-zero-trigger` : void 0,
|
|
142
142
|
children: /* @__PURE__ */ a(
|
|
143
143
|
"svg",
|
|
144
144
|
{
|
|
145
|
-
className: `w-3 h-3 ${
|
|
145
|
+
className: `w-3 h-3 ${b ? "rotate-180" : ""}`,
|
|
146
146
|
fill: "none",
|
|
147
147
|
viewBox: "0 0 24 24",
|
|
148
148
|
stroke: "currentColor",
|
|
@@ -151,38 +151,38 @@ const Y = {
|
|
|
151
151
|
)
|
|
152
152
|
}
|
|
153
153
|
);
|
|
154
|
-
return /* @__PURE__ */ a(
|
|
154
|
+
return /* @__PURE__ */ a(B.Provider, { value: { collapsed: i, collapsedWidth: n, width: o }, children: /* @__PURE__ */ Q(
|
|
155
155
|
"aside",
|
|
156
156
|
{
|
|
157
|
-
ref:
|
|
158
|
-
className:
|
|
157
|
+
ref: z,
|
|
158
|
+
className: P,
|
|
159
159
|
style: {
|
|
160
160
|
width: typeof u == "number" ? `${u}px` : u,
|
|
161
|
-
...
|
|
161
|
+
...T
|
|
162
162
|
},
|
|
163
163
|
"data-collapsed": i,
|
|
164
164
|
"data-theme": t,
|
|
165
165
|
"data-testid": x,
|
|
166
166
|
"aria-expanded": !i,
|
|
167
|
-
...
|
|
167
|
+
...W,
|
|
168
168
|
children: [
|
|
169
169
|
/* @__PURE__ */ a("div", { className: "flex-1 overflow-auto", children: s }),
|
|
170
|
-
!j && f !== null && (f ??
|
|
171
|
-
|
|
170
|
+
!j && f !== null && (f ?? V),
|
|
171
|
+
D
|
|
172
172
|
]
|
|
173
173
|
}
|
|
174
174
|
) });
|
|
175
175
|
}
|
|
176
176
|
);
|
|
177
|
-
|
|
178
|
-
const
|
|
179
|
-
Header:
|
|
177
|
+
A.displayName = "LayoutSider";
|
|
178
|
+
const ee = Object.assign(v, {
|
|
179
|
+
Header: E,
|
|
180
180
|
Footer: R,
|
|
181
|
-
Content:
|
|
182
|
-
Sider:
|
|
181
|
+
Content: $,
|
|
182
|
+
Sider: A
|
|
183
183
|
});
|
|
184
184
|
export {
|
|
185
|
-
|
|
186
|
-
|
|
185
|
+
ee as Layout,
|
|
186
|
+
I as useSiderContext
|
|
187
187
|
};
|
|
188
188
|
//# sourceMappingURL=Layout.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Layout.js","sources":["../../src/components/Layout.tsx"],"sourcesContent":["import React, { createContext, useContext, useState, useCallback, useEffect, forwardRef } from 'react'\n\n// DaisyUI classes\nconst dBgBase100 = 'd-bg-base-100'\nconst dBgBase200 = 'd-bg-base-200'\nconst dBgBase300 = 'd-bg-base-300'\n\nexport type SiderTheme = 'light' | 'dark'\nexport type SiderCollapsedType = 'clickTrigger' | 'responsive'\n\nexport interface LayoutProps extends React.HTMLAttributes<HTMLDivElement> {\n children: React.ReactNode\n /** Whether contains Sider (auto-detected if not specified) */\n hasSider?: boolean\n /** Test ID for testing */\n 'data-testid'?: string\n}\n\nexport interface LayoutHeaderProps extends React.HTMLAttributes<HTMLElement> {\n children: React.ReactNode\n /** Test ID for testing */\n 'data-testid'?: string\n}\n\nexport interface LayoutFooterProps extends React.HTMLAttributes<HTMLElement> {\n children: React.ReactNode\n /** Test ID for testing */\n 'data-testid'?: string\n}\n\nexport interface LayoutContentProps extends React.HTMLAttributes<HTMLElement> {\n children: React.ReactNode\n /** Test ID for testing */\n 'data-testid'?: string\n}\n\nexport interface LayoutSiderProps extends Omit<React.HTMLAttributes<HTMLElement>, 'onSelect'> {\n children: React.ReactNode\n /** Width of the sider */\n width?: number | string\n /** Width when collapsed */\n collapsedWidth?: number | string\n /** Controlled collapsed state */\n collapsed?: boolean\n /** Initial collapsed state (uncontrolled) */\n defaultCollapsed?: boolean\n /** Whether can be collapsed */\n collapsible?: boolean\n /** Callback when collapse state changes */\n onCollapse?: (collapsed: boolean, type: SiderCollapsedType) => void\n /** Custom trigger element (null to hide) */\n trigger?: React.ReactNode | null\n /** Responsive breakpoint for auto-collapse */\n breakpoint?: 'sm' | 'md' | 'lg' | 'xl' | '2xl'\n /** Callback when breakpoint is crossed */\n onBreakpoint?: (broken: boolean) => void\n /** Reverse direction of arrow (for right-side sider) */\n reverseArrow?: boolean\n /** Color theme of the sider */\n theme?: SiderTheme\n /** Style for zero-width trigger */\n zeroWidthTriggerStyle?: React.CSSProperties\n /** Test ID for testing */\n 'data-testid'?: string\n}\n\ninterface SiderContextValue {\n collapsed: boolean\n collapsedWidth: number | string\n width: number | string\n}\n\nconst SiderContext = createContext<SiderContextValue | null>(null)\n\nexport function useSiderContext() {\n return useContext(SiderContext)\n}\n\nconst LayoutRoot = forwardRef<HTMLDivElement, LayoutProps>(\n ({ children, hasSider: hasSiderProp, className = '', 'data-testid': testId, ...rest }, ref) => {\n // Check if any child is a Sider to determine flex direction\n const childArray = React.Children.toArray(children)\n const hasSiderDetected = childArray.some(\n (child) => React.isValidElement(child) && (child.type as any).displayName === 'LayoutSider'\n )\n const hasSider = hasSiderProp ?? hasSiderDetected\n\n const layoutClasses = [\n 'flex',\n 'min-h-0',\n hasSider ? 'flex-row' : 'flex-col',\n className,\n ]\n .filter(Boolean)\n .join(' ')\n\n // If we have a Sider, auto-add flex-1 to non-Sider Layout children\n const processedChildren = hasSider\n ? childArray.map((child) => {\n if (\n React.isValidElement(child) &&\n (child.type === LayoutRoot || (child.type as any).displayName === 'LayoutRoot') &&\n (child.type as any).displayName !== 'LayoutSider'\n ) {\n // Clone the Layout child and add flex-1 if not already present\n const existingClassName = (child.props as any).className || ''\n if (!existingClassName.includes('flex-1')) {\n return React.cloneElement(child as React.ReactElement<any>, {\n className: `flex-1 ${existingClassName}`.trim(),\n })\n }\n }\n return child\n })\n : children\n\n return (\n <div ref={ref} className={layoutClasses} data-testid={testId} {...rest}>\n {processedChildren}\n </div>\n )\n }\n)\n\nLayoutRoot.displayName = 'LayoutRoot'\n\nconst LayoutHeader = forwardRef<HTMLElement, LayoutHeaderProps>(\n ({ children, className = '', 'data-testid': testId, ...rest }, ref) => {\n const headerClasses = [\n 'flex',\n 'items-center',\n 'px-6',\n 'h-16',\n dBgBase300,\n 'flex-shrink-0',\n className,\n ]\n .filter(Boolean)\n .join(' ')\n\n return (\n <header ref={ref} className={headerClasses} data-testid={testId} {...rest}>\n {children}\n </header>\n )\n }\n)\n\nLayoutHeader.displayName = 'LayoutHeader'\n\nconst LayoutFooter = forwardRef<HTMLElement, LayoutFooterProps>(\n ({ children, className = '', 'data-testid': testId, ...rest }, ref) => {\n const footerClasses = [\n 'px-6',\n 'py-4',\n 'text-center',\n dBgBase300,\n 'flex-shrink-0',\n className,\n ]\n .filter(Boolean)\n .join(' ')\n\n return (\n <footer ref={ref} className={footerClasses} data-testid={testId} {...rest}>\n {children}\n </footer>\n )\n }\n)\n\nLayoutFooter.displayName = 'LayoutFooter'\n\nconst LayoutContent = forwardRef<HTMLElement, LayoutContentProps>(\n ({ children, className = '', 'data-testid': testId, ...rest }, ref) => {\n // flex-1 by default so Content fills available space\n const contentClasses = ['flex-1', 'min-h-0', 'overflow-auto', className].filter(Boolean).join(' ')\n\n return (\n <main ref={ref} className={contentClasses} data-testid={testId} {...rest}>\n {children}\n </main>\n )\n }\n)\n\nLayoutContent.displayName = 'LayoutContent'\n\nconst BREAKPOINT_MAP: Record<string, string> = {\n sm: '(max-width: 639px)',\n md: '(max-width: 767px)',\n lg: '(max-width: 1023px)',\n xl: '(max-width: 1279px)',\n '2xl': '(max-width: 1535px)',\n}\n\nconst LayoutSider = forwardRef<HTMLElement, LayoutSiderProps>(\n (\n {\n children,\n width = 200,\n collapsedWidth = 80,\n collapsed: controlledCollapsed,\n defaultCollapsed = false,\n collapsible = false,\n onCollapse,\n trigger,\n breakpoint,\n onBreakpoint,\n reverseArrow = false,\n theme = 'dark',\n zeroWidthTriggerStyle,\n className = '',\n style,\n 'data-testid': testId,\n ...rest\n },\n ref\n ) => {\n const [internalCollapsed, setInternalCollapsed] = useState(defaultCollapsed)\n const [broken, setBroken] = useState(false)\n\n const collapsed = controlledCollapsed ?? internalCollapsed\n\n // Handle responsive breakpoint\n useEffect(() => {\n if (!breakpoint) return\n\n const mediaQuery = window.matchMedia(BREAKPOINT_MAP[breakpoint])\n\n const handleChange = (e: MediaQueryListEvent | MediaQueryList) => {\n const isBroken = e.matches\n setBroken(isBroken)\n onBreakpoint?.(isBroken)\n\n // Auto-collapse when breakpoint is crossed\n if (controlledCollapsed === undefined) {\n setInternalCollapsed(isBroken)\n }\n if (isBroken !== broken) {\n onCollapse?.(isBroken, 'responsive')\n }\n }\n\n // Check initial state\n handleChange(mediaQuery)\n\n // Listen for changes\n mediaQuery.addEventListener('change', handleChange)\n return () => mediaQuery.removeEventListener('change', handleChange)\n }, [breakpoint, onBreakpoint, controlledCollapsed, onCollapse, broken])\n\n const handleCollapse = useCallback(() => {\n const newCollapsed = !collapsed\n if (controlledCollapsed === undefined) {\n setInternalCollapsed(newCollapsed)\n }\n onCollapse?.(newCollapsed, 'clickTrigger')\n }, [collapsed, controlledCollapsed, onCollapse])\n\n const currentWidth = collapsed ? collapsedWidth : width\n const isZeroWidth = currentWidth === 0 || currentWidth === '0' || currentWidth === '0px'\n\n const themeClasses: Record<SiderTheme, string> = {\n light: dBgBase100,\n dark: dBgBase200,\n }\n\n const siderClasses = [\n 'flex',\n 'flex-col',\n themeClasses[theme],\n 'flex-shrink-0',\n 'transition-all',\n 'duration-200',\n 'relative',\n className,\n ]\n .filter(Boolean)\n .join(' ')\n\n // Determine arrow rotation based on collapsed state and reverseArrow prop\n const getArrowRotation = () => {\n if (reverseArrow) {\n return collapsed ? '' : 'rotate-180'\n }\n return collapsed ? 'rotate-180' : ''\n }\n\n const defaultTrigger = collapsible && trigger !== null && (\n <button\n onClick={handleCollapse}\n className={`flex items-center justify-center h-10 w-full ${dBgBase300} hover:bg-base-content/10 transition-colors`}\n aria-label={collapsed ? 'Expand sidebar' : 'Collapse sidebar'}\n data-testid={testId ? `${testId}-trigger` : undefined}\n >\n <svg\n className={`w-4 h-4 transition-transform ${getArrowRotation()}`}\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M15 19l-7-7 7-7\" />\n </svg>\n </button>\n )\n\n // Zero-width trigger (floating button when sider is collapsed to 0)\n const zeroWidthTrigger = collapsible && isZeroWidth && collapsed && (\n <button\n onClick={handleCollapse}\n className={`absolute top-1/2 -translate-y-1/2 right-0 translate-x-full w-6 h-12 flex items-center justify-center ${dBgBase300} hover:bg-base-content/10 transition-colors rounded-r z-10`}\n aria-label=\"Expand sidebar\"\n style={zeroWidthTriggerStyle}\n data-testid={testId ? `${testId}-zero-trigger` : undefined}\n >\n <svg\n className={`w-3 h-3 ${reverseArrow ? 'rotate-180' : ''}`}\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M9 5l7 7-7 7\" />\n </svg>\n </button>\n )\n\n return (\n <SiderContext.Provider value={{ collapsed, collapsedWidth, width }}>\n <aside\n ref={ref}\n className={siderClasses}\n style={{\n width: typeof currentWidth === 'number' ? `${currentWidth}px` : currentWidth,\n ...style,\n }}\n data-collapsed={collapsed}\n data-theme={theme}\n data-testid={testId}\n aria-expanded={!collapsed}\n {...rest}\n >\n <div className=\"flex-1 overflow-auto\">{children}</div>\n {!isZeroWidth && trigger !== null && (trigger ?? defaultTrigger)}\n {zeroWidthTrigger}\n </aside>\n </SiderContext.Provider>\n )\n }\n)\n\nLayoutSider.displayName = 'LayoutSider'\n\nexport const Layout = Object.assign(LayoutRoot, {\n Header: LayoutHeader,\n Footer: LayoutFooter,\n Content: LayoutContent,\n Sider: LayoutSider,\n})\n"],"names":["dBgBase100","dBgBase200","dBgBase300","SiderContext","createContext","useSiderContext","useContext","LayoutRoot","forwardRef","children","hasSiderProp","className","testId","rest","ref","childArray","React","hasSiderDetected","child","hasSider","layoutClasses","processedChildren","existingClassName","jsx","LayoutHeader","headerClasses","LayoutFooter","footerClasses","LayoutContent","contentClasses","BREAKPOINT_MAP","LayoutSider","width","collapsedWidth","controlledCollapsed","defaultCollapsed","collapsible","onCollapse","trigger","breakpoint","onBreakpoint","reverseArrow","theme","zeroWidthTriggerStyle","style","internalCollapsed","setInternalCollapsed","useState","broken","setBroken","collapsed","useEffect","mediaQuery","handleChange","e","isBroken","handleCollapse","useCallback","newCollapsed","currentWidth","isZeroWidth","siderClasses","getArrowRotation","defaultTrigger","zeroWidthTrigger","jsxs","Layout"],"mappings":";;AAGA,MAAMA,IAAa,iBACbC,IAAa,iBACbC,IAAa,iBAmEbC,IAAeC,EAAwC,IAAI;AAE1D,SAASC,KAAkB;AAChC,SAAOC,EAAWH,CAAY;AAChC;AAEA,MAAMI,IAAaC;AAAA,EACjB,CAAC,EAAE,UAAAC,GAAU,UAAUC,GAAc,WAAAC,IAAY,IAAI,eAAeC,GAAQ,GAAGC,EAAA,GAAQC,MAAQ;AAE7F,UAAMC,IAAaC,EAAM,SAAS,QAAQP,CAAQ,GAC5CQ,IAAmBF,EAAW;AAAA,MAClC,CAACG,MAAUF,EAAM,eAAeE,CAAK,KAAMA,EAAM,KAAa,gBAAgB;AAAA,IAAA,GAE1EC,IAAWT,KAAgBO,GAE3BG,IAAgB;AAAA,MACpB;AAAA,MACA;AAAA,MACAD,IAAW,aAAa;AAAA,MACxBR;AAAA,IAAA,EAEC,OAAO,OAAO,EACd,KAAK,GAAG,GAGLU,IAAoBF,IACtBJ,EAAW,IAAI,CAACG,MAAU;AACxB,UACEF,EAAM,eAAeE,CAAK,MACzBA,EAAM,SAASX,KAAeW,EAAM,KAAa,gBAAgB,iBACjEA,EAAM,KAAa,gBAAgB,eACpC;AAEA,cAAMI,IAAqBJ,EAAM,MAAc,aAAa;AAC5D,YAAI,CAACI,EAAkB,SAAS,QAAQ;AACtC,iBAAON,EAAM,aAAaE,GAAkC;AAAA,YAC1D,WAAW,UAAUI,CAAiB,GAAG,KAAA;AAAA,UAAK,CAC/C;AAAA,MAEL;AACA,aAAOJ;AAAA,IACT,CAAC,IACDT;AAEJ,WACE,gBAAAc,EAAC,SAAI,KAAAT,GAAU,WAAWM,GAAe,eAAaR,GAAS,GAAGC,GAC/D,UAAAQ,EAAA,CACH;AAAA,EAEJ;AACF;AAEAd,EAAW,cAAc;AAEzB,MAAMiB,IAAehB;AAAA,EACnB,CAAC,EAAE,UAAAC,GAAU,WAAAE,IAAY,IAAI,eAAeC,GAAQ,GAAGC,EAAA,GAAQC,MAAQ;AACrE,UAAMW,IAAgB;AAAA,MACpB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACAvB;AAAA,MACA;AAAA,MACAS;AAAA,IAAA,EAEC,OAAO,OAAO,EACd,KAAK,GAAG;AAEX,WACE,gBAAAY,EAAC,YAAO,KAAAT,GAAU,WAAWW,GAAe,eAAab,GAAS,GAAGC,GAClE,UAAAJ,EAAA,CACH;AAAA,EAEJ;AACF;AAEAe,EAAa,cAAc;AAE3B,MAAME,IAAelB;AAAA,EACnB,CAAC,EAAE,UAAAC,GAAU,WAAAE,IAAY,IAAI,eAAeC,GAAQ,GAAGC,EAAA,GAAQC,MAAQ;AACrE,UAAMa,IAAgB;AAAA,MACpB;AAAA,MACA;AAAA,MACA;AAAA,MACAzB;AAAA,MACA;AAAA,MACAS;AAAA,IAAA,EAEC,OAAO,OAAO,EACd,KAAK,GAAG;AAEX,WACE,gBAAAY,EAAC,YAAO,KAAAT,GAAU,WAAWa,GAAe,eAAaf,GAAS,GAAGC,GAClE,UAAAJ,EAAA,CACH;AAAA,EAEJ;AACF;AAEAiB,EAAa,cAAc;AAE3B,MAAME,IAAgBpB;AAAA,EACpB,CAAC,EAAE,UAAAC,GAAU,WAAAE,IAAY,IAAI,eAAeC,GAAQ,GAAGC,EAAA,GAAQC,MAAQ;AAErE,UAAMe,IAAiB,CAAC,UAAU,WAAW,iBAAiBlB,CAAS,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG;AAEjG,WACE,gBAAAY,EAAC,UAAK,KAAAT,GAAU,WAAWe,GAAgB,eAAajB,GAAS,GAAGC,GACjE,UAAAJ,EAAA,CACH;AAAA,EAEJ;AACF;AAEAmB,EAAc,cAAc;AAE5B,MAAME,IAAyC;AAAA,EAC7C,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,OAAO;AACT,GAEMC,IAAcvB;AAAA,EAClB,CACE;AAAA,IACE,UAAAC;AAAA,IACA,OAAAuB,IAAQ;AAAA,IACR,gBAAAC,IAAiB;AAAA,IACjB,WAAWC;AAAA,IACX,kBAAAC,IAAmB;AAAA,IACnB,aAAAC,IAAc;AAAA,IACd,YAAAC;AAAA,IACA,SAAAC;AAAA,IACA,YAAAC;AAAA,IACA,cAAAC;AAAA,IACA,cAAAC,IAAe;AAAA,IACf,OAAAC,IAAQ;AAAA,IACR,uBAAAC;AAAA,IACA,WAAAhC,IAAY;AAAA,IACZ,OAAAiC;AAAA,IACA,eAAehC;AAAA,IACf,GAAGC;AAAA,EAAA,GAELC,MACG;AACH,UAAM,CAAC+B,GAAmBC,CAAoB,IAAIC,EAASZ,CAAgB,GACrE,CAACa,GAAQC,CAAS,IAAIF,EAAS,EAAK,GAEpCG,IAAYhB,KAAuBW;AAGzC,IAAAM,EAAU,MAAM;AACd,UAAI,CAACZ,EAAY;AAEjB,YAAMa,IAAa,OAAO,WAAWtB,EAAeS,CAAU,CAAC,GAEzDc,IAAe,CAACC,MAA4C;AAChE,cAAMC,IAAWD,EAAE;AACnB,QAAAL,EAAUM,CAAQ,GAClBf,IAAee,CAAQ,GAGnBrB,MAAwB,UAC1BY,EAAqBS,CAAQ,GAE3BA,MAAaP,KACfX,IAAakB,GAAU,YAAY;AAAA,MAEvC;AAGA,aAAAF,EAAaD,CAAU,GAGvBA,EAAW,iBAAiB,UAAUC,CAAY,GAC3C,MAAMD,EAAW,oBAAoB,UAAUC,CAAY;AAAA,IACpE,GAAG,CAACd,GAAYC,GAAcN,GAAqBG,GAAYW,CAAM,CAAC;AAEtE,UAAMQ,IAAiBC,EAAY,MAAM;AACvC,YAAMC,IAAe,CAACR;AACtB,MAAIhB,MAAwB,UAC1BY,EAAqBY,CAAY,GAEnCrB,IAAaqB,GAAc,cAAc;AAAA,IAC3C,GAAG,CAACR,GAAWhB,GAAqBG,CAAU,CAAC,GAEzCsB,IAAeT,IAAYjB,IAAiBD,GAC5C4B,IAAcD,MAAiB,KAAKA,MAAiB,OAAOA,MAAiB,OAO7EE,IAAe;AAAA,MACnB;AAAA,MACA;AAAA,MAP+C;AAAA,QAC/C,OAAO7D;AAAA,QACP,MAAMC;AAAA,MAAA,EAMOyC,CAAK;AAAA,MAClB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA/B;AAAA,IAAA,EAEC,OAAO,OAAO,EACd,KAAK,GAAG,GAGLmD,IAAmB,MACnBrB,IACKS,IAAY,KAAK,eAEnBA,IAAY,eAAe,IAG9Ba,IAAiB3B,KAAeE,MAAY,QAChD,gBAAAf;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,SAASiC;AAAA,QACT,WAAW,gDAAgDtD,CAAU;AAAA,QACrE,cAAYgD,IAAY,mBAAmB;AAAA,QAC3C,eAAatC,IAAS,GAAGA,CAAM,aAAa;AAAA,QAE5C,UAAA,gBAAAW;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,WAAW,gCAAgCuC,EAAA,CAAkB;AAAA,YAC7D,MAAK;AAAA,YACL,SAAQ;AAAA,YACR,QAAO;AAAA,YAEP,UAAA,gBAAAvC,EAAC,UAAK,eAAc,SAAQ,gBAAe,SAAQ,aAAa,GAAG,GAAE,kBAAA,CAAkB;AAAA,UAAA;AAAA,QAAA;AAAA,MACzF;AAAA,IAAA,GAKEyC,IAAmB5B,KAAewB,KAAeV,KACrD,gBAAA3B;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,SAASiC;AAAA,QACT,WAAW,wGAAwGtD,CAAU;AAAA,QAC7H,cAAW;AAAA,QACX,OAAOyC;AAAA,QACP,eAAa/B,IAAS,GAAGA,CAAM,kBAAkB;AAAA,QAEjD,UAAA,gBAAAW;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,WAAW,WAAWkB,IAAe,eAAe,EAAE;AAAA,YACtD,MAAK;AAAA,YACL,SAAQ;AAAA,YACR,QAAO;AAAA,YAEP,UAAA,gBAAAlB,EAAC,UAAK,eAAc,SAAQ,gBAAe,SAAQ,aAAa,GAAG,GAAE,eAAA,CAAe;AAAA,UAAA;AAAA,QAAA;AAAA,MACtF;AAAA,IAAA;AAIJ,WACE,gBAAAA,EAACpB,EAAa,UAAb,EAAsB,OAAO,EAAE,WAAA+C,GAAW,gBAAAjB,GAAgB,OAAAD,KACzD,UAAA,gBAAAiC;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,KAAAnD;AAAA,QACA,WAAW+C;AAAA,QACX,OAAO;AAAA,UACL,OAAO,OAAOF,KAAiB,WAAW,GAAGA,CAAY,OAAOA;AAAA,UAChE,GAAGf;AAAA,QAAA;AAAA,QAEL,kBAAgBM;AAAA,QAChB,cAAYR;AAAA,QACZ,eAAa9B;AAAA,QACb,iBAAe,CAACsC;AAAA,QACf,GAAGrC;AAAA,QAEJ,UAAA;AAAA,UAAA,gBAAAU,EAAC,OAAA,EAAI,WAAU,wBAAwB,UAAAd,EAAA,CAAS;AAAA,UAC/C,CAACmD,KAAetB,MAAY,SAASA,KAAWyB;AAAA,UAChDC;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA,GAEL;AAAA,EAEJ;AACF;AAEAjC,EAAY,cAAc;AAEnB,MAAMmC,KAAS,OAAO,OAAO3D,GAAY;AAAA,EAC9C,QAAQiB;AAAA,EACR,QAAQE;AAAA,EACR,SAASE;AAAA,EACT,OAAOG;AACT,CAAC;"}
|
|
1
|
+
{"version":3,"file":"Layout.js","sources":["../../src/components/Layout.tsx"],"sourcesContent":["import React, { createContext, useContext, useState, useCallback, useEffect, forwardRef } from 'react'\n\nexport type SiderTheme = 'light' | 'dark'\nexport type SiderCollapsedType = 'clickTrigger' | 'responsive'\n\nexport interface LayoutProps extends React.HTMLAttributes<HTMLDivElement> {\n children: React.ReactNode\n /** Whether contains Sider (auto-detected if not specified) */\n hasSider?: boolean\n /** Test ID for testing */\n 'data-testid'?: string\n}\n\nexport interface LayoutHeaderProps extends React.HTMLAttributes<HTMLElement> {\n children: React.ReactNode\n /** Test ID for testing */\n 'data-testid'?: string\n}\n\nexport interface LayoutFooterProps extends React.HTMLAttributes<HTMLElement> {\n children: React.ReactNode\n /** Test ID for testing */\n 'data-testid'?: string\n}\n\nexport interface LayoutContentProps extends React.HTMLAttributes<HTMLElement> {\n children: React.ReactNode\n /** Test ID for testing */\n 'data-testid'?: string\n}\n\nexport interface LayoutSiderProps extends Omit<React.HTMLAttributes<HTMLElement>, 'onSelect'> {\n children: React.ReactNode\n /** Width of the sider */\n width?: number | string\n /** Width when collapsed */\n collapsedWidth?: number | string\n /** Controlled collapsed state */\n collapsed?: boolean\n /** Initial collapsed state (uncontrolled) */\n defaultCollapsed?: boolean\n /** Whether can be collapsed */\n collapsible?: boolean\n /** Callback when collapse state changes */\n onCollapse?: (collapsed: boolean, type: SiderCollapsedType) => void\n /** Custom trigger element (null to hide) */\n trigger?: React.ReactNode | null\n /** Responsive breakpoint for auto-collapse */\n breakpoint?: 'sm' | 'md' | 'lg' | 'xl' | '2xl'\n /** Callback when breakpoint is crossed */\n onBreakpoint?: (broken: boolean) => void\n /** Reverse direction of arrow (for right-side sider) */\n reverseArrow?: boolean\n /** Color theme of the sider */\n theme?: SiderTheme\n /** Style for zero-width trigger */\n zeroWidthTriggerStyle?: React.CSSProperties\n /** Test ID for testing */\n 'data-testid'?: string\n}\n\ninterface SiderContextValue {\n collapsed: boolean\n collapsedWidth: number | string\n width: number | string\n}\n\nconst SiderContext = createContext<SiderContextValue | null>(null)\n\nexport function useSiderContext() {\n return useContext(SiderContext)\n}\n\nconst LayoutRoot = forwardRef<HTMLDivElement, LayoutProps>(\n ({ children, hasSider: hasSiderProp, className = '', 'data-testid': testId, ...rest }, ref) => {\n // Check if any child is a Sider to determine flex direction\n const childArray = React.Children.toArray(children)\n const hasSiderDetected = childArray.some(\n (child) => React.isValidElement(child) && (child.type as any).displayName === 'LayoutSider'\n )\n const hasSider = hasSiderProp ?? hasSiderDetected\n\n const layoutClasses = [\n 'flex',\n 'min-h-0',\n hasSider ? 'flex-row' : 'flex-col',\n className,\n ]\n .filter(Boolean)\n .join(' ')\n\n // If we have a Sider, auto-add flex-1 to non-Sider Layout children\n const processedChildren = hasSider\n ? childArray.map((child) => {\n if (\n React.isValidElement(child) &&\n (child.type === LayoutRoot || (child.type as any).displayName === 'LayoutRoot') &&\n (child.type as any).displayName !== 'LayoutSider'\n ) {\n // Clone the Layout child and add flex-1 if not already present\n const existingClassName = (child.props as any).className || ''\n if (!existingClassName.includes('flex-1')) {\n return React.cloneElement(child as React.ReactElement<any>, {\n className: `flex-1 ${existingClassName}`.trim(),\n })\n }\n }\n return child\n })\n : children\n\n return (\n <div ref={ref} className={layoutClasses} data-testid={testId} {...rest}>\n {processedChildren}\n </div>\n )\n }\n)\n\nLayoutRoot.displayName = 'LayoutRoot'\n\nconst LayoutHeader = forwardRef<HTMLElement, LayoutHeaderProps>(\n ({ children, className = '', 'data-testid': testId, ...rest }, ref) => {\n const headerClasses = [\n 'flex',\n 'items-center',\n 'px-6',\n 'h-16',\n 'bg-base-300',\n 'flex-shrink-0',\n className,\n ]\n .filter(Boolean)\n .join(' ')\n\n return (\n <header ref={ref} className={headerClasses} data-testid={testId} {...rest}>\n {children}\n </header>\n )\n }\n)\n\nLayoutHeader.displayName = 'LayoutHeader'\n\nconst LayoutFooter = forwardRef<HTMLElement, LayoutFooterProps>(\n ({ children, className = '', 'data-testid': testId, ...rest }, ref) => {\n const footerClasses = [\n 'px-6',\n 'py-4',\n 'text-center',\n 'bg-base-300',\n 'flex-shrink-0',\n className,\n ]\n .filter(Boolean)\n .join(' ')\n\n return (\n <footer ref={ref} className={footerClasses} data-testid={testId} {...rest}>\n {children}\n </footer>\n )\n }\n)\n\nLayoutFooter.displayName = 'LayoutFooter'\n\nconst LayoutContent = forwardRef<HTMLElement, LayoutContentProps>(\n ({ children, className = '', 'data-testid': testId, ...rest }, ref) => {\n // flex-1 by default so Content fills available space\n const contentClasses = ['flex-1', 'min-h-0', 'overflow-auto', className].filter(Boolean).join(' ')\n\n return (\n <main ref={ref} className={contentClasses} data-testid={testId} {...rest}>\n {children}\n </main>\n )\n }\n)\n\nLayoutContent.displayName = 'LayoutContent'\n\nconst BREAKPOINT_MAP: Record<string, string> = {\n sm: '(max-width: 639px)',\n md: '(max-width: 767px)',\n lg: '(max-width: 1023px)',\n xl: '(max-width: 1279px)',\n '2xl': '(max-width: 1535px)',\n}\n\nconst LayoutSider = forwardRef<HTMLElement, LayoutSiderProps>(\n (\n {\n children,\n width = 200,\n collapsedWidth = 80,\n collapsed: controlledCollapsed,\n defaultCollapsed = false,\n collapsible = false,\n onCollapse,\n trigger,\n breakpoint,\n onBreakpoint,\n reverseArrow = false,\n theme = 'dark',\n zeroWidthTriggerStyle,\n className = '',\n style,\n 'data-testid': testId,\n ...rest\n },\n ref\n ) => {\n const [internalCollapsed, setInternalCollapsed] = useState(defaultCollapsed)\n const [broken, setBroken] = useState(false)\n\n const collapsed = controlledCollapsed ?? internalCollapsed\n\n // Handle responsive breakpoint\n useEffect(() => {\n if (!breakpoint) return\n\n const mediaQuery = window.matchMedia(BREAKPOINT_MAP[breakpoint])\n\n const handleChange = (e: MediaQueryListEvent | MediaQueryList) => {\n const isBroken = e.matches\n setBroken(isBroken)\n onBreakpoint?.(isBroken)\n\n // Auto-collapse when breakpoint is crossed\n if (controlledCollapsed === undefined) {\n setInternalCollapsed(isBroken)\n }\n if (isBroken !== broken) {\n onCollapse?.(isBroken, 'responsive')\n }\n }\n\n // Check initial state\n handleChange(mediaQuery)\n\n // Listen for changes\n mediaQuery.addEventListener('change', handleChange)\n return () => mediaQuery.removeEventListener('change', handleChange)\n }, [breakpoint, onBreakpoint, controlledCollapsed, onCollapse, broken])\n\n const handleCollapse = useCallback(() => {\n const newCollapsed = !collapsed\n if (controlledCollapsed === undefined) {\n setInternalCollapsed(newCollapsed)\n }\n onCollapse?.(newCollapsed, 'clickTrigger')\n }, [collapsed, controlledCollapsed, onCollapse])\n\n const currentWidth = collapsed ? collapsedWidth : width\n const isZeroWidth = currentWidth === 0 || currentWidth === '0' || currentWidth === '0px'\n\n const themeClasses: Record<SiderTheme, string> = {\n light: 'bg-base-100',\n dark: 'bg-base-200',\n }\n\n const siderClasses = [\n 'flex',\n 'flex-col',\n themeClasses[theme],\n 'flex-shrink-0',\n 'transition-all',\n 'duration-200',\n 'relative',\n className,\n ]\n .filter(Boolean)\n .join(' ')\n\n // Determine arrow rotation based on collapsed state and reverseArrow prop\n const getArrowRotation = () => {\n if (reverseArrow) {\n return collapsed ? '' : 'rotate-180'\n }\n return collapsed ? 'rotate-180' : ''\n }\n\n const defaultTrigger = collapsible && trigger !== null && (\n <button\n onClick={handleCollapse}\n className=\"flex items-center justify-center h-10 w-full bg-base-300 hover:bg-base-content/10 transition-colors\"\n aria-label={collapsed ? 'Expand sidebar' : 'Collapse sidebar'}\n data-testid={testId ? `${testId}-trigger` : undefined}\n >\n <svg\n className={`w-4 h-4 transition-transform ${getArrowRotation()}`}\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M15 19l-7-7 7-7\" />\n </svg>\n </button>\n )\n\n // Zero-width trigger (floating button when sider is collapsed to 0)\n const zeroWidthTrigger = collapsible && isZeroWidth && collapsed && (\n <button\n onClick={handleCollapse}\n className=\"absolute top-1/2 -translate-y-1/2 right-0 translate-x-full w-6 h-12 flex items-center justify-center bg-base-300 hover:bg-base-content/10 transition-colors rounded-r z-10\"\n aria-label=\"Expand sidebar\"\n style={zeroWidthTriggerStyle}\n data-testid={testId ? `${testId}-zero-trigger` : undefined}\n >\n <svg\n className={`w-3 h-3 ${reverseArrow ? 'rotate-180' : ''}`}\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M9 5l7 7-7 7\" />\n </svg>\n </button>\n )\n\n return (\n <SiderContext.Provider value={{ collapsed, collapsedWidth, width }}>\n <aside\n ref={ref}\n className={siderClasses}\n style={{\n width: typeof currentWidth === 'number' ? `${currentWidth}px` : currentWidth,\n ...style,\n }}\n data-collapsed={collapsed}\n data-theme={theme}\n data-testid={testId}\n aria-expanded={!collapsed}\n {...rest}\n >\n <div className=\"flex-1 overflow-auto\">{children}</div>\n {!isZeroWidth && trigger !== null && (trigger ?? defaultTrigger)}\n {zeroWidthTrigger}\n </aside>\n </SiderContext.Provider>\n )\n }\n)\n\nLayoutSider.displayName = 'LayoutSider'\n\nexport const Layout = Object.assign(LayoutRoot, {\n Header: LayoutHeader,\n Footer: LayoutFooter,\n Content: LayoutContent,\n Sider: LayoutSider,\n})\n"],"names":["SiderContext","createContext","useSiderContext","useContext","LayoutRoot","forwardRef","children","hasSiderProp","className","testId","rest","ref","childArray","React","hasSiderDetected","child","hasSider","layoutClasses","processedChildren","existingClassName","jsx","LayoutHeader","headerClasses","LayoutFooter","footerClasses","LayoutContent","contentClasses","BREAKPOINT_MAP","LayoutSider","width","collapsedWidth","controlledCollapsed","defaultCollapsed","collapsible","onCollapse","trigger","breakpoint","onBreakpoint","reverseArrow","theme","zeroWidthTriggerStyle","style","internalCollapsed","setInternalCollapsed","useState","broken","setBroken","collapsed","useEffect","mediaQuery","handleChange","e","isBroken","handleCollapse","useCallback","newCollapsed","currentWidth","isZeroWidth","siderClasses","getArrowRotation","defaultTrigger","zeroWidthTrigger","jsxs","Layout"],"mappings":"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"}
|
|
@@ -1,126 +1,126 @@
|
|
|
1
|
-
import { jsx as h, jsxs as
|
|
2
|
-
import
|
|
3
|
-
const
|
|
1
|
+
import { jsx as h, jsxs as K, Fragment as ie } from "react/jsx-runtime";
|
|
2
|
+
import T, { useRef as L, useState as J, useCallback as y, useEffect as Q } from "react";
|
|
3
|
+
const pe = ({ children: M }) => /* @__PURE__ */ h(ie, { children: M }), ue = ({
|
|
4
4
|
children: M,
|
|
5
|
-
direction:
|
|
6
|
-
sizes:
|
|
7
|
-
defaultSizes:
|
|
8
|
-
onSizesChange:
|
|
5
|
+
direction: z = "horizontal",
|
|
6
|
+
sizes: P,
|
|
7
|
+
defaultSizes: $,
|
|
8
|
+
onSizesChange: F,
|
|
9
9
|
gutterSize: R = 8,
|
|
10
10
|
minSize: E = 50,
|
|
11
|
-
className:
|
|
11
|
+
className: Z = ""
|
|
12
12
|
}) => {
|
|
13
|
-
const D = L(null),
|
|
14
|
-
(e) =>
|
|
15
|
-
), m = u.length, [
|
|
13
|
+
const D = L(null), I = L([]), x = L(null), u = T.Children.toArray(M).filter(
|
|
14
|
+
(e) => T.isValidElement(e)
|
|
15
|
+
), m = u.length, [f, W] = J(
|
|
16
16
|
() => u.map((e) => e.props.defaultCollapsed ?? e.props.collapsed ?? !1)
|
|
17
|
-
),
|
|
17
|
+
), X = L([]), j = y(() => {
|
|
18
18
|
const e = u.map((s) => s.props.defaultSize), o = e.some((s) => s !== void 0);
|
|
19
|
-
if (
|
|
20
|
-
return
|
|
19
|
+
if ($ && $.length === m)
|
|
20
|
+
return $;
|
|
21
21
|
if (o) {
|
|
22
22
|
const s = e.reduce((l, n) => l + (n ?? 0), 0), r = e.filter((l) => l === void 0).length, a = Math.max(0, 100 - s), t = r > 0 ? a / r : 0;
|
|
23
23
|
return e.map((l) => l ?? t);
|
|
24
24
|
}
|
|
25
25
|
const i = 100 / m;
|
|
26
26
|
return Array(m).fill(i);
|
|
27
|
-
}, [
|
|
27
|
+
}, [$, m, u]), [k, Y] = J(j), ee = y(() => {
|
|
28
28
|
const e = u.map((t) => t.props.size);
|
|
29
29
|
if (!e.some((t) => t !== void 0)) return null;
|
|
30
30
|
const i = e.reduce((t, l) => t + (l ?? 0), 0), s = e.filter((t) => t === void 0).length, r = Math.max(0, 100 - i), a = s > 0 ? r / s : 0;
|
|
31
|
-
return e.map((t, l) => t ??
|
|
32
|
-
}, [u,
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
}, [m,
|
|
31
|
+
return e.map((t, l) => t ?? k[l] ?? a);
|
|
32
|
+
}, [u, k]), d = P || ee() || k;
|
|
33
|
+
Q(() => {
|
|
34
|
+
!P && k.length !== m && Y(j());
|
|
35
|
+
}, [m, P, k.length, j]), Q(() => {
|
|
36
36
|
const e = u.map(
|
|
37
|
-
(i, s) => i.props.collapsed ??
|
|
37
|
+
(i, s) => i.props.collapsed ?? f[s] ?? !1
|
|
38
38
|
);
|
|
39
|
-
e.some((i, s) => i !==
|
|
39
|
+
e.some((i, s) => i !== f[s]) && W(e);
|
|
40
40
|
}, [u.map((e) => e.props.collapsed).join(",")]);
|
|
41
|
-
const
|
|
41
|
+
const b = y(
|
|
42
42
|
(e) => {
|
|
43
|
-
|
|
43
|
+
P || Y(e), F?.(e);
|
|
44
44
|
},
|
|
45
|
-
[
|
|
46
|
-
),
|
|
45
|
+
[P, F]
|
|
46
|
+
), _ = y(
|
|
47
47
|
(e) => {
|
|
48
48
|
const o = u[e];
|
|
49
49
|
if (!o?.props.collapsible) return;
|
|
50
|
-
const s = !
|
|
51
|
-
if (r[e] = s,
|
|
52
|
-
|
|
53
|
-
const a = 0, t =
|
|
50
|
+
const s = !f[e], r = [...f];
|
|
51
|
+
if (r[e] = s, W(r), o.props.onCollapse?.(s), s) {
|
|
52
|
+
X.current = [...d];
|
|
53
|
+
const a = 0, t = d[e] - a, l = d.map((n, c) => ({ size: n, index: c })).filter((n, c) => c !== e && !r[c]);
|
|
54
54
|
if (l.length > 0) {
|
|
55
|
-
const n = t / l.length, c =
|
|
56
|
-
|
|
55
|
+
const n = t / l.length, c = d.map((p, w) => w === e ? a : r[w] ? p : p + n);
|
|
56
|
+
b(c);
|
|
57
57
|
}
|
|
58
58
|
} else {
|
|
59
|
-
const a =
|
|
59
|
+
const a = X.current[e] || 100 / m, l = d.map((n, c) => ({ size: n, index: c })).filter((n, c) => c !== e && !r[c]).reduce((n, c) => n + c.size, 0);
|
|
60
60
|
if (l > 0) {
|
|
61
|
-
const n =
|
|
61
|
+
const n = d.map((c, p) => {
|
|
62
62
|
if (p === e) return a;
|
|
63
63
|
if (!r[p]) {
|
|
64
|
-
const
|
|
65
|
-
return c - a *
|
|
64
|
+
const w = c / l;
|
|
65
|
+
return c - a * w;
|
|
66
66
|
}
|
|
67
67
|
return c;
|
|
68
68
|
});
|
|
69
|
-
|
|
69
|
+
b(n);
|
|
70
70
|
}
|
|
71
71
|
}
|
|
72
72
|
},
|
|
73
|
-
[u,
|
|
74
|
-
),
|
|
73
|
+
[u, f, d, m, b]
|
|
74
|
+
), te = y(
|
|
75
75
|
(e, o) => {
|
|
76
76
|
const i = u[e]?.props || {}, s = u[e + 1]?.props || {};
|
|
77
|
-
if (i.resizable === !1 || s.resizable === !1 ||
|
|
77
|
+
if (i.resizable === !1 || s.resizable === !1 || f[e] || f[e + 1])
|
|
78
78
|
return;
|
|
79
79
|
o.preventDefault();
|
|
80
|
-
const r =
|
|
80
|
+
const r = z === "horizontal" ? o.clientX : o.clientY;
|
|
81
81
|
x.current = {
|
|
82
82
|
index: e,
|
|
83
83
|
startPos: r,
|
|
84
|
-
startSizes: [...
|
|
84
|
+
startSizes: [...d]
|
|
85
85
|
};
|
|
86
86
|
const a = (l) => {
|
|
87
87
|
if (!x.current || !D.current) return;
|
|
88
|
-
const { index: n, startPos: c, startSizes: p } = x.current,
|
|
89
|
-
let v = p[n] +
|
|
90
|
-
v < A && (v = A,
|
|
91
|
-
const
|
|
92
|
-
if (
|
|
93
|
-
const
|
|
94
|
-
v >
|
|
88
|
+
const { index: n, startPos: c, startSizes: p } = x.current, w = D.current.getBoundingClientRect(), se = z === "horizontal" ? w.width : w.height, re = z === "horizontal" ? l.clientX : l.clientY, le = (m - 1) * R, N = se - le, q = (re - c) / N * 100, G = u[n]?.props || {}, H = u[n + 1]?.props || {}, ae = G.minSize ?? E, ce = H.minSize ?? E, A = ae / N * 100, B = ce / N * 100;
|
|
89
|
+
let v = p[n] + q, C = p[n + 1] - q;
|
|
90
|
+
v < A && (v = A, C = p[n] + p[n + 1] - A), C < B && (C = B, v = p[n] + p[n + 1] - B);
|
|
91
|
+
const O = G.maxSize, V = H.maxSize;
|
|
92
|
+
if (O) {
|
|
93
|
+
const S = O / N * 100;
|
|
94
|
+
v > S && (v = S, C = p[n] + p[n + 1] - S);
|
|
95
95
|
}
|
|
96
|
-
if (
|
|
97
|
-
const
|
|
98
|
-
|
|
96
|
+
if (V) {
|
|
97
|
+
const S = V / N * 100;
|
|
98
|
+
C > S && (C = S, v = p[n] + p[n + 1] - S);
|
|
99
99
|
}
|
|
100
|
-
const
|
|
101
|
-
|
|
100
|
+
const U = [...p];
|
|
101
|
+
U[n] = v, U[n + 1] = C, b(U);
|
|
102
102
|
}, t = () => {
|
|
103
103
|
x.current = null, document.removeEventListener("mousemove", a), document.removeEventListener("mouseup", t), document.body.style.cursor = "", document.body.style.userSelect = "";
|
|
104
104
|
};
|
|
105
|
-
document.addEventListener("mousemove", a), document.addEventListener("mouseup", t), document.body.style.cursor =
|
|
105
|
+
document.addEventListener("mousemove", a), document.addEventListener("mouseup", t), document.body.style.cursor = z === "horizontal" ? "col-resize" : "row-resize", document.body.style.userSelect = "none";
|
|
106
106
|
},
|
|
107
|
-
[
|
|
108
|
-
),
|
|
107
|
+
[z, d, m, R, u, E, b, f]
|
|
108
|
+
), oe = y(
|
|
109
109
|
(e, o) => {
|
|
110
|
-
if (
|
|
110
|
+
if (f[e] || f[e + 1])
|
|
111
111
|
return;
|
|
112
112
|
const i = o.shiftKey ? 10 : 1;
|
|
113
113
|
let s = 0;
|
|
114
|
-
if (
|
|
114
|
+
if (z === "horizontal" ? o.key === "ArrowLeft" ? s = -i : o.key === "ArrowRight" && (s = i) : o.key === "ArrowUp" ? s = -i : o.key === "ArrowDown" && (s = i), s !== 0) {
|
|
115
115
|
o.preventDefault();
|
|
116
|
-
const r = [...
|
|
116
|
+
const r = [...d], a = 5;
|
|
117
117
|
let t = r[e] + s, l = r[e + 1] - s;
|
|
118
|
-
t >= a && l >= a && (r[e] = t, r[e + 1] = l,
|
|
118
|
+
t >= a && l >= a && (r[e] = t, r[e + 1] = l, b(r));
|
|
119
119
|
}
|
|
120
120
|
},
|
|
121
|
-
[
|
|
122
|
-
),
|
|
123
|
-
const o = u[e], i = u[e + 1], s = o?.props.collapsible, r = i?.props.collapsible, a =
|
|
121
|
+
[z, d, b, f]
|
|
122
|
+
), g = z === "horizontal", ne = (e) => {
|
|
123
|
+
const o = u[e], i = u[e + 1], s = o?.props.collapsible, r = i?.props.collapsible, a = f[e], t = f[e + 1];
|
|
124
124
|
return {
|
|
125
125
|
showStart: s && !t,
|
|
126
126
|
showEnd: r && !a,
|
|
@@ -132,19 +132,19 @@ const ze = "d-bg-base-300", ge = "d-bg-primary", B = "d-text-base-content", we =
|
|
|
132
132
|
"div",
|
|
133
133
|
{
|
|
134
134
|
ref: D,
|
|
135
|
-
className: `flex ${
|
|
135
|
+
className: `flex ${g ? "flex-row" : "flex-col"} h-full w-full ${Z}`,
|
|
136
136
|
children: u.map((e, o) => {
|
|
137
|
-
const i = e.props, s = o === u.length - 1, r =
|
|
138
|
-
return /* @__PURE__ */
|
|
137
|
+
const i = e.props, s = o === u.length - 1, r = f[o], a = i.resizable !== !1 && !r;
|
|
138
|
+
return /* @__PURE__ */ K(T.Fragment, { children: [
|
|
139
139
|
/* @__PURE__ */ h(
|
|
140
140
|
"div",
|
|
141
141
|
{
|
|
142
142
|
ref: (t) => {
|
|
143
|
-
|
|
143
|
+
I.current[o] = t;
|
|
144
144
|
},
|
|
145
145
|
className: `overflow-auto ${i.className || ""}`,
|
|
146
146
|
style: {
|
|
147
|
-
[
|
|
147
|
+
[g ? "width" : "height"]: r ? "0px" : `calc(${d[o]}% - ${(m - 1) * R / m}px)`,
|
|
148
148
|
flexShrink: 0,
|
|
149
149
|
overflow: r ? "hidden" : "auto"
|
|
150
150
|
},
|
|
@@ -156,40 +156,40 @@ const ze = "d-bg-base-300", ge = "d-bg-primary", B = "d-text-base-content", we =
|
|
|
156
156
|
"div",
|
|
157
157
|
{
|
|
158
158
|
role: "separator",
|
|
159
|
-
"aria-orientation":
|
|
160
|
-
"aria-valuenow": Math.round(
|
|
159
|
+
"aria-orientation": g ? "vertical" : "horizontal",
|
|
160
|
+
"aria-valuenow": Math.round(d[o]),
|
|
161
161
|
tabIndex: a ? 0 : -1,
|
|
162
162
|
className: `
|
|
163
|
-
flex-shrink-0
|
|
164
|
-
${a ?
|
|
165
|
-
${a ?
|
|
163
|
+
flex-shrink-0 bg-base-300 transition-colors duration-150 relative group
|
|
164
|
+
${a ? "hover:bg-primary/30 active:bg-primary/50" : ""}
|
|
165
|
+
${a ? g ? "cursor-col-resize" : "cursor-row-resize" : "cursor-default"}
|
|
166
166
|
`,
|
|
167
167
|
style: {
|
|
168
|
-
[
|
|
168
|
+
[g ? "width" : "height"]: `${R}px`
|
|
169
169
|
},
|
|
170
|
-
onMouseDown: (t) =>
|
|
171
|
-
onKeyDown: (t) =>
|
|
170
|
+
onMouseDown: (t) => te(o, t),
|
|
171
|
+
onKeyDown: (t) => oe(o, t),
|
|
172
172
|
children: (() => {
|
|
173
|
-
const { showStart: t, showEnd: l, panel1Collapsed: n, panel2Collapsed: c } =
|
|
174
|
-
return !t && !l ? /* @__PURE__ */
|
|
173
|
+
const { showStart: t, showEnd: l, panel1Collapsed: n, panel2Collapsed: c } = ne(o);
|
|
174
|
+
return !t && !l ? /* @__PURE__ */ K(
|
|
175
175
|
"div",
|
|
176
176
|
{
|
|
177
177
|
className: `
|
|
178
178
|
absolute inset-0 flex items-center justify-center
|
|
179
|
-
${
|
|
179
|
+
${g ? "flex-col gap-0.5" : "flex-row gap-0.5"}
|
|
180
180
|
`,
|
|
181
181
|
children: [
|
|
182
|
-
/* @__PURE__ */ h("div", { className:
|
|
183
|
-
/* @__PURE__ */ h("div", { className:
|
|
184
|
-
/* @__PURE__ */ h("div", { className:
|
|
182
|
+
/* @__PURE__ */ h("div", { className: "w-1 h-1 rounded-full bg-base-content/30 group-hover:bg-primary/60" }),
|
|
183
|
+
/* @__PURE__ */ h("div", { className: "w-1 h-1 rounded-full bg-base-content/30 group-hover:bg-primary/60" }),
|
|
184
|
+
/* @__PURE__ */ h("div", { className: "w-1 h-1 rounded-full bg-base-content/30 group-hover:bg-primary/60" })
|
|
185
185
|
]
|
|
186
186
|
}
|
|
187
|
-
) : /* @__PURE__ */
|
|
187
|
+
) : /* @__PURE__ */ K(
|
|
188
188
|
"div",
|
|
189
189
|
{
|
|
190
190
|
className: `
|
|
191
191
|
absolute inset-0 flex items-center justify-center
|
|
192
|
-
${
|
|
192
|
+
${g ? "flex-col" : "flex-row"}
|
|
193
193
|
`,
|
|
194
194
|
children: [
|
|
195
195
|
t && /* @__PURE__ */ h(
|
|
@@ -197,17 +197,17 @@ const ze = "d-bg-base-300", ge = "d-bg-primary", B = "d-text-base-content", we =
|
|
|
197
197
|
{
|
|
198
198
|
type: "button",
|
|
199
199
|
onClick: (p) => {
|
|
200
|
-
p.stopPropagation(),
|
|
200
|
+
p.stopPropagation(), _(o);
|
|
201
201
|
},
|
|
202
202
|
className: `
|
|
203
|
-
p-0.5
|
|
203
|
+
p-0.5 rounded hover:bg-base-content/20 transition-colors
|
|
204
204
|
|
|
205
205
|
`,
|
|
206
206
|
"aria-label": n ? "Expand panel" : "Collapse panel",
|
|
207
207
|
children: /* @__PURE__ */ h(
|
|
208
208
|
"svg",
|
|
209
209
|
{
|
|
210
|
-
className: `w-3 h-3
|
|
210
|
+
className: `w-3 h-3 text-base-content/50 hover:text-base-content transition-transform ${n ? g ? "rotate-180" : "-rotate-90" : g ? "rotate-0" : "rotate-90"}`,
|
|
211
211
|
fill: "none",
|
|
212
212
|
viewBox: "0 0 24 24",
|
|
213
213
|
stroke: "currentColor",
|
|
@@ -221,16 +221,14 @@ const ze = "d-bg-base-300", ge = "d-bg-primary", B = "d-text-base-content", we =
|
|
|
221
221
|
{
|
|
222
222
|
type: "button",
|
|
223
223
|
onClick: (p) => {
|
|
224
|
-
p.stopPropagation(),
|
|
224
|
+
p.stopPropagation(), _(o + 1);
|
|
225
225
|
},
|
|
226
|
-
className:
|
|
227
|
-
p-0.5 ${ne} ${oe}/20 transition-colors
|
|
228
|
-
`,
|
|
226
|
+
className: "p-0.5 rounded hover:bg-base-content/20 transition-colors",
|
|
229
227
|
"aria-label": c ? "Expand panel" : "Collapse panel",
|
|
230
228
|
children: /* @__PURE__ */ h(
|
|
231
229
|
"svg",
|
|
232
230
|
{
|
|
233
|
-
className: `w-3 h-3
|
|
231
|
+
className: `w-3 h-3 text-base-content/50 hover:text-base-content transition-transform ${c ? g ? "rotate-0" : "rotate-90" : g ? "rotate-180" : "-rotate-90"}`,
|
|
234
232
|
fill: "none",
|
|
235
233
|
viewBox: "0 0 24 24",
|
|
236
234
|
stroke: "currentColor",
|
|
@@ -250,8 +248,8 @@ const ze = "d-bg-base-300", ge = "d-bg-primary", B = "d-text-base-content", we =
|
|
|
250
248
|
}
|
|
251
249
|
);
|
|
252
250
|
};
|
|
253
|
-
|
|
251
|
+
ue.Panel = pe;
|
|
254
252
|
export {
|
|
255
|
-
|
|
253
|
+
ue as Splitter
|
|
256
254
|
};
|
|
257
255
|
//# sourceMappingURL=Splitter.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Splitter.js","sources":["../../src/components/Splitter.tsx"],"sourcesContent":["import React, { useState, useRef, useCallback, useEffect } from 'react'\n\n// DaisyUI classes\nconst dBgBase300 = 'd-bg-base-300'\nconst dBgPrimary = 'd-bg-primary'\nconst dTextBaseContent = 'd-text-base-content'\nconst dHoverBgPrimary = 'd-hover:bg-primary'\nconst dHoverTextBaseContent = 'd-hover:text-base-content'\nconst dGroupHoverBgPrimary = 'd-group-hover:bg-primary'\nconst dHoverBgBaseContent = 'd-hover:bg-base-content'\nconst dRounded = 'd-rounded'\nconst dRoundedFull = 'd-rounded-full'\n\nexport interface SplitterPanelProps {\n children: React.ReactNode\n defaultSize?: number\n size?: number\n minSize?: number\n maxSize?: number\n collapsible?: boolean\n collapsed?: boolean\n defaultCollapsed?: boolean\n onCollapse?: (collapsed: boolean) => void\n resizable?: boolean\n className?: string\n}\n\nexport interface SplitterProps {\n children: React.ReactNode\n direction?: 'horizontal' | 'vertical'\n sizes?: number[]\n defaultSizes?: number[]\n onSizesChange?: (sizes: number[]) => void\n gutterSize?: number\n minSize?: number\n className?: string\n}\n\nconst Panel: React.FC<SplitterPanelProps> = ({ children }) => {\n return <>{children}</>\n}\n\nexport const Splitter: React.FC<SplitterProps> & { Panel: typeof Panel } = ({\n children,\n direction = 'horizontal',\n sizes,\n defaultSizes,\n onSizesChange,\n gutterSize = 8,\n minSize = 50,\n className = '',\n}) => {\n const containerRef = useRef<HTMLDivElement>(null)\n const panelsRef = useRef<(HTMLDivElement | null)[]>([])\n const draggingRef = useRef<{ index: number; startPos: number; startSizes: number[] } | null>(null)\n\n // Extract panel props from children\n const panels = React.Children.toArray(children).filter(\n (child): child is React.ReactElement<SplitterPanelProps> =>\n React.isValidElement(child)\n )\n\n const panelCount = panels.length\n\n // Track collapsed state for each panel\n const [collapsedStates, setCollapsedStates] = useState<boolean[]>(() =>\n panels.map((panel) => panel.props.defaultCollapsed ?? panel.props.collapsed ?? false)\n )\n\n // Store sizes before collapse for restoration\n const sizesBeforeCollapseRef = useRef<number[]>([])\n\n // Initialize sizes from panel props or defaults\n const getInitialSizes = useCallback(() => {\n // First check if any panels have defaultSize\n const panelDefaultSizes = panels.map((panel) => panel.props.defaultSize)\n const hasAnyPanelSize = panelDefaultSizes.some((s) => s !== undefined)\n\n if (defaultSizes && defaultSizes.length === panelCount) {\n return defaultSizes\n }\n\n if (hasAnyPanelSize) {\n // Calculate sizes from panel props\n const definedTotal = panelDefaultSizes.reduce<number>((sum, s) => sum + (s ?? 0), 0)\n const undefinedCount = panelDefaultSizes.filter((s) => s === undefined).length\n const remainingSize = Math.max(0, 100 - definedTotal)\n const sizePerUndefined = undefinedCount > 0 ? remainingSize / undefinedCount : 0\n\n return panelDefaultSizes.map((s) => s ?? sizePerUndefined)\n }\n\n // Equal distribution\n const equalSize = 100 / panelCount\n return Array(panelCount).fill(equalSize)\n }, [defaultSizes, panelCount, panels])\n\n const [internalSizes, setInternalSizes] = useState<number[]>(getInitialSizes)\n\n // Handle controlled sizes from panel props\n const getControlledSizes = useCallback(() => {\n const panelSizes = panels.map((panel) => panel.props.size)\n const hasControlledPanel = panelSizes.some((s) => s !== undefined)\n\n if (!hasControlledPanel) return null\n\n // Mix controlled and uncontrolled\n const definedTotal = panelSizes.reduce<number>((sum, s) => sum + (s ?? 0), 0)\n const undefinedCount = panelSizes.filter((s) => s === undefined).length\n const remainingSize = Math.max(0, 100 - definedTotal)\n const sizePerUndefined = undefinedCount > 0 ? remainingSize / undefinedCount : 0\n\n return panelSizes.map((s, i) => s ?? internalSizes[i] ?? sizePerUndefined)\n }, [panels, internalSizes])\n\n const currentSizes = sizes || getControlledSizes() || internalSizes\n\n // Update internal sizes when panel count changes\n useEffect(() => {\n if (!sizes && internalSizes.length !== panelCount) {\n setInternalSizes(getInitialSizes())\n }\n }, [panelCount, sizes, internalSizes.length, getInitialSizes])\n\n // Sync controlled collapsed states from props\n useEffect(() => {\n const newCollapsedStates = panels.map((panel, i) =>\n panel.props.collapsed ?? collapsedStates[i] ?? false\n )\n const hasChange = newCollapsedStates.some((s, i) => s !== collapsedStates[i])\n if (hasChange) {\n setCollapsedStates(newCollapsedStates)\n }\n }, [panels.map(p => p.props.collapsed).join(',')])\n\n const updateSizes = useCallback(\n (newSizes: number[]) => {\n if (!sizes) {\n setInternalSizes(newSizes)\n }\n onSizesChange?.(newSizes)\n },\n [sizes, onSizesChange]\n )\n\n const toggleCollapse = useCallback(\n (panelIndex: number) => {\n const panel = panels[panelIndex]\n if (!panel?.props.collapsible) return\n\n const isCurrentlyCollapsed = collapsedStates[panelIndex]\n const newCollapsed = !isCurrentlyCollapsed\n\n // Update collapsed state\n const newCollapsedStates = [...collapsedStates]\n newCollapsedStates[panelIndex] = newCollapsed\n setCollapsedStates(newCollapsedStates)\n\n // Call panel's onCollapse callback\n panel.props.onCollapse?.(newCollapsed)\n\n // Adjust sizes\n if (newCollapsed) {\n // Store current sizes before collapse\n sizesBeforeCollapseRef.current = [...currentSizes]\n\n // Collapse: set to minimum (we'll use 0 for collapsed)\n const collapsedSize = 0\n const sizeToRedistribute = currentSizes[panelIndex] - collapsedSize\n\n // Find panels that can receive the size\n const otherPanels = currentSizes\n .map((s, i) => ({ size: s, index: i }))\n .filter((_, i) => i !== panelIndex && !newCollapsedStates[i])\n\n if (otherPanels.length > 0) {\n const sizePerPanel = sizeToRedistribute / otherPanels.length\n const newSizes = currentSizes.map((s, i) => {\n if (i === panelIndex) return collapsedSize\n if (!newCollapsedStates[i]) return s + sizePerPanel\n return s\n })\n updateSizes(newSizes)\n }\n } else {\n // Expand: restore previous size\n const previousSize = sizesBeforeCollapseRef.current[panelIndex] || (100 / panelCount)\n\n // Take size from other panels proportionally\n const otherPanels = currentSizes\n .map((s, i) => ({ size: s, index: i }))\n .filter((_, i) => i !== panelIndex && !newCollapsedStates[i])\n\n const totalOtherSize = otherPanels.reduce((sum, p) => sum + p.size, 0)\n\n if (totalOtherSize > 0) {\n const newSizes = currentSizes.map((s, i) => {\n if (i === panelIndex) return previousSize\n if (!newCollapsedStates[i]) {\n const proportion = s / totalOtherSize\n return s - previousSize * proportion\n }\n return s\n })\n updateSizes(newSizes)\n }\n }\n },\n [panels, collapsedStates, currentSizes, panelCount, updateSizes]\n )\n\n const handleMouseDown = useCallback(\n (index: number, e: React.MouseEvent) => {\n // Check if either panel is non-resizable\n const panel1Props = panels[index]?.props || {}\n const panel2Props = panels[index + 1]?.props || {}\n\n if (panel1Props.resizable === false || panel2Props.resizable === false) {\n return // Don't allow dragging\n }\n\n // Don't allow dragging if either panel is collapsed\n if (collapsedStates[index] || collapsedStates[index + 1]) {\n return\n }\n\n e.preventDefault()\n const startPos = direction === 'horizontal' ? e.clientX : e.clientY\n draggingRef.current = {\n index,\n startPos,\n startSizes: [...currentSizes],\n }\n\n const handleMouseMove = (moveEvent: MouseEvent) => {\n if (!draggingRef.current || !containerRef.current) return\n\n const { index: dragIndex, startPos: dragStartPos, startSizes } = draggingRef.current\n const containerRect = containerRef.current.getBoundingClientRect()\n const containerSize = direction === 'horizontal' ? containerRect.width : containerRect.height\n const currentPos = direction === 'horizontal' ? moveEvent.clientX : moveEvent.clientY\n\n // Calculate delta as percentage\n const gutterCount = panelCount - 1\n const totalGutterSize = gutterCount * gutterSize\n const availableSize = containerSize - totalGutterSize\n const deltaPixels = currentPos - dragStartPos\n const deltaPercent = (deltaPixels / availableSize) * 100\n\n // Get min sizes for panels\n const panel1Props = panels[dragIndex]?.props || {}\n const panel2Props = panels[dragIndex + 1]?.props || {}\n const minSize1 = panel1Props.minSize ?? minSize\n const minSize2 = panel2Props.minSize ?? minSize\n const minPercent1 = (minSize1 / availableSize) * 100\n const minPercent2 = (minSize2 / availableSize) * 100\n\n // Calculate new sizes\n let newSize1 = startSizes[dragIndex] + deltaPercent\n let newSize2 = startSizes[dragIndex + 1] - deltaPercent\n\n // Apply min constraints\n if (newSize1 < minPercent1) {\n newSize1 = minPercent1\n newSize2 = startSizes[dragIndex] + startSizes[dragIndex + 1] - minPercent1\n }\n if (newSize2 < minPercent2) {\n newSize2 = minPercent2\n newSize1 = startSizes[dragIndex] + startSizes[dragIndex + 1] - minPercent2\n }\n\n // Apply max constraints\n const maxSize1 = panel1Props.maxSize\n const maxSize2 = panel2Props.maxSize\n if (maxSize1) {\n const maxPercent1 = (maxSize1 / availableSize) * 100\n if (newSize1 > maxPercent1) {\n newSize1 = maxPercent1\n newSize2 = startSizes[dragIndex] + startSizes[dragIndex + 1] - maxPercent1\n }\n }\n if (maxSize2) {\n const maxPercent2 = (maxSize2 / availableSize) * 100\n if (newSize2 > maxPercent2) {\n newSize2 = maxPercent2\n newSize1 = startSizes[dragIndex] + startSizes[dragIndex + 1] - maxPercent2\n }\n }\n\n const newSizes = [...startSizes]\n newSizes[dragIndex] = newSize1\n newSizes[dragIndex + 1] = newSize2\n updateSizes(newSizes)\n }\n\n const handleMouseUp = () => {\n draggingRef.current = null\n document.removeEventListener('mousemove', handleMouseMove)\n document.removeEventListener('mouseup', handleMouseUp)\n document.body.style.cursor = ''\n document.body.style.userSelect = ''\n }\n\n document.addEventListener('mousemove', handleMouseMove)\n document.addEventListener('mouseup', handleMouseUp)\n document.body.style.cursor = direction === 'horizontal' ? 'col-resize' : 'row-resize'\n document.body.style.userSelect = 'none'\n },\n [direction, currentSizes, panelCount, gutterSize, panels, minSize, updateSizes, collapsedStates]\n )\n\n const handleKeyDown = useCallback(\n (index: number, e: React.KeyboardEvent) => {\n // Don't allow keyboard resize if either panel is collapsed\n if (collapsedStates[index] || collapsedStates[index + 1]) {\n return\n }\n\n const step = e.shiftKey ? 10 : 1\n let delta = 0\n\n if (direction === 'horizontal') {\n if (e.key === 'ArrowLeft') delta = -step\n else if (e.key === 'ArrowRight') delta = step\n } else {\n if (e.key === 'ArrowUp') delta = -step\n else if (e.key === 'ArrowDown') delta = step\n }\n\n if (delta !== 0) {\n e.preventDefault()\n const newSizes = [...currentSizes]\n const minPercent = 5 // Minimum 5% when using keyboard\n\n let newSize1 = newSizes[index] + delta\n let newSize2 = newSizes[index + 1] - delta\n\n if (newSize1 >= minPercent && newSize2 >= minPercent) {\n newSizes[index] = newSize1\n newSizes[index + 1] = newSize2\n updateSizes(newSizes)\n }\n }\n },\n [direction, currentSizes, updateSizes, collapsedStates]\n )\n\n const isHorizontal = direction === 'horizontal'\n\n // Determine if gutter should show collapse buttons\n const getCollapseConfig = (index: number) => {\n const panel1 = panels[index]\n const panel2 = panels[index + 1]\n const panel1Collapsible = panel1?.props.collapsible\n const panel2Collapsible = panel2?.props.collapsible\n const panel1Collapsed = collapsedStates[index]\n const panel2Collapsed = collapsedStates[index + 1]\n\n return {\n showStart: panel1Collapsible && !panel2Collapsed,\n showEnd: panel2Collapsible && !panel1Collapsed,\n panel1Collapsed,\n panel2Collapsed,\n }\n }\n\n return (\n <div\n ref={containerRef}\n className={`flex ${isHorizontal ? 'flex-row' : 'flex-col'} h-full w-full ${className}`}\n >\n {panels.map((panel, index) => {\n const panelProps = panel.props\n const isLast = index === panels.length - 1\n const isCollapsed = collapsedStates[index]\n const canResize = panelProps.resizable !== false && !isCollapsed\n\n return (\n <React.Fragment key={index}>\n <div\n ref={(el) => {\n panelsRef.current[index] = el\n }}\n className={`overflow-auto ${panelProps.className || ''}`}\n style={{\n [isHorizontal ? 'width' : 'height']: isCollapsed\n ? '0px'\n : `calc(${currentSizes[index]}% - ${((panelCount - 1) * gutterSize) / panelCount}px)`,\n flexShrink: 0,\n overflow: isCollapsed ? 'hidden' : 'auto',\n }}\n data-collapsed={isCollapsed}\n >\n {panelProps.children}\n </div>\n {!isLast && (\n <div\n role=\"separator\"\n aria-orientation={isHorizontal ? 'vertical' : 'horizontal'}\n aria-valuenow={Math.round(currentSizes[index])}\n tabIndex={canResize ? 0 : -1}\n className={`\n flex-shrink-0 ${dBgBase300} transition-colors duration-150 relative group\n ${canResize ? `${dHoverBgPrimary}/30 active:${dBgPrimary}/50` : ''}\n ${canResize ? (isHorizontal ? 'cursor-col-resize' : 'cursor-row-resize') : 'cursor-default'}\n `}\n style={{\n [isHorizontal ? 'width' : 'height']: `${gutterSize}px`,\n }}\n onMouseDown={(e) => handleMouseDown(index, e)}\n onKeyDown={(e) => handleKeyDown(index, e)}\n >\n {/* Collapse buttons */}\n {(() => {\n const { showStart, showEnd, panel1Collapsed, panel2Collapsed } = getCollapseConfig(index)\n\n if (!showStart && !showEnd) {\n // Just show grip indicator\n return (\n <div\n className={`\n absolute inset-0 flex items-center justify-center\n ${isHorizontal ? 'flex-col gap-0.5' : 'flex-row gap-0.5'}\n `}\n >\n <div className={`w-1 h-1 ${dRoundedFull} ${dTextBaseContent}/30 ${dGroupHoverBgPrimary}/60`} />\n <div className={`w-1 h-1 ${dRoundedFull} ${dTextBaseContent}/30 ${dGroupHoverBgPrimary}/60`} />\n <div className={`w-1 h-1 ${dRoundedFull} ${dTextBaseContent}/30 ${dGroupHoverBgPrimary}/60`} />\n </div>\n )\n }\n\n return (\n <div\n className={`\n absolute inset-0 flex items-center justify-center\n ${isHorizontal ? 'flex-col' : 'flex-row'}\n `}\n >\n {showStart && (\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation()\n toggleCollapse(index)\n }}\n className={`\n p-0.5 ${dRounded} ${dHoverBgBaseContent}/20 transition-colors\n ${isHorizontal ? '' : ''}\n `}\n aria-label={panel1Collapsed ? 'Expand panel' : 'Collapse panel'}\n >\n <svg\n className={`w-3 h-3 ${dTextBaseContent}/50 ${dHoverTextBaseContent} transition-transform ${\n panel1Collapsed\n ? isHorizontal ? 'rotate-180' : '-rotate-90'\n : isHorizontal ? 'rotate-0' : 'rotate-90'\n }`}\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M15 19l-7-7 7-7\" />\n </svg>\n </button>\n )}\n {showEnd && (\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation()\n toggleCollapse(index + 1)\n }}\n className={`\n p-0.5 ${dRounded} ${dHoverBgBaseContent}/20 transition-colors\n `}\n aria-label={panel2Collapsed ? 'Expand panel' : 'Collapse panel'}\n >\n <svg\n className={`w-3 h-3 ${dTextBaseContent}/50 ${dHoverTextBaseContent} transition-transform ${\n panel2Collapsed\n ? isHorizontal ? 'rotate-0' : 'rotate-90'\n : isHorizontal ? 'rotate-180' : '-rotate-90'\n }`}\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M15 19l-7-7 7-7\" />\n </svg>\n </button>\n )}\n </div>\n )\n })()}\n </div>\n )}\n </React.Fragment>\n )\n })}\n </div>\n )\n}\n\nSplitter.Panel = Panel\n"],"names":["dBgBase300","dBgPrimary","dTextBaseContent","dHoverBgPrimary","dHoverTextBaseContent","dGroupHoverBgPrimary","dHoverBgBaseContent","dRounded","dRoundedFull","Panel","children","Splitter","direction","sizes","defaultSizes","onSizesChange","gutterSize","minSize","className","containerRef","useRef","panelsRef","draggingRef","panels","React","child","panelCount","collapsedStates","setCollapsedStates","useState","panel","sizesBeforeCollapseRef","getInitialSizes","useCallback","panelDefaultSizes","hasAnyPanelSize","definedTotal","sum","s","undefinedCount","remainingSize","sizePerUndefined","equalSize","internalSizes","setInternalSizes","getControlledSizes","panelSizes","i","currentSizes","useEffect","newCollapsedStates","p","updateSizes","newSizes","toggleCollapse","panelIndex","newCollapsed","collapsedSize","sizeToRedistribute","otherPanels","_","sizePerPanel","previousSize","totalOtherSize","proportion","handleMouseDown","index","e","panel1Props","panel2Props","startPos","handleMouseMove","moveEvent","dragIndex","dragStartPos","startSizes","containerRect","containerSize","currentPos","totalGutterSize","availableSize","deltaPercent","minSize1","minSize2","minPercent1","minPercent2","newSize1","newSize2","maxSize1","maxSize2","maxPercent1","maxPercent2","handleMouseUp","handleKeyDown","step","delta","minPercent","isHorizontal","getCollapseConfig","panel1","panel2","panel1Collapsible","panel2Collapsible","panel1Collapsed","panel2Collapsed","jsx","panelProps","isLast","isCollapsed","canResize","jsxs","el","showStart","showEnd"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Splitter.js","sources":["../../src/components/Splitter.tsx"],"sourcesContent":["import React, { useState, useRef, useCallback, useEffect } from 'react'\n\nexport interface SplitterPanelProps {\n children: React.ReactNode\n defaultSize?: number\n size?: number\n minSize?: number\n maxSize?: number\n collapsible?: boolean\n collapsed?: boolean\n defaultCollapsed?: boolean\n onCollapse?: (collapsed: boolean) => void\n resizable?: boolean\n className?: string\n}\n\nexport interface SplitterProps {\n children: React.ReactNode\n direction?: 'horizontal' | 'vertical'\n sizes?: number[]\n defaultSizes?: number[]\n onSizesChange?: (sizes: number[]) => void\n gutterSize?: number\n minSize?: number\n className?: string\n}\n\nconst Panel: React.FC<SplitterPanelProps> = ({ children }) => {\n return <>{children}</>\n}\n\nexport const Splitter: React.FC<SplitterProps> & { Panel: typeof Panel } = ({\n children,\n direction = 'horizontal',\n sizes,\n defaultSizes,\n onSizesChange,\n gutterSize = 8,\n minSize = 50,\n className = '',\n}) => {\n const containerRef = useRef<HTMLDivElement>(null)\n const panelsRef = useRef<(HTMLDivElement | null)[]>([])\n const draggingRef = useRef<{ index: number; startPos: number; startSizes: number[] } | null>(null)\n\n // Extract panel props from children\n const panels = React.Children.toArray(children).filter(\n (child): child is React.ReactElement<SplitterPanelProps> =>\n React.isValidElement(child)\n )\n\n const panelCount = panels.length\n\n // Track collapsed state for each panel\n const [collapsedStates, setCollapsedStates] = useState<boolean[]>(() =>\n panels.map((panel) => panel.props.defaultCollapsed ?? panel.props.collapsed ?? false)\n )\n\n // Store sizes before collapse for restoration\n const sizesBeforeCollapseRef = useRef<number[]>([])\n\n // Initialize sizes from panel props or defaults\n const getInitialSizes = useCallback(() => {\n // First check if any panels have defaultSize\n const panelDefaultSizes = panels.map((panel) => panel.props.defaultSize)\n const hasAnyPanelSize = panelDefaultSizes.some((s) => s !== undefined)\n\n if (defaultSizes && defaultSizes.length === panelCount) {\n return defaultSizes\n }\n\n if (hasAnyPanelSize) {\n // Calculate sizes from panel props\n const definedTotal = panelDefaultSizes.reduce<number>((sum, s) => sum + (s ?? 0), 0)\n const undefinedCount = panelDefaultSizes.filter((s) => s === undefined).length\n const remainingSize = Math.max(0, 100 - definedTotal)\n const sizePerUndefined = undefinedCount > 0 ? remainingSize / undefinedCount : 0\n\n return panelDefaultSizes.map((s) => s ?? sizePerUndefined)\n }\n\n // Equal distribution\n const equalSize = 100 / panelCount\n return Array(panelCount).fill(equalSize)\n }, [defaultSizes, panelCount, panels])\n\n const [internalSizes, setInternalSizes] = useState<number[]>(getInitialSizes)\n\n // Handle controlled sizes from panel props\n const getControlledSizes = useCallback(() => {\n const panelSizes = panels.map((panel) => panel.props.size)\n const hasControlledPanel = panelSizes.some((s) => s !== undefined)\n\n if (!hasControlledPanel) return null\n\n // Mix controlled and uncontrolled\n const definedTotal = panelSizes.reduce<number>((sum, s) => sum + (s ?? 0), 0)\n const undefinedCount = panelSizes.filter((s) => s === undefined).length\n const remainingSize = Math.max(0, 100 - definedTotal)\n const sizePerUndefined = undefinedCount > 0 ? remainingSize / undefinedCount : 0\n\n return panelSizes.map((s, i) => s ?? internalSizes[i] ?? sizePerUndefined)\n }, [panels, internalSizes])\n\n const currentSizes = sizes || getControlledSizes() || internalSizes\n\n // Update internal sizes when panel count changes\n useEffect(() => {\n if (!sizes && internalSizes.length !== panelCount) {\n setInternalSizes(getInitialSizes())\n }\n }, [panelCount, sizes, internalSizes.length, getInitialSizes])\n\n // Sync controlled collapsed states from props\n useEffect(() => {\n const newCollapsedStates = panels.map((panel, i) =>\n panel.props.collapsed ?? collapsedStates[i] ?? false\n )\n const hasChange = newCollapsedStates.some((s, i) => s !== collapsedStates[i])\n if (hasChange) {\n setCollapsedStates(newCollapsedStates)\n }\n }, [panels.map(p => p.props.collapsed).join(',')])\n\n const updateSizes = useCallback(\n (newSizes: number[]) => {\n if (!sizes) {\n setInternalSizes(newSizes)\n }\n onSizesChange?.(newSizes)\n },\n [sizes, onSizesChange]\n )\n\n const toggleCollapse = useCallback(\n (panelIndex: number) => {\n const panel = panels[panelIndex]\n if (!panel?.props.collapsible) return\n\n const isCurrentlyCollapsed = collapsedStates[panelIndex]\n const newCollapsed = !isCurrentlyCollapsed\n\n // Update collapsed state\n const newCollapsedStates = [...collapsedStates]\n newCollapsedStates[panelIndex] = newCollapsed\n setCollapsedStates(newCollapsedStates)\n\n // Call panel's onCollapse callback\n panel.props.onCollapse?.(newCollapsed)\n\n // Adjust sizes\n if (newCollapsed) {\n // Store current sizes before collapse\n sizesBeforeCollapseRef.current = [...currentSizes]\n\n // Collapse: set to minimum (we'll use 0 for collapsed)\n const collapsedSize = 0\n const sizeToRedistribute = currentSizes[panelIndex] - collapsedSize\n\n // Find panels that can receive the size\n const otherPanels = currentSizes\n .map((s, i) => ({ size: s, index: i }))\n .filter((_, i) => i !== panelIndex && !newCollapsedStates[i])\n\n if (otherPanels.length > 0) {\n const sizePerPanel = sizeToRedistribute / otherPanels.length\n const newSizes = currentSizes.map((s, i) => {\n if (i === panelIndex) return collapsedSize\n if (!newCollapsedStates[i]) return s + sizePerPanel\n return s\n })\n updateSizes(newSizes)\n }\n } else {\n // Expand: restore previous size\n const previousSize = sizesBeforeCollapseRef.current[panelIndex] || (100 / panelCount)\n\n // Take size from other panels proportionally\n const otherPanels = currentSizes\n .map((s, i) => ({ size: s, index: i }))\n .filter((_, i) => i !== panelIndex && !newCollapsedStates[i])\n\n const totalOtherSize = otherPanels.reduce((sum, p) => sum + p.size, 0)\n\n if (totalOtherSize > 0) {\n const newSizes = currentSizes.map((s, i) => {\n if (i === panelIndex) return previousSize\n if (!newCollapsedStates[i]) {\n const proportion = s / totalOtherSize\n return s - previousSize * proportion\n }\n return s\n })\n updateSizes(newSizes)\n }\n }\n },\n [panels, collapsedStates, currentSizes, panelCount, updateSizes]\n )\n\n const handleMouseDown = useCallback(\n (index: number, e: React.MouseEvent) => {\n // Check if either panel is non-resizable\n const panel1Props = panels[index]?.props || {}\n const panel2Props = panels[index + 1]?.props || {}\n\n if (panel1Props.resizable === false || panel2Props.resizable === false) {\n return // Don't allow dragging\n }\n\n // Don't allow dragging if either panel is collapsed\n if (collapsedStates[index] || collapsedStates[index + 1]) {\n return\n }\n\n e.preventDefault()\n const startPos = direction === 'horizontal' ? e.clientX : e.clientY\n draggingRef.current = {\n index,\n startPos,\n startSizes: [...currentSizes],\n }\n\n const handleMouseMove = (moveEvent: MouseEvent) => {\n if (!draggingRef.current || !containerRef.current) return\n\n const { index: dragIndex, startPos: dragStartPos, startSizes } = draggingRef.current\n const containerRect = containerRef.current.getBoundingClientRect()\n const containerSize = direction === 'horizontal' ? containerRect.width : containerRect.height\n const currentPos = direction === 'horizontal' ? moveEvent.clientX : moveEvent.clientY\n\n // Calculate delta as percentage\n const gutterCount = panelCount - 1\n const totalGutterSize = gutterCount * gutterSize\n const availableSize = containerSize - totalGutterSize\n const deltaPixels = currentPos - dragStartPos\n const deltaPercent = (deltaPixels / availableSize) * 100\n\n // Get min sizes for panels\n const panel1Props = panels[dragIndex]?.props || {}\n const panel2Props = panels[dragIndex + 1]?.props || {}\n const minSize1 = panel1Props.minSize ?? minSize\n const minSize2 = panel2Props.minSize ?? minSize\n const minPercent1 = (minSize1 / availableSize) * 100\n const minPercent2 = (minSize2 / availableSize) * 100\n\n // Calculate new sizes\n let newSize1 = startSizes[dragIndex] + deltaPercent\n let newSize2 = startSizes[dragIndex + 1] - deltaPercent\n\n // Apply min constraints\n if (newSize1 < minPercent1) {\n newSize1 = minPercent1\n newSize2 = startSizes[dragIndex] + startSizes[dragIndex + 1] - minPercent1\n }\n if (newSize2 < minPercent2) {\n newSize2 = minPercent2\n newSize1 = startSizes[dragIndex] + startSizes[dragIndex + 1] - minPercent2\n }\n\n // Apply max constraints\n const maxSize1 = panel1Props.maxSize\n const maxSize2 = panel2Props.maxSize\n if (maxSize1) {\n const maxPercent1 = (maxSize1 / availableSize) * 100\n if (newSize1 > maxPercent1) {\n newSize1 = maxPercent1\n newSize2 = startSizes[dragIndex] + startSizes[dragIndex + 1] - maxPercent1\n }\n }\n if (maxSize2) {\n const maxPercent2 = (maxSize2 / availableSize) * 100\n if (newSize2 > maxPercent2) {\n newSize2 = maxPercent2\n newSize1 = startSizes[dragIndex] + startSizes[dragIndex + 1] - maxPercent2\n }\n }\n\n const newSizes = [...startSizes]\n newSizes[dragIndex] = newSize1\n newSizes[dragIndex + 1] = newSize2\n updateSizes(newSizes)\n }\n\n const handleMouseUp = () => {\n draggingRef.current = null\n document.removeEventListener('mousemove', handleMouseMove)\n document.removeEventListener('mouseup', handleMouseUp)\n document.body.style.cursor = ''\n document.body.style.userSelect = ''\n }\n\n document.addEventListener('mousemove', handleMouseMove)\n document.addEventListener('mouseup', handleMouseUp)\n document.body.style.cursor = direction === 'horizontal' ? 'col-resize' : 'row-resize'\n document.body.style.userSelect = 'none'\n },\n [direction, currentSizes, panelCount, gutterSize, panels, minSize, updateSizes, collapsedStates]\n )\n\n const handleKeyDown = useCallback(\n (index: number, e: React.KeyboardEvent) => {\n // Don't allow keyboard resize if either panel is collapsed\n if (collapsedStates[index] || collapsedStates[index + 1]) {\n return\n }\n\n const step = e.shiftKey ? 10 : 1\n let delta = 0\n\n if (direction === 'horizontal') {\n if (e.key === 'ArrowLeft') delta = -step\n else if (e.key === 'ArrowRight') delta = step\n } else {\n if (e.key === 'ArrowUp') delta = -step\n else if (e.key === 'ArrowDown') delta = step\n }\n\n if (delta !== 0) {\n e.preventDefault()\n const newSizes = [...currentSizes]\n const minPercent = 5 // Minimum 5% when using keyboard\n\n let newSize1 = newSizes[index] + delta\n let newSize2 = newSizes[index + 1] - delta\n\n if (newSize1 >= minPercent && newSize2 >= minPercent) {\n newSizes[index] = newSize1\n newSizes[index + 1] = newSize2\n updateSizes(newSizes)\n }\n }\n },\n [direction, currentSizes, updateSizes, collapsedStates]\n )\n\n const isHorizontal = direction === 'horizontal'\n\n // Determine if gutter should show collapse buttons\n const getCollapseConfig = (index: number) => {\n const panel1 = panels[index]\n const panel2 = panels[index + 1]\n const panel1Collapsible = panel1?.props.collapsible\n const panel2Collapsible = panel2?.props.collapsible\n const panel1Collapsed = collapsedStates[index]\n const panel2Collapsed = collapsedStates[index + 1]\n\n return {\n showStart: panel1Collapsible && !panel2Collapsed,\n showEnd: panel2Collapsible && !panel1Collapsed,\n panel1Collapsed,\n panel2Collapsed,\n }\n }\n\n return (\n <div\n ref={containerRef}\n className={`flex ${isHorizontal ? 'flex-row' : 'flex-col'} h-full w-full ${className}`}\n >\n {panels.map((panel, index) => {\n const panelProps = panel.props\n const isLast = index === panels.length - 1\n const isCollapsed = collapsedStates[index]\n const canResize = panelProps.resizable !== false && !isCollapsed\n\n return (\n <React.Fragment key={index}>\n <div\n ref={(el) => {\n panelsRef.current[index] = el\n }}\n className={`overflow-auto ${panelProps.className || ''}`}\n style={{\n [isHorizontal ? 'width' : 'height']: isCollapsed\n ? '0px'\n : `calc(${currentSizes[index]}% - ${((panelCount - 1) * gutterSize) / panelCount}px)`,\n flexShrink: 0,\n overflow: isCollapsed ? 'hidden' : 'auto',\n }}\n data-collapsed={isCollapsed}\n >\n {panelProps.children}\n </div>\n {!isLast && (\n <div\n role=\"separator\"\n aria-orientation={isHorizontal ? 'vertical' : 'horizontal'}\n aria-valuenow={Math.round(currentSizes[index])}\n tabIndex={canResize ? 0 : -1}\n className={`\n flex-shrink-0 bg-base-300 transition-colors duration-150 relative group\n ${canResize ? 'hover:bg-primary/30 active:bg-primary/50' : ''}\n ${canResize ? (isHorizontal ? 'cursor-col-resize' : 'cursor-row-resize') : 'cursor-default'}\n `}\n style={{\n [isHorizontal ? 'width' : 'height']: `${gutterSize}px`,\n }}\n onMouseDown={(e) => handleMouseDown(index, e)}\n onKeyDown={(e) => handleKeyDown(index, e)}\n >\n {/* Collapse buttons */}\n {(() => {\n const { showStart, showEnd, panel1Collapsed, panel2Collapsed } = getCollapseConfig(index)\n\n if (!showStart && !showEnd) {\n // Just show grip indicator\n return (\n <div\n className={`\n absolute inset-0 flex items-center justify-center\n ${isHorizontal ? 'flex-col gap-0.5' : 'flex-row gap-0.5'}\n `}\n >\n <div className=\"w-1 h-1 rounded-full bg-base-content/30 group-hover:bg-primary/60\" />\n <div className=\"w-1 h-1 rounded-full bg-base-content/30 group-hover:bg-primary/60\" />\n <div className=\"w-1 h-1 rounded-full bg-base-content/30 group-hover:bg-primary/60\" />\n </div>\n )\n }\n\n return (\n <div\n className={`\n absolute inset-0 flex items-center justify-center\n ${isHorizontal ? 'flex-col' : 'flex-row'}\n `}\n >\n {showStart && (\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation()\n toggleCollapse(index)\n }}\n className={`\n p-0.5 rounded hover:bg-base-content/20 transition-colors\n ${isHorizontal ? '' : ''}\n `}\n aria-label={panel1Collapsed ? 'Expand panel' : 'Collapse panel'}\n >\n <svg\n className={`w-3 h-3 text-base-content/50 hover:text-base-content transition-transform ${\n panel1Collapsed\n ? isHorizontal ? 'rotate-180' : '-rotate-90'\n : isHorizontal ? 'rotate-0' : 'rotate-90'\n }`}\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M15 19l-7-7 7-7\" />\n </svg>\n </button>\n )}\n {showEnd && (\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation()\n toggleCollapse(index + 1)\n }}\n className=\"p-0.5 rounded hover:bg-base-content/20 transition-colors\"\n aria-label={panel2Collapsed ? 'Expand panel' : 'Collapse panel'}\n >\n <svg\n className={`w-3 h-3 text-base-content/50 hover:text-base-content transition-transform ${\n panel2Collapsed\n ? isHorizontal ? 'rotate-0' : 'rotate-90'\n : isHorizontal ? 'rotate-180' : '-rotate-90'\n }`}\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M15 19l-7-7 7-7\" />\n </svg>\n </button>\n )}\n </div>\n )\n })()}\n </div>\n )}\n </React.Fragment>\n )\n })}\n </div>\n )\n}\n\nSplitter.Panel = Panel\n"],"names":["Panel","children","Splitter","direction","sizes","defaultSizes","onSizesChange","gutterSize","minSize","className","containerRef","useRef","panelsRef","draggingRef","panels","React","child","panelCount","collapsedStates","setCollapsedStates","useState","panel","sizesBeforeCollapseRef","getInitialSizes","useCallback","panelDefaultSizes","hasAnyPanelSize","definedTotal","sum","s","undefinedCount","remainingSize","sizePerUndefined","equalSize","internalSizes","setInternalSizes","getControlledSizes","panelSizes","i","currentSizes","useEffect","newCollapsedStates","p","updateSizes","newSizes","toggleCollapse","panelIndex","newCollapsed","collapsedSize","sizeToRedistribute","otherPanels","_","sizePerPanel","previousSize","totalOtherSize","proportion","handleMouseDown","index","e","panel1Props","panel2Props","startPos","handleMouseMove","moveEvent","dragIndex","dragStartPos","startSizes","containerRect","containerSize","currentPos","totalGutterSize","availableSize","deltaPercent","minSize1","minSize2","minPercent1","minPercent2","newSize1","newSize2","maxSize1","maxSize2","maxPercent1","maxPercent2","handleMouseUp","handleKeyDown","step","delta","minPercent","isHorizontal","getCollapseConfig","panel1","panel2","panel1Collapsible","panel2Collapsible","panel1Collapsed","panel2Collapsed","jsx","panelProps","isLast","isCollapsed","canResize","jsxs","el","showStart","showEnd"],"mappings":"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"}
|