@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.
Files changed (70) hide show
  1. package/LICENSE +21 -0
  2. package/lib/components/Affix.js +1 -1
  3. package/lib/components/Alert.js +1 -1
  4. package/lib/components/Avatar.js +4 -1
  5. package/lib/components/BackTop.js +1 -1
  6. package/lib/components/Badge.js +1 -1
  7. package/lib/components/Breadcrumb.js +4 -2
  8. package/lib/components/Button.js +3 -2
  9. package/lib/components/Card.d.ts +14 -1
  10. package/lib/components/Card.js +30 -3
  11. package/lib/components/Checkbox.d.ts +2 -0
  12. package/lib/components/Checkbox.js +14 -2
  13. package/lib/components/Collapse.d.ts +34 -4
  14. package/lib/components/Collapse.js +122 -4
  15. package/lib/components/Descriptions.js +3 -5
  16. package/lib/components/Divider.d.ts +8 -0
  17. package/lib/components/Divider.js +38 -3
  18. package/lib/components/Drawer.d.ts +7 -1
  19. package/lib/components/Drawer.js +167 -4
  20. package/lib/components/Dropdown.js +1 -1
  21. package/lib/components/FloatButton.js +1 -1
  22. package/lib/components/Form.d.ts +25 -14
  23. package/lib/components/Form.js +315 -92
  24. package/lib/components/Image.js +1 -1
  25. package/lib/components/Input.js +25 -4
  26. package/lib/components/InputNumber.d.ts +1 -1
  27. package/lib/components/InputNumber.js +15 -1
  28. package/lib/components/Layout.d.ts +1 -1
  29. package/lib/components/Layout.js +41 -16
  30. package/lib/components/Menu.js +55 -11
  31. package/lib/components/Modal.d.ts +4 -1
  32. package/lib/components/Modal.js +137 -20
  33. package/lib/components/PageHeader.js +1 -1
  34. package/lib/components/Pagination.js +1 -1
  35. package/lib/components/Popconfirm.js +1 -1
  36. package/lib/components/Popover.js +1 -1
  37. package/lib/components/Progress.js +1 -1
  38. package/lib/components/Radio.d.ts +5 -3
  39. package/lib/components/Radio.js +24 -13
  40. package/lib/components/Rate.js +1 -1
  41. package/lib/components/Result.js +1 -1
  42. package/lib/components/Segmented.d.ts +5 -3
  43. package/lib/components/Segmented.js +4 -1
  44. package/lib/components/Select.js +1 -1
  45. package/lib/components/Slider.d.ts +9 -2
  46. package/lib/components/Slider.js +8 -1
  47. package/lib/components/Space.d.ts +2 -1
  48. package/lib/components/Space.js +47 -4
  49. package/lib/components/Spin.js +1 -1
  50. package/lib/components/Statistic.d.ts +1 -0
  51. package/lib/components/Statistic.js +5 -1
  52. package/lib/components/Steps.js +4 -2
  53. package/lib/components/Switch.d.ts +6 -0
  54. package/lib/components/Switch.js +15 -1
  55. package/lib/components/Table.js +68 -12
  56. package/lib/components/Tabs.js +52 -27
  57. package/lib/components/Tag.d.ts +1 -0
  58. package/lib/components/Tag.js +16 -2
  59. package/lib/components/TimePicker.js +1 -1
  60. package/lib/components/Timeline.js +9 -1
  61. package/lib/components/Tooltip.js +1 -1
  62. package/lib/components/Tree.js +2 -4
  63. package/lib/components/TreeSelect.d.ts +2 -0
  64. package/lib/components/TreeSelect.js +19 -1
  65. package/lib/components/Typography.js +7 -3
  66. package/lib/components/Upload.js +1 -1
  67. package/lib/components/Watermark.js +21 -1
  68. package/lib/components/message.js +4 -3
  69. package/lib/components/notification.js +3 -1
  70. package/package.json +5 -6
@@ -2,7 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { HbLoading } from '@huibo-ui/react';
3
3
  export function Spin(props) {
4
4
  if (props.children) {
5
- return _jsxs("div", { style: { position: 'relative' }, children: [props.spinning && _jsx(HbLoading, { size: props.size === 'middle' ? 'default' : props.size, fullscreen: false }), props.children] });
5
+ return (_jsxs("div", { style: { position: 'relative' }, children: [props.spinning && _jsx(HbLoading, { size: props.size === 'middle' ? 'default' : props.size, fullscreen: false }), props.children] }));
6
6
  }
7
7
  return _jsx(HbLoading, { size: props.size === 'middle' ? 'default' : props.size });
8
8
  }
