funda-ui 1.0.272

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 (246) hide show
  1. package/BackToTop/index.css +34 -0
  2. package/BackToTop/index.d.ts +11 -0
  3. package/BackToTop/index.js +458 -0
  4. package/CascadingSelect/index.css +159 -0
  5. package/CascadingSelect/index.d.ts +56 -0
  6. package/CascadingSelect/index.js +958 -0
  7. package/CascadingSelectE2E/index.css +159 -0
  8. package/CascadingSelectE2E/index.d.ts +60 -0
  9. package/CascadingSelectE2E/index.js +1126 -0
  10. package/Checkbox/index.d.ts +30 -0
  11. package/Checkbox/index.js +226 -0
  12. package/ColorPicker/index.css +38 -0
  13. package/ColorPicker/index.d.ts +27 -0
  14. package/ColorPicker/index.js +246 -0
  15. package/DigitalClock/index.d.ts +7 -0
  16. package/DigitalClock/index.js +208 -0
  17. package/DropdownMenu/index.css +127 -0
  18. package/DropdownMenu/index.d.ts +37 -0
  19. package/DropdownMenu/index.js +237 -0
  20. package/DynamicFields/index.d.ts +26 -0
  21. package/DynamicFields/index.js +412 -0
  22. package/File/index.d.ts +36 -0
  23. package/File/index.js +473 -0
  24. package/Input/index.d.ts +42 -0
  25. package/Input/index.js +286 -0
  26. package/LiveSearch/index.d.ts +37 -0
  27. package/LiveSearch/index.js +1195 -0
  28. package/ModalDialog/index.d.ts +60 -0
  29. package/ModalDialog/index.js +725 -0
  30. package/ModeSwitch/index.d.ts +17 -0
  31. package/ModeSwitch/index.js +202 -0
  32. package/MultiFuncSelect/index.css +178 -0
  33. package/MultiFuncSelect/index.d.ts +67 -0
  34. package/MultiFuncSelect/index.js +1826 -0
  35. package/MultilevelDropdownMenu/index.css +35 -0
  36. package/MultilevelDropdownMenu/index.d.ts +25 -0
  37. package/MultilevelDropdownMenu/index.js +464 -0
  38. package/Pagination/index.d.ts +49 -0
  39. package/Pagination/index.js +341 -0
  40. package/README.md +108 -0
  41. package/Radio/index.d.ts +31 -0
  42. package/Radio/index.js +246 -0
  43. package/RangeSlider/index.css +149 -0
  44. package/RangeSlider/index.d.ts +21 -0
  45. package/RangeSlider/index.js +730 -0
  46. package/ScrollReveal/index.css +23 -0
  47. package/ScrollReveal/index.d.ts +21 -0
  48. package/ScrollReveal/index.js +216 -0
  49. package/Scrollbar/index.css +168 -0
  50. package/Scrollbar/index.d.ts +15 -0
  51. package/Scrollbar/index.js +605 -0
  52. package/SearchBar/index.d.ts +32 -0
  53. package/SearchBar/index.js +246 -0
  54. package/Select/index.d.ts +34 -0
  55. package/Select/index.js +331 -0
  56. package/ShowMoreLess/index.css +23 -0
  57. package/ShowMoreLess/index.d.ts +30 -0
  58. package/ShowMoreLess/index.js +202 -0
  59. package/Switch/index.d.ts +29 -0
  60. package/Switch/index.js +211 -0
  61. package/Table/index.css +533 -0
  62. package/Table/index.d.ts +25 -0
  63. package/Table/index.js +2113 -0
  64. package/Tabs/index.d.ts +3 -0
  65. package/Tabs/index.js +323 -0
  66. package/TagInput/index.css +90 -0
  67. package/TagInput/index.d.ts +28 -0
  68. package/TagInput/index.js +370 -0
  69. package/Textarea/index.d.ts +30 -0
  70. package/Textarea/index.js +242 -0
  71. package/Toast/index.css +95 -0
  72. package/Toast/index.d.ts +35 -0
  73. package/Toast/index.js +340 -0
  74. package/Tooltip/index.css +240 -0
  75. package/Tooltip/index.d.ts +19 -0
  76. package/Tooltip/index.js +200 -0
  77. package/Tree/index.css +225 -0
  78. package/Tree/index.d.ts +37 -0
  79. package/Tree/index.js +1406 -0
  80. package/all.d.ts +33 -0
  81. package/all.js +35 -0
  82. package/lib/cjs/BackToTop/index.d.ts +11 -0
  83. package/lib/cjs/BackToTop/index.js +458 -0
  84. package/lib/cjs/CascadingSelect/index.d.ts +56 -0
  85. package/lib/cjs/CascadingSelect/index.js +958 -0
  86. package/lib/cjs/CascadingSelectE2E/index.d.ts +60 -0
  87. package/lib/cjs/CascadingSelectE2E/index.js +1126 -0
  88. package/lib/cjs/Checkbox/index.d.ts +30 -0
  89. package/lib/cjs/Checkbox/index.js +226 -0
  90. package/lib/cjs/ColorPicker/index.d.ts +27 -0
  91. package/lib/cjs/ColorPicker/index.js +246 -0
  92. package/lib/cjs/DigitalClock/index.d.ts +7 -0
  93. package/lib/cjs/DigitalClock/index.js +208 -0
  94. package/lib/cjs/DropdownMenu/index.d.ts +37 -0
  95. package/lib/cjs/DropdownMenu/index.js +237 -0
  96. package/lib/cjs/DynamicFields/index.d.ts +26 -0
  97. package/lib/cjs/DynamicFields/index.js +412 -0
  98. package/lib/cjs/File/index.d.ts +36 -0
  99. package/lib/cjs/File/index.js +473 -0
  100. package/lib/cjs/Input/index.d.ts +42 -0
  101. package/lib/cjs/Input/index.js +286 -0
  102. package/lib/cjs/LiveSearch/index.d.ts +37 -0
  103. package/lib/cjs/LiveSearch/index.js +1195 -0
  104. package/lib/cjs/ModalDialog/index.d.ts +60 -0
  105. package/lib/cjs/ModalDialog/index.js +725 -0
  106. package/lib/cjs/ModeSwitch/index.d.ts +17 -0
  107. package/lib/cjs/ModeSwitch/index.js +202 -0
  108. package/lib/cjs/MultiFuncSelect/index.d.ts +67 -0
  109. package/lib/cjs/MultiFuncSelect/index.js +1826 -0
  110. package/lib/cjs/MultilevelDropdownMenu/index.d.ts +25 -0
  111. package/lib/cjs/MultilevelDropdownMenu/index.js +464 -0
  112. package/lib/cjs/Pagination/index.d.ts +49 -0
  113. package/lib/cjs/Pagination/index.js +341 -0
  114. package/lib/cjs/Radio/index.d.ts +31 -0
  115. package/lib/cjs/Radio/index.js +246 -0
  116. package/lib/cjs/RangeSlider/index.d.ts +21 -0
  117. package/lib/cjs/RangeSlider/index.js +730 -0
  118. package/lib/cjs/ScrollReveal/index.d.ts +21 -0
  119. package/lib/cjs/ScrollReveal/index.js +216 -0
  120. package/lib/cjs/Scrollbar/index.d.ts +15 -0
  121. package/lib/cjs/Scrollbar/index.js +605 -0
  122. package/lib/cjs/SearchBar/index.d.ts +32 -0
  123. package/lib/cjs/SearchBar/index.js +246 -0
  124. package/lib/cjs/Select/index.d.ts +34 -0
  125. package/lib/cjs/Select/index.js +331 -0
  126. package/lib/cjs/ShowMoreLess/index.d.ts +30 -0
  127. package/lib/cjs/ShowMoreLess/index.js +202 -0
  128. package/lib/cjs/Switch/index.d.ts +29 -0
  129. package/lib/cjs/Switch/index.js +211 -0
  130. package/lib/cjs/Table/index.d.ts +25 -0
  131. package/lib/cjs/Table/index.js +2113 -0
  132. package/lib/cjs/Tabs/index.d.ts +3 -0
  133. package/lib/cjs/Tabs/index.js +323 -0
  134. package/lib/cjs/TagInput/index.d.ts +28 -0
  135. package/lib/cjs/TagInput/index.js +370 -0
  136. package/lib/cjs/Textarea/index.d.ts +30 -0
  137. package/lib/cjs/Textarea/index.js +242 -0
  138. package/lib/cjs/Toast/index.d.ts +35 -0
  139. package/lib/cjs/Toast/index.js +340 -0
  140. package/lib/cjs/Tooltip/index.d.ts +19 -0
  141. package/lib/cjs/Tooltip/index.js +200 -0
  142. package/lib/cjs/Tree/index.d.ts +37 -0
  143. package/lib/cjs/Tree/index.js +1406 -0
  144. package/lib/cjs/index.d.ts +33 -0
  145. package/lib/cjs/index.js +35 -0
  146. package/lib/css/BackToTop/index.css +34 -0
  147. package/lib/css/CascadingSelect/index.css +159 -0
  148. package/lib/css/CascadingSelectE2E/index.css +159 -0
  149. package/lib/css/ColorPicker/index.css +38 -0
  150. package/lib/css/DropdownMenu/index.css +127 -0
  151. package/lib/css/MultiFuncSelect/index.css +178 -0
  152. package/lib/css/MultilevelDropdownMenu/index.css +35 -0
  153. package/lib/css/RangeSlider/index.css +149 -0
  154. package/lib/css/ScrollReveal/index.css +23 -0
  155. package/lib/css/Scrollbar/index.css +168 -0
  156. package/lib/css/ShowMoreLess/index.css +23 -0
  157. package/lib/css/Table/index.css +533 -0
  158. package/lib/css/TagInput/index.css +90 -0
  159. package/lib/css/Toast/index.css +95 -0
  160. package/lib/css/Tooltip/index.css +240 -0
  161. package/lib/css/Tree/index.css +225 -0
  162. package/lib/esm/BackToTop/index.scss +47 -0
  163. package/lib/esm/BackToTop/index.tsx +182 -0
  164. package/lib/esm/BackToTop/utils/easing.js +200 -0
  165. package/lib/esm/BackToTop/utils/performance.js +52 -0
  166. package/lib/esm/CascadingSelect/Group.tsx +39 -0
  167. package/lib/esm/CascadingSelect/index.scss +214 -0
  168. package/lib/esm/CascadingSelect/index.tsx +922 -0
  169. package/lib/esm/CascadingSelect/utils/performance.js +52 -0
  170. package/lib/esm/CascadingSelectE2E/Group.tsx +39 -0
  171. package/lib/esm/CascadingSelectE2E/index.scss +214 -0
  172. package/lib/esm/CascadingSelectE2E/index.tsx +1091 -0
  173. package/lib/esm/CascadingSelectE2E/utils/performance.js +52 -0
  174. package/lib/esm/Checkbox/index.tsx +160 -0
  175. package/lib/esm/ColorPicker/index.scss +48 -0
  176. package/lib/esm/ColorPicker/index.tsx +187 -0
  177. package/lib/esm/DigitalClock/index.tsx +72 -0
  178. package/lib/esm/DigitalClock/utils/useInterval.js +43 -0
  179. package/lib/esm/DropdownMenu/Option.tsx +27 -0
  180. package/lib/esm/DropdownMenu/index.scss +180 -0
  181. package/lib/esm/DropdownMenu/index.tsx +148 -0
  182. package/lib/esm/DynamicFields/index.tsx +386 -0
  183. package/lib/esm/File/index.tsx +302 -0
  184. package/lib/esm/Input/index.tsx +233 -0
  185. package/lib/esm/LiveSearch/index.tsx +582 -0
  186. package/lib/esm/LiveSearch/utils/performance.js +52 -0
  187. package/lib/esm/LiveSearch/utils/useThrottle.js +36 -0
  188. package/lib/esm/ModalDialog/index.tsx +479 -0
  189. package/lib/esm/ModalDialog/plugins/BSL/bodyScrollLock.es6.js +262 -0
  190. package/lib/esm/ModalDialog/plugins/BSL/index.ts +2 -0
  191. package/lib/esm/ModeSwitch/index.tsx +82 -0
  192. package/lib/esm/MultiFuncSelect/index.scss +269 -0
  193. package/lib/esm/MultiFuncSelect/index.tsx +1597 -0
  194. package/lib/esm/MultiFuncSelect/utils/performance.js +52 -0
  195. package/lib/esm/MultiFuncSelect/utils/tree.js +103 -0
  196. package/lib/esm/MultiFuncSelect/utils/useThrottle.js +36 -0
  197. package/lib/esm/MultilevelDropdownMenu/MenuList.tsx +230 -0
  198. package/lib/esm/MultilevelDropdownMenu/index.scss +75 -0
  199. package/lib/esm/MultilevelDropdownMenu/index.tsx +71 -0
  200. package/lib/esm/MultilevelDropdownMenu/utils/dom.js +81 -0
  201. package/lib/esm/Pagination/index.tsx +230 -0
  202. package/lib/esm/Pagination/pagination-navigators.tsx +60 -0
  203. package/lib/esm/Radio/index.tsx +201 -0
  204. package/lib/esm/RangeSlider/index.scss +184 -0
  205. package/lib/esm/RangeSlider/index.tsx +223 -0
  206. package/lib/esm/ScrollReveal/index.scss +27 -0
  207. package/lib/esm/ScrollReveal/index.tsx +146 -0
  208. package/lib/esm/Scrollbar/index.scss +217 -0
  209. package/lib/esm/Scrollbar/index.tsx +497 -0
  210. package/lib/esm/Scrollbar/utils/performance.js +52 -0
  211. package/lib/esm/SearchBar/index.tsx +181 -0
  212. package/lib/esm/Select/index.tsx +276 -0
  213. package/lib/esm/ShowMoreLess/index.scss +27 -0
  214. package/lib/esm/ShowMoreLess/index.tsx +144 -0
  215. package/lib/esm/Switch/index.tsx +143 -0
  216. package/lib/esm/Table/TableColgroup.tsx +29 -0
  217. package/lib/esm/Table/TableField.tsx +40 -0
  218. package/lib/esm/Table/TableFieldRow.tsx +212 -0
  219. package/lib/esm/Table/TableHeaders.tsx +146 -0
  220. package/lib/esm/Table/TableRow.tsx +127 -0
  221. package/lib/esm/Table/TableSummaries.tsx +36 -0
  222. package/lib/esm/Table/index.scss +364 -0
  223. package/lib/esm/Table/index.tsx +576 -0
  224. package/lib/esm/Table/table-utils.ts +65 -0
  225. package/lib/esm/Table/utils/dom.js +81 -0
  226. package/lib/esm/Table/utils/performance.js +52 -0
  227. package/lib/esm/Tabs/TabList.tsx +42 -0
  228. package/lib/esm/Tabs/TabPanel.tsx +34 -0
  229. package/lib/esm/Tabs/Tabs.tsx +232 -0
  230. package/lib/esm/Tabs/index.tsx +3 -0
  231. package/lib/esm/TagInput/index.scss +125 -0
  232. package/lib/esm/TagInput/index.tsx +314 -0
  233. package/lib/esm/Textarea/index.tsx +178 -0
  234. package/lib/esm/Toast/Item.tsx +75 -0
  235. package/lib/esm/Toast/index.scss +120 -0
  236. package/lib/esm/Toast/index.tsx +249 -0
  237. package/lib/esm/Tooltip/index.scss +327 -0
  238. package/lib/esm/Tooltip/index.tsx +142 -0
  239. package/lib/esm/Tree/TreeList.tsx +503 -0
  240. package/lib/esm/Tree/index.scss +375 -0
  241. package/lib/esm/Tree/index.tsx +301 -0
  242. package/lib/esm/Tree/init-height.tsx +27 -0
  243. package/lib/esm/Tree/utils/convert-tree.js +29 -0
  244. package/lib/esm/Tree/utils/dom.js +81 -0
  245. package/lib/esm/index.js +31 -0
  246. package/package.json +40 -0
