@huibo-ui/react-antd 1.0.10 → 1.0.12
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/LICENSE +21 -0
- package/lib/components/Affix.js +1 -1
- package/lib/components/Alert.js +1 -1
- package/lib/components/Avatar.js +4 -1
- package/lib/components/BackTop.js +1 -1
- package/lib/components/Badge.js +1 -1
- package/lib/components/Breadcrumb.js +4 -2
- package/lib/components/Button.js +3 -2
- package/lib/components/Card.d.ts +14 -1
- package/lib/components/Card.js +30 -3
- package/lib/components/Checkbox.d.ts +2 -0
- package/lib/components/Checkbox.js +14 -2
- package/lib/components/Collapse.d.ts +34 -4
- package/lib/components/Collapse.js +122 -4
- package/lib/components/Descriptions.js +3 -5
- package/lib/components/Divider.d.ts +8 -0
- package/lib/components/Divider.js +38 -3
- package/lib/components/Drawer.d.ts +7 -1
- package/lib/components/Drawer.js +167 -4
- package/lib/components/Dropdown.js +1 -1
- package/lib/components/FloatButton.js +1 -1
- package/lib/components/Form.d.ts +25 -14
- package/lib/components/Form.js +315 -92
- package/lib/components/Image.js +1 -1
- package/lib/components/Input.js +25 -4
- package/lib/components/InputNumber.d.ts +1 -1
- package/lib/components/InputNumber.js +15 -1
- package/lib/components/Layout.d.ts +1 -1
- package/lib/components/Layout.js +41 -16
- package/lib/components/Menu.js +55 -11
- package/lib/components/Modal.d.ts +4 -1
- package/lib/components/Modal.js +137 -20
- package/lib/components/PageHeader.js +1 -1
- package/lib/components/Pagination.js +1 -1
- package/lib/components/Popconfirm.js +1 -1
- package/lib/components/Popover.js +1 -1
- package/lib/components/Progress.js +1 -1
- package/lib/components/Radio.d.ts +5 -3
- package/lib/components/Radio.js +24 -13
- package/lib/components/Rate.js +1 -1
- package/lib/components/Result.js +1 -1
- package/lib/components/Segmented.d.ts +5 -3
- package/lib/components/Segmented.js +4 -1
- package/lib/components/Select.js +1 -1
- package/lib/components/Slider.d.ts +9 -2
- package/lib/components/Slider.js +8 -1
- package/lib/components/Space.d.ts +2 -1
- package/lib/components/Space.js +47 -4
- package/lib/components/Spin.js +1 -1
- package/lib/components/Statistic.d.ts +1 -0
- package/lib/components/Statistic.js +5 -1
- package/lib/components/Steps.js +4 -2
- package/lib/components/Switch.d.ts +6 -0
- package/lib/components/Switch.js +15 -1
- package/lib/components/Table.js +68 -12
- package/lib/components/Tabs.js +52 -27
- package/lib/components/Tag.d.ts +1 -0
- package/lib/components/Tag.js +16 -2
- package/lib/components/TimePicker.js +1 -1
- package/lib/components/Timeline.js +9 -1
- package/lib/components/Tooltip.js +1 -1
- package/lib/components/Tree.js +2 -4
- package/lib/components/TreeSelect.d.ts +2 -0
- package/lib/components/TreeSelect.js +19 -1
- package/lib/components/Typography.js +7 -3
- package/lib/components/Upload.js +1 -1
- package/lib/components/Watermark.js +21 -1
- package/lib/components/message.js +4 -3
- package/lib/components/notification.js +3 -1
- package/package.json +5 -6
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/lib/components/Affix.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { HbAffix } from '@huibo-ui/react';
|
|
3
3
|
export function Affix(props) {
|
|
4
|
-
return _jsx(HbAffix, { top: props.offsetTop, bottom: props.offsetBottom, children: props.children });
|
|
4
|
+
return (_jsx(HbAffix, { top: props.offsetTop, bottom: props.offsetBottom, children: props.children }));
|
|
5
5
|
}
|
package/lib/components/Alert.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { HbAlert } from '@huibo-ui/react';
|
|
3
3
|
export function Alert(props) {
|
|
4
|
-
return _jsx(HbAlert, { type: props.type, title: typeof props.message === 'string' ? props.message : '', closable: props.closable, showIcon: props.showIcon ?? true, onHbClose: () => props.onClose?.(), style: props.style });
|
|
4
|
+
return (_jsx(HbAlert, { type: props.type, title: typeof props.message === 'string' ? props.message : '', closable: props.closable, showIcon: props.showIcon ?? true, onHbClose: () => props.onClose?.(), style: props.style }));
|
|
5
5
|
}
|
package/lib/components/Avatar.js
CHANGED
|
@@ -2,5 +2,8 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
2
2
|
import { HbAvatar } from '@huibo-ui/react';
|
|
3
3
|
export function Avatar(props) {
|
|
4
4
|
const sz = props.size === 'middle' ? 'default' : props.size;
|
|
5
|
-
return
|
|
5
|
+
return (
|
|
6
|
+
// antd Avatar 默认圆形;兼容层未传 shape 时显式给 circle,
|
|
7
|
+
// 否则 undefined 会覆盖 hb-avatar 的默认值,导致 class 变 --undefined(非圆)。
|
|
8
|
+
_jsx(HbAvatar, { src: props.src, size: sz, shape: props.shape ?? 'circle', style: props.style, children: props.src ? null : props.children }));
|
|
6
9
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { HbBacktop } from '@huibo-ui/react';
|
|
3
3
|
export function BackTop(props) {
|
|
4
|
-
return _jsx(HbBacktop, { visibilityHeight: props.visibilityHeight, onHbClick: () => props.onClick?.(), children: props.children });
|
|
4
|
+
return (_jsx(HbBacktop, { visibilityHeight: props.visibilityHeight, onHbClick: () => props.onClick?.(), children: props.children }));
|
|
5
5
|
}
|
package/lib/components/Badge.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { HbBadge } from '@huibo-ui/react';
|
|
3
3
|
export function Badge(props) {
|
|
4
|
-
return _jsx(HbBadge, { value: props.count ?? 0, max: props.overflowCount ?? 99, type: props.status, dot: props.dot, showZero: props.showZero, children: props.children });
|
|
4
|
+
return (_jsx(HbBadge, { value: props.count ?? 0, max: props.overflowCount ?? 99, type: props.status, dot: props.dot, showZero: props.showZero, children: props.children }));
|
|
5
5
|
}
|
|
@@ -3,8 +3,10 @@ import React from 'react';
|
|
|
3
3
|
import { HbBreadcrumb, HbBreadcrumbItem } from '@huibo-ui/react';
|
|
4
4
|
export function Breadcrumb(props) {
|
|
5
5
|
if (props.items) {
|
|
6
|
-
return _jsx(HbBreadcrumb, { separator: props.separator, children: props.items.map((item, i) => React.createElement(HbBreadcrumbItem, { key: i, href: item.href }, item.title)) });
|
|
6
|
+
return (_jsx(HbBreadcrumb, { separator: props.separator, children: props.items.map((item, i) => React.createElement(HbBreadcrumbItem, { key: i, href: item.href }, item.title)) }));
|
|
7
7
|
}
|
|
8
8
|
return _jsx(HbBreadcrumb, { children: props.children });
|
|
9
9
|
}
|
|
10
|
-
Breadcrumb.Item = function BreadcrumbItem(props) {
|
|
10
|
+
Breadcrumb.Item = function BreadcrumbItem(props) {
|
|
11
|
+
return React.createElement(HbBreadcrumbItem, props);
|
|
12
|
+
};
|
package/lib/components/Button.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { HbButton } from '@huibo-ui/react';
|
|
3
3
|
export function Button({ type, size, danger, block, loading, disabled, icon, htmlType, children, onClick, ...rest }) {
|
|
4
|
-
|
|
4
|
+
// antd danger 语义由 hb-button 的 danger prop + .hb-button--danger 样式承载
|
|
5
|
+
// (primary+danger → 红底白字;其余 → 红框红字白底,见 button.css)。
|
|
5
6
|
const huiboSize = size === 'middle' ? 'default' : size || 'default';
|
|
6
|
-
return (_jsxs(HbButton, { type:
|
|
7
|
+
return (_jsxs(HbButton, { type: (type || 'default'), danger: danger, htmlType: htmlType || 'button', size: huiboSize, disabled: disabled, loading: loading, block: block, onClick: onClick, children: [icon, children] }));
|
|
7
8
|
}
|
package/lib/components/Card.d.ts
CHANGED
|
@@ -1,11 +1,24 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* antd Card 兼容层(纯 div 实现)。
|
|
4
|
+
*
|
|
5
|
+
* 不再走 <HbCard>(Shadow DOM slot):子内容进 slot 后,bodyStyle/hoverable/loading 等
|
|
6
|
+
* 布局相关样式无法稳定穿透 Shadow DOM,且 hb-card 的圆角/内边距与 antd 存在偏差
|
|
7
|
+
* (hb-card 6px 圆角 / 16px 内边距;antd 8px / 24px)。纯 div 可精确对齐 antd 几何,
|
|
8
|
+
* children 作为真实 DOM 参与 flex 流,嵌套 <Descriptions>/<Table> 不会错乱。
|
|
9
|
+
*/
|
|
2
10
|
export declare function Card(props: {
|
|
3
11
|
title?: React.ReactNode;
|
|
4
12
|
bordered?: boolean;
|
|
5
13
|
extra?: React.ReactNode;
|
|
6
14
|
children?: React.ReactNode;
|
|
7
15
|
bodyStyle?: React.CSSProperties;
|
|
8
|
-
|
|
16
|
+
headStyle?: React.CSSProperties;
|
|
9
17
|
loading?: boolean;
|
|
10
18
|
hoverable?: boolean;
|
|
19
|
+
cover?: React.ReactNode;
|
|
20
|
+
actions?: React.ReactNode[];
|
|
21
|
+
size?: 'default' | 'small';
|
|
22
|
+
style?: React.CSSProperties;
|
|
23
|
+
className?: string;
|
|
11
24
|
}): React.JSX.Element;
|
package/lib/components/Card.js
CHANGED
|
@@ -1,5 +1,32 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* antd Card 兼容层(纯 div 实现)。
|
|
4
|
+
*
|
|
5
|
+
* 不再走 <HbCard>(Shadow DOM slot):子内容进 slot 后,bodyStyle/hoverable/loading 等
|
|
6
|
+
* 布局相关样式无法稳定穿透 Shadow DOM,且 hb-card 的圆角/内边距与 antd 存在偏差
|
|
7
|
+
* (hb-card 6px 圆角 / 16px 内边距;antd 8px / 24px)。纯 div 可精确对齐 antd 几何,
|
|
8
|
+
* children 作为真实 DOM 参与 flex 流,嵌套 <Descriptions>/<Table> 不会错乱。
|
|
9
|
+
*/
|
|
3
10
|
export function Card(props) {
|
|
4
|
-
|
|
11
|
+
const { title, bordered = true, extra, children, bodyStyle, headStyle, loading, hoverable, cover, actions, size = 'default', style, className } = props;
|
|
12
|
+
const hasHead = title !== undefined || extra !== undefined;
|
|
13
|
+
const bodyPadding = size === 'small' ? 12 : 24;
|
|
14
|
+
const headPadding = size === 'small' ? '8px 12px' : undefined;
|
|
15
|
+
return (_jsxs("div", { style: {
|
|
16
|
+
borderRadius: 8,
|
|
17
|
+
border: bordered ? '1px solid var(--hb-color-border-secondary, #f0f0f0)' : undefined,
|
|
18
|
+
background: 'var(--hb-color-bg-container, #fff)',
|
|
19
|
+
overflow: 'hidden',
|
|
20
|
+
transition: hoverable ? 'all 0.2s cubic-bezier(0.645, 0.045, 0.355, 1)' : undefined,
|
|
21
|
+
boxShadow: hoverable ? '0 1px 2px -2px rgba(0,0,0,0.16), 0 3px 6px 0 rgba(0,0,0,0.12), 0 5px 12px 4px rgba(0,0,0,0.09)' : undefined,
|
|
22
|
+
...style,
|
|
23
|
+
}, className: className, children: [cover, hasHead && (_jsxs("div", { style: {
|
|
24
|
+
display: 'flex',
|
|
25
|
+
alignItems: 'center',
|
|
26
|
+
justifyContent: 'space-between',
|
|
27
|
+
padding: headPadding ?? 'var(--hb-spacing-sm, 8px) var(--hb-spacing-lg, 24px)',
|
|
28
|
+
minHeight: 56,
|
|
29
|
+
borderBottom: '1px solid var(--hb-color-border-secondary, #f0f0f0)',
|
|
30
|
+
...headStyle,
|
|
31
|
+
}, children: [_jsx("div", { style: { display: 'flex', alignItems: 'center', fontSize: 16, fontWeight: 500, color: 'var(--hb-color-text, rgba(0,0,0,0.88))' }, children: title }), extra !== undefined && _jsx("div", { children: extra })] })), _jsx("div", { style: { padding: bodyPadding, ...bodyStyle }, children: loading ? _jsx("div", { style: { color: 'var(--hb-color-text-secondary, rgba(0,0,0,0.45))' }, children: "\u52A0\u8F7D\u4E2D..." }) : children }), actions && actions.length > 0 && (_jsx("div", { style: { display: 'flex', borderTop: '1px solid var(--hb-color-border-secondary, #f0f0f0)' }, children: actions.map((a, i) => (_jsx("div", { style: { flex: 1, textAlign: 'center', padding: '12px 0', borderRight: i < actions.length - 1 ? '1px solid var(--hb-color-border-secondary, #f0f0f0)' : undefined }, children: a }, i))) }))] }));
|
|
5
32
|
}
|
|
@@ -5,12 +5,14 @@ export declare function Checkbox(props: {
|
|
|
5
5
|
disabled?: boolean;
|
|
6
6
|
children?: React.ReactNode;
|
|
7
7
|
indeterminate?: boolean;
|
|
8
|
+
value?: any;
|
|
8
9
|
}): React.JSX.Element;
|
|
9
10
|
export declare namespace Checkbox {
|
|
10
11
|
var Group: any;
|
|
11
12
|
}
|
|
12
13
|
export declare function CheckboxGroup(props: {
|
|
13
14
|
value?: any[];
|
|
15
|
+
defaultValue?: any[];
|
|
14
16
|
onChange?: (value: any[]) => void;
|
|
15
17
|
options?: any[];
|
|
16
18
|
disabled?: boolean;
|
|
@@ -1,10 +1,22 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { HbCheckbox, HbCheckboxGroup } from '@huibo-ui/react';
|
|
3
3
|
export function Checkbox(props) {
|
|
4
|
-
return _jsx(HbCheckbox, { checked: props.checked ?? false, disabled: props.disabled, label: props.children, onHbChange: (e) => props.onChange?.({ target: { checked: e.detail } }), children: props.children });
|
|
4
|
+
return (_jsx(HbCheckbox, { checked: props.checked ?? false, indeterminate: props.indeterminate, disabled: props.disabled, label: props.children, onHbChange: (e) => props.onChange?.({ target: { checked: e.detail } }), children: props.children }));
|
|
5
5
|
}
|
|
6
6
|
export function CheckboxGroup(props) {
|
|
7
|
-
|
|
7
|
+
// hb-checkbox-group 没有 options prop(只渲染 slot 子元素)。故 options 模式下,
|
|
8
|
+
// 兼容层自己把 options 渲染成 <HbCheckbox> 子元素传入,对齐 antd <Checkbox.Group options>。
|
|
9
|
+
// children 模式(<Checkbox.Group><Checkbox/></Checkbox.Group>)则直接透传。
|
|
10
|
+
const options = props.options;
|
|
11
|
+
return (_jsx(HbCheckboxGroup, { modelValue: props.value ?? props.defaultValue ?? [], disabled: props.disabled, onHbChange: (e) => props.onChange?.(e.detail), children: options && options.length > 0
|
|
12
|
+
? options.map((o, i) => {
|
|
13
|
+
const isObj = typeof o !== 'string';
|
|
14
|
+
const label = isObj ? o.label : o;
|
|
15
|
+
const val = isObj ? o.value : o;
|
|
16
|
+
const dis = isObj ? o.disabled : false;
|
|
17
|
+
return _jsx(HbCheckbox, { label: label, value: val, disabled: dis || props.disabled }, i);
|
|
18
|
+
})
|
|
19
|
+
: props.children }));
|
|
8
20
|
}
|
|
9
21
|
// antd 静态子组件:Checkbox.Group
|
|
10
22
|
Checkbox.Group = CheckboxGroup;
|
|
@@ -1,11 +1,41 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
/**
|
|
3
|
+
* antd Collapse 兼容层(纯 div 实现)。
|
|
4
|
+
*
|
|
5
|
+
* 不再走 <HbCollapse>(Shadow DOM slot):面板内容进 slot 后,嵌套 <Table>/<Form>
|
|
6
|
+
* 的布局会受 ::slotted 干扰。纯 div 自渲染折叠头/体,children 作为真实 DOM,
|
|
7
|
+
* 嵌套复杂内容(表格、表单、描述列表)布局稳定。
|
|
8
|
+
*
|
|
9
|
+
* 支持两种 antd 写法:
|
|
10
|
+
* 1) items 数组:items={[{key,label,children,disabled}]}
|
|
11
|
+
* 2) <Collapse.Panel key="x" header="..">子内容</Collapse.Panel>
|
|
12
|
+
*
|
|
13
|
+
* 注意:React 会吞掉 key prop(不进 props),故 Panel 自己渲染并通过 React key
|
|
14
|
+
* 标识(Collapse 用 child.key 作为面板 key),与 antd 的 `<Panel key>` 语义一致。
|
|
15
|
+
*/
|
|
16
|
+
export interface CollapseProps {
|
|
17
|
+
activeKey?: string[] | string | number;
|
|
18
|
+
defaultActiveKey?: string[] | string;
|
|
5
19
|
accordion?: boolean;
|
|
20
|
+
onChange?: (key: string[]) => void;
|
|
21
|
+
bordered?: boolean;
|
|
22
|
+
ghost?: boolean;
|
|
23
|
+
items?: Array<{
|
|
24
|
+
key?: string | number;
|
|
25
|
+
label?: React.ReactNode;
|
|
26
|
+
children?: React.ReactNode;
|
|
27
|
+
disabled?: boolean;
|
|
28
|
+
forceRender?: boolean;
|
|
29
|
+
showArrow?: boolean;
|
|
30
|
+
}>;
|
|
6
31
|
children?: React.ReactNode;
|
|
7
32
|
style?: React.CSSProperties;
|
|
8
|
-
|
|
33
|
+
className?: string;
|
|
34
|
+
expandIcon?: (p: {
|
|
35
|
+
isActive?: boolean;
|
|
36
|
+
}) => React.ReactNode;
|
|
37
|
+
}
|
|
38
|
+
export declare function Collapse(props: CollapseProps): React.JSX.Element;
|
|
9
39
|
export declare namespace Collapse {
|
|
10
40
|
var Panel: any;
|
|
11
41
|
}
|
|
@@ -1,7 +1,125 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import React from 'react';
|
|
3
|
-
|
|
3
|
+
function toArray(val) {
|
|
4
|
+
if (val === undefined || val === null)
|
|
5
|
+
return [];
|
|
6
|
+
if (Array.isArray(val))
|
|
7
|
+
return val.map(String);
|
|
8
|
+
return [String(val)];
|
|
9
|
+
}
|
|
10
|
+
const CollapseContext = React.createContext({ activeKeys: [], toggle: () => { } });
|
|
11
|
+
/**
|
|
12
|
+
* 折叠体:对齐 antd Collapse 的展开/收起高度动画(修复 #16-17)。
|
|
13
|
+
*
|
|
14
|
+
* 修复前 body 用 display:none/block 硬切,无动画。这里测量真实 scrollHeight,
|
|
15
|
+
* 对 height + opacity 做过渡:展开时 height:0→scrollHeight,收起时反向,
|
|
16
|
+
* 动画结束后释放 height(变 auto)以适应内容自适应高度。
|
|
17
|
+
*
|
|
18
|
+
* 实现要点(rc-motion 思路的轻量版):
|
|
19
|
+
* - 展开:mount body(display:block, height:0),下一帧测 scrollHeight 设为该值触发过渡,
|
|
20
|
+
* 过渡结束清 height:auto。
|
|
21
|
+
* - 收起:从当前 scrollHeight 过渡到 0,结束后若该面板已彻底不用可卸载(这里保持挂载、display:none)。
|
|
22
|
+
* - forceRender:非 active 也挂载(display:none + height:0),保证首次展开有可测高度。
|
|
23
|
+
*/
|
|
24
|
+
/**
|
|
25
|
+
* 折叠体:对齐 antd Collapse 的展开/收起高度动画(修复 #16-17)。
|
|
26
|
+
*
|
|
27
|
+
* 用 CSS grid-template-rows 0fr→1fr 技巧动画到「内容自适应高度」,
|
|
28
|
+
* 无需 JS 测量 scrollHeight、可逆:
|
|
29
|
+
* - 外层 display:grid + grid-template-rows(active 时 1fr,否则 0fr)+ transition;
|
|
30
|
+
* - 内层 overflow:hidden + min-height:0(grid 子项默认 min-height:auto 会撑开,需显式 0)。
|
|
31
|
+
* 兼容性:grid-template-rows 过渡在现代浏览器(Chrome 107+/Safari 16+/Firefox 66+)支持。
|
|
32
|
+
*
|
|
33
|
+
* 为保证「展开」时也有动画,PanelBody 在收起态也保持挂载(grid 0fr + overflow:hidden 隐藏内容),
|
|
34
|
+
* 这样 active 由 false→true 时 grid-template-rows 从 0fr 过渡到 1fr。代价是收起态内容仍在 DOM 中
|
|
35
|
+
* (对齐 antd keep-alive / forceRender 行为,对 Collapse 面板内容可接受)。
|
|
36
|
+
*/
|
|
37
|
+
function PanelBody({ active, children }) {
|
|
38
|
+
return (_jsx("div", { style: {
|
|
39
|
+
display: 'grid',
|
|
40
|
+
gridTemplateRows: active ? '1fr' : '0fr',
|
|
41
|
+
opacity: active ? 1 : 0,
|
|
42
|
+
transition: 'grid-template-rows 0.3s cubic-bezier(0.645, 0.045, 0.355, 1), opacity 0.3s',
|
|
43
|
+
}, children: _jsx("div", { style: { overflow: 'hidden', minHeight: 0 }, children: _jsx("div", { style: { padding: 16 }, children: children }) }) }));
|
|
44
|
+
}
|
|
45
|
+
function DefaultArrow() {
|
|
46
|
+
return (_jsx("svg", { width: "10", height: "10", viewBox: "0 0 1024 1024", fill: "currentColor", "aria-hidden": "true", children: _jsx("path", { d: "M765.7 486.8L314.9 134.7c-5.3-4.1-13-.3-13 6.4v75.5c0 4.9 2.3 9.6 6.2 12.6l361 280.5-361 280.5c-3.9 3-6.2 7.7-6.2 12.6V883c0 6.7 7.7 10.5 13 6.4l450.8-352.1c5-3.9 5-11.4 0-15.3z" }) }));
|
|
47
|
+
}
|
|
48
|
+
function PanelRender({ panelKey, isFirst }) {
|
|
49
|
+
// 读取自身由 cloneElement 注入的 header/children/disabled 等其余 props
|
|
50
|
+
return _jsx(PanelInner, { panelKey: panelKey, isFirst: isFirst });
|
|
51
|
+
}
|
|
52
|
+
/** 把单个面板渲染为折叠头 + 展开体。 */
|
|
53
|
+
function PanelInner({ panelKey, isFirst, header, children, disabled, forceRender, showArrow = true }) {
|
|
54
|
+
const ctx = React.useContext(CollapseContext);
|
|
55
|
+
const isActive = ctx.activeKeys.includes(panelKey);
|
|
56
|
+
return (_jsxs("div", { style: {
|
|
57
|
+
// antd 每个 panel 项白底,靠 border 分隔(外层 Collapse 是浅灰底)。
|
|
58
|
+
background: '#fff',
|
|
59
|
+
borderBottom: '1px solid var(--hb-color-border-secondary, #f0f0f0)',
|
|
60
|
+
borderTop: isFirst ? '1px solid var(--hb-color-border-secondary, #f0f0f0)' : undefined,
|
|
61
|
+
}, children: [_jsxs("button", { type: "button", disabled: disabled, onClick: () => ctx.toggle(panelKey, disabled), style: {
|
|
62
|
+
display: 'flex',
|
|
63
|
+
alignItems: 'center',
|
|
64
|
+
width: '100%',
|
|
65
|
+
padding: '12px 16px',
|
|
66
|
+
border: 'none',
|
|
67
|
+
background: 'none',
|
|
68
|
+
textAlign: 'left',
|
|
69
|
+
cursor: disabled ? 'not-allowed' : 'pointer',
|
|
70
|
+
color: 'var(--hb-color-text, rgba(0,0,0,0.88))',
|
|
71
|
+
fontSize: 14,
|
|
72
|
+
fontWeight: 500,
|
|
73
|
+
opacity: disabled ? 0.5 : 1,
|
|
74
|
+
}, children: [showArrow && (_jsx("span", { style: { display: 'inline-flex', marginRight: 12, transition: 'transform 0.2s', transform: isActive ? 'rotate(90deg)' : 'rotate(0deg)' }, children: ctx.expandIcon ? ctx.expandIcon({ isActive }) : _jsx(DefaultArrow, {}) })), _jsx("span", { style: { flex: 1 }, children: header })] }), _jsx(PanelBody, { active: isActive, children: children })] }));
|
|
75
|
+
}
|
|
4
76
|
export function Collapse(props) {
|
|
5
|
-
|
|
77
|
+
const { activeKey, defaultActiveKey, accordion, onChange, bordered = true, ghost, items, children, style, className, expandIcon } = props;
|
|
78
|
+
const isControlled = activeKey !== undefined;
|
|
79
|
+
const [internal, setInternal] = React.useState(() => toArray(defaultActiveKey ?? (isControlled ? undefined : [])));
|
|
80
|
+
const activeKeys = isControlled ? toArray(activeKey) : internal;
|
|
81
|
+
const toggle = (key, disabled) => {
|
|
82
|
+
if (disabled)
|
|
83
|
+
return;
|
|
84
|
+
let next;
|
|
85
|
+
if (accordion) {
|
|
86
|
+
next = activeKeys.includes(key) ? [] : [key];
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
next = activeKeys.includes(key) ? activeKeys.filter(k => k !== key) : [...activeKeys, key];
|
|
90
|
+
}
|
|
91
|
+
if (!isControlled)
|
|
92
|
+
setInternal(next);
|
|
93
|
+
onChange?.(next);
|
|
94
|
+
};
|
|
95
|
+
const ctxValue = React.useMemo(() => ({ activeKeys, toggle, expandIcon }), [activeKeys, accordion, expandIcon]);
|
|
96
|
+
// children 模式:遍历 <Collapse.Panel>,用 React key + cloneElement 把 panelKey/isFirst 注入并就地渲染。
|
|
97
|
+
let panelChildren = null;
|
|
98
|
+
if (!items) {
|
|
99
|
+
const childArr = React.Children.toArray(children).filter(c => React.isValidElement(c) && c.type && c.type.__isCollapsePanel);
|
|
100
|
+
panelChildren = childArr.map((child, i) => {
|
|
101
|
+
const c = child;
|
|
102
|
+
const key = String((c.key ?? i));
|
|
103
|
+
return _jsx(PanelInner, { panelKey: key, isFirst: i === 0, ...c.props }, key);
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
return (_jsx(CollapseContext.Provider, { value: ctxValue, children: _jsx("div", { style: {
|
|
107
|
+
// antd Collapse 默认背景 rgba(0,0,0,0.02)(极浅灰),边框 #d9d9d9,圆角 8。
|
|
108
|
+
background: ghost ? 'transparent' : 'rgba(0, 0, 0, 0.02)',
|
|
109
|
+
border: ghost || !bordered ? undefined : '1px solid var(--hb-color-border, #d9d9d9)',
|
|
110
|
+
borderRadius: ghost || !bordered ? undefined : 8,
|
|
111
|
+
overflow: 'hidden',
|
|
112
|
+
...style,
|
|
113
|
+
}, className: className, children: items
|
|
114
|
+
? items.map((it, i) => (_jsx(PanelInner, { panelKey: String(it.key ?? i), isFirst: i === 0, header: it.label, disabled: it.disabled, forceRender: it.forceRender, showArrow: it.showArrow, children: it.children }, String(it.key ?? i))))
|
|
115
|
+
: panelChildren }) }));
|
|
6
116
|
}
|
|
7
|
-
|
|
117
|
+
/**
|
|
118
|
+
* <Collapse.Panel key="x" header="标题">子内容</Collapse.Panel>
|
|
119
|
+
* 由父 Collapse 遍历并 cloneElement 就地渲染;panel 用 React key 标识(与 antd 语义一致)。
|
|
120
|
+
* 自身 render 仅返回 null(占位),真实渲染交给 Collapse 内的 PanelInner。
|
|
121
|
+
*/
|
|
122
|
+
Collapse.Panel = function Panel(_props) {
|
|
123
|
+
return null;
|
|
124
|
+
};
|
|
125
|
+
Collapse.Panel.__isCollapsePanel = true;
|
|
@@ -19,10 +19,8 @@ function itemsFromChildren(children) {
|
|
|
19
19
|
return out;
|
|
20
20
|
}
|
|
21
21
|
export function Descriptions(props) {
|
|
22
|
-
const { title, bordered = false, column = 3, colon = true, items, contentStyle, labelStyle, children, style, className
|
|
23
|
-
const resolved = items && items.length > 0
|
|
24
|
-
? items.map(it => ({ label: it.label, value: it.children, span: SPAN(it.span) }))
|
|
25
|
-
: itemsFromChildren(children);
|
|
22
|
+
const { title, bordered = false, column = 3, colon = true, items, contentStyle, labelStyle, children, style, className } = props;
|
|
23
|
+
const resolved = items && items.length > 0 ? items.map(it => ({ label: it.label, value: it.children, span: SPAN(it.span) })) : itemsFromChildren(children);
|
|
26
24
|
const cols = column > 0 ? Math.floor(column) : 3;
|
|
27
25
|
// 按列数把 items 切成行(span 累计超过列数则换行),用于 bordered 表格渲染
|
|
28
26
|
const rows = [];
|
|
@@ -44,7 +42,7 @@ export function Descriptions(props) {
|
|
|
44
42
|
const LABEL_COLOR = 'rgba(0,0,0,0.88)';
|
|
45
43
|
const VALUE_COLOR = 'rgba(0,0,0,0.88)';
|
|
46
44
|
const PAD = 16;
|
|
47
|
-
const titleNode = title != null ?
|
|
45
|
+
const titleNode = title != null ? _jsx("div", { style: { fontSize: 16, fontWeight: 500, color: LABEL_COLOR, marginBottom: 12 }, children: title }) : null;
|
|
48
46
|
let body;
|
|
49
47
|
if (bordered) {
|
|
50
48
|
body = (_jsx("table", { style: { borderCollapse: 'collapse', width: '100%', tableLayout: 'fixed', fontSize: 14 }, children: _jsx("tbody", { children: rows.map((row, ri) => (_jsx("tr", { children: row.flatMap((it, ci) => [
|
|
@@ -1,8 +1,16 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* antd Divider 兼容层(纯 div 实现)。
|
|
4
|
+
*
|
|
5
|
+
* 不再走 <HbDivider>(Shadow DOM slot):带文字的分隔线,文字位置/contentPosition
|
|
6
|
+
* 受 slot 样式影响,纯 div + flex 可精确复刻 antd 的「文字左/中/右 + 两侧线条」布局。
|
|
7
|
+
*/
|
|
2
8
|
export declare function Divider(props: {
|
|
3
9
|
type?: 'horizontal' | 'vertical';
|
|
4
10
|
orientation?: 'left' | 'center' | 'right';
|
|
5
11
|
dashed?: boolean;
|
|
12
|
+
plain?: boolean;
|
|
6
13
|
children?: React.ReactNode;
|
|
7
14
|
style?: React.CSSProperties;
|
|
15
|
+
className?: string;
|
|
8
16
|
}): React.JSX.Element;
|
|
@@ -1,5 +1,40 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* antd Divider 兼容层(纯 div 实现)。
|
|
4
|
+
*
|
|
5
|
+
* 不再走 <HbDivider>(Shadow DOM slot):带文字的分隔线,文字位置/contentPosition
|
|
6
|
+
* 受 slot 样式影响,纯 div + flex 可精确复刻 antd 的「文字左/中/右 + 两侧线条」布局。
|
|
7
|
+
*/
|
|
3
8
|
export function Divider(props) {
|
|
4
|
-
|
|
9
|
+
const { type = 'horizontal', orientation = 'center', dashed, plain, children, style, className } = props;
|
|
10
|
+
const borderStyle = dashed ? 'dashed' : 'solid';
|
|
11
|
+
// antd 分割线色 rgba(5,5,5,0.06) 偏浅,在白底 + flex 段里几乎不可见,用更明确的边框色兜底。
|
|
12
|
+
const lineColor = 'var(--hb-color-border, #d9d9d9)';
|
|
13
|
+
if (type === 'vertical') {
|
|
14
|
+
// 垂直分隔线:行内,固定高度,左右 margin,由父行高决定。
|
|
15
|
+
return (_jsx("span", { role: "separator", "aria-orientation": "vertical", style: {
|
|
16
|
+
display: 'inline-block',
|
|
17
|
+
width: 0,
|
|
18
|
+
height: '0.9em',
|
|
19
|
+
margin: '0 8px',
|
|
20
|
+
verticalAlign: 'middle',
|
|
21
|
+
borderLeft: `1px ${borderStyle} ${lineColor}`,
|
|
22
|
+
...style,
|
|
23
|
+
}, className: className }));
|
|
24
|
+
}
|
|
25
|
+
// 水平分隔线:若无文字,就是一条线;若有文字,文字两侧各一条 flex 线。
|
|
26
|
+
const hasText = children !== undefined && children !== null;
|
|
27
|
+
if (!hasText) {
|
|
28
|
+
return _jsx("div", { role: "separator", style: { width: '100%', minWidth: '100%', borderTop: `1px ${borderStyle} ${lineColor}`, margin: '24px 0', ...style }, className: className });
|
|
29
|
+
}
|
|
30
|
+
// 有文字:flex 三段。orientation 决定文字占比。
|
|
31
|
+
const flexMap = { left: '0 auto 1fr', center: '1fr auto 1fr', right: '1fr auto 0' };
|
|
32
|
+
const [leftFlex, , rightFlex] = (flexMap[orientation] || flexMap.center).split(' ');
|
|
33
|
+
return (_jsxs("div", { role: "separator", style: {
|
|
34
|
+
display: 'flex',
|
|
35
|
+
alignItems: 'center',
|
|
36
|
+
margin: '24px 0',
|
|
37
|
+
color: plain ? 'var(--hb-color-text-secondary, rgba(0,0,0,0.45))' : 'var(--hb-color-text, rgba(0,0,0,0.88))',
|
|
38
|
+
...style,
|
|
39
|
+
}, className: className, children: [_jsx("span", { style: { flex: leftFlex, borderTop: `1px ${borderStyle} ${lineColor}` } }), _jsx("span", { style: { padding: '0 1em', whiteSpace: 'nowrap', fontSize: plain ? 14 : 16, fontWeight: plain ? 400 : 500 }, children: children }), _jsx("span", { style: { flex: rightFlex, borderTop: `1px ${borderStyle} ${lineColor}` } })] }));
|
|
5
40
|
}
|
|
@@ -4,8 +4,14 @@ export declare function Drawer(props: {
|
|
|
4
4
|
title?: React.ReactNode;
|
|
5
5
|
placement?: 'top' | 'right' | 'bottom' | 'left';
|
|
6
6
|
width?: string | number;
|
|
7
|
+
height?: string | number;
|
|
7
8
|
onClose?: () => void;
|
|
8
9
|
maskClosable?: boolean;
|
|
10
|
+
keyboard?: boolean;
|
|
11
|
+
destroyOnClose?: boolean;
|
|
9
12
|
children?: React.ReactNode;
|
|
13
|
+
footer?: React.ReactNode | null;
|
|
10
14
|
style?: React.CSSProperties;
|
|
11
|
-
|
|
15
|
+
className?: string;
|
|
16
|
+
closable?: boolean;
|
|
17
|
+
}): React.JSX.Element | null;
|