funda-ui 4.7.150 → 4.7.152
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/Chatbox/index.d.ts +7 -0
- package/Chatbox/index.js +247 -163
- package/lib/cjs/Chatbox/index.d.ts +7 -0
- package/lib/cjs/Chatbox/index.js +247 -163
- package/lib/esm/Chatbox/index.tsx +96 -11
- package/lib/esm/Textarea/index.tsx +0 -1
- package/package.json +1 -1
|
@@ -13,7 +13,6 @@ import { htmlEncode } from 'funda-utils/dist/cjs/sanitize';
|
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
|
|
16
|
-
|
|
17
16
|
// loader
|
|
18
17
|
import PureLoader from './PureLoader';
|
|
19
18
|
import TypingEffect from "./TypingEffect";
|
|
@@ -46,16 +45,24 @@ export type QuestionData = {
|
|
|
46
45
|
list: Array<string>;
|
|
47
46
|
};
|
|
48
47
|
|
|
48
|
+
export type SelectedOption = {
|
|
49
|
+
[key: string]: string | number;
|
|
50
|
+
curIndex: number;
|
|
51
|
+
curValue: string;
|
|
52
|
+
};
|
|
49
53
|
|
|
50
54
|
export interface FloatingButton {
|
|
51
55
|
label: string; // HTML string
|
|
52
56
|
value: string;
|
|
53
57
|
onClick: string;
|
|
58
|
+
active?: boolean; // Specify if the button should be active by default
|
|
54
59
|
isSelect?: boolean; // Mark whether it is a drop-down selection button
|
|
55
60
|
dynamicOptions?: boolean; // Mark whether to use dynamic options
|
|
61
|
+
defaultSelected?: number; // Specify default selected option index
|
|
56
62
|
[key: string]: any; // Allows dynamic `onSelect__<number>` attributes, such as `onSelect__1`, `onSelect__2`, ...
|
|
57
63
|
}
|
|
58
64
|
|
|
65
|
+
|
|
59
66
|
export interface FloatingButtonSelectOption {
|
|
60
67
|
label: string;
|
|
61
68
|
value: string;
|
|
@@ -178,6 +185,11 @@ const Chatbox = (props: ChatboxProps) => {
|
|
|
178
185
|
const [enableStreamMode, setEnableStreamMode] = useState<boolean>(true);
|
|
179
186
|
const animatedMessagesRef = useRef<Set<number>>(new Set()); // Add a ref to keep track of messages that have already been animated
|
|
180
187
|
|
|
188
|
+
// Keep track of whether the default values have been initialized
|
|
189
|
+
const [initializedDefaults, setInitializedDefaults] = useState<Record<string, boolean>>({});
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
|
|
181
193
|
//
|
|
182
194
|
const timer = useRef<any>(null);
|
|
183
195
|
|
|
@@ -508,6 +520,19 @@ const Chatbox = (props: ChatboxProps) => {
|
|
|
508
520
|
return newState;
|
|
509
521
|
});
|
|
510
522
|
};
|
|
523
|
+
|
|
524
|
+
// The onClick action specifically used to perform the default options
|
|
525
|
+
const executeDefaultOptionAction = async (actionStr: string, buttonId: string) => {
|
|
526
|
+
try {
|
|
527
|
+
const actionFn = new Function('method', 'isActive', 'button', actionStr);
|
|
528
|
+
// To perform the action, pass false as the "isActive" parameter, as this is the default option
|
|
529
|
+
await actionFn(exposedMethods(), false, document.getElementById(buttonId));
|
|
530
|
+
} catch (error) {
|
|
531
|
+
console.error('Error executing default option action:', error);
|
|
532
|
+
}
|
|
533
|
+
};
|
|
534
|
+
|
|
535
|
+
|
|
511
536
|
const executeButtonAction = async (actionStr: string, buttonId: string, buttonElement: HTMLButtonElement) => {
|
|
512
537
|
try {
|
|
513
538
|
const actionFn = new Function('method', 'isActive', 'button', actionStr);
|
|
@@ -547,7 +572,11 @@ const Chatbox = (props: ChatboxProps) => {
|
|
|
547
572
|
|
|
548
573
|
|
|
549
574
|
// options
|
|
550
|
-
const [selectedOpt, setSelectedOpt] = useState<
|
|
575
|
+
const [selectedOpt, setSelectedOpt] = useState<SelectedOption>({
|
|
576
|
+
curIndex: -1,
|
|
577
|
+
curValue: ''
|
|
578
|
+
});
|
|
579
|
+
|
|
551
580
|
// Store dynamic options
|
|
552
581
|
const [dynamicOptions, setDynamicOptions] = useState<Record<string, FloatingButtonSelectOption[]>>({});
|
|
553
582
|
|
|
@@ -575,7 +604,7 @@ const Chatbox = (props: ChatboxProps) => {
|
|
|
575
604
|
return options;
|
|
576
605
|
};
|
|
577
606
|
|
|
578
|
-
const handleExecuteButtonSelect = (buttonId: string, option: FloatingButtonSelectOption, index: number, value: string) => {
|
|
607
|
+
const handleExecuteButtonSelect = (buttonId: string, option: FloatingButtonSelectOption, index: number, value: string, isDefaultSelection: boolean = false) => {
|
|
579
608
|
|
|
580
609
|
if (option.value === "cancel") {
|
|
581
610
|
setSelectedOpt(prev => {
|
|
@@ -597,11 +626,15 @@ const Chatbox = (props: ChatboxProps) => {
|
|
|
597
626
|
}));
|
|
598
627
|
}
|
|
599
628
|
|
|
629
|
+
|
|
630
|
+
// The button action is performed and the drop-down menu is closed only when it is not the default selection
|
|
631
|
+
if (!isDefaultSelection) {
|
|
632
|
+
executeButtonAction(option.onClick, buttonId, document.getElementById(buttonId) as HTMLButtonElement);
|
|
633
|
+
|
|
634
|
+
// Close the drop-down
|
|
635
|
+
closeDropdowns();
|
|
636
|
+
}
|
|
600
637
|
|
|
601
|
-
executeButtonAction(option.onClick, buttonId, document.getElementById(buttonId) as HTMLButtonElement);
|
|
602
|
-
|
|
603
|
-
// Close the drop-down
|
|
604
|
-
closeDropdowns();
|
|
605
638
|
};
|
|
606
639
|
|
|
607
640
|
// click outside
|
|
@@ -1054,10 +1087,11 @@ const Chatbox = (props: ChatboxProps) => {
|
|
|
1054
1087
|
customMethodsRef.current,
|
|
1055
1088
|
conversationHistory.current
|
|
1056
1089
|
);
|
|
1057
|
-
|
|
1058
1090
|
const { content, isStream } = customResponse;
|
|
1059
1091
|
let contentRes: any = content;
|
|
1060
1092
|
|
|
1093
|
+
|
|
1094
|
+
|
|
1061
1095
|
// Update stream mode
|
|
1062
1096
|
setEnableStreamMode(isStream);
|
|
1063
1097
|
|
|
@@ -1164,6 +1198,7 @@ const Chatbox = (props: ChatboxProps) => {
|
|
|
1164
1198
|
// hide loader
|
|
1165
1199
|
setLoaderDisplay(false);
|
|
1166
1200
|
|
|
1201
|
+
|
|
1167
1202
|
let result: any = jsonResponse;
|
|
1168
1203
|
if (extractPath) {
|
|
1169
1204
|
for (const path of extractPath) {
|
|
@@ -1176,6 +1211,7 @@ const Chatbox = (props: ChatboxProps) => {
|
|
|
1176
1211
|
// Replace with a valid label
|
|
1177
1212
|
content = fixHtmlTags(content, args().withReasoning, args().reasoningSwitchLabel);
|
|
1178
1213
|
|
|
1214
|
+
|
|
1179
1215
|
return {
|
|
1180
1216
|
reply: formatLatestDisplayContent(content),
|
|
1181
1217
|
useStreamRender: false
|
|
@@ -1244,6 +1280,53 @@ const Chatbox = (props: ChatboxProps) => {
|
|
|
1244
1280
|
(window as any).chatboxCopyToClipboard = chatboxCopyToClipboard;
|
|
1245
1281
|
}, []);
|
|
1246
1282
|
|
|
1283
|
+
|
|
1284
|
+
|
|
1285
|
+
// Initialize the default value of toolkit buttons
|
|
1286
|
+
useEffect(() => {
|
|
1287
|
+
if (args().toolkitButtons) {
|
|
1288
|
+
args().toolkitButtons.forEach((btn: FloatingButton, index: number) => {
|
|
1289
|
+
const _id = `${args().prefix || 'custom-'}chatbox-btn-tools-${chatId}${index}`;
|
|
1290
|
+
|
|
1291
|
+
if (btn.isSelect) {
|
|
1292
|
+
|
|
1293
|
+
if (!initializedDefaults[_id] && typeof btn.defaultSelected === 'number') {
|
|
1294
|
+
const options = getButtonOptions(btn, _id);
|
|
1295
|
+
|
|
1296
|
+
// If there is a default selected item, initialize the selected state
|
|
1297
|
+
if (btn.defaultSelected >= 0 && btn.defaultSelected < options.length) {
|
|
1298
|
+
const defaultOption = options[btn.defaultSelected];
|
|
1299
|
+
if (defaultOption) {
|
|
1300
|
+
// Update the selected status
|
|
1301
|
+
// console.log('--> defaultOption: ', defaultOption);
|
|
1302
|
+
|
|
1303
|
+
// Pass the "isDefaultSelection" parameter as true
|
|
1304
|
+
handleExecuteButtonSelect(_id, defaultOption, btn.defaultSelected, defaultOption.value, true);
|
|
1305
|
+
|
|
1306
|
+
// Perform the onClick action alone
|
|
1307
|
+
executeDefaultOptionAction(defaultOption.onClick, _id);
|
|
1308
|
+
|
|
1309
|
+
|
|
1310
|
+
// Mark this button with the default value initialized
|
|
1311
|
+
setInitializedDefaults(prev => ({
|
|
1312
|
+
...prev,
|
|
1313
|
+
[_id]: true
|
|
1314
|
+
}));
|
|
1315
|
+
|
|
1316
|
+
}
|
|
1317
|
+
}
|
|
1318
|
+
}
|
|
1319
|
+
} else if (btn.active) {
|
|
1320
|
+
// For non-select buttons, if defaultActive is true, execute the onClick action
|
|
1321
|
+
executeButtonAction(btn.onClick, _id, document.getElementById(_id) as HTMLButtonElement);
|
|
1322
|
+
}
|
|
1323
|
+
|
|
1324
|
+
|
|
1325
|
+
})
|
|
1326
|
+
}
|
|
1327
|
+
}, [chatId, args().toolkitButtons]); // It is only executed when the component is first rendered and when toolkitButtons changes
|
|
1328
|
+
|
|
1329
|
+
|
|
1247
1330
|
return (
|
|
1248
1331
|
<>
|
|
1249
1332
|
|
|
@@ -1570,12 +1653,13 @@ const Chatbox = (props: ChatboxProps) => {
|
|
|
1570
1653
|
|
|
1571
1654
|
if (btn.isSelect) {
|
|
1572
1655
|
const options = getButtonOptions(btn, _id);
|
|
1573
|
-
|
|
1656
|
+
|
|
1574
1657
|
return (
|
|
1575
1658
|
<div key={index} className="toolkit-select-wrapper">
|
|
1576
1659
|
<button
|
|
1577
1660
|
id={_id}
|
|
1578
|
-
|
|
1661
|
+
data-value={btn.value || ''}
|
|
1662
|
+
className={`toolkit-select-btn ${isActive ? 'active' : ''} ${selectedOpt.curValue !== 'cancel' && typeof selectedOpt.curValue !== 'undefined' && selectedOpt.curValue !== '' ? 'opt-active' : ''}`}
|
|
1579
1663
|
onClick={(e: React.MouseEvent<HTMLButtonElement>) => {
|
|
1580
1664
|
e.preventDefault();
|
|
1581
1665
|
setActiveButtons(prev => ({
|
|
@@ -1610,7 +1694,8 @@ const Chatbox = (props: ChatboxProps) => {
|
|
|
1610
1694
|
{options.map((option: FloatingButtonSelectOption, optIndex: number) => (
|
|
1611
1695
|
<div
|
|
1612
1696
|
key={optIndex}
|
|
1613
|
-
|
|
1697
|
+
data-value={option.value || ''}
|
|
1698
|
+
className={`toolkit-select-option ${selectedOpt.curIndex === optIndex ? 'selected' : ''}`}
|
|
1614
1699
|
onClick={() => handleExecuteButtonSelect(_id, option, optIndex, option.value)}
|
|
1615
1700
|
>
|
|
1616
1701
|
<span dangerouslySetInnerHTML={{ __html: option.label }}></span>
|
|
@@ -7,7 +7,6 @@ import { clsWrite, combinedCls } from 'funda-utils/dist/cjs/cls';
|
|
|
7
7
|
import { actualPropertyValue, getTextTop } from 'funda-utils/dist/cjs/inputsCalculation';
|
|
8
8
|
import useDebounce from 'funda-utils/dist/cjs/useDebounce';
|
|
9
9
|
|
|
10
|
-
|
|
11
10
|
export type TextareaProps = {
|
|
12
11
|
contentRef?: React.ForwardedRef<any>; // could use "Array" on contentRef.current, such as contentRef.current[0], contentRef.current[1]
|
|
13
12
|
wrapperClassName?: string;
|
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.7.
|
|
5
|
+
"version": "4.7.152",
|
|
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",
|