react-vant-nova 1.0.8 → 1.1.0

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 (45) hide show
  1. package/README.md +2 -2
  2. package/bundle/index.css +201 -0
  3. package/bundle/index.min.css +1 -1
  4. package/bundle/react-vant-nova.es.js +917 -626
  5. package/bundle/react-vant-nova.js +921 -628
  6. package/bundle/react-vant-nova.min.js +2 -2
  7. package/es/avatar/Avatar.d.ts +4 -0
  8. package/es/avatar/Avatar.js +68 -0
  9. package/es/avatar/PropsType.d.ts +34 -0
  10. package/es/avatar/PropsType.js +1 -0
  11. package/es/avatar/index.d.ts +5 -0
  12. package/es/avatar/index.js +4 -0
  13. package/es/avatar/style/index.css +52 -0
  14. package/es/avatar/style/var.css +0 -0
  15. package/es/index.d.ts +2 -0
  16. package/es/index.js +3 -1
  17. package/es/treeSelect/PropsType.d.ts +85 -0
  18. package/es/treeSelect/PropsType.js +1 -0
  19. package/es/treeSelect/TreeSelect.d.ts +4 -0
  20. package/es/treeSelect/TreeSelect.js +259 -0
  21. package/es/treeSelect/index.d.ts +5 -0
  22. package/es/treeSelect/index.js +4 -0
  23. package/es/treeSelect/style/index.css +149 -0
  24. package/es/treeSelect/style/var.css +0 -0
  25. package/lib/avatar/Avatar.d.ts +4 -0
  26. package/lib/avatar/Avatar.js +94 -0
  27. package/lib/avatar/PropsType.d.ts +34 -0
  28. package/lib/avatar/PropsType.js +6 -0
  29. package/lib/avatar/index.d.ts +5 -0
  30. package/lib/avatar/index.js +16 -0
  31. package/lib/avatar/style/index.css +52 -0
  32. package/lib/avatar/style/var.css +0 -0
  33. package/lib/index.css +201 -0
  34. package/lib/index.d.ts +2 -0
  35. package/lib/index.js +24 -0
  36. package/lib/index.min.css +1 -1
  37. package/lib/treeSelect/PropsType.d.ts +85 -0
  38. package/lib/treeSelect/PropsType.js +6 -0
  39. package/lib/treeSelect/TreeSelect.d.ts +4 -0
  40. package/lib/treeSelect/TreeSelect.js +291 -0
  41. package/lib/treeSelect/index.d.ts +5 -0
  42. package/lib/treeSelect/index.js +16 -0
  43. package/lib/treeSelect/style/index.css +149 -0
  44. package/lib/treeSelect/style/var.css +0 -0
  45. package/package.json +5 -5
