deepsea-components 5.5.14 → 5.6.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.
@@ -44,10 +44,12 @@ export declare function getFileData<T extends InputFileDataType>(file: File, typ
44
44
  export declare const InputFile: import("react").ForwardRefExoticComponent<InputFileProps & import("react").RefAttributes<HTMLInputElement>>;
45
45
  export type InputFileButtonProps = ButtonHTMLAttributes<HTMLButtonElement> & {
46
46
  input: InputFileProps;
47
+ dragFile?: boolean;
47
48
  };
48
49
  /** 专用于读取文件的 button 组件 */
49
50
  export declare const InputFileButton: import("react").ForwardRefExoticComponent<ButtonHTMLAttributes<HTMLButtonElement> & {
50
51
  input: InputFileProps;
52
+ dragFile?: boolean | undefined;
51
53
  } & import("react").RefAttributes<HTMLButtonElement>>;
52
54
  export interface ImportExcelProps extends Omit<InputFileProps, "multiple" | "onChange" | "accept" | "type"> {
53
55
  onChange?: (data: Record<string, string>[]) => void;
@@ -79,27 +79,70 @@ var InputFile = (0, import_react.forwardRef)((props, ref) => {
79
79
  file: files[0]
80
80
  });
81
81
  }
82
- setDisabled(false);
82
+ } finally {
83
83
  if (clearAfterChange)
84
84
  input.value = "";
85
- } catch (error) {
86
85
  setDisabled(false);
87
- if (clearAfterChange)
88
- input.value = "";
89
- throw error;
90
86
  }
91
87
  }
92
88
  return /* @__PURE__ */ React.createElement("input", { ref, disabled: disabled || inputDisabled, type: "file", multiple, onChange: onInputChange, ...rest });
93
89
  });
