@aozi6666/bee-design 0.1.0 → 0.2.2

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 (102) hide show
  1. package/dist/App.d.ts +4 -0
  2. package/{build → dist}/components/AutoComplete/autoComplete.d.ts +2 -2
  3. package/{build → dist}/components/AutoComplete/autoComplete.types.d.ts +4 -4
  4. package/{build → dist}/components/AutoComplete/autoCompleteDropdown.d.ts +2 -2
  5. package/dist/components/AutoComplete/index.d.ts +4 -0
  6. package/{build → dist}/components/Button/button.d.ts +2 -2
  7. package/{build → dist}/components/Button/button.types.d.ts +1 -1
  8. package/dist/components/Button/index.d.ts +2 -0
  9. package/{build → dist}/components/Icon/icon.d.ts +2 -2
  10. package/dist/components/Icon/icon.types.d.ts +6 -0
  11. package/dist/components/Icon/index.d.ts +2 -0
  12. package/dist/components/Input/index.d.ts +4 -0
  13. package/dist/components/Input/input.d.ts +5 -0
  14. package/{build → dist}/components/Input/input.types.d.ts +4 -4
  15. package/{build → dist}/components/Menu/index.d.ts +4 -4
  16. package/{build → dist}/components/Menu/menu.d.ts +2 -10
  17. package/dist/components/Menu/menuContext.d.ts +9 -0
  18. package/{build → dist}/components/Menu/menuItem.d.ts +2 -2
  19. package/{build → dist}/components/Menu/subMenu.d.ts +1 -1
  20. package/dist/components/Progress/index.d.ts +2 -0
  21. package/dist/components/Progress/progress.d.ts +4 -0
  22. package/{build → dist}/components/Progress/progress.types.d.ts +2 -2
  23. package/dist/components/Transition/index.d.ts +3 -0
  24. package/dist/components/Transition/transition.d.ts +4 -0
  25. package/dist/components/Transition/transition.types.d.ts +9 -0
  26. package/{build → dist}/components/Upload/dragger.d.ts +1 -1
  27. package/dist/components/Upload/index.d.ts +2 -0
  28. package/{build → dist}/components/Upload/upload.d.ts +2 -2
  29. package/{build → dist}/components/Upload/upload.types.d.ts +7 -11
  30. package/{build → dist}/components/Upload/uploadList.d.ts +2 -2
  31. package/dist/hooks/useClickOutside.d.ts +3 -0
  32. package/dist/hooks/useDebounce.d.ts +2 -0
  33. package/dist/index.cjs +16272 -0
  34. package/dist/index.cjs.map +1 -0
  35. package/{build → dist}/index.css +24 -24
  36. package/dist/index.d.ts +9 -0
  37. package/dist/index.esm.js +709 -0
  38. package/dist/index.esm.js.map +1 -0
  39. package/dist/index.umd.js +14381 -0
  40. package/dist/index.umd.js.map +1 -0
  41. package/dist/main.d.ts +1 -0
  42. package/dist/setupIcons.d.ts +1 -0
  43. package/dist/setupTests.d.ts +1 -0
  44. package/package.json +61 -48
  45. package/README.md +0 -73
  46. package/build/App.d.ts +0 -4
  47. package/build/App.js +0 -137
  48. package/build/components/AutoComplete/autoComplete.js +0 -123
  49. package/build/components/AutoComplete/autoComplete.types.js +0 -1
  50. package/build/components/AutoComplete/autoCompleteDropdown.js +0 -17
  51. package/build/components/AutoComplete/index.d.ts +0 -4
  52. package/build/components/AutoComplete/index.js +0 -3
  53. package/build/components/Button/button.js +0 -43
  54. package/build/components/Button/button.types.js +0 -19
  55. package/build/components/Button/index.d.ts +0 -2
  56. package/build/components/Button/index.js +0 -2
  57. package/build/components/Icon/icon.js +0 -24
  58. package/build/components/Icon/icon.types.d.ts +0 -6
  59. package/build/components/Icon/icon.types.js +0 -2
  60. package/build/components/Icon/index.d.ts +0 -2
  61. package/build/components/Icon/index.js +0 -2
  62. package/build/components/Input/index.d.ts +0 -4
  63. package/build/components/Input/index.js +0 -3
  64. package/build/components/Input/input.d.ts +0 -5
  65. package/build/components/Input/input.js +0 -32
  66. package/build/components/Input/input.types.js +0 -1
  67. package/build/components/Menu/index.js +0 -9
  68. package/build/components/Menu/menu.js +0 -48
  69. package/build/components/Menu/menuItem.js +0 -20
  70. package/build/components/Menu/subMenu.js +0 -56
  71. package/build/components/Progress/index.d.ts +0 -2
  72. package/build/components/Progress/index.js +0 -2
  73. package/build/components/Progress/progress.d.ts +0 -4
  74. package/build/components/Progress/progress.js +0 -6
  75. package/build/components/Progress/progress.types.js +0 -2
  76. package/build/components/Transition/index.d.ts +0 -3
  77. package/build/components/Transition/index.js +0 -2
  78. package/build/components/Transition/transition.d.ts +0 -4
  79. package/build/components/Transition/transition.js +0 -18
  80. package/build/components/Transition/transition.types.d.ts +0 -10
  81. package/build/components/Transition/transition.types.js +0 -1
  82. package/build/components/Upload/dragger.js +0 -42
  83. package/build/components/Upload/index.d.ts +0 -2
  84. package/build/components/Upload/index.js +0 -2
  85. package/build/components/Upload/native/axios-react.js +0 -99
  86. package/build/components/Upload/native/from-html.js +0 -5
  87. package/build/components/Upload/upload.js +0 -192
  88. package/build/components/Upload/upload.types.js +0 -3
  89. package/build/components/Upload/uploadList.js +0 -13
  90. package/build/hooks/useClickOutside.d.ts +0 -3
  91. package/build/hooks/useClickOutside.js +0 -18
  92. package/build/hooks/useDebounce.d.ts +0 -2
  93. package/build/hooks/useDebounce.js +0 -14
  94. package/build/index.css.map +0 -1
  95. package/build/index.d.ts +0 -9
  96. package/build/index.js +0 -12
  97. package/build/main.d.ts +0 -1
  98. package/build/main.js +0 -7
  99. package/build/setupTests.d.ts +0 -1
  100. package/build/setupTests.js +0 -1
  101. /package/{build → dist}/components/Upload/native/axios-react.d.ts +0 -0
  102. /package/{build → dist}/components/Upload/native/from-html.d.ts +0 -0
