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
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { cn as e } from "../../utils/cn.js";
|
|
2
|
+
import t from "../Page/index.js";
|
|
3
|
+
import n from "../../layouts/Sidebar.js";
|
|
4
|
+
/* empty css */
|
|
5
|
+
import { DashboardSuite as r } from "./DashboardSuite.js";
|
|
6
|
+
import { useState as i } from "react";
|
|
7
|
+
import { jsx as a, jsxs as o } from "react/jsx-runtime";
|
|
8
|
+
//#region src/components/LayoutSuite/index.tsx
|
|
9
|
+
var s = ({ side: r, panel: o, resizable: s = !1, language: c = "zh", isCollapsed: l = !1, ...u }) => {
|
|
10
|
+
let { initialWidth: d = 280, collapsedWidth: f = 64, onWidthChange: p } = u, m = o?.minWidth ?? u.minWidth ?? 160, h = o?.maxWidth ?? u.maxWidth ?? 400, g = Number.isFinite(m) ? Math.max(0, m) : 160, _ = Math.max(g, Number.isFinite(h) ? h : 400), v = o?.style?.width ?? o?.width ?? d, y = (e) => Math.max(g, Math.min(Number.isFinite(e) ? e : 280, _)), [b, x] = i(() => ({
|
|
11
|
+
initialWidth: d,
|
|
12
|
+
sourceWidth: v,
|
|
13
|
+
minWidth: g,
|
|
14
|
+
maxWidth: _,
|
|
15
|
+
width: typeof v == "number" ? y(v) : v
|
|
16
|
+
})), S = !Object.is(b.initialWidth, d) || !Object.is(b.sourceWidth, v) || !Object.is(b.minWidth, g) || !Object.is(b.maxWidth, _), C = S ? typeof v == "number" ? y(v) : v : b.width;
|
|
17
|
+
S && x({
|
|
18
|
+
initialWidth: d,
|
|
19
|
+
sourceWidth: v,
|
|
20
|
+
minWidth: g,
|
|
21
|
+
maxWidth: _,
|
|
22
|
+
width: C
|
|
23
|
+
});
|
|
24
|
+
let w = (e) => {
|
|
25
|
+
let t = y(e);
|
|
26
|
+
x({
|
|
27
|
+
initialWidth: d,
|
|
28
|
+
sourceWidth: v,
|
|
29
|
+
minWidth: g,
|
|
30
|
+
maxWidth: _,
|
|
31
|
+
width: t
|
|
32
|
+
}), p?.(t);
|
|
33
|
+
}, T = (e) => {
|
|
34
|
+
w(e), o?.onWidthChange !== p && o?.onWidthChange?.(y(e));
|
|
35
|
+
}, E = typeof C == "number" ? C : y(d), D = r === "left" ? t.Left : t.Right;
|
|
36
|
+
return /* @__PURE__ */ a(D, {
|
|
37
|
+
bordered: !1,
|
|
38
|
+
scroll: !1,
|
|
39
|
+
...o,
|
|
40
|
+
width: l ? f : C,
|
|
41
|
+
style: o?.style ? {
|
|
42
|
+
...o.style,
|
|
43
|
+
width: void 0
|
|
44
|
+
} : void 0,
|
|
45
|
+
minWidth: g,
|
|
46
|
+
maxWidth: _,
|
|
47
|
+
resizable: !l && (o?.resizable ?? s),
|
|
48
|
+
resizeVariant: u.onToggle ? "line" : o?.resizeVariant,
|
|
49
|
+
onWidthChange: T,
|
|
50
|
+
className: e("dishui-layout-suite-sidebar", !l && typeof C == "string" && "dishui-layout-suite-sidebar-css-width", o?.className),
|
|
51
|
+
children: /* @__PURE__ */ a(n, {
|
|
52
|
+
...u,
|
|
53
|
+
side: r,
|
|
54
|
+
language: c,
|
|
55
|
+
isCollapsed: l,
|
|
56
|
+
initialWidth: E,
|
|
57
|
+
minWidth: g,
|
|
58
|
+
maxWidth: _,
|
|
59
|
+
onWidthChange: p || u.onToggle && (o?.resizable ?? s) ? T : void 0
|
|
60
|
+
})
|
|
61
|
+
});
|
|
62
|
+
}, c = ({ header: n, left: r, right: i, footer: c, float: l, body: u, main: d, fullHeight: f = !1, children: p, className: m, ...h }) => /* @__PURE__ */ o(t, {
|
|
63
|
+
fullHeight: f,
|
|
64
|
+
...h,
|
|
65
|
+
className: e("dishui-layout-suite", m),
|
|
66
|
+
children: [
|
|
67
|
+
n && /* @__PURE__ */ a(t.Header, { ...n }),
|
|
68
|
+
/* @__PURE__ */ o(t.Body, {
|
|
69
|
+
gap: 0,
|
|
70
|
+
scroll: f,
|
|
71
|
+
...u,
|
|
72
|
+
children: [
|
|
73
|
+
r && /* @__PURE__ */ a(s, {
|
|
74
|
+
side: "left",
|
|
75
|
+
...r
|
|
76
|
+
}),
|
|
77
|
+
/* @__PURE__ */ a(t.Main, {
|
|
78
|
+
scroll: f,
|
|
79
|
+
...d,
|
|
80
|
+
children: p === void 0 ? d?.children : p
|
|
81
|
+
}),
|
|
82
|
+
i && /* @__PURE__ */ a(s, {
|
|
83
|
+
side: "right",
|
|
84
|
+
...i
|
|
85
|
+
})
|
|
86
|
+
]
|
|
87
|
+
}),
|
|
88
|
+
c && /* @__PURE__ */ a(t.Footer, { ...c }),
|
|
89
|
+
l && /* @__PURE__ */ a(t.Float, { ...l })
|
|
90
|
+
]
|
|
91
|
+
}), l = (e) => /* @__PURE__ */ a(c, { ...e }), u = (e) => /* @__PURE__ */ a(c, { ...e }), d = (e) => /* @__PURE__ */ a(c, { ...e }), f = (e) => /* @__PURE__ */ a(c, { ...e }), p = {
|
|
92
|
+
AdminSuite: l,
|
|
93
|
+
WikiSuite: u,
|
|
94
|
+
BlogSuite: d,
|
|
95
|
+
BlankSuite: f,
|
|
96
|
+
DashboardSuite: r
|
|
97
|
+
};
|
|
98
|
+
//#endregion
|
|
99
|
+
export { l as AdminSuite, f as BlankSuite, d as BlogSuite, r as DashboardSuite, p as LayoutSuite, p as default, u as WikiSuite };
|
|
100
|
+
|
|
101
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../../src/components/LayoutSuite/index.tsx"],"sourcesContent":["import React, { useState } from 'react';\nimport Page, {\n type PageProps,\n type PageBodyProps,\n type PageMainProps,\n type PageAsideProps,\n type PagePanelProps,\n type PageFooterProps,\n type PageFloatProps,\n} from '../Page';\nimport type { PageHeaderProps } from '../PageHeader';\nimport Sidebar from '../../layouts/Sidebar';\nimport { cn } from '../../utils/cn';\nimport './style.css';\nimport { DashboardSuite } from './DashboardSuite';\nexport { DashboardSuite } from './DashboardSuite';\nexport type { DashboardSuiteProps } from './DashboardSuite';\n\n/** Sidebar 保持原有 API;panel 仅配置外层 Page.Left / Page.Right。 */\nexport type LayoutSuiteSidebarProps = Omit<React.ComponentProps<typeof Sidebar>, 'language' | 'isCollapsed' | 'side'> & {\n language?: 'zh' | 'en';\n isCollapsed?: boolean;\n /** 独立启用区域边缘调宽,不要求 onToggle 或 onWidthChange。 */\n resizable?: boolean;\n panel?: Omit<PageAsideProps, 'children'>;\n};\n\nexport type LayoutSuiteHeaderProps = PageHeaderProps & PagePanelProps;\n\nexport type LayoutSuiteBaseProps = PageProps & {\n /** 可选三段式页头;Admin / Blog 仍要求配置 header。 */\n header?: LayoutSuiteHeaderProps;\n footer?: PageFooterProps;\n /** body 不接收 children;主内容支持顶层 children 或 main.children。 */\n body?: Omit<PageBodyProps, 'children'>;\n main?: PageMainProps;\n};\n\nexport type AdminSuiteProps = LayoutSuiteBaseProps & {\n header: LayoutSuiteHeaderProps;\n left: LayoutSuiteSidebarProps;\n};\n\nexport type WikiSuiteProps = LayoutSuiteBaseProps & {\n left?: LayoutSuiteSidebarProps;\n right?: LayoutSuiteSidebarProps;\n float?: PageFloatProps;\n};\n\nexport type BlogSuiteProps = LayoutSuiteBaseProps & {\n header: LayoutSuiteHeaderProps;\n footer?: PageFooterProps;\n};\n\nexport type BlankSuiteProps = LayoutSuiteBaseProps & {\n float?: PageFloatProps;\n};\n\nconst SidebarPanel = ({\n side,\n panel,\n resizable = false,\n language = 'zh',\n isCollapsed = false,\n ...sidebar\n}: LayoutSuiteSidebarProps & { side: 'left' | 'right' }) => {\n const { initialWidth = 280, collapsedWidth = 64, onWidthChange } = sidebar;\n const requestedMin = panel?.minWidth ?? sidebar.minWidth ?? 160;\n const requestedMax = panel?.maxWidth ?? sidebar.maxWidth ?? 400;\n const minWidth = Number.isFinite(requestedMin) ? Math.max(0, requestedMin) : 160;\n const maxWidth = Math.max(minWidth, Number.isFinite(requestedMax) ? requestedMax : 400);\n const panelWidth = panel?.style?.width ?? panel?.width;\n const sourceWidth = panelWidth ?? initialWidth;\n const clamp = (width: number) => Math.max(minWidth, Math.min(Number.isFinite(width) ? width : 280, maxWidth));\n const [widthState, setWidthState] = useState(() => ({\n initialWidth, sourceWidth, minWidth, maxWidth,\n width: typeof sourceWidth === 'number' ? clamp(sourceWidth) : sourceWidth,\n }));\n\n // 与 Sidebar 的配置同步规则一致;折叠不重置用户拖动后的展开宽度。\n const configChanged = !Object.is(widthState.initialWidth, initialWidth)\n || !Object.is(widthState.sourceWidth, sourceWidth)\n || !Object.is(widthState.minWidth, minWidth) || !Object.is(widthState.maxWidth, maxWidth);\n const expandedWidth = configChanged\n ? (typeof sourceWidth === 'number' ? clamp(sourceWidth) : sourceWidth)\n : widthState.width;\n if (configChanged) {\n setWidthState({ initialWidth, sourceWidth, minWidth, maxWidth, width: expandedWidth });\n }\n\n const handleWidthChange = (width: number) => {\n const next = clamp(width);\n setWidthState({ initialWidth, sourceWidth, minWidth, maxWidth, width: next });\n onWidthChange?.(next);\n };\n const handlePanelWidthChange = (width: number) => {\n handleWidthChange(width);\n if (panel?.onWidthChange !== onWidthChange) panel?.onWidthChange?.(clamp(width));\n };\n const sidebarWidth = typeof expandedWidth === 'number' ? expandedWidth : clamp(initialWidth);\n const Aside = side === 'left' ? Page.Left : Page.Right;\n return (\n <Aside\n bordered={false}\n scroll={false}\n {...panel}\n width={isCollapsed ? collapsedWidth : expandedWidth}\n style={panel?.style ? { ...panel.style, width: undefined } : undefined}\n minWidth={minWidth}\n maxWidth={maxWidth}\n resizable={!isCollapsed && (panel?.resizable ?? resizable)}\n resizeVariant={sidebar.onToggle ? 'line' : panel?.resizeVariant}\n onWidthChange={handlePanelWidthChange}\n className={cn('dishui-layout-suite-sidebar',\n !isCollapsed && typeof expandedWidth === 'string' && 'dishui-layout-suite-sidebar-css-width', panel?.className)}\n >\n <Sidebar {...sidebar} side={side} language={language} isCollapsed={isCollapsed}\n initialWidth={sidebarWidth} minWidth={minWidth} maxWidth={maxWidth}\n onWidthChange={onWidthChange || (sidebar.onToggle && (panel?.resizable ?? resizable)) ? handlePanelWidthChange : undefined} />\n </Aside>\n );\n};\n\ntype SuiteFrameProps = LayoutSuiteBaseProps & {\n header?: LayoutSuiteHeaderProps;\n left?: LayoutSuiteSidebarProps;\n right?: LayoutSuiteSidebarProps;\n footer?: PageFooterProps;\n float?: PageFloatProps;\n};\n\nconst SuiteFrame = ({\n header,\n left,\n right,\n footer,\n float,\n body,\n main,\n fullHeight = false,\n children,\n className,\n ...page\n}: SuiteFrameProps) => (\n <Page fullHeight={fullHeight} {...page} className={cn('dishui-layout-suite', className)}>\n {header && <Page.Header {...header} />}\n <Page.Body gap={0} scroll={fullHeight} {...body}>\n {left && <SidebarPanel side=\"left\" {...left} />}\n <Page.Main scroll={fullHeight} {...main}>{children !== undefined ? children : main?.children}</Page.Main>\n {right && <SidebarPanel side=\"right\" {...right} />}\n </Page.Body>\n {footer && <Page.Footer {...footer} />}\n {float && <Page.Float {...float} />}\n </Page>\n);\n\n/** 后台:必填页头和内置导航侧栏。Sidebar 需置于 TanStack Router 上下文中。 */\nexport const AdminSuite = (props: AdminSuiteProps) => <SuiteFrame {...props} />;\n\n/** 文档:可选双侧导航与浮窗。 */\nexport const WikiSuite = (props: WikiSuiteProps) => <SuiteFrame {...props} />;\n\n/** 博客:必填页头,可选页脚。 */\nexport const BlogSuite = (props: BlogSuiteProps) => <SuiteFrame {...props} />;\n\n/** 空白页:主内容与可选浮窗。 */\nexport const BlankSuite = (props: BlankSuiteProps) => <SuiteFrame {...props} />;\n\nexport const LayoutSuite = { AdminSuite, WikiSuite, BlogSuite, BlankSuite, DashboardSuite };\n\nexport default LayoutSuite;\n"],"mappings":"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"}
|
|
@@ -3,7 +3,7 @@ import "react";
|
|
|
3
3
|
import { jsx as t } from "react/jsx-runtime";
|
|
4
4
|
//#region src/components/List/index.tsx
|
|
5
5
|
var n = ({ children: n, className: r = "", onClick: i, onMouseEnter: a, onMouseLeave: o }) => {
|
|
6
|
-
let s = e("list", r);
|
|
6
|
+
let s = e("dishui-list list text-body leading-5 text-base-content", r);
|
|
7
7
|
return /* @__PURE__ */ t("ul", {
|
|
8
8
|
className: s,
|
|
9
9
|
onClick: i,
|
|
@@ -12,7 +12,7 @@ var n = ({ children: n, className: r = "", onClick: i, onMouseEnter: a, onMouseL
|
|
|
12
12
|
children: n
|
|
13
13
|
});
|
|
14
14
|
}, r = ({ children: n, className: r = "", selected: i = !1, onClick: a, onDoubleClick: o, onMouseEnter: s, onMouseLeave: c, onContextMenu: l }) => {
|
|
15
|
-
let u = e("list-row", i && "bg-base-200", r);
|
|
15
|
+
let u = e("dishui-list-row list-row min-h-10 gap-3 rounded-none px-3 py-2 text-body transition-colors duration-150 motion-reduce:transition-none", i && "bg-base-200", r);
|
|
16
16
|
return /* @__PURE__ */ t("li", {
|
|
17
17
|
className: u,
|
|
18
18
|
onClick: a,
|
|
@@ -23,19 +23,19 @@ var n = ({ children: n, className: r = "", onClick: i, onMouseEnter: a, onMouseL
|
|
|
23
23
|
children: n
|
|
24
24
|
});
|
|
25
25
|
}, i = ({ children: n, className: r = "" }) => {
|
|
26
|
-
let i = e("list-col-wrap", r);
|
|
26
|
+
let i = e("list-col-wrap min-w-0 break-words", r);
|
|
27
27
|
return /* @__PURE__ */ t("div", {
|
|
28
28
|
className: i,
|
|
29
29
|
children: n
|
|
30
30
|
});
|
|
31
31
|
}, a = ({ children: n, className: r = "" }) => {
|
|
32
|
-
let i = e("list-col-grow", r);
|
|
32
|
+
let i = e("list-col-grow min-w-0 break-words", r);
|
|
33
33
|
return /* @__PURE__ */ t("div", {
|
|
34
34
|
className: i,
|
|
35
35
|
children: n
|
|
36
36
|
});
|
|
37
37
|
}, o = ({ children: n, className: r = "" }) => {
|
|
38
|
-
let i = e("
|
|
38
|
+
let i = e("dishui-list-header px-3 py-2", "text-body-sm font-medium leading-5", "text-base-content/70", r);
|
|
39
39
|
return /* @__PURE__ */ t("li", {
|
|
40
40
|
className: i,
|
|
41
41
|
children: n
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../../src/components/List/index.tsx"],"sourcesContent":["import React from 'react';\nimport { cn } from '../../utils/cn';\n\nexport type ListProps = {\n children: React.ReactNode;\n className?: string;\n onClick?: (e: React.MouseEvent) => void;\n onMouseEnter?: (e: React.MouseEvent) => void;\n onMouseLeave?: (e: React.MouseEvent) => void;\n};\n\nconst List = ({\n children,\n className = '',\n onClick,\n onMouseEnter,\n onMouseLeave,\n}: ListProps) => {\n const baseClass = 'list';\n \n const listClasses = cn(baseClass, className);\n\n return (\n <ul \n className={listClasses}\n onClick={onClick}\n onMouseEnter={onMouseEnter}\n onMouseLeave={onMouseLeave}\n >\n {children}\n </ul>\n );\n};\n\n// List.Row 组件\nexport type ListRowProps = {\n children: React.ReactNode;\n className?: string;\n selected?: boolean;\n onClick?: (e: React.MouseEvent) => void;\n onDoubleClick?: (e: React.MouseEvent) => void;\n onMouseEnter?: (e: React.MouseEvent) => void;\n onMouseLeave?: (e: React.MouseEvent) => void;\n onContextMenu?: (e: React.MouseEvent) => void;\n};\n\nconst ListRow = ({\n children,\n className = '',\n selected = false,\n onClick,\n onDoubleClick,\n onMouseEnter,\n onMouseLeave,\n onContextMenu,\n}: ListRowProps) => {\n const baseClass = 'list-row';\n \n const rowClasses = cn(baseClass, selected && 'bg-base-200', className);\n\n return (\n <li \n className={rowClasses}\n onClick={onClick}\n onDoubleClick={onDoubleClick}\n onMouseEnter={onMouseEnter}\n onMouseLeave={onMouseLeave}\n onContextMenu={onContextMenu}\n >\n {children}\n </li>\n );\n};\n\n// List.ColWrap 组件\nexport type ListColWrapProps = {\n children: React.ReactNode;\n className?: string;\n};\n\nconst ListColWrap = ({\n children,\n className = '',\n}: ListColWrapProps) => {\n const baseClass = 'list-col-wrap';\n \n const colWrapClasses = cn(baseClass, className);\n\n return (\n <div className={colWrapClasses}>\n {children}\n </div>\n );\n};\n\n// List.ColGrow 组件\nexport type ListColGrowProps = {\n children: React.ReactNode;\n className?: string;\n};\n\nconst ListColGrow = ({\n children,\n className = '',\n}: ListColGrowProps) => {\n const baseClass = 'list-col-grow';\n \n const colGrowClasses = cn(baseClass, className);\n\n return (\n <div className={colGrowClasses}>\n {children}\n </div>\n );\n};\n\n// List.Header 组件\nexport type ListHeaderProps = {\n children: React.ReactNode;\n className?: string;\n};\n\nconst ListHeader = ({\n children,\n className = '',\n}: ListHeaderProps) => {\n const headerClasses = cn(\n '
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../../src/components/List/index.tsx"],"sourcesContent":["import React from 'react';\nimport { cn } from '../../utils/cn';\n\nexport type ListProps = {\n children: React.ReactNode;\n className?: string;\n onClick?: (e: React.MouseEvent) => void;\n onMouseEnter?: (e: React.MouseEvent) => void;\n onMouseLeave?: (e: React.MouseEvent) => void;\n};\n\nconst List = ({\n children,\n className = '',\n onClick,\n onMouseEnter,\n onMouseLeave,\n}: ListProps) => {\n const baseClass = 'dishui-list list text-body leading-5 text-base-content';\n \n const listClasses = cn(baseClass, className);\n\n return (\n <ul \n className={listClasses}\n onClick={onClick}\n onMouseEnter={onMouseEnter}\n onMouseLeave={onMouseLeave}\n >\n {children}\n </ul>\n );\n};\n\n// List.Row 组件\nexport type ListRowProps = {\n children: React.ReactNode;\n className?: string;\n selected?: boolean;\n onClick?: (e: React.MouseEvent) => void;\n onDoubleClick?: (e: React.MouseEvent) => void;\n onMouseEnter?: (e: React.MouseEvent) => void;\n onMouseLeave?: (e: React.MouseEvent) => void;\n onContextMenu?: (e: React.MouseEvent) => void;\n};\n\nconst ListRow = ({\n children,\n className = '',\n selected = false,\n onClick,\n onDoubleClick,\n onMouseEnter,\n onMouseLeave,\n onContextMenu,\n}: ListRowProps) => {\n const baseClass = 'dishui-list-row list-row min-h-10 gap-3 rounded-none px-3 py-2 text-body transition-colors duration-150 motion-reduce:transition-none';\n \n const rowClasses = cn(baseClass, selected && 'bg-base-200', className);\n\n return (\n <li \n className={rowClasses}\n onClick={onClick}\n onDoubleClick={onDoubleClick}\n onMouseEnter={onMouseEnter}\n onMouseLeave={onMouseLeave}\n onContextMenu={onContextMenu}\n >\n {children}\n </li>\n );\n};\n\n// List.ColWrap 组件\nexport type ListColWrapProps = {\n children: React.ReactNode;\n className?: string;\n};\n\nconst ListColWrap = ({\n children,\n className = '',\n}: ListColWrapProps) => {\n const baseClass = 'list-col-wrap min-w-0 break-words';\n \n const colWrapClasses = cn(baseClass, className);\n\n return (\n <div className={colWrapClasses}>\n {children}\n </div>\n );\n};\n\n// List.ColGrow 组件\nexport type ListColGrowProps = {\n children: React.ReactNode;\n className?: string;\n};\n\nconst ListColGrow = ({\n children,\n className = '',\n}: ListColGrowProps) => {\n const baseClass = 'list-col-grow min-w-0 break-words';\n \n const colGrowClasses = cn(baseClass, className);\n\n return (\n <div className={colGrowClasses}>\n {children}\n </div>\n );\n};\n\n// List.Header 组件\nexport type ListHeaderProps = {\n children: React.ReactNode;\n className?: string;\n};\n\nconst ListHeader = ({\n children,\n className = '',\n}: ListHeaderProps) => {\n const headerClasses = cn(\n 'dishui-list-header px-3 py-2',\n 'text-body-sm font-medium leading-5',\n 'text-base-content/70',\n className\n );\n\n return (\n <li className={headerClasses}>\n {children}\n </li>\n );\n};\n\n// 扩展List组件,添加Row、ColWrap和ColGrow子组件\ninterface ListCompound extends React.FC<ListProps> {\n Row: React.FC<ListRowProps>;\n ColWrap: React.FC<ListColWrapProps>;\n ColGrow: React.FC<ListColGrowProps>;\n Header: React.FC<ListHeaderProps>;\n}\n\nconst ListWithCompounds = List as ListCompound;\nListWithCompounds.Row = ListRow;\nListWithCompounds.ColWrap = ListColWrap;\nListWithCompounds.ColGrow = ListColGrow;\nListWithCompounds.Header = ListHeader;\n\nexport default ListWithCompounds; "],"mappings":";;;;AAWA,IAAM,KAAQ,EACZ,aACA,eAAY,IACZ,YACA,iBACA,sBACe;CAGf,IAAM,IAAc,EAAG,0DAAW,CAAS;CAE3C,OACE,kBAAC,MAAD;EACE,WAAW;EACF;EACK;EACA;EAEb;CACC,CAAA;AAER,GAcM,KAAW,EACf,aACA,eAAY,IACZ,cAAW,IACX,YACA,kBACA,iBACA,iBACA,uBACkB;CAGlB,IAAM,IAAa,EAAG,yIAAW,KAAY,eAAe,CAAS;CAErE,OACE,kBAAC,MAAD;EACE,WAAW;EACF;EACM;EACD;EACA;EACC;EAEd;CACC,CAAA;AAER,GAQM,KAAe,EACnB,aACA,eAAY,SACU;CAGtB,IAAM,IAAiB,EAAG,qCAAW,CAAS;CAE9C,OACE,kBAAC,OAAD;EAAK,WAAW;EACb;CACE,CAAA;AAET,GAQM,KAAe,EACnB,aACA,eAAY,SACU;CAGtB,IAAM,IAAiB,EAAG,qCAAW,CAAS;CAE9C,OACE,kBAAC,OAAD;EAAK,WAAW;EACb;CACE,CAAA;AAET,GAQM,KAAc,EAClB,aACA,eAAY,SACS;CACrB,IAAM,IAAgB,EACpB,gCACA,sCACA,wBACA,CACF;CAEA,OACE,kBAAC,MAAD;EAAI,WAAW;EACZ;CACC,CAAA;AAER,GAUM,IAAoB;AAC1B,EAAkB,MAAM,GACxB,EAAkB,UAAU,GAC5B,EAAkB,UAAU,GAC5B,EAAkB,SAAS"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function mountFocusScope(panel: HTMLElement, overlay: HTMLElement, trigger: HTMLElement | null, close: () => void): () => void;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
//#region src/components/Modal/focusScope.ts
|
|
2
|
+
var e = [], t = /* @__PURE__ */ new Map(), n = "", r, i = "button, a[href], input, select, textarea, [tabindex], [contenteditable=\"true\"]", a = () => e[e.length - 1], o = (e) => !!e.panel.querySelector("[role=\"combobox\"][aria-expanded=\"true\"]"), s = (e) => {
|
|
3
|
+
let t = /* @__PURE__ */ new Set();
|
|
4
|
+
for (let n of e.panel.querySelectorAll("[aria-haspopup=\"menu\"][aria-expanded=\"true\"][aria-controls]")) for (let e of n.getAttribute("aria-controls").split(/\s+/)) {
|
|
5
|
+
let n = document.getElementById(e);
|
|
6
|
+
n?.parentElement === document.body && n.getAttribute("role") === "menu" && t.add(n);
|
|
7
|
+
}
|
|
8
|
+
return [...t];
|
|
9
|
+
}, c = (e) => {
|
|
10
|
+
let t = o(e) ? Array.from(document.body.children).filter((t) => !e.existing.has(t) && t.matches("[role=\"listbox\"]")) : [];
|
|
11
|
+
return [
|
|
12
|
+
e.panel,
|
|
13
|
+
...t,
|
|
14
|
+
...s(e)
|
|
15
|
+
];
|
|
16
|
+
}, l = (e, t) => c(e).some((e) => e.contains(t)), u = (e, t = !0) => c(e).filter((n) => t || n === e.panel || n.getAttribute("role") !== "menu").flatMap((e) => Array.from(e.querySelectorAll(i))).filter((e) => e.tabIndex >= 0 && !e.matches(":disabled") && !e.closest("[inert]") && e.getClientRects().length > 0 && getComputedStyle(e).visibility !== "hidden"), d = () => {
|
|
17
|
+
t.forEach((e, t) => {
|
|
18
|
+
t.inert = e.inert, e.hidden === null ? t.removeAttribute("aria-hidden") : t.setAttribute("aria-hidden", e.hidden);
|
|
19
|
+
}), t.clear();
|
|
20
|
+
}, f = () => {
|
|
21
|
+
d();
|
|
22
|
+
let e = a();
|
|
23
|
+
if (!e) return;
|
|
24
|
+
let n = [e.overlay, ...c(e)];
|
|
25
|
+
for (let e of Array.from(document.body.children)) e instanceof HTMLElement && !n.includes(e) && (t.set(e, {
|
|
26
|
+
inert: e.inert,
|
|
27
|
+
hidden: e.getAttribute("aria-hidden")
|
|
28
|
+
}), e.inert = !0, e.setAttribute("aria-hidden", "true"));
|
|
29
|
+
}, p = (e) => (u(e)[0] || e.panel).focus({ preventScroll: !0 }), m = (e) => {
|
|
30
|
+
let t = a();
|
|
31
|
+
t && e.target instanceof Node && !l(t, e.target) && p(t);
|
|
32
|
+
}, h = /* @__PURE__ */ new WeakSet(), g = /* @__PURE__ */ new WeakSet(), _ = (e, t) => {
|
|
33
|
+
let n = u(e, !1), r = n.indexOf(document.activeElement);
|
|
34
|
+
(!n.length || r < 0 || (t.shiftKey ? r === 0 : r === n.length - 1)) && (t.preventDefault(), (t.shiftKey ? n.at(-1) || e.panel : n[0] || e.panel).focus());
|
|
35
|
+
}, v = (e) => {
|
|
36
|
+
let t = a();
|
|
37
|
+
if (t && (e.key === "Escape" && o(t) && h.add(e), e.key === "Tab")) {
|
|
38
|
+
if (e.target instanceof Node && s(t).some((t) => t.contains(e.target))) {
|
|
39
|
+
g.add(e);
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
_(t, e);
|
|
43
|
+
}
|
|
44
|
+
}, y = (e) => {
|
|
45
|
+
if (e.key === "Tab" && g.has(e) && !e.defaultPrevented) {
|
|
46
|
+
let t = a();
|
|
47
|
+
t && _(t, e);
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
if (e.key !== "Escape" || e.defaultPrevented || h.has(e)) return;
|
|
51
|
+
let t = a();
|
|
52
|
+
t && (e.preventDefault(), t.close());
|
|
53
|
+
};
|
|
54
|
+
function b(t, i, o, s) {
|
|
55
|
+
let c = {
|
|
56
|
+
panel: t,
|
|
57
|
+
overlay: i,
|
|
58
|
+
trigger: o,
|
|
59
|
+
close: s,
|
|
60
|
+
existing: new Set(document.body.children)
|
|
61
|
+
};
|
|
62
|
+
return e.length || (n = document.body.style.overflow, document.body.style.overflow = "hidden", document.addEventListener("focusin", m), document.addEventListener("keydown", v, !0), window.addEventListener("keydown", y), r = new MutationObserver(f), r.observe(document.body, {
|
|
63
|
+
childList: !0,
|
|
64
|
+
subtree: !0,
|
|
65
|
+
attributes: !0,
|
|
66
|
+
attributeFilter: [
|
|
67
|
+
"aria-expanded",
|
|
68
|
+
"aria-controls",
|
|
69
|
+
"aria-haspopup",
|
|
70
|
+
"role",
|
|
71
|
+
"id"
|
|
72
|
+
]
|
|
73
|
+
})), e.push(c), l(c, document.activeElement) || p(c), f(), () => {
|
|
74
|
+
let t = a() === c;
|
|
75
|
+
e.splice(e.indexOf(c), 1), f(), e.length || (r?.disconnect(), document.body.style.overflow = n, document.removeEventListener("focusin", m), document.removeEventListener("keydown", v, !0), window.removeEventListener("keydown", y)), t && (o?.isConnected && !o.closest("[inert]") ? o.focus({ preventScroll: !0 }) : a() && p(a()));
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
//#endregion
|
|
79
|
+
export { b as mountFocusScope };
|
|
80
|
+
|
|
81
|
+
//# sourceMappingURL=focusScope.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"focusScope.js","names":[],"sources":["../../../src/components/Modal/focusScope.ts"],"sourcesContent":["// Only the top Modal owns focus and background isolation. Keep original attributes\n// so nested modals and pre-existing inert/aria-hidden regions restore correctly.\ntype Scope = { panel: HTMLElement; overlay: HTMLElement; trigger: HTMLElement | null; close: () => void; existing: Set<Element> };\nconst scopes: Scope[] = [];\nconst locked = new Map<HTMLElement, { inert: boolean; hidden: string | null }>();\nlet overflow = '';\nlet observer: MutationObserver | undefined;\nconst focusable = 'button, a[href], input, select, textarea, [tabindex], [contenteditable=\"true\"]';\nconst top = () => scopes[scopes.length - 1];\nconst expanded = (scope: Scope) => !!scope.panel.querySelector('[role=\"combobox\"][aria-expanded=\"true\"]');\nconst linkedMenus = (scope: Scope): HTMLElement[] => {\n const menus = new Set<HTMLElement>();\n for (const trigger of scope.panel.querySelectorAll('[aria-haspopup=\"menu\"][aria-expanded=\"true\"][aria-controls]')) {\n for (const id of trigger.getAttribute('aria-controls')!.split(/\\s+/)) {\n const menu = document.getElementById(id);\n if (menu?.parentElement === document.body && menu.getAttribute('role') === 'menu') menus.add(menu);\n }\n }\n return [...menus];\n};\nconst roots = (scope: Scope): HTMLElement[] => {\n // Select currently portals an unlinked listbox directly to body. Only admit\n // new listboxes while a combobox in this modal is expanded, not arbitrary portals.\n const portals = expanded(scope) ? Array.from(document.body.children).filter(element =>\n !scope.existing.has(element) && element.matches('[role=\"listbox\"]')) as HTMLElement[] : [];\n return [scope.panel, ...portals, ...linkedMenus(scope)];\n};\nconst contains = (scope: Scope, node: Node) => roots(scope).some(root => root.contains(node));\nconst candidates = (scope: Scope, includeMenus = true) => roots(scope)\n .filter(root => includeMenus || root === scope.panel || root.getAttribute('role') !== 'menu')\n .flatMap(root => Array.from(root.querySelectorAll<HTMLElement>(focusable)))\n .filter(element => element.tabIndex >= 0 && !element.matches(':disabled') && !element.closest('[inert]') && element.getClientRects().length > 0 && getComputedStyle(element).visibility !== 'hidden');\nconst restoreBackground = () => {\n locked.forEach((value, element) => {\n element.inert = value.inert;\n if (value.hidden === null) element.removeAttribute('aria-hidden');\n else element.setAttribute('aria-hidden', value.hidden);\n });\n locked.clear();\n};\nconst isolate = () => {\n restoreBackground();\n const scope = top();\n if (!scope) return;\n const allowed = [scope.overlay, ...roots(scope)];\n for (const child of Array.from(document.body.children)) {\n if (!(child instanceof HTMLElement) || allowed.includes(child)) continue;\n locked.set(child, { inert: child.inert, hidden: child.getAttribute('aria-hidden') });\n child.inert = true;\n child.setAttribute('aria-hidden', 'true');\n }\n};\nconst focusInside = (scope: Scope) => (candidates(scope)[0] || scope.panel).focus({ preventScroll: true });\nconst onFocus = (event: FocusEvent) => {\n const scope = top();\n if (scope && event.target instanceof Node && !contains(scope, event.target)) focusInside(scope);\n};\nconst selectEscapes = new WeakSet<KeyboardEvent>();\nconst menuTabs = new WeakSet<KeyboardEvent>();\nconst trapTab = (scope: Scope, event: KeyboardEvent) => {\n // Menu items use roving focus, not the dialog's sequential tab order.\n const items = candidates(scope, false);\n const index = items.indexOf(document.activeElement as HTMLElement);\n if (!items.length || index < 0 || (event.shiftKey ? index === 0 : index === items.length - 1)) {\n event.preventDefault();\n (event.shiftKey ? items.at(-1) || scope.panel : items[0] || scope.panel).focus();\n }\n};\nconst onKeyCapture = (event: KeyboardEvent) => {\n const scope = top();\n if (!scope) return;\n if (event.key === 'Escape' && expanded(scope)) selectEscapes.add(event);\n if (event.key !== 'Tab') return;\n if (event.target instanceof Node && linkedMenus(scope).some(menu => menu.contains(event.target as Node))) {\n // ButtonMenu closes and returns focus to its trigger during bubbling.\n // Only then can the dialog decide whether native Tab needs to wrap.\n menuTabs.add(event);\n return;\n }\n trapTab(scope, event);\n};\nconst onKey = (event: KeyboardEvent) => {\n if (event.key === 'Tab' && menuTabs.has(event) && !event.defaultPrevented) {\n const scope = top();\n if (scope) trapTab(scope, event);\n return;\n }\n if (event.key !== 'Escape' || event.defaultPrevented || selectEscapes.has(event)) return;\n const scope = top();\n if (scope) { event.preventDefault(); scope.close(); }\n};\nexport function mountFocusScope(panel: HTMLElement, overlay: HTMLElement, trigger: HTMLElement | null, close: () => void) {\n const scope: Scope = { panel, overlay, trigger, close, existing: new Set(document.body.children) };\n if (!scopes.length) {\n overflow = document.body.style.overflow;\n document.body.style.overflow = 'hidden';\n document.addEventListener('focusin', onFocus);\n document.addEventListener('keydown', onKeyCapture, true);\n window.addEventListener('keydown', onKey);\n observer = new MutationObserver(isolate);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['aria-expanded', 'aria-controls', 'aria-haspopup', 'role', 'id'] });\n }\n scopes.push(scope);\n // React autoFocus has already run during commit; don't replace the safe action.\n if (!contains(scope, document.activeElement!)) focusInside(scope);\n isolate();\n return () => {\n const wasTop = top() === scope;\n scopes.splice(scopes.indexOf(scope), 1);\n isolate();\n if (!scopes.length) {\n observer?.disconnect();\n document.body.style.overflow = overflow;\n document.removeEventListener('focusin', onFocus);\n document.removeEventListener('keydown', onKeyCapture, true);\n window.removeEventListener('keydown', onKey);\n }\n if (wasTop) {\n if (trigger?.isConnected && !trigger.closest('[inert]')) trigger.focus({ preventScroll: true });\n else if (top()) focusInside(top());\n }\n };\n}\n"],"mappings":"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"}
|
|
@@ -23,9 +23,12 @@ export type ModalProps = {
|
|
|
23
23
|
/** 是否显示右上角关闭按钮(默认 true) */
|
|
24
24
|
showClose?: boolean;
|
|
25
25
|
className?: string;
|
|
26
|
+
'aria-label'?: string;
|
|
27
|
+
'aria-labelledby'?: string;
|
|
28
|
+
'aria-describedby'?: string;
|
|
26
29
|
};
|
|
27
30
|
/**
|
|
28
31
|
* 轻量模态框:遮罩 + 居中面板,支持 Esc 关闭、遮罩点击关闭与滚动锁定。
|
|
29
32
|
*/
|
|
30
|
-
declare const Modal: ({ open, onClose, title, description, children, footer, size, width, height, closeOnOverlay, showClose, className, }: ModalProps) => React.
|
|
33
|
+
declare const Modal: ({ open, onClose, title, description, children, footer, size, width, height, closeOnOverlay, showClose, className, 'aria-label': ariaLabel, 'aria-labelledby': labelledBy, 'aria-describedby': describedBy, }: ModalProps) => React.ReactPortal | null;
|
|
31
34
|
export default Modal;
|
|
@@ -1,65 +1,70 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { mountFocusScope as e } from "./focusScope.js";
|
|
2
|
+
import { useId as t, useLayoutEffect as n, useRef as r } from "react";
|
|
3
|
+
import { jsx as i, jsxs as a } from "react/jsx-runtime";
|
|
4
|
+
import { createPortal as o } from "react-dom";
|
|
3
5
|
//#region src/components/Modal/index.tsx
|
|
4
|
-
var
|
|
6
|
+
var s = {
|
|
5
7
|
sm: "max-w-sm",
|
|
6
8
|
md: "max-w-lg",
|
|
7
9
|
lg: "max-w-2xl",
|
|
8
10
|
xl: "max-w-5xl",
|
|
9
11
|
full: "max-w-[95vw]"
|
|
10
|
-
},
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
}, [a, o]), !a) return null;
|
|
22
|
-
let _ = f !== void 0, v = {
|
|
23
|
-
width: _ ? i(f) : void 0,
|
|
24
|
-
maxWidth: _ ? "95vw" : void 0,
|
|
25
|
-
height: i(p),
|
|
12
|
+
}, c = (e) => typeof e == "number" ? `${e}px` : e, l = ({ open: l, onClose: u, title: d, description: f, children: p, footer: m, size: h = "md", width: g, height: _, closeOnOverlay: v = !0, showClose: y = !0, className: b = "", "aria-label": x, "aria-labelledby": S, "aria-describedby": C }) => {
|
|
13
|
+
let w = t(), T = t(), E = r(null), D = r(null), O = r(null), k = r(!1), A = r(u);
|
|
14
|
+
if (l && !k.current && typeof document < "u" && (O.current = document.activeElement), k.current = l, n(() => {
|
|
15
|
+
A.current = u;
|
|
16
|
+
}), n(() => {
|
|
17
|
+
if (l && E.current && D.current) return e(E.current, D.current, O.current, () => A.current());
|
|
18
|
+
}, [l]), !l || typeof document > "u") return null;
|
|
19
|
+
let j = g !== void 0, M = {
|
|
20
|
+
width: j ? c(g) : void 0,
|
|
21
|
+
maxWidth: j ? "95vw" : void 0,
|
|
22
|
+
height: c(_),
|
|
26
23
|
maxHeight: "92vh"
|
|
27
|
-
},
|
|
28
|
-
return /* @__PURE__ */
|
|
24
|
+
}, N = j ? "" : s[h], P = _ === void 0 ? "max-h-[70vh] overflow-y-auto px-5 py-4" : "min-h-0 flex-1 overflow-y-auto px-5 py-4";
|
|
25
|
+
return o(/* @__PURE__ */ a("div", {
|
|
26
|
+
ref: D,
|
|
29
27
|
className: "fixed inset-0 z-50 flex items-center justify-center bg-black/50 p-4",
|
|
30
|
-
children: [/* @__PURE__ */
|
|
28
|
+
children: [/* @__PURE__ */ i("div", {
|
|
31
29
|
className: "absolute inset-0",
|
|
32
|
-
onClick:
|
|
30
|
+
onClick: v ? u : void 0,
|
|
33
31
|
"aria-hidden": !0
|
|
34
|
-
}), /* @__PURE__ */
|
|
32
|
+
}), /* @__PURE__ */ a("div", {
|
|
33
|
+
ref: E,
|
|
35
34
|
role: "dialog",
|
|
35
|
+
tabIndex: -1,
|
|
36
36
|
"aria-modal": "true",
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
"aria-label": x,
|
|
38
|
+
"aria-labelledby": S ?? (d && !x ? w : void 0),
|
|
39
|
+
"aria-describedby": C ?? (f ? T : void 0),
|
|
40
|
+
className: `dishui-modal card relative flex w-full min-w-0 flex-col rounded-xl border border-base-300 bg-base-100 text-body leading-5 text-base-content shadow-md ${N} ${b}`.trim(),
|
|
41
|
+
style: M,
|
|
39
42
|
children: [
|
|
40
|
-
(
|
|
41
|
-
className: "flex shrink-0 items-start justify-between gap-3 border-b border-base-300 px-5 py-3
|
|
42
|
-
children: [/* @__PURE__ */
|
|
43
|
+
(d || f || y) && /* @__PURE__ */ a("div", {
|
|
44
|
+
className: "flex shrink-0 items-start justify-between gap-3 border-b border-base-300 px-5 py-3",
|
|
45
|
+
children: [/* @__PURE__ */ a("div", {
|
|
43
46
|
className: "min-w-0",
|
|
44
|
-
children: [
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
47
|
+
children: [d && /* @__PURE__ */ i("h3", {
|
|
48
|
+
id: w,
|
|
49
|
+
className: "break-words text-body font-semibold text-base-content",
|
|
50
|
+
children: d
|
|
51
|
+
}), f && /* @__PURE__ */ i("p", {
|
|
52
|
+
id: T,
|
|
53
|
+
className: "mt-1 text-body-sm leading-5 text-base-content/70",
|
|
54
|
+
children: f
|
|
50
55
|
})]
|
|
51
|
-
}),
|
|
56
|
+
}), y && /* @__PURE__ */ i("button", {
|
|
52
57
|
type: "button",
|
|
53
|
-
onClick:
|
|
58
|
+
onClick: u,
|
|
54
59
|
"aria-label": "Close",
|
|
55
|
-
className: "shrink-0 rounded-md p-1 text-base-content/
|
|
56
|
-
children: /* @__PURE__ */
|
|
60
|
+
className: "shrink-0 rounded-md p-1 text-base-content/70 transition-colors duration-150 motion-reduce:transition-none hover:bg-base-200 hover:text-base-content focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-current",
|
|
61
|
+
children: /* @__PURE__ */ i("svg", {
|
|
57
62
|
className: "h-4 w-4",
|
|
58
63
|
fill: "none",
|
|
59
64
|
viewBox: "0 0 24 24",
|
|
60
65
|
stroke: "currentColor",
|
|
61
66
|
strokeWidth: 2,
|
|
62
|
-
children: /* @__PURE__ */
|
|
67
|
+
children: /* @__PURE__ */ i("path", {
|
|
63
68
|
strokeLinecap: "round",
|
|
64
69
|
strokeLinejoin: "round",
|
|
65
70
|
d: "M6 18L18 6M6 6l12 12"
|
|
@@ -67,19 +72,19 @@ var r = {
|
|
|
67
72
|
})
|
|
68
73
|
})]
|
|
69
74
|
}),
|
|
70
|
-
/* @__PURE__ */
|
|
71
|
-
className:
|
|
72
|
-
children:
|
|
75
|
+
/* @__PURE__ */ i("div", {
|
|
76
|
+
className: P,
|
|
77
|
+
children: p
|
|
73
78
|
}),
|
|
74
|
-
|
|
75
|
-
className: "flex shrink-0 justify-end gap-2 border-t border-base-300 px-5 py-3
|
|
76
|
-
children:
|
|
79
|
+
m && /* @__PURE__ */ i("div", {
|
|
80
|
+
className: "flex shrink-0 flex-wrap justify-end gap-2 border-t border-base-300 px-5 py-3",
|
|
81
|
+
children: m
|
|
77
82
|
})
|
|
78
83
|
]
|
|
79
84
|
})]
|
|
80
|
-
});
|
|
85
|
+
}), document.body);
|
|
81
86
|
};
|
|
82
87
|
//#endregion
|
|
83
|
-
export {
|
|
88
|
+
export { l as default };
|
|
84
89
|
|
|
85
90
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../../src/components/Modal/index.tsx"],"sourcesContent":["import React, {
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../../src/components/Modal/index.tsx"],"sourcesContent":["import React, { useId, useLayoutEffect, useRef } from 'react';\nimport { createPortal } from 'react-dom';\nimport { mountFocusScope } from './focusScope';\n\nexport type ModalProps = {\n /** 是否打开 */\n open: boolean;\n /** 关闭回调(遮罩点击 / Esc / 关闭按钮触发) */\n onClose: () => void;\n /** 标题 */\n title?: React.ReactNode;\n /** 标题下的说明文字 */\n description?: React.ReactNode;\n /** 正文内容 */\n children?: React.ReactNode;\n /** 底部操作区(默认右对齐) */\n footer?: React.ReactNode;\n /** 尺寸(预设):sm / md / lg / xl / full */\n size?: 'sm' | 'md' | 'lg' | 'xl' | 'full';\n /** 自定义宽度:支持百分比/像素等 CSS 长度(如 \"80%\"、640)。优先于 size。 */\n width?: number | string;\n /** 自定义高度:支持百分比/像素等 CSS 长度(如 \"80%\"、480)。 */\n height?: number | string;\n /** 点击遮罩是否关闭(默认 true) */\n closeOnOverlay?: boolean;\n /** 是否显示右上角关闭按钮(默认 true) */\n showClose?: boolean;\n className?: string;\n 'aria-label'?: string;\n 'aria-labelledby'?: string;\n 'aria-describedby'?: string;\n};\n\nconst SIZE_CLASS: Record<NonNullable<ModalProps['size']>, string> = {\n sm: 'max-w-sm',\n md: 'max-w-lg',\n lg: 'max-w-2xl',\n xl: 'max-w-5xl',\n full: 'max-w-[95vw]',\n};\n\nconst toCssSize = (value: number | string | undefined): string | undefined =>\n typeof value === 'number' ? `${value}px` : value;\n\n/**\n * 轻量模态框:遮罩 + 居中面板,支持 Esc 关闭、遮罩点击关闭与滚动锁定。\n */\nconst Modal = ({\n open,\n onClose,\n title,\n description,\n children,\n footer,\n size = 'md',\n width,\n height,\n closeOnOverlay = true,\n showClose = true,\n className = '',\n 'aria-label': ariaLabel,\n 'aria-labelledby': labelledBy,\n 'aria-describedby': describedBy,\n}: ModalProps) => {\n const titleId = useId();\n const descriptionId = useId();\n const panel = useRef<HTMLDivElement>(null);\n const overlay = useRef<HTMLDivElement>(null);\n const trigger = useRef<HTMLElement | null>(null);\n const wasOpen = useRef(false);\n const close = useRef(onClose);\n // Capture before React commits autoFocus inside the newly opened portal.\n if (open && !wasOpen.current && typeof document !== 'undefined') trigger.current = document.activeElement as HTMLElement | null;\n wasOpen.current = open;\n useLayoutEffect(() => { close.current = onClose; });\n useLayoutEffect(() => {\n if (!open || !panel.current || !overlay.current) return;\n return mountFocusScope(panel.current, overlay.current, trigger.current, () => close.current());\n }, [open]);\n\n if (!open || typeof document === 'undefined') return null;\n\n // 自定义宽高:传入时优先于 size 预设;支持百分比。\n const hasCustomWidth = width !== undefined;\n const panelStyle: React.CSSProperties = {\n width: hasCustomWidth ? toCssSize(width) : undefined,\n maxWidth: hasCustomWidth ? '95vw' : undefined,\n height: toCssSize(height),\n maxHeight: '92vh',\n };\n // 面板尺寸类:未自定义宽度时才应用 max-w-* 预设。\n const sizeClass = hasCustomWidth ? '' : SIZE_CLASS[size];\n // 正文区:固定高度时自适应充满并内部滚动;否则限制最大高度。\n const bodyClass = height !== undefined\n ? 'min-h-0 flex-1 overflow-y-auto px-5 py-4'\n : 'max-h-[70vh] overflow-y-auto px-5 py-4';\n\n return createPortal(\n <div ref={overlay} className=\"fixed inset-0 z-50 flex items-center justify-center bg-black/50 p-4\">\n <div\n className=\"absolute inset-0\"\n onClick={closeOnOverlay ? onClose : undefined}\n aria-hidden\n />\n <div\n ref={panel}\n role=\"dialog\"\n tabIndex={-1}\n aria-modal=\"true\"\n aria-label={ariaLabel}\n aria-labelledby={labelledBy ?? (title && !ariaLabel ? titleId : undefined)}\n aria-describedby={describedBy ?? (description ? descriptionId : undefined)}\n className={`dishui-modal card relative flex w-full min-w-0 flex-col rounded-xl border border-base-300 bg-base-100 text-body leading-5 text-base-content shadow-md ${sizeClass} ${className}`.trim()}\n style={panelStyle}\n >\n {(title || description || showClose) && (\n <div className=\"flex shrink-0 items-start justify-between gap-3 border-b border-base-300 px-5 py-3\">\n <div className=\"min-w-0\">\n {title && (\n <h3 id={titleId} className=\"break-words text-body font-semibold text-base-content\">\n {title}\n </h3>\n )}\n {description && (\n <p id={descriptionId} className=\"mt-1 text-body-sm leading-5 text-base-content/70\">{description}</p>\n )}\n </div>\n {showClose && (\n <button\n type=\"button\"\n onClick={onClose}\n aria-label=\"Close\"\n className=\"shrink-0 rounded-md p-1 text-base-content/70 transition-colors duration-150 motion-reduce:transition-none hover:bg-base-200 hover:text-base-content focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-current\"\n >\n <svg\n className=\"h-4 w-4\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth={2}\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M6 18L18 6M6 6l12 12\"\n />\n </svg>\n </button>\n )}\n </div>\n )}\n <div className={bodyClass}>{children}</div>\n {footer && (\n <div className=\"flex shrink-0 flex-wrap justify-end gap-2 border-t border-base-300 px-5 py-3\">\n {footer}\n </div>\n )}\n </div>\n </div>,\n document.body,\n );\n};\n\nexport default Modal;\n"],"mappings":";;;;;AAiCA,IAAM,IAA8D;CAChE,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,MAAM;AACV,GAEM,KAAa,MACf,OAAO,KAAU,WAAW,GAAG,EAAM,MAAM,GAKzC,KAAS,EACX,SACA,YACA,UACA,gBACA,aACA,WACA,UAAO,MACP,UACA,WACA,oBAAiB,IACjB,eAAY,IACZ,eAAY,IACZ,cAAc,GACd,mBAAmB,GACnB,oBAAoB,QACN;CACd,IAAM,IAAU,EAAM,GAChB,IAAgB,EAAM,GACtB,IAAQ,EAAuB,IAAI,GACnC,IAAU,EAAuB,IAAI,GACrC,IAAU,EAA2B,IAAI,GACzC,IAAU,EAAO,EAAK,GACtB,IAAQ,EAAO,CAAO;CAU5B,IARI,KAAQ,CAAC,EAAQ,WAAW,OAAO,WAAa,QAAa,EAAQ,UAAU,SAAS,gBAC5F,EAAQ,UAAU,GAClB,QAAsB;EAAE,EAAM,UAAU;CAAS,CAAC,GAClD,QAAsB;EACd,IAAC,KAAS,EAAM,WAAY,EAAQ,SACxC,OAAO,EAAgB,EAAM,SAAS,EAAQ,SAAS,EAAQ,eAAe,EAAM,QAAQ,CAAC;CACjG,GAAG,CAAC,CAAI,CAAC,GAEL,CAAC,KAAQ,OAAO,WAAa,KAAa,OAAO;CAGrD,IAAM,IAAiB,MAAU,KAAA,GAC3B,IAAkC;EACpC,OAAO,IAAiB,EAAU,CAAK,IAAI,KAAA;EAC3C,UAAU,IAAiB,SAAS,KAAA;EACpC,QAAQ,EAAU,CAAM;EACxB,WAAW;CACf,GAEM,IAAY,IAAiB,KAAK,EAAW,IAE7C,IAAY,MAAW,KAAA,IAEvB,2CADA;CAGN,OAAO,EACH,kBAAC,OAAD;EAAK,KAAK;EAAS,WAAU;EAA7B,UAAA,CACI,kBAAC,OAAD;GACI,WAAU;GACV,SAAS,IAAiB,IAAU,KAAA;GACpC,eAAA;EACH,CAAA,GACD,kBAAC,OAAD;GACI,KAAK;GACL,MAAK;GACL,UAAU;GACV,cAAW;GACX,cAAY;GACZ,mBAAiB,MAAe,KAAS,CAAC,IAAY,IAAU,KAAA;GAChE,oBAAkB,MAAgB,IAAc,IAAgB,KAAA;GAChE,WAAW,yJAAyJ,EAAU,GAAG,IAAY,KAAK;GAClM,OAAO;GATX,UAAA;KAWM,KAAS,KAAe,MACtB,kBAAC,OAAD;KAAK,WAAU;KAAf,UAAA,CACI,kBAAC,OAAD;MAAK,WAAU;MAAf,UAAA,CACK,KACG,kBAAC,MAAD;OAAI,IAAI;OAAS,WAAU;OACtB,UAAA;MACD,CAAA,GAEP,KACG,kBAAC,KAAD;OAAG,IAAI;OAAe,WAAU;OAAoD,UAAA;MAAe,CAAA,CAEtG;KACJ,CAAA,GAAA,KACG,kBAAC,UAAD;MACI,MAAK;MACL,SAAS;MACT,cAAW;MACX,WAAU;MAEV,UAAA,kBAAC,OAAD;OACI,WAAU;OACV,MAAK;OACL,SAAQ;OACR,QAAO;OACP,aAAa;OAEb,UAAA,kBAAC,QAAD;QACI,eAAc;QACd,gBAAe;QACf,GAAE;OACL,CAAA;MACA,CAAA;KACD,CAAA,CAEX;;IAET,kBAAC,OAAD;KAAK,WAAW;KAAY;IAAc,CAAA;IACzC,KACG,kBAAC,OAAD;KAAK,WAAU;KACV,UAAA;IACA,CAAA;GAER;EACJ,CAAA,CAAA;CACL,CAAA,GAAA,SAAS,IACb;AACJ"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export type PageFloatProps = React.HTMLAttributes<HTMLDivElement> & {
|
|
3
|
+
title?: string;
|
|
4
|
+
collapsed?: boolean;
|
|
5
|
+
defaultCollapsed?: boolean;
|
|
6
|
+
onCollapsedChange?: (collapsed: boolean) => void;
|
|
7
|
+
defaultPosition?: {
|
|
8
|
+
x: number;
|
|
9
|
+
y: number;
|
|
10
|
+
};
|
|
11
|
+
draggable?: boolean;
|
|
12
|
+
};
|
|
13
|
+
/** Coordinates are relative to the containing Page; dragging is confined to it. */
|
|
14
|
+
export default function PageFloat({ title, collapsed, defaultCollapsed, onCollapsedChange, defaultPosition, draggable, className, style, children, ...rest }: PageFloatProps): React.JSX.Element;
|