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.
- package/Date/index.js +1078 -77
- package/EventCalendar/index.js +8 -2
- package/EventCalendarTimeline/index.js +32 -1
- package/Input/index.d.ts +7 -0
- package/Input/index.js +699 -57
- package/MasonryLayout/index.js +11 -1
- package/MultipleSelect/index.d.ts +1 -0
- package/MultipleSelect/index.js +7 -5
- package/RangeSlider/index.js +1078 -77
- package/Select/index.js +34 -2
- package/Textarea/index.d.ts +7 -0
- package/Textarea/index.js +707 -10
- package/Tree/index.js +2 -0
- package/Utils/inputsCalculation.d.ts +18 -1
- package/Utils/inputsCalculation.js +26 -0
- package/lib/cjs/Date/index.js +1078 -77
- package/lib/cjs/EventCalendar/index.js +8 -2
- package/lib/cjs/EventCalendarTimeline/index.js +32 -1
- package/lib/cjs/Input/index.d.ts +7 -0
- package/lib/cjs/Input/index.js +699 -57
- package/lib/cjs/MasonryLayout/index.js +11 -1
- package/lib/cjs/MultipleSelect/index.d.ts +1 -0
- package/lib/cjs/MultipleSelect/index.js +7 -5
- package/lib/cjs/RangeSlider/index.js +1078 -77
- package/lib/cjs/Select/index.js +34 -2
- package/lib/cjs/Textarea/index.d.ts +7 -0
- package/lib/cjs/Textarea/index.js +707 -10
- package/lib/cjs/Tree/index.js +2 -0
- package/lib/cjs/Utils/inputsCalculation.d.ts +18 -1
- package/lib/cjs/Utils/inputsCalculation.js +26 -0
- package/lib/esm/EventCalendar/index.tsx +8 -6
- package/lib/esm/EventCalendarTimeline/index.tsx +439 -403
- package/lib/esm/Input/index.tsx +299 -77
- package/lib/esm/MasonryLayout/index.tsx +9 -2
- package/lib/esm/MultipleSelect/index.tsx +6 -4
- package/lib/esm/Textarea/index.tsx +332 -39
- package/lib/esm/Tree/TreeList.tsx +4 -1
- package/lib/esm/Tree/index.tsx +1 -0
- package/lib/esm/Utils/libs/inputsCalculation.ts +60 -31
- 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
|
-
|
|
246
|
-
|
|
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
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
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
|
-
|
|
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') ) {
|
package/lib/esm/Tree/index.tsx
CHANGED
|
@@ -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
|
|
16
|
-
display
|
|
17
|
-
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 (
|
|
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
|
-
|
|
34
|
-
|
|
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 (
|
|
42
|
-
maxVal = parseFloat(
|
|
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 (
|
|
49
|
-
maxVal = parseFloat(
|
|
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 (
|
|
55
|
-
maxVal = parseFloat(
|
|
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
|
|
90
|
+
el.style.position = 'absolute';
|
|
64
91
|
el.style.visibility = 'hidden';
|
|
65
|
-
el.style.display
|
|
92
|
+
el.style.display = 'block';
|
|
66
93
|
|
|
67
94
|
|
|
68
|
-
if (
|
|
69
|
-
if (
|
|
70
|
-
if (
|
|
71
|
-
if (
|
|
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
|
|
75
|
-
el.style.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.
|
|
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",
|