@@ -5,5 +5,6 @@ export declare function Statistic(props: {
5
5
  precision?: number;
6
6
  prefix?: React.ReactNode;
7
7
  suffix?: React.ReactNode;
8
+ valueStyle?: React.CSSProperties;
8
9
  style?: React.CSSProperties;
9
10
  }): React.JSX.Element;
@@ -1,5 +1,9 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { HbStatistic } from '@huibo-ui/react';
3
3
  export function Statistic(props) {
4
- return _jsx(HbStatistic, { title: typeof props.title === 'string' ? props.title : '', value: props.value ?? 0, precision: props.precision, prefix: props.prefix, suffix: props.suffix, style: props.style });
4
+ // hb-statistic valuePrefix(非 prefix),且只接受 string
5
+ // 注意:不能传 `prefix` prop —— 它会命中 HTMLElement 原生只读 getter,抛 "has only a getter"。
6
+ const strPrefix = typeof props.prefix === 'string' ? props.prefix : '';
7
+ const strSuffix = typeof props.suffix === 'string' ? props.suffix : '';
8
+ return (_jsx(HbStatistic, { title: typeof props.title === 'string' ? props.title : '', value: props.value ?? 0, precision: props.precision, valuePrefix: strPrefix, suffix: strSuffix, style: props.style }));
5
9
  }
@@ -2,6 +2,8 @@ import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import React from 'react';
3
3
  import { HbSteps, HbStep } from '@huibo-ui/react';
4
4
  export function Steps(props) {
5
- return _jsx(HbSteps, { active: props.current ?? 0, items: props.items, direction: props.direction, type: props.type, processStatus: props.status, size: props.size, children: props.children });
5
+ return (_jsx(HbSteps, { active: props.current ?? 0, items: props.items, direction: props.direction, type: props.type, processStatus: props.status, size: props.size, children: props.children }));
6
6
  }
7
- Steps.Step = function Step(props) { return React.createElement(HbStep, { title: props.title, description: props.description, status: props.status }, props.children); };
7
+ Steps.Step = function Step(props) {
8
+ return React.createElement(HbStep, { title: props.title, description: props.description, status: props.status }, props.children);
9
+ };
@@ -1,6 +1,12 @@
1
1
  import React from 'react';