94
90
  var InputFileButton = (0, import_react.forwardRef)((props, ref) => {
95
- const { onClick, input: inputProps, ...rest } = props;
96
- const { style, ...restInputProps } = inputProps;
91
+ const { onClick: _onClick, input: inputProps, onDrop: _onDrop, onDragOver: _onDragOver, dragFile, disabled: _disabled, ...rest } = props;
92
+ const { style, disabled: __disabled, multiple, onChange, type = "file", ...restInputProps } = inputProps;
93
+ const [disabled, setDisabled] = (0, import_react.useState)(false);
97
94
  const input = (0, import_react.useRef)(null);
98
- function onBtnClick(e) {
95
+ function onClick(e) {
99
96
  input.current?.click();
100
- onClick?.(e);
97
+ _onClick?.(e);
101
98
  }
102
- return /* @__PURE__ */ React.createElement(import_react.Fragment, null, /* @__PURE__ */ React.createElement(InputFile, { ref: input, style: { display: "none", ...style }, ...restInputProps }), /* @__PURE__ */ React.createElement("button", { ref, type: "button", onClick: onBtnClick, ...rest }));
99
+ async function onDrop(e) {
100
+ _onDrop?.(e);
101
+ if (disabled || !dragFile)
102
+ return;
103
+ e.preventDefault();
104
+ const { files } = e.dataTransfer;
105
+ if (!files || files.length === 0)
106
+ return;
107
+ setDisabled(true);
108
+ try {
109
+ if (multiple) {
110
+ const result = [];
111
+ for (const file of Array.from(files)) {
112
+ result.push({
113
+ result: await getFileData(file, type),
114
+ file
115
+ });
116
+ }
117
+ onChange?.(result);
118
+ } else {
119
+ onChange?.({
120
+ result: await getFileData(files[0], type),
121
+ file: files[0]
122
+ });
123
+ }
124
+ } finally {
125
+ setDisabled(false);
126
+ }
127
+ }
128
+ function onDragOver(e) {
129
+ _onDragOver?.(e);
130
+ if (disabled || !dragFile)
131
+ return;
132
+ e.preventDefault();
133
+ }
134
+ return /* @__PURE__ */ React.createElement(import_react.Fragment, null, /* @__PURE__ */ React.createElement(
135
+ InputFile,
136
+ {
137
+ ref: input,
138
+ disabled: disabled || _disabled || __disabled,
139
+ style: { display: "none", ...style },
140
+ multiple,
141
+ onChange,
142
+ type,
143
+ ...restInputProps
144
+ }
145
+ ), /* @__PURE__ */ React.createElement("button", { ref, type: "button", disabled: disabled || _disabled, onClick, onDrop, onDragOver, ...rest }));
103
146
  });
104
147
  var ImportExcel = (0, import_react.forwardRef)((props, ref) => {
105
148
  const { onChange, ...rest } = props;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/components/InputFile.tsx"],
4
- "sourcesContent": ["\"use client\"\r\n\r\nimport { ButtonHTMLAttributes, ChangeEvent, Fragment, InputHTMLAttributes, MouseEvent as ReactMouseEvent, forwardRef, useRef, useState } from \"react\"\r\nimport { read, utils, writeFile } from \"xlsx\"\r\n\r\nexport interface InputFileDataTypes {\r\n base64: string\r\n text: string\r\n arrayBuffer: ArrayBuffer\r\n binary: string\r\n file: File\r\n}\r\n\r\nexport type InputFileDataType = keyof InputFileDataTypes\r\n\r\nexport interface InputFileData<T> {\r\n result: T\r\n file: File\r\n}\r\n\r\nexport type InputFileProps = (\r\n | {\r\n multiple?: false\r\n type: \"base64\" | \"text\" | \"binary\"\r\n onChange?: (data: InputFileData<string>) => void\r\n }\r\n | {\r\n multiple?: false\r\n type: \"arrayBuffer\"\r\n onChange?: (data: InputFileData<ArrayBuffer>) => void\r\n }\r\n | {\r\n multiple?: false\r\n type?: \"file\"\r\n onChange?: (data: InputFileData<File>) => void\r\n }\r\n | {\r\n multiple: true\r\n type: \"base64\" | \"text\" | \"binary\"\r\n onChange?: (data: InputFileData<string>[]) => void\r\n }\r\n | {\r\n multiple: true\r\n type: \"arrayBuffer\"\r\n onChange?: (data: InputFileData<ArrayBuffer>[]) => void\r\n }\r\n | {\r\n multiple: true\r\n type?: \"file\"\r\n onChange?: (data: InputFileData<File>[]) => void\r\n }\r\n) &\r\n Omit<InputHTMLAttributes<HTMLInputElement>, \"onChange\" | \"multiple\" | \"type\"> & {\r\n /** 是否在捕获文件后清除 input 上的文件,默认为 false,主要区别在于如果不清除,连续两次选择同样的文件不会触发 onChange 事件,如果用于 form 表单,请设置为 flase */\r\n clearAfterChange?: boolean\r\n }\r\n\r\nexport async function getFileData<T extends InputFileDataType>(file: File, type: T): Promise<InputFileDataTypes[T]> {\r\n const fileReader = new FileReader()\r\n switch (type) {\r\n case \"arrayBuffer\":\r\n fileReader.readAsArrayBuffer(file)\r\n break\r\n case \"binary\":\r\n fileReader.readAsBinaryString(file)\r\n break\r\n case \"base64\":\r\n fileReader.readAsDataURL(file)\r\n break\r\n case \"text\":\r\n fileReader.readAsText(file)\r\n break\r\n default:\r\n return file as any\r\n }\r\n return new Promise(resolve => {\r\n fileReader.addEventListener(\"load\", () => {\r\n resolve(fileReader.result as any)\r\n })\r\n })\r\n}\r\n\r\n/** 专用于读取文件的组件 */\r\nexport const InputFile = forwardRef<HTMLInputElement, InputFileProps>((props, ref) => {\r\n const { multiple = false, type = \"file\", onChange, disabled: inputDisabled, clearAfterChange, ...rest } = props\r\n const [disabled, setDisabled] = useState(false)\r\n\r\n async function onInputChange(e: ChangeEvent<HTMLInputElement>) {\r\n const input = e.target\r\n const { files } = input\r\n if (!files || files.length === 0) return\r\n setDisabled(true)\r\n try {\r\n if (multiple) {\r\n const result: any[] = []\r\n for (const file of Array.from(files)) {\r\n result.push({\r\n result: await getFileData(file, type),\r\n file\r\n })\r\n }\r\n onChange?.(result as any)\r\n } else {\r\n onChange?.({\r\n result: await getFileData(files[0], type),\r\n file: files[0]\r\n } as any)\r\n }\r\n setDisabled(false)\r\n if (clearAfterChange) input.value = \"\"\r\n } catch (error) {\r\n setDisabled(false)\r\n if (clearAfterChange) input.value = \"\"\r\n throw error\r\n }\r\n }\r\n\r\n return <input ref={ref} disabled={disabled || inputDisabled} type=\"file\" multiple={multiple} onChange={onInputChange} {...rest} />\r\n})\r\n\r\nexport type InputFileButtonProps = ButtonHTMLAttributes<HTMLButtonElement> & {\r\n input: InputFileProps\r\n}\r\n\r\n/** 专用于读取文件的 button 组件 */\r\nexport const InputFileButton = forwardRef<HTMLButtonElement, InputFileButtonProps>((props, ref) => {\r\n const { onClick, input: inputProps, ...rest } = props\r\n const { style, ...restInputProps } = inputProps\r\n const input = useRef<HTMLInputElement>(null)\r\n\r\n function onBtnClick(e: ReactMouseEvent<HTMLButtonElement, MouseEvent>) {\r\n input.current?.click()\r\n onClick?.(e)\r\n }\r\n\r\n return (\r\n <Fragment>\r\n <InputFile ref={input} style={{ display: \"none\", ...style }} {...restInputProps} />\r\n <button ref={ref} type=\"button\" onClick={onBtnClick} {...rest} />\r\n </Fragment>\r\n )\r\n})\r\n\r\nexport interface ImportExcelProps extends Omit<InputFileProps, \"multiple\" | \"onChange\" | \"accept\" | \"type\"> {\r\n onChange?: (data: Record<string, string>[]) => void\r\n}\r\n\r\n/** 专门用于读取 excel 的组件 */\r\nexport const ImportExcel = forwardRef<HTMLInputElement, ImportExcelProps>((props, ref) => {\r\n const { onChange, ...rest } = props\r\n\r\n function onInputChange(data: InputFileData<ArrayBuffer>) {\r\n const wb = read(data.result)\r\n const result = utils.sheet_to_json<any>(wb.Sheets[wb.SheetNames[0]])\r\n if (typeof result === \"object\") {\r\n const $ = result.map(it => {\r\n const _: Record<string, string> = {}\r\n Object.keys(it)\r\n .filter(key => key !== \"__rowNum__\")\r\n .forEach(key => (_[key] = String(it[key])))\r\n return _\r\n })\r\n onChange?.($)\r\n }\r\n }\r\n\r\n return <InputFile ref={ref} accept=\".xlsx\" type=\"arrayBuffer\" onChange={onInputChange} {...rest} />\r\n})\r\n\r\n/** 手动导出 excel */\r\nexport function exportExcel(data: Record<string, string>[], name: string) {\r\n const workSheet = utils.json_to_sheet(data)\r\n const workBook = utils.book_new()\r\n utils.book_append_sheet(workBook, workSheet)\r\n writeFile(workBook, `${name}${name.endsWith(\".xlsx\") ? \"\" : \".xlsx\"}`)\r\n}\r\n\r\nexport interface ExportExcelProps extends ButtonHTMLAttributes<HTMLButtonElement> {\r\n data: Record<string, string>[]\r\n fileName: string\r\n}\r\n\r\n/** 导出 excel 的 button 组件 */\r\nexport const ExportExcel = forwardRef<HTMLButtonElement, ExportExcelProps>((props, ref) => {\r\n const { data, fileName, onClick, ...rest } = props\r\n\r\n function onButtonClick(e: ReactMouseEvent<HTMLButtonElement, MouseEvent>) {\r\n exportExcel(data, fileName)\r\n onClick?.(e)\r\n }\r\n\r\n return <button ref={ref} onClick={onButtonClick} {...rest} />\r\n})\r\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["\"use client\"\r\n\r\nimport { ButtonHTMLAttributes, ChangeEvent, Fragment, InputHTMLAttributes, MouseEvent as ReactMouseEvent, forwardRef, useRef, useState, DragEvent } from \"react\"\r\nimport { read, utils, writeFile } from \"xlsx\"\r\n\r\nexport interface InputFileDataTypes {\r\n base64: string\r\n text: string\r\n arrayBuffer: ArrayBuffer\r\n binary: string\r\n file: File\r\n}\r\n\r\nexport type InputFileDataType = keyof InputFileDataTypes\r\n\r\nexport interface InputFileData<T> {\r\n result: T\r\n file: File\r\n}\r\n\r\nexport type InputFileProps = (\r\n | {\r\n multiple?: false\r\n type: \"base64\" | \"text\" | \"binary\"\r\n onChange?: (data: InputFileData<string>) => void\r\n }\r\n | {\r\n multiple?: false\r\n type: \"arrayBuffer\"\r\n onChange?: (data: InputFileData<ArrayBuffer>) => void\r\n }\r\n | {\r\n multiple?: false\r\n type?: \"file\"\r\n onChange?: (data: InputFileData<File>) => void\r\n }\r\n | {\r\n multiple: true\r\n type: \"base64\" | \"text\" | \"binary\"\r\n onChange?: (data: InputFileData<string>[]) => void\r\n }\r\n | {\r\n multiple: true\r\n type: \"arrayBuffer\"\r\n onChange?: (data: InputFileData<ArrayBuffer>[]) => void\r\n }\r\n | {\r\n multiple: true\r\n type?: \"file\"\r\n onChange?: (data: InputFileData<File>[]) => void\r\n }\r\n) &\r\n Omit<InputHTMLAttributes<HTMLInputElement>, \"onChange\" | \"multiple\" | \"type\"> & {\r\n /** 是否在捕获文件后清除 input 上的文件,默认为 false,主要区别在于如果不清除,连续两次选择同样的文件不会触发 onChange 事件,如果用于 form 表单,请设置为 flase */\r\n clearAfterChange?: boolean\r\n }\r\n\r\nexport async function getFileData<T extends InputFileDataType>(file: File, type: T): Promise<InputFileDataTypes[T]> {\r\n const fileReader = new FileReader()\r\n switch (type) {\r\n case \"arrayBuffer\":\r\n fileReader.readAsArrayBuffer(file)\r\n break\r\n case \"binary\":\r\n fileReader.readAsBinaryString(file)\r\n break\r\n case \"base64\":\r\n fileReader.readAsDataURL(file)\r\n break\r\n case \"text\":\r\n fileReader.readAsText(file)\r\n break\r\n default:\r\n return file as any\r\n }\r\n return new Promise(resolve => {\r\n fileReader.addEventListener(\"load\", () => {\r\n resolve(fileReader.result as any)\r\n })\r\n })\r\n}\r\n\r\n/** 专用于读取文件的组件 */\r\nexport const InputFile = forwardRef<HTMLInputElement, InputFileProps>((props, ref) => {\r\n const { multiple = false, type = \"file\", onChange, disabled: inputDisabled, clearAfterChange, ...rest } = props\r\n const [disabled, setDisabled] = useState(false)\r\n\r\n async function onInputChange(e: ChangeEvent<HTMLInputElement>) {\r\n const input = e.target\r\n const { files } = input\r\n if (!files || files.length === 0) return\r\n setDisabled(true)\r\n try {\r\n if (multiple) {\r\n const result: any[] = []\r\n for (const file of Array.from(files)) {\r\n result.push({\r\n result: await getFileData(file, type),\r\n file\r\n })\r\n }\r\n onChange?.(result as any)\r\n } else {\r\n onChange?.({\r\n result: await getFileData(files[0], type),\r\n file: files[0]\r\n } as any)\r\n }\r\n } finally {\r\n if (clearAfterChange) input.value = \"\"\r\n setDisabled(false)\r\n }\r\n }\r\n\r\n return <input ref={ref} disabled={disabled || inputDisabled} type=\"file\" multiple={multiple} onChange={onInputChange} {...rest} />\r\n})\r\n\r\nexport type InputFileButtonProps = ButtonHTMLAttributes<HTMLButtonElement> & {\r\n input: InputFileProps\r\n dragFile?: boolean\r\n}\r\n\r\n/** 专用于读取文件的 button 组件 */\r\nexport const InputFileButton = forwardRef<HTMLButtonElement, InputFileButtonProps>((props, ref) => {\r\n const { onClick: _onClick, input: inputProps, onDrop: _onDrop, onDragOver: _onDragOver, dragFile, disabled: _disabled, ...rest } = props\r\n const { style, disabled: __disabled, multiple, onChange, type = \"file\", ...restInputProps } = inputProps\r\n const [disabled, setDisabled] = useState(false)\r\n const input = useRef<HTMLInputElement>(null)\r\n\r\n function onClick(e: ReactMouseEvent<HTMLButtonElement, MouseEvent>) {\r\n input.current?.click()\r\n _onClick?.(e)\r\n }\r\n\r\n async function onDrop(e: DragEvent<HTMLButtonElement>) {\r\n _onDrop?.(e)\r\n if (disabled || !dragFile) return\r\n e.preventDefault()\r\n const { files } = e.dataTransfer\r\n if (!files || files.length === 0) return\r\n setDisabled(true)\r\n try {\r\n if (multiple) {\r\n const result: any[] = []\r\n for (const file of Array.from(files)) {\r\n result.push({\r\n result: await getFileData(file, type),\r\n file\r\n })\r\n }\r\n onChange?.(result as any)\r\n } else {\r\n onChange?.({\r\n result: await getFileData(files[0], type),\r\n file: files[0]\r\n } as any)\r\n }\r\n } finally {\r\n setDisabled(false)\r\n }\r\n }\r\n\r\n function onDragOver(e: DragEvent<HTMLButtonElement>) {\r\n _onDragOver?.(e)\r\n if (disabled || !dragFile) return\r\n e.preventDefault()\r\n }\r\n\r\n return (\r\n <Fragment>\r\n <InputFile\r\n ref={input}\r\n disabled={disabled || _disabled || __disabled}\r\n style={{ display: \"none\", ...style }}\r\n multiple={multiple as any}\r\n onChange={onChange as any}\r\n type={type as any}\r\n {...restInputProps}\r\n />\r\n <button ref={ref} type=\"button\" disabled={disabled || _disabled} onClick={onClick} onDrop={onDrop} onDragOver={onDragOver} {...rest} />\r\n </Fragment>\r\n )\r\n})\r\n\r\nexport interface ImportExcelProps extends Omit<InputFileProps, \"multiple\" | \"onChange\" | \"accept\" | \"type\"> {\r\n onChange?: (data: Record<string, string>[]) => void\r\n}\r\n\r\n/** 专门用于读取 excel 的组件 */\r\nexport const ImportExcel = forwardRef<HTMLInputElement, ImportExcelProps>((props, ref) => {\r\n const { onChange, ...rest } = props\r\n\r\n function onInputChange(data: InputFileData<ArrayBuffer>) {\r\n const wb = read(data.result)\r\n const result = utils.sheet_to_json<any>(wb.Sheets[wb.SheetNames[0]])\r\n if (typeof result === \"object\") {\r\n const $ = result.map(it => {\r\n const _: Record<string, string> = {}\r\n Object.keys(it)\r\n .filter(key => key !== \"__rowNum__\")\r\n .forEach(key => (_[key] = String(it[key])))\r\n return _\r\n })\r\n onChange?.($)\r\n }\r\n }\r\n\r\n return <InputFile ref={ref} accept=\".xlsx\" type=\"arrayBuffer\" onChange={onInputChange} {...rest} />\r\n})\r\n\r\n/** 手动导出 excel */\r\nexport function exportExcel(data: Record<string, string>[], name: string) {\r\n const workSheet = utils.json_to_sheet(data)\r\n const workBook = utils.book_new()\r\n utils.book_append_sheet(workBook, workSheet)\r\n writeFile(workBook, `${name}${name.endsWith(\".xlsx\") ? \"\" : \".xlsx\"}`)\r\n}\r\n\r\nexport interface ExportExcelProps extends ButtonHTMLAttributes<HTMLButtonElement> {\r\n data: Record<string, string>[]\r\n fileName: string\r\n}\r\n\r\n/** 导出 excel 的 button 组件 */\r\nexport const ExportExcel = forwardRef<HTMLButtonElement, ExportExcelProps>((props, ref) => {\r\n const { data, fileName, onClick, ...rest } = props\r\n\r\n function onButtonClick(e: ReactMouseEvent<HTMLButtonElement, MouseEvent>) {\r\n exportExcel(data, fileName)\r\n onClick?.(e)\r\n }\r\n\r\n return <button ref={ref} onClick={onButtonClick} {...rest} />\r\n})\r\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -44,10 +44,12 @@ export declare function getFileData<T extends InputFileDataType>(file: File, typ
44
44
  export declare const InputFile: import("react").ForwardRefExoticComponent<InputFileProps & import("react").RefAttributes<HTMLInputElement>>;
45
45
  export type InputFileButtonProps = ButtonHTMLAttributes<HTMLButtonElement> & {
46
46
  input: InputFileProps;
47
+ dragFile?: boolean;
47
48
  };
48
49
  /** 专用于读取文件的 button 组件 */
49
50
  export declare const InputFileButton: import("react").ForwardRefExoticComponent<ButtonHTMLAttributes<HTMLButtonElement> & {
50
51
  input: InputFileProps;
52
+ dragFile?: boolean | undefined;
51
53
  } & import("react").RefAttributes<HTMLButtonElement>>;
52
54
  export interface ImportExcelProps extends Omit<InputFileProps, "multiple" | "onChange" | "accept" | "type"> {
53
55
  onChange?: (data: Record<string, string>[]) => void;
@@ -63,12 +63,9 @@ export const InputFile = /*#__PURE__*/forwardRef((props, ref) => {
63
63
  file: files[0]
64
64
  });
65
65
  }
66
- setDisabled(false);
66
+ } finally {
67
67
  if (clearAfterChange) input.value = "";
68
- } catch (error) {
69
68
  setDisabled(false);
70
- if (clearAfterChange) input.value = "";
71
- throw error;
72
69
  }
73
70
  }
74
71
  return /*#__PURE__*/_jsx("input", {
@@ -83,31 +80,81 @@ export const InputFile = /*#__PURE__*/forwardRef((props, ref) => {
83
80
  /** 专用于读取文件的 button 组件 */
84
81
  export const InputFileButton = /*#__PURE__*/forwardRef((props, ref) => {
85
82
  const {
86
- onClick,
83
+ onClick: _onClick,
87
84
  input: inputProps,
85
+ onDrop: _onDrop,
86
+ onDragOver: _onDragOver,
87
+ dragFile,
88
+ disabled: _disabled,
88
89
  ...rest
89
90
  } = props;
90
91
  const {
91
92
  style,
93
+ disabled: __disabled,
94
+ multiple,
95
+ onChange,
96
+ type = "file",
92
97
  ...restInputProps
93
98
  } = inputProps;
99
+ const [disabled, setDisabled] = useState(false);
94
100
  const input = useRef(null);
95
- function onBtnClick(e) {
101
+ function onClick(e) {
96
102
  input.current?.click();
97
- onClick?.(e);
103
+ _onClick?.(e);
104
+ }
105
+ async function onDrop(e) {
106
+ _onDrop?.(e);
107
+ if (disabled || !dragFile) return;
108
+ e.preventDefault();
109
+ const {
110
+ files
111
+ } = e.dataTransfer;
112
+ if (!files || files.length === 0) return;
113
+ setDisabled(true);
114
+ try {
115
+ if (multiple) {
116
+ const result = [];
117
+ for (const file of Array.from(files)) {
118
+ result.push({
119
+ result: await getFileData(file, type),
120
+ file
121
+ });
122
+ }
123
+ onChange?.(result);
124
+ } else {
125
+ onChange?.({
126
+ result: await getFileData(files[0], type),
127
+ file: files[0]
128
+ });
129
+ }
130
+ } finally {
131
+ setDisabled(false);
132
+ }
133
+ }
134
+ function onDragOver(e) {
135
+ _onDragOver?.(e);
136
+ if (disabled || !dragFile) return;
137
+ e.preventDefault();
98
138
  }
99
139
  return /*#__PURE__*/_jsxs(Fragment, {
100
140
  children: [/*#__PURE__*/_jsx(InputFile, {
101
141
  ref: input,
142
+ disabled: disabled || _disabled || __disabled,
102
143
  style: {
103
144
  display: "none",
104
145
  ...style
105
146
  },
147
+ multiple: multiple,
148
+ onChange: onChange,
149
+ type: type,
106
150
  ...restInputProps
107
151
  }), /*#__PURE__*/_jsx("button", {
108
152
  ref: ref,
109
153
  type: "button",
110
- onClick: onBtnClick,
154
+ disabled: disabled || _disabled,
155
+ onClick: onClick,
156
+ onDrop: onDrop,
157
+ onDragOver: onDragOver,
111
158
  ...rest
112
159
  })]
113
160
  });
@@ -1 +1 @@
1
- {"version":3,"names":["Fragment","forwardRef","useRef","useState","read","utils","writeFile","jsx","_jsx","jsxs","_jsxs","getFileData","file","type","fileReader","FileReader","readAsArrayBuffer","readAsBinaryString","readAsDataURL","readAsText","Promise","resolve","addEventListener","result","InputFile","props","ref","multiple","onChange","disabled","inputDisabled","clearAfterChange","rest","setDisabled","onInputChange","e","input","target","files","length","Array","from","push","value","error","InputFileButton","onClick","inputProps","style","restInputProps","onBtnClick","current","click","children","display","ImportExcel","data","wb","sheet_to_json","Sheets","SheetNames","$","map","it","_","Object","keys","filter","key","forEach","String","accept","exportExcel","name","workSheet","json_to_sheet","workBook","book_new","book_append_sheet","endsWith","ExportExcel","fileName","onButtonClick"],"sources":["../../../src/components/InputFile.tsx"],"sourcesContent":["\"use client\"\r\n\r\nimport { ButtonHTMLAttributes, ChangeEvent, Fragment, InputHTMLAttributes, MouseEvent as ReactMouseEvent, forwardRef, useRef, useState } from \"react\"\r\nimport { read, utils, writeFile } from \"xlsx\"\r\n\r\nexport interface InputFileDataTypes {\r\n base64: string\r\n text: string\r\n arrayBuffer: ArrayBuffer\r\n binary: string\r\n file: File\r\n}\r\n\r\nexport type InputFileDataType = keyof InputFileDataTypes\r\n\r\nexport interface InputFileData<T> {\r\n result: T\r\n file: File\r\n}\r\n\r\nexport type InputFileProps = (\r\n | {\r\n multiple?: false\r\n type: \"base64\" | \"text\" | \"binary\"\r\n onChange?: (data: InputFileData<string>) => void\r\n }\r\n | {\r\n multiple?: false\r\n type: \"arrayBuffer\"\r\n onChange?: (data: InputFileData<ArrayBuffer>) => void\r\n }\r\n | {\r\n multiple?: false\r\n type?: \"file\"\r\n onChange?: (data: InputFileData<File>) => void\r\n }\r\n | {\r\n multiple: true\r\n type: \"base64\" | \"text\" | \"binary\"\r\n onChange?: (data: InputFileData<string>[]) => void\r\n }\r\n | {\r\n multiple: true\r\n type: \"arrayBuffer\"\r\n onChange?: (data: InputFileData<ArrayBuffer>[]) => void\r\n }\r\n | {\r\n multiple: true\r\n type?: \"file\"\r\n onChange?: (data: InputFileData<File>[]) => void\r\n }\r\n) &\r\n Omit<InputHTMLAttributes<HTMLInputElement>, \"onChange\" | \"multiple\" | \"type\"> & {\r\n /** 是否在捕获文件后清除 input 上的文件,默认为 false,主要区别在于如果不清除,连续两次选择同样的文件不会触发 onChange 事件,如果用于 form 表单,请设置为 flase */\r\n clearAfterChange?: boolean\r\n }\r\n\r\nexport async function getFileData<T extends InputFileDataType>(file: File, type: T): Promise<InputFileDataTypes[T]> {\r\n const fileReader = new FileReader()\r\n switch (type) {\r\n case \"arrayBuffer\":\r\n fileReader.readAsArrayBuffer(file)\r\n break\r\n case \"binary\":\r\n fileReader.readAsBinaryString(file)\r\n break\r\n case \"base64\":\r\n fileReader.readAsDataURL(file)\r\n break\r\n case \"text\":\r\n fileReader.readAsText(file)\r\n break\r\n default:\r\n return file as any\r\n }\r\n return new Promise(resolve => {\r\n fileReader.addEventListener(\"load\", () => {\r\n resolve(fileReader.result as any)\r\n })\r\n })\r\n}\r\n\r\n/** 专用于读取文件的组件 */\r\nexport const InputFile = forwardRef<HTMLInputElement, InputFileProps>((props, ref) => {\r\n const { multiple = false, type = \"file\", onChange, disabled: inputDisabled, clearAfterChange, ...rest } = props\r\n const [disabled, setDisabled] = useState(false)\r\n\r\n async function onInputChange(e: ChangeEvent<HTMLInputElement>) {\r\n const input = e.target\r\n const { files } = input\r\n if (!files || files.length === 0) return\r\n setDisabled(true)\r\n try {\r\n if (multiple) {\r\n const result: any[] = []\r\n for (const file of Array.from(files)) {\r\n result.push({\r\n result: await getFileData(file, type),\r\n file\r\n })\r\n }\r\n onChange?.(result as any)\r\n } else {\r\n onChange?.({\r\n result: await getFileData(files[0], type),\r\n file: files[0]\r\n } as any)\r\n }\r\n setDisabled(false)\r\n if (clearAfterChange) input.value = \"\"\r\n } catch (error) {\r\n setDisabled(false)\r\n if (clearAfterChange) input.value = \"\"\r\n throw error\r\n }\r\n }\r\n\r\n return <input ref={ref} disabled={disabled || inputDisabled} type=\"file\" multiple={multiple} onChange={onInputChange} {...rest} />\r\n})\r\n\r\nexport type InputFileButtonProps = ButtonHTMLAttributes<HTMLButtonElement> & {\r\n input: InputFileProps\r\n}\r\n\r\n/** 专用于读取文件的 button 组件 */\r\nexport const InputFileButton = forwardRef<HTMLButtonElement, InputFileButtonProps>((props, ref) => {\r\n const { onClick, input: inputProps, ...rest } = props\r\n const { style, ...restInputProps } = inputProps\r\n const input = useRef<HTMLInputElement>(null)\r\n\r\n function onBtnClick(e: ReactMouseEvent<HTMLButtonElement, MouseEvent>) {\r\n input.current?.click()\r\n onClick?.(e)\r\n }\r\n\r\n return (\r\n <Fragment>\r\n <InputFile ref={input} style={{ display: \"none\", ...style }} {...restInputProps} />\r\n <button ref={ref} type=\"button\" onClick={onBtnClick} {...rest} />\r\n </Fragment>\r\n )\r\n})\r\n\r\nexport interface ImportExcelProps extends Omit<InputFileProps, \"multiple\" | \"onChange\" | \"accept\" | \"type\"> {\r\n onChange?: (data: Record<string, string>[]) => void\r\n}\r\n\r\n/** 专门用于读取 excel 的组件 */\r\nexport const ImportExcel = forwardRef<HTMLInputElement, ImportExcelProps>((props, ref) => {\r\n const { onChange, ...rest } = props\r\n\r\n function onInputChange(data: InputFileData<ArrayBuffer>) {\r\n const wb = read(data.result)\r\n const result = utils.sheet_to_json<any>(wb.Sheets[wb.SheetNames[0]])\r\n if (typeof result === \"object\") {\r\n const $ = result.map(it => {\r\n const _: Record<string, string> = {}\r\n Object.keys(it)\r\n .filter(key => key !== \"__rowNum__\")\r\n .forEach(key => (_[key] = String(it[key])))\r\n return _\r\n })\r\n onChange?.($)\r\n }\r\n }\r\n\r\n return <InputFile ref={ref} accept=\".xlsx\" type=\"arrayBuffer\" onChange={onInputChange} {...rest} />\r\n})\r\n\r\n/** 手动导出 excel */\r\nexport function exportExcel(data: Record<string, string>[], name: string) {\r\n const workSheet = utils.json_to_sheet(data)\r\n const workBook = utils.book_new()\r\n utils.book_append_sheet(workBook, workSheet)\r\n writeFile(workBook, `${name}${name.endsWith(\".xlsx\") ? \"\" : \".xlsx\"}`)\r\n}\r\n\r\nexport interface ExportExcelProps extends ButtonHTMLAttributes<HTMLButtonElement> {\r\n data: Record<string, string>[]\r\n fileName: string\r\n}\r\n\r\n/** 导出 excel 的 button 组件 */\r\nexport const ExportExcel = forwardRef<HTMLButtonElement, ExportExcelProps>((props, ref) => {\r\n const { data, fileName, onClick, ...rest } = props\r\n\r\n function onButtonClick(e: ReactMouseEvent<HTMLButtonElement, MouseEvent>) {\r\n exportExcel(data, fileName)\r\n onClick?.(e)\r\n }\r\n\r\n return <button ref={ref} onClick={onButtonClick} {...rest} />\r\n})\r\n"],"mappings":"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"}
1
+ {"version":3,"names":["Fragment","forwardRef","useRef","useState","read","utils","writeFile","jsx","_jsx","jsxs","_jsxs","getFileData","file","type","fileReader","FileReader","readAsArrayBuffer","readAsBinaryString","readAsDataURL","readAsText","Promise","resolve","addEventListener","result","InputFile","props","ref","multiple","onChange","disabled","inputDisabled","clearAfterChange","rest","setDisabled","onInputChange","e","input","target","files","length","Array","from","push","value","InputFileButton","onClick","_onClick","inputProps","onDrop","_onDrop","onDragOver","_onDragOver","dragFile","_disabled","style","__disabled","restInputProps","current","click","preventDefault","dataTransfer","children","display","ImportExcel","data","wb","sheet_to_json","Sheets","SheetNames","$","map","it","_","Object","keys","filter","key","forEach","String","accept","exportExcel","name","workSheet","json_to_sheet","workBook","book_new","book_append_sheet","endsWith","ExportExcel","fileName","onButtonClick"],"sources":["../../../src/components/InputFile.tsx"],"sourcesContent":["\"use client\"\r\n\r\nimport { ButtonHTMLAttributes, ChangeEvent, Fragment, InputHTMLAttributes, MouseEvent as ReactMouseEvent, forwardRef, useRef, useState, DragEvent } from \"react\"\r\nimport { read, utils, writeFile } from \"xlsx\"\r\n\r\nexport interface InputFileDataTypes {\r\n base64: string\r\n text: string\r\n arrayBuffer: ArrayBuffer\r\n binary: string\r\n file: File\r\n}\r\n\r\nexport type InputFileDataType = keyof InputFileDataTypes\r\n\r\nexport interface InputFileData<T> {\r\n result: T\r\n file: File\r\n}\r\n\r\nexport type InputFileProps = (\r\n | {\r\n multiple?: false\r\n type: \"base64\" | \"text\" | \"binary\"\r\n onChange?: (data: InputFileData<string>) => void\r\n }\r\n | {\r\n multiple?: false\r\n type: \"arrayBuffer\"\r\n onChange?: (data: InputFileData<ArrayBuffer>) => void\r\n }\r\n | {\r\n multiple?: false\r\n type?: \"file\"\r\n onChange?: (data: InputFileData<File>) => void\r\n }\r\n | {\r\n multiple: true\r\n type: \"base64\" | \"text\" | \"binary\"\r\n onChange?: (data: InputFileData<string>[]) => void\r\n }\r\n | {\r\n multiple: true\r\n type: \"arrayBuffer\"\r\n onChange?: (data: InputFileData<ArrayBuffer>[]) => void\r\n }\r\n | {\r\n multiple: true\r\n type?: \"file\"\r\n onChange?: (data: InputFileData<File>[]) => void\r\n }\r\n) &\r\n Omit<InputHTMLAttributes<HTMLInputElement>, \"onChange\" | \"multiple\" | \"type\"> & {\r\n /** 是否在捕获文件后清除 input 上的文件,默认为 false,主要区别在于如果不清除,连续两次选择同样的文件不会触发 onChange 事件,如果用于 form 表单,请设置为 flase */\r\n clearAfterChange?: boolean\r\n }\r\n\r\nexport async function getFileData<T extends InputFileDataType>(file: File, type: T): Promise<InputFileDataTypes[T]> {\r\n const fileReader = new FileReader()\r\n switch (type) {\r\n case \"arrayBuffer\":\r\n fileReader.readAsArrayBuffer(file)\r\n break\r\n case \"binary\":\r\n fileReader.readAsBinaryString(file)\r\n break\r\n case \"base64\":\r\n fileReader.readAsDataURL(file)\r\n break\r\n case \"text\":\r\n fileReader.readAsText(file)\r\n break\r\n default:\r\n return file as any\r\n }\r\n return new Promise(resolve => {\r\n fileReader.addEventListener(\"load\", () => {\r\n resolve(fileReader.result as any)\r\n })\r\n })\r\n}\r\n\r\n/** 专用于读取文件的组件 */\r\nexport const InputFile = forwardRef<HTMLInputElement, InputFileProps>((props, ref) => {\r\n const { multiple = false, type = \"file\", onChange, disabled: inputDisabled, clearAfterChange, ...rest } = props\r\n const [disabled, setDisabled] = useState(false)\r\n\r\n async function onInputChange(e: ChangeEvent<HTMLInputElement>) {\r\n const input = e.target\r\n const { files } = input\r\n if (!files || files.length === 0) return\r\n setDisabled(true)\r\n try {\r\n if (multiple) {\r\n const result: any[] = []\r\n for (const file of Array.from(files)) {\r\n result.push({\r\n result: await getFileData(file, type),\r\n file\r\n })\r\n }\r\n onChange?.(result as any)\r\n } else {\r\n onChange?.({\r\n result: await getFileData(files[0], type),\r\n file: files[0]\r\n } as any)\r\n }\r\n } finally {\r\n if (clearAfterChange) input.value = \"\"\r\n setDisabled(false)\r\n }\r\n }\r\n\r\n return <input ref={ref} disabled={disabled || inputDisabled} type=\"file\" multiple={multiple} onChange={onInputChange} {...rest} />\r\n})\r\n\r\nexport type InputFileButtonProps = ButtonHTMLAttributes<HTMLButtonElement> & {\r\n input: InputFileProps\r\n dragFile?: boolean\r\n}\r\n\r\n/** 专用于读取文件的 button 组件 */\r\nexport const InputFileButton = forwardRef<HTMLButtonElement, InputFileButtonProps>((props, ref) => {\r\n const { onClick: _onClick, input: inputProps, onDrop: _onDrop, onDragOver: _onDragOver, dragFile, disabled: _disabled, ...rest } = props\r\n const { style, disabled: __disabled, multiple, onChange, type = \"file\", ...restInputProps } = inputProps\r\n const [disabled, setDisabled] = useState(false)\r\n const input = useRef<HTMLInputElement>(null)\r\n\r\n function onClick(e: ReactMouseEvent<HTMLButtonElement, MouseEvent>) {\r\n input.current?.click()\r\n _onClick?.(e)\r\n }\r\n\r\n async function onDrop(e: DragEvent<HTMLButtonElement>) {\r\n _onDrop?.(e)\r\n if (disabled || !dragFile) return\r\n e.preventDefault()\r\n const { files } = e.dataTransfer\r\n if (!files || files.length === 0) return\r\n setDisabled(true)\r\n try {\r\n if (multiple) {\r\n const result: any[] = []\r\n for (const file of Array.from(files)) {\r\n result.push({\r\n result: await getFileData(file, type),\r\n file\r\n })\r\n }\r\n onChange?.(result as any)\r\n } else {\r\n onChange?.({\r\n result: await getFileData(files[0], type),\r\n file: files[0]\r\n } as any)\r\n }\r\n } finally {\r\n setDisabled(false)\r\n }\r\n }\r\n\r\n function onDragOver(e: DragEvent<HTMLButtonElement>) {\r\n _onDragOver?.(e)\r\n if (disabled || !dragFile) return\r\n e.preventDefault()\r\n }\r\n\r\n return (\r\n <Fragment>\r\n <InputFile\r\n ref={input}\r\n disabled={disabled || _disabled || __disabled}\r\n style={{ display: \"none\", ...style }}\r\n multiple={multiple as any}\r\n onChange={onChange as any}\r\n type={type as any}\r\n {...restInputProps}\r\n />\r\n <button ref={ref} type=\"button\" disabled={disabled || _disabled} onClick={onClick} onDrop={onDrop} onDragOver={onDragOver} {...rest} />\r\n </Fragment>\r\n )\r\n})\r\n\r\nexport interface ImportExcelProps extends Omit<InputFileProps, \"multiple\" | \"onChange\" | \"accept\" | \"type\"> {\r\n onChange?: (data: Record<string, string>[]) => void\r\n}\r\n\r\n/** 专门用于读取 excel 的组件 */\r\nexport const ImportExcel = forwardRef<HTMLInputElement, ImportExcelProps>((props, ref) => {\r\n const { onChange, ...rest } = props\r\n\r\n function onInputChange(data: InputFileData<ArrayBuffer>) {\r\n const wb = read(data.result)\r\n const result = utils.sheet_to_json<any>(wb.Sheets[wb.SheetNames[0]])\r\n if (typeof result === \"object\") {\r\n const $ = result.map(it => {\r\n const _: Record<string, string> = {}\r\n Object.keys(it)\r\n .filter(key => key !== \"__rowNum__\")\r\n .forEach(key => (_[key] = String(it[key])))\r\n return _\r\n })\r\n onChange?.($)\r\n }\r\n }\r\n\r\n return <InputFile ref={ref} accept=\".xlsx\" type=\"arrayBuffer\" onChange={onInputChange} {...rest} />\r\n})\r\n\r\n/** 手动导出 excel */\r\nexport function exportExcel(data: Record<string, string>[], name: string) {\r\n const workSheet = utils.json_to_sheet(data)\r\n const workBook = utils.book_new()\r\n utils.book_append_sheet(workBook, workSheet)\r\n writeFile(workBook, `${name}${name.endsWith(\".xlsx\") ? \"\" : \".xlsx\"}`)\r\n}\r\n\r\nexport interface ExportExcelProps extends ButtonHTMLAttributes<HTMLButtonElement> {\r\n data: Record<string, string>[]\r\n fileName: string\r\n}\r\n\r\n/** 导出 excel 的 button 组件 */\r\nexport const ExportExcel = forwardRef<HTMLButtonElement, ExportExcelProps>((props, ref) => {\r\n const { data, fileName, onClick, ...rest } = props\r\n\r\n function onButtonClick(e: ReactMouseEvent<HTMLButtonElement, MouseEvent>) {\r\n exportExcel(data, fileName)\r\n onClick?.(e)\r\n }\r\n\r\n return <button ref={ref} onClick={onButtonClick} {...rest} />\r\n})\r\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "deepsea-components",
3
- "version": "5.5.14",
3
+ "version": "5.6.0",
4
4
  "description": "格数科技自用组件库",
5
5
  "main": "dist/cjs/index.js",
6
6
  "module": "dist/esm/index.js",
@@ -1,6 +1,6 @@
1
1
  "use client"
2
2
 
3
- import { ButtonHTMLAttributes, ChangeEvent, Fragment, InputHTMLAttributes, MouseEvent as ReactMouseEvent, forwardRef, useRef, useState } from "react"
3
+ import { ButtonHTMLAttributes, ChangeEvent, Fragment, InputHTMLAttributes, MouseEvent as ReactMouseEvent, forwardRef, useRef, useState, DragEvent } from "react"
4
4
  import { read, utils, writeFile } from "xlsx"
5
5
 
6
6
  export interface InputFileDataTypes {
@@ -106,12 +106,9 @@ export const InputFile = forwardRef<HTMLInputElement, InputFileProps>((props, re
106
106
  file: files[0]
107
107
  } as any)
108
108
  }
109
- setDisabled(false)
109
+ } finally {
110
110
  if (clearAfterChange) input.value = ""
111
- } catch (error) {
112
111
  setDisabled(false)
113
- if (clearAfterChange) input.value = ""
114
- throw error
115
112
  }
116
113
  }
117
114
 
@@ -120,23 +117,67 @@ export const InputFile = forwardRef<HTMLInputElement, InputFileProps>((props, re
120
117
 
121
118
  export type InputFileButtonProps = ButtonHTMLAttributes<HTMLButtonElement> & {
122
119
  input: InputFileProps
120
+ dragFile?: boolean
123
121
  }
124
122
 
125
123
  /** 专用于读取文件的 button 组件 */
126
124
  export const InputFileButton = forwardRef<HTMLButtonElement, InputFileButtonProps>((props, ref) => {
127
- const { onClick, input: inputProps, ...rest } = props
128
- const { style, ...restInputProps } = inputProps
125
+ const { onClick: _onClick, input: inputProps, onDrop: _onDrop, onDragOver: _onDragOver, dragFile, disabled: _disabled, ...rest } = props
126
+ const { style, disabled: __disabled, multiple, onChange, type = "file", ...restInputProps } = inputProps
127
+ const [disabled, setDisabled] = useState(false)
129
128
  const input = useRef<HTMLInputElement>(null)
130
129
 
131
- function onBtnClick(e: ReactMouseEvent<HTMLButtonElement, MouseEvent>) {
130
+ function onClick(e: ReactMouseEvent<HTMLButtonElement, MouseEvent>) {
132
131
  input.current?.click()
133
- onClick?.(e)
132
+ _onClick?.(e)
133
+ }
134
+
135
+ async function onDrop(e: DragEvent<HTMLButtonElement>) {
136
+ _onDrop?.(e)
137
+ if (disabled || !dragFile) return
138
+ e.preventDefault()
139
+ const { files } = e.dataTransfer
140
+ if (!files || files.length === 0) return
141
+ setDisabled(true)
142
+ try {
143
+ if (multiple) {
144
+ const result: any[] = []
145
+ for (const file of Array.from(files)) {
146
+ result.push({
147
+ result: await getFileData(file, type),
148
+ file
149
+ })
150
+ }
151
+ onChange?.(result as any)
152
+ } else {
153
+ onChange?.({
154
+ result: await getFileData(files[0], type),
155
+ file: files[0]
156
+ } as any)
157
+ }
158
+ } finally {
159
+ setDisabled(false)
160
+ }
161
+ }
162
+
163
+ function onDragOver(e: DragEvent<HTMLButtonElement>) {
164
+ _onDragOver?.(e)
165
+ if (disabled || !dragFile) return
166
+ e.preventDefault()
134
167
  }
135
168
 
136
169
  return (
137
170
  <Fragment>
138
- <InputFile ref={input} style={{ display: "none", ...style }} {...restInputProps} />
139
- <button ref={ref} type="button" onClick={onBtnClick} {...rest} />
171
+ <InputFile
172
+ ref={input}
173
+ disabled={disabled || _disabled || __disabled}
174
+ style={{ display: "none", ...style }}
175
+ multiple={multiple as any}
176
+ onChange={onChange as any}
177
+ type={type as any}
178
+ {...restInputProps}
179
+ />
180
+ <button ref={ref} type="button" disabled={disabled || _disabled} onClick={onClick} onDrop={onDrop} onDragOver={onDragOver} {...rest} />
140
181
  </Fragment>
141
182
  )
142
183
  })