@@ -0,0 +1,4 @@
1
+ import React from 'react';
2
+ import { AvatarProps } from './PropsType';
3
+ declare const Avatar: React.FC<AvatarProps>;
4
+ export default Avatar;
@@ -0,0 +1,68 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useEffect, useMemo, useState } from 'react';
3
+ import clsx from 'clsx';
4
+ import { addUnit, createNamespace } from '../utils';
5
+ const [bem] = createNamespace('avatar');
6
+ const presetSizes = ['mini', 'small', 'normal', 'large'];
7
+ const Avatar = props => {
8
+ const {
9
+ alt,
10
+ children,
11
+ className,
12
+ fallback,
13
+ fit = 'cover',
14
+ shape = 'circle',
15
+ size = 'normal',
16
+ src,
17
+ style,
18
+ onClick,
19
+ onError,
20
+ onLoad
21
+ } = props;
22
+ const [failed, setFailed] = useState(false);
23
+ useEffect(() => {
24
+ setFailed(false);
25
+ }, [src]);
26
+ const avatarStyle = useMemo(() => {
27
+ const internalStyle = Object.assign({}, style);
28
+ if (!presetSizes.includes(String(size))) {
29
+ const sizeValue = addUnit(size);
30
+ internalStyle.width = sizeValue;
31
+ internalStyle.height = sizeValue;
32
+ }
33
+ return internalStyle;
34
+ }, [style, size]);
35
+ const handleLoad = event => {
36
+ onLoad === null || onLoad === void 0 ? void 0 : onLoad(event);
37
+ };
38
+ const handleError = event => {
39
+ setFailed(true);
40
+ onError === null || onError === void 0 ? void 0 : onError(event);
41
+ };
42
+ const renderContent = () => {
43
+ if (src && !failed) {
44
+ return _jsx("img", {
45
+ className: clsx(bem('img')),
46
+ src: src,
47
+ alt: alt || '',
48
+ style: {
49
+ objectFit: fit
50
+ },
51
+ onLoad: handleLoad,
52
+ onError: handleError
53
+ });
54
+ }
55
+ return fallback !== null && fallback !== void 0 ? fallback : children;
56
+ };
57
+ return _jsx("div", Object.assign({
58
+ className: clsx(className, bem({
59
+ [shape]: !!shape,
60
+ [String(size)]: presetSizes.includes(String(size))
61
+ })),
62
+ style: avatarStyle,
63
+ onClick: onClick
64
+ }, {
65
+ children: renderContent()
66
+ }));
67
+ };
68
+ export default Avatar;
@@ -0,0 +1,34 @@
1
+ import React from 'react';
2
+ import { BaseTypeProps } from '../utils';
3
+ export declare type AvatarShape = 'circle' | 'square';
4
+ export declare type AvatarFit = 'contain' | 'cover' | 'fill' | 'none' | 'scale-down';
5
+ export declare type AvatarSize = 'mini' | 'small' | 'normal' | 'large' | number | string;
6
+ export interface AvatarProps extends BaseTypeProps {
7
+ /** 图片地址 */
8
+ src?: string;
9
+ /** 图片描述 */
10
+ alt?: string;
11
+ /**
12
+ * 头像形状
13
+ * @default circle
14
+ */
15
+ shape?: AvatarShape;
16
+ /**
17
+ * 头像大小
18
+ * @default normal
19
+ */
20
+ size?: AvatarSize;
21
+ /**
22
+ * 图片填充模式
23
+ * @default cover
24
+ */
25
+ fit?: AvatarFit;
26
+ /** 图片加载失败时显示的内容 */
27
+ fallback?: React.ReactNode;
28
+ /** 点击头像时触发 */
29
+ onClick?: (event: React.MouseEvent<HTMLDivElement, MouseEvent>) => void;
30
+ /** 图片加载成功时触发 */
31
+ onLoad?: (event: React.SyntheticEvent<HTMLImageElement, Event>) => void;
32
+ /** 图片加载失败时触发 */
33
+ onError?: (event: React.SyntheticEvent<HTMLImageElement, Event>) => void;
34
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,5 @@
1
+ import './style/index.less';
2
+ import Avatar from './Avatar';
3
+ export default Avatar;
4
+ export { Avatar };
5
+ export type { AvatarProps, AvatarShape, AvatarFit, AvatarSize, } from './PropsType';
@@ -0,0 +1,4 @@
1
+ import "./style/index.css";
2
+ import Avatar from './Avatar';
3
+ export default Avatar;
4
+ export { Avatar };
@@ -0,0 +1,52 @@
1
+ :root {
2
+ --rv-avatar-size-mini: 24px;
3
+ --rv-avatar-size-small: 32px;
4
+ --rv-avatar-size-normal: 40px;
5
+ --rv-avatar-size-large: 56px;
6
+ --rv-avatar-background-color: var(--rv-gray-3);
7
+ --rv-avatar-color: var(--rv-gray-7);
8
+ --rv-avatar-font-size: var(--rv-font-size-md);
9
+ --rv-avatar-border-radius: var(--rv-border-radius-md);
10
+ }
11
+ .rv-avatar {
12
+ position: relative;
13
+ display: inline-flex;
14
+ align-items: center;
15
+ justify-content: center;
16
+ width: var(--rv-avatar-size-normal);
17
+ height: var(--rv-avatar-size-normal);
18
+ overflow: hidden;
19
+ color: var(--rv-avatar-color);
20
+ font-size: var(--rv-avatar-font-size);
21
+ line-height: 1;
22
+ white-space: nowrap;
23
+ text-align: center;
24
+ vertical-align: middle;
25
+ background-color: var(--rv-avatar-background-color);
26
+ }
27
+ .rv-avatar--mini {
28
+ width: var(--rv-avatar-size-mini);
29
+ height: var(--rv-avatar-size-mini);
30
+ font-size: var(--rv-font-size-xs);
31
+ }
32
+ .rv-avatar--small {
33
+ width: var(--rv-avatar-size-small);
34
+ height: var(--rv-avatar-size-small);
35
+ font-size: var(--rv-font-size-sm);
36
+ }
37
+ .rv-avatar--large {
38
+ width: var(--rv-avatar-size-large);
39
+ height: var(--rv-avatar-size-large);
40
+ font-size: var(--rv-font-size-lg);
41
+ }
42
+ .rv-avatar--circle {
43
+ border-radius: var(--rv-border-radius-max);
44
+ }
45
+ .rv-avatar--square {
46
+ border-radius: var(--rv-avatar-border-radius);
47
+ }
48
+ .rv-avatar__img {
49
+ display: block;
50
+ width: 100%;
51
+ height: 100%;
52
+ }
File without changes
package/es/index.d.ts CHANGED
@@ -2,6 +2,7 @@ import './styles';
2
2
  export { default as hooks } from './hooks';
3
3
  export * from './button';
4
4
  export * from './badge';
5
+ export * from './avatar';
5
6
  export * from './field';
6
7
  export * from './flex';
7
8
  export * from './space';
@@ -72,3 +73,4 @@ export * from './floating-ball';
72
73
  export * from './water-mark';
73
74
  export * from './floating-panel';
74
75
  export * from './table';
76
+ export * from './treeSelect';
package/es/index.js CHANGED
@@ -2,6 +2,7 @@ import './styles';
2
2
  export { default as hooks } from './hooks';
3
3
  export * from './button';
4
4
  export * from './badge';
5
+ export * from './avatar';
5
6
  export * from './field';
6
7
  export * from './flex';
7
8
  export * from './space';
@@ -71,4 +72,5 @@ export * from './swiper';
71
72
  export * from './floating-ball';
72
73
  export * from './water-mark';
73
74
  export * from './floating-panel';
74
- export * from './table';
75
+ export * from './table';
76
+ export * from './treeSelect';
@@ -0,0 +1,85 @@
1
+ import React from 'react';
2
+ import { BaseTypeProps } from '../utils';
3
+ export declare type TreeSelectNode = {
4
+ /** 节点标题 */
5
+ title?: React.ReactNode;
6
+ /** 节点值 */
7
+ value?: string | number;
8
+ /** 节点键值 */
9
+ key?: string | number;
10
+ /** 子节点列表 */
11
+ children?: TreeSelectNode[];
12
+ /** 是否禁用节点 */
13
+ disabled?: boolean;
14
+ /** 是否为叶子节点 */
15
+ isLeaf?: boolean;
16
+ /** 自定义图标 */
17
+ icon?: React.ReactNode;
18
+ /** 节点的自定义类名 */
19
+ className?: string;
20
+ /** 节点的自定义样式 */
21
+ style?: React.CSSProperties;
22
+ /** 扩展字段 */
23
+ [key: string]: any;
24
+ };
25
+ export declare type TreeSelectFieldNames = {
26
+ title?: string;
27
+ value?: string;
28
+ key?: string;
29
+ children?: string;
30
+ };
31
+ export interface TreeSelectProps extends Omit<BaseTypeProps, 'children'> {
32
+ /** 当前选中的值 */
33
+ value?: string | number | Array<string | number>;
34
+ /** 默认选中的值 */
35
+ defaultValue?: string | number | Array<string | number>;
36
+ /** 树形数据 */
37
+ treeData?: TreeSelectNode[];
38
+ /** 自定义树节点的字段 */
39
+ fieldNames?: TreeSelectFieldNames;
40
+ /** 选择框默认文字 */
41
+ placeholder?: string;
42
+ /** 是否支持多选 */
43
+ multiple?: boolean;
44
+ /** 是否可以清除 */
45
+ allowClear?: boolean;
46
+ /** 是否禁用 */
47
+ disabled?: boolean;
48
+ /** 高度,默认 272px */
49
+ height?: number | string;
50
+ /** 左侧导航宽度 */
51
+ navWidth?: number | string;
52
+ /** 自定义右侧区域内容 */
53
+ contentRender?: (item: TreeSelectNode) => React.ReactNode;
54
+ /** 选中项改变时触发 */
55
+ onChange?: (value: string | number | Array<string | number>, selectedNodes: TreeSelectNode[]) => void;
56
+ /** 点击左侧导航时触发 */
57
+ onNavClick?: (index: number) => void;
58
+ /** 左侧导航当前选中项的索引 */
59
+ activeIndex?: number;
60
+ /** 默认选中的左侧导航索引 */
61
+ defaultActiveIndex?: number;
62
+ /** 左侧导航样式 */
63
+ navStyle?: React.CSSProperties;
64
+ /** 右侧内容样式 */
65
+ contentStyle?: React.CSSProperties;
66
+ /** 左侧导航类名 */
67
+ navClassName?: string;
68
+ /** 右侧内容类名 */
69
+ contentClassName?: string;
70
+ children?: React.ReactNode;
71
+ }
72
+ export interface TreeSelectItemProps {
73
+ /** 节点数据 */
74
+ node: TreeSelectNode;
75
+ /** 是否选中 */
76
+ selected: boolean;
77
+ /** 是否多选模式 */
78
+ multiple?: boolean;
79
+ /** 层级 */
80
+ level?: number;
81
+ /** 点击回调 */
82
+ onClick?: (node: TreeSelectNode) => void;
83
+ /** 字段映射 */
84
+ fieldNames?: TreeSelectFieldNames;
85
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,4 @@
1
+ import React from 'react';
2
+ import { TreeSelectProps } from './PropsType';
3
+ declare const TreeSelect: React.FC<TreeSelectProps>;
4
+ export default TreeSelect;
@@ -0,0 +1,259 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useMemo } from 'react';
3
+ import cls from 'clsx';
4
+ import { Success } from '@react-vant/icons';
5
+ import { createNamespace, extend } from '../utils';
6
+ import { useMemoizedFn } from '../hooks';
7
+ import useMergedState from '../hooks/use-merged-state';
8
+ import { mergeProps } from '../utils/get-default-props';
9
+ const [bem] = createNamespace('tree-select');
10
+ // TreeSelect 子项组件
11
+ const TreeSelectItem = ({
12
+ node,
13
+ selected,
14
+ multiple,
15
+ level = 0,
16
+ onClick,
17
+ fieldNames
18
+ }) => {
19
+ const {
20
+ title: titleKey = 'title',
21
+ value: valueKey = 'value',
22
+ children: childrenKey = 'children'
23
+ } = fieldNames || {};
24
+ const title = node[titleKey];
25
+ const children = node[childrenKey];
26
+ const hasChildren = children && children.length > 0;
27
+ const handleClick = () => {
28
+ if (!node.disabled) {
29
+ onClick === null || onClick === void 0 ? void 0 : onClick(node);
30
+ }
31
+ };
32
+ return _jsxs("div", Object.assign({
33
+ className: cls(bem('item-wrapper'))
34
+ }, {
35
+ children: [_jsxs("div", Object.assign({
36
+ className: cls(bem('item', {
37
+ active: selected,
38
+ disabled: node.disabled,
39
+ level: `level-${level}`
40
+ }), node.className),
41
+ style: node.style,
42
+ onClick: handleClick
43
+ }, {
44
+ children: [_jsxs("div", Object.assign({
45
+ className: cls(bem('item-content'))
46
+ }, {
47
+ children: [node.icon && _jsx("span", Object.assign({
48
+ className: cls(bem('item-icon'))
49
+ }, {
50
+ children: node.icon
51
+ })), _jsx("span", Object.assign({
52
+ className: cls(bem('item-title'))
53
+ }, {
54
+ children: title
55
+ }))]
56
+ })), selected && !multiple && _jsx(Success, {
57
+ className: cls(bem('item-selected-icon'))
58
+ }), multiple && _jsx("input", {
59
+ type: 'checkbox',
60
+ checked: selected,
61
+ disabled: node.disabled,
62
+ className: cls(bem('item-checkbox')),
63
+ readOnly: true
64
+ })]
65
+ })), hasChildren && _jsx("div", Object.assign({
66
+ className: cls(bem('item-children'))
67
+ }, {
68
+ children: children.map((child, index) => _jsx(TreeSelectItem, {
69
+ node: child,
70
+ selected: false,
71
+ multiple: multiple,
72
+ level: level + 1,
73
+ onClick: onClick,
74
+ fieldNames: fieldNames
75
+ }, child[valueKey] || index))
76
+ }))]
77
+ }));
78
+ };
79
+ const TreeSelect = p => {
80
+ const props = mergeProps(p, {
81
+ treeData: [],
82
+ height: 272,
83
+ navWidth: 80,
84
+ defaultActiveIndex: 0,
85
+ fieldNames: {
86
+ title: 'title',
87
+ value: 'value',
88
+ key: 'key',
89
+ children: 'children'
90
+ }
91
+ });
92
+ const {
93
+ title: titleKey,
94
+ value: valueKey,
95
+ key: keyKey,
96
+ children: childrenKey
97
+ } = extend({
98
+ title: 'title',
99
+ value: 'value',
100
+ key: 'key',
101
+ children: 'children'
102
+ }, props.fieldNames);
103
+ // 当前选中的值
104
+ const [selectedValue, setSelectedValue] = useMergedState({
105
+ value: props.value,
106
+ defaultValue: props.defaultValue
107
+ });
108
+ // 左侧导航当前选中的索引
109
+ const [activeIndex, setActiveIndex] = useMergedState({
110
+ value: props.activeIndex,
111
+ defaultValue: props.defaultActiveIndex
112
+ });
113
+ // 获取所有顶级节点(左侧导航)
114
+ const navItems = useMemo(() => {
115
+ return props.treeData || [];
116
+ }, [props.treeData]);
117
+ // 获取当前激活项的子节点(右侧内容)
118
+ const contentItems = useMemo(() => {
119
+ const currentNav = navItems[activeIndex];
120
+ return (currentNav === null || currentNav === void 0 ? void 0 : currentNav[childrenKey]) || [];
121
+ }, [navItems, activeIndex, childrenKey]);
122
+ // 判断值是否选中
123
+ const isValueSelected = useMemoizedFn(value => {
124
+ if (props.multiple) {
125
+ return Array.isArray(selectedValue) && selectedValue.includes(value);
126
+ }
127
+ return selectedValue === value;
128
+ });
129
+ // 查找节点
130
+ const findNode = useMemoizedFn((nodes, value) => {
131
+ for (const node of nodes) {
132
+ if (node[valueKey] === value) {
133
+ return node;
134
+ }
135
+ if (node[childrenKey]) {
136
+ const found = findNode(node[childrenKey], value);
137
+ if (found) return found;
138
+ }
139
+ }
140
+ return null;
141
+ });
142
+ // 获取所有选中的节点
143
+ const getSelectedNodes = useMemoizedFn(value => {
144
+ const values = Array.isArray(value) ? value : [value];
145
+ const nodes = [];
146
+ values.forEach(val => {
147
+ const node = findNode(props.treeData || [], val);
148
+ if (node) nodes.push(node);
149
+ });
150
+ return nodes;
151
+ });
152
+ // 左侧导航点击
153
+ const handleNavClick = useMemoizedFn(index => {
154
+ var _a;
155
+ setActiveIndex(index);
156
+ (_a = props.onNavClick) === null || _a === void 0 ? void 0 : _a.call(props, index);
157
+ });
158
+ // 右侧内容项点击
159
+ const handleItemClick = useMemoizedFn(node => {
160
+ var _a;
161
+ const value = node[valueKey];
162
+ let newValue;
163
+ if (props.multiple) {
164
+ const currentValues = Array.isArray(selectedValue) ? selectedValue : [];
165
+ if (currentValues.includes(value)) {
166
+ newValue = currentValues.filter(v => v !== value);
167
+ } else {
168
+ newValue = [...currentValues, value];
169
+ }
170
+ } else {
171
+ newValue = value;
172
+ }
173
+ setSelectedValue(newValue);
174
+ const selectedNodes = getSelectedNodes(newValue);
175
+ (_a = props.onChange) === null || _a === void 0 ? void 0 : _a.call(props, newValue, selectedNodes);
176
+ });
177
+ // 渲染左侧导航
178
+ const renderNav = () => _jsx("div", Object.assign({
179
+ className: cls(bem('nav'), props.navClassName),
180
+ style: Object.assign({
181
+ width: props.navWidth,
182
+ height: props.height
183
+ }, props.navStyle)
184
+ }, {
185
+ children: navItems.map((item, index) => {
186
+ const isActive = index === activeIndex;
187
+ const title = item[titleKey];
188
+ return _jsxs("div", Object.assign({
189
+ className: cls(bem('nav-item', {
190
+ active: isActive,
191
+ disabled: item.disabled
192
+ }), item.className),
193
+ style: item.style,
194
+ onClick: () => !item.disabled && handleNavClick(index)
195
+ }, {
196
+ children: [item.icon && _jsx("span", Object.assign({
197
+ className: cls(bem('nav-icon'))
198
+ }, {
199
+ children: item.icon
200
+ })), _jsx("span", Object.assign({
201
+ className: cls(bem('nav-text'))
202
+ }, {
203
+ children: title
204
+ })), item.badge && _jsx("span", Object.assign({
205
+ className: cls(bem('nav-badge'))
206
+ }, {
207
+ children: item.badge
208
+ }))]
209
+ }), item[keyKey] || item[valueKey] || index);
210
+ })
211
+ }));
212
+ // 渲染右侧内容
213
+ const renderContent = () => {
214
+ const currentNav = navItems[activeIndex];
215
+ if (props.contentRender && currentNav) {
216
+ return _jsx("div", Object.assign({
217
+ className: cls(bem('content'), props.contentClassName),
218
+ style: Object.assign({
219
+ height: props.height
220
+ }, props.contentStyle)
221
+ }, {
222
+ children: props.contentRender(currentNav)
223
+ }));
224
+ }
225
+ return _jsx("div", Object.assign({
226
+ className: cls(bem('content'), props.contentClassName),
227
+ style: Object.assign({
228
+ height: props.height
229
+ }, props.contentStyle)
230
+ }, {
231
+ children: contentItems.length > 0 ? _jsx("div", Object.assign({
232
+ className: cls(bem('items'))
233
+ }, {
234
+ children: contentItems.map((item, index) => {
235
+ const value = item[valueKey];
236
+ const selected = isValueSelected(value);
237
+ return _jsx(TreeSelectItem, {
238
+ node: item,
239
+ selected: selected,
240
+ multiple: props.multiple,
241
+ onClick: handleItemClick,
242
+ fieldNames: props.fieldNames
243
+ }, item[keyKey] || value || index);
244
+ })
245
+ })) : _jsx("div", Object.assign({
246
+ className: cls(bem('content-empty'))
247
+ }, {
248
+ children: props.placeholder || '暂无数据'
249
+ }))
250
+ }));
251
+ };
252
+ return _jsxs("div", Object.assign({
253
+ className: cls(props.className, bem()),
254
+ style: props.style
255
+ }, {
256
+ children: [renderNav(), renderContent()]
257
+ }));
258
+ };
259
+ export default TreeSelect;
@@ -0,0 +1,5 @@
1
+ import './style/index.less';
2
+ import TreeSelect from './TreeSelect';
3
+ export default TreeSelect;
4
+ export { TreeSelect };
5
+ export type { TreeSelectProps, TreeSelectNode, TreeSelectFieldNames, } from './PropsType';
@@ -0,0 +1,4 @@
1
+ import "./style/index.css";
2
+ import TreeSelect from './TreeSelect';
3
+ export default TreeSelect;
4
+ export { TreeSelect };