@app-studio/web 0.9.82 → 0.9.83
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/dist/components/ChatWidget/ChatWidget/ChatWidget.props.d.ts +58 -0
- package/dist/components/ChatWidget/ChatWidget/ChatWidget.state.d.ts +12 -0
- package/dist/components/ChatWidget/ChatWidget/ChatWidget.style.d.ts +87 -0
- package/dist/components/ChatWidget/ChatWidget/ChatWidget.type.d.ts +54 -0
- package/dist/components/ChatWidget/ChatWidget/ChatWidget.view.d.ts +8 -0
- package/dist/components/ChatWidget/ChatWidget.d.ts +20 -0
- package/dist/components/ChatWidget/Widget/ChatWidgetWidget.d.ts +14 -0
- package/dist/components/ChatWidget/Widget/index.d.ts +2 -0
- package/dist/components/ChatWidget/Widget/useContextSelector.d.ts +22 -0
- package/dist/components/EditComponent/EditComponent.d.ts +14 -0
- package/dist/components/EditComponent/EditPanel.d.ts +7 -0
- package/dist/components/EditComponent/EditToolbar.d.ts +16 -0
- package/dist/components/EditComponent/index.d.ts +3 -0
- package/dist/components/Form/Password/Password/Password.state.d.ts +1 -1
- package/dist/components/Icon/Icon.d.ts +4 -0
- package/dist/components/Tabs/Tabs/Tabs.props.d.ts +1 -1
- package/dist/components/Tabs/Tabs/Tabs.state.d.ts +2 -3
- package/dist/components/index.d.ts +3 -0
- package/dist/pages/chatwidget.page.d.ts +3 -0
- package/dist/pages/editComponent.page.d.ts +3 -0
- package/dist/web.cjs.development.js +953 -28
- package/dist/web.cjs.development.js.map +1 -1
- package/dist/web.cjs.production.min.js +1 -1
- package/dist/web.cjs.production.min.js.map +1 -1
- package/dist/web.esm.js +950 -29
- package/dist/web.esm.js.map +1 -1
- package/dist/web.umd.development.js +953 -28
- package/dist/web.umd.development.js.map +1 -1
- package/dist/web.umd.production.min.js +1 -1
- package/dist/web.umd.production.min.js.map +1 -1
- package/package.json +1 -1
|
@@ -775,6 +775,9 @@
|
|
|
775
775
|
var DragHandleLinesIcon = /*#__PURE__*/createIcon('grip-horizontal', {
|
|
776
776
|
filled: false
|
|
777
777
|
});
|
|
778
|
+
var MousePointerIcon = /*#__PURE__*/createIcon('mouse-pointer-2', {
|
|
779
|
+
filled: false
|
|
780
|
+
});
|
|
778
781
|
|
|
779
782
|
/**
|
|
780
783
|
* Alert Styles
|
|
@@ -3280,7 +3283,7 @@
|
|
|
3280
3283
|
var mainColorKey = (_ref6 = backgroundColor != null ? backgroundColor : color) != null ? _ref6 : 'theme.button.background';
|
|
3281
3284
|
// Decide which theme token to resolve based on state
|
|
3282
3285
|
var stateColorKey = isDisabled ? 'theme.disabled' : isLoading ? 'theme.loading' : mainColorKey;
|
|
3283
|
-
// Resolve to actual hex color.
|
|
3286
|
+
// Resolve to actual hex color.
|
|
3284
3287
|
// If 'theme.button.background' isn't defined, it falls back to 'theme.primary'
|
|
3285
3288
|
var mainTone = getColorHex(stateColorKey);
|
|
3286
3289
|
if (mainTone === 'theme.button.background' || mainTone === 'theme.loading') {
|
|
@@ -16619,40 +16622,46 @@
|
|
|
16619
16622
|
* @param defaultValue - The optional title of the tab to be initially active.
|
|
16620
16623
|
* @returns An object containing the current activeTab and a function to update it.
|
|
16621
16624
|
*/
|
|
16622
|
-
var useTabsState = (propTabs, defaultValue) => {
|
|
16625
|
+
var useTabsState = (propTabs, defaultValue, value) => {
|
|
16626
|
+
// Helper to extract the identifier (value or title) from a tab
|
|
16627
|
+
var getTabId = tab => tab.value !== undefined ? tab.value : tab.title;
|
|
16623
16628
|
// Find the initial tab based on defaultValue, or default to the first tab.
|
|
16624
|
-
// Ensure propTabs is not empty before accessing index 0.
|
|
16625
16629
|
var findInitialTab = () => {
|
|
16626
16630
|
if (!propTabs || propTabs.length === 0) {
|
|
16627
|
-
return undefined;
|
|
16631
|
+
return undefined;
|
|
16628
16632
|
}
|
|
16629
16633
|
if (defaultValue !== undefined) {
|
|
16630
|
-
var foundTab = propTabs.find(tab => tab
|
|
16634
|
+
var foundTab = propTabs.find(tab => getTabId(tab) === defaultValue);
|
|
16631
16635
|
if (foundTab) {
|
|
16632
16636
|
return foundTab;
|
|
16633
16637
|
}
|
|
16634
|
-
// Warn if defaultValue is provided but not found
|
|
16635
|
-
// console.warn(
|
|
16636
|
-
// `Tabs: defaultValue "${defaultValue}" not found in tabs. Defaulting to the first tab.`
|
|
16637
|
-
// );
|
|
16638
16638
|
}
|
|
16639
|
-
return propTabs[0];
|
|
16639
|
+
return propTabs[0];
|
|
16640
16640
|
};
|
|
16641
|
-
var [
|
|
16642
|
-
//
|
|
16643
|
-
//
|
|
16641
|
+
var [internalActiveTab, setInternalActiveTab] = React.useState(findInitialTab());
|
|
16642
|
+
// Determine the effective active tab
|
|
16643
|
+
// In controlled mode (value provided), find the tab matching value.
|
|
16644
|
+
// In uncontrolled mode, use internal state.
|
|
16645
|
+
var activeTab = value !== undefined ? propTabs.find(tab => getTabId(tab) === value) : internalActiveTab;
|
|
16646
|
+
var setActiveTab = tab => {
|
|
16647
|
+
// Only update internal state if uncontrolled
|
|
16648
|
+
if (value === undefined) {
|
|
16649
|
+
setInternalActiveTab(tab);
|
|
16650
|
+
}
|
|
16651
|
+
};
|
|
16652
|
+
// Effect to update internal active tab if defaultValue changes or tabs change
|
|
16644
16653
|
React.useEffect(() => {
|
|
16654
|
+
if (value !== undefined) return; // Skip logic if controlled
|
|
16645
16655
|
var newInitialTab = findInitialTab();
|
|
16646
|
-
|
|
16647
|
-
//
|
|
16648
|
-
|
|
16649
|
-
if (newInitialTab && (!currentActiveTabStillValid || defaultValue !== undefined &&
|
|
16650
|
-
|
|
16651
|
-
} else if (!newInitialTab &&
|
|
16652
|
-
|
|
16653
|
-
|
|
16654
|
-
|
|
16655
|
-
}, [propTabs, defaultValue]); // Rerun when tabs or initial title changes
|
|
16656
|
+
var currentActiveTabStillValid = internalActiveTab && propTabs.some(t => getTabId(t) === getTabId(internalActiveTab));
|
|
16657
|
+
// If current tab is invalid, or if defaultValue changed and suggests a different tab
|
|
16658
|
+
// (Note: The original logic forced reset on defaultValue change, we keep that behavior)
|
|
16659
|
+
if (newInitialTab && (!currentActiveTabStillValid || defaultValue !== undefined && internalActiveTab && getTabId(internalActiveTab) !== defaultValue)) {
|
|
16660
|
+
setInternalActiveTab(newInitialTab);
|
|
16661
|
+
} else if (!newInitialTab && internalActiveTab) {
|
|
16662
|
+
setInternalActiveTab(undefined);
|
|
16663
|
+
}
|
|
16664
|
+
}, [propTabs, defaultValue]); // Remove internalActiveTab dependency to avoid loops, though it shouldn't cause one if guarded
|
|
16656
16665
|
return {
|
|
16657
16666
|
activeTab,
|
|
16658
16667
|
setActiveTab
|
|
@@ -16739,6 +16748,10 @@
|
|
|
16739
16748
|
var getGap = () => {
|
|
16740
16749
|
return ['top', 'bottom'].includes(iconPosition) ? '4px' : '8px';
|
|
16741
16750
|
};
|
|
16751
|
+
// Clone icon to apply active styles (e.g. bold stroke) if valid
|
|
16752
|
+
var iconElement = tab.icon && /*#__PURE__*/React__default.isValidElement(tab.icon) ? /*#__PURE__*/React__default.cloneElement(tab.icon, {
|
|
16753
|
+
strokeWidth: isActive ? 2.5 : 2
|
|
16754
|
+
}) : tab.icon;
|
|
16742
16755
|
return /*#__PURE__*/React__default.createElement(appStudio.Element, Object.assign({
|
|
16743
16756
|
as: "div",
|
|
16744
16757
|
role: "tab",
|
|
@@ -16749,7 +16762,23 @@
|
|
|
16749
16762
|
gap: getGap(),
|
|
16750
16763
|
onClick: onClick,
|
|
16751
16764
|
"data-state": isActive ? 'active' : 'inactive'
|
|
16752
|
-
}),
|
|
16765
|
+
}), iconElement && (/*#__PURE__*/React__default.createElement(appStudio.Element, {
|
|
16766
|
+
key: isActive ? 'active-icon' : 'inactive-icon'
|
|
16767
|
+
}, iconElement)), /*#__PURE__*/React__default.createElement(appStudio.Element, {
|
|
16768
|
+
display: "grid",
|
|
16769
|
+
alignItems: "center",
|
|
16770
|
+
justifyContent: "center"
|
|
16771
|
+
}, /*#__PURE__*/React__default.createElement(appStudio.Text, Object.assign({}, textStyles, {
|
|
16772
|
+
fontWeight: "600",
|
|
16773
|
+
visibility: "hidden",
|
|
16774
|
+
gridColumn: "1",
|
|
16775
|
+
gridRow: "1",
|
|
16776
|
+
"aria-hidden": "true"
|
|
16777
|
+
}), tab.title), /*#__PURE__*/React__default.createElement(appStudio.Text, Object.assign({}, textStyles, {
|
|
16778
|
+
fontWeight: isActive ? '600' : '500',
|
|
16779
|
+
gridColumn: "1",
|
|
16780
|
+
gridRow: "1"
|
|
16781
|
+
}), tab.title)));
|
|
16753
16782
|
};
|
|
16754
16783
|
|
|
16755
16784
|
/**
|
|
@@ -16785,7 +16814,7 @@
|
|
|
16785
16814
|
borderBottomColor: "color.gray.200"
|
|
16786
16815
|
}, views.headerTabs), tabs.map(tab => {
|
|
16787
16816
|
// Determine if the current tab in the loop is the active one
|
|
16788
|
-
var isActive = tab.title === activeTab.title;
|
|
16817
|
+
var isActive = (tab.value !== undefined ? tab.value : tab.title) === (activeTab.value !== undefined ? activeTab.value : activeTab.title);
|
|
16789
16818
|
// Prepare the onClick handler for this specific tab
|
|
16790
16819
|
var onClick = () => handleTabClick(tab);
|
|
16791
16820
|
// Use the custom renderTab function if provided
|
|
@@ -16904,7 +16933,7 @@
|
|
|
16904
16933
|
// For compound component pattern
|
|
16905
16934
|
var compoundState = useTabsCompoundState(defaultValue, value, onValueChange);
|
|
16906
16935
|
// For data-driven pattern
|
|
16907
|
-
var dataState = useTabsState(tabs || [], defaultValue);
|
|
16936
|
+
var dataState = useTabsState(tabs || [], defaultValue, value);
|
|
16908
16937
|
// If using compound component pattern (children provided)
|
|
16909
16938
|
if (children) {
|
|
16910
16939
|
return /*#__PURE__*/React__default.createElement(TabsContext.Provider, {
|
|
@@ -16915,9 +16944,9 @@
|
|
|
16915
16944
|
if (tabs) {
|
|
16916
16945
|
// Handler function to change the active tab and trigger the callback
|
|
16917
16946
|
var handleTabClick = tab => {
|
|
16918
|
-
var
|
|
16947
|
+
var getTabId = t => t.value !== undefined ? t.value : t.title;
|
|
16919
16948
|
// Only update state and call callback if the clicked tab is different from the current one
|
|
16920
|
-
if (
|
|
16949
|
+
if (!dataState.activeTab || getTabId(dataState.activeTab) !== getTabId(tab)) {
|
|
16921
16950
|
dataState.setActiveTab(tab);
|
|
16922
16951
|
// Call the onTabChange callback if provided
|
|
16923
16952
|
if (onTabChange) {
|
|
@@ -26260,6 +26289,898 @@
|
|
|
26260
26289
|
});
|
|
26261
26290
|
Background.displayName = 'Background';
|
|
26262
26291
|
|
|
26292
|
+
/**
|
|
26293
|
+
* Custom hook for managing ChatWidget component state
|
|
26294
|
+
*/
|
|
26295
|
+
function useChatWidgetState(props) {
|
|
26296
|
+
var {
|
|
26297
|
+
inputValue,
|
|
26298
|
+
onInputChange,
|
|
26299
|
+
onSubmit,
|
|
26300
|
+
messages = []
|
|
26301
|
+
} = props;
|
|
26302
|
+
// Internal state for uncontrolled input
|
|
26303
|
+
var [internalInputValue, setInternalInputValue] = React.useState('');
|
|
26304
|
+
// Refs
|
|
26305
|
+
var inputRef = React.useRef(null);
|
|
26306
|
+
var messagesRef = React.useRef(null);
|
|
26307
|
+
// Determine if the component is controlled
|
|
26308
|
+
var isControlled = inputValue !== undefined;
|
|
26309
|
+
// Get the current input value
|
|
26310
|
+
var currentInputValue = inputValue !== undefined ? inputValue : internalInputValue;
|
|
26311
|
+
// Handle input changes
|
|
26312
|
+
var handleInputChange = React.useCallback(value => {
|
|
26313
|
+
if (isControlled) {
|
|
26314
|
+
onInputChange == null || onInputChange(value);
|
|
26315
|
+
} else {
|
|
26316
|
+
setInternalInputValue(value);
|
|
26317
|
+
}
|
|
26318
|
+
}, [isControlled, onInputChange]);
|
|
26319
|
+
// Handle message submission
|
|
26320
|
+
var handleSubmit = React.useCallback(e => {
|
|
26321
|
+
if (e) {
|
|
26322
|
+
e.preventDefault();
|
|
26323
|
+
}
|
|
26324
|
+
var trimmedValue = currentInputValue.trim();
|
|
26325
|
+
if (trimmedValue && onSubmit) {
|
|
26326
|
+
onSubmit(trimmedValue);
|
|
26327
|
+
// Clear input after submission (only for uncontrolled)
|
|
26328
|
+
if (!isControlled) {
|
|
26329
|
+
setInternalInputValue('');
|
|
26330
|
+
}
|
|
26331
|
+
// Reset textarea height
|
|
26332
|
+
if (inputRef.current) {
|
|
26333
|
+
inputRef.current.style.height = 'auto';
|
|
26334
|
+
}
|
|
26335
|
+
}
|
|
26336
|
+
}, [currentInputValue, onSubmit, isControlled]);
|
|
26337
|
+
// Auto-scroll to bottom when new messages arrive
|
|
26338
|
+
React.useEffect(() => {
|
|
26339
|
+
if (messagesRef.current) {
|
|
26340
|
+
messagesRef.current.scrollTop = messagesRef.current.scrollHeight;
|
|
26341
|
+
}
|
|
26342
|
+
}, [messages.length]);
|
|
26343
|
+
return {
|
|
26344
|
+
internalInputValue: currentInputValue,
|
|
26345
|
+
handleInputChange,
|
|
26346
|
+
handleSubmit,
|
|
26347
|
+
inputRef,
|
|
26348
|
+
messagesRef
|
|
26349
|
+
};
|
|
26350
|
+
}
|
|
26351
|
+
|
|
26352
|
+
/** Size mappings for the ChatWidget component */
|
|
26353
|
+
var Sizes$5 = {
|
|
26354
|
+
sm: {
|
|
26355
|
+
fontSize: '13px',
|
|
26356
|
+
padding: '8px'
|
|
26357
|
+
},
|
|
26358
|
+
md: {
|
|
26359
|
+
fontSize: '14px',
|
|
26360
|
+
padding: '12px'
|
|
26361
|
+
},
|
|
26362
|
+
lg: {
|
|
26363
|
+
fontSize: '16px',
|
|
26364
|
+
padding: '16px'
|
|
26365
|
+
}
|
|
26366
|
+
};
|
|
26367
|
+
/** Variant mappings for the ChatWidget component */
|
|
26368
|
+
var Variants$4 = {
|
|
26369
|
+
default: {
|
|
26370
|
+
backgroundColor: '#ffffff',
|
|
26371
|
+
border: '1px solid #e5e7eb',
|
|
26372
|
+
borderRadius: '16px'
|
|
26373
|
+
},
|
|
26374
|
+
glassy: {
|
|
26375
|
+
backgroundColor: 'rgba(255, 255, 255, 0.6)',
|
|
26376
|
+
backdropFilter: 'blur(12px)',
|
|
26377
|
+
border: '1px solid rgba(0, 0, 0, 0.1)',
|
|
26378
|
+
borderRadius: '16px',
|
|
26379
|
+
boxShadow: '0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)'
|
|
26380
|
+
},
|
|
26381
|
+
minimal: {
|
|
26382
|
+
backgroundColor: 'transparent',
|
|
26383
|
+
border: 'none'
|
|
26384
|
+
}
|
|
26385
|
+
};
|
|
26386
|
+
/** Bubble size mappings */
|
|
26387
|
+
var BubbleSizes = {
|
|
26388
|
+
sm: {
|
|
26389
|
+
fontSize: '13px',
|
|
26390
|
+
padding: '6px 10px',
|
|
26391
|
+
borderRadius: '14px'
|
|
26392
|
+
},
|
|
26393
|
+
md: {
|
|
26394
|
+
fontSize: '14px',
|
|
26395
|
+
padding: '8px 12px',
|
|
26396
|
+
borderRadius: '16px'
|
|
26397
|
+
},
|
|
26398
|
+
lg: {
|
|
26399
|
+
fontSize: '16px',
|
|
26400
|
+
padding: '10px 16px',
|
|
26401
|
+
borderRadius: '18px'
|
|
26402
|
+
}
|
|
26403
|
+
};
|
|
26404
|
+
/** User bubble styles (blue, aligned right) */
|
|
26405
|
+
var UserBubbleStyles = {
|
|
26406
|
+
backgroundColor: 'rgba(37, 99, 235, 0.9)',
|
|
26407
|
+
color: '#ffffff',
|
|
26408
|
+
alignSelf: 'flex-end',
|
|
26409
|
+
borderBottomRightRadius: '4px',
|
|
26410
|
+
boxShadow: '0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06)'
|
|
26411
|
+
};
|
|
26412
|
+
/** Assistant bubble styles (gray, aligned left) */
|
|
26413
|
+
var AssistantBubbleStyles = {
|
|
26414
|
+
backgroundColor: 'rgba(244, 244, 245, 0.6)',
|
|
26415
|
+
color: '#18181b',
|
|
26416
|
+
alignSelf: 'flex-start',
|
|
26417
|
+
borderBottomLeftRadius: '4px',
|
|
26418
|
+
boxShadow: '0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06)'
|
|
26419
|
+
};
|
|
26420
|
+
/** Input container styles with glassmorphic effect */
|
|
26421
|
+
var InputContainerStyles = {
|
|
26422
|
+
position: 'relative',
|
|
26423
|
+
backgroundColor: 'rgba(244, 244, 245, 0.05)',
|
|
26424
|
+
backdropFilter: 'blur(12px)',
|
|
26425
|
+
borderRadius: '16px',
|
|
26426
|
+
border: '1px solid rgba(0, 0, 0, 0.1)',
|
|
26427
|
+
boxShadow: '0 4px 6px -1px rgba(0, 0, 0, 0.1)',
|
|
26428
|
+
padding: '8px 12px',
|
|
26429
|
+
display: 'flex',
|
|
26430
|
+
alignItems: 'flex-end',
|
|
26431
|
+
gap: '8px',
|
|
26432
|
+
transition: 'all 0.2s ease'
|
|
26433
|
+
};
|
|
26434
|
+
/** Default ChatWidget component styles */
|
|
26435
|
+
var DefaultChatWidgetStyles = {
|
|
26436
|
+
container: {
|
|
26437
|
+
display: 'flex',
|
|
26438
|
+
flexDirection: 'column',
|
|
26439
|
+
width: '100%',
|
|
26440
|
+
height: '100%',
|
|
26441
|
+
overflow: 'hidden'
|
|
26442
|
+
},
|
|
26443
|
+
messagesContainer: {
|
|
26444
|
+
flex: 1,
|
|
26445
|
+
overflowY: 'auto',
|
|
26446
|
+
display: 'flex',
|
|
26447
|
+
flexDirection: 'column',
|
|
26448
|
+
gap: '8px',
|
|
26449
|
+
padding: '16px'
|
|
26450
|
+
},
|
|
26451
|
+
inputContainer: InputContainerStyles,
|
|
26452
|
+
bubble: {
|
|
26453
|
+
maxWidth: '80%',
|
|
26454
|
+
position: 'relative',
|
|
26455
|
+
wordWrap: 'break-word',
|
|
26456
|
+
animation: 'chatBubbleAppear 0.3s ease-out'
|
|
26457
|
+
},
|
|
26458
|
+
timestamp: {
|
|
26459
|
+
position: 'absolute',
|
|
26460
|
+
top: '-24px',
|
|
26461
|
+
fontSize: '12px',
|
|
26462
|
+
color: 'rgba(0, 0, 0, 0.5)',
|
|
26463
|
+
backgroundColor: 'rgba(255, 255, 255, 0.9)',
|
|
26464
|
+
padding: '2px 8px',
|
|
26465
|
+
borderRadius: '9999px',
|
|
26466
|
+
opacity: 0,
|
|
26467
|
+
transition: 'opacity 0.15s ease-out',
|
|
26468
|
+
boxShadow: '0 1px 2px 0 rgba(0, 0, 0, 0.05)'
|
|
26469
|
+
},
|
|
26470
|
+
input: {
|
|
26471
|
+
flex: 1,
|
|
26472
|
+
border: 'none',
|
|
26473
|
+
outline: 'none',
|
|
26474
|
+
backgroundColor: 'transparent',
|
|
26475
|
+
resize: 'none',
|
|
26476
|
+
fontFamily: 'inherit',
|
|
26477
|
+
fontSize: '14px',
|
|
26478
|
+
minHeight: '24px',
|
|
26479
|
+
maxHeight: '120px'
|
|
26480
|
+
},
|
|
26481
|
+
sendButton: {
|
|
26482
|
+
width: '32px',
|
|
26483
|
+
height: '32px',
|
|
26484
|
+
borderRadius: '50%',
|
|
26485
|
+
border: 'none',
|
|
26486
|
+
cursor: 'pointer',
|
|
26487
|
+
display: 'flex',
|
|
26488
|
+
alignItems: 'center',
|
|
26489
|
+
justifyContent: 'center',
|
|
26490
|
+
transition: 'all 0.2s ease',
|
|
26491
|
+
flexShrink: 0
|
|
26492
|
+
},
|
|
26493
|
+
attachmentButton: {
|
|
26494
|
+
width: '32px',
|
|
26495
|
+
height: '32px',
|
|
26496
|
+
borderRadius: '50%',
|
|
26497
|
+
border: 'none',
|
|
26498
|
+
cursor: 'pointer',
|
|
26499
|
+
display: 'flex',
|
|
26500
|
+
alignItems: 'center',
|
|
26501
|
+
justifyContent: 'center',
|
|
26502
|
+
backgroundColor: 'transparent',
|
|
26503
|
+
transition: 'background-color 0.2s ease',
|
|
26504
|
+
flexShrink: 0
|
|
26505
|
+
}
|
|
26506
|
+
};
|
|
26507
|
+
|
|
26508
|
+
var _excluded$1p = ["messages", "inputPlaceholder", "disableInput", "variant", "size", "showTimestamps", "enableAttachments", "enableContextPicker", "selectedContextElements", "onContextPickerClick", "onRemoveContextElement", "isLoading", "loadingText", "styles", "maxHeight", "internalInputValue", "handleInputChange", "handleSubmit", "inputRef", "messagesRef"],
|
|
26509
|
+
_excluded2$n = ["onSubmit"];
|
|
26510
|
+
/**
|
|
26511
|
+
* ChatWidget View Component
|
|
26512
|
+
* Presentational component for the ChatWidget interface
|
|
26513
|
+
*/
|
|
26514
|
+
var ChatWidgetView = _ref => {
|
|
26515
|
+
var _styles$contextPicker;
|
|
26516
|
+
var {
|
|
26517
|
+
messages = [],
|
|
26518
|
+
inputPlaceholder = 'Type a message...',
|
|
26519
|
+
disableInput = false,
|
|
26520
|
+
variant = 'default',
|
|
26521
|
+
size = 'md',
|
|
26522
|
+
showTimestamps = true,
|
|
26523
|
+
enableAttachments = false,
|
|
26524
|
+
enableContextPicker = false,
|
|
26525
|
+
selectedContextElements = [],
|
|
26526
|
+
onContextPickerClick,
|
|
26527
|
+
onRemoveContextElement,
|
|
26528
|
+
isLoading = false,
|
|
26529
|
+
loadingText = 'Loading...',
|
|
26530
|
+
styles = {},
|
|
26531
|
+
maxHeight = '600px',
|
|
26532
|
+
internalInputValue,
|
|
26533
|
+
handleInputChange,
|
|
26534
|
+
handleSubmit,
|
|
26535
|
+
inputRef,
|
|
26536
|
+
messagesRef
|
|
26537
|
+
} = _ref,
|
|
26538
|
+
props = _objectWithoutPropertiesLoose(_ref, _excluded$1p);
|
|
26539
|
+
// Combine styles
|
|
26540
|
+
var containerStyles = Object.assign({}, DefaultChatWidgetStyles.container, Variants$4[variant], styles.container);
|
|
26541
|
+
var messagesContainerStyles = Object.assign({}, DefaultChatWidgetStyles.messagesContainer, {
|
|
26542
|
+
maxHeight
|
|
26543
|
+
}, styles.messagesContainer);
|
|
26544
|
+
var inputContainerStyles = Object.assign({}, DefaultChatWidgetStyles.inputContainer, styles.inputContainer);
|
|
26545
|
+
var inputStyles = Object.assign({}, DefaultChatWidgetStyles.input, Sizes$5[size], styles.input);
|
|
26546
|
+
// Auto-resize textarea
|
|
26547
|
+
var handleTextareaChange = React.useCallback(e => {
|
|
26548
|
+
handleInputChange(e.target.value);
|
|
26549
|
+
// Auto-resize
|
|
26550
|
+
e.target.style.height = 'auto';
|
|
26551
|
+
e.target.style.height = e.target.scrollHeight + "px";
|
|
26552
|
+
}, [handleInputChange]);
|
|
26553
|
+
// Handle Enter key to submit
|
|
26554
|
+
var handleKeyDown = React.useCallback(e => {
|
|
26555
|
+
if (e.key === 'Enter' && !e.shiftKey) {
|
|
26556
|
+
e.preventDefault();
|
|
26557
|
+
handleSubmit();
|
|
26558
|
+
}
|
|
26559
|
+
}, [handleSubmit]);
|
|
26560
|
+
var hasText = internalInputValue.trim().length > 0;
|
|
26561
|
+
// Separate onSubmit from other props to avoid type conflict
|
|
26562
|
+
var viewProps = _objectWithoutPropertiesLoose(props, _excluded2$n);
|
|
26563
|
+
return /*#__PURE__*/React__default.createElement(appStudio.View, Object.assign({}, containerStyles, viewProps), /*#__PURE__*/React__default.createElement(appStudio.View, Object.assign({
|
|
26564
|
+
ref: messagesRef
|
|
26565
|
+
}, messagesContainerStyles), messages.length === 0 ? (/*#__PURE__*/React__default.createElement(appStudio.View, {
|
|
26566
|
+
display: "flex",
|
|
26567
|
+
alignItems: "center",
|
|
26568
|
+
justifyContent: "center",
|
|
26569
|
+
flex: 1,
|
|
26570
|
+
color: "color.gray.400"
|
|
26571
|
+
}, /*#__PURE__*/React__default.createElement(appStudio.Text, {
|
|
26572
|
+
fontSize: "14px"
|
|
26573
|
+
}, "No messages yet. Start a conversation!"))) : messages.map(message => (/*#__PURE__*/React__default.createElement(ChatBubble, {
|
|
26574
|
+
key: message.id,
|
|
26575
|
+
message: message,
|
|
26576
|
+
size: size,
|
|
26577
|
+
showTimestamp: showTimestamps,
|
|
26578
|
+
styles: {
|
|
26579
|
+
bubble: styles.bubble,
|
|
26580
|
+
userBubble: styles.userBubble,
|
|
26581
|
+
assistantBubble: styles.assistantBubble,
|
|
26582
|
+
timestamp: styles.timestamp,
|
|
26583
|
+
reasoningContainer: styles.reasoningContainer,
|
|
26584
|
+
reasoningContent: styles.reasoningContent,
|
|
26585
|
+
errorMessage: styles.errorMessage,
|
|
26586
|
+
systemMessage: styles.systemMessage,
|
|
26587
|
+
toolMessage: styles.toolMessage
|
|
26588
|
+
}
|
|
26589
|
+
}))), isLoading && (/*#__PURE__*/React__default.createElement(appStudio.Horizontal, Object.assign({
|
|
26590
|
+
justifyContent: "flex-start",
|
|
26591
|
+
alignItems: "center",
|
|
26592
|
+
gap: 8,
|
|
26593
|
+
marginTop: "8px"
|
|
26594
|
+
}, styles.loadingIndicator), /*#__PURE__*/React__default.createElement(LoadingSpinnerIcon, {
|
|
26595
|
+
widthHeight: 12,
|
|
26596
|
+
color: "currentColor",
|
|
26597
|
+
filled: false,
|
|
26598
|
+
style: {
|
|
26599
|
+
animation: 'spin 1s linear infinite'
|
|
26600
|
+
}
|
|
26601
|
+
}), /*#__PURE__*/React__default.createElement(appStudio.Text, {
|
|
26602
|
+
color: "color.gray.500",
|
|
26603
|
+
fontSize: "14px"
|
|
26604
|
+
}, loadingText)))), /*#__PURE__*/React__default.createElement(appStudio.View, null, selectedContextElements.length > 0 && (/*#__PURE__*/React__default.createElement(appStudio.Horizontal, Object.assign({
|
|
26605
|
+
gap: 8,
|
|
26606
|
+
marginBottom: "8px",
|
|
26607
|
+
flexWrap: "wrap",
|
|
26608
|
+
paddingHorizontal: "20px"
|
|
26609
|
+
}, styles.contextChipsContainer), selectedContextElements.map(element => (/*#__PURE__*/React__default.createElement(appStudio.Horizontal, {
|
|
26610
|
+
key: element.id,
|
|
26611
|
+
backgroundColor: "rgba(37, 99, 235, 0.1)",
|
|
26612
|
+
border: "1px solid rgba(37, 99, 235, 0.2)",
|
|
26613
|
+
borderRadius: "6px",
|
|
26614
|
+
padding: "4px 8px",
|
|
26615
|
+
alignItems: "center",
|
|
26616
|
+
gap: 6
|
|
26617
|
+
}, /*#__PURE__*/React__default.createElement(appStudio.Text, {
|
|
26618
|
+
fontSize: "12px",
|
|
26619
|
+
color: "color.blue.700",
|
|
26620
|
+
fontWeight: "500"
|
|
26621
|
+
}, element.name), /*#__PURE__*/React__default.createElement(appStudio.View, {
|
|
26622
|
+
as: "button",
|
|
26623
|
+
type: "button",
|
|
26624
|
+
onClick: () => onRemoveContextElement == null ? void 0 : onRemoveContextElement(element.id),
|
|
26625
|
+
cursor: "pointer",
|
|
26626
|
+
border: "none",
|
|
26627
|
+
backgroundColor: "transparent",
|
|
26628
|
+
display: "flex",
|
|
26629
|
+
alignItems: "center"
|
|
26630
|
+
}, /*#__PURE__*/React__default.createElement(CloseIcon, {
|
|
26631
|
+
widthHeight: 12,
|
|
26632
|
+
color: "color.blue.700"
|
|
26633
|
+
}))))))), /*#__PURE__*/React__default.createElement(appStudio.View, Object.assign({
|
|
26634
|
+
as: "form",
|
|
26635
|
+
onSubmit: handleSubmit
|
|
26636
|
+
}, inputContainerStyles), enableAttachments && (/*#__PURE__*/React__default.createElement(appStudio.View, Object.assign({
|
|
26637
|
+
as: "button",
|
|
26638
|
+
type: "button"
|
|
26639
|
+
}, DefaultChatWidgetStyles.attachmentButton, styles.attachmentButton, {
|
|
26640
|
+
_hover: {
|
|
26641
|
+
backgroundColor: 'color.gray.100'
|
|
26642
|
+
}
|
|
26643
|
+
}), /*#__PURE__*/React__default.createElement(AttachmentIcon, {
|
|
26644
|
+
widthHeight: 16,
|
|
26645
|
+
color: "color.gray.600"
|
|
26646
|
+
}))), /*#__PURE__*/React__default.createElement(appStudio.View, Object.assign({
|
|
26647
|
+
as: "textarea",
|
|
26648
|
+
ref: inputRef,
|
|
26649
|
+
value: internalInputValue,
|
|
26650
|
+
onChange: handleTextareaChange,
|
|
26651
|
+
onKeyDown: handleKeyDown,
|
|
26652
|
+
placeholder: inputPlaceholder,
|
|
26653
|
+
disabled: disableInput || isLoading
|
|
26654
|
+
}, inputStyles, {
|
|
26655
|
+
style: Object.assign({}, inputStyles, {
|
|
26656
|
+
opacity: disableInput || isLoading ? 0.5 : 1
|
|
26657
|
+
})
|
|
26658
|
+
})), /*#__PURE__*/React__default.createElement(appStudio.Vertical, {
|
|
26659
|
+
gap: 4,
|
|
26660
|
+
alignItems: "center"
|
|
26661
|
+
}, enableContextPicker && (/*#__PURE__*/React__default.createElement(appStudio.View, Object.assign({
|
|
26662
|
+
as: "button",
|
|
26663
|
+
type: "button",
|
|
26664
|
+
onClick: onContextPickerClick
|
|
26665
|
+
}, DefaultChatWidgetStyles.attachmentButton, styles.contextPickerButton, {
|
|
26666
|
+
_hover: Object.assign({
|
|
26667
|
+
backgroundColor: 'color.gray.100'
|
|
26668
|
+
}, (_styles$contextPicker = styles.contextPickerButton) == null ? void 0 : _styles$contextPicker._hover),
|
|
26669
|
+
title: "Select element from page"
|
|
26670
|
+
}), /*#__PURE__*/React__default.createElement(MousePointerIcon, {
|
|
26671
|
+
widthHeight: 16,
|
|
26672
|
+
color: "color.gray.600"
|
|
26673
|
+
}))), /*#__PURE__*/React__default.createElement(appStudio.View, Object.assign({
|
|
26674
|
+
as: "button",
|
|
26675
|
+
type: "submit",
|
|
26676
|
+
disabled: !hasText || disableInput || isLoading
|
|
26677
|
+
}, DefaultChatWidgetStyles.sendButton, {
|
|
26678
|
+
backgroundColor: hasText ? 'theme.primary' : 'color.gray.300',
|
|
26679
|
+
_hover: {
|
|
26680
|
+
backgroundColor: hasText ? 'color.blue.600' : 'color.gray.300'
|
|
26681
|
+
}
|
|
26682
|
+
}, styles.sendButton, {
|
|
26683
|
+
style: {
|
|
26684
|
+
cursor: hasText ? 'pointer' : 'not-allowed',
|
|
26685
|
+
opacity: !hasText || disableInput || isLoading ? 0.6 : 1
|
|
26686
|
+
}
|
|
26687
|
+
}), /*#__PURE__*/React__default.createElement(SendIcon, {
|
|
26688
|
+
widthHeight: 16,
|
|
26689
|
+
color: "color.white",
|
|
26690
|
+
filled: false
|
|
26691
|
+
}))))));
|
|
26692
|
+
};
|
|
26693
|
+
var ChatBubble = _ref2 => {
|
|
26694
|
+
var {
|
|
26695
|
+
message,
|
|
26696
|
+
size,
|
|
26697
|
+
showTimestamp,
|
|
26698
|
+
styles
|
|
26699
|
+
} = _ref2;
|
|
26700
|
+
var [showTimestampOverlay, setShowTimestampOverlay] = React__default.useState(false);
|
|
26701
|
+
var [isReasoningOpen, setIsReasoningOpen] = React__default.useState(false);
|
|
26702
|
+
var isUser = message.role === 'user';
|
|
26703
|
+
var isSystem = message.messageType === 'system';
|
|
26704
|
+
var isError = message.messageType === 'error';
|
|
26705
|
+
var isTool = message.messageType === 'tool';
|
|
26706
|
+
// System Message Rendering
|
|
26707
|
+
if (isSystem) {
|
|
26708
|
+
return /*#__PURE__*/React__default.createElement(appStudio.View, Object.assign({
|
|
26709
|
+
display: "flex",
|
|
26710
|
+
justifyContent: "center",
|
|
26711
|
+
padding: "8px",
|
|
26712
|
+
width: "100%"
|
|
26713
|
+
}, styles.systemMessage), /*#__PURE__*/React__default.createElement(appStudio.Horizontal, {
|
|
26714
|
+
gap: 6,
|
|
26715
|
+
alignItems: "center",
|
|
26716
|
+
opacity: 0.7
|
|
26717
|
+
}, /*#__PURE__*/React__default.createElement(InfoIcon, {
|
|
26718
|
+
widthHeight: 12,
|
|
26719
|
+
color: "color.gray.600"
|
|
26720
|
+
}), /*#__PURE__*/React__default.createElement(appStudio.Text, {
|
|
26721
|
+
fontSize: "12px",
|
|
26722
|
+
color: "color.gray.600",
|
|
26723
|
+
fontStyle: "italic"
|
|
26724
|
+
}, message.content)));
|
|
26725
|
+
}
|
|
26726
|
+
// Tool Message Rendering
|
|
26727
|
+
if (isTool) {
|
|
26728
|
+
return /*#__PURE__*/React__default.createElement(appStudio.View, Object.assign({
|
|
26729
|
+
display: "flex",
|
|
26730
|
+
justifyContent: "flex-start",
|
|
26731
|
+
padding: "8px 16px",
|
|
26732
|
+
width: "100%"
|
|
26733
|
+
}, styles.toolMessage), /*#__PURE__*/React__default.createElement(appStudio.Horizontal, {
|
|
26734
|
+
gap: 8,
|
|
26735
|
+
alignItems: "center",
|
|
26736
|
+
backgroundColor: "rgba(0,0,0,0.03)",
|
|
26737
|
+
padding: "8px",
|
|
26738
|
+
borderRadius: "8px",
|
|
26739
|
+
width: "100%",
|
|
26740
|
+
border: "1px solid rgba(0,0,0,0.05)"
|
|
26741
|
+
}, /*#__PURE__*/React__default.createElement(SettingsIcon, {
|
|
26742
|
+
widthHeight: 14,
|
|
26743
|
+
color: "color.gray.600"
|
|
26744
|
+
}), /*#__PURE__*/React__default.createElement(appStudio.Vertical, {
|
|
26745
|
+
gap: 2
|
|
26746
|
+
}, /*#__PURE__*/React__default.createElement(appStudio.Text, {
|
|
26747
|
+
fontSize: "11px",
|
|
26748
|
+
fontWeight: "600",
|
|
26749
|
+
color: "color.gray.700"
|
|
26750
|
+
}, "Tool Usage"), /*#__PURE__*/React__default.createElement(appStudio.Text, {
|
|
26751
|
+
fontSize: "12px",
|
|
26752
|
+
color: "color.gray.600",
|
|
26753
|
+
fontFamily: "monospace"
|
|
26754
|
+
}, message.content))));
|
|
26755
|
+
}
|
|
26756
|
+
// Bubble Styles construction
|
|
26757
|
+
var bubbleStyles = Object.assign({}, DefaultChatWidgetStyles.bubble, BubbleSizes[size], isUser ? UserBubbleStyles : AssistantBubbleStyles, isError ? {
|
|
26758
|
+
backgroundColor: 'rgba(239, 68, 68, 0.1)',
|
|
26759
|
+
border: '1px solid rgba(239, 68, 68, 0.2)',
|
|
26760
|
+
color: '#b91c1c'
|
|
26761
|
+
} : {}, styles.bubble, isUser ? styles.userBubble : styles.assistantBubble, isError ? styles.errorMessage : {});
|
|
26762
|
+
var timestampStyles = Object.assign({}, DefaultChatWidgetStyles.timestamp, {
|
|
26763
|
+
[isUser ? 'right' : 'left']: '8px',
|
|
26764
|
+
opacity: showTimestampOverlay ? 1 : 0
|
|
26765
|
+
}, styles.timestamp);
|
|
26766
|
+
return /*#__PURE__*/React__default.createElement(appStudio.View, {
|
|
26767
|
+
position: "relative",
|
|
26768
|
+
onMouseEnter: () => setShowTimestampOverlay(true),
|
|
26769
|
+
onMouseLeave: () => setShowTimestampOverlay(false),
|
|
26770
|
+
display: "flex",
|
|
26771
|
+
justifyContent: isUser ? 'flex-end' : 'flex-start'
|
|
26772
|
+
}, /*#__PURE__*/React__default.createElement(appStudio.View, Object.assign({}, bubbleStyles), showTimestamp && (/*#__PURE__*/React__default.createElement(appStudio.View, Object.assign({}, timestampStyles), message.timestamp.toLocaleTimeString([], {
|
|
26773
|
+
hour: '2-digit',
|
|
26774
|
+
minute: '2-digit'
|
|
26775
|
+
}))), isError && (/*#__PURE__*/React__default.createElement(appStudio.Horizontal, {
|
|
26776
|
+
gap: 6,
|
|
26777
|
+
marginBottom: "4px",
|
|
26778
|
+
alignItems: "center"
|
|
26779
|
+
}, /*#__PURE__*/React__default.createElement(ErrorIcon, {
|
|
26780
|
+
widthHeight: 14,
|
|
26781
|
+
color: "#b91c1c"
|
|
26782
|
+
}), /*#__PURE__*/React__default.createElement(appStudio.Text, {
|
|
26783
|
+
fontWeight: "600",
|
|
26784
|
+
fontSize: "12px"
|
|
26785
|
+
}, "Error"))), message.reasoning && (/*#__PURE__*/React__default.createElement(appStudio.View, Object.assign({
|
|
26786
|
+
marginBottom: "8px",
|
|
26787
|
+
borderBottom: "1px solid rgba(0,0,0,0.05)",
|
|
26788
|
+
paddingBottom: "8px"
|
|
26789
|
+
}, styles.reasoningContainer), /*#__PURE__*/React__default.createElement(appStudio.Horizontal, {
|
|
26790
|
+
as: "button",
|
|
26791
|
+
onClick: () => setIsReasoningOpen(!isReasoningOpen),
|
|
26792
|
+
cursor: "pointer",
|
|
26793
|
+
gap: 4,
|
|
26794
|
+
alignItems: "center",
|
|
26795
|
+
backgroundColor: "transparent",
|
|
26796
|
+
border: "none",
|
|
26797
|
+
padding: 0
|
|
26798
|
+
}, /*#__PURE__*/React__default.createElement(appStudio.Text, {
|
|
26799
|
+
fontSize: "11px",
|
|
26800
|
+
color: "color.gray.500",
|
|
26801
|
+
fontWeight: "600"
|
|
26802
|
+
}, "Thinking Process"), /*#__PURE__*/React__default.createElement(ChevronIcon, {
|
|
26803
|
+
orientation: isReasoningOpen ? 'down' : 'right',
|
|
26804
|
+
widthHeight: 10,
|
|
26805
|
+
color: "color.gray.500"
|
|
26806
|
+
})), isReasoningOpen && (/*#__PURE__*/React__default.createElement(appStudio.View, Object.assign({
|
|
26807
|
+
padding: "8px",
|
|
26808
|
+
backgroundColor: "rgba(0,0,0,0.03)",
|
|
26809
|
+
borderRadius: "8px",
|
|
26810
|
+
marginTop: "4px"
|
|
26811
|
+
}, styles.reasoningContent), /*#__PURE__*/React__default.createElement(appStudio.Text, {
|
|
26812
|
+
fontSize: "12px",
|
|
26813
|
+
color: "color.gray.600",
|
|
26814
|
+
fontStyle: "italic"
|
|
26815
|
+
}, message.reasoning))))), /*#__PURE__*/React__default.createElement(appStudio.View, {
|
|
26816
|
+
whiteSpace: "pre-wrap",
|
|
26817
|
+
wordBreak: "break-word"
|
|
26818
|
+
}, message.content), message.attachments && message.attachments.length > 0 && (/*#__PURE__*/React__default.createElement(appStudio.Vertical, {
|
|
26819
|
+
gap: 4,
|
|
26820
|
+
marginTop: "8px"
|
|
26821
|
+
}, message.attachments.map(attachment => (/*#__PURE__*/React__default.createElement(appStudio.Horizontal, {
|
|
26822
|
+
key: attachment.id,
|
|
26823
|
+
gap: 6,
|
|
26824
|
+
padding: "6px 8px",
|
|
26825
|
+
backgroundColor: "rgba(0, 0, 0, 0.05)",
|
|
26826
|
+
borderRadius: "8px",
|
|
26827
|
+
fontSize: "12px"
|
|
26828
|
+
}, /*#__PURE__*/React__default.createElement(AttachmentIcon, {
|
|
26829
|
+
widthHeight: 14
|
|
26830
|
+
}), /*#__PURE__*/React__default.createElement(appStudio.Text, null, attachment.name)))))), message.contextElements && message.contextElements.length > 0 && (/*#__PURE__*/React__default.createElement(appStudio.Vertical, {
|
|
26831
|
+
gap: 4,
|
|
26832
|
+
marginTop: "8px"
|
|
26833
|
+
}, /*#__PURE__*/React__default.createElement(appStudio.Text, {
|
|
26834
|
+
fontSize: "11px",
|
|
26835
|
+
color: "rgba(0,0,0,0.5)",
|
|
26836
|
+
fontWeight: "600"
|
|
26837
|
+
}, "Context:"), message.contextElements.map(element => (/*#__PURE__*/React__default.createElement(appStudio.Horizontal, {
|
|
26838
|
+
key: element.id,
|
|
26839
|
+
gap: 6,
|
|
26840
|
+
padding: "4px 8px",
|
|
26841
|
+
backgroundColor: "rgba(37, 99, 235, 0.1)",
|
|
26842
|
+
borderRadius: "6px",
|
|
26843
|
+
fontSize: "11px",
|
|
26844
|
+
border: "1px solid rgba(37, 99, 235, 0.2)"
|
|
26845
|
+
}, /*#__PURE__*/React__default.createElement(appStudio.Text, {
|
|
26846
|
+
color: "color.blue.700",
|
|
26847
|
+
fontWeight: "500"
|
|
26848
|
+
}, element.name))))))));
|
|
26849
|
+
};
|
|
26850
|
+
|
|
26851
|
+
/**
|
|
26852
|
+
* ChatWidget Component
|
|
26853
|
+
*
|
|
26854
|
+
* A configurable chat interface component inspired by the ChatWidget toolbar design.
|
|
26855
|
+
* This is a UI-only component without backend/LLM connections.
|
|
26856
|
+
*
|
|
26857
|
+
* @example
|
|
26858
|
+
* ```tsx
|
|
26859
|
+
* <ChatWidget
|
|
26860
|
+
* messages={messages}
|
|
26861
|
+
* onSubmit={(message) => console.log(message)}
|
|
26862
|
+
* variant="glassy"
|
|
26863
|
+
* size="md"
|
|
26864
|
+
* />
|
|
26865
|
+
* ```
|
|
26866
|
+
*/
|
|
26867
|
+
var ChatWidgetComponent = props => {
|
|
26868
|
+
var state = useChatWidgetState(props);
|
|
26869
|
+
return /*#__PURE__*/React__default.createElement(ChatWidgetView, Object.assign({}, props, state));
|
|
26870
|
+
};
|
|
26871
|
+
ChatWidgetComponent.displayName = 'ChatWidget';
|
|
26872
|
+
var ChatWidget = ChatWidgetComponent;
|
|
26873
|
+
|
|
26874
|
+
function useContextSelector(_ref) {
|
|
26875
|
+
var {
|
|
26876
|
+
onSelect,
|
|
26877
|
+
onCancel,
|
|
26878
|
+
active
|
|
26879
|
+
} = _ref;
|
|
26880
|
+
var [highlightedElement, setHighlightedElement] = React.useState(null);
|
|
26881
|
+
var overlayRef = React.useRef(null);
|
|
26882
|
+
// Handle mouse move to consistently highlight elements
|
|
26883
|
+
var handleMouseMove = React.useCallback(e => {
|
|
26884
|
+
var _target$innerText;
|
|
26885
|
+
if (!active) return;
|
|
26886
|
+
var target = document.elementFromPoint(e.clientX, e.clientY);
|
|
26887
|
+
// Ignore if targeting the overlay itself or the widget
|
|
26888
|
+
if (!target || target === document.body || target.closest('[data-chatwidget-ignore="true"]') || target.closest('#chatwidget-overlay')) {
|
|
26889
|
+
setHighlightedElement(null);
|
|
26890
|
+
return;
|
|
26891
|
+
}
|
|
26892
|
+
var rect = target.getBoundingClientRect();
|
|
26893
|
+
// Compute a helpful name
|
|
26894
|
+
var name = target.tagName.toLowerCase();
|
|
26895
|
+
if (target.id) name += "#" + target.id;else if (target.className && typeof target.className === 'string') {
|
|
26896
|
+
// Just take the first class for brevity
|
|
26897
|
+
var firstClass = target.className.split(' ')[0];
|
|
26898
|
+
if (firstClass) name += "." + firstClass;
|
|
26899
|
+
}
|
|
26900
|
+
// Get some text content if available for better context
|
|
26901
|
+
var text = (_target$innerText = target.innerText) == null ? void 0 : _target$innerText.slice(0, 20);
|
|
26902
|
+
if (text) name += " (\"" + text + "...\")";
|
|
26903
|
+
setHighlightedElement({
|
|
26904
|
+
id: target.id || "el-" + Date.now(),
|
|
26905
|
+
name,
|
|
26906
|
+
tagName: target.tagName.toLowerCase(),
|
|
26907
|
+
rect
|
|
26908
|
+
});
|
|
26909
|
+
}, [active]);
|
|
26910
|
+
// Handle click to select
|
|
26911
|
+
var handleClick = React.useCallback(e => {
|
|
26912
|
+
if (!active) return;
|
|
26913
|
+
// If clicking inside the widget, don't trigger selection
|
|
26914
|
+
var target = e.target;
|
|
26915
|
+
if (target.closest('[data-chatwidget-ignore="true"]')) {
|
|
26916
|
+
return;
|
|
26917
|
+
}
|
|
26918
|
+
e.preventDefault();
|
|
26919
|
+
e.stopPropagation();
|
|
26920
|
+
if (highlightedElement) {
|
|
26921
|
+
onSelect(highlightedElement);
|
|
26922
|
+
}
|
|
26923
|
+
}, [active, highlightedElement, onSelect]);
|
|
26924
|
+
// Handle escape to cancel
|
|
26925
|
+
var handleKeyDown = React.useCallback(e => {
|
|
26926
|
+
if (!active) return;
|
|
26927
|
+
if (e.key === 'Escape') {
|
|
26928
|
+
onCancel();
|
|
26929
|
+
}
|
|
26930
|
+
}, [active, onCancel]);
|
|
26931
|
+
React.useEffect(() => {
|
|
26932
|
+
if (active) {
|
|
26933
|
+
document.addEventListener('mousemove', handleMouseMove);
|
|
26934
|
+
document.addEventListener('click', handleClick, true); // Capture phase to prevent default
|
|
26935
|
+
document.addEventListener('keydown', handleKeyDown);
|
|
26936
|
+
document.body.style.cursor = 'crosshair';
|
|
26937
|
+
} else {
|
|
26938
|
+
setHighlightedElement(null);
|
|
26939
|
+
document.removeEventListener('mousemove', handleMouseMove);
|
|
26940
|
+
document.removeEventListener('click', handleClick, true);
|
|
26941
|
+
document.removeEventListener('keydown', handleKeyDown);
|
|
26942
|
+
document.body.style.cursor = '';
|
|
26943
|
+
}
|
|
26944
|
+
return () => {
|
|
26945
|
+
document.removeEventListener('mousemove', handleMouseMove);
|
|
26946
|
+
document.removeEventListener('click', handleClick, true);
|
|
26947
|
+
document.removeEventListener('keydown', handleKeyDown);
|
|
26948
|
+
document.body.style.cursor = '';
|
|
26949
|
+
};
|
|
26950
|
+
}, [active, handleMouseMove, handleClick, handleKeyDown]);
|
|
26951
|
+
return {
|
|
26952
|
+
highlightedElement
|
|
26953
|
+
};
|
|
26954
|
+
}
|
|
26955
|
+
/**
|
|
26956
|
+
* Overlay component to render the highlight box
|
|
26957
|
+
*/
|
|
26958
|
+
function ContextOverlay(_ref2) {
|
|
26959
|
+
var {
|
|
26960
|
+
element
|
|
26961
|
+
} = _ref2;
|
|
26962
|
+
if (!element) return null;
|
|
26963
|
+
return /*#__PURE__*/React__default.createElement("div", {
|
|
26964
|
+
id: "chatwidget-overlay",
|
|
26965
|
+
style: {
|
|
26966
|
+
position: 'fixed',
|
|
26967
|
+
top: element.rect.top,
|
|
26968
|
+
left: element.rect.left,
|
|
26969
|
+
width: element.rect.width,
|
|
26970
|
+
height: element.rect.height,
|
|
26971
|
+
border: '2px solid #2563eb',
|
|
26972
|
+
backgroundColor: 'rgba(37, 99, 235, 0.1)',
|
|
26973
|
+
pointerEvents: 'none',
|
|
26974
|
+
zIndex: 99999,
|
|
26975
|
+
transition: 'all 0.1s ease-out',
|
|
26976
|
+
borderRadius: '4px'
|
|
26977
|
+
}
|
|
26978
|
+
}, /*#__PURE__*/React__default.createElement("div", {
|
|
26979
|
+
style: {
|
|
26980
|
+
position: 'absolute',
|
|
26981
|
+
top: '-24px',
|
|
26982
|
+
left: '0',
|
|
26983
|
+
backgroundColor: '#2563eb',
|
|
26984
|
+
color: 'white',
|
|
26985
|
+
padding: '2px 8px',
|
|
26986
|
+
borderRadius: '4px',
|
|
26987
|
+
fontSize: '12px',
|
|
26988
|
+
fontWeight: 'bold',
|
|
26989
|
+
whiteSpace: 'nowrap'
|
|
26990
|
+
}
|
|
26991
|
+
}, element.name));
|
|
26992
|
+
}
|
|
26993
|
+
|
|
26994
|
+
/**
|
|
26995
|
+
* ChatWidget Widget Component
|
|
26996
|
+
* A floating chat widget with DOM element selection capabilities.
|
|
26997
|
+
*/
|
|
26998
|
+
var ChatWidgetWidget = _ref => {
|
|
26999
|
+
var {
|
|
27000
|
+
initialMessages = [],
|
|
27001
|
+
onSendMessage,
|
|
27002
|
+
bubbleSize = 'md'
|
|
27003
|
+
} = _ref;
|
|
27004
|
+
var [isOpen, setIsOpen] = React.useState(false);
|
|
27005
|
+
var [isContextPickerActive, setIsContextPickerActive] = React.useState(false);
|
|
27006
|
+
var [messages, setMessages] = React.useState(initialMessages);
|
|
27007
|
+
var [contextElements, setContextElements] = React.useState([]);
|
|
27008
|
+
// Hook for context selection
|
|
27009
|
+
var {
|
|
27010
|
+
highlightedElement
|
|
27011
|
+
} = useContextSelector({
|
|
27012
|
+
active: isContextPickerActive,
|
|
27013
|
+
onSelect: element => {
|
|
27014
|
+
setContextElements(prev => [...prev, element]);
|
|
27015
|
+
setIsContextPickerActive(false);
|
|
27016
|
+
setIsOpen(true); // Re-open chat after selection
|
|
27017
|
+
},
|
|
27018
|
+
onCancel: () => {
|
|
27019
|
+
setIsContextPickerActive(false);
|
|
27020
|
+
setIsOpen(true);
|
|
27021
|
+
}
|
|
27022
|
+
});
|
|
27023
|
+
var toggleOpen = () => setIsOpen(!isOpen);
|
|
27024
|
+
var handleContextPickerClick = () => {
|
|
27025
|
+
setIsContextPickerActive(true);
|
|
27026
|
+
setIsOpen(false); // Minimize chat while picking
|
|
27027
|
+
};
|
|
27028
|
+
var handleRemoveContextElement = id => {
|
|
27029
|
+
setContextElements(prev => prev.filter(el => el.id !== id));
|
|
27030
|
+
};
|
|
27031
|
+
var handleSubmit = content => {
|
|
27032
|
+
// Add user message
|
|
27033
|
+
var newMessage = {
|
|
27034
|
+
id: Date.now().toString(),
|
|
27035
|
+
role: 'user',
|
|
27036
|
+
content,
|
|
27037
|
+
timestamp: new Date(),
|
|
27038
|
+
contextElements: [...contextElements]
|
|
27039
|
+
};
|
|
27040
|
+
setMessages(prev => [...prev, newMessage]);
|
|
27041
|
+
onSendMessage == null || onSendMessage(content, contextElements);
|
|
27042
|
+
// Clear context after sending
|
|
27043
|
+
setContextElements([]);
|
|
27044
|
+
// Simulate assistant response
|
|
27045
|
+
setTimeout(() => {
|
|
27046
|
+
var _newMessage$contextEl;
|
|
27047
|
+
var isToolCall = Math.random() > 0.7;
|
|
27048
|
+
var hasReasoning = Math.random() > 0.4;
|
|
27049
|
+
var assistantMessage = {
|
|
27050
|
+
id: (Date.now() + 1).toString(),
|
|
27051
|
+
role: 'assistant',
|
|
27052
|
+
timestamp: new Date(),
|
|
27053
|
+
content: isToolCall ? 'I will highlight the selected element.' : "I received your message regarding: " + (((_newMessage$contextEl = newMessage.contextElements) == null ? void 0 : _newMessage$contextEl.map(e => e.name).join(', ')) || 'general context') + ". How can I assist you further?",
|
|
27054
|
+
messageType: isToolCall ? 'tool' : 'text',
|
|
27055
|
+
reasoning: hasReasoning ? 'Analyzing the user input and context... The user seems to be asking about specific elements. I should tailor my response to the selected context.' : undefined
|
|
27056
|
+
};
|
|
27057
|
+
setMessages(prev => [...prev, assistantMessage]);
|
|
27058
|
+
if (isToolCall) {
|
|
27059
|
+
// Add a follow-up system message after a tool call
|
|
27060
|
+
setTimeout(() => {
|
|
27061
|
+
setMessages(prev => [...prev, {
|
|
27062
|
+
id: (Date.now() + 2).toString(),
|
|
27063
|
+
role: 'assistant',
|
|
27064
|
+
messageType: 'system',
|
|
27065
|
+
content: 'Tool "highlightElement" executed successfully.',
|
|
27066
|
+
timestamp: new Date()
|
|
27067
|
+
}]);
|
|
27068
|
+
}, 800);
|
|
27069
|
+
}
|
|
27070
|
+
}, 1000);
|
|
27071
|
+
};
|
|
27072
|
+
return /*#__PURE__*/React__default.createElement(appStudio.View, {
|
|
27073
|
+
position: "fixed",
|
|
27074
|
+
bottom: 24,
|
|
27075
|
+
right: 24,
|
|
27076
|
+
zIndex: 9999
|
|
27077
|
+
}, /*#__PURE__*/React__default.createElement(ContextOverlay, {
|
|
27078
|
+
element: highlightedElement
|
|
27079
|
+
}), isContextPickerActive && (/*#__PURE__*/React__default.createElement(appStudio.View, {
|
|
27080
|
+
position: "fixed",
|
|
27081
|
+
top: 24,
|
|
27082
|
+
left: "50%",
|
|
27083
|
+
transform: "translateX(-50%)",
|
|
27084
|
+
backgroundColor: "rgba(0,0,0,0.8)",
|
|
27085
|
+
color: "white",
|
|
27086
|
+
padding: "8px 16px",
|
|
27087
|
+
borderRadius: "24px",
|
|
27088
|
+
zIndex: 10000,
|
|
27089
|
+
boxShadow: "0 4px 6px rgba(0,0,0,0.1)"
|
|
27090
|
+
}, /*#__PURE__*/React__default.createElement(appStudio.Text, {
|
|
27091
|
+
fontWeight: "600",
|
|
27092
|
+
fontSize: "14px"
|
|
27093
|
+
}, "Click an element to select it. Press ESC to cancel."))), isOpen && (/*#__PURE__*/React__default.createElement(appStudio.View, {
|
|
27094
|
+
position: "absolute",
|
|
27095
|
+
bottom: 60,
|
|
27096
|
+
right: 0,
|
|
27097
|
+
width: "400px",
|
|
27098
|
+
height: "600px",
|
|
27099
|
+
marginBottom: "16px",
|
|
27100
|
+
backgroundColor: "rgba(255, 255, 255, 0.8)",
|
|
27101
|
+
backdropFilter: "blur(20px)",
|
|
27102
|
+
borderRadius: "24px",
|
|
27103
|
+
border: "1px solid rgba(255, 255, 255, 0.4)",
|
|
27104
|
+
boxShadow: "0 25px 50px -12px rgba(0, 0, 0, 0.25)",
|
|
27105
|
+
overflow: "hidden",
|
|
27106
|
+
animation: "slideUp 0.3s ease-out",
|
|
27107
|
+
style: {
|
|
27108
|
+
animation: 'fadeIn 0.2s ease-out',
|
|
27109
|
+
transformOrigin: 'bottom right'
|
|
27110
|
+
}
|
|
27111
|
+
}, /*#__PURE__*/React__default.createElement(appStudio.View, {
|
|
27112
|
+
padding: "16px",
|
|
27113
|
+
borderBottom: "1px solid rgba(0,0,0,0.05)",
|
|
27114
|
+
display: "flex",
|
|
27115
|
+
justifyContent: "space-between",
|
|
27116
|
+
alignItems: "center"
|
|
27117
|
+
}, /*#__PURE__*/React__default.createElement(appStudio.Text, {
|
|
27118
|
+
fontWeight: "bold",
|
|
27119
|
+
color: "color.gray.800"
|
|
27120
|
+
}, "ChatWidget Assistant"), /*#__PURE__*/React__default.createElement(appStudio.View, {
|
|
27121
|
+
as: "button",
|
|
27122
|
+
onClick: () => setIsOpen(false),
|
|
27123
|
+
cursor: "pointer",
|
|
27124
|
+
padding: "4px",
|
|
27125
|
+
borderRadius: "50%",
|
|
27126
|
+
border: "none",
|
|
27127
|
+
backgroundColor: "transparent",
|
|
27128
|
+
_hover: {
|
|
27129
|
+
backgroundColor: 'rgba(0,0,0,0.05)'
|
|
27130
|
+
}
|
|
27131
|
+
}, /*#__PURE__*/React__default.createElement(CloseIcon, {
|
|
27132
|
+
widthHeight: 16,
|
|
27133
|
+
color: "color.gray.500"
|
|
27134
|
+
}))), /*#__PURE__*/React__default.createElement(ChatWidget, {
|
|
27135
|
+
messages: messages,
|
|
27136
|
+
onSubmit: handleSubmit,
|
|
27137
|
+
size: bubbleSize,
|
|
27138
|
+
variant: "minimal",
|
|
27139
|
+
enableContextPicker: true,
|
|
27140
|
+
selectedContextElements: contextElements,
|
|
27141
|
+
onContextPickerClick: handleContextPickerClick,
|
|
27142
|
+
onRemoveContextElement: handleRemoveContextElement,
|
|
27143
|
+
styles: {
|
|
27144
|
+
container: {
|
|
27145
|
+
height: 'calc(100% - 60px)',
|
|
27146
|
+
backgroundColor: 'transparent'
|
|
27147
|
+
},
|
|
27148
|
+
inputContainer: {
|
|
27149
|
+
backgroundColor: 'white',
|
|
27150
|
+
margin: '0 16px 16px 16px',
|
|
27151
|
+
boxShadow: '0 4px 6px -1px rgba(0, 0, 0, 0.1)'
|
|
27152
|
+
}
|
|
27153
|
+
}
|
|
27154
|
+
}))), !isContextPickerActive && (/*#__PURE__*/React__default.createElement(appStudio.View, {
|
|
27155
|
+
as: "button",
|
|
27156
|
+
onClick: toggleOpen,
|
|
27157
|
+
width: "56px",
|
|
27158
|
+
height: "56px",
|
|
27159
|
+
borderRadius: "50%",
|
|
27160
|
+
backgroundColor: "theme.primary",
|
|
27161
|
+
border: "none",
|
|
27162
|
+
boxShadow: "0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)",
|
|
27163
|
+
cursor: "pointer",
|
|
27164
|
+
display: "flex",
|
|
27165
|
+
alignItems: "center",
|
|
27166
|
+
justifyContent: "center",
|
|
27167
|
+
transition: "transform 0.2s ease",
|
|
27168
|
+
_hover: {
|
|
27169
|
+
transform: 'scale(1.05)'
|
|
27170
|
+
},
|
|
27171
|
+
_active: {
|
|
27172
|
+
transform: 'scale(0.95)'
|
|
27173
|
+
},
|
|
27174
|
+
"data-chatwidget-ignore": "true" // Ignore clicks on the widget itself for context picking
|
|
27175
|
+
}, isOpen ? (/*#__PURE__*/React__default.createElement(CloseIcon, {
|
|
27176
|
+
widthHeight: 24,
|
|
27177
|
+
color: "white"
|
|
27178
|
+
})) : (/*#__PURE__*/React__default.createElement(PanelIcon, {
|
|
27179
|
+
widthHeight: 24,
|
|
27180
|
+
color: "white"
|
|
27181
|
+
})))));
|
|
27182
|
+
};
|
|
27183
|
+
|
|
26263
27184
|
exports.Accordion = Accordion;
|
|
26264
27185
|
exports.Alert = Alert;
|
|
26265
27186
|
exports.ArrowIcon = ArrowIcon;
|
|
@@ -26285,6 +27206,9 @@
|
|
|
26285
27206
|
exports.Chart = Chart;
|
|
26286
27207
|
exports.ChartIcon = ChartIcon;
|
|
26287
27208
|
exports.ChatInput = ChatInput;
|
|
27209
|
+
exports.ChatWidget = ChatWidget;
|
|
27210
|
+
exports.ChatWidgetComponent = ChatWidgetComponent;
|
|
27211
|
+
exports.ChatWidgetWidget = ChatWidgetWidget;
|
|
26288
27212
|
exports.CheckIcon = CheckIcon;
|
|
26289
27213
|
exports.Checkbox = Checkbox;
|
|
26290
27214
|
exports.ChevronIcon = ChevronIcon;
|
|
@@ -26371,6 +27295,7 @@
|
|
|
26371
27295
|
exports.Modal = Modal;
|
|
26372
27296
|
exports.MoonIcon = MoonIcon;
|
|
26373
27297
|
exports.MoreIcon = MoreIcon;
|
|
27298
|
+
exports.MousePointerIcon = MousePointerIcon;
|
|
26374
27299
|
exports.NavigationMenu = NavigationMenu;
|
|
26375
27300
|
exports.NotificationIcon = NotificationIcon;
|
|
26376
27301
|
exports.OTPInput = OTPInput;
|