@cuekit-ai/react 1.5.0 → 1.6.0

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/index.js CHANGED
@@ -23630,11 +23630,12 @@ function setWebRTCCallbacks(newCallbacks) {
23630
23630
  function getCurrentCallbacks() {
23631
23631
  return callbacks;
23632
23632
  }
23633
- async function authenticate(userIdentity, apiKey, appId) {
23633
+ async function authenticate(userIdentity, apiKey, appId, language) {
23634
23634
  try {
23635
23635
  const authPayload = {
23636
23636
  user_identity: userIdentity,
23637
- app_id: appId || _appId
23637
+ app_id: appId || _appId,
23638
+ ...language && { language: language.code }
23638
23639
  };
23639
23640
  const response = await fetch(`${serverUrl}/auth/login`, {
23640
23641
  method: "POST",
@@ -23920,17 +23921,17 @@ var require_inline_style_parser = __commonJS({
23920
23921
  function position3() {
23921
23922
  var start2 = { line: lineno, column };
23922
23923
  return function(node2) {
23923
- node2.position = new Position(start2);
23924
+ node2.position = new Position2(start2);
23924
23925
  whitespace2();
23925
23926
  return node2;
23926
23927
  };
23927
23928
  }
23928
- function Position(start2) {
23929
+ function Position2(start2) {
23929
23930
  this.start = start2;
23930
23931
  this.end = { line: lineno, column };
23931
23932
  this.source = options.source;
23932
23933
  }
23933
- Position.prototype.content = style;
23934
+ Position2.prototype.content = style;
23934
23935
  var errorsList = [];
23935
23936
  function error(msg) {
23936
23937
  var err = new Error(
@@ -25014,11 +25015,15 @@ var require_md5 = __commonJS({
25014
25015
  // src/index.ts
25015
25016
  var index_exports = {};
25016
25017
  __export(index_exports, {
25018
+ AnsyrProvider: () => AnsyrProvider,
25017
25019
  BorderGlow: () => border_glow_default,
25018
25020
  ChatPopup: () => ChatPopup,
25019
- CuekitProvider: () => CuekitProvider,
25021
+ DraggableResizableContainer: () => DraggableResizableContainer,
25020
25022
  InitCuekit: () => InitCuekit,
25023
+ LanguageSelector: () => LanguageSelector,
25021
25024
  MicButton: () => MicButton,
25025
+ ResizeHandle: () => ResizeHandle,
25026
+ ResizeHandles: () => ResizeHandles,
25022
25027
  VoiceIntensityVisualizer: () => VoiceIntensityVisualizer,
25023
25028
  captureAllInteractiveElements: () => captureAllInteractiveElements,
25024
25029
  clearElementCache: () => clearElementCache,
@@ -25030,14 +25035,15 @@ __export(index_exports, {
25030
25035
  initWebRTC: () => initWebRTC,
25031
25036
  initWebRTCWithDeployedBackend: () => initWebRTCWithDeployedBackend,
25032
25037
  resolveRoutePath: () => resolveRoutePath,
25038
+ useAnsyrContext: () => useAnsyrContext,
25033
25039
  useCuekit: () => useCuekit,
25034
- useQubeContext: () => useQubeContext,
25040
+ useDraggableResizableContainer: () => useDraggableResizableContainer,
25035
25041
  useWebRTC: () => useWebRTC,
25036
25042
  validateDynamicElements: () => validateDynamicElements
25037
25043
  });
25038
25044
  module.exports = __toCommonJS(index_exports);
25039
25045
 
25040
- // src/providers/cuekit-provider.tsx
25046
+ // src/providers/ansyr-provider.tsx
25041
25047
  var import_react = __toESM(require("react"));
25042
25048
 
25043
25049
  // src/core/init.ts
@@ -25056,7 +25062,7 @@ function InitCuekit(config) {
25056
25062
  setWebRTCConfig(webRTCConfig);
25057
25063
  }
25058
25064
 
25059
- // src/providers/cuekit-provider.tsx
25065
+ // src/providers/ansyr-provider.tsx
25060
25066
  init_navigation();
25061
25067
  init_intent_store();
25062
25068
 
@@ -25101,9 +25107,9 @@ var initWebRTC = (apiKey) => {
25101
25107
  return initWebRTCWithDeployedBackend(apiKey);
25102
25108
  };
25103
25109
 
25104
- // src/providers/cuekit-provider.tsx
25105
- if (typeof window !== "undefined" && !globalThis.CuekitStore) {
25106
- globalThis.CuekitStore = {
25110
+ // src/providers/ansyr-provider.tsx
25111
+ if (typeof window !== "undefined" && !globalThis.AnsyrStore) {
25112
+ globalThis.AnsyrStore = {
25107
25113
  intent: null,
25108
25114
  lastText: "",
25109
25115
  lastClickedLabel: "",
@@ -25111,38 +25117,46 @@ if (typeof window !== "undefined" && !globalThis.CuekitStore) {
25111
25117
  appId: void 0,
25112
25118
  deviceId: void 0,
25113
25119
  update(data) {
25114
- Object.assign(globalThis.CuekitStore, data);
25120
+ Object.assign(globalThis.AnsyrStore, data);
25115
25121
  }
25116
25122
  };
25117
25123
  }
25118
- var QubeContext = (0, import_react.createContext)({
25124
+ var AnsyrContext = (0, import_react.createContext)({
25119
25125
  apiKey: "",
25120
- appId: ""
25126
+ appId: "",
25127
+ title: "ansyr.ai",
25128
+ showLogo: true,
25129
+ showAIIcon: true,
25130
+ showUserIcon: true
25121
25131
  });
25122
- var useQubeContext = () => (0, import_react.useContext)(QubeContext);
25132
+ var useAnsyrContext = () => (0, import_react.useContext)(AnsyrContext);
25123
25133
  var getUniqueId = () => {
25124
25134
  if (typeof window === "undefined") {
25125
25135
  return "server-" + Date.now().toString(36);
25126
25136
  }
25127
25137
  try {
25128
- let id = localStorage.getItem("cuekit_device_id");
25138
+ let id = localStorage.getItem("ansyr_device_id");
25129
25139
  if (!id) {
25130
25140
  id = Date.now().toString(36) + Math.random().toString(36).substring(2);
25131
- localStorage.setItem("cuekit_device_id", id);
25141
+ localStorage.setItem("ansyr_device_id", id);
25132
25142
  }
25133
25143
  return id;
25134
25144
  } catch {
25135
25145
  return "anon-" + Date.now().toString(36);
25136
25146
  }
25137
25147
  };
25138
- var CuekitProvider = ({
25148
+ var AnsyrProvider = ({
25139
25149
  apiKey,
25140
25150
  deviceId = "",
25141
25151
  appId,
25142
25152
  children,
25143
25153
  navigationHandler: navigationHandler2,
25144
25154
  onConnectionStateChange,
25145
- onParticipantUpdate
25155
+ onParticipantUpdate,
25156
+ title = "ansyr.ai",
25157
+ showLogo = true,
25158
+ showAIIcon = true,
25159
+ showUserIcon = true
25146
25160
  }) => {
25147
25161
  const [internalDeviceId, setInternalDeviceId] = (0, import_react.useState)(deviceId);
25148
25162
  (0, import_react.useEffect)(() => {
@@ -25190,8 +25204,8 @@ var CuekitProvider = ({
25190
25204
  }, [onConnectionStateChange, onParticipantUpdate, navigationHandler2]);
25191
25205
  (0, import_react.useEffect)(() => {
25192
25206
  const updateGlobalStore = (id) => {
25193
- if (typeof window !== "undefined" && globalThis.CuekitStore) {
25194
- globalThis.CuekitStore.update({
25207
+ if (typeof window !== "undefined" && globalThis.AnsyrStore) {
25208
+ globalThis.AnsyrStore.update({
25195
25209
  apiKey,
25196
25210
  appId,
25197
25211
  deviceId: id
@@ -25241,11 +25255,15 @@ var CuekitProvider = ({
25241
25255
  };
25242
25256
  }, [apiKey, appId, internalDeviceId]);
25243
25257
  return /* @__PURE__ */ import_react.default.createElement(
25244
- QubeContext.Provider,
25258
+ AnsyrContext.Provider,
25245
25259
  {
25246
25260
  value: {
25247
25261
  apiKey,
25248
- appId
25262
+ appId,
25263
+ title,
25264
+ showLogo,
25265
+ showAIIcon,
25266
+ showUserIcon
25249
25267
  }
25250
25268
  },
25251
25269
  children
@@ -25253,7 +25271,7 @@ var CuekitProvider = ({
25253
25271
  };
25254
25272
 
25255
25273
  // src/components/mic-button.tsx
25256
- var import_react15 = __toESM(require("react"));
25274
+ var import_react20 = __toESM(require("react"));
25257
25275
 
25258
25276
  // src/hooks/use-cuekit.ts
25259
25277
  var import_react3 = require("react");
@@ -25303,22 +25321,25 @@ var useWebRTC = (options) => {
25303
25321
  options?.onAISpeechStart,
25304
25322
  options?.onAISpeechEnd
25305
25323
  ]);
25306
- const connect = (0, import_react2.useCallback)(async (identity, apiKey, appId) => {
25307
- try {
25308
- setError(null);
25309
- setIsConnecting(true);
25310
- const authData = await authenticate(identity, apiKey || _apiKey, appId || _appId);
25311
- await connectToRoom(authData.livekit_url, authData.livekit_token);
25312
- setRoom(getRoom());
25313
- setIsConnected(true);
25314
- return authData;
25315
- } catch (err) {
25316
- setError(err.message || "Failed to connect");
25317
- setIsConnected(false);
25318
- } finally {
25319
- setIsConnecting(false);
25320
- }
25321
- }, []);
25324
+ const connect = (0, import_react2.useCallback)(
25325
+ async (identity, apiKey, appId, language) => {
25326
+ try {
25327
+ setError(null);
25328
+ setIsConnecting(true);
25329
+ const authData = await authenticate(identity, apiKey || _apiKey, appId || _appId, language);
25330
+ await connectToRoom(authData.livekit_url, authData.livekit_token);
25331
+ setRoom(getRoom());
25332
+ setIsConnected(true);
25333
+ return authData;
25334
+ } catch (err) {
25335
+ setError(err.message || "Failed to connect");
25336
+ setIsConnected(false);
25337
+ } finally {
25338
+ setIsConnecting(false);
25339
+ }
25340
+ },
25341
+ []
25342
+ );
25322
25343
  const disconnect = (0, import_react2.useCallback)(async () => {
25323
25344
  await disconnectFromRoom();
25324
25345
  setIsConnected(false);
@@ -25538,8 +25559,8 @@ var useCuekit = (options) => {
25538
25559
  onNavigationCommand: handleNavigationCommand
25539
25560
  });
25540
25561
  const connect = (0, import_react3.useCallback)(
25541
- async (identity, apiKey, appId) => {
25542
- await webrtc.connect(identity, apiKey, appId);
25562
+ async (identity, apiKey, appId, language) => {
25563
+ await webrtc.connect(identity, apiKey, appId, language);
25543
25564
  },
25544
25565
  [webrtc]
25545
25566
  );
@@ -25646,7 +25667,7 @@ var useCuekit = (options) => {
25646
25667
  };
25647
25668
 
25648
25669
  // src/components/chat-popup.tsx
25649
- var import_react11 = __toESM(require("react"));
25670
+ var import_react14 = __toESM(require("react"));
25650
25671
 
25651
25672
  // node_modules/devlop/lib/default.js
25652
25673
  function ok() {
@@ -38443,6 +38464,606 @@ var MicIcon = ({ width = 24, height = 24, className, ...props }) => {
38443
38464
  };
38444
38465
  var mic_default = MicIcon;
38445
38466
 
38467
+ // src/components/draggable-resizable-container.tsx
38468
+ var import_react13 = __toESM(require("react"));
38469
+
38470
+ // src/utils/draggable-resizable.ts
38471
+ var import_react11 = require("react");
38472
+ var absoluteToRelative = (position3, size, viewportWidth, viewportHeight) => {
38473
+ return {
38474
+ position: {
38475
+ xPercent: position3.x / viewportWidth * 100,
38476
+ yPercent: position3.y / viewportHeight * 100
38477
+ },
38478
+ size: {
38479
+ widthPercent: size.width / viewportWidth * 100,
38480
+ heightPercent: size.height / viewportHeight * 100
38481
+ }
38482
+ };
38483
+ };
38484
+ var relativeToAbsolute = (relativePosition, relativeSize, viewportWidth, viewportHeight) => {
38485
+ return {
38486
+ position: {
38487
+ x: relativePosition.xPercent / 100 * viewportWidth,
38488
+ y: relativePosition.yPercent / 100 * viewportHeight
38489
+ },
38490
+ size: {
38491
+ width: relativeSize.widthPercent / 100 * viewportWidth,
38492
+ height: relativeSize.heightPercent / 100 * viewportHeight
38493
+ }
38494
+ };
38495
+ };
38496
+ var DEFAULT_BOUNDS = {
38497
+ minWidth: 300,
38498
+ minHeight: 200,
38499
+ maxWidth: typeof window !== "undefined" ? Math.min(window.innerWidth * 0.92, 800) : 800,
38500
+ maxHeight: typeof window !== "undefined" ? Math.min(window.innerHeight * 0.9, 600) : 600
38501
+ };
38502
+ var DEFAULT_POSITION = { x: 0, y: 0 };
38503
+ var DEFAULT_SIZE = {
38504
+ width: 420,
38505
+ height: typeof window !== "undefined" ? Math.min(window.innerHeight * 0.55, 500) : 400
38506
+ };
38507
+ function useDraggableResizable(options = {}) {
38508
+ const {
38509
+ bounds = DEFAULT_BOUNDS,
38510
+ initialPosition = DEFAULT_POSITION,
38511
+ initialSize = DEFAULT_SIZE,
38512
+ onPositionChange,
38513
+ onSizeChange,
38514
+ disabled = false,
38515
+ dragHandle
38516
+ } = options;
38517
+ const [position3, setPositionState] = (0, import_react11.useState)(initialPosition);
38518
+ const [size, setSizeState] = (0, import_react11.useState)(initialSize);
38519
+ const [dragState, setDragState] = (0, import_react11.useState)({
38520
+ isDragging: false,
38521
+ startPosition: { x: 0, y: 0 },
38522
+ startMousePosition: { x: 0, y: 0 }
38523
+ });
38524
+ const [resizeState, setResizeState] = (0, import_react11.useState)({
38525
+ isResizing: false,
38526
+ direction: "se",
38527
+ startSize: { width: 0, height: 0 },
38528
+ startPosition: { x: 0, y: 0 },
38529
+ startMousePosition: { x: 0, y: 0 }
38530
+ });
38531
+ const containerRef = (0, import_react11.useRef)(null);
38532
+ const constrainPosition = (0, import_react11.useCallback)((pos, size2) => {
38533
+ const maxX = window.innerWidth - size2.width;
38534
+ const maxY = window.innerHeight - size2.height;
38535
+ return {
38536
+ x: Math.max(0, Math.min(pos.x, maxX)),
38537
+ y: Math.max(0, Math.min(pos.y, maxY))
38538
+ };
38539
+ }, []);
38540
+ const constrainSize = (0, import_react11.useCallback)(
38541
+ (newSize) => {
38542
+ return {
38543
+ width: Math.max(bounds.minWidth, Math.min(newSize.width, bounds.maxWidth || Infinity)),
38544
+ height: Math.max(bounds.minHeight, Math.min(newSize.height, bounds.maxHeight || Infinity))
38545
+ };
38546
+ },
38547
+ [bounds]
38548
+ );
38549
+ const setPosition = (0, import_react11.useCallback)(
38550
+ (newPosition) => {
38551
+ const constrainedPosition = constrainPosition(newPosition, size);
38552
+ setPositionState(constrainedPosition);
38553
+ onPositionChange?.(constrainedPosition);
38554
+ },
38555
+ [size, constrainPosition, onPositionChange]
38556
+ );
38557
+ const setSize = (0, import_react11.useCallback)(
38558
+ (newSize) => {
38559
+ const constrainedSize = constrainSize(newSize);
38560
+ setSizeState(constrainedSize);
38561
+ onSizeChange?.(constrainedSize);
38562
+ const constrainedPosition = constrainPosition(position3, constrainedSize);
38563
+ if (constrainedPosition.x !== position3.x || constrainedPosition.y !== position3.y) {
38564
+ setPositionState(constrainedPosition);
38565
+ onPositionChange?.(constrainedPosition);
38566
+ }
38567
+ },
38568
+ [position3, constrainSize, constrainPosition, onSizeChange, onPositionChange]
38569
+ );
38570
+ const resetToInitial = (0, import_react11.useCallback)(() => {
38571
+ setPositionState(initialPosition);
38572
+ setSizeState(initialSize);
38573
+ onPositionChange?.(initialPosition);
38574
+ onSizeChange?.(initialSize);
38575
+ }, [initialPosition, initialSize, onPositionChange, onSizeChange]);
38576
+ const handleDragStart = (0, import_react11.useCallback)(
38577
+ (e3) => {
38578
+ if (disabled) return;
38579
+ if (dragHandle) {
38580
+ const target = e3.target;
38581
+ if (!target.closest(dragHandle)) return;
38582
+ }
38583
+ e3.preventDefault();
38584
+ e3.stopPropagation();
38585
+ setDragState({
38586
+ isDragging: true,
38587
+ startPosition: { ...position3 },
38588
+ startMousePosition: { x: e3.clientX, y: e3.clientY }
38589
+ });
38590
+ },
38591
+ [disabled, dragHandle, position3]
38592
+ );
38593
+ const handleResizeStart = (0, import_react11.useCallback)(
38594
+ (direction) => (e3) => {
38595
+ if (disabled) return;
38596
+ e3.preventDefault();
38597
+ e3.stopPropagation();
38598
+ setResizeState({
38599
+ isResizing: true,
38600
+ direction,
38601
+ startSize: { ...size },
38602
+ startPosition: { ...position3 },
38603
+ startMousePosition: { x: e3.clientX, y: e3.clientY }
38604
+ });
38605
+ },
38606
+ [disabled, size, position3]
38607
+ );
38608
+ (0, import_react11.useEffect)(() => {
38609
+ const handleMouseMove = (e3) => {
38610
+ if (dragState.isDragging) {
38611
+ const deltaX = e3.clientX - dragState.startMousePosition.x;
38612
+ const deltaY = e3.clientY - dragState.startMousePosition.y;
38613
+ const newPosition = {
38614
+ x: dragState.startPosition.x + deltaX,
38615
+ y: dragState.startPosition.y + deltaY
38616
+ };
38617
+ setPosition(newPosition);
38618
+ } else if (resizeState.isResizing) {
38619
+ const deltaX = e3.clientX - resizeState.startMousePosition.x;
38620
+ const deltaY = e3.clientY - resizeState.startMousePosition.y;
38621
+ let newSize = { ...resizeState.startSize };
38622
+ let newPosition = { ...resizeState.startPosition };
38623
+ const { direction } = resizeState;
38624
+ if (direction.includes("e")) {
38625
+ newSize.width = resizeState.startSize.width + deltaX;
38626
+ }
38627
+ if (direction.includes("w")) {
38628
+ newSize.width = resizeState.startSize.width - deltaX;
38629
+ newPosition.x = resizeState.startPosition.x + deltaX;
38630
+ }
38631
+ if (direction.includes("s")) {
38632
+ newSize.height = resizeState.startSize.height + deltaY;
38633
+ }
38634
+ if (direction.includes("n")) {
38635
+ newSize.height = resizeState.startSize.height - deltaY;
38636
+ newPosition.y = resizeState.startPosition.y + deltaY;
38637
+ }
38638
+ setSize(newSize);
38639
+ if (newPosition.x !== resizeState.startPosition.x || newPosition.y !== resizeState.startPosition.y) {
38640
+ setPosition(newPosition);
38641
+ }
38642
+ }
38643
+ };
38644
+ const handleMouseUp = () => {
38645
+ setDragState((prev) => ({ ...prev, isDragging: false }));
38646
+ setResizeState((prev) => ({ ...prev, isResizing: false }));
38647
+ };
38648
+ if (dragState.isDragging || resizeState.isResizing) {
38649
+ document.addEventListener("mousemove", handleMouseMove);
38650
+ document.addEventListener("mouseup", handleMouseUp);
38651
+ }
38652
+ return () => {
38653
+ document.removeEventListener("mousemove", handleMouseMove);
38654
+ document.removeEventListener("mouseup", handleMouseUp);
38655
+ };
38656
+ }, [dragState, resizeState, setPosition, setSize]);
38657
+ const resizeHandlers = {
38658
+ n: { onMouseDown: handleResizeStart("n") },
38659
+ s: { onMouseDown: handleResizeStart("s") },
38660
+ e: { onMouseDown: handleResizeStart("e") },
38661
+ w: { onMouseDown: handleResizeStart("w") },
38662
+ ne: { onMouseDown: handleResizeStart("ne") },
38663
+ nw: { onMouseDown: handleResizeStart("nw") },
38664
+ se: { onMouseDown: handleResizeStart("se") },
38665
+ sw: { onMouseDown: handleResizeStart("sw") }
38666
+ };
38667
+ return {
38668
+ position: position3,
38669
+ size,
38670
+ isDragging: dragState.isDragging,
38671
+ isResizing: resizeState.isResizing,
38672
+ dragHandlers: {
38673
+ onMouseDown: handleDragStart
38674
+ },
38675
+ resizeHandlers,
38676
+ setPosition,
38677
+ setSize,
38678
+ resetToInitial
38679
+ };
38680
+ }
38681
+ function getResizeCursor(direction) {
38682
+ const cursorMap = {
38683
+ n: "n-resize",
38684
+ s: "s-resize",
38685
+ e: "e-resize",
38686
+ w: "w-resize",
38687
+ ne: "ne-resize",
38688
+ nw: "nw-resize",
38689
+ se: "se-resize",
38690
+ sw: "sw-resize"
38691
+ };
38692
+ return cursorMap[direction];
38693
+ }
38694
+
38695
+ // src/components/resize-handle.tsx
38696
+ var import_react12 = __toESM(require("react"));
38697
+ var ResizeHandle = ({
38698
+ direction,
38699
+ onMouseDown,
38700
+ disabled = false,
38701
+ className = "",
38702
+ style = {},
38703
+ size = 8
38704
+ }) => {
38705
+ const getHandleStyle = () => {
38706
+ const baseStyle = {
38707
+ position: "absolute",
38708
+ backgroundColor: "transparent",
38709
+ cursor: disabled ? "default" : getResizeCursor(direction),
38710
+ zIndex: 1e3,
38711
+ userSelect: "none",
38712
+ ...style
38713
+ };
38714
+ switch (direction) {
38715
+ case "n":
38716
+ return {
38717
+ ...baseStyle,
38718
+ top: -size / 2,
38719
+ left: 0,
38720
+ right: 0,
38721
+ height: size
38722
+ };
38723
+ case "s":
38724
+ return {
38725
+ ...baseStyle,
38726
+ bottom: -size / 2,
38727
+ left: 0,
38728
+ right: 0,
38729
+ height: size
38730
+ };
38731
+ case "e":
38732
+ return {
38733
+ ...baseStyle,
38734
+ top: 0,
38735
+ bottom: 0,
38736
+ right: -size / 2,
38737
+ width: size
38738
+ };
38739
+ case "w":
38740
+ return {
38741
+ ...baseStyle,
38742
+ top: 0,
38743
+ bottom: 0,
38744
+ left: -size / 2,
38745
+ width: size
38746
+ };
38747
+ case "ne":
38748
+ return {
38749
+ ...baseStyle,
38750
+ top: -size / 2,
38751
+ right: -size / 2,
38752
+ width: size,
38753
+ height: size
38754
+ };
38755
+ case "nw":
38756
+ return {
38757
+ ...baseStyle,
38758
+ top: -size / 2,
38759
+ left: -size / 2,
38760
+ width: size,
38761
+ height: size
38762
+ };
38763
+ case "se":
38764
+ return {
38765
+ ...baseStyle,
38766
+ bottom: -size / 2,
38767
+ right: -size / 2,
38768
+ width: size,
38769
+ height: size
38770
+ };
38771
+ case "sw":
38772
+ return {
38773
+ ...baseStyle,
38774
+ bottom: -size / 2,
38775
+ left: -size / 2,
38776
+ width: size,
38777
+ height: size
38778
+ };
38779
+ default:
38780
+ return baseStyle;
38781
+ }
38782
+ };
38783
+ const handleMouseDown = (e3) => {
38784
+ if (!disabled) {
38785
+ onMouseDown(e3);
38786
+ }
38787
+ };
38788
+ return /* @__PURE__ */ import_react12.default.createElement(
38789
+ "div",
38790
+ {
38791
+ className: `resize-handle resize-handle-${direction} ${className}`,
38792
+ style: getHandleStyle(),
38793
+ onMouseDown: handleMouseDown,
38794
+ "data-direction": direction,
38795
+ "aria-label": `Resize ${direction}`
38796
+ }
38797
+ );
38798
+ };
38799
+ var ResizeHandles = ({
38800
+ onResizeStart,
38801
+ disabled = false,
38802
+ className = "",
38803
+ style = {},
38804
+ size = 8,
38805
+ showHandles = ["n", "s", "e", "w", "ne", "nw", "se", "sw"]
38806
+ }) => {
38807
+ return /* @__PURE__ */ import_react12.default.createElement(import_react12.default.Fragment, null, showHandles.map((direction) => /* @__PURE__ */ import_react12.default.createElement(
38808
+ ResizeHandle,
38809
+ {
38810
+ key: direction,
38811
+ direction,
38812
+ onMouseDown: onResizeStart(direction),
38813
+ disabled,
38814
+ className,
38815
+ style,
38816
+ size
38817
+ }
38818
+ )));
38819
+ };
38820
+
38821
+ // src/components/draggable-resizable-container.tsx
38822
+ var DraggableResizableContainer = ({
38823
+ children,
38824
+ className = "",
38825
+ style = {},
38826
+ dragHandle,
38827
+ showResizeHandles = true,
38828
+ resizeHandleSize = 8,
38829
+ onPositionChange,
38830
+ onSizeChange,
38831
+ onDragStart,
38832
+ onDragEnd,
38833
+ onResizeStart,
38834
+ onResizeEnd,
38835
+ storageKey,
38836
+ persistPosition = false,
38837
+ persistSize = false,
38838
+ ...options
38839
+ }) => {
38840
+ const containerRef = (0, import_react13.useRef)(null);
38841
+ const loadPersistedData = () => {
38842
+ if (!storageKey || typeof window === "undefined") return {};
38843
+ try {
38844
+ const data = localStorage.getItem(`cuekit-${storageKey}`);
38845
+ if (data) {
38846
+ const parsed = JSON.parse(data);
38847
+ if (parsed.relativePosition && parsed.relativeSize) {
38848
+ const viewportWidth = window.innerWidth;
38849
+ const viewportHeight = window.innerHeight;
38850
+ const { position: position4, size: size2 } = relativeToAbsolute(
38851
+ parsed.relativePosition,
38852
+ parsed.relativeSize,
38853
+ viewportWidth,
38854
+ viewportHeight
38855
+ );
38856
+ return { position: position4, size: size2 };
38857
+ }
38858
+ return {
38859
+ position: parsed.position,
38860
+ size: parsed.size
38861
+ };
38862
+ }
38863
+ } catch (error) {
38864
+ console.warn("Failed to load persisted position/size:", error);
38865
+ }
38866
+ return {};
38867
+ };
38868
+ const savePersistedData = (position4, size2) => {
38869
+ if (!storageKey || typeof window === "undefined") return;
38870
+ try {
38871
+ const viewportWidth = window.innerWidth;
38872
+ const viewportHeight = window.innerHeight;
38873
+ const { position: relativePosition, size: relativeSize } = absoluteToRelative(
38874
+ position4,
38875
+ size2,
38876
+ viewportWidth,
38877
+ viewportHeight
38878
+ );
38879
+ const data = {};
38880
+ if (persistPosition) {
38881
+ data.position = position4;
38882
+ data.relativePosition = relativePosition;
38883
+ }
38884
+ if (persistSize) {
38885
+ data.size = size2;
38886
+ data.relativeSize = relativeSize;
38887
+ }
38888
+ localStorage.setItem(`cuekit-${storageKey}`, JSON.stringify(data));
38889
+ } catch (error) {
38890
+ console.warn("Failed to save persisted position/size:", error);
38891
+ }
38892
+ };
38893
+ const persistedData = loadPersistedData();
38894
+ const initialPosition = persistedData.position || options.initialPosition;
38895
+ const initialSize = persistedData.size || options.initialSize;
38896
+ (0, import_react13.useEffect)(() => {
38897
+ const handleResize = () => {
38898
+ if (!storageKey || typeof window === "undefined") return;
38899
+ try {
38900
+ const data = localStorage.getItem(`cuekit-${storageKey}`);
38901
+ if (data) {
38902
+ const parsed = JSON.parse(data);
38903
+ if (parsed.relativePosition && parsed.relativeSize) {
38904
+ const viewportWidth = window.innerWidth;
38905
+ const viewportHeight = window.innerHeight;
38906
+ const { position: position4, size: size2 } = relativeToAbsolute(
38907
+ parsed.relativePosition,
38908
+ parsed.relativeSize,
38909
+ viewportWidth,
38910
+ viewportHeight
38911
+ );
38912
+ if (containerRef.current) {
38913
+ containerRef.current.style.left = `${position4.x}px`;
38914
+ containerRef.current.style.top = `${position4.y}px`;
38915
+ containerRef.current.style.width = `${size2.width}px`;
38916
+ containerRef.current.style.height = `${size2.height}px`;
38917
+ }
38918
+ }
38919
+ }
38920
+ } catch (error) {
38921
+ console.warn("Failed to update position on resize:", error);
38922
+ }
38923
+ };
38924
+ window.addEventListener("resize", handleResize);
38925
+ return () => window.removeEventListener("resize", handleResize);
38926
+ }, [storageKey]);
38927
+ const {
38928
+ position: position3,
38929
+ size,
38930
+ isDragging,
38931
+ isResizing,
38932
+ dragHandlers,
38933
+ resizeHandlers,
38934
+ setPosition,
38935
+ setSize
38936
+ } = useDraggableResizable({
38937
+ ...options,
38938
+ initialPosition,
38939
+ initialSize,
38940
+ onPositionChange: (pos) => {
38941
+ onPositionChange?.(pos);
38942
+ if (persistPosition || persistSize) {
38943
+ savePersistedData(pos, size);
38944
+ }
38945
+ },
38946
+ onSizeChange: (newSize) => {
38947
+ onSizeChange?.(newSize);
38948
+ if (persistPosition || persistSize) {
38949
+ savePersistedData(position3, newSize);
38950
+ }
38951
+ }
38952
+ });
38953
+ const handleDragStart = (e3) => {
38954
+ dragHandlers.onMouseDown(e3);
38955
+ onDragStart?.();
38956
+ };
38957
+ const handleResizeStart = (direction) => (e3) => {
38958
+ resizeHandlers[direction].onMouseDown(e3);
38959
+ onResizeStart?.();
38960
+ };
38961
+ (0, import_react13.useEffect)(() => {
38962
+ if (!isDragging) {
38963
+ onDragEnd?.();
38964
+ }
38965
+ }, [isDragging, onDragEnd]);
38966
+ (0, import_react13.useEffect)(() => {
38967
+ if (!isResizing) {
38968
+ onResizeEnd?.();
38969
+ }
38970
+ }, [isResizing, onResizeEnd]);
38971
+ const containerStyle = {
38972
+ position: "fixed",
38973
+ left: position3.x,
38974
+ top: position3.y,
38975
+ width: size.width,
38976
+ height: size.height,
38977
+ transform: "none",
38978
+ // We use left/top instead of transform for better performance
38979
+ zIndex: 1e3,
38980
+ ...style
38981
+ };
38982
+ const containerClassName = [
38983
+ "draggable-resizable-container",
38984
+ isDragging ? "is-dragging" : "",
38985
+ isResizing ? "is-resizing" : "",
38986
+ className
38987
+ ].filter(Boolean).join(" ");
38988
+ return /* @__PURE__ */ import_react13.default.createElement(
38989
+ "div",
38990
+ {
38991
+ ref: containerRef,
38992
+ className: containerClassName,
38993
+ style: containerStyle,
38994
+ "data-cuekit-ignore": true
38995
+ },
38996
+ /* @__PURE__ */ import_react13.default.createElement(
38997
+ "div",
38998
+ {
38999
+ className: "drag-handle",
39000
+ style: {
39001
+ position: "absolute",
39002
+ top: 0,
39003
+ left: 0,
39004
+ right: 0,
39005
+ height: "20px",
39006
+ // Height of the header area
39007
+ cursor: "move",
39008
+ zIndex: 10
39009
+ },
39010
+ onMouseDown: handleDragStart,
39011
+ "data-drag-handle": "true"
39012
+ }
39013
+ ),
39014
+ /* @__PURE__ */ import_react13.default.createElement(
39015
+ "div",
39016
+ {
39017
+ className: "draggable-content",
39018
+ style: {
39019
+ width: "100%",
39020
+ height: "100%",
39021
+ overflow: "hidden",
39022
+ display: "flex",
39023
+ flexDirection: "column"
39024
+ }
39025
+ },
39026
+ children
39027
+ ),
39028
+ showResizeHandles && /* @__PURE__ */ import_react13.default.createElement(
39029
+ ResizeHandles,
39030
+ {
39031
+ onResizeStart: handleResizeStart,
39032
+ disabled: options.disabled,
39033
+ size: resizeHandleSize
39034
+ }
39035
+ )
39036
+ );
39037
+ };
39038
+ var useDraggableResizableContainer = (storageKey) => {
39039
+ const loadData = () => {
39040
+ if (!storageKey || typeof window === "undefined") return null;
39041
+ try {
39042
+ const data = localStorage.getItem(`cuekit-${storageKey}`);
39043
+ return data ? JSON.parse(data) : null;
39044
+ } catch {
39045
+ return null;
39046
+ }
39047
+ };
39048
+ const saveData = (data) => {
39049
+ if (!storageKey || typeof window === "undefined") return;
39050
+ try {
39051
+ localStorage.setItem(`cuekit-${storageKey}`, JSON.stringify(data));
39052
+ } catch (error) {
39053
+ console.warn("Failed to save data:", error);
39054
+ }
39055
+ };
39056
+ const clearData = () => {
39057
+ if (!storageKey || typeof window === "undefined") return;
39058
+ try {
39059
+ localStorage.removeItem(`cuekit-${storageKey}`);
39060
+ } catch (error) {
39061
+ console.warn("Failed to clear data:", error);
39062
+ }
39063
+ };
39064
+ return { loadData, saveData, clearData };
39065
+ };
39066
+
38446
39067
  // src/components/chat-popup.tsx
38447
39068
  var ChatPopup = ({
38448
39069
  isOpen,
@@ -38461,15 +39082,26 @@ var ChatPopup = ({
38461
39082
  status,
38462
39083
  anchor,
38463
39084
  muteState,
38464
- onToggleMute
39085
+ onToggleMute,
39086
+ // Draggable/Resizable props
39087
+ draggable = true,
39088
+ resizable = true,
39089
+ initialPosition,
39090
+ initialSize,
39091
+ onPositionChange,
39092
+ onSizeChange,
39093
+ persistPosition = true,
39094
+ persistSize = true,
39095
+ storageKey = "chat-popup"
38465
39096
  }) => {
38466
- const [inputText, setInputText] = (0, import_react11.useState)("");
38467
- const [isSending, setIsSending] = (0, import_react11.useState)(false);
38468
- const messagesEndRef = (0, import_react11.useRef)(null);
39097
+ const { title, showLogo, showAIIcon, showUserIcon } = useAnsyrContext();
39098
+ const [inputText, setInputText] = (0, import_react14.useState)("");
39099
+ const [isSending, setIsSending] = (0, import_react14.useState)(false);
39100
+ const messagesEndRef = (0, import_react14.useRef)(null);
38469
39101
  const scrollToBottom = () => {
38470
39102
  messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
38471
39103
  };
38472
- (0, import_react11.useEffect)(() => {
39104
+ (0, import_react14.useEffect)(() => {
38473
39105
  console.log("\u{1F4EC} ChatPopup received messages:", JSON.stringify(messages, null, 2));
38474
39106
  scrollToBottom();
38475
39107
  }, [messages]);
@@ -38491,7 +39123,6 @@ var ChatPopup = ({
38491
39123
  handleSend();
38492
39124
  }
38493
39125
  };
38494
- if (!isOpen || isMinimized) return null;
38495
39126
  const getStatusText = () => {
38496
39127
  if (status) return status;
38497
39128
  if (micState === "listening") return "Listening...";
@@ -38499,48 +39130,57 @@ var ChatPopup = ({
38499
39130
  if (micState === "replying") return "Responding...";
38500
39131
  return "Listening...";
38501
39132
  };
38502
- const getPositionStyle = () => {
39133
+ const getInitialPosition = () => {
39134
+ if (initialPosition) return initialPosition;
38503
39135
  if (!anchor) {
38504
39136
  return {
38505
- bottom: "100px",
38506
- right: "20px"
39137
+ x: window.innerWidth - 420 - 20,
39138
+ y: window.innerHeight - window.innerHeight * 0.55 - 20
38507
39139
  };
38508
39140
  }
38509
39141
  const bottomOffset = anchor.bottom + anchor.size + 16;
38510
- const baseStyle = {
38511
- bottom: `${bottomOffset}px`
38512
- };
39142
+ const popupHeight = window.innerHeight * 0.55;
39143
+ const y = window.innerHeight - bottomOffset - popupHeight;
38513
39144
  switch (anchor.position) {
38514
39145
  case "bottom-center":
38515
- return {
38516
- ...baseStyle,
38517
- left: "50%",
38518
- transform: "translateX(-50%)"
38519
- };
39146
+ return { x: (window.innerWidth - 420) / 2, y };
38520
39147
  case "bottom-left":
38521
- return {
38522
- ...baseStyle,
38523
- left: "20px"
38524
- };
39148
+ return { x: 20, y };
38525
39149
  case "bottom-right":
38526
39150
  default:
38527
- return {
38528
- ...baseStyle,
38529
- right: "20px"
38530
- };
39151
+ return { x: window.innerWidth - 420 - 20, y };
38531
39152
  }
38532
39153
  };
38533
- const positionStyle = getPositionStyle();
38534
- return /* @__PURE__ */ import_react11.default.createElement(
38535
- "div",
39154
+ const getInitialSize = () => {
39155
+ if (initialSize) return initialSize;
39156
+ return {
39157
+ width: 420,
39158
+ height: window.innerHeight * 0.55
39159
+ };
39160
+ };
39161
+ if (!isOpen || isMinimized) return null;
39162
+ return /* @__PURE__ */ import_react14.default.createElement(
39163
+ DraggableResizableContainer,
38536
39164
  {
38537
- "data-cuekit-ignore": true,
39165
+ initialPosition: getInitialPosition(),
39166
+ initialSize: getInitialSize(),
39167
+ onPositionChange,
39168
+ onSizeChange,
39169
+ persistPosition,
39170
+ persistSize,
39171
+ storageKey,
39172
+ disabled: !draggable && !resizable,
39173
+ showResizeHandles: resizable,
39174
+ bounds: {
39175
+ minWidth: 300,
39176
+ minHeight: 200,
39177
+ maxWidth: Math.min(window.innerWidth * 0.92, 800),
39178
+ // Cap at 800px max width
39179
+ maxHeight: Math.min(window.innerHeight * 0.9, 600)
39180
+ // Cap at 600px max height
39181
+ },
38538
39182
  className: `cuekit-voice-popup ${currentTheme === "dark" ? "cuekit-dark" : ""}`,
38539
39183
  style: {
38540
- position: "fixed",
38541
- width: "420px",
38542
- maxWidth: "92vw",
38543
- height: "55vh",
38544
39184
  borderRadius: "10px",
38545
39185
  background: "hsl(var(--voice-bg))",
38546
39186
  boxShadow: "var(--shadow-card)",
@@ -38548,13 +39188,11 @@ var ChatPopup = ({
38548
39188
  display: "flex",
38549
39189
  animation: "scaleIn 0.3s ease-out",
38550
39190
  flexDirection: "column",
38551
- zIndex: 1e3,
38552
39191
  fontFamily: "Inter, system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif",
38553
- overflow: "hidden",
38554
- ...positionStyle
39192
+ overflow: "hidden"
38555
39193
  }
38556
39194
  },
38557
- /* @__PURE__ */ import_react11.default.createElement(
39195
+ /* @__PURE__ */ import_react14.default.createElement(
38558
39196
  "div",
38559
39197
  {
38560
39198
  style: {
@@ -38565,14 +39203,14 @@ var ChatPopup = ({
38565
39203
  justifyContent: "space-between"
38566
39204
  }
38567
39205
  },
38568
- /* @__PURE__ */ import_react11.default.createElement("div", { style: { display: "flex", alignItems: "center", gap: 0 } }, /* @__PURE__ */ import_react11.default.createElement(
39206
+ /* @__PURE__ */ import_react14.default.createElement("div", { style: { display: "flex", alignItems: "center", gap: 0 } }, showLogo && /* @__PURE__ */ import_react14.default.createElement(
38569
39207
  "img",
38570
39208
  {
38571
39209
  src: "https://dashboard.cuekit.ai/_next/image?url=%2Fimages%2Fcuekit-logo-2.png&w=256&q=100",
38572
39210
  alt: "Cuekit AI",
38573
39211
  style: { width: 58, objectFit: "cover" }
38574
39212
  }
38575
- ), /* @__PURE__ */ import_react11.default.createElement(
39213
+ ), /* @__PURE__ */ import_react14.default.createElement(
38576
39214
  "div",
38577
39215
  {
38578
39216
  style: {
@@ -38583,10 +39221,11 @@ var ChatPopup = ({
38583
39221
  justifyContent: "center"
38584
39222
  }
38585
39223
  },
38586
- /* @__PURE__ */ import_react11.default.createElement(
39224
+ /* @__PURE__ */ import_react14.default.createElement(
38587
39225
  "span",
38588
39226
  {
38589
39227
  style: {
39228
+ paddingLeft: showLogo ? 0 : 12,
38590
39229
  fontSize: 18,
38591
39230
  fontWeight: 700,
38592
39231
  lineHeight: "1.2",
@@ -38598,9 +39237,9 @@ var ChatPopup = ({
38598
39237
  WebkitTextFillColor: "transparent"
38599
39238
  }
38600
39239
  },
38601
- "ansyr.ai"
39240
+ title
38602
39241
  ),
38603
- /* @__PURE__ */ import_react11.default.createElement("div", { style: { display: "flex", flexDirection: "column", alignItems: "center", gap: 4 } }, /* @__PURE__ */ import_react11.default.createElement(
39242
+ /* @__PURE__ */ import_react14.default.createElement("div", { style: { display: "flex", flexDirection: "column", alignItems: "center", gap: 4 } }, /* @__PURE__ */ import_react14.default.createElement(
38604
39243
  "div",
38605
39244
  {
38606
39245
  style: {
@@ -38616,7 +39255,7 @@ var ChatPopup = ({
38616
39255
  fontWeight: "500"
38617
39256
  }
38618
39257
  },
38619
- /* @__PURE__ */ import_react11.default.createElement(
39258
+ /* @__PURE__ */ import_react14.default.createElement(
38620
39259
  "span",
38621
39260
  {
38622
39261
  style: {
@@ -38627,8 +39266,8 @@ var ChatPopup = ({
38627
39266
  )
38628
39267
  ))
38629
39268
  )),
38630
- /* @__PURE__ */ import_react11.default.createElement("div", { style: { minWidth: 100, textAlign: "center" } }),
38631
- /* @__PURE__ */ import_react11.default.createElement(
39269
+ /* @__PURE__ */ import_react14.default.createElement("div", { style: { minWidth: 100, textAlign: "center" } }),
39270
+ /* @__PURE__ */ import_react14.default.createElement(
38632
39271
  "div",
38633
39272
  {
38634
39273
  style: {
@@ -38640,7 +39279,7 @@ var ChatPopup = ({
38640
39279
  top: 16
38641
39280
  }
38642
39281
  },
38643
- onThemeToggle && /* @__PURE__ */ import_react11.default.createElement(
39282
+ onThemeToggle && /* @__PURE__ */ import_react14.default.createElement(
38644
39283
  "button",
38645
39284
  {
38646
39285
  onClick: () => {
@@ -38670,7 +39309,7 @@ var ChatPopup = ({
38670
39309
  "aria-label": "Toggle theme",
38671
39310
  title: `Switch to ${currentTheme === "dark" ? "light" : "dark"} mode`
38672
39311
  },
38673
- currentTheme === "dark" ? /* @__PURE__ */ import_react11.default.createElement(
39312
+ currentTheme === "dark" ? /* @__PURE__ */ import_react14.default.createElement(
38674
39313
  sun_default,
38675
39314
  {
38676
39315
  style: {
@@ -38680,7 +39319,7 @@ var ChatPopup = ({
38680
39319
  animation: "themeToggleEnter 0.3s ease-in-out"
38681
39320
  }
38682
39321
  }
38683
- ) : /* @__PURE__ */ import_react11.default.createElement(
39322
+ ) : /* @__PURE__ */ import_react14.default.createElement(
38684
39323
  moon_default,
38685
39324
  {
38686
39325
  style: {
@@ -38692,7 +39331,7 @@ var ChatPopup = ({
38692
39331
  }
38693
39332
  )
38694
39333
  ),
38695
- /* @__PURE__ */ import_react11.default.createElement(
39334
+ /* @__PURE__ */ import_react14.default.createElement(
38696
39335
  "button",
38697
39336
  {
38698
39337
  onClick: onMinimize,
@@ -38719,11 +39358,11 @@ var ChatPopup = ({
38719
39358
  "aria-label": "Minimize",
38720
39359
  title: "Minimize chat"
38721
39360
  },
38722
- /* @__PURE__ */ import_react11.default.createElement(close_default, { style: { width: 16, height: 16, color: "hsl(var(--voice-text-muted))" } })
39361
+ /* @__PURE__ */ import_react14.default.createElement(close_default, { style: { width: 16, height: 16, color: "hsl(var(--voice-text-muted))" } })
38723
39362
  )
38724
39363
  )
38725
39364
  ),
38726
- /* @__PURE__ */ import_react11.default.createElement(
39365
+ /* @__PURE__ */ import_react14.default.createElement(
38727
39366
  "div",
38728
39367
  {
38729
39368
  style: {
@@ -38736,7 +39375,7 @@ var ChatPopup = ({
38736
39375
  color: "hsl(var(--voice-text))"
38737
39376
  }
38738
39377
  },
38739
- messages.length === 0 ? /* @__PURE__ */ import_react11.default.createElement(
39378
+ messages.length === 0 ? /* @__PURE__ */ import_react14.default.createElement(
38740
39379
  "div",
38741
39380
  {
38742
39381
  style: {
@@ -38746,7 +39385,7 @@ var ChatPopup = ({
38746
39385
  }
38747
39386
  },
38748
39387
  "Start a conversation with CueKit AI"
38749
- ) : messages.map((message, index2) => /* @__PURE__ */ import_react11.default.createElement(
39388
+ ) : messages.map((message, index2) => /* @__PURE__ */ import_react14.default.createElement(
38750
39389
  "div",
38751
39390
  {
38752
39391
  key: index2,
@@ -38760,7 +39399,7 @@ var ChatPopup = ({
38760
39399
  justifyContent: message.sender === "user" ? "flex-end" : "flex-start"
38761
39400
  }
38762
39401
  },
38763
- message.sender === "assistant" && /* @__PURE__ */ import_react11.default.createElement(
39402
+ message.sender === "assistant" && showAIIcon && /* @__PURE__ */ import_react14.default.createElement(
38764
39403
  "div",
38765
39404
  {
38766
39405
  style: {
@@ -38775,7 +39414,7 @@ var ChatPopup = ({
38775
39414
  overflow: "hidden"
38776
39415
  }
38777
39416
  },
38778
- /* @__PURE__ */ import_react11.default.createElement(
39417
+ /* @__PURE__ */ import_react14.default.createElement(
38779
39418
  "img",
38780
39419
  {
38781
39420
  src: "https://dashboard.cuekit.ai/_next/image?url=%2Fimages%2Fcuekit-logo-2.png&w=256&q=100",
@@ -38789,7 +39428,7 @@ var ChatPopup = ({
38789
39428
  }
38790
39429
  )
38791
39430
  ),
38792
- /* @__PURE__ */ import_react11.default.createElement(
39431
+ /* @__PURE__ */ import_react14.default.createElement(
38793
39432
  "div",
38794
39433
  {
38795
39434
  style: {
@@ -38800,7 +39439,7 @@ var ChatPopup = ({
38800
39439
  flex: 1
38801
39440
  }
38802
39441
  },
38803
- /* @__PURE__ */ import_react11.default.createElement(
39442
+ /* @__PURE__ */ import_react14.default.createElement(
38804
39443
  "div",
38805
39444
  {
38806
39445
  style: {
@@ -38818,12 +39457,12 @@ var ChatPopup = ({
38818
39457
  marginLeft: message.sender === "user" ? "auto" : 0
38819
39458
  }
38820
39459
  },
38821
- /* @__PURE__ */ import_react11.default.createElement("div", null, /* @__PURE__ */ import_react11.default.createElement(
39460
+ /* @__PURE__ */ import_react14.default.createElement("div", null, /* @__PURE__ */ import_react14.default.createElement(
38822
39461
  Markdown,
38823
39462
  {
38824
39463
  remarkPlugins: [remarkGfm],
38825
39464
  components: {
38826
- p: ({ children }) => /* @__PURE__ */ import_react11.default.createElement(
39465
+ p: ({ children }) => /* @__PURE__ */ import_react14.default.createElement(
38827
39466
  "p",
38828
39467
  {
38829
39468
  style: {
@@ -38834,7 +39473,7 @@ var ChatPopup = ({
38834
39473
  },
38835
39474
  children
38836
39475
  ),
38837
- h1: ({ children }) => /* @__PURE__ */ import_react11.default.createElement(
39476
+ h1: ({ children }) => /* @__PURE__ */ import_react14.default.createElement(
38838
39477
  "h1",
38839
39478
  {
38840
39479
  style: {
@@ -38846,7 +39485,7 @@ var ChatPopup = ({
38846
39485
  },
38847
39486
  children
38848
39487
  ),
38849
- h2: ({ children }) => /* @__PURE__ */ import_react11.default.createElement(
39488
+ h2: ({ children }) => /* @__PURE__ */ import_react14.default.createElement(
38850
39489
  "h2",
38851
39490
  {
38852
39491
  style: {
@@ -38858,7 +39497,7 @@ var ChatPopup = ({
38858
39497
  },
38859
39498
  children
38860
39499
  ),
38861
- h3: ({ children }) => /* @__PURE__ */ import_react11.default.createElement(
39500
+ h3: ({ children }) => /* @__PURE__ */ import_react14.default.createElement(
38862
39501
  "h3",
38863
39502
  {
38864
39503
  style: {
@@ -38870,7 +39509,7 @@ var ChatPopup = ({
38870
39509
  },
38871
39510
  children
38872
39511
  ),
38873
- ul: ({ children }) => /* @__PURE__ */ import_react11.default.createElement(
39512
+ ul: ({ children }) => /* @__PURE__ */ import_react14.default.createElement(
38874
39513
  "ul",
38875
39514
  {
38876
39515
  style: {
@@ -38882,7 +39521,7 @@ var ChatPopup = ({
38882
39521
  },
38883
39522
  children
38884
39523
  ),
38885
- ol: ({ children }) => /* @__PURE__ */ import_react11.default.createElement(
39524
+ ol: ({ children }) => /* @__PURE__ */ import_react14.default.createElement(
38886
39525
  "ol",
38887
39526
  {
38888
39527
  style: {
@@ -38894,7 +39533,7 @@ var ChatPopup = ({
38894
39533
  },
38895
39534
  children
38896
39535
  ),
38897
- li: ({ children }) => /* @__PURE__ */ import_react11.default.createElement(
39536
+ li: ({ children }) => /* @__PURE__ */ import_react14.default.createElement(
38898
39537
  "li",
38899
39538
  {
38900
39539
  style: {
@@ -38905,7 +39544,7 @@ var ChatPopup = ({
38905
39544
  },
38906
39545
  children
38907
39546
  ),
38908
- strong: ({ children }) => /* @__PURE__ */ import_react11.default.createElement(
39547
+ strong: ({ children }) => /* @__PURE__ */ import_react14.default.createElement(
38909
39548
  "strong",
38910
39549
  {
38911
39550
  style: {
@@ -38916,7 +39555,7 @@ var ChatPopup = ({
38916
39555
  },
38917
39556
  children
38918
39557
  ),
38919
- em: ({ children }) => /* @__PURE__ */ import_react11.default.createElement(
39558
+ em: ({ children }) => /* @__PURE__ */ import_react14.default.createElement(
38920
39559
  "em",
38921
39560
  {
38922
39561
  style: {
@@ -38927,7 +39566,7 @@ var ChatPopup = ({
38927
39566
  },
38928
39567
  children
38929
39568
  ),
38930
- code: ({ children }) => /* @__PURE__ */ import_react11.default.createElement(
39569
+ code: ({ children }) => /* @__PURE__ */ import_react14.default.createElement(
38931
39570
  "code",
38932
39571
  {
38933
39572
  style: {
@@ -38940,7 +39579,7 @@ var ChatPopup = ({
38940
39579
  },
38941
39580
  children
38942
39581
  ),
38943
- pre: ({ children }) => /* @__PURE__ */ import_react11.default.createElement(
39582
+ pre: ({ children }) => /* @__PURE__ */ import_react14.default.createElement(
38944
39583
  "pre",
38945
39584
  {
38946
39585
  style: {
@@ -38955,7 +39594,7 @@ var ChatPopup = ({
38955
39594
  },
38956
39595
  children
38957
39596
  ),
38958
- blockquote: ({ children }) => /* @__PURE__ */ import_react11.default.createElement(
39597
+ blockquote: ({ children }) => /* @__PURE__ */ import_react14.default.createElement(
38959
39598
  "blockquote",
38960
39599
  {
38961
39600
  style: {
@@ -38974,7 +39613,7 @@ var ChatPopup = ({
38974
39613
  message.text
38975
39614
  ))
38976
39615
  ),
38977
- message.sender === "user" && /* @__PURE__ */ import_react11.default.createElement(
39616
+ message.sender === "user" && showUserIcon && /* @__PURE__ */ import_react14.default.createElement(
38978
39617
  "div",
38979
39618
  {
38980
39619
  style: {
@@ -38995,9 +39634,9 @@ var ChatPopup = ({
38995
39634
  )
38996
39635
  )
38997
39636
  )),
38998
- /* @__PURE__ */ import_react11.default.createElement("div", { ref: messagesEndRef })
39637
+ /* @__PURE__ */ import_react14.default.createElement("div", { ref: messagesEndRef })
38999
39638
  ),
39000
- /* @__PURE__ */ import_react11.default.createElement(
39639
+ /* @__PURE__ */ import_react14.default.createElement(
39001
39640
  "div",
39002
39641
  {
39003
39642
  style: {
@@ -39006,7 +39645,7 @@ var ChatPopup = ({
39006
39645
  background: "hsl(var(--voice-bg))"
39007
39646
  }
39008
39647
  },
39009
- /* @__PURE__ */ import_react11.default.createElement(
39648
+ /* @__PURE__ */ import_react14.default.createElement(
39010
39649
  "form",
39011
39650
  {
39012
39651
  onSubmit: (e3) => {
@@ -39015,7 +39654,7 @@ var ChatPopup = ({
39015
39654
  },
39016
39655
  style: { display: "flex", alignItems: "center", gap: 8, margin: 0 }
39017
39656
  },
39018
- /* @__PURE__ */ import_react11.default.createElement(
39657
+ /* @__PURE__ */ import_react14.default.createElement(
39019
39658
  "input",
39020
39659
  {
39021
39660
  type: "text",
@@ -39042,7 +39681,7 @@ var ChatPopup = ({
39042
39681
  }
39043
39682
  }
39044
39683
  ),
39045
- muteState?.canMute && onToggleMute && /* @__PURE__ */ import_react11.default.createElement(
39684
+ muteState?.canMute && onToggleMute && /* @__PURE__ */ import_react14.default.createElement(
39046
39685
  "button",
39047
39686
  {
39048
39687
  onClick: onToggleMute,
@@ -39062,8 +39701,8 @@ var ChatPopup = ({
39062
39701
  "aria-label": muteState.isMuted ? "Unmute microphone" : "Mute microphone",
39063
39702
  title: muteState.isMuted ? "Unmute microphone" : "Mute microphone"
39064
39703
  },
39065
- muteState.isMuted ? /* @__PURE__ */ import_react11.default.createElement(
39066
- mic_default,
39704
+ muteState.isMuted ? /* @__PURE__ */ import_react14.default.createElement(
39705
+ mic_off_default,
39067
39706
  {
39068
39707
  style: {
39069
39708
  width: 16,
@@ -39071,8 +39710,8 @@ var ChatPopup = ({
39071
39710
  color: "hsl(var(--voice-user-text))"
39072
39711
  }
39073
39712
  }
39074
- ) : /* @__PURE__ */ import_react11.default.createElement(
39075
- mic_off_default,
39713
+ ) : /* @__PURE__ */ import_react14.default.createElement(
39714
+ mic_default,
39076
39715
  {
39077
39716
  style: {
39078
39717
  width: 16,
@@ -39082,7 +39721,7 @@ var ChatPopup = ({
39082
39721
  }
39083
39722
  )
39084
39723
  ),
39085
- isConnected2 && onEndCall && /* @__PURE__ */ import_react11.default.createElement(
39724
+ isConnected2 && onEndCall && /* @__PURE__ */ import_react14.default.createElement(
39086
39725
  "button",
39087
39726
  {
39088
39727
  type: "submit",
@@ -39101,7 +39740,7 @@ var ChatPopup = ({
39101
39740
  cursor: "pointer"
39102
39741
  }
39103
39742
  },
39104
- /* @__PURE__ */ import_react11.default.createElement(phone_off_default, { style: { width: 16, height: 16 } })
39743
+ /* @__PURE__ */ import_react14.default.createElement(phone_off_default, { style: { width: 16, height: 16 } })
39105
39744
  )
39106
39745
  )
39107
39746
  )
@@ -39109,7 +39748,7 @@ var ChatPopup = ({
39109
39748
  };
39110
39749
 
39111
39750
  // src/components/border-glow.tsx
39112
- var import_react12 = __toESM(require("react"));
39751
+ var import_react15 = __toESM(require("react"));
39113
39752
  var BorderGlow = ({ isActive }) => {
39114
39753
  if (!isActive) return null;
39115
39754
  const styles = {
@@ -39236,7 +39875,7 @@ var BorderGlow = ({ isActive }) => {
39236
39875
  opacity: 0.6
39237
39876
  }
39238
39877
  };
39239
- return /* @__PURE__ */ import_react12.default.createElement(import_react12.default.Fragment, null, /* @__PURE__ */ import_react12.default.createElement("style", null, `
39878
+ return /* @__PURE__ */ import_react15.default.createElement(import_react15.default.Fragment, null, /* @__PURE__ */ import_react15.default.createElement("style", null, `
39240
39879
  @keyframes borderPulse {
39241
39880
  0%, 100% {
39242
39881
  opacity: 1;
@@ -39245,12 +39884,12 @@ var BorderGlow = ({ isActive }) => {
39245
39884
  opacity: 0.5;
39246
39885
  }
39247
39886
  }
39248
- `), /* @__PURE__ */ import_react12.default.createElement("div", { style: styles.container }, /* @__PURE__ */ import_react12.default.createElement("div", { style: styles.rightBorder1 }), /* @__PURE__ */ import_react12.default.createElement("div", { style: styles.rightBorder2 }), /* @__PURE__ */ import_react12.default.createElement("div", { style: styles.rightBorder3 }), /* @__PURE__ */ import_react12.default.createElement("div", { style: styles.leftBorder1 }), /* @__PURE__ */ import_react12.default.createElement("div", { style: styles.leftBorder2 }), /* @__PURE__ */ import_react12.default.createElement("div", { style: styles.leftBorder3 }), /* @__PURE__ */ import_react12.default.createElement("div", { style: styles.cornerTopLeft }), /* @__PURE__ */ import_react12.default.createElement("div", { style: styles.cornerTopRight }), /* @__PURE__ */ import_react12.default.createElement("div", { style: styles.cornerBottomRight }), /* @__PURE__ */ import_react12.default.createElement("div", { style: styles.cornerBottomLeft })));
39887
+ `), /* @__PURE__ */ import_react15.default.createElement("div", { style: styles.container }, /* @__PURE__ */ import_react15.default.createElement("div", { style: styles.rightBorder1 }), /* @__PURE__ */ import_react15.default.createElement("div", { style: styles.rightBorder2 }), /* @__PURE__ */ import_react15.default.createElement("div", { style: styles.rightBorder3 }), /* @__PURE__ */ import_react15.default.createElement("div", { style: styles.leftBorder1 }), /* @__PURE__ */ import_react15.default.createElement("div", { style: styles.leftBorder2 }), /* @__PURE__ */ import_react15.default.createElement("div", { style: styles.leftBorder3 }), /* @__PURE__ */ import_react15.default.createElement("div", { style: styles.cornerTopLeft }), /* @__PURE__ */ import_react15.default.createElement("div", { style: styles.cornerTopRight }), /* @__PURE__ */ import_react15.default.createElement("div", { style: styles.cornerBottomRight }), /* @__PURE__ */ import_react15.default.createElement("div", { style: styles.cornerBottomLeft })));
39249
39888
  };
39250
39889
  var border_glow_default = BorderGlow;
39251
39890
 
39252
39891
  // src/components/voice-intensity-visualizer.tsx
39253
- var import_react14 = __toESM(require("react"));
39892
+ var import_react17 = __toESM(require("react"));
39254
39893
 
39255
39894
  // node_modules/@livekit/components-react/dist/hooks-C2Bp5v2q.mjs
39256
39895
  var r2 = __toESM(require("react"), 1);
@@ -40896,7 +41535,7 @@ function Yt(e3, t = {}) {
40896
41535
 
40897
41536
  // node_modules/@livekit/components-react/dist/components-Bz2b1Fa9.mjs
40898
41537
  var e2 = __toESM(require("react"), 1);
40899
- var import_react13 = require("react");
41538
+ var import_react16 = require("react");
40900
41539
  init_livekit_client_esm();
40901
41540
  var Y;
40902
41541
  var ue;
@@ -40991,8 +41630,8 @@ var Dt = (t) => {
40991
41630
  };
40992
41631
  var fe2 = (t) => [[Math.floor(t / 2)], [-1]];
40993
41632
  var Ut2 = (t, n, a) => {
40994
- const [r3, c] = (0, import_react13.useState)(0), [s, o2] = (0, import_react13.useState)([[]]);
40995
- (0, import_react13.useEffect)(() => {
41633
+ const [r3, c] = (0, import_react16.useState)(0), [s, o2] = (0, import_react16.useState)([[]]);
41634
+ (0, import_react16.useEffect)(() => {
40996
41635
  if (t === "thinking")
40997
41636
  o2(fe2(n));
40998
41637
  else if (t === "connecting" || t === "initializing") {
@@ -41001,8 +41640,8 @@ var Ut2 = (t, n, a) => {
41001
41640
  } else o2(t === "listening" ? fe2(n) : t === void 0 || t === "speaking" ? [new Array(n).fill(0).map((i2, u) => u)] : [[]]);
41002
41641
  c(0);
41003
41642
  }, [t, n]);
41004
- const l = (0, import_react13.useRef)(null);
41005
- return (0, import_react13.useEffect)(() => {
41643
+ const l = (0, import_react16.useRef)(null);
41644
+ return (0, import_react16.useEffect)(() => {
41006
41645
  let i2 = performance.now();
41007
41646
  const u = (d) => {
41008
41647
  d - i2 >= a && (c((f) => f + 1), i2 = d), l.current = requestAnimationFrame(u);
@@ -41072,8 +41711,8 @@ var Xt = /* @__PURE__ */ e2.forwardRef(
41072
41711
  init_livekit_client_esm();
41073
41712
  init_webrtc_service();
41074
41713
  var VoiceIntensityWithRoom = (props) => {
41075
- const [room2, setRoom] = (0, import_react14.useState)(null);
41076
- (0, import_react14.useEffect)(() => {
41714
+ const [room2, setRoom] = (0, import_react17.useState)(null);
41715
+ (0, import_react17.useEffect)(() => {
41077
41716
  if (props.isActive) {
41078
41717
  const currentRoom = getRoom();
41079
41718
  if (currentRoom) {
@@ -41086,7 +41725,7 @@ var VoiceIntensityWithRoom = (props) => {
41086
41725
  if (!room2) {
41087
41726
  return null;
41088
41727
  }
41089
- return /* @__PURE__ */ import_react14.default.createElement(Wn.Provider, { value: room2 }, /* @__PURE__ */ import_react14.default.createElement(VoiceIntensityBars, { ...props }));
41728
+ return /* @__PURE__ */ import_react17.default.createElement(Wn.Provider, { value: room2 }, /* @__PURE__ */ import_react17.default.createElement(VoiceIntensityBars, { ...props }));
41090
41729
  };
41091
41730
  var VoiceIntensityBars = ({
41092
41731
  isActive,
@@ -41129,7 +41768,7 @@ var VoiceIntensityBars = ({
41129
41768
  if (!trackRef) {
41130
41769
  return null;
41131
41770
  }
41132
- return /* @__PURE__ */ import_react14.default.createElement(
41771
+ return /* @__PURE__ */ import_react17.default.createElement(
41133
41772
  "div",
41134
41773
  {
41135
41774
  className: `voice-intensity-visualizer ${className}`,
@@ -41146,7 +41785,7 @@ var VoiceIntensityBars = ({
41146
41785
  pointerEvents: "none"
41147
41786
  }
41148
41787
  },
41149
- /* @__PURE__ */ import_react14.default.createElement(
41788
+ /* @__PURE__ */ import_react17.default.createElement(
41150
41789
  Xt,
41151
41790
  {
41152
41791
  barCount,
@@ -41160,7 +41799,7 @@ var VoiceIntensityBars = ({
41160
41799
  gap: "0.25rem"
41161
41800
  }
41162
41801
  },
41163
- /* @__PURE__ */ import_react14.default.createElement("span", { className: "cuekit-voice-intensity-bar" })
41802
+ /* @__PURE__ */ import_react17.default.createElement("span", { className: "cuekit-voice-intensity-bar" })
41164
41803
  )
41165
41804
  );
41166
41805
  };
@@ -41168,12 +41807,146 @@ var VoiceIntensityVisualizer = VoiceIntensityWithRoom;
41168
41807
 
41169
41808
  // src/components/mic-button.tsx
41170
41809
  init_webrtc_service();
41810
+
41811
+ // src/components/language-selector.tsx
41812
+ var import_react19 = __toESM(require("react"));
41813
+
41814
+ // src/components/svgs/chevron-down.tsx
41815
+ var import_react18 = __toESM(require("react"));
41816
+ function ChevronDownIcon({
41817
+ width = 24,
41818
+ height = 24,
41819
+ className,
41820
+ ...props
41821
+ }) {
41822
+ return /* @__PURE__ */ import_react18.default.createElement(
41823
+ "svg",
41824
+ {
41825
+ xmlns: "http://www.w3.org/2000/svg",
41826
+ width,
41827
+ height,
41828
+ viewBox: "0 0 24 24",
41829
+ fill: "none",
41830
+ stroke: "currentColor",
41831
+ "stroke-width": "2",
41832
+ "stroke-linecap": "round",
41833
+ "stroke-linejoin": "round",
41834
+ className,
41835
+ ...props
41836
+ },
41837
+ /* @__PURE__ */ import_react18.default.createElement("path", { d: "m6 9 6 6 6-6" })
41838
+ );
41839
+ }
41840
+
41841
+ // src/components/language-selector.tsx
41842
+ var FLAG_EMOJIS = {
41843
+ "en-US": "\u{1F1FA}\u{1F1F8}",
41844
+ "ar-SA": "\u{1F1F8}\u{1F1E6}",
41845
+ "es-ES": "\u{1F1EA}\u{1F1F8}",
41846
+ "fr-FR": "\u{1F1EB}\u{1F1F7}",
41847
+ "de-DE": "\u{1F1E9}\u{1F1EA}",
41848
+ "it-IT": "\u{1F1EE}\u{1F1F9}",
41849
+ "pt-BR": "\u{1F1E7}\u{1F1F7}",
41850
+ "ja-JP": "\u{1F1EF}\u{1F1F5}",
41851
+ "ko-KR": "\u{1F1F0}\u{1F1F7}",
41852
+ "zh-CN": "\u{1F1E8}\u{1F1F3}",
41853
+ "hi-IN": "\u{1F1EE}\u{1F1F3}"
41854
+ };
41855
+ var LanguageSelector = ({
41856
+ selectedLanguage,
41857
+ onLanguageChange,
41858
+ availableLanguages,
41859
+ disabled = false,
41860
+ className = "",
41861
+ tooltip,
41862
+ screenPosition = "bottom-center"
41863
+ }) => {
41864
+ const [isOpen, setIsOpen] = (0, import_react19.useState)(false);
41865
+ const [showTooltip, setShowTooltip] = (0, import_react19.useState)(false);
41866
+ const [dropdownUp, setDropdownUp] = (0, import_react19.useState)(false);
41867
+ const dropdownRef = (0, import_react19.useRef)(null);
41868
+ (0, import_react19.useEffect)(() => {
41869
+ const handleClickOutside = (event) => {
41870
+ if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
41871
+ setIsOpen(false);
41872
+ }
41873
+ };
41874
+ document.addEventListener("mousedown", handleClickOutside);
41875
+ return () => {
41876
+ document.removeEventListener("mousedown", handleClickOutside);
41877
+ };
41878
+ }, []);
41879
+ const handleLanguageSelect = (language) => {
41880
+ if (disabled) return;
41881
+ onLanguageChange(language);
41882
+ setIsOpen(false);
41883
+ };
41884
+ const handleButtonClick = () => {
41885
+ if (disabled) return;
41886
+ const isBottomPosition = screenPosition.startsWith("bottom");
41887
+ setDropdownUp(isBottomPosition);
41888
+ setIsOpen(!isOpen);
41889
+ };
41890
+ const getFlagEmoji = (code4) => {
41891
+ return FLAG_EMOJIS[code4] || "\u{1F310}";
41892
+ };
41893
+ return /* @__PURE__ */ import_react19.default.createElement(
41894
+ "div",
41895
+ {
41896
+ className: `language-selector-container ${className}`,
41897
+ ref: dropdownRef,
41898
+ onMouseEnter: () => {
41899
+ if (disabled) {
41900
+ setShowTooltip(true);
41901
+ }
41902
+ },
41903
+ onMouseLeave: () => {
41904
+ setShowTooltip(false);
41905
+ }
41906
+ },
41907
+ /* @__PURE__ */ import_react19.default.createElement(
41908
+ "button",
41909
+ {
41910
+ className: `language-selector-button ${isOpen ? "open" : ""} ${disabled ? "disabled" : ""}`,
41911
+ onClick: handleButtonClick,
41912
+ disabled,
41913
+ "aria-label": disabled ? tooltip || "Language cannot be changed during conversation" : "Select language",
41914
+ "aria-expanded": isOpen,
41915
+ "aria-haspopup": "listbox"
41916
+ },
41917
+ /* @__PURE__ */ import_react19.default.createElement("div", { className: "language-selector-content" }, /* @__PURE__ */ import_react19.default.createElement("span", { className: "language-flag" }, getFlagEmoji(selectedLanguage.code)), /* @__PURE__ */ import_react19.default.createElement("span", { className: "language-code" }, selectedLanguage.code), /* @__PURE__ */ import_react19.default.createElement(
41918
+ ChevronDownIcon,
41919
+ {
41920
+ className: `language-chevron ${isOpen ? dropdownUp ? "rotated-up" : "rotated" : ""}`,
41921
+ width: 14,
41922
+ height: 14
41923
+ }
41924
+ ))
41925
+ ),
41926
+ disabled && /* @__PURE__ */ import_react19.default.createElement("div", { className: `language-tooltip ${showTooltip ? "show" : ""}` }, /* @__PURE__ */ import_react19.default.createElement("div", { className: "language-tooltip-content" }, tooltip || "Close the conversation to change the language"), /* @__PURE__ */ import_react19.default.createElement("div", { className: "language-tooltip-arrow" })),
41927
+ isOpen && /* @__PURE__ */ import_react19.default.createElement("div", { className: `language-dropdown ${dropdownUp ? "dropdown-up" : ""}` }, /* @__PURE__ */ import_react19.default.createElement("div", { className: "language-dropdown-content" }, availableLanguages.map((language) => /* @__PURE__ */ import_react19.default.createElement(
41928
+ "button",
41929
+ {
41930
+ key: language.code,
41931
+ className: `language-option ${selectedLanguage.code === language.code ? "selected" : ""}`,
41932
+ onClick: () => handleLanguageSelect(language),
41933
+ role: "option",
41934
+ "aria-selected": selectedLanguage.code === language.code
41935
+ },
41936
+ /* @__PURE__ */ import_react19.default.createElement("span", { className: "language-flag" }, getFlagEmoji(language.code)),
41937
+ /* @__PURE__ */ import_react19.default.createElement("div", { className: "language-info" }, /* @__PURE__ */ import_react19.default.createElement("span", { className: "language-name" }, language.name)),
41938
+ selectedLanguage.code === language.code && /* @__PURE__ */ import_react19.default.createElement("div", { className: "language-check" }, "\u2713")
41939
+ ))))
41940
+ );
41941
+ };
41942
+
41943
+ // src/components/mic-button.tsx
41171
41944
  var chatState = {
41172
41945
  isOpen: false,
41173
41946
  isMinimized: false
41174
41947
  };
41175
41948
  var VoiceIntensityWrapper = ({ active, buttonSize }) => {
41176
- return /* @__PURE__ */ import_react15.default.createElement(
41949
+ return /* @__PURE__ */ import_react20.default.createElement(
41177
41950
  VoiceIntensityVisualizer,
41178
41951
  {
41179
41952
  isActive: active,
@@ -41183,6 +41956,10 @@ var VoiceIntensityWrapper = ({ active, buttonSize }) => {
41183
41956
  }
41184
41957
  );
41185
41958
  };
41959
+ var DEFAULT_LANGUAGES = [
41960
+ { code: "en-US", name: "English (US)", flag: "\u{1F1FA}\u{1F1F8}" },
41961
+ { code: "ar-SA", name: "\u0627\u0644\u0639\u0631\u0628\u064A\u0629", flag: "\u{1F1F8}\u{1F1E6}" }
41962
+ ];
41186
41963
  var MicButton = ({
41187
41964
  buttonSize = 52,
41188
41965
  screenPosition = "bottom-center",
@@ -41194,22 +41971,29 @@ var MicButton = ({
41194
41971
  buttonStyle,
41195
41972
  bottomSpace = 20,
41196
41973
  defaultTheme = "system",
41197
- showBorderGlow = false
41974
+ showBorderGlow = false,
41975
+ language,
41976
+ defaultLanguage,
41977
+ onLanguageChange
41198
41978
  }) => {
41199
- const { apiKey, appId } = useQubeContext();
41200
- const [showBodyGlow, setShowBodyGlow] = (0, import_react15.useState)(false);
41201
- const [currentTheme, setCurrentTheme] = (0, import_react15.useState)("dark");
41202
- const [isChatOpen, setIsChatOpen] = (0, import_react15.useState)(chatState.isOpen);
41203
- const [isChatMinimized, setIsChatMinimized] = (0, import_react15.useState)(chatState.isMinimized);
41204
- (0, import_react15.useEffect)(() => {
41979
+ const { apiKey, appId } = useAnsyrContext();
41980
+ const [showBodyGlow, setShowBodyGlow] = (0, import_react20.useState)(false);
41981
+ const [currentTheme, setCurrentTheme] = (0, import_react20.useState)("dark");
41982
+ const [showLanguageSelector, setShowLanguageSelector] = (0, import_react20.useState)(false);
41983
+ const [selectedLanguage, setSelectedLanguage] = (0, import_react20.useState)(
41984
+ language || defaultLanguage || DEFAULT_LANGUAGES[0]
41985
+ );
41986
+ const [isChatOpen, setIsChatOpen] = (0, import_react20.useState)(chatState.isOpen);
41987
+ const [isChatMinimized, setIsChatMinimized] = (0, import_react20.useState)(chatState.isMinimized);
41988
+ (0, import_react20.useEffect)(() => {
41205
41989
  chatState.isOpen = isChatOpen;
41206
41990
  chatState.isMinimized = isChatMinimized;
41207
41991
  }, [isChatOpen, isChatMinimized]);
41208
- const audioContainerRef2 = (0, import_react15.useRef)(null);
41209
- const silenceTimerRef = (0, import_react15.useRef)(null);
41210
- const aiSpeakingRef = (0, import_react15.useRef)(false);
41211
- const aiSpeechTimeoutRef = (0, import_react15.useRef)(null);
41212
- const activeAITracksRef = (0, import_react15.useRef)(/* @__PURE__ */ new Set());
41992
+ const audioContainerRef2 = (0, import_react20.useRef)(null);
41993
+ const silenceTimerRef = (0, import_react20.useRef)(null);
41994
+ const aiSpeakingRef = (0, import_react20.useRef)(false);
41995
+ const aiSpeechTimeoutRef = (0, import_react20.useRef)(null);
41996
+ const activeAITracksRef = (0, import_react20.useRef)(/* @__PURE__ */ new Set());
41213
41997
  const {
41214
41998
  isConnected: isConnected2,
41215
41999
  isConnecting,
@@ -41239,7 +42023,7 @@ var MicButton = ({
41239
42023
  onAISpeechEnd: (trackId) => handleAISpeech(false, trackId),
41240
42024
  appId
41241
42025
  });
41242
- (0, import_react15.useEffect)(() => {
42026
+ (0, import_react20.useEffect)(() => {
41243
42027
  const checkTheme = () => {
41244
42028
  if (typeof document !== "undefined") {
41245
42029
  let newTheme;
@@ -41262,31 +42046,31 @@ var MicButton = ({
41262
42046
  return () => observer.disconnect();
41263
42047
  }
41264
42048
  }, [defaultTheme]);
41265
- const openChat = (0, import_react15.useCallback)(() => {
42049
+ const openChat = (0, import_react20.useCallback)(() => {
41266
42050
  setIsChatOpen(true);
41267
42051
  setIsChatMinimized(false);
41268
42052
  }, []);
41269
- const minimizeChat = (0, import_react15.useCallback)(() => {
42053
+ const minimizeChat = (0, import_react20.useCallback)(() => {
41270
42054
  setIsChatMinimized(true);
41271
42055
  if (showBorderGlow) {
41272
42056
  setShowBodyGlow(false);
41273
42057
  }
41274
42058
  }, [showBorderGlow]);
41275
- const restoreChat = (0, import_react15.useCallback)(() => {
42059
+ const restoreChat = (0, import_react20.useCallback)(() => {
41276
42060
  setIsChatMinimized(false);
41277
42061
  setIsChatOpen(true);
41278
42062
  if (showBorderGlow && (micState === "listening" || micState === "thinking" || micState === "replying")) {
41279
42063
  setShowBodyGlow(true);
41280
42064
  }
41281
42065
  }, [showBorderGlow, micState]);
41282
- const closeChat = (0, import_react15.useCallback)(() => {
42066
+ const closeChat = (0, import_react20.useCallback)(() => {
41283
42067
  setIsChatOpen(false);
41284
42068
  setIsChatMinimized(false);
41285
42069
  if (showBorderGlow) {
41286
42070
  setShowBodyGlow(false);
41287
42071
  }
41288
42072
  }, [showBorderGlow]);
41289
- const handleAISpeech = (0, import_react15.useCallback)(
42073
+ const handleAISpeech = (0, import_react20.useCallback)(
41290
42074
  (isSpeaking, trackId) => {
41291
42075
  if (isSpeaking && trackId) {
41292
42076
  activeAITracksRef.current.add(trackId);
@@ -41307,7 +42091,7 @@ var MicButton = ({
41307
42091
  },
41308
42092
  [status, micState, isConnected2]
41309
42093
  );
41310
- (0, import_react15.useEffect)(() => {
42094
+ (0, import_react20.useEffect)(() => {
41311
42095
  if (audioContainerRef2.current) {
41312
42096
  setAudioContainer(audioContainerRef2);
41313
42097
  }
@@ -41334,29 +42118,51 @@ var MicButton = ({
41334
42118
  }
41335
42119
  return isConnected3 ? "Ready" : "Connecting...";
41336
42120
  };
41337
- (0, import_react15.useEffect)(() => {
42121
+ (0, import_react20.useEffect)(() => {
41338
42122
  if (isConnected2) {
41339
42123
  } else {
41340
42124
  }
41341
42125
  }, [isConnected2]);
41342
- (0, import_react15.useEffect)(() => {
42126
+ (0, import_react20.useEffect)(() => {
41343
42127
  if (isConnected2 && !isChatOpen) {
41344
42128
  openChat();
41345
42129
  }
41346
42130
  }, [isConnected2, isChatOpen, openChat]);
41347
- (0, import_react15.useEffect)(() => {
42131
+ (0, import_react20.useEffect)(() => {
41348
42132
  if (messageManagerMessages.length > 0 && !isChatOpen) {
41349
42133
  openChat();
41350
42134
  }
41351
42135
  }, [messageManagerMessages.length, isChatOpen, openChat]);
41352
- const handleMicClick = (0, import_react15.useCallback)(() => {
42136
+ const handleLanguageChange = (0, import_react20.useCallback)(
42137
+ (newLanguage) => {
42138
+ setSelectedLanguage(newLanguage);
42139
+ onLanguageChange?.(newLanguage);
42140
+ },
42141
+ [onLanguageChange]
42142
+ );
42143
+ const handleLanguageConfirm = (0, import_react20.useCallback)(() => {
42144
+ setShowLanguageSelector(false);
42145
+ voiceConnect(`user_${Date.now()}`, apiKey, appId, selectedLanguage).then(() => {
42146
+ if (showBorderGlow) setShowBodyGlow(true);
42147
+ openChat();
42148
+ setTimeout(() => {
42149
+ openChat();
42150
+ }, 500);
42151
+ }).catch((error) => {
42152
+ });
42153
+ }, [voiceConnect, apiKey, appId, selectedLanguage, showBorderGlow, openChat]);
42154
+ const handleMicClick = (0, import_react20.useCallback)(() => {
41353
42155
  const shouldStop = micState === "listening" && isConnected2;
41354
42156
  if (shouldStop) {
41355
42157
  voiceDisconnect().then(() => {
41356
42158
  }).catch((error) => {
41357
42159
  });
41358
42160
  } else {
41359
- voiceConnect(`user_${Date.now()}`, apiKey, appId).then(() => {
42161
+ if (!language && !defaultLanguage && !selectedLanguage) {
42162
+ setShowLanguageSelector(true);
42163
+ return;
42164
+ }
42165
+ voiceConnect(`user_${Date.now()}`, apiKey, appId, selectedLanguage).then(() => {
41360
42166
  if (showBorderGlow) setShowBodyGlow(true);
41361
42167
  openChat();
41362
42168
  setTimeout(() => {
@@ -41372,6 +42178,8 @@ var MicButton = ({
41372
42178
  voiceConnect,
41373
42179
  apiKey,
41374
42180
  appId,
42181
+ language,
42182
+ selectedLanguage,
41375
42183
  openChat,
41376
42184
  showBorderGlow,
41377
42185
  sendChatMessage,
@@ -41420,9 +42228,9 @@ var MicButton = ({
41420
42228
  ...imageStyle
41421
42229
  };
41422
42230
  if (micState === "idle") {
41423
- return /* @__PURE__ */ import_react15.default.createElement("img", { src: imageSource, alt: "Voice Assistant", style: baseImageStyle });
42231
+ return /* @__PURE__ */ import_react20.default.createElement("img", { src: imageSource, alt: "Voice Assistant", style: baseImageStyle });
41424
42232
  } else {
41425
- return /* @__PURE__ */ import_react15.default.createElement(VoiceIntensityWrapper, { active: true, buttonSize });
42233
+ return /* @__PURE__ */ import_react20.default.createElement(VoiceIntensityWrapper, { active: true, buttonSize });
41426
42234
  }
41427
42235
  }
41428
42236
  const iconStyle = {
@@ -41432,9 +42240,9 @@ var MicButton = ({
41432
42240
  filter: "drop-shadow(0 10px 8px rgba(0, 0, 0, 0.04)) drop-shadow(0 4px 3px rgba(0, 0, 0, 0.1))"
41433
42241
  };
41434
42242
  if (micState === "idle") {
41435
- return /* @__PURE__ */ import_react15.default.createElement(mic_default, { style: iconStyle });
42243
+ return /* @__PURE__ */ import_react20.default.createElement(mic_default, { style: iconStyle });
41436
42244
  } else {
41437
- return /* @__PURE__ */ import_react15.default.createElement(VoiceIntensityWrapper, { active: true, buttonSize });
42245
+ return /* @__PURE__ */ import_react20.default.createElement(VoiceIntensityWrapper, { active: true, buttonSize });
41438
42246
  }
41439
42247
  };
41440
42248
  const getPositionStyle = () => {
@@ -41496,15 +42304,15 @@ var MicButton = ({
41496
42304
  const baseStyle = { ...buttonStyles.button };
41497
42305
  switch (micState) {
41498
42306
  case "listening":
41499
- baseStyle.transform = "scale(1.1)";
42307
+ baseStyle.transform = "scale(1.05)";
41500
42308
  baseStyle.boxShadow = "0 25px 50px -12px rgba(59, 130, 246, 0.6)";
41501
42309
  break;
41502
42310
  case "thinking":
41503
- baseStyle.transform = "scale(1.05)";
42311
+ baseStyle.transform = "scale(1.02)";
41504
42312
  baseStyle.boxShadow = "0 20px 25px -5px rgba(196, 132, 252, 0.4)";
41505
42313
  break;
41506
42314
  case "replying":
41507
- baseStyle.transform = "scale(1.05)";
42315
+ baseStyle.transform = "scale(1.02)";
41508
42316
  baseStyle.boxShadow = "0 20px 25px -5px rgba(34, 211, 238, 0.4)";
41509
42317
  break;
41510
42318
  default:
@@ -41513,7 +42321,34 @@ var MicButton = ({
41513
42321
  }
41514
42322
  return baseStyle;
41515
42323
  };
41516
- return /* @__PURE__ */ import_react15.default.createElement(import_react15.default.Fragment, null, /* @__PURE__ */ import_react15.default.createElement("div", { "data-cuekit-ignore": true, style: { ...buttonStyles.container, ...getPositionStyle() } }, /* @__PURE__ */ import_react15.default.createElement("div", { style: { display: "flex", flexDirection: "column", alignItems: "center", gap: "8px" } }, /* @__PURE__ */ import_react15.default.createElement(
42324
+ return /* @__PURE__ */ import_react20.default.createElement(import_react20.default.Fragment, null, /* @__PURE__ */ import_react20.default.createElement("div", { "data-cuekit-ignore": true, style: { ...buttonStyles.container, ...getPositionStyle() } }, showLanguageSelector ? /* @__PURE__ */ import_react20.default.createElement("div", { className: "voice-chat-language-selection" }, /* @__PURE__ */ import_react20.default.createElement("div", { className: "voice-chat-language-header" }, /* @__PURE__ */ import_react20.default.createElement("div", { className: "voice-chat-language-icon" }, /* @__PURE__ */ import_react20.default.createElement(mic_default, { width: 20, height: 20 })), /* @__PURE__ */ import_react20.default.createElement("span", { className: "voice-chat-language-title" }, "Select Language")), /* @__PURE__ */ import_react20.default.createElement(
42325
+ LanguageSelector,
42326
+ {
42327
+ selectedLanguage,
42328
+ onLanguageChange: handleLanguageChange,
42329
+ availableLanguages: DEFAULT_LANGUAGES,
42330
+ className: "voice-chat-language-selector",
42331
+ screenPosition
42332
+ }
42333
+ ), /* @__PURE__ */ import_react20.default.createElement("div", { className: "voice-chat-language-actions" }, /* @__PURE__ */ import_react20.default.createElement(
42334
+ "button",
42335
+ {
42336
+ className: "voice-chat-cancel-button",
42337
+ onClick: () => setShowLanguageSelector(false)
42338
+ },
42339
+ "Cancel"
42340
+ ), /* @__PURE__ */ import_react20.default.createElement("button", { className: "voice-chat-confirm-button", onClick: handleLanguageConfirm }, "Start Voice Chat"))) : /* @__PURE__ */ import_react20.default.createElement("div", { className: "voice-chat-main-button" }, /* @__PURE__ */ import_react20.default.createElement(
42341
+ LanguageSelector,
42342
+ {
42343
+ selectedLanguage,
42344
+ onLanguageChange: handleLanguageChange,
42345
+ availableLanguages: DEFAULT_LANGUAGES,
42346
+ className: "voice-chat-language-preview",
42347
+ disabled: isConnected2 || micState !== "idle",
42348
+ tooltip: "Close the conversation to change the language",
42349
+ screenPosition
42350
+ }
42351
+ ), /* @__PURE__ */ import_react20.default.createElement(
41517
42352
  "button",
41518
42353
  {
41519
42354
  "data-testid": "ignore",
@@ -41534,8 +42369,8 @@ var MicButton = ({
41534
42369
  },
41535
42370
  "aria-label": micState === "thinking" ? "Processing..." : micState === "replying" ? "AI is responding..." : isListening ? "Stop listening" : "Start listening"
41536
42371
  },
41537
- /* @__PURE__ */ import_react15.default.createElement("div", { style: buttonStyles.iconContainer }, getIcon())
41538
- ), hasText && text7 && /* @__PURE__ */ import_react15.default.createElement(
42372
+ /* @__PURE__ */ import_react20.default.createElement("div", { style: buttonStyles.iconContainer }, getIcon())
42373
+ )), !showLanguageSelector && hasText && text7 && /* @__PURE__ */ import_react20.default.createElement(
41539
42374
  "div",
41540
42375
  {
41541
42376
  style: {
@@ -41553,11 +42388,12 @@ var MicButton = ({
41553
42388
  alignItems: "center",
41554
42389
  justifyContent: "center",
41555
42390
  gap: "4px",
42391
+ marginTop: "8px",
41556
42392
  ...textStyle
41557
42393
  }
41558
42394
  },
41559
- /* @__PURE__ */ import_react15.default.createElement("span", null, text7)
41560
- ))), /* @__PURE__ */ import_react15.default.createElement(
42395
+ /* @__PURE__ */ import_react20.default.createElement("span", null, text7)
42396
+ )), /* @__PURE__ */ import_react20.default.createElement(
41561
42397
  ChatPopup,
41562
42398
  {
41563
42399
  isOpen: isChatOpen,
@@ -41580,9 +42416,14 @@ var MicButton = ({
41580
42416
  status: getUserFriendlyStatus(micState, isConnected2 ?? false),
41581
42417
  anchor: { position: screenPosition, bottom: bottomSpace, size: buttonSize },
41582
42418
  muteState,
41583
- onToggleMute: toggleMute
41584
- }
41585
- ), isChatOpen && isChatMinimized && /* @__PURE__ */ import_react15.default.createElement(
42419
+ onToggleMute: toggleMute,
42420
+ draggable: true,
42421
+ resizable: true,
42422
+ persistPosition: true,
42423
+ persistSize: true,
42424
+ storageKey: "cuekit-chat-popup"
42425
+ }
42426
+ ), isChatOpen && isChatMinimized && /* @__PURE__ */ import_react20.default.createElement(
41586
42427
  "button",
41587
42428
  {
41588
42429
  onClick: restoreChat,
@@ -41603,8 +42444,8 @@ var MicButton = ({
41603
42444
  className: `cuekit-voice-popup ${currentTheme === "dark" ? "cuekit-dark" : ""}`,
41604
42445
  "aria-label": "Open chat"
41605
42446
  },
41606
- /* @__PURE__ */ import_react15.default.createElement("span", { style: { fontSize: 12, fontWeight: 600, color: "hsl(var(--voice-text))" } }, "Open chat")
41607
- ), /* @__PURE__ */ import_react15.default.createElement("div", { ref: audioContainerRef2, style: { display: "none" } }), showBorderGlow && showBodyGlow && /* @__PURE__ */ import_react15.default.createElement(border_glow_default, { isActive: true }));
42447
+ /* @__PURE__ */ import_react20.default.createElement("span", { style: { fontSize: 12, fontWeight: 600, color: "hsl(var(--voice-text))" } }, "Open chat")
42448
+ ), /* @__PURE__ */ import_react20.default.createElement("div", { ref: audioContainerRef2, style: { display: "none" } }), showBorderGlow && showBodyGlow && /* @__PURE__ */ import_react20.default.createElement(border_glow_default, { isActive: true }));
41608
42449
  };
41609
42450
 
41610
42451
  // src/index.ts