@@ -0,0 +1,302 @@
1
+ import React, { useId, useState, useEffect, useRef, forwardRef } from 'react';
2
+
3
+ declare module 'react' {
4
+ interface ReactI18NextChildren<T> {
5
+ children?: any;
6
+ }
7
+ }
8
+
9
+ type FileProps = {
10
+ wrapperClassName?: string;
11
+ controlClassName?: string;
12
+ labelClassName?: string;
13
+ labelHoverClassName?: string;
14
+ fetchUrl?: string;
15
+ fetchMethod?: string;
16
+ multiple?: boolean;
17
+ submitLabel?: React.ReactNode | string;
18
+ submitClassName?: string;
19
+ value?: string;
20
+ label?: React.ReactNode | string;
21
+ name?: string;
22
+ disabled?: any;
23
+ required?: any;
24
+ /** Incoming data, you can set the third parameter of `onComplete` */
25
+ data?: any;
26
+ /** -- */
27
+ id?: string;
28
+ tabIndex?: number;
29
+ [key: `data-${string}`]: string | undefined;
30
+ fetchFuncAsync?: any;
31
+ fetchFuncMethod?: string;
32
+ fetchFuncMethodParams?: any[];
33
+ onChange?: (e: any, e2: any, value: any) => void;
34
+ onComplete?: (e: any, e2: any, callback: any, incomingData: string | null | undefined) => void;
35
+ onProgress?: (files: any, e2: any) => void;
36
+
37
+ };
38
+
39
+
40
+ const File = forwardRef((props: FileProps, ref: any) => {
41
+ const {
42
+ wrapperClassName,
43
+ controlClassName,
44
+ labelClassName,
45
+ labelHoverClassName,
46
+ fetchUrl,
47
+ fetchMethod,
48
+ multiple,
49
+ submitLabel,
50
+ submitClassName,
51
+ disabled,
52
+ required,
53
+ value,
54
+ label,
55
+ name,
56
+ id,
57
+ data,
58
+ tabIndex,
59
+ fetchFuncAsync,
60
+ fetchFuncMethod,
61
+ fetchFuncMethodParams,
62
+ onChange,
63
+ onComplete,
64
+ onProgress,
65
+ ...attributes
66
+ } = props;
67
+
68
+
69
+ const uniqueID = useId();
70
+ const idRes = id || uniqueID;
71
+ const rootRef = useRef<any>(null);
72
+ const fileInputRef = useRef<any>(null);
73
+ const labelRef = useRef<any>(null);
74
+ const submitRef = useRef<any>(null);
75
+ const [forceUpdate, setForceUpdate] = useState<Boolean>(false);
76
+ const [defaultValue, setDefaultValue] = useState<any>(null);
77
+ const [incomingData, setIncomingData] = useState<string | null | undefined>(null);
78
+
79
+ function handleFileInput(event: any) {
80
+ if (fileInputRef.current.nextSibling.contains(document.activeElement)) {
81
+ // Bind space to trigger clicking of the button when focused
82
+ if (event.keyCode === 32) {
83
+ fileInputRef.current.click();
84
+ }
85
+ }
86
+ }
87
+
88
+ async function fetchData(params: any, data: any) {
89
+
90
+ if (typeof fetchFuncAsync === 'object') {
91
+ const response: any = await fetchFuncAsync[`${fetchFuncMethod}`](...params.split(','), data);
92
+ return response.data;
93
+ } else {
94
+ return null;
95
+ }
96
+
97
+ }
98
+
99
+ async function fetchDataDefault(url: string, data: any = {}, methord: string = 'GET', ...rest: any) {
100
+
101
+ let res = {};
102
+ if (typeof window === 'undefined') return res;
103
+
104
+ try {
105
+ const response = await fetch(url, {
106
+ method: methord,
107
+ body: data,
108
+ ...rest
109
+ });
110
+
111
+ res = await response.json();
112
+
113
+ } catch (error) {
114
+ res = {
115
+ 'error': error
116
+ }
117
+ }
118
+
119
+ return res;
120
+
121
+ }
122
+
123
+
124
+ function handleLabelEnter(event: any) {
125
+ event.currentTarget.getElementsByTagName('button')[0].className = labelHoverClassName ? labelHoverClassName : 'btn btn-primary';
126
+ }
127
+
128
+ function handleLabelLeave(event: any) {
129
+ event.currentTarget.getElementsByTagName('button')[0].className = labelClassName ? labelClassName : 'btn btn-outline-secondary';
130
+ }
131
+
132
+
133
+
134
+ function handleSubmit(event: any) {
135
+ event.preventDefault();
136
+
137
+
138
+ const curFiles = fileInputRef.current.files;
139
+
140
+ onProgress?.(curFiles, submitRef.current);
141
+
142
+ if (fetchUrl) {
143
+
144
+ const formData = new FormData();
145
+ formData.append('action', 'upload_plug_action');
146
+
147
+ for (let i = 0; i < curFiles.length; i++) {
148
+ formData.append("clientFiles", curFiles[i]);
149
+ }
150
+
151
+ fetchDataDefault(fetchUrl, formData, fetchMethod ? fetchMethod : 'POST', {
152
+ headers: { 'Content-Type': 'multipart/form-data' }
153
+ }).then(function (response: any) {
154
+ const jsonData = response.data;
155
+ onComplete?.(event, submitRef.current, jsonData, incomingData);
156
+
157
+ // update default value
158
+ setDefaultValue(undefined);
159
+ fileInputRef.current.value = '';
160
+
161
+ });
162
+ } else {
163
+
164
+ const streamToText = async (blob: any) => {
165
+ const readableStream = await blob.getReader();
166
+ const chunk = await readableStream.read();
167
+
168
+ return new TextDecoder('utf-8').decode(chunk.value);
169
+ };
170
+
171
+
172
+ (async () => {
173
+
174
+ const allFiles: any[] = [];
175
+ for (let i = 0; i < curFiles.length; i++) {
176
+
177
+ const file = curFiles[i];
178
+ const fileSliceBlob = file.slice(0, file.length);
179
+ const fileSliceBlobStream = await fileSliceBlob.stream();
180
+ allFiles.push(await streamToText(fileSliceBlobStream));
181
+
182
+ }
183
+
184
+ //send
185
+ Promise.all(allFiles).then((values) => {
186
+ const _params: any[] = fetchFuncMethodParams || [];
187
+ fetchData((_params).join(','), values);
188
+
189
+ });
190
+ })();
191
+
192
+
193
+ }
194
+
195
+ }
196
+
197
+ function handleChange(event: any) {
198
+ const val = event.target.value;
199
+
200
+ setForceUpdate(!forceUpdate);
201
+
202
+
203
+ // update default value
204
+ setDefaultValue(null);
205
+
206
+
207
+ //----
208
+ //remove focus style
209
+ if (val === '') {
210
+ rootRef.current.classList.remove('focus');
211
+ }
212
+
213
+ //
214
+ onChange?.(event, submitRef.current, fileInputRef.current.files);
215
+ }
216
+
217
+ function fileNames() {
218
+
219
+ const { current } = fileInputRef;
220
+
221
+ if (current && current.files.length > 0) {
222
+ let messages: string[] = [];
223
+ for (let file of current.files) {
224
+ messages = messages.concat(file.name);
225
+ }
226
+ return messages.join(',');
227
+ }
228
+ return null;
229
+ }
230
+
231
+
232
+ useEffect(() => {
233
+
234
+ // update incoming data
235
+ //------------------------------------------
236
+ setIncomingData(data);
237
+
238
+ // update default value
239
+ //--------------
240
+ setDefaultValue(value);
241
+
242
+ }, [data]);
243
+
244
+
245
+
246
+ return (
247
+ <>
248
+
249
+
250
+ <div className={wrapperClassName || wrapperClassName === '' ? wrapperClassName : "mb-3 position-relative upload-control"} ref={rootRef}>
251
+ <label
252
+ ref={labelRef}
253
+ onMouseEnter={handleLabelEnter}
254
+ onMouseLeave={handleLabelLeave}
255
+ style={{ cursor: 'pointer', pointerEvents: disabled ? 'none' : 'auto', opacity: disabled ? 0.5 : 1 }}
256
+ htmlFor={idRes}
257
+ className="form-label d-inline"
258
+ ><button className={labelClassName ? labelClassName : 'btn btn-outline-secondary'} type="button" style={{ pointerEvents: 'none' }}>{label ? label : <svg width="25px" height="25px" viewBox="0 0 1024 1024"><path d="M512 256l144.8 144.8-36.2 36.2-83-83v311.6h-51.2V354l-83 83-36.2-36.2L512 256zM307.2 716.8V768h409.6v-51.2H307.2z" fill="#000000" fillRule="evenodd" /></svg>} {required ? <><span className="text-danger">*</span></> : ''}</button></label>
259
+
260
+
261
+ <div className="input-group">
262
+ <input
263
+ ref={(node) => {
264
+ fileInputRef.current = node;
265
+ if (typeof ref === 'function') {
266
+ ref(node);
267
+ } else if (ref) {
268
+ ref.current = node;
269
+ }
270
+ }}
271
+ tabIndex={tabIndex || 0}
272
+ className={controlClassName || controlClassName === '' ? controlClassName : "form-control"}
273
+ id={idRes}
274
+ type="file"
275
+ // The onChange should trigger updates whenever
276
+ // the value changes?
277
+ // Try to select a file, then try selecting another one.
278
+ multiple={multiple || false}
279
+ name={name}
280
+ onKeyUp={handleFileInput}
281
+ onChange={handleChange}
282
+ disabled={disabled || null}
283
+ required={required || null}
284
+ style={{ display: 'none' }}
285
+ {...attributes}
286
+ />
287
+ {typeof defaultValue !== 'undefined' ? fileNames() : null}
288
+ {defaultValue}
289
+
290
+ </div>
291
+
292
+ <button ref={submitRef} className={submitClassName ? submitClassName + ` ${disabled ? 'disabled' : ''}` : 'btn btn-primary mt-2' + ` ${disabled ? 'disabled' : ''}`} type="button" onClick={handleSubmit}>{submitLabel ? submitLabel : null}</button>
293
+
294
+
295
+ </div>
296
+
297
+
298
+ </>
299
+ )
300
+ });
301
+
302
+ export default File;
@@ -0,0 +1,233 @@
1
+ import React, { useId, useState, useEffect, useRef, forwardRef, ChangeEvent, CompositionEvent } from 'react';
2
+
3
+ declare module 'react' {
4
+ interface ReactI18NextChildren<T> {
5
+ children?: any;
6
+ }
7
+ }
8
+
9
+ type InputProps = {
10
+ wrapperClassName?: string;
11
+ controlClassName?: string;
12
+ type?: string;
13
+ value?: string;
14
+ label?: React.ReactNode | string;
15
+ units?: string;
16
+ name?: string;
17
+ step?: any;
18
+ min?: any;
19
+ max?: any;
20
+ src?: any;
21
+ size?: any;
22
+ minLength?: any;
23
+ maxLength?: any;
24
+ alt?: any;
25
+ disabled?: any;
26
+ required?: any;
27
+ readOnly?: any;
28
+ placeholder?: string;
29
+ pattern?: any;
30
+ iconLeft?: React.ReactNode | string;
31
+ iconRight?: React.ReactNode | string;
32
+ /** -- */
33
+ id?: string;
34
+ style?: React.CSSProperties;
35
+ autoComplete?: string;
36
+ tabIndex?: number;
37
+ [key: `data-${string}`]: string | undefined;
38
+ onChangeCallback?: (e: any) => void;
39
+ onChange?: (e: any, param: any) => void;
40
+ onBlur?: (e: any, param: any) => void;
41
+ onFocus?: (e: any, param: any) => void;
42
+
43
+ };
44
+
45
+
46
+ const Input = forwardRef((props: InputProps, ref: any) => {
47
+ const {
48
+ wrapperClassName,
49
+ controlClassName,
50
+ type,
51
+ disabled,
52
+ required,
53
+ placeholder,
54
+ pattern,
55
+ readOnly,
56
+ value,
57
+ label,
58
+ units,
59
+ name,
60
+ step,
61
+ min,
62
+ max,
63
+ src,
64
+ size,
65
+ minLength,
66
+ maxLength,
67
+ alt,
68
+ id,
69
+ iconLeft,
70
+ iconRight,
71
+ autoComplete,
72
+ style,
73
+ tabIndex,
74
+ onChangeCallback,
75
+ onChange,
76
+ onBlur,
77
+ onFocus,
78
+ ...attributes
79
+ } = props;
80
+
81
+
82
+ const uniqueID = useId();
83
+ const idRes = id || uniqueID;
84
+ const rootRef = useRef<any>(null);
85
+ const valRef = useRef<any>(null);
86
+ const typeRes = typeof (type) === 'undefined' ? 'text' : type;
87
+ const [onComposition, setOnComposition] = useState(false);
88
+ const [changedVal, setChangedVal] = useState<string>(value || '');
89
+
90
+ function handleComposition(event: CompositionEvent<HTMLInputElement>) {
91
+ if (event.type === 'compositionstart') {
92
+ setOnComposition(true);
93
+ }
94
+ if (event.type === 'compositionend') {
95
+ setOnComposition(false);
96
+ }
97
+ }
98
+
99
+
100
+ function handleFocus(event: ChangeEvent<HTMLInputElement>) {
101
+ rootRef.current.classList.add('focus');
102
+
103
+ //
104
+ onFocus?.(event, onComposition);
105
+ }
106
+
107
+ function handleChange(event: ChangeEvent<HTMLInputElement>) {
108
+ const val = event.target.value;
109
+
110
+ setChangedVal(val);
111
+
112
+
113
+ //----
114
+ //remove focus style
115
+ if (val === '') {
116
+ rootRef.current.classList.remove('focus');
117
+ }
118
+
119
+ //
120
+ onChange?.(event, onComposition);
121
+ if (typeof (onChangeCallback) === 'function') {
122
+ const newData: any = onChangeCallback(event);
123
+ setChangedVal(newData);
124
+ }
125
+
126
+ }
127
+
128
+ function handleBlur(event: ChangeEvent<HTMLInputElement>) {
129
+ const el = event.target;
130
+ const val = event.target.value;
131
+
132
+
133
+ //----
134
+ //remove focus style
135
+ if (val === '') {
136
+ rootRef.current.classList.remove('focus');
137
+ }
138
+
139
+ //
140
+ onBlur?.(event, onComposition);
141
+ }
142
+
143
+
144
+ useEffect(() => {
145
+
146
+ // update default value
147
+ //--------------
148
+ setChangedVal(value || '');
149
+
150
+ // If you use the dynamic form assignment (such as document.getElementById(xxx).value),
151
+ // you need to judge the value of the input obtained by using the macrotask "setInterval()"
152
+ let timer: any = null;
153
+ let initTimes: number = 0;
154
+ let hasValue: boolean = false;
155
+ timer = setInterval( () => {
156
+ if ( initTimes > 5 || hasValue ) {
157
+ clearInterval(timer);
158
+ } else {
159
+ if ( valRef.current !== null && valRef.current.value !== '' && ( typeof value === 'undefined' || value === '' ) ) {
160
+ setChangedVal(valRef.current.value);
161
+ hasValue = true;
162
+ }
163
+ initTimes++;
164
+
165
+ }
166
+ }, 500);
167
+
168
+ return () => {
169
+ clearInterval(timer);
170
+ }
171
+
172
+ }, [value]);
173
+
174
+
175
+ return (
176
+ <>
177
+
178
+ <div className={wrapperClassName || wrapperClassName === '' ? wrapperClassName : "mb-3 position-relative"} ref={rootRef}>
179
+ {label ? <><label htmlFor={idRes} className="form-label">{label}</label></> : null}
180
+
181
+ <div className="input-group">
182
+ {iconLeft ? <><span className="input-group-text">{iconLeft}</span></>: null}
183
+ <input
184
+ ref={(node) => {
185
+ valRef.current = node;
186
+ if (typeof ref === 'function') {
187
+ ref(node);
188
+ } else if (ref) {
189
+ ref.current = node;
190
+ }
191
+ }}
192
+ tabIndex={tabIndex || 0}
193
+ type={typeRes}
194
+ className={controlClassName || controlClassName === '' ? controlClassName : "form-control"}
195
+ id={idRes}
196
+ name={name}
197
+ step={step || null}
198
+ min={min || null}
199
+ max={max || null}
200
+ src={src || null}
201
+ size={size || null}
202
+ alt={alt || null}
203
+ pattern={pattern || null}
204
+ placeholder={placeholder || ''}
205
+ value={changedVal}
206
+ minLength={minLength || null}
207
+ maxLength={maxLength || null}
208
+ autoComplete={autoComplete ? 'on' : 'off'}
209
+ onFocus={handleFocus}
210
+ onBlur={handleBlur}
211
+ onChange={handleChange}
212
+ onCompositionStart={handleComposition}
213
+ onCompositionUpdate={handleComposition}
214
+ onCompositionEnd={handleComposition}
215
+ disabled={disabled || null}
216
+ required={required || null}
217
+ readOnly={readOnly || null}
218
+ style={style}
219
+ {...attributes}
220
+ />
221
+ {units ? <><span className="input-group-text">{units}</span></>: null}
222
+ {iconRight ? <><span className="input-group-text">{iconRight}</span></>: null}
223
+ </div>
224
+ {required ? <><span className="position-absolute end-0 top-0 my-2 mx-2"><span className="text-danger">*</span></span></> : ''}
225
+
226
+ </div>
227
+
228
+
229
+ </>
230
+ )
231
+ });
232
+
233
+ export default Input;