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