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