@@ -1,6 +0,0 @@
1
- import type { FontAwesomeIconProps } from '@fortawesome/react-fontawesome';
2
- export type ThemeProps = 'primary' | 'secondary' | 'success' | 'info' | 'warning' | 'danger' | 'light' | 'dark';
3
- export interface IconProps extends FontAwesomeIconProps {
4
- /** 支持框架主题,根据主题显示不同的颜色 */
5
- theme?: ThemeProps;
6
- }
@@ -1,2 +0,0 @@
1
- // Icon 组件的类型定义拆分到单独文件
2
- export {};
@@ -1,2 +0,0 @@
1
- import Icon from './icon';
2
- export default Icon;
@@ -1,2 +0,0 @@
1
- import Icon from './icon';
2
- export default Icon;
@@ -1,4 +0,0 @@
1
- import Input from './input';
2
- export default Input;
3
- export { Input } from './input';
4
- export type * from './input.types';
@@ -1,3 +0,0 @@
1
- import Input from './input';
2
- export default Input;
3
- export { Input } from './input';
@@ -1,5 +0,0 @@
1
- import type { FC } from 'react';
2
- import type { InputProps } from './input.types';
3
- export type { InputProps, InputSize } from './input.types';
4
- export declare const Input: FC<InputProps>;
5
- export default Input;
@@ -1,32 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useMemo } from 'react';
3
- import classNames from 'classnames';
4
- import Icon from '../Icon/icon';
5
- export const Input = (props) => {
6
- const { disabled, size, icon, prepend, append, style, onChange, ...restProps } = props;
7
- const classes = useMemo(() => classNames('viking-input-wrapper', {
8
- [`input-size-${size}`]: size,
9
- 'input-group': prepend || append,
10
- 'input-group-prepend': !!prepend,
11
- 'input-group-append': !!append,
12
- }), [append, prepend, size]);
13
- const inputClasses = classNames('viking-input-inner', {
14
- 'is-disabled': disabled,
15
- });
16
- const handleChange = (e) => {
17
- if (onChange)
18
- onChange(e);
19
- };
20
- const renderPrepend = () => {
21
- if (!prepend)
22
- return null;
23
- return _jsx("div", { className: "viking-input-group-prepend", children: prepend });
24
- };
25
- const renderAppend = () => {
26
- if (!append && !icon)
27
- return null;
28
- return (_jsxs("div", { className: "viking-input-group-append", children: [append, icon ? (_jsx("div", { className: "icon-wrapper", children: _jsx(Icon, { icon: icon }) })) : null] }));
29
- };
30
- return (_jsxs("div", { className: classes, style: style, children: [renderPrepend(), _jsx("input", { className: inputClasses, disabled: disabled, onChange: handleChange, ...restProps }), renderAppend()] }));
31
- };
32
- export default Input;
@@ -1 +0,0 @@
1
- export {};
@@ -1,9 +0,0 @@
1
- import Menu, {} from './menu';
2
- import SubMenu, {} from './subMenu';
3
- import MenuItem, {} from './menuItem';
4
- // Menu 做类型转换
5
- const TransMenu = Menu;
6
- // 把子组件挂到 Menu 上
7
- TransMenu.Item = MenuItem;
8
- TransMenu.SubMenu = SubMenu;
9
- export default TransMenu;
@@ -1,48 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import React, { useState, createContext } from 'react';
3
- import classNames from 'classnames';
4
- export const MenuContext = createContext({ index: '0' });
5
- /**
6
- * 为网站提供导航功能的菜单。支持横向纵向两种模式,支持下拉菜单。
7
- *
8
- * ```javascript
9
- * import { Menu } from 'vikingship'
10
- *
11
- * //然后可以使用 Menu.Item 和 Menu.Submenu 访问选项和子下拉菜单组件
12
- * ```
13
- */
14
- export const Menu = ({ className, mode = 'horizontal', style, children, defaultIndex = '0', onSelect, defaultOpenSubMenus = [], }) => {
15
- const [currentActive, setActive] = useState(defaultIndex);
16
- const classes = classNames('viking-menu', className, {
17
- 'menu-vertical': mode === 'vertical',
18
- 'menu-horizontal': mode !== 'vertical',
19
- });
20
- const handleClick = (index) => {
21
- setActive(index);
22
- if (onSelect) {
23
- onSelect(index);
24
- }
25
- };
26
- const passedContext = {
27
- index: currentActive ? currentActive : '0',
28
- onSelect: handleClick,
29
- mode,
30
- defaultOpenSubMenus,
31
- };
32
- const renderChildren = () => {
33
- return React.Children.map(children, (child, index) => {
34
- const childElement = child;
35
- const { displayName } = childElement.type;
36
- if (displayName === 'MenuItem' || displayName === 'SubMenu') {
37
- return React.cloneElement(childElement, {
38
- index: index.toString()
39
- });
40
- }
41
- else {
42
- console.error("Warning: Menu has a child which is not a MenuItem component");
43
- }
44
- });
45
- };
46
- return (_jsx("ul", { className: classes, style: style, "data-testid": "test-menu", children: _jsx(MenuContext.Provider, { value: passedContext, children: renderChildren() }) }));
47
- };
48
- export default Menu;
@@ -1,20 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import React, { useContext } from 'react';
3
- import classNames from 'classnames';
4
- import { MenuContext } from './menu';
5
- export const MenuItem = (props) => {
6
- const { index, disabled, className, style, children } = props;
7
- const context = useContext(MenuContext);
8
- const classes = classNames('menu-item', className, {
9
- 'is-disabled': disabled,
10
- 'is-active': context.index === index
11
- });
12
- const handleClick = () => {
13
- if (context.onSelect && !disabled && (typeof index === 'string')) {
14
- context.onSelect(index);
15
- }
16
- };
17
- return (_jsx("li", { className: classes, style: style, onClick: handleClick, children: children }));
18
- };
19
- MenuItem.displayName = 'MenuItem';
20
- export default MenuItem;
@@ -1,56 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import React, { useContext, useState } from 'react';
3
- import classNames from 'classnames';
4
- import { MenuContext } from './menu';
5
- import Icon from '../Icon/icon';
6
- import Transition from '../Transition/transition';
7
- export const SubMenu = ({ index, title, children, className }) => {
8
- const context = useContext(MenuContext);
9
- const openedSubMenus = context.defaultOpenSubMenus;
10
- const isOpend = (index && context.mode === 'vertical') ? openedSubMenus.includes(index) : false;
11
- const [menuOpen, setOpen] = useState(isOpend);
12
- const classes = classNames('menu-item submenu-item', className, {
13
- 'is-active': context.index === index,
14
- 'is-opened': menuOpen,
15
- 'is-vertical': context.mode === 'vertical'
16
- });
17
- const handleClick = (e) => {
18
- e.preventDefault();
19
- setOpen(!menuOpen);
20
- };
21
- let timer;
22
- const handleMouse = (e, toggle) => {
23
- clearTimeout(timer);
24
- e.preventDefault();
25
- timer = setTimeout(() => {
26
- setOpen(toggle);
27
- }, 300);
28
- };
29
- const clickEvents = context.mode === 'vertical' ? {
30
- onClick: handleClick
31
- } : {};
32
- const hoverEvents = context.mode !== 'vertical' ? {
33
- onMouseEnter: (e) => { handleMouse(e, true); },
34
- onMouseLeave: (e) => { handleMouse(e, false); }
35
- } : {};
36
- const renderChildren = () => {
37
- const subMenuClasses = classNames('viking-submenu', {
38
- 'menu-opened': menuOpen
39
- });
40
- const childrenComponent = React.Children.map(children, (child, i) => {
41
- const childElement = child;
42
- if (childElement.type.displayName === 'MenuItem') {
43
- return React.cloneElement(childElement, {
44
- index: `${index}-${i}`
45
- });
46
- }
47
- else {
48
- console.error("Warning: SubMenu has a child which is not a MenuItem component");
49
- }
50
- });
51
- return (_jsx(Transition, { in: menuOpen, timeout: 300, animation: "zoom-in-top", children: _jsx("ul", { className: subMenuClasses, children: childrenComponent }) }));
52
- };
53
- return (_jsxs("li", { className: classes, ...hoverEvents, children: [_jsxs("div", { className: "submenu-title", ...clickEvents, children: [title, _jsx(Icon, { icon: "angle-down", className: "arrow-icon" })] }), renderChildren()] }, index));
54
- };
55
- SubMenu.displayName = 'SubMenu';
56
- export default SubMenu;
@@ -1,2 +0,0 @@
1
- import Progress from './progress';
2
- export default Progress;
@@ -1,2 +0,0 @@
1
- import Progress from './progress';
2
- export default Progress;
@@ -1,4 +0,0 @@
1
- import type { FC } from 'react';
2
- import type { ProgressProps } from './progress.types';
3
- declare const Progress: FC<ProgressProps>;
4
- export default Progress;
@@ -1,6 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- const Progress = (props) => {
3
- const { percent, strokeHeight = 15, showText = true, styles, theme = 'primary', } = props;
4
- return (_jsx("div", { className: "viking-progress-bar", style: styles, children: _jsx("div", { className: "viking-progress-bar-outer", style: { height: `${strokeHeight}px` }, children: _jsx("div", { className: `viking-progress-bar-inner color-${theme}`, style: { width: `${percent}%` }, children: showText && _jsx("span", { className: "inner-text", children: `${percent}%` }) }) }) }));
5
- };
6
- export default Progress;
@@ -1,2 +0,0 @@
1
- // Progress 组件的类型定义,单独拆分成文件,便于复用
2
- export {};
@@ -1,3 +0,0 @@
1
- import Transition from './transition';
2
- export default Transition;
3
- export type { AnimationName, TransitionProps } from './transition';
@@ -1,2 +0,0 @@
1
- import Transition from './transition';
2
- export default Transition;
@@ -1,4 +0,0 @@
1
- import type { TransitionProps } from './transition.types';
2
- export type { AnimationName, TransitionProps } from './transition.types';
3
- declare const Transition: (props: TransitionProps) => import("react/jsx-runtime").JSX.Element;
4
- export default Transition;
@@ -1,18 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import { useRef } from 'react';
3
- import { CSSTransition } from 'react-transition-group';
4
- const Transition = (props) => {
5
- const { children, classNames: classNamesProp, animation, wrapper = false, unmountOnExit = true, appear = true, addEndListener, ...restProps } = props;
6
- const cls = animation ? animation : classNamesProp;
7
- const nodeRef = useRef(null);
8
- const transitionProps = {
9
- classNames: cls,
10
- unmountOnExit,
11
- appear,
12
- ...restProps,
13
- };
14
- if (addEndListener)
15
- transitionProps.addEndListener = addEndListener;
16
- return (_jsx(CSSTransition, { nodeRef: nodeRef, ...transitionProps, children: _jsx("div", { ref: nodeRef, "data-transition-wrapper": wrapper ? 'true' : 'false', children: children }) }));
17
- };
18
- export default Transition;
@@ -1,10 +0,0 @@
1
- import type { ReactNode } from 'react';
2
- import type { CSSTransitionProps } from 'react-transition-group/CSSTransition';
3
- export type AnimationName = 'zoom-in-top' | 'zoom-in-left' | 'zoom-in-bottom' | 'zoom-in-right';
4
- export type TransitionProps = Omit<CSSTransitionProps<HTMLElement>, 'addEndListener' | 'timeout'> & {
5
- animation?: AnimationName;
6
- wrapper?: boolean;
7
- children?: ReactNode;
8
- timeout: CSSTransitionProps<HTMLElement>['timeout'];
9
- addEndListener?: (node: HTMLElement, done: () => void) => void;
10
- };
@@ -1 +0,0 @@
1
- export {};
@@ -1,42 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- /* Dragger 是专门处理拖拽上传逻辑的子组件:
3
- - 只负责获取拖拽的文件
4
- - 上传文件还是靠 Upload
5
- 监听浏览器拖拽事件 → 拿到拖进来的文件 → 传回 Upload 组件
6
-
7
- 浏览器 Drag & Drop API 事件:
8
- dragenter → 进入区域
9
- dragover → 在区域上方拖动
10
- dragleave → 离开区域
11
- drop → 松手放下文件(包含拖进来的文件)
12
- */
13
- import { useState } from 'react';
14
- import classNames from 'classnames';
15
- export const Dragger = (props) => {
16
- const { onFile, children } = props;
17
- // 负责拖拽样式
18
- const [dragOver, setDragOver] = useState(false);
19
- // 使用 `classNames` 拼 `className`:
20
- const klass = classNames('viking-uploader-dragger', {
21
- // 如果 `dragOver === true` 时,再加一个:`is-dragover`
22
- 'is-dragover': dragOver
23
- });
24
- // 上传流程
25
- const handleDrop = (e) => {
26
- e.preventDefault(); // 阻止默认行为
27
- setDragOver(false); // 拖拽结束:改变拖拽样式
28
- // dataTransfer: 浏览器 drop-API 的对象
29
- // 包含: files(文件列表FileList)、items、types
30
- // 通过 onFile回调 传回 Upload 处理
31
- onFile(e.dataTransfer.files);
32
- };
33
- // 回调: 控制拖拽状态(改变样式)
34
- const handleDrag = (e, over) => {
35
- e.preventDefault();
36
- setDragOver(over);
37
- };
38
- return (_jsx("div", { className: klass,
39
- // e: 监听DragEvent拖拽事件对象
40
- onDragOver: e => { handleDrag(e, true); }, onDragLeave: e => { handleDrag(e, false); }, onDrop: handleDrop, children: children }));
41
- };
42
- export default Dragger;
@@ -1,2 +0,0 @@
1
- import Upload from './upload';
2
- export default Upload;
@@ -1,2 +0,0 @@
1
- import Upload from './upload';
2
- export default Upload;
@@ -1,99 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import axios from 'axios';
3
- const AxiosReact = () => {
4
- /*
5
- e: 这次变化事件的事件对象 -- “事件说明单”
6
- e = {
7
- 谁触发的这次变化,
8
- 发生了什么,
9
- 当前 input 里有什么值
10
- }
11
-
12
- e.target: 触发这次事件的那个 DOM 元素(input 节点本身)
13
- e: React.ChangeEvent<HTMLInputElement>: 给参数 e 标注类型
14
- - React 里的 ChangeEvent
15
- - 这个事件来自 <HTMLInputElement> 泛型参数
16
-
17
- 提前告诉大家:e 是“来自 input 元素的 change 事件对象” (贴标签)
18
- - 放心大胆用:e.target.files
19
- */
20
- const handleFileChange = (e) => {
21
- // 1)取出 用户上传的 文件
22
- /*
23
- input type="file" 文件类型输入框:
24
- - 有一个特殊属性 files: 用户当前选中的 文件列表 FileList
25
- - 用户一次性可以选3个文件
26
- FileList {
27
- // File对象
28
- 0: File {
29
- name: "a.png",
30
- size: 12345,
31
- type: "image/png"
32
-
33
- // 内部隐藏
34
- [[BinaryData]]: <文件二进制>0100110101...
35
- },
36
-
37
- 1: File {
38
- name: "b.jpg",
39
- size: 23456,
40
- type: "image/jpeg"
41
- },
42
-
43
- 2: File {
44
- name: "c.pdf",
45
- size: 34567,
46
- type: "application/pdf"
47
- },
48
-
49
- length: 3
50
- }
51
- */
52
- // 获取 文件列表
53
- const files = e.target.files;
54
- if (files) {
55
- // 从文件列表中取出 第一个 File 对象 : 文件信息 + 文件内容(二进制)
56
- const uploadedFile = files[0];
57
- // 2)将 本次文件 放进 formData
58
- const formData = new FormData();
59
- // key-value 形式
60
- formData.append("file", uploadedFile);
61
- // 3)使用 Axios 发送请求
62
- /*
63
- 常见参数: axios.post(url, data, config)
64
- - url:地址
65
- - data: 请求体body (这次 POST 请求要携带的数据)
66
- - config配置项 对象:
67
- */
68
- axios.post("https://jsonplaceholder.typicode.com/posts",
69
- // Axios 发出去的不是 FormData 对象本身
70
- /*
71
- FormData 里装的是一个 File 对象引用
72
- -> 当 Axios / fetch 看到: body: formData
73
- -> 浏览器会开始做“编码
74
- -> 先遍历 FormData 里的每一项
75
- -> 变成 HTTP body 里的某一个 "part"
76
- -> 每一个"part"包含:(文件相关的描述信息 + 二进制内容)
77
- ------WebKitBoundary123【包裹边界】
78
- Content-Disposition: form-data; name="file"; filename="a.png"
79
- Content-Type: image/png
80
-
81
- <文件二进制内容>
82
- ------WebKitBoundary123--【结束边界】
83
- */
84
- formData, {
85
- // 设置 请求头信息
86
- headers: {
87
- // 表单文件数据
88
- 'Content-Type': 'multipart/form-data'
89
- }
90
- }).then(resp => {
91
- console.log(resp);
92
- });
93
- }
94
- };
95
- return (_jsx("div", { className: "AxiosReact", style: { marginTop: '100px', marginLeft: '100px' }, children: _jsx("input", { type: "file",
96
- // {/* 原生必须传,自定义不用传 name="myFile" */}
97
- onChange: handleFileChange }) }));
98
- };
99
- export default AxiosReact;
@@ -1,5 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- const FromHtml = () => {
3
- return (_jsx("div", { className: "App", style: { marginTop: '100px', marginLeft: '100px' }, children: _jsxs("form", { method: "post", encType: "multipart/form-data", action: "https://jsonplaceholder.typicode.com/posts", children: [_jsx("input", { type: "file", name: "myFile" }), _jsx("button", { type: "submit", children: "Submit" })] }) }));
4
- };
5
- export default FromHtml;
@@ -1,192 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useRef, useState } from 'react';
3
- import axios from 'axios';
4
- import UploadList from './uploadList';
5
- import Dragger from './dragger';
6
- /**
7
- * 通过点击或者拖拽上传文件
8
- * ### 引用方法
9
- *
10
- * ~~~js
11
- * import { Upload } from 'vikingship'
12
- * ~~~
13
- */
14
- export const Upload = (props) => {
15
- const { action, defaultFileList, beforeUpload, onProgress, onSuccess, onError, onChange, onRemove, name = 'file', headers, data, withCredentials, accept, multiple, children, drag, } = props;
16
- // 文件输入框 ref 引用
17
- const fileInput = useRef(null);
18
- // (子组件)页面上 正在显示 的 上传文件列表
19
- const [fileList, setFileList] = useState(defaultFileList || []);
20
- // **`UploadList`** 子组件: 从 上传文件列表fileList 渲染一堆 列表项 class
21
- // 上传列表状态更新器
22
- const updateFileList = (updateFile, updateObj) => {
23
- setFileList(prevList => {
24
- return prevList.map(file => {
25
- // 在列表里找到同一个 uid 文件
26
- if (file.uid === updateFile.uid) {
27
- // 更新部分字段
28
- return { ...file, ...updateObj };
29
- }
30
- else {
31
- return file;
32
- }
33
- });
34
- });
35
- };
36
- // 点击上传回调:用户点击 上传文件 输入框
37
- const handleClick = () => {
38
- // 用 ref 拿到“隐藏的” input元素
39
- if (fileInput.current) {
40
- // 调用浏览器的原生能力: 弹出 系统级文件选择框
41
- fileInput.current.click();
42
- }
43
- };
44
- // 文件上传回调:当有文件传来的时候触发
45
- const handleFileChange = (e) => {
46
- // 获取文件列表:类型为 FileList
47
- const files = e.target.files;
48
- if (!files) {
49
- return;
50
- }
51
- // 调用 上传文件函数(含发送请求):决定 每个/不同文件 怎么处理
52
- uploadFiles(files);
53
- // 清空 文件输入框
54
- if (fileInput.current) {
55
- fileInput.current.value = '';
56
- }
57
- };
58
- // 传递给 UploadList 子组件的 回调函数
59
- const handleRemove = (file) => {
60
- setFileList((prevList) => {
61
- return prevList.filter(item => item.uid !== file.uid);
62
- });
63
- if (onRemove) {
64
- onRemove(file);
65
- }
66
- };
67
- // 函数: 上传文件: 决定 每个文件 上传
68
- // (beforeUpload: “上传前钩子”)
69
- const uploadFiles = (files, test) => {
70
- // 传来的文件列表 FileList类型,不是数组 =》 转为数组
71
- let postFiles = Array.from(files);
72
- //
73
- if (test) {
74
- console.log('drag', postFiles[0]);
75
- }
76
- // 遍历 数组 每一项
77
- postFiles.forEach(file => {
78
- // 没有配置 beforeUpload,直接上传
79
- if (!beforeUpload) {
80
- post(file);
81
- }
82
- else {
83
- // 用户使用了 beforeUpload => 需要等待 用户的异步处理结果(例如压缩图片)
84
- // beforeUpload(file)用户在钩子里写的回调: 会返回 Promise<newFile>
85
- // 获取 Promise<newFile> 用这个处理完的 File 对象发送
86
- // 执行用户传进来的回调函数,并把它的返回值接住,放进 result
87
- const result = beforeUpload(file);
88
- //
89
- if (result && result instanceof Promise) {
90
- // 获取 异步回调 reslove(newFile)后的 newFile
91
- result.then(processedFile => {
92
- post(processedFile); // 发送用户异步处理完的 新File文件
93
- });
94
- }
95
- else if (result !== false) {
96
- // 用户使用了拦截:return false ==> 永远不会触发 post, 不上传
97
- // 返回 true → 上传原文件
98
- post(file);
99
- }
100
- }
101
- });
102
- };
103
- // 函数: 发axios请求
104
- const post = (file) => {
105
- // 改造浏览器原生File,创建 内部文件对象 `_file` (文件本体 + 上传状态)
106
- let _file = {
107
- uid: Date.now() + 'upload-file',
108
- status: 'ready',
109
- name: file.name,
110
- size: file.size,
111
- percent: 0,
112
- raw: file
113
- };
114
- // 请求发送之前放进 fileList,列表先显示出来
115
- setFileList(prevList => {
116
- return [_file, ...prevList];
117
- });
118
- // 2) 构建 `FormData`
119
- const formData = new FormData();
120
- formData.append(name || 'file', file);
121
- // 如果传了 `data`, 额外字段也 append 进 FormData
122
- // (例如 `userId`、`token`)
123
- if (data) {
124
- Object.keys(data).forEach(key => {
125
- formData.append(key, data[key]);
126
- });
127
- }
128
- // 使用 axios 发送 POST 请求
129
- axios.post(action, formData, {
130
- headers: {
131
- ...headers,
132
- 'Content-Type': 'multipart/form-data'
133
- },
134
- // 跨域请求 凭证信息(Cookie)
135
- // 需要 后端 允许跨域携带凭证: Access-Control-Allow-Credentials: true
136
- withCredentials,
137
- // axios 提供的 请求配置回调(“系统回调”)
138
- // (不需要手动调用)上传过程中,axios 内部自动不断触发 onUploadProgress
139
- onUploadProgress: (e) => {
140
- // 把字节进度算成百分比
141
- const total = e.total ?? 0;
142
- const percentage = total ? Math.round((e.loaded * 100) / total) : 0;
143
- // 更新 fileList 中这条文件的 percent/status
144
- if (percentage < 100) {
145
- // 更新 React state(驱动UI):让 UploadList 子组件重新渲染
146
- updateFileList(_file, { percent: percentage, status: 'uploading' });
147
- // 更新当前 _file 对象,保证传给回调的值是新的
148
- _file.status = 'uploading';
149
- _file.percent = percentage;
150
- // 将 axios 的 onUploadProgress 得到的上传进度结果,包装一层
151
- // 提供给 Upload 组件的外部使用者 外部钩子onProgress:给组件外部使用
152
- if (onProgress) {
153
- onProgress(percentage, _file);
154
- }
155
- }
156
- }
157
- }).then(resp => {
158
- // 成功时:更新React UI内部状态
159
- updateFileList(_file, { status: 'success', response: resp.data });
160
- // 更新当前 _file 对象,保证传给回调的值是新的
161
- _file.status = 'success';
162
- _file.response = resp.data;
163
- // 通知外部 onSuccess / onChange 钩子
164
- if (onSuccess) {
165
- onSuccess(resp.data, _file);
166
- }
167
- if (onChange) {
168
- onChange(_file);
169
- }
170
- }).catch(err => {
171
- // 失败时:更新React UI内部状态
172
- updateFileList(_file, { status: 'error', error: err });
173
- // 更新当前 _file 对象,保证传给回调的值是新的
174
- _file.status = 'error';
175
- _file.error = err;
176
- //
177
- if (onError) {
178
- onError(err, _file);
179
- }
180
- if (onChange) {
181
- onChange(_file);
182
- }
183
- });
184
- };
185
- return (_jsxs("div", { className: "viking-upload-component", children: [_jsxs("div", { className: "viking-upload-input", style: { display: 'inline-block' }, onClick: handleClick, children: [children, drag ?
186
- // 传给 Dragger子组件回调函数 onFile
187
- // 当用户拖拽文件,Dragger 的onDrop状态触发 onFile(files)
188
- _jsx(Dragger, { onFile: (files) => { uploadFiles(files, true); }, children: children }) :
189
- // 如果 drag = false, 直接渲染 children(普通模式)
190
- children, _jsx("input", { className: "viking-file-input", style: { display: 'none' }, ref: fileInput, onChange: handleFileChange, type: "file", accept: accept, multiple: multiple })] }), _jsx(UploadList, { fileList: fileList, onRemove: handleRemove })] }));
191
- };
192
- export default Upload;
@@ -1,3 +0,0 @@
1
- // Upload 组件相关的 TS 类型定义
2
- // 独立成文件,方便在多个子组件之间复用
3
- export {};