funda-ui 4.4.35 → 4.5.12

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 (40) hide show
  1. package/Date/index.js +1078 -77
  2. package/EventCalendar/index.js +8 -2
  3. package/EventCalendarTimeline/index.js +32 -1
  4. package/Input/index.d.ts +7 -0
  5. package/Input/index.js +699 -57
  6. package/MasonryLayout/index.js +11 -1
  7. package/MultipleSelect/index.d.ts +1 -0
  8. package/MultipleSelect/index.js +7 -5
  9. package/RangeSlider/index.js +1078 -77
  10. package/Select/index.js +34 -2
  11. package/Textarea/index.d.ts +7 -0
  12. package/Textarea/index.js +707 -10
  13. package/Tree/index.js +2 -0
  14. package/Utils/inputsCalculation.d.ts +18 -1
  15. package/Utils/inputsCalculation.js +26 -0
  16. package/lib/cjs/Date/index.js +1078 -77
  17. package/lib/cjs/EventCalendar/index.js +8 -2
  18. package/lib/cjs/EventCalendarTimeline/index.js +32 -1
  19. package/lib/cjs/Input/index.d.ts +7 -0
  20. package/lib/cjs/Input/index.js +699 -57
  21. package/lib/cjs/MasonryLayout/index.js +11 -1
  22. package/lib/cjs/MultipleSelect/index.d.ts +1 -0
  23. package/lib/cjs/MultipleSelect/index.js +7 -5
  24. package/lib/cjs/RangeSlider/index.js +1078 -77
  25. package/lib/cjs/Select/index.js +34 -2
  26. package/lib/cjs/Textarea/index.d.ts +7 -0
  27. package/lib/cjs/Textarea/index.js +707 -10
  28. package/lib/cjs/Tree/index.js +2 -0
  29. package/lib/cjs/Utils/inputsCalculation.d.ts +18 -1
  30. package/lib/cjs/Utils/inputsCalculation.js +26 -0
  31. package/lib/esm/EventCalendar/index.tsx +8 -6
  32. package/lib/esm/EventCalendarTimeline/index.tsx +439 -403
  33. package/lib/esm/Input/index.tsx +299 -77
  34. package/lib/esm/MasonryLayout/index.tsx +9 -2
  35. package/lib/esm/MultipleSelect/index.tsx +6 -4
  36. package/lib/esm/Textarea/index.tsx +332 -39
  37. package/lib/esm/Tree/TreeList.tsx +4 -1
  38. package/lib/esm/Tree/index.tsx +1 -0
  39. package/lib/esm/Utils/libs/inputsCalculation.ts +60 -31
  40. package/package.json +1 -1
@@ -1,11 +1,11 @@
1
1
  import React, { useState, useEffect, useRef, forwardRef, KeyboardEvent, useImperativeHandle } from 'react';
2
2
 
3
3
 
4
-
5
4
  import useComId from 'funda-utils/dist/cjs/useComId';
6
5
  import useAutosizeTextArea from 'funda-utils/dist/cjs/useAutosizeTextArea';
7
6
  import { clsWrite, combinedCls } from 'funda-utils/dist/cjs/cls';
8
-
7
+ import { actualPropertyValue, getTextTop } from 'funda-utils/dist/cjs/inputsCalculation';
8
+ import useDebounce from 'funda-utils/dist/cjs/useDebounce';
9
9
 
10
10
 
