dishui 0.0.81 → 0.0.83
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.
- package/dist/components/Accordion/index.js +6 -6
- package/dist/components/Accordion/index.js.map +1 -1
- package/dist/components/Button/index.d.ts +1 -0
- package/dist/components/Button/index.js.map +1 -1
- package/dist/components/ButtonMenu/index.d.ts +28 -0
- package/dist/components/ButtonMenu/index.js +197 -0
- package/dist/components/ButtonMenu/index.js.map +1 -0
- package/dist/components/Card/index.d.ts +7 -4
- package/dist/components/Card/index.js +98 -65
- package/dist/components/Card/index.js.map +1 -1
- package/dist/components/Demo/index.d.ts +5 -0
- package/dist/components/Demo/index.js +131 -56
- package/dist/components/Demo/index.js.map +1 -1
- package/dist/components/Demo/source.d.ts +9 -0
- package/dist/components/Demo/source.js +32 -0
- package/dist/components/Demo/source.js.map +1 -0
- package/dist/components/EmptyState/index.js +4 -4
- package/dist/components/EmptyState/index.js.map +1 -1
- package/dist/components/Field/index.d.ts +8 -0
- package/dist/components/Field/index.js +43 -0
- package/dist/components/Field/index.js.map +1 -0
- package/dist/components/LayoutSuite/DashboardSuite.d.ts +35 -0
- package/dist/components/LayoutSuite/DashboardSuite.js +61 -0
- package/dist/components/LayoutSuite/DashboardSuite.js.map +1 -0
- package/dist/components/LayoutSuite/index.d.ts +56 -0
- package/dist/components/LayoutSuite/index.js +101 -0
- package/dist/components/LayoutSuite/index.js.map +1 -0
- package/dist/components/List/index.js +5 -5
- package/dist/components/List/index.js.map +1 -1
- package/dist/components/Modal/focusScope.d.ts +1 -0
- package/dist/components/Modal/focusScope.js +81 -0
- package/dist/components/Modal/focusScope.js.map +1 -0
- package/dist/components/Modal/index.d.ts +4 -1
- package/dist/components/Modal/index.js +53 -48
- package/dist/components/Modal/index.js.map +1 -1
- package/dist/components/Page/Float.d.ts +14 -0
- package/dist/components/Page/Float2.js +154 -0
- package/dist/components/Page/Float2.js.map +1 -0
- package/dist/components/Page/index.d.ts +18 -5
- package/dist/components/Page/index.js +103 -34
- package/dist/components/Page/index.js.map +1 -1
- package/dist/components/Page/resize.d.ts +28 -0
- package/dist/components/Page/resize2.js +95 -0
- package/dist/components/Page/resize2.js.map +1 -0
- package/dist/components/PageHeader/index.d.ts +10 -3
- package/dist/components/PageHeader/index.js +46 -25
- package/dist/components/PageHeader/index.js.map +1 -1
- package/dist/components/PagePanel/index.d.ts +29 -0
- package/dist/components/PagePanel/index.js +99 -0
- package/dist/components/PagePanel/index.js.map +1 -0
- package/dist/components/Resizable/ResizeGrip.d.ts +5 -0
- package/dist/components/Resizable/ResizeGrip.js +14 -0
- package/dist/components/Resizable/ResizeGrip.js.map +1 -0
- package/dist/components/Resizable/index.js +57 -59
- package/dist/components/Resizable/index.js.map +1 -1
- package/dist/components/Resizable/useResize.d.ts +6 -0
- package/dist/components/Resizable/useResize.js +29 -28
- package/dist/components/Resizable/useResize.js.map +1 -1
- package/dist/components/SidebarToggleButton/index.d.ts +5 -3
- package/dist/components/SidebarToggleButton/index.js +24 -21
- package/dist/components/SidebarToggleButton/index.js.map +1 -1
- package/dist/components/Table/index.d.ts +10 -12
- package/dist/components/Table/index.js +25 -20
- package/dist/components/Table/index.js.map +1 -1
- package/dist/components/Text/index.d.ts +1 -1
- package/dist/components/Text/index.js +11 -10
- package/dist/components/Text/index.js.map +1 -1
- package/dist/components/Textarea/index.d.ts +14 -0
- package/dist/components/Textarea/index.js +44 -0
- package/dist/components/Textarea/index.js.map +1 -0
- package/dist/components/Tree/Tree.d.ts +2 -0
- package/dist/components/Tree/Tree.js +49 -40
- package/dist/components/Tree/Tree.js.map +1 -1
- package/dist/dishui.css +1 -1
- package/dist/index-nostyled.d.ts +9 -0
- package/dist/index.d.ts +11 -2
- package/dist/index.js +119 -113
- package/dist/layouts/Sidebar.d.ts +12 -1
- package/dist/layouts/Sidebar.js +121 -97
- package/dist/layouts/Sidebar.js.map +1 -1
- package/dist/lite.d.ts +10 -2
- package/dist/lite.js +17 -12
- package/dist/styles/themeStyles.js +6 -6
- package/dist/styles/themeStyles.js.map +1 -1
- package/dist/utils/menu.js +14 -16
- package/dist/utils/menu.js.map +1 -1
- package/package.json +3 -1
|
@@ -1,32 +1,53 @@
|
|
|
1
|
-
import "
|
|
2
|
-
|
|
1
|
+
import e from "../PagePanel/index.js";
|
|
2
|
+
/* empty css */
|
|
3
|
+
import t from "react";
|
|
4
|
+
import { Fragment as n, jsx as r, jsxs as i } from "react/jsx-runtime";
|
|
3
5
|
//#region src/components/PageHeader/index.tsx
|
|
4
|
-
var
|
|
5
|
-
let
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
className: `shrink-0 text-primary ${l}`,
|
|
14
|
-
children: i
|
|
15
|
-
}), /* @__PURE__ */ e("h1", {
|
|
16
|
-
className: `truncate font-bold text-base-content ${c}`,
|
|
17
|
-
children: n
|
|
18
|
-
})]
|
|
19
|
-
}), r && /* @__PURE__ */ e("p", {
|
|
20
|
-
className: "mt-0.5 text-xs text-base-content/60",
|
|
21
|
-
children: r
|
|
22
|
-
})]
|
|
23
|
-
}), a && /* @__PURE__ */ e("div", {
|
|
24
|
-
className: "flex shrink-0 items-center gap-2",
|
|
25
|
-
children: a
|
|
6
|
+
var a = (e) => t.Children.toArray(e).some((e) => t.isValidElement(e) && e.type === t.Fragment ? a(e.props.children) : typeof e != "string" || e.trim().length > 0), o = ({ open: t, mode: o, animated: s, duration: c, autoHide: l, title: u, description: d, icon: f, actions: p, left: m, center: h, right: g, compact: _ = !0, className: v = "" }) => {
|
|
7
|
+
let y = _ ? "text-lg" : "text-xl", b = _ ? "[&>svg]:h-5 [&>svg]:w-5" : "[&>svg]:h-6 [&>svg]:w-6", x = _ ? "mb-4" : "mb-6", S = /* @__PURE__ */ i(n, { children: [(a(f) || a(u)) && /* @__PURE__ */ i("div", {
|
|
8
|
+
className: "flex min-w-0 items-center gap-2.5",
|
|
9
|
+
children: [a(f) && /* @__PURE__ */ r("span", {
|
|
10
|
+
className: `shrink-0 text-base-content/70 ${b}`,
|
|
11
|
+
children: f
|
|
12
|
+
}), a(u) && /* @__PURE__ */ r("h1", {
|
|
13
|
+
className: `min-w-0 truncate font-semibold text-base-content ${y}`,
|
|
14
|
+
children: u
|
|
26
15
|
})]
|
|
16
|
+
}), a(d) && /* @__PURE__ */ r("p", {
|
|
17
|
+
className: "mt-1 text-body-sm leading-5 text-base-content/70",
|
|
18
|
+
children: d
|
|
19
|
+
})] }), C = m === void 0 ? S : m, w = g === void 0 ? p : g;
|
|
20
|
+
return /* @__PURE__ */ r(e, {
|
|
21
|
+
edge: "header",
|
|
22
|
+
autoHide: l,
|
|
23
|
+
open: t,
|
|
24
|
+
mode: o,
|
|
25
|
+
animated: s,
|
|
26
|
+
duration: c,
|
|
27
|
+
children: /* @__PURE__ */ r("header", {
|
|
28
|
+
className: `dishui-page-header text-body ${x} ${v}`.trim(),
|
|
29
|
+
children: /* @__PURE__ */ i("div", {
|
|
30
|
+
className: "dishui-page-header-layout",
|
|
31
|
+
"data-centered": a(h) || void 0,
|
|
32
|
+
children: [
|
|
33
|
+
a(C) && /* @__PURE__ */ r("div", {
|
|
34
|
+
className: "dishui-page-header-left",
|
|
35
|
+
children: C
|
|
36
|
+
}),
|
|
37
|
+
a(h) && /* @__PURE__ */ r("div", {
|
|
38
|
+
className: "dishui-page-header-center",
|
|
39
|
+
children: h
|
|
40
|
+
}),
|
|
41
|
+
a(w) && /* @__PURE__ */ r("div", {
|
|
42
|
+
className: "dishui-page-header-right",
|
|
43
|
+
children: w
|
|
44
|
+
})
|
|
45
|
+
]
|
|
46
|
+
})
|
|
47
|
+
})
|
|
27
48
|
});
|
|
28
49
|
};
|
|
29
50
|
//#endregion
|
|
30
|
-
export {
|
|
51
|
+
export { o as default };
|
|
31
52
|
|
|
32
53
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../../src/components/PageHeader/index.tsx"],"sourcesContent":["import React from 'react';\n\nexport type PageHeaderProps = {\n /** 页面标题 */\n title
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../../src/components/PageHeader/index.tsx"],"sourcesContent":["import React from 'react';\nimport PagePanel, { type PagePanelProps, type PageAutoHideProps } from '../PagePanel';\nimport './style.css';\n\nexport type PageHeaderProps = PagePanelProps & PageAutoHideProps & {\n /** 页面标题 */\n title?: React.ReactNode;\n /** 覆盖默认图标、标题和描述;null 清空,undefined 使用旧 API。 */\n left?: React.ReactNode;\n /** 相对整个 header 水平居中的内容。 */\n center?: React.ReactNode;\n /** 覆盖 actions;null 清空,undefined 使用 actions。 */\n right?: React.ReactNode;\n /** 标题下方的描述文字 */\n description?: React.ReactNode;\n /** 标题左侧的图标(通常为 lucide 图标) */\n icon?: React.ReactNode;\n /** 右侧操作区(按钮组等) */\n actions?: React.ReactNode;\n /** 紧凑模式:标题与间距更小 */\n compact?: boolean;\n className?: string;\n};\n\nconst hasContent = (node: React.ReactNode): boolean =>\n React.Children.toArray(node).some(child =>\n React.isValidElement<{ children?: React.ReactNode }>(child) && child.type === React.Fragment\n ? hasContent(child.props.children)\n : typeof child !== 'string' || child.trim().length > 0,\n );\n\n/**\n * 页面头部:统一管理后台等页面的标题 / 描述 / 操作区排版。\n * 相比页面内手写的 `text-3xl` 标题,默认字号更精致(text-lg)。\n */\nconst PageHeader = ({\n open, mode, animated, duration, autoHide,\n title,\n description,\n icon,\n actions,\n left,\n center,\n right,\n compact = true,\n className = '',\n}: PageHeaderProps) => {\n const titleSize = compact ? 'text-lg' : 'text-xl';\n const iconSize = compact ? '[&>svg]:h-5 [&>svg]:w-5' : '[&>svg]:h-6 [&>svg]:w-6';\n const spacing = compact ? 'mb-4' : 'mb-6';\n\n\n const defaultLeft = (\n <>\n {(hasContent(icon) || hasContent(title)) && (\n <div className=\"flex min-w-0 items-center gap-2.5\">\n {hasContent(icon) && (\n <span className={`shrink-0 text-base-content/70 ${iconSize}`}>{icon}</span>\n )}\n {hasContent(title) && (\n <h1 className={`min-w-0 truncate font-semibold text-base-content ${titleSize}`}>{title}</h1>\n )}\n </div>\n )}\n {hasContent(description) && (\n <p className=\"mt-1 text-body-sm leading-5 text-base-content/70\">{description}</p>\n )}\n </>\n );\n const leftContent = left !== undefined ? left : defaultLeft;\n const rightContent = right !== undefined ? right : actions;\n\n return (\n <PagePanel edge=\"header\" autoHide={autoHide} open={open} mode={mode} animated={animated} duration={duration}>\n <header className={`dishui-page-header text-body ${spacing} ${className}`.trim()}>\n <div className=\"dishui-page-header-layout\" data-centered={hasContent(center) || undefined}>\n {hasContent(leftContent) && <div className=\"dishui-page-header-left\">{leftContent}</div>}\n {hasContent(center) && <div className=\"dishui-page-header-center\">{center}</div>}\n {hasContent(rightContent) && <div className=\"dishui-page-header-right\">{rightContent}</div>}\n </div>\n </header>\n </PagePanel>\n );\n};\n\nexport default PageHeader;\n"],"mappings":";;;;;AAwBA,IAAM,KAAc,MAChB,EAAM,SAAS,QAAQ,CAAI,CAAC,CAAC,MAAK,MAC9B,EAAM,eAA+C,CAAK,KAAK,EAAM,SAAS,EAAM,WAC9E,EAAW,EAAM,MAAM,QAAQ,IAC/B,OAAO,KAAU,YAAY,EAAM,KAAK,CAAC,CAAC,SAAS,CAC7D,GAME,KAAc,EAChB,SAAM,SAAM,aAAU,aAAU,aAChC,UACA,gBACA,SACA,YACA,SACA,WACA,UACA,aAAU,IACV,eAAY,SACO;CACnB,IAAM,IAAY,IAAU,YAAY,WAClC,IAAW,IAAU,4BAA4B,2BACjD,IAAU,IAAU,SAAS,QAG7B,IACF,kBAAA,GAAA,EAAA,UAAA,EACM,EAAW,CAAI,KAAK,EAAW,CAAK,MAClC,kBAAC,OAAD;EAAK,WAAU;EAAf,UAAA,CACK,EAAW,CAAI,KACZ,kBAAC,QAAD;GAAM,WAAW,iCAAiC;GAAa,UAAA;EAAW,CAAA,GAE7E,EAAW,CAAK,KACb,kBAAC,MAAD;GAAI,WAAW,oDAAoD;GAAc,UAAA;EAAU,CAAA,CAE9F;CAER,CAAA,GAAA,EAAW,CAAW,KACnB,kBAAC,KAAD;EAAG,WAAU;EAAoD,UAAA;CAAe,CAAA,CAEtF,EAAA,CAAA,GAEA,IAAc,MAAS,KAAA,IAAmB,IAAP,GACnC,IAAe,MAAU,KAAA,IAAoB,IAAR;CAE3C,OACI,kBAAC,GAAD;EAAW,MAAK;EAAmB;EAAgB;EAAY;EAAgB;EAAoB;EAC/F,UAAA,kBAAC,UAAD;GAAQ,WAAW,gCAAgC,EAAQ,GAAG,IAAY,KAAK;GAC3E,UAAA,kBAAC,OAAD;IAAK,WAAU;IAA4B,iBAAe,EAAW,CAAM,KAAK,KAAA;IAAhF,UAAA;KACK,EAAW,CAAW,KAAK,kBAAC,OAAD;MAAK,WAAU;MAA2B,UAAA;KAAiB,CAAA;KACtF,EAAW,CAAM,KAAK,kBAAC,OAAD;MAAK,WAAU;MAA6B,UAAA;KAAY,CAAA;KAC9E,EAAW,CAAY,KAAK,kBAAC,OAAD;MAAK,WAAU;MAA4B,UAAA;KAAkB,CAAA;IACzF;;EACD,CAAA;CACD,CAAA;AAEnB"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export type PagePanelProps = {
|
|
3
|
+
/** 是否展开,默认 true。折叠时保留内容挂载,但禁用交互。 */
|
|
4
|
+
open?: boolean;
|
|
5
|
+
/** push 占用布局空间;overlay 覆盖 Page / Body,默认 push。 */
|
|
6
|
+
mode?: 'push' | 'overlay';
|
|
7
|
+
/** 是否启用动画,默认 true;遵循 prefers-reduced-motion。 */
|
|
8
|
+
animated?: boolean;
|
|
9
|
+
/** 动画时长(毫秒),默认 200。 */
|
|
10
|
+
duration?: number;
|
|
11
|
+
};
|
|
12
|
+
export type PageAutoHideProps = {
|
|
13
|
+
/** 正文下滚隐藏、上滚或到顶显示。默认 false;阈值默认 24px。显式 open 优先。 */
|
|
14
|
+
autoHide?: boolean | {
|
|
15
|
+
threshold?: number;
|
|
16
|
+
/** 达到下滚阈值后等待的毫秒数,默认 0;与动画 duration 独立。 */
|
|
17
|
+
delay?: number;
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
type PanelProps = PagePanelProps & PageAutoHideProps & {
|
|
21
|
+
edge: 'header' | 'footer' | 'left' | 'right';
|
|
22
|
+
width?: number | string;
|
|
23
|
+
hideOnMobile?: boolean;
|
|
24
|
+
children: React.ReactNode;
|
|
25
|
+
/** Internal resize control, outside the clipping/scrolling content. */
|
|
26
|
+
resizeHandle?: React.ReactNode;
|
|
27
|
+
};
|
|
28
|
+
declare const PagePanel: (props: PanelProps) => React.JSX.Element;
|
|
29
|
+
export default PagePanel;
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/* empty css */
|
|
2
|
+
import { useEffect as e, useRef as t, useState as n } from "react";
|
|
3
|
+
import { jsx as r, jsxs as i } from "react/jsx-runtime";
|
|
4
|
+
//#region src/components/PagePanel/index.tsx
|
|
5
|
+
var a = ({ open: e = !0, mode: t = "push", animated: n = !0, duration: a = 200, edge: o, width: s, hideOnMobile: c = !1, children: l, resizeHandle: u }, d) => /* @__PURE__ */ i("div", {
|
|
6
|
+
ref: d,
|
|
7
|
+
className: "dishui-page-panel",
|
|
8
|
+
"data-edge": o,
|
|
9
|
+
"data-resizable": u ? !0 : void 0,
|
|
10
|
+
"data-mode": t,
|
|
11
|
+
"data-open": e,
|
|
12
|
+
"data-hide-mobile": c || void 0,
|
|
13
|
+
inert: !e,
|
|
14
|
+
"aria-hidden": !e || void 0,
|
|
15
|
+
style: {
|
|
16
|
+
"--dishui-panel-duration": `${n && Number.isFinite(a) ? Math.max(0, a) : 0}ms`,
|
|
17
|
+
"--dishui-panel-width": typeof s == "number" ? `${s}px` : s
|
|
18
|
+
},
|
|
19
|
+
children: [/* @__PURE__ */ r("div", {
|
|
20
|
+
className: "dishui-page-panel-clip",
|
|
21
|
+
children: l
|
|
22
|
+
}), u]
|
|
23
|
+
}), o = (r) => {
|
|
24
|
+
let i = t(null), [o, s] = n(!0), c = !!r.autoHide && r.open === void 0, l = typeof r.autoHide == "object" ? r.autoHide.threshold : void 0, u = typeof l == "number" && Number.isFinite(l) && l > 0 ? l : 24, d = typeof r.autoHide == "object" ? r.autoHide.delay : void 0, f = typeof d == "number" && Number.isFinite(d) && d >= 0 ? Math.min(d, 2147483647) : 0;
|
|
25
|
+
return e(() => {
|
|
26
|
+
if (!c) {
|
|
27
|
+
s(!0);
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
let e = i.current, t = e?.closest(".dishui-page");
|
|
31
|
+
if (!e || !t) return;
|
|
32
|
+
let n = e.ownerDocument, r = n.defaultView;
|
|
33
|
+
if (!r) return;
|
|
34
|
+
let a = Array.from(t.querySelectorAll(".dishui-page-main")).find((e) => e.closest(".dishui-page") === t);
|
|
35
|
+
if (!a) return;
|
|
36
|
+
let o = () => /auto|scroll|overlay/.test(r.getComputedStyle(a).overflowY), l = () => {
|
|
37
|
+
let e = o(), t = e ? a : n.scrollingElement;
|
|
38
|
+
return {
|
|
39
|
+
local: e,
|
|
40
|
+
top: Math.max(0, t.scrollTop),
|
|
41
|
+
max: Math.max(0, t.scrollHeight - t.clientHeight),
|
|
42
|
+
origin: e ? 0 : a.getBoundingClientRect().top + r.scrollY
|
|
43
|
+
};
|
|
44
|
+
}, d = l(), p = 0, m = 0, h, g = () => {
|
|
45
|
+
h !== void 0 && r.clearTimeout(h), h = void 0;
|
|
46
|
+
}, _ = () => {
|
|
47
|
+
let e = t.getBoundingClientRect();
|
|
48
|
+
return e.bottom > 0 && e.top < r.innerHeight && e.right > 0 && e.left < r.innerWidth;
|
|
49
|
+
}, v = () => {
|
|
50
|
+
if (h !== void 0) return;
|
|
51
|
+
let t = () => {
|
|
52
|
+
h = void 0, !e.contains(n.activeElement) && _() && l().top > 0 && s(!1);
|
|
53
|
+
};
|
|
54
|
+
f === 0 ? t() : h = r.setTimeout(t, f);
|
|
55
|
+
}, y = () => {
|
|
56
|
+
m = 0;
|
|
57
|
+
let i = l(), a = t.getBoundingClientRect(), o = Math.abs(i.max - d.max) + Math.abs(i.origin - d.origin), c = i.local !== d.local, f = i.top - d.top;
|
|
58
|
+
d = i;
|
|
59
|
+
let h = o > .5 && Math.abs(f) <= o + 1;
|
|
60
|
+
if (c || h || a.bottom <= 0 || a.top >= r.innerHeight || a.right <= 0 || a.left >= r.innerWidth) {
|
|
61
|
+
p = 0, (c || !_()) && g();
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
if (f) {
|
|
65
|
+
if (f < 0 && g(), i.top <= 0) {
|
|
66
|
+
g(), p = 0, s(!0);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
if (e.contains(n.activeElement)) {
|
|
70
|
+
g(), p = 0;
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
p = Math.sign(f) === Math.sign(p) ? p + f : f, Math.abs(p) >= u && (p < 0 ? s(!0) : v(), p = 0);
|
|
74
|
+
}
|
|
75
|
+
}, b = () => {
|
|
76
|
+
m ||= r.requestAnimationFrame(y);
|
|
77
|
+
}, x = (e) => {
|
|
78
|
+
(o() ? e.target === a : e.target === n || e.target === r) && b();
|
|
79
|
+
}, S = () => {
|
|
80
|
+
g(), p = 0, s(!0);
|
|
81
|
+
};
|
|
82
|
+
a.addEventListener("scroll", x, { passive: !0 }), r.addEventListener("scroll", x, { passive: !0 }), e.addEventListener("focusin", S);
|
|
83
|
+
let C = new ResizeObserver(b);
|
|
84
|
+
return C.observe(a), C.observe(t), C.observe(n.documentElement), () => {
|
|
85
|
+
a.removeEventListener("scroll", x), r.removeEventListener("scroll", x), e.removeEventListener("focusin", S), C.disconnect(), g(), r.cancelAnimationFrame(m);
|
|
86
|
+
};
|
|
87
|
+
}, [
|
|
88
|
+
c,
|
|
89
|
+
u,
|
|
90
|
+
f
|
|
91
|
+
]), a({
|
|
92
|
+
...r,
|
|
93
|
+
open: r.open ?? (!c || o)
|
|
94
|
+
}, i);
|
|
95
|
+
}, s = (e) => e.edge === "header" || e.edge === "footer" ? /* @__PURE__ */ r(o, { ...e }) : a(e);
|
|
96
|
+
//#endregion
|
|
97
|
+
export { s as default };
|
|
98
|
+
|
|
99
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../../src/components/PagePanel/index.tsx"],"sourcesContent":["import React, { useEffect, useRef, useState } from 'react';\nimport './style.css';\n\nexport type PagePanelProps = {\n /** 是否展开,默认 true。折叠时保留内容挂载,但禁用交互。 */\n open?: boolean;\n /** push 占用布局空间;overlay 覆盖 Page / Body,默认 push。 */\n mode?: 'push' | 'overlay';\n /** 是否启用动画,默认 true;遵循 prefers-reduced-motion。 */\n animated?: boolean;\n /** 动画时长(毫秒),默认 200。 */\n duration?: number;\n};\n\nexport type PageAutoHideProps = {\n /** 正文下滚隐藏、上滚或到顶显示。默认 false;阈值默认 24px。显式 open 优先。 */\n autoHide?: boolean | {\n threshold?: number;\n /** 达到下滚阈值后等待的毫秒数,默认 0;与动画 duration 独立。 */\n delay?: number;\n };\n};\n\ntype PanelProps = PagePanelProps & PageAutoHideProps & {\n edge: 'header' | 'footer' | 'left' | 'right';\n width?: number | string;\n hideOnMobile?: boolean;\n children: React.ReactNode;\n /** Internal resize control, outside the clipping/scrolling content. */\n resizeHandle?: React.ReactNode;\n};\n\n/** Layout-only shell: consumer classes and HTML attributes stay on the semantic content. */\nconst renderPanel = ({\n open = true,\n mode = 'push',\n animated = true,\n duration = 200,\n edge,\n width,\n hideOnMobile = false,\n children,\n resizeHandle,\n}: PanelProps, ref?: React.Ref<HTMLDivElement>) => (\n <div\n ref={ref}\n className=\"dishui-page-panel\"\n data-edge={edge}\n data-resizable={resizeHandle ? true : undefined}\n data-mode={mode}\n data-open={open}\n data-hide-mobile={hideOnMobile || undefined}\n inert={!open}\n aria-hidden={!open || undefined}\n style={{\n '--dishui-panel-duration': `${animated && Number.isFinite(duration) ? Math.max(0, duration) : 0}ms`,\n '--dishui-panel-width': typeof width === 'number' ? `${width}px` : width,\n } as React.CSSProperties}\n >\n <div className=\"dishui-page-panel-clip\">{children}</div>\n {resizeHandle}\n </div>\n);\n\nconst AutoHidePanel = (props: PanelProps) => {\n const ref = useRef<HTMLDivElement>(null);\n const [open, setOpen] = useState(true);\n const enabled = Boolean(props.autoHide) && props.open === undefined;\n const value = typeof props.autoHide === 'object' ? props.autoHide.threshold : undefined;\n const threshold = typeof value === 'number' && Number.isFinite(value) && value > 0 ? value : 24;\n\n const requestedDelay = typeof props.autoHide === 'object' ? props.autoHide.delay : undefined;\n const delay = typeof requestedDelay === 'number' && Number.isFinite(requestedDelay) && requestedDelay >= 0\n ? Math.min(requestedDelay, 2147483647) : 0;\n\n useEffect(() => {\n if (!enabled) {\n setOpen(true);\n return;\n }\n const panel = ref.current;\n const page = panel?.closest<HTMLElement>('.dishui-page');\n if (!panel || !page) return;\n const doc = panel.ownerDocument;\n const win = doc.defaultView;\n if (!win) return;\n const main = Array.from(page.querySelectorAll<HTMLElement>('.dishui-page-main'))\n .find(node => node.closest('.dishui-page') === page);\n if (!main) return;\n const internal = () => /auto|scroll|overlay/.test(win.getComputedStyle(main).overflowY);\n const measure = () => {\n const local = internal();\n const scroller = local ? main : doc.scrollingElement!;\n return {\n local,\n top: Math.max(0, scroller.scrollTop),\n max: Math.max(0, scroller.scrollHeight - scroller.clientHeight),\n origin: local ? 0 : main.getBoundingClientRect().top + win.scrollY,\n };\n };\n let previous = measure();\n let travel = 0;\n let frame = 0;\n let hideTimer: number | undefined;\n const cancelHide = () => {\n if (hideTimer !== undefined) win.clearTimeout(hideTimer);\n hideTimer = undefined;\n };\n const visible = () => {\n const rect = page.getBoundingClientRect();\n return rect.bottom > 0 && rect.top < win.innerHeight && rect.right > 0 && rect.left < win.innerWidth;\n };\n const hide = () => {\n if (hideTimer !== undefined) return;\n const commit = () => {\n hideTimer = undefined;\n if (!panel.contains(doc.activeElement) && visible() && measure().top > 0) setOpen(false);\n };\n if (delay === 0) commit();\n else hideTimer = win.setTimeout(commit, delay);\n };\n const sample = () => {\n frame = 0;\n const next = measure();\n const rect = page.getBoundingClientRect();\n // Grid collapse, scroll anchoring and bottom clamping are layout, not intent.\n const layoutMovement = Math.abs(next.max - previous.max) + Math.abs(next.origin - previous.origin);\n const sourceChanged = next.local !== previous.local;\n const delta = next.top - previous.top;\n previous = next;\n // A larger movement cannot be explained by anchoring/clamping alone;\n // keep responding to deliberate scrolling during an animation.\n const layoutOnly = layoutMovement > 0.5 && Math.abs(delta) <= layoutMovement + 1;\n if (sourceChanged || layoutOnly || rect.bottom <= 0 || rect.top >= win.innerHeight\n || rect.right <= 0 || rect.left >= win.innerWidth) {\n travel = 0;\n if (sourceChanged || !visible()) cancelHide();\n return;\n }\n if (!delta) return;\n if (delta < 0) cancelHide();\n if (next.top <= 0) {\n cancelHide();\n travel = 0;\n setOpen(true);\n return;\n }\n if (panel.contains(doc.activeElement)) {\n cancelHide();\n travel = 0;\n return;\n }\n travel = Math.sign(delta) === Math.sign(travel) ? travel + delta : delta;\n if (Math.abs(travel) >= threshold) {\n if (travel < 0) setOpen(true);\n else hide();\n travel = 0;\n }\n };\n const schedule = () => { if (!frame) frame = win.requestAnimationFrame(sample); };\n const onScroll = (event: Event) => {\n if (internal() ? event.target === main : event.target === doc || event.target === win) schedule();\n };\n const onFocus = () => { cancelHide(); travel = 0; setOpen(true); };\n main.addEventListener('scroll', onScroll, { passive: true });\n win.addEventListener('scroll', onScroll, { passive: true });\n panel.addEventListener('focusin', onFocus);\n const observer = new ResizeObserver(schedule);\n observer.observe(main);\n observer.observe(page);\n observer.observe(doc.documentElement);\n return () => {\n main.removeEventListener('scroll', onScroll);\n win.removeEventListener('scroll', onScroll);\n panel.removeEventListener('focusin', onFocus);\n observer.disconnect();\n cancelHide();\n win.cancelAnimationFrame(frame);\n };\n }, [enabled, threshold, delay]);\n\n return renderPanel({ ...props, open: props.open ?? (enabled ? open : true) }, ref);\n};\n\nconst PagePanel = (props: PanelProps) => props.edge === 'header' || props.edge === 'footer'\n ? <AutoHidePanel {...props} />\n : renderPanel(props);\n\nexport default PagePanel;\n"],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/* empty css */
|
|
2
|
+
import "react";
|
|
3
|
+
import { jsx as e } from "react/jsx-runtime";
|
|
4
|
+
//#region src/components/Resizable/ResizeGrip.tsx
|
|
5
|
+
function t({ variant: t = "pill" }) {
|
|
6
|
+
return t === "pill" ? /* @__PURE__ */ e("span", {
|
|
7
|
+
className: "dishui-resizable-grip",
|
|
8
|
+
"aria-hidden": "true"
|
|
9
|
+
}) : null;
|
|
10
|
+
}
|
|
11
|
+
//#endregion
|
|
12
|
+
export { t as ResizeGrip };
|
|
13
|
+
|
|
14
|
+
//# sourceMappingURL=ResizeGrip.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ResizeGrip.js","names":[],"sources":["../../../src/components/Resizable/ResizeGrip.tsx"],"sourcesContent":["import React from 'react';\nimport './ResizeHandle.css';\n\n/** Visual-only primitive; consumers own layout, semantics and interaction. */\nexport function ResizeGrip({ variant = 'pill' }: { variant?: 'pill' | 'line' }) {\n return variant === 'pill' ? <span className=\"dishui-resizable-grip\" aria-hidden=\"true\" /> : null;\n}\n"],"mappings":";;;;AAIA,SAAgB,EAAW,EAAE,aAAU,UAAyC;CAC9E,OAAO,MAAY,SAAS,kBAAC,QAAD;EAAM,WAAU;EAAwB,eAAY;CAAQ,CAAA,IAAI;AAC9F"}
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import { useResize as e } from "./useResize.js";
|
|
2
|
+
import { ResizeGrip as t } from "./ResizeGrip.js";
|
|
2
3
|
/* empty css */
|
|
3
|
-
import { Children as
|
|
4
|
-
import { jsx as
|
|
4
|
+
import { Children as n, createContext as r, isValidElement as i, useContext as a, useId as o, useLayoutEffect as s, useRef as c, useState as l } from "react";
|
|
5
|
+
import { jsx as u } from "react/jsx-runtime";
|
|
5
6
|
//#region src/components/Resizable/index.tsx
|
|
6
|
-
var
|
|
7
|
-
function
|
|
8
|
-
let o =
|
|
7
|
+
var d = r(null), f = r(0);
|
|
8
|
+
function p({ minSize: e, maxSize: t, className: n = "", style: r, ...i }) {
|
|
9
|
+
let o = a(d), s = a(f);
|
|
9
10
|
if (!o) throw Error("Resizable.Panel must be inside Resizable");
|
|
10
|
-
return /* @__PURE__ */
|
|
11
|
-
...
|
|
11
|
+
return /* @__PURE__ */ u("div", {
|
|
12
|
+
...i,
|
|
12
13
|
id: o.ids[s],
|
|
13
14
|
className: `dishui-resizable-panel ${n}`,
|
|
14
15
|
style: {
|
|
@@ -17,59 +18,56 @@ function f({ minSize: e, maxSize: t, className: n = "", style: r, ...a }) {
|
|
|
17
18
|
}
|
|
18
19
|
});
|
|
19
20
|
}
|
|
20
|
-
function
|
|
21
|
-
let
|
|
22
|
-
if (!
|
|
23
|
-
let
|
|
24
|
-
orientation:
|
|
25
|
-
value:
|
|
26
|
-
min:
|
|
27
|
-
max:
|
|
28
|
-
disabled:
|
|
29
|
-
step:
|
|
21
|
+
function m({ variant: n = "pill", disabled: r = !1, step: i = 1, className: o = "", onPointerDown: s, onKeyDown: c, onClickCapture: l, children: p, ...m }) {
|
|
22
|
+
let h = a(d), g = a(f);
|
|
23
|
+
if (!h) throw Error("Resizable.Handle must be inside Resizable");
|
|
24
|
+
let _ = h.sizes[g] + h.sizes[g + 1], v = Math.max(h.bounds[g].min, _ - h.bounds[g + 1].max), y = Math.min(h.bounds[g].max, _ - h.bounds[g + 1].min), b = r || h.disabled || v >= y, x = e({
|
|
25
|
+
orientation: h.orientation,
|
|
26
|
+
value: h.sizes[g],
|
|
27
|
+
min: v,
|
|
28
|
+
max: y,
|
|
29
|
+
disabled: b,
|
|
30
|
+
step: i,
|
|
30
31
|
getScale: () => {
|
|
31
|
-
let e =
|
|
32
|
+
let e = h.root.current;
|
|
32
33
|
if (!e) return 0;
|
|
33
|
-
let t =
|
|
34
|
+
let t = h.orientation === "horizontal" ? "width" : "height", n = Array.from(e.children).filter((e) => e.classList.contains("dishui-resizable-panel")).reduce((e, n) => e + n.getBoundingClientRect()[t], 0), r = h.orientation === "horizontal" && getComputedStyle(e).direction === "rtl";
|
|
34
35
|
return n > 0 ? (r ? -100 : 100) / n : 0;
|
|
35
36
|
},
|
|
36
|
-
onChange: (e) =>
|
|
37
|
-
onCommit: (e) =>
|
|
37
|
+
onChange: (e) => h.change(g, e),
|
|
38
|
+
onCommit: (e) => h.change(g, e, !0)
|
|
38
39
|
});
|
|
39
|
-
return /* @__PURE__ */
|
|
40
|
-
...
|
|
40
|
+
return /* @__PURE__ */ u("div", {
|
|
41
|
+
...m,
|
|
41
42
|
role: "separator",
|
|
42
|
-
tabIndex:
|
|
43
|
-
"aria-label":
|
|
44
|
-
"aria-orientation":
|
|
45
|
-
"aria-controls":
|
|
46
|
-
"aria-valuemin":
|
|
47
|
-
"aria-valuemax":
|
|
48
|
-
"aria-valuenow":
|
|
49
|
-
"aria-valuetext": `${Number(
|
|
50
|
-
"aria-disabled":
|
|
51
|
-
"data-orientation":
|
|
52
|
-
"data-variant":
|
|
53
|
-
"data-dragging":
|
|
54
|
-
className: `dishui-resizable-handle ${
|
|
43
|
+
tabIndex: b ? -1 : 0,
|
|
44
|
+
"aria-label": m["aria-label"] ?? "Resize panels",
|
|
45
|
+
"aria-orientation": h.orientation === "horizontal" ? "vertical" : "horizontal",
|
|
46
|
+
"aria-controls": h.ids[g],
|
|
47
|
+
"aria-valuemin": v,
|
|
48
|
+
"aria-valuemax": y,
|
|
49
|
+
"aria-valuenow": h.sizes[g],
|
|
50
|
+
"aria-valuetext": `${Number(h.sizes[g].toFixed(2))}%`,
|
|
51
|
+
"aria-disabled": b,
|
|
52
|
+
"data-orientation": h.orientation,
|
|
53
|
+
"data-variant": n,
|
|
54
|
+
"data-dragging": x.dragging || void 0,
|
|
55
|
+
className: `dishui-resize-handle dishui-resizable-handle ${o}`,
|
|
55
56
|
onPointerDown: (e) => {
|
|
56
|
-
|
|
57
|
+
s?.(e), e.defaultPrevented || x.onPointerDown(e);
|
|
57
58
|
},
|
|
58
59
|
onKeyDown: (e) => {
|
|
59
|
-
|
|
60
|
+
c?.(e), e.defaultPrevented || x.onKeyDown(e);
|
|
60
61
|
},
|
|
61
62
|
onClickCapture: (e) => {
|
|
62
|
-
|
|
63
|
+
x.onClickCapture(e), e.defaultPrevented || l?.(e);
|
|
63
64
|
},
|
|
64
|
-
children:
|
|
65
|
-
className: "dishui-resizable-grip",
|
|
66
|
-
"aria-hidden": "true"
|
|
67
|
-
}) : null)
|
|
65
|
+
children: p ?? /* @__PURE__ */ u(t, { variant: n })
|
|
68
66
|
});
|
|
69
67
|
}
|
|
70
|
-
function
|
|
71
|
-
let x =
|
|
72
|
-
if (!C.length || C.some((e, t) => !
|
|
68
|
+
function h({ orientation: e = "horizontal", sizes: t, defaultSizes: r, onSizesChange: a, onSizesCommit: h, disabled: g = !1, children: _, className: v = "", style: y, ...b }) {
|
|
69
|
+
let x = c(null), S = o(), C = n.toArray(_);
|
|
70
|
+
if (!C.length || C.some((e, t) => !i(e) || e.type !== (t % 2 == 0 ? p : m)) || C.length % 2 == 0) throw Error("Resizable requires alternating Panel / Handle children, starting and ending with Panel. Nest groups inside a Panel.");
|
|
73
71
|
let w = C.filter((e, t) => t % 2 == 0), T = w.map((e) => ({
|
|
74
72
|
min: e.props.minSize ?? 0,
|
|
75
73
|
max: e.props.maxSize ?? 100
|
|
@@ -83,19 +81,19 @@ function m({ orientation: e = "horizontal", sizes: n, defaultSizes: i, onSizesCh
|
|
|
83
81
|
t[e] += r, n -= r;
|
|
84
82
|
}
|
|
85
83
|
return t;
|
|
86
|
-
}, [D, O] =
|
|
87
|
-
|
|
84
|
+
}, [D, O] = l(() => E(r)), k = E(t ?? (D.length === w.length ? D : void 0)), A = c(k);
|
|
85
|
+
s(() => {
|
|
88
86
|
A.current = k;
|
|
89
87
|
});
|
|
90
|
-
let j = (e,
|
|
91
|
-
let i = [...A.current],
|
|
92
|
-
if (i[e] =
|
|
88
|
+
let j = (e, n, r = !1) => {
|
|
89
|
+
let i = [...A.current], o = i[e] + i[e + 1];
|
|
90
|
+
if (i[e] = n, i[e + 1] = o - n, r) {
|
|
93
91
|
h?.(i);
|
|
94
92
|
return;
|
|
95
93
|
}
|
|
96
|
-
|
|
94
|
+
t || (A.current = i, O(i)), a?.(i);
|
|
97
95
|
}, M = w.map((e, t) => e.props.id ?? `${S}-panel-${t}`);
|
|
98
|
-
return /* @__PURE__ */
|
|
96
|
+
return /* @__PURE__ */ u(d.Provider, {
|
|
99
97
|
value: {
|
|
100
98
|
orientation: e,
|
|
101
99
|
disabled: g,
|
|
@@ -105,24 +103,24 @@ function m({ orientation: e = "horizontal", sizes: n, defaultSizes: i, onSizesCh
|
|
|
105
103
|
root: x,
|
|
106
104
|
change: j
|
|
107
105
|
},
|
|
108
|
-
children: /* @__PURE__ */
|
|
106
|
+
children: /* @__PURE__ */ u("div", {
|
|
109
107
|
...b,
|
|
110
108
|
ref: x,
|
|
111
109
|
className: `dishui-resizable ${v}`,
|
|
112
110
|
"data-orientation": e,
|
|
113
111
|
style: y,
|
|
114
|
-
children: C.map((e, t) => /* @__PURE__ */
|
|
112
|
+
children: C.map((e, t) => /* @__PURE__ */ u(f.Provider, {
|
|
115
113
|
value: Math.floor(t / 2),
|
|
116
114
|
children: e
|
|
117
115
|
}, e.key ?? t))
|
|
118
116
|
})
|
|
119
117
|
});
|
|
120
118
|
}
|
|
121
|
-
var
|
|
122
|
-
Panel:
|
|
123
|
-
Handle:
|
|
119
|
+
var g = Object.assign(h, {
|
|
120
|
+
Panel: p,
|
|
121
|
+
Handle: m
|
|
124
122
|
});
|
|
125
123
|
//#endregion
|
|
126
|
-
export {
|
|
124
|
+
export { g as Resizable, g as default, m as ResizableHandle, p as ResizablePanel, e as useResize };
|
|
127
125
|
|
|
128
126
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../../src/components/Resizable/index.tsx"],"sourcesContent":["import React, { Children, createContext, isValidElement, useContext, useId, useLayoutEffect, useRef, useState } from 'react';\nimport { useResize } from './useResize';\nimport './Resizable.css';\nexport { useResize } from './useResize';\nexport type { UseResizeOptions } from './useResize';\n\nexport interface ResizablePanelProps extends React.HTMLAttributes<HTMLDivElement> {\n minSize?: number;\n maxSize?: number;\n}\nexport interface ResizableHandleProps extends React.HTMLAttributes<HTMLDivElement> {\n variant?: 'line' | 'pill';\n disabled?: boolean;\n step?: number;\n}\nexport interface ResizableProps extends React.HTMLAttributes<HTMLDivElement> {\n orientation?: 'horizontal' | 'vertical';\n sizes?: number[];\n defaultSizes?: number[];\n onSizesChange?: (sizes: number[]) => void;\n onSizesCommit?: (sizes: number[]) => void;\n disabled?: boolean;\n}\ninterface GroupContext {\n orientation: 'horizontal' | 'vertical';\n disabled: boolean;\n sizes: number[];\n bounds: { min: number; max: number }[];\n ids: string[];\n root: React.RefObject<HTMLDivElement | null>;\n change: (index: number, value: number, commit?: boolean) => void;\n}\nconst Group = createContext<GroupContext | null>(null);\nconst Position = createContext(0);\n\nexport function ResizablePanel({ minSize: _min, maxSize: _max, className = '', style, ...props }: ResizablePanelProps) {\n const group = useContext(Group);\n const index = useContext(Position);\n if (!group) throw new Error('Resizable.Panel must be inside Resizable');\n return <div {...props} id={group.ids[index]} className={`dishui-resizable-panel ${className}`} style={{ ...style, flex: `${group.sizes[index]} 1 0px` }} />;\n}\n\nexport function ResizableHandle({ variant = 'line', disabled = false, step = 1, className = '', onPointerDown, onKeyDown, onClickCapture, children, ...props }: ResizableHandleProps) {\n const group = useContext(Group);\n const index = useContext(Position);\n if (!group) throw new Error('Resizable.Handle must be inside Resizable');\n const total = group.sizes[index] + group.sizes[index + 1];\n const min = Math.max(group.bounds[index].min, total - group.bounds[index + 1].max);\n const max = Math.min(group.bounds[index].max, total - group.bounds[index + 1].min);\n const locked = disabled || group.disabled || min >= max;\n const resize = useResize({\n orientation: group.orientation, value: group.sizes[index], min, max, disabled: locked, step,\n getScale: () => {\n const root = group.root.current;\n if (!root) return 0;\n const dimension = group.orientation === 'horizontal' ? 'width' : 'height';\n const available = Array.from(root.children).filter(el => el.classList.contains('dishui-resizable-panel')).reduce((sum, el) => sum + el.getBoundingClientRect()[dimension], 0);\n const rtl = group.orientation === 'horizontal' && getComputedStyle(root).direction === 'rtl';\n return available > 0 ? (rtl ? -100 : 100) / available : 0;\n },\n onChange: value => group.change(index, value),\n onCommit: value => group.change(index, value, true),\n });\n return <div {...props} role=\"separator\" tabIndex={locked ? -1 : 0}\n aria-label={props['aria-label'] ?? 'Resize panels'} aria-orientation={group.orientation === 'horizontal' ? 'vertical' : 'horizontal'}\n aria-controls={group.ids[index]} aria-valuemin={min} aria-valuemax={max} aria-valuenow={group.sizes[index]} aria-valuetext={`${Number(group.sizes[index].toFixed(2))}%`} aria-disabled={locked}\n data-orientation={group.orientation} data-variant={variant} data-dragging={resize.dragging || undefined}\n className={`dishui-resizable-handle ${className}`}\n onPointerDown={event => { onPointerDown?.(event); if (!event.defaultPrevented) resize.onPointerDown(event); }}\n onKeyDown={event => { onKeyDown?.(event); if (!event.defaultPrevented) resize.onKeyDown(event); }}\n onClickCapture={event => { resize.onClickCapture(event); if (!event.defaultPrevented) onClickCapture?.(event); }}>\n {children ?? (variant === 'pill' ? <span className=\"dishui-resizable-grip\" aria-hidden=\"true\" /> : null)}\n </div>;\n}\n\nfunction ResizableRoot({ orientation = 'horizontal', sizes: controlled, defaultSizes, onSizesChange, onSizesCommit, disabled = false, children, className = '', style, ...props }: ResizableProps) {\n const root = useRef<HTMLDivElement>(null);\n const id = useId();\n const nodes = Children.toArray(children);\n if (!nodes.length || nodes.some((node, i) => !isValidElement(node) || node.type !== (i % 2 === 0 ? ResizablePanel : ResizableHandle)) || nodes.length % 2 === 0) {\n throw new Error('Resizable requires alternating Panel / Handle children, starting and ending with Panel. Nest groups inside a Panel.');\n }\n const panels = nodes.filter((_, i) => i % 2 === 0) as React.ReactElement<ResizablePanelProps>[];\n const bounds = panels.map(panel => ({ min: panel.props.minSize ?? 0, max: panel.props.maxSize ?? 100 }));\n if (bounds.some(b => !Number.isFinite(b.min) || !Number.isFinite(b.max) || b.min < 0 || b.max > 100 || b.min > b.max) || bounds.reduce((s, b) => s + b.min, 0) > 100 || bounds.reduce((s, b) => s + b.max, 0) < 100) throw new Error('Resizable panel constraints must be feasible percentages between 0 and 100');\n const normalize = (input?: number[]) => {\n if (input && (input.length !== panels.length || input.some(v => !Number.isFinite(v) || v < 0) || Math.abs(input.reduce((s, v) => s + v, 0) - 100) > 0.001)) throw new Error('Resizable sizes must match the panel count and sum to 100');\n const values = bounds.map((b, i) => Math.max(b.min, Math.min(b.max, input?.[i] ?? 100 / panels.length)));\n let remaining = 100 - values.reduce((s, v) => s + v, 0);\n for (let i = 0; i < values.length && Math.abs(remaining) > 1e-8; i++) {\n const delta = Math.max(bounds[i].min - values[i], Math.min(bounds[i].max - values[i], remaining));\n values[i] += delta;\n remaining -= delta;\n }\n return values;\n };\n const [internal, setInternal] = useState(() => normalize(defaultSizes));\n const sizes = normalize(controlled ?? (internal.length === panels.length ? internal : undefined));\n const current = useRef(sizes);\n useLayoutEffect(() => { current.current = sizes; });\n const change = (index: number, value: number, commit = false) => {\n const next = [...current.current];\n const total = next[index] + next[index + 1];\n next[index] = value;\n next[index + 1] = total - value;\n if (commit) { onSizesCommit?.(next); return; }\n if (!controlled) { current.current = next; setInternal(next); }\n onSizesChange?.(next);\n };\n const ids = panels.map((panel, i) => panel.props.id ?? `${id}-panel-${i}`);\n return <Group.Provider value={{ orientation, disabled, sizes, bounds, ids, root, change }}>\n <div {...props} ref={root} className={`dishui-resizable ${className}`} data-orientation={orientation} style={style}>\n {nodes.map((node, i) => <Position.Provider key={(node as React.ReactElement).key ?? i} value={Math.floor(i / 2)}>{node}</Position.Provider>)}\n </div>\n </Group.Provider>;\n}\n\nexport const Resizable = Object.assign(ResizableRoot, { Panel: ResizablePanel, Handle: ResizableHandle });\nexport default Resizable;\n"],"mappings":";;;;;AAgCA,IAAM,IAAQ,EAAmC,IAAI,GAC/C,IAAW,EAAc,CAAC;AAEhC,SAAgB,EAAe,EAAE,SAAS,GAAM,SAAS,GAAM,eAAY,IAAI,UAAO,GAAG,KAA8B;CACrH,IAAM,IAAQ,EAAW,CAAK,GACxB,IAAQ,EAAW,CAAQ;CACjC,IAAI,CAAC,GAAO,MAAU,MAAM,0CAA0C;CACtE,OAAO,kBAAC,OAAD;EAAK,GAAI;EAAO,IAAI,EAAM,IAAI;EAAQ,WAAW,0BAA0B;EAAa,OAAO;GAAE,GAAG;GAAO,MAAM,GAAG,EAAM,MAAM,GAAO;EAAQ;CAAI,CAAA;AAC5J;AAEA,SAAgB,EAAgB,EAAE,aAAU,QAAQ,cAAW,IAAO,UAAO,GAAG,eAAY,IAAI,kBAAe,cAAW,mBAAgB,aAAU,GAAG,KAA+B;CACpL,IAAM,IAAQ,EAAW,CAAK,GACxB,IAAQ,EAAW,CAAQ;CACjC,IAAI,CAAC,GAAO,MAAU,MAAM,2CAA2C;CACvE,IAAM,IAAQ,EAAM,MAAM,KAAS,EAAM,MAAM,IAAQ,IACjD,IAAM,KAAK,IAAI,EAAM,OAAO,EAAM,CAAC,KAAK,IAAQ,EAAM,OAAO,IAAQ,EAAE,CAAC,GAAG,GAC3E,IAAM,KAAK,IAAI,EAAM,OAAO,EAAM,CAAC,KAAK,IAAQ,EAAM,OAAO,IAAQ,EAAE,CAAC,GAAG,GAC3E,IAAS,KAAY,EAAM,YAAY,KAAO,GAC9C,IAAS,EAAU;EACvB,aAAa,EAAM;EAAa,OAAO,EAAM,MAAM;EAAQ;EAAK;EAAK,UAAU;EAAQ;EACvF,gBAAgB;GACd,IAAM,IAAO,EAAM,KAAK;GACxB,IAAI,CAAC,GAAM,OAAO;GAClB,IAAM,IAAY,EAAM,gBAAgB,eAAe,UAAU,UAC3D,IAAY,MAAM,KAAK,EAAK,QAAQ,CAAC,CAAC,QAAO,MAAM,EAAG,UAAU,SAAS,wBAAwB,CAAC,CAAC,CAAC,QAAQ,GAAK,MAAO,IAAM,EAAG,sBAAsB,CAAC,CAAC,IAAY,CAAC,GACtK,IAAM,EAAM,gBAAgB,gBAAgB,iBAAiB,CAAI,CAAC,CAAC,cAAc;GACvF,OAAO,IAAY,KAAK,IAAM,OAAO,OAAO,IAAY;EAC1D;EACA,WAAU,MAAS,EAAM,OAAO,GAAO,CAAK;EAC5C,WAAU,MAAS,EAAM,OAAO,GAAO,GAAO,EAAI;CACpD,CAAC;CACD,OAAO,kBAAC,OAAD;EAAK,GAAI;EAAO,MAAK;EAAY,UAAU,IAAS,KAAK;EAC9D,cAAY,EAAM,iBAAiB;EAAiB,oBAAkB,EAAM,gBAAgB,eAAe,aAAa;EACxH,iBAAe,EAAM,IAAI;EAAQ,iBAAe;EAAK,iBAAe;EAAK,iBAAe,EAAM,MAAM;EAAQ,kBAAgB,GAAG,OAAO,EAAM,MAAM,EAAM,CAAC,QAAQ,CAAC,CAAC,EAAE;EAAI,iBAAe;EACxL,oBAAkB,EAAM;EAAa,gBAAc;EAAS,iBAAe,EAAO,YAAY,KAAA;EAC9F,WAAW,2BAA2B;EACtC,gBAAe,MAAS;GAA0B,AAAxB,IAAgB,CAAK,GAAQ,EAAM,oBAAkB,EAAO,cAAc,CAAK;EAAG;EAC5G,YAAW,MAAS;GAAsB,AAApB,IAAY,CAAK,GAAQ,EAAM,oBAAkB,EAAO,UAAU,CAAK;EAAG;EAChG,iBAAgB,MAAS;GAAgC,AAA9B,EAAO,eAAe,CAAK,GAAQ,EAAM,oBAAkB,IAAiB,CAAK;EAAG;EAC9G,UAAA,MAAa,MAAY,SAAS,kBAAC,QAAD;GAAM,WAAU;GAAwB,eAAY;EAAQ,CAAA,IAAI;CAChG,CAAA;AACP;AAEA,SAAS,EAAc,EAAE,iBAAc,cAAc,OAAO,GAAY,iBAAc,kBAAe,kBAAe,cAAW,IAAO,aAAU,eAAY,IAAI,UAAO,GAAG,KAAyB;CACjM,IAAM,IAAO,EAAuB,IAAI,GAClC,IAAK,EAAM,GACX,IAAQ,EAAS,QAAQ,CAAQ;CACvC,IAAI,CAAC,EAAM,UAAU,EAAM,MAAM,GAAM,MAAM,CAAC,EAAe,CAAI,KAAK,EAAK,UAAU,IAAI,KAAM,IAAI,IAAiB,EAAgB,KAAK,EAAM,SAAS,KAAM,GAC5J,MAAU,MAAM,qHAAqH;CAEvI,IAAM,IAAS,EAAM,QAAQ,GAAG,MAAM,IAAI,KAAM,CAAC,GAC3C,IAAS,EAAO,KAAI,OAAU;EAAE,KAAK,EAAM,MAAM,WAAW;EAAG,KAAK,EAAM,MAAM,WAAW;CAAI,EAAE;CACvG,IAAI,EAAO,MAAK,MAAK,CAAC,OAAO,SAAS,EAAE,GAAG,KAAK,CAAC,OAAO,SAAS,EAAE,GAAG,KAAK,EAAE,MAAM,KAAK,EAAE,MAAM,OAAO,EAAE,MAAM,EAAE,GAAG,KAAK,EAAO,QAAQ,GAAG,MAAM,IAAI,EAAE,KAAK,CAAC,IAAI,OAAO,EAAO,QAAQ,GAAG,MAAM,IAAI,EAAE,KAAK,CAAC,IAAI,KAAK,MAAU,MAAM,4EAA4E;CACjT,IAAM,KAAa,MAAqB;EACtC,IAAI,MAAU,EAAM,WAAW,EAAO,UAAU,EAAM,MAAK,MAAK,CAAC,OAAO,SAAS,CAAC,KAAK,IAAI,CAAC,KAAK,KAAK,IAAI,EAAM,QAAQ,GAAG,MAAM,IAAI,GAAG,CAAC,IAAI,GAAG,IAAI,OAAQ,MAAU,MAAM,2DAA2D;EACvO,IAAM,IAAS,EAAO,KAAK,GAAG,MAAM,KAAK,IAAI,EAAE,KAAK,KAAK,IAAI,EAAE,KAAK,IAAQ,MAAM,MAAM,EAAO,MAAM,CAAC,CAAC,GACnG,IAAY,MAAM,EAAO,QAAQ,GAAG,MAAM,IAAI,GAAG,CAAC;EACtD,KAAK,IAAI,IAAI,GAAG,IAAI,EAAO,UAAU,KAAK,IAAI,CAAS,IAAI,MAAM,KAAK;GACpE,IAAM,IAAQ,KAAK,IAAI,EAAO,EAAE,CAAC,MAAM,EAAO,IAAI,KAAK,IAAI,EAAO,EAAE,CAAC,MAAM,EAAO,IAAI,CAAS,CAAC;GAEhG,AADA,EAAO,MAAM,GACb,KAAa;EACf;EACA,OAAO;CACT,GACM,CAAC,GAAU,KAAe,QAAe,EAAU,CAAY,CAAC,GAChE,IAAQ,EAAU,MAAe,EAAS,WAAW,EAAO,SAAS,IAAW,KAAA,EAAU,GAC1F,IAAU,EAAO,CAAK;CAC5B,QAAsB;EAAE,EAAQ,UAAU;CAAO,CAAC;CAClD,IAAM,KAAU,GAAe,GAAe,IAAS,OAAU;EAC/D,IAAM,IAAO,CAAC,GAAG,EAAQ,OAAO,GAC1B,IAAQ,EAAK,KAAS,EAAK,IAAQ;EAGzC,IAFA,EAAK,KAAS,GACd,EAAK,IAAQ,KAAK,IAAQ,GACtB,GAAQ;GAAE,IAAgB,CAAI;GAAG;EAAQ;EAE7C,AADK,MAAc,EAAQ,UAAU,GAAM,EAAY,CAAI,IAC3D,IAAgB,CAAI;CACtB,GACM,IAAM,EAAO,KAAK,GAAO,MAAM,EAAM,MAAM,MAAM,GAAG,EAAG,SAAS,GAAG;CACzE,OAAO,kBAAC,EAAM,UAAP;EAAgB,OAAO;GAAE;GAAa;GAAU;GAAO;GAAQ;GAAK;GAAM;EAAO;EACtF,UAAA,kBAAC,OAAD;GAAK,GAAI;GAAO,KAAK;GAAM,WAAW,oBAAoB;GAAa,oBAAkB;GAAoB;GAC1G,UAAA,EAAM,KAAK,GAAM,MAAM,kBAAC,EAAS,UAAV;IAA+D,OAAO,KAAK,MAAM,IAAI,CAAC;IAAI,UAAA;GAAwB,GAAzF,EAA4B,OAAO,CAAsD,CAAC;EACxI,CAAA;CACS,CAAA;AAClB;AAEA,IAAa,IAAY,OAAO,OAAO,GAAe;CAAE,OAAO;CAAgB,QAAQ;AAAgB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../../src/components/Resizable/index.tsx"],"sourcesContent":["import React, { Children, createContext, isValidElement, useContext, useId, useLayoutEffect, useRef, useState } from 'react';\nimport { useResize } from './useResize';\nimport { ResizeGrip } from './ResizeGrip';\nimport './Resizable.css';\nexport { useResize } from './useResize';\nexport type { UseResizeOptions } from './useResize';\n\nexport interface ResizablePanelProps extends React.HTMLAttributes<HTMLDivElement> {\n minSize?: number;\n maxSize?: number;\n}\nexport interface ResizableHandleProps extends React.HTMLAttributes<HTMLDivElement> {\n variant?: 'line' | 'pill';\n disabled?: boolean;\n step?: number;\n}\nexport interface ResizableProps extends React.HTMLAttributes<HTMLDivElement> {\n orientation?: 'horizontal' | 'vertical';\n sizes?: number[];\n defaultSizes?: number[];\n onSizesChange?: (sizes: number[]) => void;\n onSizesCommit?: (sizes: number[]) => void;\n disabled?: boolean;\n}\ninterface GroupContext {\n orientation: 'horizontal' | 'vertical';\n disabled: boolean;\n sizes: number[];\n bounds: { min: number; max: number }[];\n ids: string[];\n root: React.RefObject<HTMLDivElement | null>;\n change: (index: number, value: number, commit?: boolean) => void;\n}\nconst Group = createContext<GroupContext | null>(null);\nconst Position = createContext(0);\n\nexport function ResizablePanel({ minSize: _min, maxSize: _max, className = '', style, ...props }: ResizablePanelProps) {\n const group = useContext(Group);\n const index = useContext(Position);\n if (!group) throw new Error('Resizable.Panel must be inside Resizable');\n return <div {...props} id={group.ids[index]} className={`dishui-resizable-panel ${className}`} style={{ ...style, flex: `${group.sizes[index]} 1 0px` }} />;\n}\n\nexport function ResizableHandle({ variant = 'pill', disabled = false, step = 1, className = '', onPointerDown, onKeyDown, onClickCapture, children, ...props }: ResizableHandleProps) {\n const group = useContext(Group);\n const index = useContext(Position);\n if (!group) throw new Error('Resizable.Handle must be inside Resizable');\n const total = group.sizes[index] + group.sizes[index + 1];\n const min = Math.max(group.bounds[index].min, total - group.bounds[index + 1].max);\n const max = Math.min(group.bounds[index].max, total - group.bounds[index + 1].min);\n const locked = disabled || group.disabled || min >= max;\n const resize = useResize({\n orientation: group.orientation, value: group.sizes[index], min, max, disabled: locked, step,\n getScale: () => {\n const root = group.root.current;\n if (!root) return 0;\n const dimension = group.orientation === 'horizontal' ? 'width' : 'height';\n const available = Array.from(root.children).filter(el => el.classList.contains('dishui-resizable-panel')).reduce((sum, el) => sum + el.getBoundingClientRect()[dimension], 0);\n const rtl = group.orientation === 'horizontal' && getComputedStyle(root).direction === 'rtl';\n return available > 0 ? (rtl ? -100 : 100) / available : 0;\n },\n onChange: value => group.change(index, value),\n onCommit: value => group.change(index, value, true),\n });\n return <div {...props} role=\"separator\" tabIndex={locked ? -1 : 0}\n aria-label={props['aria-label'] ?? 'Resize panels'} aria-orientation={group.orientation === 'horizontal' ? 'vertical' : 'horizontal'}\n aria-controls={group.ids[index]} aria-valuemin={min} aria-valuemax={max} aria-valuenow={group.sizes[index]} aria-valuetext={`${Number(group.sizes[index].toFixed(2))}%`} aria-disabled={locked}\n data-orientation={group.orientation} data-variant={variant} data-dragging={resize.dragging || undefined}\n className={`dishui-resize-handle dishui-resizable-handle ${className}`}\n onPointerDown={event => { onPointerDown?.(event); if (!event.defaultPrevented) resize.onPointerDown(event); }}\n onKeyDown={event => { onKeyDown?.(event); if (!event.defaultPrevented) resize.onKeyDown(event); }}\n onClickCapture={event => { resize.onClickCapture(event); if (!event.defaultPrevented) onClickCapture?.(event); }}>\n {children ?? <ResizeGrip variant={variant} />}\n </div>;\n}\n\nfunction ResizableRoot({ orientation = 'horizontal', sizes: controlled, defaultSizes, onSizesChange, onSizesCommit, disabled = false, children, className = '', style, ...props }: ResizableProps) {\n const root = useRef<HTMLDivElement>(null);\n const id = useId();\n const nodes = Children.toArray(children);\n if (!nodes.length || nodes.some((node, i) => !isValidElement(node) || node.type !== (i % 2 === 0 ? ResizablePanel : ResizableHandle)) || nodes.length % 2 === 0) {\n throw new Error('Resizable requires alternating Panel / Handle children, starting and ending with Panel. Nest groups inside a Panel.');\n }\n const panels = nodes.filter((_, i) => i % 2 === 0) as React.ReactElement<ResizablePanelProps>[];\n const bounds = panels.map(panel => ({ min: panel.props.minSize ?? 0, max: panel.props.maxSize ?? 100 }));\n if (bounds.some(b => !Number.isFinite(b.min) || !Number.isFinite(b.max) || b.min < 0 || b.max > 100 || b.min > b.max) || bounds.reduce((s, b) => s + b.min, 0) > 100 || bounds.reduce((s, b) => s + b.max, 0) < 100) throw new Error('Resizable panel constraints must be feasible percentages between 0 and 100');\n const normalize = (input?: number[]) => {\n if (input && (input.length !== panels.length || input.some(v => !Number.isFinite(v) || v < 0) || Math.abs(input.reduce((s, v) => s + v, 0) - 100) > 0.001)) throw new Error('Resizable sizes must match the panel count and sum to 100');\n const values = bounds.map((b, i) => Math.max(b.min, Math.min(b.max, input?.[i] ?? 100 / panels.length)));\n let remaining = 100 - values.reduce((s, v) => s + v, 0);\n for (let i = 0; i < values.length && Math.abs(remaining) > 1e-8; i++) {\n const delta = Math.max(bounds[i].min - values[i], Math.min(bounds[i].max - values[i], remaining));\n values[i] += delta;\n remaining -= delta;\n }\n return values;\n };\n const [internal, setInternal] = useState(() => normalize(defaultSizes));\n const sizes = normalize(controlled ?? (internal.length === panels.length ? internal : undefined));\n const current = useRef(sizes);\n useLayoutEffect(() => { current.current = sizes; });\n const change = (index: number, value: number, commit = false) => {\n const next = [...current.current];\n const total = next[index] + next[index + 1];\n next[index] = value;\n next[index + 1] = total - value;\n if (commit) { onSizesCommit?.(next); return; }\n if (!controlled) { current.current = next; setInternal(next); }\n onSizesChange?.(next);\n };\n const ids = panels.map((panel, i) => panel.props.id ?? `${id}-panel-${i}`);\n return <Group.Provider value={{ orientation, disabled, sizes, bounds, ids, root, change }}>\n <div {...props} ref={root} className={`dishui-resizable ${className}`} data-orientation={orientation} style={style}>\n {nodes.map((node, i) => <Position.Provider key={(node as React.ReactElement).key ?? i} value={Math.floor(i / 2)}>{node}</Position.Provider>)}\n </div>\n </Group.Provider>;\n}\n\nexport const Resizable = Object.assign(ResizableRoot, { Panel: ResizablePanel, Handle: ResizableHandle });\nexport default Resizable;\n"],"mappings":"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"}
|
|
@@ -6,6 +6,11 @@ export interface UseResizeOptions {
|
|
|
6
6
|
max?: number;
|
|
7
7
|
disabled?: boolean;
|
|
8
8
|
step?: number;
|
|
9
|
+
/** Arrow-key direction; independent of pointer scaling. Defaults to 1. */
|
|
10
|
+
keyboardDirection?: 1 | -1;
|
|
11
|
+
shiftMultiplier?: number;
|
|
12
|
+
/** Read the actual size at pointer down / key down (e.g. CSS-sized edges). */
|
|
13
|
+
getValue?: () => number;
|
|
9
14
|
/** Value units per CSS pixel; evaluated at pointer down. */
|
|
10
15
|
getScale?: () => number;
|
|
11
16
|
threshold?: number;
|
|
@@ -15,6 +20,7 @@ export interface UseResizeOptions {
|
|
|
15
20
|
/** Shared pointer/keyboard engine. Does not mutate document/body styles. */
|
|
16
21
|
export declare function useResize(options: UseResizeOptions): {
|
|
17
22
|
dragging: boolean;
|
|
23
|
+
cancel: () => void | undefined;
|
|
18
24
|
onPointerDown: (event: React.PointerEvent<HTMLElement>) => void;
|
|
19
25
|
onKeyDown: (event: React.KeyboardEvent<HTMLElement>) => void;
|
|
20
26
|
onClickCapture: (event: React.MouseEvent<HTMLElement>) => void;
|