funda-ui 4.7.625 → 4.7.711

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 (90) hide show
  1. package/CascadingSelect/index.js +2 -2
  2. package/CascadingSelectE2E/index.js +2 -2
  3. package/Chatbox/index.js +3 -17
  4. package/Checkbox/index.js +3 -3
  5. package/ColorPicker/index.js +3 -18
  6. package/Date/index.js +3 -18
  7. package/EventCalendarTimeline/index.d.ts +2 -2
  8. package/EventCalendarTimeline/index.js +24 -6
  9. package/File/index.d.ts +9 -0
  10. package/File/index.js +245 -93
  11. package/Input/index.js +3 -18
  12. package/LiveSearch/index.js +3 -18
  13. package/NativeSelect/index.js +3 -3
  14. package/NumberInput/index.js +3 -18
  15. package/Popover/index.css +198 -0
  16. package/Popover/index.d.ts +4 -0
  17. package/Popover/index.js +1808 -0
  18. package/README.md +1 -0
  19. package/Radio/index.js +3 -3
  20. package/RangeSlider/index.js +3 -18
  21. package/SearchBar/index.js +3 -18
  22. package/Select/index.js +3 -2
  23. package/Switch/index.js +3 -3
  24. package/TagInput/index.css +31 -31
  25. package/TagInput/index.js +12 -23
  26. package/Textarea/index.js +3 -17
  27. package/Utils/usePageVisibility.d.ts +5 -0
  28. package/Utils/usePageVisibility.js +166 -0
  29. package/Utils/useSSE.d.ts +50 -0
  30. package/Utils/useSSE.js +235 -0
  31. package/all.d.ts +1 -0
  32. package/all.js +1 -0
  33. package/lib/cjs/CascadingSelect/index.js +2 -2
  34. package/lib/cjs/CascadingSelectE2E/index.js +2 -2
  35. package/lib/cjs/Chatbox/index.js +3 -17
  36. package/lib/cjs/Checkbox/index.js +3 -3
  37. package/lib/cjs/ColorPicker/index.js +3 -18
  38. package/lib/cjs/Date/index.js +3 -18
  39. package/lib/cjs/EventCalendarTimeline/index.d.ts +2 -2
  40. package/lib/cjs/EventCalendarTimeline/index.js +24 -6
  41. package/lib/cjs/File/index.d.ts +9 -0
  42. package/lib/cjs/File/index.js +245 -93
  43. package/lib/cjs/Input/index.js +3 -18
  44. package/lib/cjs/LiveSearch/index.js +3 -18
  45. package/lib/cjs/NativeSelect/index.js +3 -3
  46. package/lib/cjs/NumberInput/index.js +3 -18
  47. package/lib/cjs/Popover/index.d.ts +4 -0
  48. package/lib/cjs/Popover/index.js +1808 -0
  49. package/lib/cjs/Radio/index.js +3 -3
  50. package/lib/cjs/RangeSlider/index.js +3 -18
  51. package/lib/cjs/SearchBar/index.js +3 -18
  52. package/lib/cjs/Select/index.js +3 -2
  53. package/lib/cjs/Switch/index.js +3 -3
  54. package/lib/cjs/TagInput/index.js +12 -23
  55. package/lib/cjs/Textarea/index.js +3 -17
  56. package/lib/cjs/Utils/usePageVisibility.d.ts +5 -0
  57. package/lib/cjs/Utils/usePageVisibility.js +166 -0
  58. package/lib/cjs/Utils/useSSE.d.ts +50 -0
  59. package/lib/cjs/Utils/useSSE.js +235 -0
  60. package/lib/cjs/index.d.ts +1 -0
  61. package/lib/cjs/index.js +1 -0
  62. package/lib/css/Popover/index.css +198 -0
  63. package/lib/css/TagInput/index.css +31 -31
  64. package/lib/esm/CascadingSelect/index.tsx +2 -2
  65. package/lib/esm/CascadingSelectE2E/index.tsx +2 -2
  66. package/lib/esm/Checkbox/index.tsx +3 -3
  67. package/lib/esm/ColorPicker/index.tsx +4 -15
  68. package/lib/esm/EventCalendarTimeline/index.tsx +30 -13
  69. package/lib/esm/File/index.tsx +148 -23
  70. package/lib/esm/Input/index.tsx +6 -17
  71. package/lib/esm/ModalDialog/index.tsx +0 -1
  72. package/lib/esm/NativeSelect/index.tsx +3 -3
  73. package/lib/esm/NumberInput/index.tsx +7 -15
  74. package/lib/esm/Popover/Popover.tsx +251 -0
  75. package/lib/esm/Popover/PopoverClose.tsx +51 -0
  76. package/lib/esm/Popover/PopoverContent.tsx +72 -0
  77. package/lib/esm/Popover/PopoverTrigger.tsx +62 -0
  78. package/lib/esm/Popover/index.scss +272 -0
  79. package/lib/esm/Popover/index.tsx +4 -0
  80. package/lib/esm/Radio/index.tsx +3 -3
  81. package/lib/esm/SearchBar/index.tsx +8 -12
  82. package/lib/esm/Select/index.tsx +2 -2
  83. package/lib/esm/Switch/index.tsx +3 -3
  84. package/lib/esm/TagInput/index.scss +24 -24
  85. package/lib/esm/TagInput/index.tsx +13 -20
  86. package/lib/esm/Textarea/index.tsx +6 -14
  87. package/lib/esm/Utils/hooks/usePageVisibility.tsx +84 -0
  88. package/lib/esm/Utils/hooks/useSSE.tsx +134 -0
  89. package/lib/esm/index.js +1 -0
  90. package/package.json +1 -1
