deepsea-components 5.9.7 → 5.10.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.
@@ -1,8 +1,7 @@
1
1
  "use client";
2
2
 
3
- import { Fragment, forwardRef, useRef, useState } from "react";
3
+ import { useState } from "react";
4
4
  import { jsx as _jsx } from "react/jsx-runtime";
5
- import { jsxs as _jsxs } from "react/jsx-runtime";
6
5
  export async function getFileData(file, type) {
7
6
  const fileReader = new FileReader();
8
7
  switch (type) {
@@ -27,19 +26,21 @@ export async function getFileData(file, type) {
27
26
  });
28
27
  });
29
28
  }
30
-
31
29
  /** 专用于读取文件的组件 */
32
- export const InputFile = /*#__PURE__*/forwardRef((props, ref) => {
30
+ export function InputFile(props) {
33
31
  const {
34
32
  multiple = false,
35
33
  type = "file",
36
- onChange,
37
- disabled: inputDisabled,
34
+ onChange: _onChange,
35
+ disabled: _disabled,
38
36
  clearAfterChange,
37
+ onValueChange,
38
+ onFileChange,
39
39
  ...rest
40
40
  } = props;
41
41
  const [disabled, setDisabled] = useState(false);
42
- async function onInputChange(e) {
42
+ async function onChange(e) {
43
+ _onChange?.(e);
43
44
  const input = e.target;
44
45
  const {
45
46
  files
@@ -48,19 +49,18 @@ export const InputFile = /*#__PURE__*/forwardRef((props, ref) => {
48
49
  setDisabled(true);
49
50
  try {
50
51
  if (multiple) {
51
- const result = [];
52
- for (const file of Array.from(files)) {
53
- result.push({
54
- result: await getFileData(file, type),
55
- file
56
- });
52
+ const files2 = Array.from(files);
53
+ const values = [];
54
+ for (const file of files2) {
55
+ const value = await getFileData(file, type);
56
+ values.push(value);
57
57
  }
58
- onChange?.(result);
58
+ onFileChange?.(files2);
59
+ onValueChange?.(values);
59
60
  } else {
60
- onChange?.({
61
- result: await getFileData(files[0], type),
62
- file: files[0]
63
- });
61
+ const file = files[0];
62
+ onFileChange?.(file);
63
+ onValueChange?.(await getFileData(file, type));
64
64
  }
65
65
  } finally {
66
66
  if (clearAfterChange) input.value = "";
@@ -68,94 +68,11 @@ export const InputFile = /*#__PURE__*/forwardRef((props, ref) => {
68
68
  }
69
69
  }
70
70
  return /*#__PURE__*/_jsx("input", {
71
- ref: ref,
72
- disabled: disabled || inputDisabled,
71
+ disabled: disabled || _disabled,
73
72
  type: "file",
74
73
  multiple: multiple,
75
- onChange: onInputChange,
74
+ onChange: onChange,
76
75
  ...rest
77
76
  });
78
- });
79
- /** 专用于读取文件的 button 组件 */
80
- export const InputFileButton = /*#__PURE__*/forwardRef((props, ref) => {
81
- const {
82
- onClick: _onClick,
83
- input: inputProps,
84
- onDrop: _onDrop,
85
- onDragOver: _onDragOver,
86
- dragFile,
87
- disabled: _disabled,
88
- ...rest
89
- } = props;
90
- const {
91
- style,
92
- disabled: __disabled,
93
- multiple,
94
- onChange,
95
- type = "file",
96
- ...restInputProps
97
- } = inputProps;
98
- const [disabled, setDisabled] = useState(false);
99
- const input = useRef(null);
100
- function onClick(e) {
101
- input.current?.click();
102
- _onClick?.(e);
103
- }
104
- async function onDrop(e) {
105
- _onDrop?.(e);
106
- if (disabled || !dragFile) return;
107
- e.preventDefault();
108
- const {
109
- files
110
- } = e.dataTransfer;
111
- if (!files || files.length === 0) return;
112
- setDisabled(true);
113
- try {
114
- if (multiple) {
115
- const result = [];
116
- for (const file of Array.from(files)) {
117
- result.push({
118
- result: await getFileData(file, type),
119
- file
120
- });
121
- }
122
- onChange?.(result);
123
- } else {
124
- onChange?.({
125
- result: await getFileData(files[0], type),
126
- file: files[0]
127
- });
128
- }
129
- } finally {
130
- setDisabled(false);
131
- }
132
- }
133
- function onDragOver(e) {
134
- _onDragOver?.(e);
135
- if (disabled || !dragFile) return;
136
- e.preventDefault();
137
- }
138
- return /*#__PURE__*/_jsxs(Fragment, {
139
- children: [/*#__PURE__*/_jsx(InputFile, {
140
- ref: input,
141
- disabled: disabled || _disabled || __disabled,
142
- style: {
143
- display: "none",
144
- ...style
145
- },
146
- multiple: multiple,
147
- onChange: onChange,
148
- type: type,
149
- ...restInputProps
150
- }), /*#__PURE__*/_jsx("button", {
151
- ref: ref,
152
- type: "button",
153
- disabled: disabled || _disabled,
154
- onClick: onClick,
155
- onDrop: onDrop,
156
- onDragOver: onDragOver,
157
- ...rest
158
- })]
159
- });
160
- });
77
+ }
161
78
  //# sourceMappingURL=InputFile.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["Fragment","forwardRef","useRef","useState","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"],"sources":["../../../src/components/InputFile.tsx"],"sourcesContent":["\"use client\"\n\nimport { ButtonHTMLAttributes, ChangeEvent, DragEvent, Fragment, InputHTMLAttributes, MouseEvent as ReactMouseEvent, forwardRef, useRef, useState } from \"react\"\n\nexport interface InputFileDataTypes {\n base64: string\n text: string\n arrayBuffer: ArrayBuffer\n binary: string\n file: File\n}\n\nexport type InputFileDataType = keyof InputFileDataTypes\n\nexport interface InputFileData<T> {\n result: T\n file: File\n}\n\nexport type InputFileProps = (\n | {\n multiple?: false\n type: \"base64\" | \"text\" | \"binary\"\n onChange?: (data: InputFileData<string>) => void\n }\n | {\n multiple?: false\n type: \"arrayBuffer\"\n onChange?: (data: InputFileData<ArrayBuffer>) => void\n }\n | {\n multiple?: false\n type?: \"file\"\n onChange?: (data: InputFileData<File>) => void\n }\n | {\n multiple: true\n type: \"base64\" | \"text\" | \"binary\"\n onChange?: (data: InputFileData<string>[]) => void\n }\n | {\n multiple: true\n type: \"arrayBuffer\"\n onChange?: (data: InputFileData<ArrayBuffer>[]) => void\n }\n | {\n multiple: true\n type?: \"file\"\n onChange?: (data: InputFileData<File>[]) => void\n }\n) &\n Omit<InputHTMLAttributes<HTMLInputElement>, \"onChange\" | \"multiple\" | \"type\"> & {\n /** 是否在捕获文件后清除 input 上的文件,默认为 false,主要区别在于如果不清除,连续两次选择同样的文件不会触发 onChange 事件,如果用于 form 表单,请设置为 flase */\n clearAfterChange?: boolean\n }\n\nexport async function getFileData<T extends InputFileDataType>(file: File, type: T): Promise<InputFileDataTypes[T]> {\n const fileReader = new FileReader()\n switch (type) {\n case \"arrayBuffer\":\n fileReader.readAsArrayBuffer(file)\n break\n case \"binary\":\n fileReader.readAsBinaryString(file)\n break\n case \"base64\":\n fileReader.readAsDataURL(file)\n break\n case \"text\":\n fileReader.readAsText(file)\n break\n default:\n return file as any\n }\n return new Promise(resolve => {\n fileReader.addEventListener(\"load\", () => {\n resolve(fileReader.result as any)\n })\n })\n}\n\n/** 专用于读取文件的组件 */\nexport const InputFile = forwardRef<HTMLInputElement, InputFileProps>((props, ref) => {\n const { multiple = false, type = \"file\", onChange, disabled: inputDisabled, clearAfterChange, ...rest } = props\n const [disabled, setDisabled] = useState(false)\n\n async function onInputChange(e: ChangeEvent<HTMLInputElement>) {\n const input = e.target\n const { files } = input\n if (!files || files.length === 0) return\n setDisabled(true)\n try {\n if (multiple) {\n const result: any[] = []\n for (const file of Array.from(files)) {\n result.push({\n result: await getFileData(file, type),\n file,\n })\n }\n onChange?.(result as any)\n } else {\n onChange?.({\n result: await getFileData(files[0], type),\n file: files[0],\n } as any)\n }\n } finally {\n if (clearAfterChange) input.value = \"\"\n setDisabled(false)\n }\n }\n\n return <input ref={ref} disabled={disabled || inputDisabled} type=\"file\" multiple={multiple} onChange={onInputChange} {...rest} />\n})\n\nexport type InputFileButtonProps = ButtonHTMLAttributes<HTMLButtonElement> & {\n input: InputFileProps\n dragFile?: boolean\n}\n\n/** 专用于读取文件的 button 组件 */\nexport const InputFileButton = forwardRef<HTMLButtonElement, InputFileButtonProps>((props, ref) => {\n const { onClick: _onClick, input: inputProps, onDrop: _onDrop, onDragOver: _onDragOver, dragFile, disabled: _disabled, ...rest } = props\n const { style, disabled: __disabled, multiple, onChange, type = \"file\", ...restInputProps } = inputProps\n const [disabled, setDisabled] = useState(false)\n const input = useRef<HTMLInputElement>(null)\n\n function onClick(e: ReactMouseEvent<HTMLButtonElement, MouseEvent>) {\n input.current?.click()\n _onClick?.(e)\n }\n\n async function onDrop(e: DragEvent<HTMLButtonElement>) {\n _onDrop?.(e)\n if (disabled || !dragFile) return\n e.preventDefault()\n const { files } = e.dataTransfer\n if (!files || files.length === 0) return\n setDisabled(true)\n try {\n if (multiple) {\n const result: any[] = []\n for (const file of Array.from(files)) {\n result.push({\n result: await getFileData(file, type),\n file,\n })\n }\n onChange?.(result as any)\n } else {\n onChange?.({\n result: await getFileData(files[0], type),\n file: files[0],\n } as any)\n }\n } finally {\n setDisabled(false)\n }\n }\n\n function onDragOver(e: DragEvent<HTMLButtonElement>) {\n _onDragOver?.(e)\n if (disabled || !dragFile) return\n e.preventDefault()\n }\n\n return (\n <Fragment>\n <InputFile\n ref={input}\n disabled={disabled || _disabled || __disabled}\n style={{ display: \"none\", ...style }}\n multiple={multiple as any}\n onChange={onChange as any}\n type={type as any}\n {...restInputProps}\n />\n <button ref={ref} type=\"button\" disabled={disabled || _disabled} onClick={onClick} onDrop={onDrop} onDragOver={onDragOver} {...rest} />\n </Fragment>\n )\n})\n"],"mappings":"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"}
1
+ {"version":3,"names":["useState","jsx","_jsx","getFileData","file","type","fileReader","FileReader","readAsArrayBuffer","readAsBinaryString","readAsDataURL","readAsText","Promise","resolve","addEventListener","result","InputFile","props","multiple","onChange","_onChange","disabled","_disabled","clearAfterChange","onValueChange","onFileChange","rest","setDisabled","e","input","target","files","length","files2","Array","from","values","value","push"],"sources":["../../../src/components/InputFile.tsx"],"sourcesContent":["\"use client\"\n\nimport { ChangeEvent, ComponentProps, ReactNode, useState } from \"react\"\n\nexport interface InputFileDataTypeMap {\n base64: string\n text: string\n arrayBuffer: ArrayBuffer\n binary: string\n file: File\n}\n\nexport type InputFileDataType = keyof InputFileDataTypeMap\n\nexport async function getFileData<T extends InputFileDataType>(file: File, type: T): Promise<InputFileDataTypeMap[T]> {\n const fileReader = new FileReader()\n switch (type) {\n case \"arrayBuffer\":\n fileReader.readAsArrayBuffer(file)\n break\n case \"binary\":\n fileReader.readAsBinaryString(file)\n break\n case \"base64\":\n fileReader.readAsDataURL(file)\n break\n case \"text\":\n fileReader.readAsText(file)\n break\n default:\n return file as any\n }\n return new Promise(resolve => {\n fileReader.addEventListener(\"load\", () => {\n resolve(fileReader.result as any)\n })\n })\n}\n\nexport interface InputFileBaseProps extends Omit<ComponentProps<\"input\">, \"multiple\" | \"type\"> {}\n\nexport type FileType<Multiple extends boolean> = Multiple extends true ? File[] : File\nexport type ValueType<Multiple extends boolean, Type extends InputFileDataType> = Multiple extends true\n ? InputFileDataTypeMap[Type][]\n : InputFileDataTypeMap[Type]\n\nexport interface InputFileExtraProps<Multiple extends boolean = false, Type extends InputFileDataType = \"file\"> {\n multiple?: Multiple\n type?: Type\n onValueChange?: (data: ValueType<Multiple, Type>) => void\n onFileChange?: (data: FileType<Multiple>) => void\n /** 是否在捕获文件后清除 input 上的文件,默认为 false,主要区别在于如果不清除,连续两次选择同样的文件不会触发 onChange 事件,如果用于 form 表单,请设置为 flase */\n clearAfterChange?: boolean\n}\n\nexport interface InputFileProps<Multiple extends boolean = false, Type extends InputFileDataType = \"file\">\n extends InputFileBaseProps,\n InputFileExtraProps<Multiple, Type> {}\n\n/** 专用于读取文件的组件 */\nexport function InputFile<Multiple extends boolean = false, Type extends InputFileDataType = \"file\">(props: InputFileProps<Multiple, Type>): ReactNode {\n const { multiple = false, type = \"file\", onChange: _onChange, disabled: _disabled, clearAfterChange, onValueChange, onFileChange, ...rest } = props\n const [disabled, setDisabled] = useState(false)\n\n async function onChange(e: ChangeEvent<HTMLInputElement>) {\n _onChange?.(e)\n const input = e.target\n const { files } = input\n if (!files || files.length === 0) return\n setDisabled(true)\n try {\n if (multiple) {\n const files2: File[] = Array.from(files)\n const values: InputFileDataTypeMap[Type][] = []\n for (const file of files2) {\n const value = (await getFileData(file, type)) as InputFileDataTypeMap[Type]\n values.push(value)\n }\n onFileChange?.(files2 as FileType<Multiple>)\n onValueChange?.(values as ValueType<Multiple, Type>)\n } else {\n const file = files[0]\n onFileChange?.(file as FileType<Multiple>)\n onValueChange?.((await getFileData(file, type)) as ValueType<Multiple, Type>)\n }\n } finally {\n if (clearAfterChange) input.value = \"\"\n setDisabled(false)\n }\n }\n\n return <input disabled={disabled || _disabled} type=\"file\" multiple={multiple} onChange={onChange} {...rest} />\n}\n"],"mappings":"AAAA,YAAY;;AAEZ,SAAiDA,QAAQ,QAAQ,OAAO;AAAA,SAAAC,GAAA,IAAAC,IAAA;AAYxE,OAAO,eAAeC,WAAWA,CAA8BC,IAAU,EAAEC,IAAO,EAAoC;EAClH,MAAMC,UAAU,GAAG,IAAIC,UAAU,CAAC,CAAC;EACnC,QAAQF,IAAI;IACR,KAAK,aAAa;MACdC,UAAU,CAACE,iBAAiB,CAACJ,IAAI,CAAC;MAClC;IACJ,KAAK,QAAQ;MACTE,UAAU,CAACG,kBAAkB,CAACL,IAAI,CAAC;MACnC;IACJ,KAAK,QAAQ;MACTE,UAAU,CAACI,aAAa,CAACN,IAAI,CAAC;MAC9B;IACJ,KAAK,MAAM;MACPE,UAAU,CAACK,UAAU,CAACP,IAAI,CAAC;MAC3B;IACJ;MACI,OAAOA,IAAI;EACnB;EACA,OAAO,IAAIQ,OAAO,CAACC,OAAO,IAAI;IAC1BP,UAAU,CAACQ,gBAAgB,CAAC,MAAM,EAAE,MAAM;MACtCD,OAAO,CAACP,UAAU,CAACS,MAAa,CAAC;IACrC,CAAC,CAAC;EACN,CAAC,CAAC;AACN;AAsBA;AACA,OAAO,SAASC,SAASA,CAA4EC,KAAqC,EAAa;EACnJ,MAAM;IAAEC,QAAQ,GAAG,KAAK;IAAEb,IAAI,GAAG,MAAM;IAAEc,QAAQ,EAAEC,SAAS;IAAEC,QAAQ,EAAEC,SAAS;IAAEC,gBAAgB;IAAEC,aAAa;IAAEC,YAAY;IAAE,GAAGC;EAAK,CAAC,GAAGT,KAAK;EACnJ,MAAM,CAACI,QAAQ,EAAEM,WAAW,CAAC,GAAG3B,QAAQ,CAAC,KAAK,CAAC;EAE/C,eAAemB,QAAQA,CAACS,CAAgC,EAAE;IACtDR,SAAS,GAAGQ,CAAC,CAAC;IACd,MAAMC,KAAK,GAAGD,CAAC,CAACE,MAAM;IACtB,MAAM;MAAEC;IAAM,CAAC,GAAGF,KAAK;IACvB,IAAI,CAACE,KAAK,IAAIA,KAAK,CAACC,MAAM,KAAK,CAAC,EAAE;IAClCL,WAAW,CAAC,IAAI,CAAC;IACjB,IAAI;MACA,IAAIT,QAAQ,EAAE;QACV,MAAMe,MAAc,GAAGC,KAAK,CAACC,IAAI,CAACJ,KAAK,CAAC;QACxC,MAAMK,MAAoC,GAAG,EAAE;QAC/C,KAAK,MAAMhC,IAAI,IAAI6B,MAAM,EAAE;UACvB,MAAMI,KAAK,GAAI,MAAMlC,WAAW,CAACC,IAAI,EAAEC,IAAI,CAAgC;UAC3E+B,MAAM,CAACE,IAAI,CAACD,KAAK,CAAC;QACtB;QACAZ,YAAY,GAAGQ,MAA4B,CAAC;QAC5CT,aAAa,GAAGY,MAAmC,CAAC;MACxD,CAAC,MAAM;QACH,MAAMhC,IAAI,GAAG2B,KAAK,CAAC,CAAC,CAAC;QACrBN,YAAY,GAAGrB,IAA0B,CAAC;QAC1CoB,aAAa,GAAI,MAAMrB,WAAW,CAACC,IAAI,EAAEC,IAAI,CAA+B,CAAC;MACjF;IACJ,CAAC,SAAS;MACN,IAAIkB,gBAAgB,EAAEM,KAAK,CAACQ,KAAK,GAAG,EAAE;MACtCV,WAAW,CAAC,KAAK,CAAC;IACtB;EACJ;EAEA,oBAAOzB,IAAA;IAAOmB,QAAQ,EAAEA,QAAQ,IAAIC,SAAU;IAACjB,IAAI,EAAC,MAAM;IAACa,QAAQ,EAAEA,QAAS;IAACC,QAAQ,EAAEA,QAAS;IAAA,GAAKO;EAAI,CAAG,CAAC;AACnH"}
@@ -0,0 +1,10 @@
1
+ import { ComponentProps, JSX } from "react";
2
+ import { InputFileBaseProps, InputFileDataType, InputFileExtraProps } from "./InputFile";
3
+ export type InputFileButtonProps<Multiple extends boolean = false, Type extends InputFileDataType = "file", AS extends keyof JSX.IntrinsicElements = "button"> = Omit<ComponentProps<AS>, "type" | "disabled"> & InputFileExtraProps<Multiple, Type> & {
4
+ disabled?: boolean;
5
+ inputProps?: InputFileBaseProps;
6
+ dragFile?: boolean;
7
+ as?: AS;
8
+ };
9
+ /** 专用于读取文件的 button 组件 */
10
+ export declare function InputFileButton<Multiple extends boolean = false, Type extends InputFileDataType = "file", AS extends keyof JSX.IntrinsicElements = "button">(props: InputFileButtonProps<Multiple, Type, AS>): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,90 @@
1
+ "use client";
2
+
3
+ import { createElement, Fragment, useRef, useState } from "react";
4
+ import { getFileData, InputFile } from "./InputFile";
5
+ import { jsx as _jsx } from "react/jsx-runtime";
6
+ import { jsxs as _jsxs } from "react/jsx-runtime";
7
+ /** 专用于读取文件的 button 组件 */
8
+ export function InputFileButton(props) {
9
+ const {
10
+ as = "button",
11
+ onClick: _onClick,
12
+ inputProps = {},
13
+ onDrop: _onDrop,
14
+ onDragOver: _onDragOver,
15
+ dragFile,
16
+ disabled: _disabled,
17
+ type = "file",
18
+ multiple,
19
+ onValueChange,
20
+ onFileChange,
21
+ clearAfterChange,
22
+ ...rest
23
+ } = props;
24
+ const {
25
+ style,
26
+ disabled: __disabled,
27
+ ...restInputProps
28
+ } = inputProps;
29
+ const [disabled, setDisabled] = useState(false);
30
+ const input = useRef(null);
31
+ function onClick(e) {
32
+ input.current?.click();
33
+ _onClick?.(e);
34
+ }
35
+ async function onDrop(e) {
36
+ _onDrop?.(e);
37
+ if (disabled || !dragFile) return;
38
+ e.preventDefault();
39
+ const {
40
+ files
41
+ } = e.dataTransfer;
42
+ if (!files || files.length === 0) return;
43
+ setDisabled(true);
44
+ try {
45
+ if (multiple) {
46
+ const files2 = Array.from(files);
47
+ const values = [];
48
+ for (const file of files2) {
49
+ const value = await getFileData(file, type);
50
+ values.push(value);
51
+ }
52
+ onFileChange?.(files2);
53
+ onValueChange?.(values);
54
+ } else {
55
+ const file = files[0];
56
+ onFileChange?.(file);
57
+ onValueChange?.(await getFileData(file, type));
58
+ }
59
+ } finally {
60
+ setDisabled(false);
61
+ }
62
+ }
63
+ function onDragOver(e) {
64
+ _onDragOver?.(e);
65
+ if (disabled || !dragFile) return;
66
+ e.preventDefault();
67
+ }
68
+ return /*#__PURE__*/_jsxs(Fragment, {
69
+ children: [/*#__PURE__*/_jsx(InputFile, {
70
+ disabled: disabled || _disabled || __disabled,
71
+ style: {
72
+ display: "none",
73
+ ...style
74
+ },
75
+ multiple: multiple,
76
+ type: type,
77
+ onValueChange: onValueChange,
78
+ onFileChange: onFileChange,
79
+ clearAfterChange: clearAfterChange,
80
+ ...restInputProps
81
+ }), /*#__PURE__*/createElement(as, {
82
+ disabled: disabled || _disabled,
83
+ onClick,
84
+ onDrop,
85
+ onDragOver,
86
+ ...rest
87
+ })]
88
+ });
89
+ }
90
+ //# sourceMappingURL=InputFileButton.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["createElement","Fragment","useRef","useState","getFileData","InputFile","jsx","_jsx","jsxs","_jsxs","InputFileButton","props","as","onClick","_onClick","inputProps","onDrop","_onDrop","onDragOver","_onDragOver","dragFile","disabled","_disabled","type","multiple","onValueChange","onFileChange","clearAfterChange","rest","style","__disabled","restInputProps","setDisabled","input","e","current","click","preventDefault","files","dataTransfer","length","files2","Array","from","values","file","value","push","children","display"],"sources":["../../../src/components/InputFileButton.tsx"],"sourcesContent":["\"use client\"\r\n\r\nimport { ComponentProps, ComponentRef, createElement, DragEvent, Fragment, JSX, MouseEvent as ReactMouseEvent, useRef, useState } from \"react\"\r\nimport { FileType, getFileData, InputFile, InputFileBaseProps, InputFileDataType, InputFileDataTypeMap, InputFileExtraProps, ValueType } from \"./InputFile\"\r\n\r\nexport type InputFileButtonProps<\r\n Multiple extends boolean = false,\r\n Type extends InputFileDataType = \"file\",\r\n AS extends keyof JSX.IntrinsicElements = \"button\",\r\n> = Omit<ComponentProps<AS>, \"type\" | \"disabled\"> &\r\n InputFileExtraProps<Multiple, Type> & {\r\n disabled?: boolean\r\n inputProps?: InputFileBaseProps\r\n dragFile?: boolean\r\n as?: AS\r\n }\r\n\r\n/** 专用于读取文件的 button 组件 */\r\nexport function InputFileButton<Multiple extends boolean = false, Type extends InputFileDataType = \"file\", AS extends keyof JSX.IntrinsicElements = \"button\">(\r\n props: InputFileButtonProps<Multiple, Type, AS>,\r\n) {\r\n const {\r\n as = \"button\",\r\n onClick: _onClick,\r\n inputProps = {},\r\n onDrop: _onDrop,\r\n onDragOver: _onDragOver,\r\n dragFile,\r\n disabled: _disabled,\r\n type = \"file\",\r\n multiple,\r\n onValueChange,\r\n onFileChange,\r\n clearAfterChange,\r\n ...rest\r\n } = props\r\n\r\n const { style, disabled: __disabled, ...restInputProps } = inputProps\r\n const [disabled, setDisabled] = useState(false)\r\n const input = useRef<HTMLInputElement>(null)\r\n\r\n function onClick(e: ReactMouseEvent<ComponentRef<AS>, MouseEvent>) {\r\n input.current?.click()\r\n _onClick?.(e as any)\r\n }\r\n\r\n async function onDrop(e: DragEvent<ComponentRef<AS>>) {\r\n _onDrop?.(e as any)\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 files2: File[] = Array.from(files)\r\n const values: InputFileDataTypeMap[Type][] = []\r\n for (const file of files2) {\r\n const value = (await getFileData(file, type)) as InputFileDataTypeMap[Type]\r\n values.push(value)\r\n }\r\n onFileChange?.(files2 as FileType<Multiple>)\r\n onValueChange?.(values as ValueType<Multiple, Type>)\r\n } else {\r\n const file = files[0]\r\n onFileChange?.(file as FileType<Multiple>)\r\n onValueChange?.((await getFileData(file, type)) as ValueType<Multiple, Type>)\r\n }\r\n } finally {\r\n setDisabled(false)\r\n }\r\n }\r\n\r\n function onDragOver(e: DragEvent<ComponentRef<AS>>) {\r\n _onDragOver?.(e as any)\r\n if (disabled || !dragFile) return\r\n e.preventDefault()\r\n }\r\n\r\n return (\r\n <Fragment>\r\n <InputFile<Multiple, Type>\r\n disabled={disabled || _disabled || __disabled}\r\n style={{ display: \"none\", ...style }}\r\n multiple={multiple}\r\n type={type as Type}\r\n onValueChange={onValueChange}\r\n onFileChange={onFileChange}\r\n clearAfterChange={clearAfterChange}\r\n {...restInputProps}\r\n />\r\n {createElement(as, {\r\n disabled: disabled || _disabled,\r\n onClick,\r\n onDrop,\r\n onDragOver,\r\n ...rest,\r\n })}\r\n </Fragment>\r\n )\r\n}\r\n\r\n"],"mappings":"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"}
@@ -11,6 +11,7 @@ export * from "./components/HlsPlayer";
11
11
  export * from "./components/ImportExcel";
12
12
  export * from "./components/InfiniteScroll";
13
13
  export * from "./components/InputFile";
14
+ export * from "./components/InputFileButton";
14
15
  export * from "./components/LoopSwiper";
15
16
  export * from "./components/Ring";
16
17
  export * from "./components/Scroll";
package/dist/esm/index.js CHANGED
@@ -11,6 +11,7 @@ export * from "./components/HlsPlayer";
11
11
  export * from "./components/ImportExcel";
12
12
  export * from "./components/InfiniteScroll";
13
13
  export * from "./components/InputFile";
14
+ export * from "./components/InputFileButton";
14
15
  export * from "./components/LoopSwiper";
15
16
  export * from "./components/Ring";
16
17
  export * from "./components/Scroll";
@@ -1 +1 @@
1
- {"version":3,"names":[],"sources":["../../src/index.ts"],"sourcesContent":["export * from \"@/components/AutoFit\"\nexport * from \"@/components/AutoScroll\"\nexport * from \"@/components/AutoSizeTextarea\"\nexport * from \"@/components/CircleText\"\nexport * from \"@/components/CopyButton\"\nexport * from \"@/components/Echart\"\nexport * from \"@/components/ExportExcel\"\nexport * from \"@/components/Flow\"\nexport * from \"@/components/FormLabel\"\nexport * from \"@/components/HlsPlayer\"\nexport * from \"@/components/ImportExcel\"\nexport * from \"@/components/InfiniteScroll\"\nexport * from \"@/components/InputFile\"\nexport * from \"@/components/LoopSwiper\"\nexport * from \"@/components/Ring\"\nexport * from \"@/components/Scroll\"\nexport * from \"@/components/SectionRing\"\nexport * from \"@/components/Skeleton\"\nexport * from \"@/components/Title\"\nexport * from \"@/components/TransitionBox\"\nexport * from \"@/components/TransitionNum\"\nexport * from \"@/components/Trapezium\"\nexport * from \"@/components/Unify\"\nexport * from \"@/utils/getReactVersion\"\nexport * from \"@/utils/index\"\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA"}
1
+ {"version":3,"names":[],"sources":["../../src/index.ts"],"sourcesContent":["export * from \"@/components/AutoFit\"\nexport * from \"@/components/AutoScroll\"\nexport * from \"@/components/AutoSizeTextarea\"\nexport * from \"@/components/CircleText\"\nexport * from \"@/components/CopyButton\"\nexport * from \"@/components/Echart\"\nexport * from \"@/components/ExportExcel\"\nexport * from \"@/components/Flow\"\nexport * from \"@/components/FormLabel\"\nexport * from \"@/components/HlsPlayer\"\nexport * from \"@/components/ImportExcel\"\nexport * from \"@/components/InfiniteScroll\"\nexport * from \"@/components/InputFile\"\nexport * from \"@/components/InputFileButton\"\nexport * from \"@/components/LoopSwiper\"\nexport * from \"@/components/Ring\"\nexport * from \"@/components/Scroll\"\nexport * from \"@/components/SectionRing\"\nexport * from \"@/components/Skeleton\"\nexport * from \"@/components/Title\"\nexport * from \"@/components/TransitionBox\"\nexport * from \"@/components/TransitionNum\"\nexport * from \"@/components/Trapezium\"\nexport * from \"@/components/Unify\"\nexport * from \"@/utils/getReactVersion\"\nexport * from \"@/utils/index\"\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "deepsea-components",
3
- "version": "5.9.7",
3
+ "version": "5.10.0",
4
4
  "description": "格数科技自用组件库",
5
5
  "main": "dist/cjs/index.js",
6
6
  "module": "dist/esm/index.js",
@@ -29,8 +29,8 @@
29
29
  "@emotion/css": "^11.13.5",
30
30
  "ahooks": "^3.8.4",
31
31
  "clipboard": "^2.0.11",
32
- "echarts": "^5.5.1",
33
- "hls.js": "^1.5.18",
32
+ "echarts": "^5.6.0",
33
+ "hls.js": "^1.5.20",
34
34
  "smooth-scrollbar": "^8.8.4",
35
35
  "deepsea-tools": "5.19.3"
36
36
  },
@@ -1,17 +1,17 @@
1
1
  "use client"
2
2
 
3
- import { forwardRef } from "react"
4
3
  import { readExcel } from "deepsea-tools"
4
+ import { FC } from "react"
5
5
 
6
6
  import { InputFile, InputFileProps } from "./InputFile"
7
7
 
8
- export interface ImportExcelProps extends Omit<InputFileProps, "multiple" | "onChange" | "accept" | "type"> {
9
- onChange?: (data: Record<string, any>[]) => void
8
+ export interface ImportExcelProps extends Omit<InputFileProps<false, "arrayBuffer">, "multiple" | "accept" | "type" | "onValueChange"> {
9
+ onValueChange?: (data: Record<string, any>[]) => void
10
10
  }
11
11
 
12
12
  /** 专门用于读取 excel 的组件 */
13
- export const ImportExcel = forwardRef<HTMLInputElement, ImportExcelProps>((props, ref) => {
14
- const { onChange, ...rest } = props
13
+ export const ImportExcel: FC<ImportExcelProps> = props => {
14
+ const { onValueChange, ...rest } = props
15
15
 
16
- return <InputFile ref={ref} accept=".xlsx" type="arrayBuffer" onChange={({ result }) => onChange?.(readExcel(result))} {...rest} />
17
- })
16
+ return <InputFile accept=".xlsx" type="arrayBuffer" onValueChange={data => onValueChange?.(readExcel(data))} {...rest} />
17
+ }
@@ -1,8 +1,8 @@
1
1
  "use client"
2
2
 
3
- import { ButtonHTMLAttributes, ChangeEvent, DragEvent, Fragment, InputHTMLAttributes, MouseEvent as ReactMouseEvent, forwardRef, useRef, useState } from "react"
3
+ import { ChangeEvent, ComponentProps, ReactNode, useState } from "react"
4
4
 
5
- export interface InputFileDataTypes {
5
+ export interface InputFileDataTypeMap {
6
6
  base64: string
7
7
  text: string
8
8
  arrayBuffer: ArrayBuffer
@@ -10,51 +10,9 @@ export interface InputFileDataTypes {
10
10
  file: File
11
11
  }
12
12
 
13
- export type InputFileDataType = keyof InputFileDataTypes
13
+ export type InputFileDataType = keyof InputFileDataTypeMap
14
14
 
15
- export interface InputFileData<T> {
16
- result: T
17
- file: File
18
- }
19
-
20
- export type InputFileProps = (
21
- | {
22
- multiple?: false
23
- type: "base64" | "text" | "binary"
24
- onChange?: (data: InputFileData<string>) => void
25
- }
26
- | {
27
- multiple?: false
28
- type: "arrayBuffer"
29
- onChange?: (data: InputFileData<ArrayBuffer>) => void
30
- }
31
- | {
32
- multiple?: false
33
- type?: "file"
34
- onChange?: (data: InputFileData<File>) => void
35
- }
36
- | {
37
- multiple: true
38
- type: "base64" | "text" | "binary"
39
- onChange?: (data: InputFileData<string>[]) => void
40
- }
41
- | {
42
- multiple: true
43
- type: "arrayBuffer"
44
- onChange?: (data: InputFileData<ArrayBuffer>[]) => void
45
- }
46
- | {
47
- multiple: true
48
- type?: "file"
49
- onChange?: (data: InputFileData<File>[]) => void
50
- }
51
- ) &
52
- Omit<InputHTMLAttributes<HTMLInputElement>, "onChange" | "multiple" | "type"> & {
53
- /** 是否在捕获文件后清除 input 上的文件,默认为 false,主要区别在于如果不清除,连续两次选择同样的文件不会触发 onChange 事件,如果用于 form 表单,请设置为 flase */
54
- clearAfterChange?: boolean
55
- }
56
-
57
- export async function getFileData<T extends InputFileDataType>(file: File, type: T): Promise<InputFileDataTypes[T]> {
15
+ export async function getFileData<T extends InputFileDataType>(file: File, type: T): Promise<InputFileDataTypeMap[T]> {
58
16
  const fileReader = new FileReader()
59
17
  switch (type) {
60
18
  case "arrayBuffer":
@@ -79,31 +37,51 @@ export async function getFileData<T extends InputFileDataType>(file: File, type:
79
37
  })
80
38
  }
81
39
 
40
+ export interface InputFileBaseProps extends Omit<ComponentProps<"input">, "multiple" | "type"> {}
41
+
42
+ export type FileType<Multiple extends boolean> = Multiple extends true ? File[] : File
43
+ export type ValueType<Multiple extends boolean, Type extends InputFileDataType> = Multiple extends true
44
+ ? InputFileDataTypeMap[Type][]
45
+ : InputFileDataTypeMap[Type]
46
+
47
+ export interface InputFileExtraProps<Multiple extends boolean = false, Type extends InputFileDataType = "file"> {
48
+ multiple?: Multiple
49
+ type?: Type
50
+ onValueChange?: (data: ValueType<Multiple, Type>) => void
51
+ onFileChange?: (data: FileType<Multiple>) => void
52
+ /** 是否在捕获文件后清除 input 上的文件,默认为 false,主要区别在于如果不清除,连续两次选择同样的文件不会触发 onChange 事件,如果用于 form 表单,请设置为 flase */
53
+ clearAfterChange?: boolean
54
+ }
55
+
56
+ export interface InputFileProps<Multiple extends boolean = false, Type extends InputFileDataType = "file">
57
+ extends InputFileBaseProps,
58
+ InputFileExtraProps<Multiple, Type> {}
59
+
82
60
  /** 专用于读取文件的组件 */
83
- export const InputFile = forwardRef<HTMLInputElement, InputFileProps>((props, ref) => {
84
- const { multiple = false, type = "file", onChange, disabled: inputDisabled, clearAfterChange, ...rest } = props
61
+ export function InputFile<Multiple extends boolean = false, Type extends InputFileDataType = "file">(props: InputFileProps<Multiple, Type>): ReactNode {
62
+ const { multiple = false, type = "file", onChange: _onChange, disabled: _disabled, clearAfterChange, onValueChange, onFileChange, ...rest } = props
85
63
  const [disabled, setDisabled] = useState(false)
86
64
 
87
- async function onInputChange(e: ChangeEvent<HTMLInputElement>) {
65
+ async function onChange(e: ChangeEvent<HTMLInputElement>) {
66
+ _onChange?.(e)
88
67
  const input = e.target
89
68
  const { files } = input
90
69
  if (!files || files.length === 0) return
91
70
  setDisabled(true)
92
71
  try {
93
72
  if (multiple) {
94
- const result: any[] = []
95
- for (const file of Array.from(files)) {
96
- result.push({
97
- result: await getFileData(file, type),
98
- file,
99
- })
73
+ const files2: File[] = Array.from(files)
74
+ const values: InputFileDataTypeMap[Type][] = []
75
+ for (const file of files2) {
76
+ const value = (await getFileData(file, type)) as InputFileDataTypeMap[Type]
77
+ values.push(value)
100
78
  }
101
- onChange?.(result as any)
79
+ onFileChange?.(files2 as FileType<Multiple>)
80
+ onValueChange?.(values as ValueType<Multiple, Type>)
102
81
  } else {
103
- onChange?.({
104
- result: await getFileData(files[0], type),
105
- file: files[0],
106
- } as any)
82
+ const file = files[0]
83
+ onFileChange?.(file as FileType<Multiple>)
84
+ onValueChange?.((await getFileData(file, type)) as ValueType<Multiple, Type>)
107
85
  }
108
86
  } finally {
109
87
  if (clearAfterChange) input.value = ""
@@ -111,72 +89,5 @@ export const InputFile = forwardRef<HTMLInputElement, InputFileProps>((props, re
111
89
  }
112
90
  }
113
91
 
114
- return <input ref={ref} disabled={disabled || inputDisabled} type="file" multiple={multiple} onChange={onInputChange} {...rest} />
115
- })
116
-
117
- export type InputFileButtonProps = ButtonHTMLAttributes<HTMLButtonElement> & {
118
- input: InputFileProps
119
- dragFile?: boolean
92
+ return <input disabled={disabled || _disabled} type="file" multiple={multiple} onChange={onChange} {...rest} />
120
93
  }
121
-
122
- /** 专用于读取文件的 button 组件 */
123
- export const InputFileButton = forwardRef<HTMLButtonElement, InputFileButtonProps>((props, ref) => {
124
- const { onClick: _onClick, input: inputProps, onDrop: _onDrop, onDragOver: _onDragOver, dragFile, disabled: _disabled, ...rest } = props
125
- const { style, disabled: __disabled, multiple, onChange, type = "file", ...restInputProps } = inputProps
126
- const [disabled, setDisabled] = useState(false)
127
- const input = useRef<HTMLInputElement>(null)
128
-
129
- function onClick(e: ReactMouseEvent<HTMLButtonElement, MouseEvent>) {
130
- input.current?.click()
131
- _onClick?.(e)
132
- }
133
-
134
- async function onDrop(e: DragEvent<HTMLButtonElement>) {
135
- _onDrop?.(e)
136
- if (disabled || !dragFile) return
137
- e.preventDefault()
138
- const { files } = e.dataTransfer
139
- if (!files || files.length === 0) return
140
- setDisabled(true)
141
- try {
142
- if (multiple) {
143
- const result: any[] = []
144
- for (const file of Array.from(files)) {
145
- result.push({
146
- result: await getFileData(file, type),
147
- file,
148
- })
149
- }
150
- onChange?.(result as any)
151
- } else {
152
- onChange?.({
153
- result: await getFileData(files[0], type),
154
- file: files[0],
155
- } as any)
156
- }
157
- } finally {
158
- setDisabled(false)
159
- }
160
- }
161
-
162
- function onDragOver(e: DragEvent<HTMLButtonElement>) {
163
- _onDragOver?.(e)
164
- if (disabled || !dragFile) return
165
- e.preventDefault()
166
- }
167
-
168
- return (
169
- <Fragment>
170
- <InputFile
171
- ref={input}
172
- disabled={disabled || _disabled || __disabled}
173
- style={{ display: "none", ...style }}
174
- multiple={multiple as any}
175
- onChange={onChange as any}
176
- type={type as any}
177
- {...restInputProps}
178
- />
179
- <button ref={ref} type="button" disabled={disabled || _disabled} onClick={onClick} onDrop={onDrop} onDragOver={onDragOver} {...rest} />
180
- </Fragment>
181
- )
182
- })