2
+ /**
3
+ * antd Switch 兼容层。
4
+ * antd 有受控(checked)和非受控(defaultChecked)两种模式;兼容层需同时支持。
5
+ * 之前只读 checked、忽略 defaultChecked,导致 <Switch defaultChecked /> 实际未打开。
6
+ */
2
7
  export declare function Switch(props: {
3
8
  checked?: boolean;
9
+ defaultChecked?: boolean;
4
10
  onChange?: (checked: boolean) => void;
5
11
  disabled?: boolean;
6
12
  size?: 'small' | 'middle' | 'large';
@@ -1,5 +1,19 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
+ import React from 'react';
2
3
  import { HbSwitch } from '@huibo-ui/react';
4
+ /**
5
+ * antd Switch 兼容层。
6
+ * antd 有受控(checked)和非受控(defaultChecked)两种模式;兼容层需同时支持。
7
+ * 之前只读 checked、忽略 defaultChecked,导致 <Switch defaultChecked /> 实际未打开。
8
+ */
3
9
  export function Switch(props) {
4
- return _jsx(HbSwitch, { modelValue: props.checked ?? false, disabled: props.disabled, size: props.size === 'middle' ? 'default' : props.size, activeText: props.checkedChildren, inactiveText: props.unCheckedChildren, onHbChange: (e) => props.onChange?.(e.detail) });
10
+ // 非受控:用内部 state 跟踪,初始值取 defaultChecked。
11
+ const isControlled = props.checked !== undefined;
12
+ const [inner, setInner] = React.useState(props.defaultChecked ?? false);
13
+ const value = isControlled ? props.checked : inner;
14
+ return (_jsx(HbSwitch, { modelValue: value, disabled: props.disabled || props.loading, size: props.size === 'middle' ? 'default' : props.size, activeText: props.checkedChildren, inactiveText: props.unCheckedChildren, onHbChange: (e) => {
15
+ if (!isControlled)
16
+ setInner(e.detail);
17
+ props.onChange?.(e.detail);
18
+ } }));
5
19
  }
@@ -30,6 +30,53 @@ function renderToHtml(node) {
30
30
  return '';
31
31
  }
32
32
  }
33
+ /**
34
+ * 自动建树:当 dataSource 是「扁平数据(每行带 parentId/parentKey 等父级标识字段,
35
+ * 且自身无 children 嵌套)」时,按父级关系构建出树形结构,让 hb-table 以树形渲染。
36
+ *
37
+ * 背景:antd 项目里常见的树形表格用法是——后端返回扁平数据(id + parentId),
38
+ * 应用层(getDataList / 拦截器 / 工具函数)把它转成树形(children 嵌套)再喂给表格。
39
+ * 迁移到 huibo-ui 时,部分页面丢失了这层转换,导致扁平数据被表格当成普通行全部展开。
40
+ * 在此兼容层统一兜底,避免要求每个业务页面都改回「转树形」逻辑。
41
+ *
42
+ * 触发条件(同时满足才转,避免误伤已经是树形的数据):
43
+ * 1. dataSource 是非空数组
44
+ * 2. 至少有一行的「父级字段」(默认 parentId) 有值(指向另一行)
45
+ * 3. 所有行自身都没有 children 数组(说明不是已经建好的树)
46
+ *
47
+ * 字段名可通过 props.treeBuild({ idKey, parentIdKey })覆盖,默认 idKey='id', parentIdKey='parentId'。
48
+ */
49
+ function buildTreeFromFlat(list, opts = {}) {
50
+ const idKey = opts.idKey || 'id';
51
+ const parentIdKey = opts.parentIdKey || 'parentId';
52
+ if (!Array.isArray(list) || list.length === 0)
53
+ return list;
54
+ // 触发条件校验:必须有人在引用父级,且没人已经有 children
55
+ const hasParentRef = list.some(row => row[parentIdKey] != null && row[parentIdKey] !== '' && row[parentIdKey] !== 0 && row[parentIdKey] !== '0');
56
+ const hasExistingChildren = list.some(row => Array.isArray(row.children) && row.children.length > 0);
57
+ if (!hasParentRef || hasExistingChildren)
58
+ return list;
59
+ const map = new Map();
60
+ const roots = [];
61
+ // 第一遍:建索引(浅拷贝,避免污染调用方数据)
62
+ list.forEach(row => map.set(row[idKey], { ...row }));
63
+ // 第二遍:挂子节点。找不到父节点的当根节点。
64
+ list.forEach(row => {
65
+ const pid = row[parentIdKey];
66
+ const node = map.get(row[idKey]);
67
+ const parent = map.get(pid);
68
+ if (parent) {
69
+ if (!parent.children)
70
+ parent.children = [];
71
+ parent.children.push(node);
72
+ }
73
+ else {
74
+ roots.push(node);
75
+ }
76
+ });
77
+ // 根节点为 0 时(即整棵树只有一层,没有真正的父子关系)直接返回原数据
78
+ return roots.length > 0 ? roots : list;
79
+ }
33
80
  export function Table(props) {
34
81
  const { dataSource = [], columns = [], rowKey, loading, size, bordered, pagination, rowSelection, scroll, onChange } = props;
35
82
  // antd columns → huibo columns
@@ -56,18 +103,24 @@ export function Table(props) {
56
103
  // rowKey 函数 → 字符串
57
104
  const huiboRowKey = typeof rowKey === 'string' ? rowKey : '';
58
105
  // pagination 适配
59
- const huiboPagination = pagination === false ? undefined : pagination ? {
60
- current: pagination.current,
61
- pageSize: pagination.pageSize,
62
- pageSizes: pagination.pageSizeOptions?.map((s) => parseInt(s)),
63
- showTotal: !!pagination.showTotal,
64
- } : undefined;
106
+ const huiboPagination = pagination === false
107
+ ? undefined
108
+ : pagination
109
+ ? {
110
+ current: pagination.current,
111
+ pageSize: pagination.pageSize,
112
+ pageSizes: pagination.pageSizeOptions?.map((s) => parseInt(s)),
113
+ showTotal: !!pagination.showTotal,
114
+ }
115
+ : undefined;
65
116
  // rowSelection 适配
66
- const huiboRowSelection = rowSelection ? {
67
- type: rowSelection.type || 'checkbox',
68
- selectedRowKeys: rowSelection.selectedRowKeys,
69
- getCheckboxProps: rowSelection.getCheckboxProps,
70
- } : undefined;
117
+ const huiboRowSelection = rowSelection
118
+ ? {
119
+ type: rowSelection.type || 'checkbox',
120
+ selectedRowKeys: rowSelection.selectedRowKeys,
121
+ getCheckboxProps: rowSelection.getCheckboxProps,
122
+ }
123
+ : undefined;
71
124
  // ===== 单元格 portal:把含交互内容的单元格用 React createRoot 挂进 hb-table 的 sentinel span =====
72
125
  // 用 callback ref 稳定拿到 hb-table CE 节点(输出目标 forwardRef 模板兼容)。
73
126
  const tableHostRef = React.useRef(null);
@@ -171,7 +224,10 @@ export function Table(props) {
171
224
  cellRootsRef.current.clear();
172
225
  };
173
226
  }, []);
174
- return (_jsx(HbTable, { ref: setTableHost, data: dataSource, columns: huiboColumns, rowKey: huiboRowKey, loading: loading, size: size === 'middle' ? 'default' : size || 'default', border: bordered, stripe: false, pagination: huiboPagination, rowSelection: huiboRowSelection, tableScroll: scroll ? { x: scroll.x ? String(scroll.x) : undefined, y: scroll.y ? String(scroll.y) : undefined } : undefined, onHbPageChange: (e) => {
227
+ // 自动建树兜底:扁平数据(带 parentId children)→ 树形结构
228
+ // 让 hb-table 以树形渲染,对齐 antd 表格在应用层已转树形后的效果。
229
+ const treeData = React.useMemo(() => buildTreeFromFlat(dataSource, props.treeBuild), [dataSource, props.treeBuild]);
230
+ return (_jsx(HbTable, { ref: setTableHost, data: treeData, columns: huiboColumns, rowKey: huiboRowKey, loading: loading, size: size === 'middle' ? 'default' : size || 'default', border: bordered, stripe: false, pagination: huiboPagination, rowSelection: huiboRowSelection, tableScroll: scroll ? { x: scroll.x ? String(scroll.x) : undefined, y: scroll.y ? String(scroll.y) : undefined } : undefined, onHbPageChange: (e) => {
175
231
  if (pagination && pagination.onChange)
176
232
  pagination.onChange(e.detail.current, e.detail.pageSize);
177
233
  }, onHbSelectionChange: (e) => {
@@ -2,7 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import React from 'react';
3
3
  const PRIMARY = 'var(--hb-color-primary, #ff6700)';
4
4
  export function Tabs(props) {
5
- const { items, activeKey, defaultActiveKey, onChange, type = 'line', size = 'middle', tabPosition = 'top', destroyInactiveTabPane = false, style, className, children, } = props;
5
+ const { items, activeKey, defaultActiveKey, onChange, type = 'line', size = 'middle', tabPosition = 'top', destroyInactiveTabPane = false, style, className, children } = props;
6
6
  const list = items && items.length > 0 ? items : [];
7
7
  const [internal, setInternal] = React.useState(activeKey ?? defaultActiveKey ?? list[0]?.key ?? '');
8
8
  const current = activeKey !== undefined ? activeKey : internal;
@@ -17,7 +17,36 @@ export function Tabs(props) {
17
17
  const card = type === 'card';
18
18
  const fontSize = size === 'large' ? 16 : size === 'small' ? 13 : 14;
19
19
  const tabPadding = size === 'large' ? '16px 24px' : size === 'small' ? '8px 16px' : '12px 16px';
20
- const tabBar = (_jsx("div", { style: {
20
+ /**
21
+ * 滑动 ink bar(对齐 antd,修复 #18):
22
+ * 修复前每个 tab 各自按 active 条件渲染一个无 transition 的下划线,切换时瞬变;
23
+ * 现在用单一绝对定位 ink bar,位置/宽度由当前 active tab 的 offset 测量驱动,
24
+ * 切换时 transform/width 平滑过渡(滑动效果)。
25
+ */
26
+ const tabRefs = React.useRef({});
27
+ const navRef = React.useRef(null);
28
+ const [ink, setInk] = React.useState({ offset: 0, size: 0, ready: false });
29
+ const measureInk = React.useCallback(() => {
30
+ const el = tabRefs.current[current] ?? null;
31
+ const nav = navRef.current;
32
+ if (!el || !nav)
33
+ return;
34
+ // 水平:左偏移与宽度;垂直:上偏移与高度
35
+ if (vertical) {
36
+ setInk({ offset: el.offsetTop, size: el.offsetHeight, ready: true });
37
+ }
38
+ else {
39
+ setInk({ offset: el.offsetLeft, size: el.offsetWidth, ready: true });
40
+ }
41
+ }, [current, vertical]);
42
+ React.useEffect(() => {
43
+ measureInk();
44
+ }, [measureInk, list.length, tabPosition]);
45
+ const inkStyle = vertical
46
+ ? { position: 'absolute', left: 0, top: ink.offset, height: ink.size, width: 2, background: PRIMARY, transition: 'top 0.3s cubic-bezier(0.645,0.045,0.355,1), height 0.3s' }
47
+ : { position: 'absolute', left: ink.offset, bottom: 0, width: ink.size, height: 2, background: PRIMARY, transition: 'left 0.3s cubic-bezier(0.645,0.045,0.355,1), width 0.3s' };
48
+ const tabBar = (_jsxs("div", { ref: navRef, style: {
49
+ position: 'relative',
21
50
  display: 'flex',
22
51
  flexDirection: vertical ? 'column' : 'row',
23
52
  borderBottom: vertical || card ? 'none' : '1px solid #f0f0f0',
@@ -25,31 +54,27 @@ export function Tabs(props) {
25
54
  gap: vertical ? 0 : 4,
26
55
  overflowX: vertical ? 'visible' : 'auto',
27
56
  scrollbarWidth: 'thin',
28
- }, children: list.map(it => {
29
- const active = it.key === current;
30
- return (_jsxs("div", { role: "tab", "aria-selected": active, onClick: () => select(it.key, it.disabled), style: {
31
- padding: tabPadding,
32
- cursor: it.disabled ? 'not-allowed' : 'pointer',
33
- color: it.disabled ? 'rgba(0,0,0,0.25)' : active ? PRIMARY : 'rgba(0,0,0,0.88)',
34
- fontWeight: active ? 500 : 400,
35
- fontSize,
36
- whiteSpace: 'nowrap',
37
- position: 'relative',
38
- background: card ? (active ? '#fff' : 'transparent') : 'transparent',
39
- border: card ? '1px solid #f0f0f0' : 'none',
40
- [vertical ? 'borderBottom' : 'borderBottom']: card ? (active ? '1px solid #fff' : '1px solid #f0f0f0') : 'none',
41
- marginBottom: card && !vertical ? '-1px' : undefined,
42
- borderRadius: card ? (vertical ? '4px 0 0 4px' : '4px 4px 0 0') : undefined,
43
- transition: 'color .2s',
44
- }, children: [it.label, active && !card && (_jsx("span", { style: {
45
- position: 'absolute',
46
- [vertical ? 'right' : 'bottom']: 0,
47
- [vertical ? 'top' : 'left']: vertical ? 0 : 0,
48
- [vertical ? 'width' : 'height']: '2px',
49
- [vertical ? 'height' : 'width']: '100%',
50
- background: PRIMARY,
51
- } }))] }, it.key));
52
- }) }));
57
+ }, children: [!card && ink.ready && _jsx("span", { style: inkStyle, "aria-hidden": "true" }), list.map(it => {
58
+ const active = it.key === current;
59
+ return (_jsx("div", { ref: el => {
60
+ tabRefs.current[it.key] = el;
61
+ }, role: "tab", "aria-selected": active, onClick: () => select(it.key, it.disabled), style: {
62
+ padding: tabPadding,
63
+ cursor: it.disabled ? 'not-allowed' : 'pointer',
64
+ color: it.disabled ? 'rgba(0,0,0,0.25)' : active ? PRIMARY : 'rgba(0,0,0,0.88)',
65
+ fontWeight: active ? 500 : 400,
66
+ fontSize,
67
+ whiteSpace: 'nowrap',
68
+ position: 'relative',
69
+ zIndex: 1,
70
+ background: card ? (active ? '#fff' : 'transparent') : 'transparent',
71
+ border: card ? '1px solid #f0f0f0' : 'none',
72
+ [vertical ? 'borderBottom' : 'borderBottom']: card ? (active ? '1px solid #fff' : '1px solid #f0f0f0') : 'none',
73
+ marginBottom: card && !vertical ? '-1px' : undefined,
74
+ borderRadius: card ? (vertical ? '4px 0 0 4px' : '4px 4px 0 0') : undefined,
75
+ transition: 'color .2s',
76
+ }, children: it.label }, it.key));
77
+ })] }));
53
78
  // 对齐 antd Tabs 默认的渲染策略:
54
79
  // - destroyInactiveTabPane=true:只渲染当前 active(切换即销毁旧的)
55
80
  // - 默认(lazy keep-alive):只渲染「当前 active」和「曾经 active 过」的;
@@ -3,6 +3,7 @@ export declare function Tag(props: {
3
3
  color?: string;
4
4
  closable?: boolean;
5
5
  onClose?: () => void;
6
+ bordered?: boolean;
6
7
  children?: React.ReactNode;
7
8
  style?: React.CSSProperties;
8
9
  }): React.JSX.Element;
@@ -1,6 +1,20 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { HbTag } from '@huibo-ui/react';
3
- const colorMap = { success: 'success', processing: 'info', error: 'danger', default: 'info', warning: 'warning', blue: 'primary', green: 'success', red: 'danger', orange: 'warning' };
3
+ const colorMap = {
4
+ success: 'success',
5
+ processing: 'info',
6
+ error: 'danger',
7
+ default: 'default',
8
+ warning: 'warning',
9
+ blue: 'primary',
10
+ green: 'success',
11
+ red: 'danger',
12
+ orange: 'warning',
13
+ };
4
14
  export function Tag(props) {
5
- return _jsx(HbTag, { type: (colorMap[props.color || 'default'] || 'default'), closable: props.closable, onHbClose: () => props.onClose?.(), style: props.style, children: props.children });
15
+ // antd color 既支持预设色名也支持任意 CSS 色(#hex / rgb)。
16
+ // 预设色名 → 映射成 hb-tag type;任意 hex/rgb → 传给 hb-tag 的 color prop(自定义色,由底层渲染)。
17
+ // bordered 默认 true(对齐 antd),透传给 hb-tag。
18
+ const isPreset = props.color && colorMap[props.color];
19
+ return (_jsx(HbTag, { type: isPreset ? colorMap[props.color] : 'default', color: isPreset ? undefined : props.color, closable: props.closable, bordered: props.bordered ?? true, onHbClose: () => props.onClose?.(), style: props.style, children: props.children }));
6
20
  }
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { HbTimePicker } from '@huibo-ui/react';
3
3
  export function TimePicker(props) {
4
- return _jsx(HbTimePicker, { modelValue: props.value, format: props.format, clearable: props.allowClear, disabled: props.disabled, size: props.size === 'middle' ? 'default' : props.size, placeholder: props.placeholder, style: props.style, onHbChange: (e) => props.onChange?.(e.detail) });
4
+ return (_jsx(HbTimePicker, { modelValue: props.value, format: props.format, clearable: props.allowClear, disabled: props.disabled, size: props.size === 'middle' ? 'default' : props.size, placeholder: props.placeholder, style: props.style, onHbChange: (e) => props.onChange?.(e.detail) }));
5
5
  }
@@ -1,5 +1,13 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { HbTimeline } from '@huibo-ui/react';
3
3
  export function Timeline(props) {
4
- return _jsx(HbTimeline, { items: props.items, direction: props.mode, reverse: props.reverse });
4
+ // hb-timeline 的 item 用 { content, time?, color? };antd 用 { children, label, color }
5
+ // 兼容层把 antd 的 children/label 映射到 content(取字符串),color 透传,
6
+ // 否则 items 透传后 hb-timeline 取不到 content,时间线文字为空。
7
+ const mapped = props.items?.map(it => ({
8
+ content: typeof it?.children === 'string' ? it.children : typeof it?.label === 'string' ? it.label : '',
9
+ time: typeof it?.time === 'string' ? it.time : undefined,
10
+ color: it?.color,
11
+ }));
12
+ return _jsx(HbTimeline, { items: mapped, direction: props.mode, reverse: props.reverse });
5
13
  }
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { HbTooltip } from '@huibo-ui/react';
3
3
  export function Tooltip(props) {
4
- return _jsx(HbTooltip, { content: typeof props.title === 'string' ? props.title : '', position: (props.placement || 'top'), children: props.children });
4
+ return (_jsx(HbTooltip, { content: typeof props.title === 'string' ? props.title : '', position: (props.placement || 'top'), children: props.children }));
5
5
  }
@@ -18,9 +18,7 @@ const titleToText = (title) => {
18
18
  if (typeof child === 'number')
19
19
  return String(child);
20
20
  if (Array.isArray(child)) {
21
- return child
22
- .map((c) => (typeof c === 'string' || typeof c === 'number' ? String(c) : ''))
23
- .join('');
21
+ return child.map((c) => (typeof c === 'string' || typeof c === 'number' ? String(c) : '')).join('');
24
22
  }
25
23
  return '';
26
24
  }
@@ -33,7 +31,7 @@ export function Tree(props) {
33
31
  const childField = fieldNames?.children || 'children';
34
32
  // 1) 适配 fieldNames;2) 把 title(含 React 元素)统一转成字符串,避免 hb-tree 渲染冻结对象
35
33
  const normalizedData = React.useMemo(() => {
36
- const walk = (nodes) => (nodes || []).map((n) => ({
34
+ const walk = (nodes) => (nodes || []).map(n => ({
37
35
  key: String(n[keyField]),
38
36
  title: titleToText(n[titleField]),
39
37
  disabled: !!n.disabled,
@@ -2,10 +2,12 @@ import React from 'react';
2
2
  export declare function TreeSelect(props: {
3
3
  treeData?: any[];
4
4
  value?: any;
5
+ defaultValue?: any;
5
6
  onChange?: (value: any) => void;
6
7
  multiple?: boolean;
7
8
  treeCheckable?: boolean;
8
9
  placeholder?: string;
9
10
  disabled?: boolean;
10
11
  style?: React.CSSProperties;
12
+ children?: React.ReactNode;
11
13
  }): React.JSX.Element;
@@ -1,5 +1,23 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { HbTreeSelect } from '@huibo-ui/react';
3
+ /**
4
+ * 把 antd treeData(字段 value/title/children/disabled)归一化成 hb-tree-select 需要的
5
+ * key/title/children/disabled。hb-tree-select 内部用 node.key 标识节点(渲染 data-tree-key),
6
+ * antd treeData 用 value。修复前直接透传 treeData,hb 取 node.key 得到 undefined,
7
+ * 导致 data-tree-key 缺失、点击节点选中失效(modelValue 用 undefined 比较)、子节点选不中。
8
+ */
9
+ function normalizeTreeData(nodes) {
10
+ return (nodes || []).map(n => {
11
+ const out = {
12
+ key: n.key !== undefined ? String(n.key) : n.value !== undefined ? String(n.value) : n.title,
13
+ title: n.title ?? n.label,
14
+ disabled: !!n.disabled,
15
+ };
16
+ if (n.children && n.children.length > 0)
17
+ out.children = normalizeTreeData(n.children);
18
+ return out;
19
+ });
20
+ }
3
21
  export function TreeSelect(props) {
4
- return _jsx(HbTreeSelect, { data: props.treeData || [], modelValue: props.value, multiple: props.multiple || props.treeCheckable, checkable: props.treeCheckable, placeholder: props.placeholder, disabled: props.disabled, onHbChange: (e) => props.onChange?.(e.detail), style: props.style });
22
+ return (_jsx(HbTreeSelect, { data: normalizeTreeData(props.treeData || []), modelValue: props.value ?? props.defaultValue ?? '', multiple: props.multiple || props.treeCheckable, checkable: props.treeCheckable, placeholder: props.placeholder, disabled: props.disabled, onHbChange: (e) => props.onChange?.(e.detail), style: props.style, children: props.children }));
5
23
  }
@@ -1,6 +1,5 @@
1
1
  import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
2
2
  import React from 'react';
3
- import { HbLink } from '@huibo-ui/react';
4
3
  export function Typography(props) {
5
4
  return _jsx(_Fragment, { children: props.children });
6
5
  }
@@ -12,8 +11,13 @@ Typography.Paragraph = function Paragraph(props) {
12
11
  return _jsx("p", { children: props.children });
13
12
  };
14
13
  Typography.Link = function Link(props) {
15
- return _jsx(HbLink, { href: props.href, children: props.children });
14
+ const { href, children, target, onClick, style, className, ...rest } = props;
15
+ return (_jsx("a", { href: href, target: target, onClick: onClick, style: { color: 'var(--hb-color-primary)', textDecoration: 'none', cursor: 'pointer', ...style }, className: className, ...rest, children: children }));
16
16
  };
17
17
  Typography.Text = function Text(props) {
18
- return _jsx("span", { style: { fontWeight: props.strong ? 'bold' : undefined, fontStyle: props.italic ? 'italic' : undefined, textDecoration: props.delete ? 'line-through' : props.underline ? 'underline' : undefined }, children: props.children });
18
+ return (_jsx("span", { style: {
19
+ fontWeight: props.strong ? 'bold' : undefined,
20
+ fontStyle: props.italic ? 'italic' : undefined,
21
+ textDecoration: props.delete ? 'line-through' : props.underline ? 'underline' : undefined,
22
+ }, children: props.children }));
19
23
  };
@@ -1,7 +1,7 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { HbUpload } from '@huibo-ui/react';
3
3
  export function Upload(props) {
4
- return _jsx(HbUpload, { action: props.action, multiple: props.multiple, accept: props.accept, limit: props.maxCount, fileList: props.fileList || [], beforeUpload: props.beforeUpload, customRequest: props.customRequest, listType: props.listType || 'text', disabled: props.disabled, onHbChange: (e) => props.onChange?.({ fileList: e.detail }), style: props.style, children: props.children });
4
+ return (_jsx(HbUpload, { action: props.action, multiple: props.multiple, accept: props.accept, limit: props.maxCount, fileList: props.fileList || [], beforeUpload: props.beforeUpload, customRequest: props.customRequest, listType: props.listType || 'text', disabled: props.disabled, onHbChange: (e) => props.onChange?.({ fileList: e.detail }), style: props.style, children: props.children }));
5
5
  }
6
6
  /**
7
7
  * Upload.Dragger —— 拖拽上传(antd 子组件)。huibo hb-upload 无 drag 形态,
@@ -1,5 +1,25 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { HbWatermark } from '@huibo-ui/react';
3
3
  export function Watermark(props) {
4
- return _jsx(HbWatermark, { content: props.content || '', width: props.width, height: props.height, gap: Array.isArray(props.gap) ? props.gap[0] : props.gap, rotate: props.rotate, fontColor: props.font?.color, fontSize: props.font?.fontSize, children: props.children });
4
+ // 仅传递显式提供的 props:底层 hb-watermark @Prop 带默认值
5
+ // (width=120 / height=120 / gap=8 / rotate=-22 / fontSize=14 / fontColor),
6
+ // 若此处把 undefined 透传给 HbWatermark,React 兼容层的 attachProps 会执行
7
+ // `node.width = undefined` 覆盖 Stencil 默认值,导致 SVG 取到 undefined、
8
+ // backgroundSize 缺失,水印完全不显示。
9
+ const { content, width, height, gap, rotate, font, children } = props;
10
+ const layerProps = { content: content || '' };
11
+ if (width !== undefined)
12
+ layerProps.width = width;
13
+ if (height !== undefined)
14
+ layerProps.height = height;
15
+ const gapValue = Array.isArray(gap) ? gap[0] : gap;
16
+ if (gapValue !== undefined)
17
+ layerProps.gap = gapValue;
18
+ if (rotate !== undefined)
19
+ layerProps.rotate = rotate;
20
+ if (font?.color !== undefined)
21
+ layerProps.fontColor = font.color;
22
+ if (font?.fontSize !== undefined)
23
+ layerProps.fontSize = font.fontSize;
24
+ return _jsx(HbWatermark, { ...layerProps, children: children });
5
25
  }
@@ -14,8 +14,7 @@ function getMessageContainer() {
14
14
  container = document.createElement('div');
15
15
  container.id = 'hb-message-container';
16
16
  container.style.cssText =
17
- 'position:fixed;top:20px;left:50%;transform:translateX(-50%);z-index:1100;' +
18
- 'display:flex;flex-direction:column;align-items:center;gap:8px;pointer-events:none;';
17
+ 'position:fixed;top:20px;left:50%;transform:translateX(-50%);z-index:1100;' + 'display:flex;flex-direction:column;align-items:center;gap:8px;pointer-events:none;';
19
18
  document.body.appendChild(container);
20
19
  }
21
20
  return container;
@@ -33,7 +32,9 @@ function showMessage(type, content, duration) {
33
32
  el.closable = false;
34
33
  div.appendChild(el);
35
34
  // 等动画结束后移除
36
- setTimeout(() => { div.remove(); }, (duration ?? 3000) + 500);
35
+ setTimeout(() => {
36
+ div.remove();
37
+ }, (duration ?? 3000) + 500);
37
38
  return { close: () => div.remove() };
38
39
  }
39
40
  export const message = {
@@ -12,7 +12,9 @@ function showNotification(type, props) {
12
12
  el.duration = props.duration ?? 4500;
13
13
  el.position = 'top-right';
14
14
  div.appendChild(el);
15
- setTimeout(() => { div.remove(); }, (props.duration ?? 4500) + 500);
15
+ setTimeout(() => {
16
+ div.remove();
17
+ }, (props.duration ?? 4500) + 500);
16
18
  return { close: () => div.remove() };
17
19
  }
18
20
  export const notification = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@huibo-ui/react-antd",
3
- "version": "1.0.10",
3
+ "version": "1.0.12",
4
4
  "description": "antd 兼容层 — 接收 antd 原生 props,内部转换为 huibo-ui,实现丝滑平替",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",
@@ -9,10 +9,6 @@
9
9
  "files": [
10
10
  "lib"
11
11
  ],
12
- "scripts": {
13
- "build": "tsc --outDir lib || true",
14
- "prepublishOnly": "pnpm run build"
15
- },
16
12
  "peerDependencies": {
17
13
  "react": ">=16.8.0",
18
14
  "react-dom": ">=16.8.0",
@@ -29,5 +25,8 @@
29
25
  },
30
26
  "publishConfig": {
31
27
  "access": "public"
28
+ },
29
+ "scripts": {
30
+ "build": "tsc --outDir lib || true"
32
31
  }
33
- }
32
+ }