@@ -14,7 +14,6 @@ import { clsWrite, combinedCls } from 'funda-utils/dist/cjs/cls';
14
14
  import getOs from 'funda-utils//dist/cjs/os';
15
15
 
16
16
 
17
-
18
17
  export interface EventsValueConfig {
19
18
  id: string | number;
20
19
  date: string,
@@ -71,7 +70,7 @@ export type EventCalendarTimelineProps = {
71
70
  cellAddBtnLabel?: string | React.ReactNode;
72
71
  forwardAndBackFillDisabled?: boolean;
73
72
  draggable?: boolean;
74
- showWeek?: boolean;
73
+ headerShowWeek?: boolean;
75
74
  autoScroll?: boolean;
76
75
  onChangeDate?: (e: any, currentData: any) => void;
77
76
  onChangeMonth?: (currentData: any) => void;
@@ -115,7 +114,7 @@ export type EventCalendarTimelineProps = {
115
114
 
116
115
  // table
117
116
  tableListSectionTitle?: string | React.ReactNode;
118
- tableCellMinWidth?: number;
117
+ tableCellMinWidth?: number | ((mode: 'week' | 'month') => number);
119
118
 
120
119
  // tooltip
121
120
  tableTooltipDirection?: string;
@@ -161,7 +160,7 @@ const EventCalendarTimeline = (props: EventCalendarTimelineProps) => {
161
160
  cellAddBtnLabel,
162
161
  forwardAndBackFillDisabled,
163
162
  draggable,
164
- showWeek,
163
+ headerShowWeek,
165
164
  autoScroll,
166
165
  onChangeDate,
167
166
  onChangeMonth,
@@ -272,9 +271,8 @@ const EventCalendarTimeline = (props: EventCalendarTimelineProps) => {
272
271
 
273
272
  // table grid
274
273
  const AUTO_SCROLL = autoScroll || false;
275
- const SHOW_WEEK = showWeek || false;
274
+ const HEADER_SHOW_WEEK = headerShowWeek || false;
276
275
  const BODY_DRAG = draggable || false;
277
- const CELL_MIN_W = typeof tableCellMinWidth === 'undefined' ? (SHOW_WEEK ? 100 : 50) : tableCellMinWidth;
278
276
  const tableGridRef = useRef<any>(null);
279
277
  const tableGridHeaderRef = useRef<any>(null);
280
278
  const scrollHeaderRef = useRef(null);
@@ -301,6 +299,16 @@ const EventCalendarTimeline = (props: EventCalendarTimelineProps) => {
301
299
  // appearance mode
302
300
  const [appearanceMode, setAppearanceMode] = useState<string>(appearance);
303
301
 
302
+ // Calculate CELL_MIN_W based on appearanceMode and tableCellMinWidth
303
+ const CELL_MIN_W = useMemo(() => {
304
+ if (typeof tableCellMinWidth === 'undefined') {
305
+ return (headerShowWeek || false) ? 100 : 50;
306
+ }
307
+ if (typeof tableCellMinWidth === 'function') {
308
+ return tableCellMinWidth(appearanceMode as 'week' | 'month');
309
+ }
310
+ return tableCellMinWidth;
311
+ }, [tableCellMinWidth, appearanceMode, headerShowWeek]);
304
312
 
305
313
  const findMondayAndTruncate = (dates: string[]) => {
306
314
  const _res = dates.map((s: string) => new Date(s));
@@ -1246,7 +1254,7 @@ const EventCalendarTimeline = (props: EventCalendarTimelineProps) => {
1246
1254
 
1247
1255
  // week day
1248
1256
  const weekDay = item.week[i];
1249
- const _weekDayStr = SHOW_WEEK ? <span dangerouslySetInnerHTML={{
1257
+ const _weekDayStr = HEADER_SHOW_WEEK ? <span dangerouslySetInnerHTML={{
1250
1258
  __html: item.weekDisplay[i]
1251
1259
  }} /> : null;
1252
1260
 
@@ -1346,7 +1354,7 @@ const EventCalendarTimeline = (props: EventCalendarTimelineProps) => {
1346
1354
  'disabled': !isInteractive
1347
1355
  }
1348
1356
  )}
1349
- style={{ width: (CELL_MIN_W - 1) + 'px' }}
1357
+ style={{ width: (CELL_MIN_W as number - 1) + 'px' }}
1350
1358
  >
1351
1359
 
1352
1360
  {d}
@@ -1624,7 +1632,7 @@ const EventCalendarTimeline = (props: EventCalendarTimelineProps) => {
1624
1632
  'disabled': !isInteractive
1625
1633
  }
1626
1634
  )}
1627
- style={{ width: (CELL_MIN_W - 1) + 'px' }}
1635
+ style={{ width: (CELL_MIN_W as number - 1) + 'px' }}
1628
1636
  >
1629
1637
 
1630
1638
  {/*++++++++++++++++ EVENT ++++++++++++++++*/}
@@ -1856,18 +1864,26 @@ const EventCalendarTimeline = (props: EventCalendarTimelineProps) => {
1856
1864
  const tableGridEl: any = tableGridRef.current;
1857
1865
 
1858
1866
  // initialize cell height
1859
- const headerTitleTrElements = tableGridEl.querySelector('.custom-event-tl-table__datagrid-body__title tbody').getElementsByTagName('tr');
1860
- const trElements = tableGridEl.querySelector('.custom-event-tl-table__datagrid-body__content tbody').getElementsByTagName('tr');
1867
+ const headerTitleTbody = tableGridEl.querySelector('.custom-event-tl-table__datagrid-body__title tbody');
1868
+ const contentTbody = tableGridEl.querySelector('.custom-event-tl-table__datagrid-body__content tbody');
1869
+ if (!headerTitleTbody || !contentTbody) return;
1861
1870
 
1871
+ const headerTitleTrElements = headerTitleTbody.getElementsByTagName('tr');
1872
+ const trElements = contentTbody.getElementsByTagName('tr');
1873
+
1874
+ // Reset any previously set inline heights so we measure natural heights.
1862
1875
  for (let i = 0; i < headerTitleTrElements.length; i++) {
1876
+ // set to 'auto' (or remove inline style) to allow shrink
1877
+ headerTitleTrElements[i].style.height = 'auto';
1878
+ if (trElements[i]) trElements[i].style.height = 'auto';
1863
1879
 
1864
1880
  const targetElement = headerTitleTrElements[i].offsetHeight > trElements[i].offsetHeight ? headerTitleTrElements[i] : trElements[i];
1865
1881
  const tdOHeight = window.getComputedStyle(targetElement).height;
1866
1882
  headerTitleTrElements[i].style.height = tdOHeight;
1867
1883
  trElements[i].style.height = tdOHeight;
1868
-
1869
1884
  }
1870
1885
 
1886
+
1871
1887
  }
1872
1888
 
1873
1889
  function tableGridInit() {
@@ -1877,7 +1893,7 @@ const EventCalendarTimeline = (props: EventCalendarTimelineProps) => {
1877
1893
 
1878
1894
  const { forwardFillTotal, list: cellsList } = getCells();
1879
1895
  const tableGridEl: any = tableGridRef.current;
1880
- let _curCellMinWidth: number = CELL_MIN_W;
1896
+ let _curCellMinWidth: number = CELL_MIN_W as number;
1881
1897
  let _curColCount: number = FILL_BLANK_DATE_DISABLD ? days[month] : 7 * cellsList.length;
1882
1898
 
1883
1899
 
@@ -2194,6 +2210,7 @@ const EventCalendarTimeline = (props: EventCalendarTimelineProps) => {
2194
2210
  // Call a function when the list has been rendered completely
2195
2211
  onListRenderComplete?.();
2196
2212
 
2213
+
2197
2214
  }, [eventsValue, customTodayDate, appearanceMode]);
2198
2215
 
2199
2216
 
@@ -8,6 +8,8 @@ import {
8
8
  } from 'funda-utils/dist/cjs/buffer';
9
9
  import { clsWrite, combinedCls } from 'funda-utils/dist/cjs/cls';
10
10
 
11
+
12
+
11
13
  export type FileProps = {
12
14
  contentRef?: React.ForwardedRef<any>;
13
15
  wrapperClassName?: string;
@@ -41,6 +43,15 @@ export type FileProps = {
41
43
  fetchFuncAsync?: any;
42
44
  fetchFuncMethod?: string;
43
45
  fetchFuncMethodParams?: any[];
46
+ formDataAppend?: (formData: FormData, files: FileList) => void;
47
+ /** Enable chunked upload for large files */
48
+ enableChunkedUpload?: boolean;
49
+ /** Chunk size in bytes (default: 2MB) */
50
+ chunkSize?: number;
51
+ /** Custom function to append chunk data to FormData. Receives (formData: FormData, chunk: Blob, chunkIndex: number, totalChunks: number, file: File) */
52
+ chunkDataAppend?: (formData: FormData, chunk: Blob, chunkIndex: number, totalChunks: number, file: File) => void;
53
+ /** Callback for chunk upload progress. Receives (uploadedBytes: number, totalBytes: number, file: File, chunkIndex: number, totalChunks: number) */
54
+ onChunkProgress?: (uploadedBytes: number, totalBytes: number, file: File, chunkIndex: number, totalChunks: number) => void;
44
55
  onChange?: (e: any, e2: any, value: any) => void;
45
56
  onComplete?: (e: any, e2: any, callback: any, incomingData: string | null | undefined) => void;
46
57
  onProgress?: (files: any, e: any, e2: any) => void;
@@ -79,9 +90,17 @@ const File = forwardRef((props: FileProps, externalRef: any) => {
79
90
  fetchFuncAsync,
80
91
  fetchFuncMethod,
81
92
  fetchFuncMethodParams,
93
+ formDataAppend,
82
94
  onChange,
83
95
  onComplete,
84
96
  onProgress,
97
+
98
+ // Upload file in chunks
99
+ enableChunkedUpload,
100
+ chunkSize = 2 * 1024 * 1024, // Default 2MB
101
+ chunkDataAppend,
102
+ onChunkProgress,
103
+
85
104
  ...attributes
86
105
  } = props;
87
106
 
@@ -144,10 +163,9 @@ const File = forwardRef((props: FileProps, externalRef: any) => {
144
163
 
145
164
  let res = {};
146
165
  if (typeof window === 'undefined') return res;
147
-
148
-
166
+
149
167
  try {
150
- const response = await fetch(url + '?' + new URLSearchParams(fetchParams as any), {
168
+ const response = await fetch(typeof fetchParams !== 'undefined' ? url + '?' + new URLSearchParams(fetchParams as any) : url, {
151
169
  method: methord,
152
170
  body: data,
153
171
  ...rest
@@ -165,6 +183,75 @@ const File = forwardRef((props: FileProps, externalRef: any) => {
165
183
 
166
184
  }
167
185
 
186
+ /**
187
+ * Upload file in chunks
188
+ */
189
+ async function uploadFileInChunks(file: File, url: string, method: string = 'POST'): Promise<any> {
190
+ const totalChunks = Math.ceil(file.size / chunkSize);
191
+ const uploadId = `${Date.now()}-${Math.random().toString(36).substring(2, 11)}`;
192
+ let uploadedBytes = 0;
193
+
194
+ // Upload each chunk sequentially
195
+ for (let chunkIndex = 0; chunkIndex < totalChunks; chunkIndex++) {
196
+ const start = chunkIndex * chunkSize;
197
+ const end = Math.min(start + chunkSize, file.size);
198
+ const chunk = file.slice(start, end);
199
+
200
+ const formData = new FormData();
201
+
202
+ if (chunkDataAppend) {
203
+ // Use custom chunk data append function
204
+ chunkDataAppend(formData, chunk, chunkIndex, totalChunks, file);
205
+ } else {
206
+ // Default chunk upload format
207
+ formData.append('chunk', chunk);
208
+ formData.append('chunkIndex', chunkIndex.toString());
209
+ formData.append('totalChunks', totalChunks.toString());
210
+ formData.append('uploadId', uploadId);
211
+ formData.append('fileName', file.name);
212
+ formData.append('fileSize', file.size.toString());
213
+ formData.append('fileType', file.type);
214
+ }
215
+
216
+ // Update progress
217
+ uploadedBytes += (end - start);
218
+ onChunkProgress?.(uploadedBytes, file.size, file, chunkIndex, totalChunks);
219
+
220
+ // Upload chunk
221
+ const response: any = await fetchDataDefault(
222
+ url,
223
+ formData,
224
+ method,
225
+ {
226
+ headers: { 'Content-Type': 'multipart/form-data' }
227
+ }
228
+ );
229
+
230
+ // Check if chunk upload failed
231
+ if (response.error) {
232
+ throw new Error(`Chunk ${chunkIndex + 1}/${totalChunks} upload failed: ${response.error}`);
233
+ }
234
+
235
+ // If server returns a specific response indicating chunk upload success/failure, handle it
236
+ if (response.code !== undefined && response.code !== 0 && response.code !== 200) {
237
+ throw new Error(`Chunk ${chunkIndex + 1}/${totalChunks} upload failed: ${response.message || 'Unknown error'}`);
238
+ }
239
+ }
240
+
241
+ // After all chunks are uploaded, return the final response
242
+ // The server should merge chunks and return the final result
243
+ return {
244
+ code: 0,
245
+ message: 'Upload completed',
246
+ data: {
247
+ uploadId,
248
+ fileName: file.name,
249
+ fileSize: file.size,
250
+ totalChunks
251
+ }
252
+ };
253
+ }
254
+
168
255
 
169
256
  function handleLabelEnter(event: any) {
170
257
  event.currentTarget.getElementsByTagName('button')[0].className = labelHoverClassName ? labelHoverClassName : 'btn btn-primary';
@@ -192,26 +279,70 @@ const File = forwardRef((props: FileProps, externalRef: any) => {
192
279
  setProgressing(true);
193
280
 
194
281
 
282
+ // Use the default "fetch()" method to handle file references
195
283
  if (fetchUrl) {
196
284
 
197
- const formData = new FormData();
198
- formData.append('action', 'upload_plug_action');
285
+ // Check if chunked upload is enabled
286
+ if (enableChunkedUpload) {
287
+ // Upload files in chunks
288
+ (async () => {
289
+ try {
290
+ const uploadPromises: Promise<any>[] = [];
291
+
292
+ for (let i = 0; i < curFiles.length; i++) {
293
+ const file = curFiles[i];
294
+ uploadPromises.push(uploadFileInChunks(file, fetchUrl, fetchMethod ? fetchMethod : 'POST'));
295
+ }
199
296
 
200
- for (let i = 0; i < curFiles.length; i++) {
201
- formData.append("clientFiles", curFiles[i]);
202
- }
297
+ const results = await Promise.all(uploadPromises);
298
+
299
+ // Combine results from all files
300
+ const jsonData = {
301
+ code: 0,
302
+ message: 'All files uploaded successfully',
303
+ data: results
304
+ };
305
+
306
+ onComplete?.(fileInputRef.current, submitRef.current, jsonData, incomingData);
307
+ setProgressing(false);
308
+ resetDefaultVal();
309
+ } catch (error: any) {
310
+ const errorResponse = {
311
+ code: -1,
312
+ message: error.message || 'Upload failed',
313
+ error: error
314
+ };
315
+ onComplete?.(fileInputRef.current, submitRef.current, errorResponse, incomingData);
316
+ setProgressing(false);
317
+ }
318
+ })();
319
+ } else {
320
+ // Original non-chunked upload
321
+ const formData = new FormData();
322
+
323
+ if (formDataAppend) {
324
+ // Use custom formData.append function
325
+ formDataAppend(formData, curFiles);
326
+ } else {
327
+ // Default behavior
328
+ formData.append('action', 'upload_plug_action');
329
+ for (let i = 0; i < curFiles.length; i++) {
330
+ formData.append("clientFiles", curFiles[i]);
331
+ }
332
+ }
203
333
 
204
- fetchDataDefault(fetchUrl, formData, fetchMethod ? fetchMethod : 'POST', {
205
- headers: { 'Content-Type': 'multipart/form-data' }
206
- }).then(function (response: any) {
207
- const jsonData = response.data;
208
- onComplete?.(fileInputRef.current, submitRef.current, jsonData, incomingData);
209
- setProgressing(false);
334
+ fetchDataDefault(fetchUrl, formData, fetchMethod ? fetchMethod : 'POST', {
335
+ headers: { 'Content-Type': 'multipart/form-data' }
336
+ }).then(function (response: any) {
337
+ const jsonData = response;
338
+ onComplete?.(fileInputRef.current, submitRef.current, jsonData, incomingData);
339
+ setProgressing(false);
210
340
 
211
- // update default value
212
- resetDefaultVal();
341
+ // update default value
342
+ resetDefaultVal();
213
343
 
214
- });
344
+ });
345
+ }
215
346
  } else {
216
347
 
217
348
 
@@ -322,12 +453,6 @@ const File = forwardRef((props: FileProps, externalRef: any) => {
322
453
  setDefaultValue(null);
323
454
 
324
455
 
325
- //----
326
- //remove focus style
327
- if (val === '') {
328
- rootRef.current?.classList.remove('focus');
329
- }
330
-
331
456
  //
332
457
  onChange?.(fileInputRef.current, submitRef.current, fileInputRef.current.files);
333
458
 
@@ -354,8 +354,6 @@ const Input = forwardRef((props: InputProps, externalRef: any) => {
354
354
 
355
355
 
356
356
  function handleFocus(event: FocusEvent<HTMLInputElement>) {
357
- rootRef.current?.classList.add('focus');
358
-
359
357
  //
360
358
  if (valRef.current) {
361
359
  onFocus?.(event, onComposition, valRef.current);
@@ -365,13 +363,6 @@ const Input = forwardRef((props: InputProps, externalRef: any) => {
365
363
  function handleChange(event: ChangeEvent<HTMLInputElement> | KeyboardEvent<HTMLInputElement> | null, curVal: string) {
366
364
  setChangedVal(curVal);
367
365
 
368
-
369
- //----
370
- //remove focus style
371
- if (curVal === '') {
372
- rootRef.current?.classList.remove('focus');
373
- }
374
-
375
366
  //
376
367
  if (valRef.current) {
377
368
  onChange?.(event, onComposition, valRef.current, curVal);
@@ -390,13 +381,6 @@ const Input = forwardRef((props: InputProps, externalRef: any) => {
390
381
  const el = event.target;
391
382
  const val = event.target.value;
392
383
 
393
-
394
- //----
395
- //remove focus style
396
- if (val === '') {
397
- rootRef.current?.classList.remove('focus');
398
- }
399
-
400
384
  //
401
385
  if (valRef.current) {
402
386
  onBlur?.(event, onComposition, valRef.current);
@@ -520,7 +504,12 @@ const Input = forwardRef((props: InputProps, externalRef: any) => {
520
504
  return (
521
505
  <>
522
506
 
523
- <div className={clsWrite(wrapperClassName, 'mb-3 position-relative')} ref={rootRef}>
507
+ <div className={combinedCls(
508
+ clsWrite(wrapperClassName, 'mb-3 position-relative'),
509
+ {
510
+ 'focus-floating': changedVal !== ''
511
+ }
512
+ )} ref={rootRef}>
524
513
  {label ? <>{typeof label === 'string' ? <label htmlFor={idRes} className="form-label" dangerouslySetInnerHTML={{ __html: `${label}` }}></label> : <label htmlFor={idRes} className="form-label">{label}</label>}</> : null}
525
514
 
526
515
  <div className={combinedCls(
@@ -14,7 +14,6 @@ import {
14
14
 
15
15
 
16
16
 
17
-
18
17
  declare global {
19
18
  interface Window {
20
19
  curVideo?: any;
@@ -260,7 +260,7 @@ const NativeSelect = forwardRef((props: NativeSelectProps, externalRef: any) =>
260
260
 
261
261
  //
262
262
  function handleFocus(event: any) {
263
- rootRef.current?.classList.add('focus');
263
+ rootRef.current?.classList.add('focus-floating');
264
264
 
265
265
  //
266
266
  onFocus?.(event);
@@ -283,7 +283,7 @@ const NativeSelect = forwardRef((props: NativeSelectProps, externalRef: any) =>
283
283
 
284
284
  //----
285
285
  //remove focus style
286
- rootRef.current?.classList.remove('focus');
286
+ rootRef.current?.classList.remove('focus-floating');
287
287
 
288
288
  //
289
289
  if ( typeof(onChange) === 'function' ) {
@@ -298,7 +298,7 @@ const NativeSelect = forwardRef((props: NativeSelectProps, externalRef: any) =>
298
298
 
299
299
  //----
300
300
  //remove focus style
301
- rootRef.current?.classList.remove('focus');
301
+ rootRef.current?.classList.remove('focus-floating');
302
302
 
303
303
  //
304
304
  onBlur?.(event);
@@ -183,7 +183,6 @@ const NumberInput = forwardRef((props: NumberInputProps, externalRef: any) => {
183
183
 
184
184
 
185
185
  function handleFocus(event: FocusEvent<HTMLInputElement>) {
186
- rootRef.current?.classList.add('focus');
187
186
 
188
187
  //
189
188
  onFocus?.(event, valRef.current);
@@ -220,12 +219,7 @@ const NumberInput = forwardRef((props: NumberInputProps, externalRef: any) => {
220
219
  setChangedVal(resToInput);
221
220
 
222
221
 
223
- //----
224
- //remove focus style
225
- if (val === '') {
226
- rootRef.current?.classList.remove('focus');
227
- }
228
-
222
+
229
223
  //
230
224
  onChange?.(event, valRef.current, Number(!isNumeric(newVal) ? '0' : resToInput));
231
225
 
@@ -247,13 +241,6 @@ const NumberInput = forwardRef((props: NumberInputProps, externalRef: any) => {
247
241
  setChangedVal('0');
248
242
  }
249
243
 
250
-
251
- //----
252
- //remove focus style
253
- if (val === '') {
254
- rootRef.current?.classList.remove('focus');
255
- }
256
-
257
244
  //
258
245
  onBlur?.(event, valRef.current);
259
246
 
@@ -286,7 +273,12 @@ const NumberInput = forwardRef((props: NumberInputProps, externalRef: any) => {
286
273
  return (
287
274
  <>
288
275
 
289
- <div className={clsWrite(wrapperClassName, 'mb-3 position-relative')} ref={rootRef}>
276
+ <div className={combinedCls(
277
+ clsWrite(wrapperClassName, 'mb-3 position-relative'),
278
+ {
279
+ 'focus-floating': changedVal !== ''
280
+ }
281
+ )} ref={rootRef}>
290
282
  {label ? <>{typeof label === 'string' ? <label htmlFor={idRes} className="form-label" dangerouslySetInnerHTML={{__html: `${label}`}}></label> : <label htmlFor={idRes} className="form-label">{label}</label>}</> : null}
291
283
 
292
284
  <div className="position-relative">