@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
package/dist/web.esm.js
CHANGED
|
@@ -808,6 +808,9 @@ var ZoomInIcon = /*#__PURE__*/createIcon('zoom-in', {
|
|
|
808
808
|
var DragHandleLinesIcon = /*#__PURE__*/createIcon('grip-horizontal', {
|
|
809
809
|
filled: false
|
|
810
810
|
});
|
|
811
|
+
var MousePointerIcon = /*#__PURE__*/createIcon('mouse-pointer-2', {
|
|
812
|
+
filled: false
|
|
813
|
+
});
|
|
811
814
|
|
|
812
815
|
/**
|
|
813
816
|
* Alert Styles
|
|
@@ -3313,7 +3316,7 @@ var ButtonView = _ref5 => {
|
|
|
3313
3316
|
var mainColorKey = (_ref6 = backgroundColor != null ? backgroundColor : color) != null ? _ref6 : 'theme.button.background';
|
|
3314
3317
|
// Decide which theme token to resolve based on state
|
|
3315
3318
|
var stateColorKey = isDisabled ? 'theme.disabled' : isLoading ? 'theme.loading' : mainColorKey;
|
|
3316
|
-
// Resolve to actual hex color.
|
|
3319
|
+
// Resolve to actual hex color.
|
|
3317
3320
|
// If 'theme.button.background' isn't defined, it falls back to 'theme.primary'
|
|
3318
3321
|
var mainTone = getColorHex(stateColorKey);
|
|
3319
3322
|
if (mainTone === 'theme.button.background' || mainTone === 'theme.loading') {
|
|
@@ -16652,40 +16655,46 @@ Table.Template = TableView;
|
|
|
16652
16655
|
* @param defaultValue - The optional title of the tab to be initially active.
|
|
16653
16656
|
* @returns An object containing the current activeTab and a function to update it.
|
|
16654
16657
|
*/
|
|
16655
|
-
var useTabsState = (propTabs, defaultValue) => {
|
|
16658
|
+
var useTabsState = (propTabs, defaultValue, value) => {
|
|
16659
|
+
// Helper to extract the identifier (value or title) from a tab
|
|
16660
|
+
var getTabId = tab => tab.value !== undefined ? tab.value : tab.title;
|
|
16656
16661
|
// Find the initial tab based on defaultValue, or default to the first tab.
|
|
16657
|
-
// Ensure propTabs is not empty before accessing index 0.
|
|
16658
16662
|
var findInitialTab = () => {
|
|
16659
16663
|
if (!propTabs || propTabs.length === 0) {
|
|
16660
|
-
return undefined;
|
|
16664
|
+
return undefined;
|
|
16661
16665
|
}
|
|
16662
16666
|
if (defaultValue !== undefined) {
|
|
16663
|
-
var foundTab = propTabs.find(tab => tab
|
|
16667
|
+
var foundTab = propTabs.find(tab => getTabId(tab) === defaultValue);
|
|
16664
16668
|
if (foundTab) {
|
|
16665
16669
|
return foundTab;
|
|
16666
16670
|
}
|
|
16667
|
-
// Warn if defaultValue is provided but not found
|
|
16668
|
-
// console.warn(
|
|
16669
|
-
// `Tabs: defaultValue "${defaultValue}" not found in tabs. Defaulting to the first tab.`
|
|
16670
|
-
// );
|
|
16671
16671
|
}
|
|
16672
|
-
return propTabs[0];
|
|
16672
|
+
return propTabs[0];
|
|
16673
16673
|
};
|
|
16674
|
-
var [
|
|
16675
|
-
//
|
|
16676
|
-
//
|
|
16674
|
+
var [internalActiveTab, setInternalActiveTab] = useState(findInitialTab());
|
|
16675
|
+
// Determine the effective active tab
|
|
16676
|
+
// In controlled mode (value provided), find the tab matching value.
|
|
16677
|
+
// In uncontrolled mode, use internal state.
|
|
16678
|
+
var activeTab = value !== undefined ? propTabs.find(tab => getTabId(tab) === value) : internalActiveTab;
|
|
16679
|
+
var setActiveTab = tab => {
|
|
16680
|
+
// Only update internal state if uncontrolled
|
|
16681
|
+
if (value === undefined) {
|
|
16682
|
+
setInternalActiveTab(tab);
|
|
16683
|
+
}
|
|
16684
|
+
};
|
|
16685
|
+
// Effect to update internal active tab if defaultValue changes or tabs change
|
|
16677
16686
|
useEffect(() => {
|
|
16687
|
+
if (value !== undefined) return; // Skip logic if controlled
|
|
16678
16688
|
var newInitialTab = findInitialTab();
|
|
16679
|
-
|
|
16680
|
-
//
|
|
16681
|
-
|
|
16682
|
-
if (newInitialTab && (!currentActiveTabStillValid || defaultValue !== undefined &&
|
|
16683
|
-
|
|
16684
|
-
} else if (!newInitialTab &&
|
|
16685
|
-
|
|
16686
|
-
|
|
16687
|
-
|
|
16688
|
-
}, [propTabs, defaultValue]); // Rerun when tabs or initial title changes
|
|
16689
|
+
var currentActiveTabStillValid = internalActiveTab && propTabs.some(t => getTabId(t) === getTabId(internalActiveTab));
|
|
16690
|
+
// If current tab is invalid, or if defaultValue changed and suggests a different tab
|
|
16691
|
+
// (Note: The original logic forced reset on defaultValue change, we keep that behavior)
|
|
16692
|
+
if (newInitialTab && (!currentActiveTabStillValid || defaultValue !== undefined && internalActiveTab && getTabId(internalActiveTab) !== defaultValue)) {
|
|
16693
|
+
setInternalActiveTab(newInitialTab);
|
|
16694
|
+
} else if (!newInitialTab && internalActiveTab) {
|
|
16695
|
+
setInternalActiveTab(undefined);
|
|
16696
|
+
}
|
|
16697
|
+
}, [propTabs, defaultValue]); // Remove internalActiveTab dependency to avoid loops, though it shouldn't cause one if guarded
|
|
16689
16698
|
return {
|
|
16690
16699
|
activeTab,
|
|
16691
16700
|
setActiveTab
|
|
@@ -16772,6 +16781,10 @@ var TabHeader = _ref => {
|
|
|
16772
16781
|
var getGap = () => {
|
|
16773
16782
|
return ['top', 'bottom'].includes(iconPosition) ? '4px' : '8px';
|
|
16774
16783
|
};
|
|
16784
|
+
// Clone icon to apply active styles (e.g. bold stroke) if valid
|
|
16785
|
+
var iconElement = tab.icon && /*#__PURE__*/React.isValidElement(tab.icon) ? /*#__PURE__*/React.cloneElement(tab.icon, {
|
|
16786
|
+
strokeWidth: isActive ? 2.5 : 2
|
|
16787
|
+
}) : tab.icon;
|
|
16775
16788
|
return /*#__PURE__*/React.createElement(Element, Object.assign({
|
|
16776
16789
|
as: "div",
|
|
16777
16790
|
role: "tab",
|
|
@@ -16782,7 +16795,23 @@ var TabHeader = _ref => {
|
|
|
16782
16795
|
gap: getGap(),
|
|
16783
16796
|
onClick: onClick,
|
|
16784
16797
|
"data-state": isActive ? 'active' : 'inactive'
|
|
16785
|
-
}),
|
|
16798
|
+
}), iconElement && (/*#__PURE__*/React.createElement(Element, {
|
|
16799
|
+
key: isActive ? 'active-icon' : 'inactive-icon'
|
|
16800
|
+
}, iconElement)), /*#__PURE__*/React.createElement(Element, {
|
|
16801
|
+
display: "grid",
|
|
16802
|
+
alignItems: "center",
|
|
16803
|
+
justifyContent: "center"
|
|
16804
|
+
}, /*#__PURE__*/React.createElement(Text, Object.assign({}, textStyles, {
|
|
16805
|
+
fontWeight: "600",
|
|
16806
|
+
visibility: "hidden",
|
|
16807
|
+
gridColumn: "1",
|
|
16808
|
+
gridRow: "1",
|
|
16809
|
+
"aria-hidden": "true"
|
|
16810
|
+
}), tab.title), /*#__PURE__*/React.createElement(Text, Object.assign({}, textStyles, {
|
|
16811
|
+
fontWeight: isActive ? '600' : '500',
|
|
16812
|
+
gridColumn: "1",
|
|
16813
|
+
gridRow: "1"
|
|
16814
|
+
}), tab.title)));
|
|
16786
16815
|
};
|
|
16787
16816
|
|
|
16788
16817
|
/**
|
|
@@ -16818,7 +16847,7 @@ var TabsView = _ref => {
|
|
|
16818
16847
|
borderBottomColor: "color.gray.200"
|
|
16819
16848
|
}, views.headerTabs), tabs.map(tab => {
|
|
16820
16849
|
// Determine if the current tab in the loop is the active one
|
|
16821
|
-
var isActive = tab.title === activeTab.title;
|
|
16850
|
+
var isActive = (tab.value !== undefined ? tab.value : tab.title) === (activeTab.value !== undefined ? activeTab.value : activeTab.title);
|
|
16822
16851
|
// Prepare the onClick handler for this specific tab
|
|
16823
16852
|
var onClick = () => handleTabClick(tab);
|
|
16824
16853
|
// Use the custom renderTab function if provided
|
|
@@ -16937,7 +16966,7 @@ var TabsComponent = _ref => {
|
|
|
16937
16966
|
// For compound component pattern
|
|
16938
16967
|
var compoundState = useTabsCompoundState(defaultValue, value, onValueChange);
|
|
16939
16968
|
// For data-driven pattern
|
|
16940
|
-
var dataState = useTabsState(tabs || [], defaultValue);
|
|
16969
|
+
var dataState = useTabsState(tabs || [], defaultValue, value);
|
|
16941
16970
|
// If using compound component pattern (children provided)
|
|
16942
16971
|
if (children) {
|
|
16943
16972
|
return /*#__PURE__*/React.createElement(TabsContext.Provider, {
|
|
@@ -16948,9 +16977,9 @@ var TabsComponent = _ref => {
|
|
|
16948
16977
|
if (tabs) {
|
|
16949
16978
|
// Handler function to change the active tab and trigger the callback
|
|
16950
16979
|
var handleTabClick = tab => {
|
|
16951
|
-
var
|
|
16980
|
+
var getTabId = t => t.value !== undefined ? t.value : t.title;
|
|
16952
16981
|
// Only update state and call callback if the clicked tab is different from the current one
|
|
16953
|
-
if (
|
|
16982
|
+
if (!dataState.activeTab || getTabId(dataState.activeTab) !== getTabId(tab)) {
|
|
16954
16983
|
dataState.setActiveTab(tab);
|
|
16955
16984
|
// Call the onTabChange callback if provided
|
|
16956
16985
|
if (onTabChange) {
|
|
@@ -26293,5 +26322,897 @@ var Background = /*#__PURE__*/Object.assign(BackgroundComponent, {
|
|
|
26293
26322
|
});
|
|
26294
26323
|
Background.displayName = 'Background';
|
|
26295
26324
|
|
|
26296
|
-
|
|
26325
|
+
/**
|
|
26326
|
+
* Custom hook for managing ChatWidget component state
|
|
26327
|
+
*/
|
|
26328
|
+
function useChatWidgetState(props) {
|
|
26329
|
+
var {
|
|
26330
|
+
inputValue,
|
|
26331
|
+
onInputChange,
|
|
26332
|
+
onSubmit,
|
|
26333
|
+
messages = []
|
|
26334
|
+
} = props;
|
|
26335
|
+
// Internal state for uncontrolled input
|
|
26336
|
+
var [internalInputValue, setInternalInputValue] = useState('');
|
|
26337
|
+
// Refs
|
|
26338
|
+
var inputRef = useRef(null);
|
|
26339
|
+
var messagesRef = useRef(null);
|
|
26340
|
+
// Determine if the component is controlled
|
|
26341
|
+
var isControlled = inputValue !== undefined;
|
|
26342
|
+
// Get the current input value
|
|
26343
|
+
var currentInputValue = inputValue !== undefined ? inputValue : internalInputValue;
|
|
26344
|
+
// Handle input changes
|
|
26345
|
+
var handleInputChange = useCallback(value => {
|
|
26346
|
+
if (isControlled) {
|
|
26347
|
+
onInputChange == null || onInputChange(value);
|
|
26348
|
+
} else {
|
|
26349
|
+
setInternalInputValue(value);
|
|
26350
|
+
}
|
|
26351
|
+
}, [isControlled, onInputChange]);
|
|
26352
|
+
// Handle message submission
|
|
26353
|
+
var handleSubmit = useCallback(e => {
|
|
26354
|
+
if (e) {
|
|
26355
|
+
e.preventDefault();
|
|
26356
|
+
}
|
|
26357
|
+
var trimmedValue = currentInputValue.trim();
|
|
26358
|
+
if (trimmedValue && onSubmit) {
|
|
26359
|
+
onSubmit(trimmedValue);
|
|
26360
|
+
// Clear input after submission (only for uncontrolled)
|
|
26361
|
+
if (!isControlled) {
|
|
26362
|
+
setInternalInputValue('');
|
|
26363
|
+
}
|
|
26364
|
+
// Reset textarea height
|
|
26365
|
+
if (inputRef.current) {
|
|
26366
|
+
inputRef.current.style.height = 'auto';
|
|
26367
|
+
}
|
|
26368
|
+
}
|
|
26369
|
+
}, [currentInputValue, onSubmit, isControlled]);
|
|
26370
|
+
// Auto-scroll to bottom when new messages arrive
|
|
26371
|
+
useEffect(() => {
|
|
26372
|
+
if (messagesRef.current) {
|
|
26373
|
+
messagesRef.current.scrollTop = messagesRef.current.scrollHeight;
|
|
26374
|
+
}
|
|
26375
|
+
}, [messages.length]);
|
|
26376
|
+
return {
|
|
26377
|
+
internalInputValue: currentInputValue,
|
|
26378
|
+
handleInputChange,
|
|
26379
|
+
handleSubmit,
|
|
26380
|
+
inputRef,
|
|
26381
|
+
messagesRef
|
|
26382
|
+
};
|
|
26383
|
+
}
|
|
26384
|
+
|
|
26385
|
+
/** Size mappings for the ChatWidget component */
|
|
26386
|
+
var Sizes$5 = {
|
|
26387
|
+
sm: {
|
|
26388
|
+
fontSize: '13px',
|
|
26389
|
+
padding: '8px'
|
|
26390
|
+
},
|
|
26391
|
+
md: {
|
|
26392
|
+
fontSize: '14px',
|
|
26393
|
+
padding: '12px'
|
|
26394
|
+
},
|
|
26395
|
+
lg: {
|
|
26396
|
+
fontSize: '16px',
|
|
26397
|
+
padding: '16px'
|
|
26398
|
+
}
|
|
26399
|
+
};
|
|
26400
|
+
/** Variant mappings for the ChatWidget component */
|
|
26401
|
+
var Variants$4 = {
|
|
26402
|
+
default: {
|
|
26403
|
+
backgroundColor: '#ffffff',
|
|
26404
|
+
border: '1px solid #e5e7eb',
|
|
26405
|
+
borderRadius: '16px'
|
|
26406
|
+
},
|
|
26407
|
+
glassy: {
|
|
26408
|
+
backgroundColor: 'rgba(255, 255, 255, 0.6)',
|
|
26409
|
+
backdropFilter: 'blur(12px)',
|
|
26410
|
+
border: '1px solid rgba(0, 0, 0, 0.1)',
|
|
26411
|
+
borderRadius: '16px',
|
|
26412
|
+
boxShadow: '0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)'
|
|
26413
|
+
},
|
|
26414
|
+
minimal: {
|
|
26415
|
+
backgroundColor: 'transparent',
|
|
26416
|
+
border: 'none'
|
|
26417
|
+
}
|
|
26418
|
+
};
|
|
26419
|
+
/** Bubble size mappings */
|
|
26420
|
+
var BubbleSizes = {
|
|
26421
|
+
sm: {
|
|
26422
|
+
fontSize: '13px',
|
|
26423
|
+
padding: '6px 10px',
|
|
26424
|
+
borderRadius: '14px'
|
|
26425
|
+
},
|
|
26426
|
+
md: {
|
|
26427
|
+
fontSize: '14px',
|
|
26428
|
+
padding: '8px 12px',
|
|
26429
|
+
borderRadius: '16px'
|
|
26430
|
+
},
|
|
26431
|
+
lg: {
|
|
26432
|
+
fontSize: '16px',
|
|
26433
|
+
padding: '10px 16px',
|
|
26434
|
+
borderRadius: '18px'
|
|
26435
|
+
}
|
|
26436
|
+
};
|
|
26437
|
+
/** User bubble styles (blue, aligned right) */
|
|
26438
|
+
var UserBubbleStyles = {
|
|
26439
|
+
backgroundColor: 'rgba(37, 99, 235, 0.9)',
|
|
26440
|
+
color: '#ffffff',
|
|
26441
|
+
alignSelf: 'flex-end',
|
|
26442
|
+
borderBottomRightRadius: '4px',
|
|
26443
|
+
boxShadow: '0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06)'
|
|
26444
|
+
};
|
|
26445
|
+
/** Assistant bubble styles (gray, aligned left) */
|
|
26446
|
+
var AssistantBubbleStyles = {
|
|
26447
|
+
backgroundColor: 'rgba(244, 244, 245, 0.6)',
|
|
26448
|
+
color: '#18181b',
|
|
26449
|
+
alignSelf: 'flex-start',
|
|
26450
|
+
borderBottomLeftRadius: '4px',
|
|
26451
|
+
boxShadow: '0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06)'
|
|
26452
|
+
};
|
|
26453
|
+
/** Input container styles with glassmorphic effect */
|
|
26454
|
+
var InputContainerStyles = {
|
|
26455
|
+
position: 'relative',
|
|
26456
|
+
backgroundColor: 'rgba(244, 244, 245, 0.05)',
|
|
26457
|
+
backdropFilter: 'blur(12px)',
|
|
26458
|
+
borderRadius: '16px',
|
|
26459
|
+
border: '1px solid rgba(0, 0, 0, 0.1)',
|
|
26460
|
+
boxShadow: '0 4px 6px -1px rgba(0, 0, 0, 0.1)',
|
|
26461
|
+
padding: '8px 12px',
|
|
26462
|
+
display: 'flex',
|
|
26463
|
+
alignItems: 'flex-end',
|
|
26464
|
+
gap: '8px',
|
|
26465
|
+
transition: 'all 0.2s ease'
|
|
26466
|
+
};
|
|
26467
|
+
/** Default ChatWidget component styles */
|
|
26468
|
+
var DefaultChatWidgetStyles = {
|
|
26469
|
+
container: {
|
|
26470
|
+
display: 'flex',
|
|
26471
|
+
flexDirection: 'column',
|
|
26472
|
+
width: '100%',
|
|
26473
|
+
height: '100%',
|
|
26474
|
+
overflow: 'hidden'
|
|
26475
|
+
},
|
|
26476
|
+
messagesContainer: {
|
|
26477
|
+
flex: 1,
|
|
26478
|
+
overflowY: 'auto',
|
|
26479
|
+
display: 'flex',
|
|
26480
|
+
flexDirection: 'column',
|
|
26481
|
+
gap: '8px',
|
|
26482
|
+
padding: '16px'
|
|
26483
|
+
},
|
|
26484
|
+
inputContainer: InputContainerStyles,
|
|
26485
|
+
bubble: {
|
|
26486
|
+
maxWidth: '80%',
|
|
26487
|
+
position: 'relative',
|
|
26488
|
+
wordWrap: 'break-word',
|
|
26489
|
+
animation: 'chatBubbleAppear 0.3s ease-out'
|
|
26490
|
+
},
|
|
26491
|
+
timestamp: {
|
|
26492
|
+
position: 'absolute',
|
|
26493
|
+
top: '-24px',
|
|
26494
|
+
fontSize: '12px',
|
|
26495
|
+
color: 'rgba(0, 0, 0, 0.5)',
|
|
26496
|
+
backgroundColor: 'rgba(255, 255, 255, 0.9)',
|
|
26497
|
+
padding: '2px 8px',
|
|
26498
|
+
borderRadius: '9999px',
|
|
26499
|
+
opacity: 0,
|
|
26500
|
+
transition: 'opacity 0.15s ease-out',
|
|
26501
|
+
boxShadow: '0 1px 2px 0 rgba(0, 0, 0, 0.05)'
|
|
26502
|
+
},
|
|
26503
|
+
input: {
|
|
26504
|
+
flex: 1,
|
|
26505
|
+
border: 'none',
|
|
26506
|
+
outline: 'none',
|
|
26507
|
+
backgroundColor: 'transparent',
|
|
26508
|
+
resize: 'none',
|
|
26509
|
+
fontFamily: 'inherit',
|
|
26510
|
+
fontSize: '14px',
|
|
26511
|
+
minHeight: '24px',
|
|
26512
|
+
maxHeight: '120px'
|
|
26513
|
+
},
|
|
26514
|
+
sendButton: {
|
|
26515
|
+
width: '32px',
|
|
26516
|
+
height: '32px',
|
|
26517
|
+
borderRadius: '50%',
|
|
26518
|
+
border: 'none',
|
|
26519
|
+
cursor: 'pointer',
|
|
26520
|
+
display: 'flex',
|
|
26521
|
+
alignItems: 'center',
|
|
26522
|
+
justifyContent: 'center',
|
|
26523
|
+
transition: 'all 0.2s ease',
|
|
26524
|
+
flexShrink: 0
|
|
26525
|
+
},
|
|
26526
|
+
attachmentButton: {
|
|
26527
|
+
width: '32px',
|
|
26528
|
+
height: '32px',
|
|
26529
|
+
borderRadius: '50%',
|
|
26530
|
+
border: 'none',
|
|
26531
|
+
cursor: 'pointer',
|
|
26532
|
+
display: 'flex',
|
|
26533
|
+
alignItems: 'center',
|
|
26534
|
+
justifyContent: 'center',
|
|
26535
|
+
backgroundColor: 'transparent',
|
|
26536
|
+
transition: 'background-color 0.2s ease',
|
|
26537
|
+
flexShrink: 0
|
|
26538
|
+
}
|
|
26539
|
+
};
|
|
26540
|
+
|
|
26541
|
+
var _excluded$1p = ["messages", "inputPlaceholder", "disableInput", "variant", "size", "showTimestamps", "enableAttachments", "enableContextPicker", "selectedContextElements", "onContextPickerClick", "onRemoveContextElement", "isLoading", "loadingText", "styles", "maxHeight", "internalInputValue", "handleInputChange", "handleSubmit", "inputRef", "messagesRef"],
|
|
26542
|
+
_excluded2$n = ["onSubmit"];
|
|
26543
|
+
/**
|
|
26544
|
+
* ChatWidget View Component
|
|
26545
|
+
* Presentational component for the ChatWidget interface
|
|
26546
|
+
*/
|
|
26547
|
+
var ChatWidgetView = _ref => {
|
|
26548
|
+
var _styles$contextPicker;
|
|
26549
|
+
var {
|
|
26550
|
+
messages = [],
|
|
26551
|
+
inputPlaceholder = 'Type a message...',
|
|
26552
|
+
disableInput = false,
|
|
26553
|
+
variant = 'default',
|
|
26554
|
+
size = 'md',
|
|
26555
|
+
showTimestamps = true,
|
|
26556
|
+
enableAttachments = false,
|
|
26557
|
+
enableContextPicker = false,
|
|
26558
|
+
selectedContextElements = [],
|
|
26559
|
+
onContextPickerClick,
|
|
26560
|
+
onRemoveContextElement,
|
|
26561
|
+
isLoading = false,
|
|
26562
|
+
loadingText = 'Loading...',
|
|
26563
|
+
styles = {},
|
|
26564
|
+
maxHeight = '600px',
|
|
26565
|
+
internalInputValue,
|
|
26566
|
+
handleInputChange,
|
|
26567
|
+
handleSubmit,
|
|
26568
|
+
inputRef,
|
|
26569
|
+
messagesRef
|
|
26570
|
+
} = _ref,
|
|
26571
|
+
props = _objectWithoutPropertiesLoose(_ref, _excluded$1p);
|
|
26572
|
+
// Combine styles
|
|
26573
|
+
var containerStyles = Object.assign({}, DefaultChatWidgetStyles.container, Variants$4[variant], styles.container);
|
|
26574
|
+
var messagesContainerStyles = Object.assign({}, DefaultChatWidgetStyles.messagesContainer, {
|
|
26575
|
+
maxHeight
|
|
26576
|
+
}, styles.messagesContainer);
|
|
26577
|
+
var inputContainerStyles = Object.assign({}, DefaultChatWidgetStyles.inputContainer, styles.inputContainer);
|
|
26578
|
+
var inputStyles = Object.assign({}, DefaultChatWidgetStyles.input, Sizes$5[size], styles.input);
|
|
26579
|
+
// Auto-resize textarea
|
|
26580
|
+
var handleTextareaChange = useCallback(e => {
|
|
26581
|
+
handleInputChange(e.target.value);
|
|
26582
|
+
// Auto-resize
|
|
26583
|
+
e.target.style.height = 'auto';
|
|
26584
|
+
e.target.style.height = e.target.scrollHeight + "px";
|
|
26585
|
+
}, [handleInputChange]);
|
|
26586
|
+
// Handle Enter key to submit
|
|
26587
|
+
var handleKeyDown = useCallback(e => {
|
|
26588
|
+
if (e.key === 'Enter' && !e.shiftKey) {
|
|
26589
|
+
e.preventDefault();
|
|
26590
|
+
handleSubmit();
|
|
26591
|
+
}
|
|
26592
|
+
}, [handleSubmit]);
|
|
26593
|
+
var hasText = internalInputValue.trim().length > 0;
|
|
26594
|
+
// Separate onSubmit from other props to avoid type conflict
|
|
26595
|
+
var viewProps = _objectWithoutPropertiesLoose(props, _excluded2$n);
|
|
26596
|
+
return /*#__PURE__*/React.createElement(View, Object.assign({}, containerStyles, viewProps), /*#__PURE__*/React.createElement(View, Object.assign({
|
|
26597
|
+
ref: messagesRef
|
|
26598
|
+
}, messagesContainerStyles), messages.length === 0 ? (/*#__PURE__*/React.createElement(View, {
|
|
26599
|
+
display: "flex",
|
|
26600
|
+
alignItems: "center",
|
|
26601
|
+
justifyContent: "center",
|
|
26602
|
+
flex: 1,
|
|
26603
|
+
color: "color.gray.400"
|
|
26604
|
+
}, /*#__PURE__*/React.createElement(Text, {
|
|
26605
|
+
fontSize: "14px"
|
|
26606
|
+
}, "No messages yet. Start a conversation!"))) : messages.map(message => (/*#__PURE__*/React.createElement(ChatBubble, {
|
|
26607
|
+
key: message.id,
|
|
26608
|
+
message: message,
|
|
26609
|
+
size: size,
|
|
26610
|
+
showTimestamp: showTimestamps,
|
|
26611
|
+
styles: {
|
|
26612
|
+
bubble: styles.bubble,
|
|
26613
|
+
userBubble: styles.userBubble,
|
|
26614
|
+
assistantBubble: styles.assistantBubble,
|
|
26615
|
+
timestamp: styles.timestamp,
|
|
26616
|
+
reasoningContainer: styles.reasoningContainer,
|
|
26617
|
+
reasoningContent: styles.reasoningContent,
|
|
26618
|
+
errorMessage: styles.errorMessage,
|
|
26619
|
+
systemMessage: styles.systemMessage,
|
|
26620
|
+
toolMessage: styles.toolMessage
|
|
26621
|
+
}
|
|
26622
|
+
}))), isLoading && (/*#__PURE__*/React.createElement(Horizontal, Object.assign({
|
|
26623
|
+
justifyContent: "flex-start",
|
|
26624
|
+
alignItems: "center",
|
|
26625
|
+
gap: 8,
|
|
26626
|
+
marginTop: "8px"
|
|
26627
|
+
}, styles.loadingIndicator), /*#__PURE__*/React.createElement(LoadingSpinnerIcon, {
|
|
26628
|
+
widthHeight: 12,
|
|
26629
|
+
color: "currentColor",
|
|
26630
|
+
filled: false,
|
|
26631
|
+
style: {
|
|
26632
|
+
animation: 'spin 1s linear infinite'
|
|
26633
|
+
}
|
|
26634
|
+
}), /*#__PURE__*/React.createElement(Text, {
|
|
26635
|
+
color: "color.gray.500",
|
|
26636
|
+
fontSize: "14px"
|
|
26637
|
+
}, loadingText)))), /*#__PURE__*/React.createElement(View, null, selectedContextElements.length > 0 && (/*#__PURE__*/React.createElement(Horizontal, Object.assign({
|
|
26638
|
+
gap: 8,
|
|
26639
|
+
marginBottom: "8px",
|
|
26640
|
+
flexWrap: "wrap",
|
|
26641
|
+
paddingHorizontal: "20px"
|
|
26642
|
+
}, styles.contextChipsContainer), selectedContextElements.map(element => (/*#__PURE__*/React.createElement(Horizontal, {
|
|
26643
|
+
key: element.id,
|
|
26644
|
+
backgroundColor: "rgba(37, 99, 235, 0.1)",
|
|
26645
|
+
border: "1px solid rgba(37, 99, 235, 0.2)",
|
|
26646
|
+
borderRadius: "6px",
|
|
26647
|
+
padding: "4px 8px",
|
|
26648
|
+
alignItems: "center",
|
|
26649
|
+
gap: 6
|
|
26650
|
+
}, /*#__PURE__*/React.createElement(Text, {
|
|
26651
|
+
fontSize: "12px",
|
|
26652
|
+
color: "color.blue.700",
|
|
26653
|
+
fontWeight: "500"
|
|
26654
|
+
}, element.name), /*#__PURE__*/React.createElement(View, {
|
|
26655
|
+
as: "button",
|
|
26656
|
+
type: "button",
|
|
26657
|
+
onClick: () => onRemoveContextElement == null ? void 0 : onRemoveContextElement(element.id),
|
|
26658
|
+
cursor: "pointer",
|
|
26659
|
+
border: "none",
|
|
26660
|
+
backgroundColor: "transparent",
|
|
26661
|
+
display: "flex",
|
|
26662
|
+
alignItems: "center"
|
|
26663
|
+
}, /*#__PURE__*/React.createElement(CloseIcon, {
|
|
26664
|
+
widthHeight: 12,
|
|
26665
|
+
color: "color.blue.700"
|
|
26666
|
+
}))))))), /*#__PURE__*/React.createElement(View, Object.assign({
|
|
26667
|
+
as: "form",
|
|
26668
|
+
onSubmit: handleSubmit
|
|
26669
|
+
}, inputContainerStyles), enableAttachments && (/*#__PURE__*/React.createElement(View, Object.assign({
|
|
26670
|
+
as: "button",
|
|
26671
|
+
type: "button"
|
|
26672
|
+
}, DefaultChatWidgetStyles.attachmentButton, styles.attachmentButton, {
|
|
26673
|
+
_hover: {
|
|
26674
|
+
backgroundColor: 'color.gray.100'
|
|
26675
|
+
}
|
|
26676
|
+
}), /*#__PURE__*/React.createElement(AttachmentIcon, {
|
|
26677
|
+
widthHeight: 16,
|
|
26678
|
+
color: "color.gray.600"
|
|
26679
|
+
}))), /*#__PURE__*/React.createElement(View, Object.assign({
|
|
26680
|
+
as: "textarea",
|
|
26681
|
+
ref: inputRef,
|
|
26682
|
+
value: internalInputValue,
|
|
26683
|
+
onChange: handleTextareaChange,
|
|
26684
|
+
onKeyDown: handleKeyDown,
|
|
26685
|
+
placeholder: inputPlaceholder,
|
|
26686
|
+
disabled: disableInput || isLoading
|
|
26687
|
+
}, inputStyles, {
|
|
26688
|
+
style: Object.assign({}, inputStyles, {
|
|
26689
|
+
opacity: disableInput || isLoading ? 0.5 : 1
|
|
26690
|
+
})
|
|
26691
|
+
})), /*#__PURE__*/React.createElement(Vertical, {
|
|
26692
|
+
gap: 4,
|
|
26693
|
+
alignItems: "center"
|
|
26694
|
+
}, enableContextPicker && (/*#__PURE__*/React.createElement(View, Object.assign({
|
|
26695
|
+
as: "button",
|
|
26696
|
+
type: "button",
|
|
26697
|
+
onClick: onContextPickerClick
|
|
26698
|
+
}, DefaultChatWidgetStyles.attachmentButton, styles.contextPickerButton, {
|
|
26699
|
+
_hover: Object.assign({
|
|
26700
|
+
backgroundColor: 'color.gray.100'
|
|
26701
|
+
}, (_styles$contextPicker = styles.contextPickerButton) == null ? void 0 : _styles$contextPicker._hover),
|
|
26702
|
+
title: "Select element from page"
|
|
26703
|
+
}), /*#__PURE__*/React.createElement(MousePointerIcon, {
|
|
26704
|
+
widthHeight: 16,
|
|
26705
|
+
color: "color.gray.600"
|
|
26706
|
+
}))), /*#__PURE__*/React.createElement(View, Object.assign({
|
|
26707
|
+
as: "button",
|
|
26708
|
+
type: "submit",
|
|
26709
|
+
disabled: !hasText || disableInput || isLoading
|
|
26710
|
+
}, DefaultChatWidgetStyles.sendButton, {
|
|
26711
|
+
backgroundColor: hasText ? 'theme.primary' : 'color.gray.300',
|
|
26712
|
+
_hover: {
|
|
26713
|
+
backgroundColor: hasText ? 'color.blue.600' : 'color.gray.300'
|
|
26714
|
+
}
|
|
26715
|
+
}, styles.sendButton, {
|
|
26716
|
+
style: {
|
|
26717
|
+
cursor: hasText ? 'pointer' : 'not-allowed',
|
|
26718
|
+
opacity: !hasText || disableInput || isLoading ? 0.6 : 1
|
|
26719
|
+
}
|
|
26720
|
+
}), /*#__PURE__*/React.createElement(SendIcon, {
|
|
26721
|
+
widthHeight: 16,
|
|
26722
|
+
color: "color.white",
|
|
26723
|
+
filled: false
|
|
26724
|
+
}))))));
|
|
26725
|
+
};
|
|
26726
|
+
var ChatBubble = _ref2 => {
|
|
26727
|
+
var {
|
|
26728
|
+
message,
|
|
26729
|
+
size,
|
|
26730
|
+
showTimestamp,
|
|
26731
|
+
styles
|
|
26732
|
+
} = _ref2;
|
|
26733
|
+
var [showTimestampOverlay, setShowTimestampOverlay] = React.useState(false);
|
|
26734
|
+
var [isReasoningOpen, setIsReasoningOpen] = React.useState(false);
|
|
26735
|
+
var isUser = message.role === 'user';
|
|
26736
|
+
var isSystem = message.messageType === 'system';
|
|
26737
|
+
var isError = message.messageType === 'error';
|
|
26738
|
+
var isTool = message.messageType === 'tool';
|
|
26739
|
+
// System Message Rendering
|
|
26740
|
+
if (isSystem) {
|
|
26741
|
+
return /*#__PURE__*/React.createElement(View, Object.assign({
|
|
26742
|
+
display: "flex",
|
|
26743
|
+
justifyContent: "center",
|
|
26744
|
+
padding: "8px",
|
|
26745
|
+
width: "100%"
|
|
26746
|
+
}, styles.systemMessage), /*#__PURE__*/React.createElement(Horizontal, {
|
|
26747
|
+
gap: 6,
|
|
26748
|
+
alignItems: "center",
|
|
26749
|
+
opacity: 0.7
|
|
26750
|
+
}, /*#__PURE__*/React.createElement(InfoIcon, {
|
|
26751
|
+
widthHeight: 12,
|
|
26752
|
+
color: "color.gray.600"
|
|
26753
|
+
}), /*#__PURE__*/React.createElement(Text, {
|
|
26754
|
+
fontSize: "12px",
|
|
26755
|
+
color: "color.gray.600",
|
|
26756
|
+
fontStyle: "italic"
|
|
26757
|
+
}, message.content)));
|
|
26758
|
+
}
|
|
26759
|
+
// Tool Message Rendering
|
|
26760
|
+
if (isTool) {
|
|
26761
|
+
return /*#__PURE__*/React.createElement(View, Object.assign({
|
|
26762
|
+
display: "flex",
|
|
26763
|
+
justifyContent: "flex-start",
|
|
26764
|
+
padding: "8px 16px",
|
|
26765
|
+
width: "100%"
|
|
26766
|
+
}, styles.toolMessage), /*#__PURE__*/React.createElement(Horizontal, {
|
|
26767
|
+
gap: 8,
|
|
26768
|
+
alignItems: "center",
|
|
26769
|
+
backgroundColor: "rgba(0,0,0,0.03)",
|
|
26770
|
+
padding: "8px",
|
|
26771
|
+
borderRadius: "8px",
|
|
26772
|
+
width: "100%",
|
|
26773
|
+
border: "1px solid rgba(0,0,0,0.05)"
|
|
26774
|
+
}, /*#__PURE__*/React.createElement(SettingsIcon, {
|
|
26775
|
+
widthHeight: 14,
|
|
26776
|
+
color: "color.gray.600"
|
|
26777
|
+
}), /*#__PURE__*/React.createElement(Vertical, {
|
|
26778
|
+
gap: 2
|
|
26779
|
+
}, /*#__PURE__*/React.createElement(Text, {
|
|
26780
|
+
fontSize: "11px",
|
|
26781
|
+
fontWeight: "600",
|
|
26782
|
+
color: "color.gray.700"
|
|
26783
|
+
}, "Tool Usage"), /*#__PURE__*/React.createElement(Text, {
|
|
26784
|
+
fontSize: "12px",
|
|
26785
|
+
color: "color.gray.600",
|
|
26786
|
+
fontFamily: "monospace"
|
|
26787
|
+
}, message.content))));
|
|
26788
|
+
}
|
|
26789
|
+
// Bubble Styles construction
|
|
26790
|
+
var bubbleStyles = Object.assign({}, DefaultChatWidgetStyles.bubble, BubbleSizes[size], isUser ? UserBubbleStyles : AssistantBubbleStyles, isError ? {
|
|
26791
|
+
backgroundColor: 'rgba(239, 68, 68, 0.1)',
|
|
26792
|
+
border: '1px solid rgba(239, 68, 68, 0.2)',
|
|
26793
|
+
color: '#b91c1c'
|
|
26794
|
+
} : {}, styles.bubble, isUser ? styles.userBubble : styles.assistantBubble, isError ? styles.errorMessage : {});
|
|
26795
|
+
var timestampStyles = Object.assign({}, DefaultChatWidgetStyles.timestamp, {
|
|
26796
|
+
[isUser ? 'right' : 'left']: '8px',
|
|
26797
|
+
opacity: showTimestampOverlay ? 1 : 0
|
|
26798
|
+
}, styles.timestamp);
|
|
26799
|
+
return /*#__PURE__*/React.createElement(View, {
|
|
26800
|
+
position: "relative",
|
|
26801
|
+
onMouseEnter: () => setShowTimestampOverlay(true),
|
|
26802
|
+
onMouseLeave: () => setShowTimestampOverlay(false),
|
|
26803
|
+
display: "flex",
|
|
26804
|
+
justifyContent: isUser ? 'flex-end' : 'flex-start'
|
|
26805
|
+
}, /*#__PURE__*/React.createElement(View, Object.assign({}, bubbleStyles), showTimestamp && (/*#__PURE__*/React.createElement(View, Object.assign({}, timestampStyles), message.timestamp.toLocaleTimeString([], {
|
|
26806
|
+
hour: '2-digit',
|
|
26807
|
+
minute: '2-digit'
|
|
26808
|
+
}))), isError && (/*#__PURE__*/React.createElement(Horizontal, {
|
|
26809
|
+
gap: 6,
|
|
26810
|
+
marginBottom: "4px",
|
|
26811
|
+
alignItems: "center"
|
|
26812
|
+
}, /*#__PURE__*/React.createElement(ErrorIcon, {
|
|
26813
|
+
widthHeight: 14,
|
|
26814
|
+
color: "#b91c1c"
|
|
26815
|
+
}), /*#__PURE__*/React.createElement(Text, {
|
|
26816
|
+
fontWeight: "600",
|
|
26817
|
+
fontSize: "12px"
|
|
26818
|
+
}, "Error"))), message.reasoning && (/*#__PURE__*/React.createElement(View, Object.assign({
|
|
26819
|
+
marginBottom: "8px",
|
|
26820
|
+
borderBottom: "1px solid rgba(0,0,0,0.05)",
|
|
26821
|
+
paddingBottom: "8px"
|
|
26822
|
+
}, styles.reasoningContainer), /*#__PURE__*/React.createElement(Horizontal, {
|
|
26823
|
+
as: "button",
|
|
26824
|
+
onClick: () => setIsReasoningOpen(!isReasoningOpen),
|
|
26825
|
+
cursor: "pointer",
|
|
26826
|
+
gap: 4,
|
|
26827
|
+
alignItems: "center",
|
|
26828
|
+
backgroundColor: "transparent",
|
|
26829
|
+
border: "none",
|
|
26830
|
+
padding: 0
|
|
26831
|
+
}, /*#__PURE__*/React.createElement(Text, {
|
|
26832
|
+
fontSize: "11px",
|
|
26833
|
+
color: "color.gray.500",
|
|
26834
|
+
fontWeight: "600"
|
|
26835
|
+
}, "Thinking Process"), /*#__PURE__*/React.createElement(ChevronIcon, {
|
|
26836
|
+
orientation: isReasoningOpen ? 'down' : 'right',
|
|
26837
|
+
widthHeight: 10,
|
|
26838
|
+
color: "color.gray.500"
|
|
26839
|
+
})), isReasoningOpen && (/*#__PURE__*/React.createElement(View, Object.assign({
|
|
26840
|
+
padding: "8px",
|
|
26841
|
+
backgroundColor: "rgba(0,0,0,0.03)",
|
|
26842
|
+
borderRadius: "8px",
|
|
26843
|
+
marginTop: "4px"
|
|
26844
|
+
}, styles.reasoningContent), /*#__PURE__*/React.createElement(Text, {
|
|
26845
|
+
fontSize: "12px",
|
|
26846
|
+
color: "color.gray.600",
|
|
26847
|
+
fontStyle: "italic"
|
|
26848
|
+
}, message.reasoning))))), /*#__PURE__*/React.createElement(View, {
|
|
26849
|
+
whiteSpace: "pre-wrap",
|
|
26850
|
+
wordBreak: "break-word"
|
|
26851
|
+
}, message.content), message.attachments && message.attachments.length > 0 && (/*#__PURE__*/React.createElement(Vertical, {
|
|
26852
|
+
gap: 4,
|
|
26853
|
+
marginTop: "8px"
|
|
26854
|
+
}, message.attachments.map(attachment => (/*#__PURE__*/React.createElement(Horizontal, {
|
|
26855
|
+
key: attachment.id,
|
|
26856
|
+
gap: 6,
|
|
26857
|
+
padding: "6px 8px",
|
|
26858
|
+
backgroundColor: "rgba(0, 0, 0, 0.05)",
|
|
26859
|
+
borderRadius: "8px",
|
|
26860
|
+
fontSize: "12px"
|
|
26861
|
+
}, /*#__PURE__*/React.createElement(AttachmentIcon, {
|
|
26862
|
+
widthHeight: 14
|
|
26863
|
+
}), /*#__PURE__*/React.createElement(Text, null, attachment.name)))))), message.contextElements && message.contextElements.length > 0 && (/*#__PURE__*/React.createElement(Vertical, {
|
|
26864
|
+
gap: 4,
|
|
26865
|
+
marginTop: "8px"
|
|
26866
|
+
}, /*#__PURE__*/React.createElement(Text, {
|
|
26867
|
+
fontSize: "11px",
|
|
26868
|
+
color: "rgba(0,0,0,0.5)",
|
|
26869
|
+
fontWeight: "600"
|
|
26870
|
+
}, "Context:"), message.contextElements.map(element => (/*#__PURE__*/React.createElement(Horizontal, {
|
|
26871
|
+
key: element.id,
|
|
26872
|
+
gap: 6,
|
|
26873
|
+
padding: "4px 8px",
|
|
26874
|
+
backgroundColor: "rgba(37, 99, 235, 0.1)",
|
|
26875
|
+
borderRadius: "6px",
|
|
26876
|
+
fontSize: "11px",
|
|
26877
|
+
border: "1px solid rgba(37, 99, 235, 0.2)"
|
|
26878
|
+
}, /*#__PURE__*/React.createElement(Text, {
|
|
26879
|
+
color: "color.blue.700",
|
|
26880
|
+
fontWeight: "500"
|
|
26881
|
+
}, element.name))))))));
|
|
26882
|
+
};
|
|
26883
|
+
|
|
26884
|
+
/**
|
|
26885
|
+
* ChatWidget Component
|
|
26886
|
+
*
|
|
26887
|
+
* A configurable chat interface component inspired by the ChatWidget toolbar design.
|
|
26888
|
+
* This is a UI-only component without backend/LLM connections.
|
|
26889
|
+
*
|
|
26890
|
+
* @example
|
|
26891
|
+
* ```tsx
|
|
26892
|
+
* <ChatWidget
|
|
26893
|
+
* messages={messages}
|
|
26894
|
+
* onSubmit={(message) => console.log(message)}
|
|
26895
|
+
* variant="glassy"
|
|
26896
|
+
* size="md"
|
|
26897
|
+
* />
|
|
26898
|
+
* ```
|
|
26899
|
+
*/
|
|
26900
|
+
var ChatWidgetComponent = props => {
|
|
26901
|
+
var state = useChatWidgetState(props);
|
|
26902
|
+
return /*#__PURE__*/React.createElement(ChatWidgetView, Object.assign({}, props, state));
|
|
26903
|
+
};
|
|
26904
|
+
ChatWidgetComponent.displayName = 'ChatWidget';
|
|
26905
|
+
var ChatWidget = ChatWidgetComponent;
|
|
26906
|
+
|
|
26907
|
+
function useContextSelector(_ref) {
|
|
26908
|
+
var {
|
|
26909
|
+
onSelect,
|
|
26910
|
+
onCancel,
|
|
26911
|
+
active
|
|
26912
|
+
} = _ref;
|
|
26913
|
+
var [highlightedElement, setHighlightedElement] = useState(null);
|
|
26914
|
+
var overlayRef = useRef(null);
|
|
26915
|
+
// Handle mouse move to consistently highlight elements
|
|
26916
|
+
var handleMouseMove = useCallback(e => {
|
|
26917
|
+
var _target$innerText;
|
|
26918
|
+
if (!active) return;
|
|
26919
|
+
var target = document.elementFromPoint(e.clientX, e.clientY);
|
|
26920
|
+
// Ignore if targeting the overlay itself or the widget
|
|
26921
|
+
if (!target || target === document.body || target.closest('[data-chatwidget-ignore="true"]') || target.closest('#chatwidget-overlay')) {
|
|
26922
|
+
setHighlightedElement(null);
|
|
26923
|
+
return;
|
|
26924
|
+
}
|
|
26925
|
+
var rect = target.getBoundingClientRect();
|
|
26926
|
+
// Compute a helpful name
|
|
26927
|
+
var name = target.tagName.toLowerCase();
|
|
26928
|
+
if (target.id) name += "#" + target.id;else if (target.className && typeof target.className === 'string') {
|
|
26929
|
+
// Just take the first class for brevity
|
|
26930
|
+
var firstClass = target.className.split(' ')[0];
|
|
26931
|
+
if (firstClass) name += "." + firstClass;
|
|
26932
|
+
}
|
|
26933
|
+
// Get some text content if available for better context
|
|
26934
|
+
var text = (_target$innerText = target.innerText) == null ? void 0 : _target$innerText.slice(0, 20);
|
|
26935
|
+
if (text) name += " (\"" + text + "...\")";
|
|
26936
|
+
setHighlightedElement({
|
|
26937
|
+
id: target.id || "el-" + Date.now(),
|
|
26938
|
+
name,
|
|
26939
|
+
tagName: target.tagName.toLowerCase(),
|
|
26940
|
+
rect
|
|
26941
|
+
});
|
|
26942
|
+
}, [active]);
|
|
26943
|
+
// Handle click to select
|
|
26944
|
+
var handleClick = useCallback(e => {
|
|
26945
|
+
if (!active) return;
|
|
26946
|
+
// If clicking inside the widget, don't trigger selection
|
|
26947
|
+
var target = e.target;
|
|
26948
|
+
if (target.closest('[data-chatwidget-ignore="true"]')) {
|
|
26949
|
+
return;
|
|
26950
|
+
}
|
|
26951
|
+
e.preventDefault();
|
|
26952
|
+
e.stopPropagation();
|
|
26953
|
+
if (highlightedElement) {
|
|
26954
|
+
onSelect(highlightedElement);
|
|
26955
|
+
}
|
|
26956
|
+
}, [active, highlightedElement, onSelect]);
|
|
26957
|
+
// Handle escape to cancel
|
|
26958
|
+
var handleKeyDown = useCallback(e => {
|
|
26959
|
+
if (!active) return;
|
|
26960
|
+
if (e.key === 'Escape') {
|
|
26961
|
+
onCancel();
|
|
26962
|
+
}
|
|
26963
|
+
}, [active, onCancel]);
|
|
26964
|
+
useEffect(() => {
|
|
26965
|
+
if (active) {
|
|
26966
|
+
document.addEventListener('mousemove', handleMouseMove);
|
|
26967
|
+
document.addEventListener('click', handleClick, true); // Capture phase to prevent default
|
|
26968
|
+
document.addEventListener('keydown', handleKeyDown);
|
|
26969
|
+
document.body.style.cursor = 'crosshair';
|
|
26970
|
+
} else {
|
|
26971
|
+
setHighlightedElement(null);
|
|
26972
|
+
document.removeEventListener('mousemove', handleMouseMove);
|
|
26973
|
+
document.removeEventListener('click', handleClick, true);
|
|
26974
|
+
document.removeEventListener('keydown', handleKeyDown);
|
|
26975
|
+
document.body.style.cursor = '';
|
|
26976
|
+
}
|
|
26977
|
+
return () => {
|
|
26978
|
+
document.removeEventListener('mousemove', handleMouseMove);
|
|
26979
|
+
document.removeEventListener('click', handleClick, true);
|
|
26980
|
+
document.removeEventListener('keydown', handleKeyDown);
|
|
26981
|
+
document.body.style.cursor = '';
|
|
26982
|
+
};
|
|
26983
|
+
}, [active, handleMouseMove, handleClick, handleKeyDown]);
|
|
26984
|
+
return {
|
|
26985
|
+
highlightedElement
|
|
26986
|
+
};
|
|
26987
|
+
}
|
|
26988
|
+
/**
|
|
26989
|
+
* Overlay component to render the highlight box
|
|
26990
|
+
*/
|
|
26991
|
+
function ContextOverlay(_ref2) {
|
|
26992
|
+
var {
|
|
26993
|
+
element
|
|
26994
|
+
} = _ref2;
|
|
26995
|
+
if (!element) return null;
|
|
26996
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
26997
|
+
id: "chatwidget-overlay",
|
|
26998
|
+
style: {
|
|
26999
|
+
position: 'fixed',
|
|
27000
|
+
top: element.rect.top,
|
|
27001
|
+
left: element.rect.left,
|
|
27002
|
+
width: element.rect.width,
|
|
27003
|
+
height: element.rect.height,
|
|
27004
|
+
border: '2px solid #2563eb',
|
|
27005
|
+
backgroundColor: 'rgba(37, 99, 235, 0.1)',
|
|
27006
|
+
pointerEvents: 'none',
|
|
27007
|
+
zIndex: 99999,
|
|
27008
|
+
transition: 'all 0.1s ease-out',
|
|
27009
|
+
borderRadius: '4px'
|
|
27010
|
+
}
|
|
27011
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
27012
|
+
style: {
|
|
27013
|
+
position: 'absolute',
|
|
27014
|
+
top: '-24px',
|
|
27015
|
+
left: '0',
|
|
27016
|
+
backgroundColor: '#2563eb',
|
|
27017
|
+
color: 'white',
|
|
27018
|
+
padding: '2px 8px',
|
|
27019
|
+
borderRadius: '4px',
|
|
27020
|
+
fontSize: '12px',
|
|
27021
|
+
fontWeight: 'bold',
|
|
27022
|
+
whiteSpace: 'nowrap'
|
|
27023
|
+
}
|
|
27024
|
+
}, element.name));
|
|
27025
|
+
}
|
|
27026
|
+
|
|
27027
|
+
/**
|
|
27028
|
+
* ChatWidget Widget Component
|
|
27029
|
+
* A floating chat widget with DOM element selection capabilities.
|
|
27030
|
+
*/
|
|
27031
|
+
var ChatWidgetWidget = _ref => {
|
|
27032
|
+
var {
|
|
27033
|
+
initialMessages = [],
|
|
27034
|
+
onSendMessage,
|
|
27035
|
+
bubbleSize = 'md'
|
|
27036
|
+
} = _ref;
|
|
27037
|
+
var [isOpen, setIsOpen] = useState(false);
|
|
27038
|
+
var [isContextPickerActive, setIsContextPickerActive] = useState(false);
|
|
27039
|
+
var [messages, setMessages] = useState(initialMessages);
|
|
27040
|
+
var [contextElements, setContextElements] = useState([]);
|
|
27041
|
+
// Hook for context selection
|
|
27042
|
+
var {
|
|
27043
|
+
highlightedElement
|
|
27044
|
+
} = useContextSelector({
|
|
27045
|
+
active: isContextPickerActive,
|
|
27046
|
+
onSelect: element => {
|
|
27047
|
+
setContextElements(prev => [...prev, element]);
|
|
27048
|
+
setIsContextPickerActive(false);
|
|
27049
|
+
setIsOpen(true); // Re-open chat after selection
|
|
27050
|
+
},
|
|
27051
|
+
onCancel: () => {
|
|
27052
|
+
setIsContextPickerActive(false);
|
|
27053
|
+
setIsOpen(true);
|
|
27054
|
+
}
|
|
27055
|
+
});
|
|
27056
|
+
var toggleOpen = () => setIsOpen(!isOpen);
|
|
27057
|
+
var handleContextPickerClick = () => {
|
|
27058
|
+
setIsContextPickerActive(true);
|
|
27059
|
+
setIsOpen(false); // Minimize chat while picking
|
|
27060
|
+
};
|
|
27061
|
+
var handleRemoveContextElement = id => {
|
|
27062
|
+
setContextElements(prev => prev.filter(el => el.id !== id));
|
|
27063
|
+
};
|
|
27064
|
+
var handleSubmit = content => {
|
|
27065
|
+
// Add user message
|
|
27066
|
+
var newMessage = {
|
|
27067
|
+
id: Date.now().toString(),
|
|
27068
|
+
role: 'user',
|
|
27069
|
+
content,
|
|
27070
|
+
timestamp: new Date(),
|
|
27071
|
+
contextElements: [...contextElements]
|
|
27072
|
+
};
|
|
27073
|
+
setMessages(prev => [...prev, newMessage]);
|
|
27074
|
+
onSendMessage == null || onSendMessage(content, contextElements);
|
|
27075
|
+
// Clear context after sending
|
|
27076
|
+
setContextElements([]);
|
|
27077
|
+
// Simulate assistant response
|
|
27078
|
+
setTimeout(() => {
|
|
27079
|
+
var _newMessage$contextEl;
|
|
27080
|
+
var isToolCall = Math.random() > 0.7;
|
|
27081
|
+
var hasReasoning = Math.random() > 0.4;
|
|
27082
|
+
var assistantMessage = {
|
|
27083
|
+
id: (Date.now() + 1).toString(),
|
|
27084
|
+
role: 'assistant',
|
|
27085
|
+
timestamp: new Date(),
|
|
27086
|
+
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?",
|
|
27087
|
+
messageType: isToolCall ? 'tool' : 'text',
|
|
27088
|
+
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
|
|
27089
|
+
};
|
|
27090
|
+
setMessages(prev => [...prev, assistantMessage]);
|
|
27091
|
+
if (isToolCall) {
|
|
27092
|
+
// Add a follow-up system message after a tool call
|
|
27093
|
+
setTimeout(() => {
|
|
27094
|
+
setMessages(prev => [...prev, {
|
|
27095
|
+
id: (Date.now() + 2).toString(),
|
|
27096
|
+
role: 'assistant',
|
|
27097
|
+
messageType: 'system',
|
|
27098
|
+
content: 'Tool "highlightElement" executed successfully.',
|
|
27099
|
+
timestamp: new Date()
|
|
27100
|
+
}]);
|
|
27101
|
+
}, 800);
|
|
27102
|
+
}
|
|
27103
|
+
}, 1000);
|
|
27104
|
+
};
|
|
27105
|
+
return /*#__PURE__*/React.createElement(View, {
|
|
27106
|
+
position: "fixed",
|
|
27107
|
+
bottom: 24,
|
|
27108
|
+
right: 24,
|
|
27109
|
+
zIndex: 9999
|
|
27110
|
+
}, /*#__PURE__*/React.createElement(ContextOverlay, {
|
|
27111
|
+
element: highlightedElement
|
|
27112
|
+
}), isContextPickerActive && (/*#__PURE__*/React.createElement(View, {
|
|
27113
|
+
position: "fixed",
|
|
27114
|
+
top: 24,
|
|
27115
|
+
left: "50%",
|
|
27116
|
+
transform: "translateX(-50%)",
|
|
27117
|
+
backgroundColor: "rgba(0,0,0,0.8)",
|
|
27118
|
+
color: "white",
|
|
27119
|
+
padding: "8px 16px",
|
|
27120
|
+
borderRadius: "24px",
|
|
27121
|
+
zIndex: 10000,
|
|
27122
|
+
boxShadow: "0 4px 6px rgba(0,0,0,0.1)"
|
|
27123
|
+
}, /*#__PURE__*/React.createElement(Text, {
|
|
27124
|
+
fontWeight: "600",
|
|
27125
|
+
fontSize: "14px"
|
|
27126
|
+
}, "Click an element to select it. Press ESC to cancel."))), isOpen && (/*#__PURE__*/React.createElement(View, {
|
|
27127
|
+
position: "absolute",
|
|
27128
|
+
bottom: 60,
|
|
27129
|
+
right: 0,
|
|
27130
|
+
width: "400px",
|
|
27131
|
+
height: "600px",
|
|
27132
|
+
marginBottom: "16px",
|
|
27133
|
+
backgroundColor: "rgba(255, 255, 255, 0.8)",
|
|
27134
|
+
backdropFilter: "blur(20px)",
|
|
27135
|
+
borderRadius: "24px",
|
|
27136
|
+
border: "1px solid rgba(255, 255, 255, 0.4)",
|
|
27137
|
+
boxShadow: "0 25px 50px -12px rgba(0, 0, 0, 0.25)",
|
|
27138
|
+
overflow: "hidden",
|
|
27139
|
+
animation: "slideUp 0.3s ease-out",
|
|
27140
|
+
style: {
|
|
27141
|
+
animation: 'fadeIn 0.2s ease-out',
|
|
27142
|
+
transformOrigin: 'bottom right'
|
|
27143
|
+
}
|
|
27144
|
+
}, /*#__PURE__*/React.createElement(View, {
|
|
27145
|
+
padding: "16px",
|
|
27146
|
+
borderBottom: "1px solid rgba(0,0,0,0.05)",
|
|
27147
|
+
display: "flex",
|
|
27148
|
+
justifyContent: "space-between",
|
|
27149
|
+
alignItems: "center"
|
|
27150
|
+
}, /*#__PURE__*/React.createElement(Text, {
|
|
27151
|
+
fontWeight: "bold",
|
|
27152
|
+
color: "color.gray.800"
|
|
27153
|
+
}, "ChatWidget Assistant"), /*#__PURE__*/React.createElement(View, {
|
|
27154
|
+
as: "button",
|
|
27155
|
+
onClick: () => setIsOpen(false),
|
|
27156
|
+
cursor: "pointer",
|
|
27157
|
+
padding: "4px",
|
|
27158
|
+
borderRadius: "50%",
|
|
27159
|
+
border: "none",
|
|
27160
|
+
backgroundColor: "transparent",
|
|
27161
|
+
_hover: {
|
|
27162
|
+
backgroundColor: 'rgba(0,0,0,0.05)'
|
|
27163
|
+
}
|
|
27164
|
+
}, /*#__PURE__*/React.createElement(CloseIcon, {
|
|
27165
|
+
widthHeight: 16,
|
|
27166
|
+
color: "color.gray.500"
|
|
27167
|
+
}))), /*#__PURE__*/React.createElement(ChatWidget, {
|
|
27168
|
+
messages: messages,
|
|
27169
|
+
onSubmit: handleSubmit,
|
|
27170
|
+
size: bubbleSize,
|
|
27171
|
+
variant: "minimal",
|
|
27172
|
+
enableContextPicker: true,
|
|
27173
|
+
selectedContextElements: contextElements,
|
|
27174
|
+
onContextPickerClick: handleContextPickerClick,
|
|
27175
|
+
onRemoveContextElement: handleRemoveContextElement,
|
|
27176
|
+
styles: {
|
|
27177
|
+
container: {
|
|
27178
|
+
height: 'calc(100% - 60px)',
|
|
27179
|
+
backgroundColor: 'transparent'
|
|
27180
|
+
},
|
|
27181
|
+
inputContainer: {
|
|
27182
|
+
backgroundColor: 'white',
|
|
27183
|
+
margin: '0 16px 16px 16px',
|
|
27184
|
+
boxShadow: '0 4px 6px -1px rgba(0, 0, 0, 0.1)'
|
|
27185
|
+
}
|
|
27186
|
+
}
|
|
27187
|
+
}))), !isContextPickerActive && (/*#__PURE__*/React.createElement(View, {
|
|
27188
|
+
as: "button",
|
|
27189
|
+
onClick: toggleOpen,
|
|
27190
|
+
width: "56px",
|
|
27191
|
+
height: "56px",
|
|
27192
|
+
borderRadius: "50%",
|
|
27193
|
+
backgroundColor: "theme.primary",
|
|
27194
|
+
border: "none",
|
|
27195
|
+
boxShadow: "0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)",
|
|
27196
|
+
cursor: "pointer",
|
|
27197
|
+
display: "flex",
|
|
27198
|
+
alignItems: "center",
|
|
27199
|
+
justifyContent: "center",
|
|
27200
|
+
transition: "transform 0.2s ease",
|
|
27201
|
+
_hover: {
|
|
27202
|
+
transform: 'scale(1.05)'
|
|
27203
|
+
},
|
|
27204
|
+
_active: {
|
|
27205
|
+
transform: 'scale(0.95)'
|
|
27206
|
+
},
|
|
27207
|
+
"data-chatwidget-ignore": "true" // Ignore clicks on the widget itself for context picking
|
|
27208
|
+
}, isOpen ? (/*#__PURE__*/React.createElement(CloseIcon, {
|
|
27209
|
+
widthHeight: 24,
|
|
27210
|
+
color: "white"
|
|
27211
|
+
})) : (/*#__PURE__*/React.createElement(PanelIcon, {
|
|
27212
|
+
widthHeight: 24,
|
|
27213
|
+
color: "white"
|
|
27214
|
+
})))));
|
|
27215
|
+
};
|
|
27216
|
+
|
|
27217
|
+
export { Accordion, Alert, ArrowIcon, AspectRatio, AttachmentIcon, AttachmentPreview, AudioIcon, AudioInput, AudioWaveform, Avatar, BackIcon, Background, Badge, BatteryIcon, BluetoothIcon, BoldArrowIcon, BookmarkIcon, Button, CalendarIcon, CameraIcon, Card, Carousel, Chart, ChartIcon, ChatInput, ChatWidget, ChatWidgetComponent, ChatWidgetWidget, CheckIcon, Checkbox, ChevronIcon, ClockIcon, CloseEyeIcon, CloseIcon, CloudIcon, ColorInput, ColorPicker, ComboBox, Command, ContextMenu, CookieConsent, CopyIcon, CountryPicker, CreditCardIcon, CropIcon, DatePicker, DeleteIcon, Divider, DocumentIcon, DownloadIcon, DragAndDrop, DragAndDropComponent, DragHandleIcon, DragHandleLinesIcon, Drawer, DropdownMenu, DustBinIcon, EditIcon, EmojiPicker, ErrorIcon, ExternalLinkIcon, FacebookIcon, FileIcon, FileImage, FileSVG, FilterIcon, FolderIcon, FormikChatInput, FormikCheckbox, FormikColorInput, FormikComboBox, FormikCountryPicker, FormikDatePicker, FormikForm, FormikOTPInput, FormikPassword, FormikSelect, FormikSelector, FormikSlider, FormikSwitch, FormikTagInput, FormikTextArea, FormikTextField, FormikUploader, GiftIcon, HeartIcon, HelpIcon, HomeIcon, HoverCard, Icon, ImageIcon, InfoIcon, InstagramIcon, LayoutIcon, LikeIcon, Link, LinkIcon, LinkedinIcon, Loader, LoadingSpinnerIcon, LockIcon, LogoutIcon, MagicWandIcon, MapPinIcon, MediaPreview, MenuIcon, Menubar, MessageLayout, MessageView, MicrophoneIcon, MinusIcon, Modal, MoonIcon, MoreIcon, MousePointerIcon, NavigationMenu, NotificationIcon, OTPInput, OpenEyeIcon, Pagination, PanelIcon, Password, PauseIcon, PlayIcon, PlusIcon, PowerOffIcon, PrintIcon, ProfileIcon, ProgressBar, RefreshIcon, Resizable, RotateIcon, SaveIcon, SearchIcon, Select, Selector, SendIcon, Separator, SettingsIcon, ShapeIcon, ShareButton, ShareIcon, ShieldIcon, Sidebar, Slider, SliderIcon, SpinnerIcon, StarIcon, StatusIndicator, StopIcon, SuccessIcon, Switch, Table, Tabs, TagInput, TextArea, TextField, TextIcon, ThreadsIcon, TickIcon, Title, Toast, Toggle, ToggleGroup, Tooltip, TrashIcon, TwitchIcon, TwitterIcon, UnLikeIcon, UnlockIcon, UploadIcon, Uploader, UserIcon, VideoIcon, WarningIcon, WifiIcon, XIcon, YoutubeIcon, ZapIcon, ZoomInIcon, ZoomOutIcon, hideMessage, hideModal, showMessage, showModal, showToast, useMessageStore, useModalStore, useToast$1 as useToast };
|
|
26297
27218
|
//# sourceMappingURL=web.esm.js.map
|