11
11
  export type TextareaProps = {
@@ -31,6 +31,13 @@ export type TextareaProps = {
31
31
  autoSize?: boolean;
32
32
  iconLeft?: React.ReactNode | string;
33
33
  iconRight?: React.ReactNode | string;
34
+ aiPredict?: boolean;
35
+ aiPredictRemainingTextRGB?: number[];
36
+ aiPredictConfirmKey?: Array<string[]>;
37
+ aiPredictFetchFuncAsync?: any;
38
+ aiPredictFetchFuncMethod?: string;
39
+ aiPredictFetchFuncMethodParams?: any[];
40
+ aiPredictFetchCallback?: (data: any) => void;
34
41
  /** -- */
35
42
  id?: string;
36
43
  style?: React.CSSProperties;
@@ -64,6 +71,13 @@ const Textarea = forwardRef((props: TextareaProps, externalRef: any) => {
64
71
  autoSize,
65
72
  iconLeft,
66
73
  iconRight,
74
+ aiPredict = false,
75
+ aiPredictRemainingTextRGB = [153, 153, 153],
76
+ aiPredictConfirmKey = [['Enter'],['Tab'],['Shift', ' ']],
77
+ aiPredictFetchFuncAsync,
78
+ aiPredictFetchFuncMethod,
79
+ aiPredictFetchFuncMethodParams,
80
+ aiPredictFetchCallback,
67
81
  readOnly,
68
82
  defaultValue,
69
83
  value,
@@ -93,6 +107,173 @@ const Textarea = forwardRef((props: TextareaProps, externalRef: any) => {
93
107
  const valRef = useRef<any>(null);
94
108
  const [changedVal, setChangedVal] = useState<string>(value || '');
95
109
 
110
+
111
+ //================================================================
112
+ // AI Predict
113
+ //================================================================
114
+ const [currentSuggestion, setCurrentSuggestion] = useState<string>('');
115
+ const [tempMatchedSuggestion, setTempMatchedSuggestion] = useState<string[]>([]);
116
+ const [textWidth, setTextWidth] = useState<number>(0);
117
+ const aiInputRef = useRef<any>(null);
118
+ const originInputComputedStyle = useRef<Record<string, any>>({
119
+ fontSize: 16,
120
+ fontFamily: 'inherit',
121
+ letterSpacing: 'normal',
122
+ textTop: 10
123
+ });
124
+ const [hasErr, setHasErr] = useState<boolean>(false);
125
+ const currentSuggestionIndex = useRef<number>(0);
126
+
127
+
128
+
129
+ // A list of suggestions
130
+ //----------------
131
+ const [suggestions, setSuggestions] = useState<string[]>([]);
132
+
133
+ //performance
134
+ const handleChangeSuggestionsFetchSafe = useDebounce((e: any, curVal: string) => {
135
+ const _oparams: any[] = aiPredictFetchFuncMethodParams || [];
136
+ const _params: any[] = _oparams.map((item: any) => item !== '$QUERY_STRING' ? item : curVal);
137
+ fetchSuggestionsData((_params).join(',')).then((resSuggestions: string[]) => {
138
+ handleInputAiPredictChange(curVal, resSuggestions);
139
+ });
140
+ }, 350, []);
141
+
142
+ async function fetchSuggestionsData(params: any) {
143
+
144
+ if (typeof aiPredictFetchFuncAsync === 'object') {
145
+
146
+ const response: any = await aiPredictFetchFuncAsync[`${aiPredictFetchFuncMethod}`](...params.split(','));
147
+ let _ORGIN_DATA = response.data;
148
+
149
+ // reset data structure
150
+ if (typeof (aiPredictFetchCallback) === 'function') {
151
+ _ORGIN_DATA = aiPredictFetchCallback(_ORGIN_DATA);
152
+ }
153
+
154
+ // Determine whether the data structure matches
155
+ if (!Array.isArray(_ORGIN_DATA)) {
156
+ console.warn('The data structure does not match, please refer to the example in the component documentation.');
157
+ setHasErr(true);
158
+ _ORGIN_DATA = [];
159
+ }
160
+
161
+ //
162
+ setSuggestions(_ORGIN_DATA);
163
+
164
+ return _ORGIN_DATA;
165
+ } else {
166
+ return [];
167
+ }
168
+
169
+
170
+ }
171
+
172
+
173
+
174
+ // Calculates the width of the input text
175
+ //----------------
176
+ const calculateTextWidth = (text: string) => {
177
+ if (valRef.current) {
178
+ const canvas = document.createElement('canvas');
179
+ const context: any = canvas.getContext('2d');
180
+ context.font = `${originInputComputedStyle.current.fontSize}px ${originInputComputedStyle.current.fontFamily}`;
181
+ return context.measureText(text).width;
182
+ }
183
+ return 0;
184
+ };
185
+
186
+
187
+
188
+ // Get the rest of the suggested text
189
+ //----------------
190
+ const getRemainingText = (fullSuggestion: string) => {
191
+ if (!changedVal || !fullSuggestion) return '';
192
+
193
+
194
+ // Only the parts of the suggested text that were not entered are returned
195
+ const lastInputChar = changedVal[changedVal.length - 1];
196
+ const lastCharIndex = fullSuggestion.toLowerCase().lastIndexOf(lastInputChar.toLowerCase());
197
+ return fullSuggestion.slice(lastCharIndex + 1);
198
+
199
+ };
200
+
201
+ // Match exactly from the start
202
+ //----------------
203
+ const preciseMatch = (input: any, suggestions: string[]) => {
204
+ if (!input) return '';
205
+
206
+ const filtered = suggestions.filter(s =>
207
+ s.toLowerCase().startsWith(input.toLowerCase())
208
+ );
209
+
210
+ setTempMatchedSuggestion(filtered);
211
+ return filtered;
212
+ };
213
+
214
+
215
+ // Fuzzy matching
216
+ //----------------
217
+ const fuzzyMatch = (input: any, suggestions: string[]) => {
218
+ if (!input) return '';
219
+
220
+ // Convert input to a regular expression pattern with support for arbitrary position matching
221
+ const pattern = input.split('').map((char: string) =>
222
+ char.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
223
+ ).join('.*');
224
+ const regex = new RegExp(pattern, 'i');
225
+
226
+ // Find the first matching suggestion (multiple matches)
227
+ const filtered = suggestions.filter((suggestion: string) => regex.test(suggestion));
228
+ setTempMatchedSuggestion(filtered);
229
+ return filtered;
230
+ };
231
+
232
+ // Handle input variations
233
+ //----------------
234
+ const handleInputAiPredictChange = (newValue: string, curSuggestions: string[]) => {
235
+ setTextWidth(calculateTextWidth(newValue));
236
+
237
+ // Match results
238
+ const matchedSuggestion = fuzzyMatch(newValue, curSuggestions);
239
+ setCurrentSuggestion(matchedSuggestion[0] || '');
240
+
241
+ };
242
+
243
+
244
+
245
+
246
+ // Calculate the color shade of the prompt text
247
+ //----------------
248
+ const calculateOpacity = () => {
249
+ // Transparency is calculated based on the input length
250
+ const baseOpacity = 0.5;
251
+ const inputLength = changedVal.length;
252
+ return Math.max(0.2, baseOpacity - (inputLength * 0.05));
253
+ };
254
+
255
+
256
+ // Confirm
257
+ //----------------
258
+ const handleAiPredictKeyDown = (e: KeyboardEvent<HTMLTextAreaElement>) => {
259
+ // Prevents the default behavior of the enter key
260
+ e.preventDefault();
261
+
262
+ const remainingText = getRemainingText(currentSuggestion);
263
+ if (remainingText) {
264
+ // Only the second half of the text is added
265
+ setChangedVal(changedVal + remainingText);
266
+ setCurrentSuggestion('');
267
+ }
268
+ };
269
+
270
+ //
271
+ const remainingText = getRemainingText(currentSuggestion);
272
+
273
+
274
+ //================================================================
275
+ // General
276
+ //================================================================
96
277
  // exposes the following methods
97
278
  useImperativeHandle(
98
279
  contentRef,
@@ -121,6 +302,12 @@ const Textarea = forwardRef((props: TextareaProps, externalRef: any) => {
121
302
  onResize?.(valRef.current, res);
122
303
  }
123
304
  });
305
+
306
+
307
+ const propExist = (p: any) => {
308
+ return typeof p !== 'undefined' && p !== null && p !== '';
309
+ };
310
+
124
311
 
125
312
  function handleFocus(event: any) {
126
313
  const el = event.target;
@@ -130,6 +317,7 @@ const Textarea = forwardRef((props: TextareaProps, externalRef: any) => {
130
317
  onFocus?.(event, valRef.current);
131
318
  }
132
319
 
320
+
133
321
  function handleChange(event: any) {
134
322
  const val = event.target.value;
135
323
 
@@ -186,6 +374,49 @@ const Textarea = forwardRef((props: TextareaProps, externalRef: any) => {
186
374
  onPressEnter?.(event, valRef.current);
187
375
  }
188
376
 
377
+ // AI Predict
378
+ //----
379
+ if (aiPredict && currentSuggestion !== '') {
380
+ const keyBindings: Array<string[]> = aiPredictConfirmKey;
381
+ // The parameter 'registerKeyEvents' is an array, and each element is an object
382
+ // eg. { keys: ["Control", "S"], action: () => { console.log("Ctrl+S"); } }
383
+ const registerKeyEvents: Record<string, any>[] = keyBindings.map((s: string[]) => {
384
+ return {
385
+ keys: s,
386
+ action: () => {
387
+ handleAiPredictKeyDown(event);
388
+ },
389
+ };
390
+ });
391
+
392
+ registerKeyEvents.forEach((binding: Record<string, any>) => {
393
+ const keysPressed = binding.keys.every((key: string) =>
394
+ key === "Shift" ? event.shiftKey :
395
+ key === "Control" ? event.ctrlKey :
396
+ key === "Alt" ? event.altKey :
397
+ key === "Meta" ? event.metaKey :
398
+ event.key === key
399
+ );
400
+
401
+ if (keysPressed) {
402
+ binding.action();
403
+ }
404
+ });
405
+
406
+
407
+ // switch result of suggestions
408
+ if (event.code === 'ArrowUp') {
409
+ currentSuggestionIndex.current = (currentSuggestionIndex.current - 1 + tempMatchedSuggestion.length) % tempMatchedSuggestion.length;
410
+ }
411
+
412
+ if (event.code === 'ArrowDown') {
413
+ currentSuggestionIndex.current = (currentSuggestionIndex.current + 1) % tempMatchedSuggestion.length;
414
+ }
415
+ setCurrentSuggestion(tempMatchedSuggestion[currentSuggestionIndex.current] || '');
416
+
417
+ }
418
+
419
+
189
420
  }
190
421
 
191
422
 
@@ -234,6 +465,19 @@ const Textarea = forwardRef((props: TextareaProps, externalRef: any) => {
234
465
  }
235
466
  }
236
467
 
468
+ // AI Predict initalization
469
+ //--------------
470
+ if (aiPredict && valRef.current !== null) {
471
+ originInputComputedStyle.current = {
472
+ fontSize: actualPropertyValue(valRef.current as HTMLInputElement, 'fontSize'),
473
+ fontFamily: actualPropertyValue(valRef.current as HTMLInputElement, 'fontFamily'),
474
+ letterSpacing: actualPropertyValue(valRef.current as HTMLInputElement, 'letterSpacing'),
475
+ textTop: getTextTop(valRef.current)
476
+ };
477
+ }
478
+
479
+
480
+
237
481
  }, []);
238
482
 
239
483
  return (
@@ -242,45 +486,94 @@ const Textarea = forwardRef((props: TextareaProps, externalRef: any) => {
242
486
  <div className={clsWrite(wrapperClassName, 'mb-3 position-relative')} ref={rootRef}>
243
487
  {label ? <>{typeof label === 'string' ? <label htmlFor={idRes} className="form-label" dangerouslySetInnerHTML={{__html: `${label}`}}></label> : <label htmlFor={idRes} className="form-label">{label}</label>}</> : null}
244
488
 
245
- <div className={clsWrite(controlGroupWrapperClassName, 'input-group')}>
246
- {typeof iconLeft !== 'undefined' && iconLeft !== null && iconLeft !== '' ? <><span className={clsWrite(controlGroupTextClassName, 'input-group-text')}>{iconLeft}</span></>: null}
247
-
489
+
490
+ <div className={combinedCls(
491
+ 'position-relative z-1',
492
+ clsWrite(controlGroupWrapperClassName, 'input-group'),
493
+ {
494
+ 'has-left-content': propExist(iconLeft),
495
+ 'has-right-content': propExist(iconRight)
496
+ }
497
+ )}>
498
+ {propExist(iconLeft) ? <><span className={clsWrite(controlGroupTextClassName, 'input-group-text')}>{iconLeft}</span></> : null}
499
+
500
+ <div className="input-group-control-container flex-fill position-relative">
248
501
  <textarea
249
- ref={(node) => {
250
- valRef.current = node;
251
- if (typeof externalRef === 'function') {
252
- externalRef(node);
253
- } else if (externalRef) {
254
- externalRef.current = node;
255
- }
256
- }}
257
- tabIndex={tabIndex || 0}
258
- className={combinedCls(
259
- clsWrite(controlClassName, 'form-control'),
260
- controlExClassName
261
- )}
262
- id={idRes}
263
- name={name}
264
- placeholder={placeholder || ''}
265
- defaultValue={defaultValue}
266
- value={changedVal}
267
- minLength={minLength || null}
268
- maxLength={maxLength || null}
269
- onFocus={handleFocus}
270
- onBlur={handleBlur}
271
- onChange={handleChange}
272
- onKeyDown={handleKeyPressed}
273
- disabled={disabled || null}
274
- required={required || null}
275
- readOnly={readOnly || null}
276
- cols={cols || 20}
277
- rows={rows || 2}
278
- style={style}
279
- {...attributes}
280
- />
281
- {typeof iconRight !== 'undefined' && iconRight !== null && iconRight !== '' ? <><span className={clsWrite(controlGroupTextClassName, 'input-group-text')}>{iconRight}</span></>: null}
502
+ ref={(node) => {
503
+ valRef.current = node;
504
+ if (typeof externalRef === 'function') {
505
+ externalRef(node);
506
+ } else if (externalRef) {
507
+ externalRef.current = node;
508
+ }
509
+ }}
510
+ tabIndex={tabIndex || 0}
511
+ className={combinedCls(
512
+ clsWrite(controlClassName, 'form-control'),
513
+ controlExClassName,
514
+ {
515
+ 'rounded': !propExist(iconLeft) && !propExist(iconRight),
516
+ 'rounded-start-0': propExist(iconLeft),
517
+ 'rounded-end-0': propExist(iconRight)
518
+ }
519
+ )}
520
+ id={idRes}
521
+ name={name}
522
+ placeholder={placeholder || ''}
523
+ defaultValue={defaultValue}
524
+ value={changedVal}
525
+ minLength={minLength || null}
526
+ maxLength={maxLength || null}
527
+ onFocus={handleFocus}
528
+ onBlur={handleBlur}
529
+ onChange={(e: any) => {
530
+ handleChange(e);
531
+
532
+ // AI Predict
533
+ if (aiPredict) {
534
+ handleChangeSuggestionsFetchSafe(e, e.target.value);
535
+ }
536
+ }}
537
+ onKeyDown={handleKeyPressed}
538
+ disabled={disabled || null}
539
+ required={required || null}
540
+ readOnly={readOnly || null}
541
+ cols={cols || 20}
542
+ rows={rows || 2}
543
+ style={style}
544
+ {...attributes}
545
+ />
546
+
547
+ {/* AI Predict */}
548
+ {aiPredict && remainingText && (
549
+ <div
550
+ ref={aiInputRef}
551
+ className="position-absolute z-1"
552
+ style={{
553
+ left: `${originInputComputedStyle.current.fontSize + textWidth}px`,
554
+ top: originInputComputedStyle.current.textTop + 'px',
555
+ color: `rgba(${aiPredictRemainingTextRGB[0]}, ${aiPredictRemainingTextRGB[1]}, ${aiPredictRemainingTextRGB[2]}, ${calculateOpacity()})`,
556
+ pointerEvents: 'none',
557
+ fontSize: originInputComputedStyle.current.fontSize + 'px',
558
+ fontFamily: originInputComputedStyle.current.fontFamily,
559
+ letterSpacing: originInputComputedStyle.current.letterSpacing
560
+ }}
561
+ >
562
+ {remainingText}
563
+ </div>
564
+ )}
565
+
566
+ {/* Required marking */}
567
+ {required ? <>{requiredLabel || requiredLabel === '' ? requiredLabel : <span className="position-absolute end-0 top-0 my-2 mx-2"><span className="text-danger">*</span></span>}</> : ''}
568
+
569
+ </div>
570
+
571
+
572
+ {propExist(iconRight) ? <><span className={clsWrite(controlGroupTextClassName, 'input-group-text')}>{iconRight}</span></> : null}
573
+
574
+
282
575
  </div>
283
- {required ? <>{requiredLabel || requiredLabel === '' ? requiredLabel : <span className="position-absolute end-0 top-0 my-2 mx-2"><span className="text-danger">*</span></span>}</> : ''}
576
+
284
577
 
285
578
  </div>
286
579
 
@@ -194,8 +194,9 @@ export default function TreeList(props: TreeListProps) {
194
194
  function handleCollapse(e: any) {
195
195
  if ( disableCollapse ) return;
196
196
 
197
-
198
197
  e.preventDefault();
198
+ e.stopPropagation();
199
+
199
200
  const hyperlink = e.currentTarget;
200
201
  const url = hyperlink.getAttribute('href');
201
202
  const subElement = getNextSiblings(hyperlink, 'ul');
@@ -258,6 +259,8 @@ export default function TreeList(props: TreeListProps) {
258
259
 
259
260
  function handleSelect(e: any) {
260
261
  e.preventDefault();
262
+ e.stopPropagation();
263
+
261
264
  const hyperlink = e.currentTarget;
262
265
 
263
266
  if ( hyperlink.classList.contains('selected') ) {
@@ -7,6 +7,7 @@ import {
7
7
  flatData
8
8
  } from 'funda-utils/dist/cjs/object';
9
9
 
10
+
10
11
  import TreeList from './TreeList';
11
12
  import { initUlHeight, initAsyncItems } from './init-height';
12
13
 
@@ -1,4 +1,21 @@
1
1
 
2
+
3
+ /**
4
+ * Gets the relative upside of the text
5
+ * @param {Element} el - A DOM node containing one selector to match against.
6
+ * @returns {Number} - Returns a pure number.
7
+ */
8
+ function getTextTop(el: HTMLElement) {
9
+ const styles = window.getComputedStyle(el);
10
+ const fontSize = parseFloat(styles.fontSize);
11
+ const lineHeight = parseFloat(styles.lineHeight) || fontSize;
12
+ const paddingTop = parseFloat(styles.paddingTop);
13
+ const borderWidth = parseFloat(styles.borderWidth);
14
+
15
+ const textTop = paddingTop + (lineHeight - fontSize) / 2 - borderWidth*2;
16
+ return textTop;
17
+ }
18
+
2
19
  /**
3
20
  * Get the actual value with user specific methed
4
21
  * it can be 'width', 'height', 'outerWidth', 'outerHeight'
@@ -9,14 +26,14 @@
9
26
  takes effect when set to true
10
27
  * @return {Number} - Returns a pure number.
11
28
  */
12
- function actualPropertyValue(el: any, prop: string, config: any = undefined ) {
29
+ function actualPropertyValue(el: any, prop: string, config: any = undefined) {
13
30
  if (el === null) return 0;
14
31
 
15
- const style = window.getComputedStyle ? window.getComputedStyle(el) : el.currentStyle,
16
- display = style.display,
17
- position = style.position,
32
+ const style = window.getComputedStyle ? window.getComputedStyle(el) : el.currentStyle,
33
+ display = style.display,
34
+ position = style.position,
18
35
  visibility = style.visibility;
19
-
36
+
20
37
  let marginWidth = 0;
21
38
  let marginHeight = 0;
22
39
 
@@ -24,55 +41,65 @@ function actualPropertyValue(el: any, prop: string, config: any = undefined ) {
24
41
  let actualVal: any;
25
42
 
26
43
 
27
- if ( config && config.includeMargin === true ) {
44
+ if (config && config.includeMargin === true) {
28
45
  marginWidth = parseFloat(style.marginLeft) + parseFloat(style.marginRight);
29
46
  marginHeight = parseFloat(style.marginTop) + parseFloat(style.marginBottom);
30
47
  }
31
48
 
32
-
33
- if ( prop === 'width' ) {
34
- maxVal = parseFloat( style.maxWidth );
49
+ if (prop === 'fontSize') {
50
+ actualVal = parseFloat(style.fontSize);
51
+ }
52
+
53
+ if (prop === 'fontFamily') {
54
+ actualVal = style.fontFamily;
55
+ }
56
+
57
+ if (prop === 'letterSpacing') {
58
+ actualVal = style.letterSpacing;
59
+ }
60
+ if (prop === 'width') {
61
+ maxVal = parseFloat(style.maxWidth);
35
62
 
36
63
  // if its not hidden we just return normal height
37
- if(display !== 'none' && maxVal !== 0) {
64
+ if (display !== 'none' && maxVal !== 0) {
38
65
  return el.clientWidth;
39
66
  }
40
67
  }
41
- if ( prop === 'height' ) {
42
- maxVal = parseFloat( style.maxHeight );
43
- if(display !== 'none' && maxVal !== 0) {
68
+ if (prop === 'height') {
69
+ maxVal = parseFloat(style.maxHeight);
70
+ if (display !== 'none' && maxVal !== 0) {
44
71
  return el.clientHeight;
45
- }
72
+ }
46
73
  }
47
-
48
- if ( prop === 'outerWidth' ) {
49
- maxVal = parseFloat( style.maxWidth );
50
- if(display !== 'none' && maxVal !== 0) {
74
+
75
+ if (prop === 'outerWidth') {
76
+ maxVal = parseFloat(style.maxWidth);
77
+ if (display !== 'none' && maxVal !== 0) {
51
78
  return el.offsetWidth + marginWidth;
52
79
  }
53
80
  }
54
- if ( prop === 'outerHeight' ) {
55
- maxVal = parseFloat( style.maxHeight );
56
- if(display !== 'none' && maxVal !== 0) {
81
+ if (prop === 'outerHeight') {
82
+ maxVal = parseFloat(style.maxHeight);
83
+ if (display !== 'none' && maxVal !== 0) {
57
84
  return el.offsetHeight + marginHeight;
58
- }
85
+ }
59
86
  }
60
87
 
61
88
  // the element is hidden so:
62
89
  // making the el block so we can meassure its height but still be hidden
63
- el.style.position = 'absolute';
90
+ el.style.position = 'absolute';
64
91
  el.style.visibility = 'hidden';
65
- el.style.display = 'block';
92
+ el.style.display = 'block';
66
93
 
67
94
 
68
- if ( prop === 'width' ) actualVal = el.clientWidth;
69
- if ( prop === 'height' ) actualVal = el.clientHeight;
70
- if ( prop === 'outerWidth' ) actualVal = el.offsetWidth + marginWidth;
71
- if ( prop === 'outerHeight' ) actualVal = el.offsetHeight + marginHeight;
95
+ if (prop === 'width') actualVal = el.clientWidth;
96
+ if (prop === 'height') actualVal = el.clientHeight;
97
+ if (prop === 'outerWidth') actualVal = el.offsetWidth + marginWidth;
98
+ if (prop === 'outerHeight') actualVal = el.offsetHeight + marginHeight;
72
99
 
73
100
  // reverting to the original values
74
- el.style.display = display;
75
- el.style.position = position;
101
+ el.style.display = display;
102
+ el.style.position = position;
76
103
  el.style.visibility = visibility;
77
104
 
78
105
  return actualVal;
@@ -119,11 +146,13 @@ function getTextWidth(input: HTMLInputElement, fauxContainer: HTMLSpanElement, r
119
146
  _faux.textContent = input.value.substring(0, _off).replace(/\s/g, "\u00a0");
120
147
  return actualPropertyValue(_faux, 'outerWidth');
121
148
  }
122
-
149
+
123
150
  }
124
151
 
125
152
 
126
153
  export {
154
+ getTextTop,
155
+ actualPropertyValue,
127
156
  getTextWidth
128
157
  };
129
158
 
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "author": "UIUX Lab",
3
3
  "email": "uiuxlab@gmail.com",
4
4
  "name": "funda-ui",
5
- "version": "4.4.35",
5
+ "version": "4.5.12",
6
6
  "description": "React components using pure Bootstrap 5+ which does not contain any external style and script libraries.",
7
7
  "repository": {
8
8
  "type": "git",