@salla.sa/ui-ai-kit-core 1.1.0 → 2.0.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.
Files changed (147) hide show
  1. package/dist/cjs/ai-card.cjs.entry.js +2 -2
  2. package/dist/cjs/ai-chat-container.cjs.entry.js +84 -57
  3. package/dist/cjs/ai-chat-header.cjs.entry.js +29 -19
  4. package/dist/cjs/ai-chat-message.cjs.entry.js +1456 -21
  5. package/dist/cjs/ai-conversation-list.cjs.entry.js +80 -0
  6. package/dist/cjs/ai-conversation-summary.cjs.entry.js +33 -0
  7. package/dist/cjs/ai-icon.cjs.entry.js +2 -2
  8. package/dist/cjs/ai-link.cjs.entry.js +4 -4
  9. package/dist/cjs/ai-loading.cjs.entry.js +35 -22
  10. package/dist/cjs/ai-message-input.cjs.entry.js +48 -15
  11. package/dist/cjs/ai-rating.cjs.entry.js +2 -2
  12. package/dist/cjs/ai-route-decision.cjs.entry.js +48 -0
  13. package/dist/cjs/ai-suggestion.cjs.entry.js +4 -4
  14. package/dist/cjs/ai-voice-input.cjs.entry.js +75 -21
  15. package/dist/cjs/{icon-registry-dmfLA-Dj.js → icon-registry-BKb9-2Nt.js} +24 -0
  16. package/dist/cjs/{index-DLJcLHFH.js → index-BkNg07SW.js} +1 -1
  17. package/dist/cjs/loader.cjs.js +2 -2
  18. package/dist/cjs/ui-ai-kit.cjs.js +2 -2
  19. package/dist/collection/collection-manifest.json +3 -0
  20. package/dist/collection/components/ai-card/ai-card.css +5 -8
  21. package/dist/collection/components/ai-chat-container/ai-chat-container.css +17 -14
  22. package/dist/collection/components/ai-chat-container/ai-chat-container.js +125 -53
  23. package/dist/collection/components/ai-chat-header/ai-chat-header.css +50 -17
  24. package/dist/collection/components/ai-chat-header/ai-chat-header.js +53 -18
  25. package/dist/collection/components/ai-chat-message/ai-chat-message.css +47 -38
  26. package/dist/collection/components/ai-chat-message/ai-chat-message.js +68 -18
  27. package/dist/collection/components/ai-conversation-list/ai-conversation-list.css +196 -0
  28. package/dist/collection/components/ai-conversation-list/ai-conversation-list.js +176 -0
  29. package/dist/collection/components/ai-conversation-summary/ai-conversation-summary.css +103 -0
  30. package/dist/collection/components/ai-conversation-summary/ai-conversation-summary.js +118 -0
  31. package/dist/collection/components/ai-icon/ai-icon.js +1 -1
  32. package/dist/collection/components/ai-link/ai-link.css +3 -7
  33. package/dist/collection/components/ai-link/ai-link.js +1 -1
  34. package/dist/collection/components/ai-loading/ai-loading.css +149 -20
  35. package/dist/collection/components/ai-loading/ai-loading.js +100 -23
  36. package/dist/collection/components/ai-message-input/ai-message-input.css +41 -37
  37. package/dist/collection/components/ai-message-input/ai-message-input.js +100 -19
  38. package/dist/collection/components/ai-rating/ai-rating.css +8 -14
  39. package/dist/collection/components/ai-route-decision/ai-route-decision.css +132 -0
  40. package/dist/collection/components/ai-route-decision/ai-route-decision.js +195 -0
  41. package/dist/collection/components/ai-suggestion/ai-suggestion.css +5 -11
  42. package/dist/collection/components/ai-suggestion/ai-suggestion.js +2 -2
  43. package/dist/collection/components/ai-voice-input/ai-voice-input.css +27 -22
  44. package/dist/collection/components/ai-voice-input/ai-voice-input.js +116 -20
  45. package/dist/collection/utils/icon-registry.js +24 -0
  46. package/dist/components/ai-card.js +1 -1
  47. package/dist/components/ai-chat-container.js +1 -1
  48. package/dist/components/ai-chat-header.js +1 -1
  49. package/dist/components/ai-chat-message.js +2 -1
  50. package/dist/components/ai-conversation-list.d.ts +11 -0
  51. package/dist/components/ai-conversation-list.js +1 -0
  52. package/dist/components/ai-conversation-summary.d.ts +11 -0
  53. package/dist/components/ai-conversation-summary.js +1 -0
  54. package/dist/components/ai-icon.js +1 -1
  55. package/dist/components/ai-link.js +1 -1
  56. package/dist/components/ai-loading.js +1 -1
  57. package/dist/components/ai-message-input.js +1 -1
  58. package/dist/components/ai-rating.js +1 -1
  59. package/dist/components/ai-route-decision.d.ts +11 -0
  60. package/dist/components/ai-route-decision.js +1 -0
  61. package/dist/components/ai-suggestion.js +1 -1
  62. package/dist/components/ai-voice-input.js +1 -1
  63. package/dist/components/index.js +1 -1
  64. package/dist/components/p-CX1Yp79q.js +1 -0
  65. package/dist/components/p-DnO4dikr.js +1 -0
  66. package/dist/components/{p-CY6emva2.js → p-Dr2tAPV7.js} +1 -1
  67. package/dist/{ui-ai-kit/p-DYv5ef4M.js → components/p-SJZ6Ujn9.js} +1 -1
  68. package/dist/esm/ai-card.entry.js +2 -2
  69. package/dist/esm/ai-chat-container.entry.js +84 -57
  70. package/dist/esm/ai-chat-header.entry.js +29 -19
  71. package/dist/esm/ai-chat-message.entry.js +1456 -21
  72. package/dist/esm/ai-conversation-list.entry.js +78 -0
  73. package/dist/esm/ai-conversation-summary.entry.js +31 -0
  74. package/dist/esm/ai-icon.entry.js +2 -2
  75. package/dist/esm/ai-link.entry.js +4 -4
  76. package/dist/esm/ai-loading.entry.js +35 -22
  77. package/dist/esm/ai-message-input.entry.js +48 -15
  78. package/dist/esm/ai-rating.entry.js +2 -2
  79. package/dist/esm/ai-route-decision.entry.js +46 -0
  80. package/dist/esm/ai-suggestion.entry.js +4 -4
  81. package/dist/esm/ai-voice-input.entry.js +75 -21
  82. package/dist/esm/{icon-registry-DYv5ef4M.js → icon-registry-SJZ6Ujn9.js} +24 -0
  83. package/dist/esm/{index-7hrZ8FOQ.js → index-B0yIzgh4.js} +1 -1
  84. package/dist/esm/loader.js +3 -3
  85. package/dist/esm/ui-ai-kit.js +3 -3
  86. package/dist/types/components/ai-chat-container/ai-chat-container.d.ts +11 -1
  87. package/dist/types/components/ai-chat-header/ai-chat-header.d.ts +7 -2
  88. package/dist/types/components/ai-conversation-list/ai-conversation-list.d.ts +24 -0
  89. package/dist/types/components/ai-conversation-summary/ai-conversation-summary.d.ts +12 -0
  90. package/dist/types/components/ai-loading/ai-loading.d.ts +12 -6
  91. package/dist/types/components/ai-message-input/ai-message-input.d.ts +17 -3
  92. package/dist/types/components/ai-route-decision/ai-route-decision.d.ts +21 -0
  93. package/dist/types/components/ai-voice-input/ai-voice-input.d.ts +7 -0
  94. package/dist/types/components.d.ts +335 -11
  95. package/dist/types/index.d.ts +2 -0
  96. package/dist/types/utils/icon-registry.d.ts +1 -1
  97. package/dist/ui-ai-kit/p-2955439f.entry.js +1 -0
  98. package/dist/ui-ai-kit/p-5c9e9822.entry.js +1 -0
  99. package/dist/ui-ai-kit/p-5caf1c38.entry.js +1 -0
  100. package/dist/ui-ai-kit/p-74c5c83f.entry.js +1 -0
  101. package/dist/ui-ai-kit/p-76195745.entry.js +1 -0
  102. package/dist/ui-ai-kit/p-79c78d8e.entry.js +1 -0
  103. package/dist/ui-ai-kit/p-87e9739b.entry.js +1 -0
  104. package/dist/ui-ai-kit/p-9c4c6c01.entry.js +1 -0
  105. package/dist/ui-ai-kit/p-B0yIzgh4.js +2 -0
  106. package/dist/{components/p-DYv5ef4M.js → ui-ai-kit/p-SJZ6Ujn9.js} +1 -1
  107. package/dist/ui-ai-kit/p-a099fcfb.entry.js +1 -0
  108. package/dist/ui-ai-kit/p-b28af13a.entry.js +1 -0
  109. package/dist/ui-ai-kit/p-d1bb1ad0.entry.js +1 -0
  110. package/dist/ui-ai-kit/p-eb0c7e7a.entry.js +1 -0
  111. package/dist/ui-ai-kit/{p-455daa17.entry.js → p-eec6f083.entry.js} +1 -1
  112. package/dist/ui-ai-kit/p-ef07638f.entry.js +2 -0
  113. package/dist/ui-ai-kit/ui-ai-kit.css +1 -1
  114. package/dist/ui-ai-kit/ui-ai-kit.esm.js +1 -1
  115. package/package.json +5 -13
  116. package/dist/collection/components/ai-card/ai-card.stories.js +0 -52
  117. package/dist/collection/components/ai-chat-container/ai-chat-container.stories.js +0 -160
  118. package/dist/collection/components/ai-chat-header/ai-chat-header.stories.js +0 -138
  119. package/dist/collection/components/ai-chat-message/ai-chat-message.stories.js +0 -164
  120. package/dist/collection/components/ai-link/ai-link.stories.js +0 -79
  121. package/dist/collection/components/ai-loading/ai-loading.stories.js +0 -145
  122. package/dist/collection/components/ai-message-input/ai-message-input.stories.js +0 -125
  123. package/dist/collection/components/ai-rating/ai-rating.stories.js +0 -78
  124. package/dist/collection/components/ai-suggestion/ai-suggestion.stories.js +0 -62
  125. package/dist/collection/components/ai-voice-input/ai-voice-input.stories.js +0 -118
  126. package/dist/components/p-CWjXxYJI.js +0 -1
  127. package/dist/types/components/ai-card/ai-card.stories.d.ts +0 -7
  128. package/dist/types/components/ai-chat-container/ai-chat-container.stories.d.ts +0 -7
  129. package/dist/types/components/ai-chat-header/ai-chat-header.stories.d.ts +0 -8
  130. package/dist/types/components/ai-chat-message/ai-chat-message.stories.d.ts +0 -10
  131. package/dist/types/components/ai-link/ai-link.stories.d.ts +0 -8
  132. package/dist/types/components/ai-loading/ai-loading.stories.d.ts +0 -10
  133. package/dist/types/components/ai-message-input/ai-message-input.stories.d.ts +0 -13
  134. package/dist/types/components/ai-rating/ai-rating.stories.d.ts +0 -8
  135. package/dist/types/components/ai-suggestion/ai-suggestion.stories.d.ts +0 -8
  136. package/dist/types/components/ai-voice-input/ai-voice-input.stories.d.ts +0 -9
  137. package/dist/ui-ai-kit/p-11facfad.entry.js +0 -1
  138. package/dist/ui-ai-kit/p-128a2ed4.entry.js +0 -1
  139. package/dist/ui-ai-kit/p-227bdb8f.entry.js +0 -1
  140. package/dist/ui-ai-kit/p-56163e8c.entry.js +0 -1
  141. package/dist/ui-ai-kit/p-6d21d0fd.entry.js +0 -1
  142. package/dist/ui-ai-kit/p-6ddcd77b.entry.js +0 -1
  143. package/dist/ui-ai-kit/p-7hrZ8FOQ.js +0 -2
  144. package/dist/ui-ai-kit/p-8e90143e.entry.js +0 -1
  145. package/dist/ui-ai-kit/p-9938c277.entry.js +0 -1
  146. package/dist/ui-ai-kit/p-dc5b4a7f.entry.js +0 -1
  147. package/dist/ui-ai-kit/p-fb1702de.entry.js +0 -1
@@ -1,8 +1,8 @@
1
1
  'use strict';
2
2
 
3
- var index = require('./index-DLJcLHFH.js');
3
+ var index = require('./index-BkNg07SW.js');
4
4
 
5
- const aiCardCss = () => `:host{--ai-card-bg:var(--ai-bg-card, #ffffff);--ai-card-border:1px solid var(--ai-border-default, #eeeeee);--ai-card-radius:16px;--ai-card-padding:16px;--ai-card-gap:12px;--ai-card-shadow:0px 1px 2px 0px rgba(18, 18, 23, 0.05);--ai-text-color:var(--ai-text-primary, #333333);display:block;direction:rtl}.card{background:var(--ai-card-bg);border:var(--ai-card-border);border-radius:var(--ai-card-radius);padding:var(--ai-card-padding);box-shadow:var(--ai-card-shadow);box-sizing:border-box;overflow:hidden;color:var(--ai-text-color);width:100%;display:flex;flex-direction:column;gap:var(--ai-card-gap);text-align:right;font-size:14px;line-height:20px}.card--no-padding{padding:0}.card--no-shadow{box-shadow:none}`;
5
+ const aiCardCss = () => `:host{--ai-card-border:1px solid var(--ai-border-default);--ai-card-radius:16px;--ai-card-padding:16px;--ai-card-gap:12px;--ai-card-shadow:var(--ai-shadow-sm);display:block}.card{background:var(--ai-bg-card);border:var(--ai-card-border);border-radius:var(--ai-card-radius);padding:var(--ai-card-padding);box-shadow:var(--ai-card-shadow);box-sizing:border-box;overflow:hidden;color:var(--ai-text-primary);width:100%;display:flex;flex-direction:column;gap:var(--ai-card-gap);text-align:start;font-size:14px;line-height:20px}.card--no-padding{padding:0}.card--no-shadow{box-shadow:none}`;
6
6
 
7
7
  const AiCard = class {
8
8
  constructor(hostRef) {
@@ -1,13 +1,10 @@
1
1
  'use strict';
2
2
 
3
- var index = require('./index-DLJcLHFH.js');
3
+ var index = require('./index-BkNg07SW.js');
4
4
 
5
- const aiChatContainerCss = () => `:host{display:contents}.chat-container{font-family:var(--ai-font-family, 'PingARLT', sans-serif);display:flex;flex-direction:column;overflow:hidden;position:relative;background-color:var(--ai-container-bg, var(--ai-bg-card, white));border:1px solid var(--border-default, var(--ai-border-default, #eee));z-index:50;box-sizing:border-box}.messages-area{flex:1;overflow-y:auto;min-height:0;scrollbar-width:thin;scrollbar-color:var(--ai-scrollbar-thumb, rgba(0, 0, 0, 0.15)) transparent}.messages-area::-webkit-scrollbar{width:3px}.messages-area::-webkit-scrollbar-track{background:transparent}.messages-area::-webkit-scrollbar-thumb{background:var(--ai-scrollbar-thumb, rgba(0, 0, 0, 0.15));border-radius:99px}.messages-area::-webkit-scrollbar-thumb:hover{background:var(--ai-scrollbar-thumb, rgba(0, 0, 0, 0.28))}.chat-container.left,.chat-container.right{position:fixed;top:0;bottom:0;transition:transform 300ms cubic-bezier(0.4, 0, 0.2, 1)}.chat-container.left{left:0;transform:translateX(-100%)}.chat-container.right{right:0;transform:translateX(100%)}.chat-container.left.open,.chat-container.right.open{transform:translateX(0)}.chat-container.float{position:fixed;top:24px;left:24px;border-radius:16px;box-shadow:0 8px 32px rgba(0, 0, 0, 0.12), 0 2px 8px rgba(0, 0, 0, 0.08);display:none}.chat-container.float.open{display:flex}.watermark{position:absolute;top:50%;left:50%;transform:translate(-50%, -50%);pointer-events:none}.watermark ai-icon{opacity:0.8;filter:drop-shadow(0 4px 6px rgba(0, 0, 0, 0.05))}.chat-container.mobile{width:100% !important}.chat-container.float.mobile{left:0 !important;right:0 !important;top:0 !important;bottom:0 !important;height:100% !important;border-radius:0 !important}@media (max-width: 767px){.chat-container{width:100% !important}.chat-container.float{left:0 !important;right:0 !important;top:0 !important;bottom:0 !important;height:100% !important;border-radius:0 !important}}:host(.dark) .watermark ai-icon{opacity:0.6}`;
5
+ const aiChatContainerCss = () => `:host{display:contents}.chat-container{font-family:var(--ai-font-family);display:flex;flex-direction:column;overflow:hidden;position:relative;background-color:var(--ai-container-bg, var(--ai-bg-card));border:1px solid var(--ai-border-default);z-index:50;box-sizing:border-box}.messages-area{flex:1;overflow-y:auto;min-height:0;scrollbar-width:thin;padding:var(--ai-spacing-2xl, 16px);scrollbar-color:var(--ai-scrollbar-thumb) transparent}.messages-area::-webkit-scrollbar{width:3px}.messages-area::-webkit-scrollbar-track{background:transparent}.messages-area::-webkit-scrollbar-thumb{background:var(--ai-scrollbar-thumb);border-radius:99px}.messages-area::-webkit-scrollbar-thumb:hover{background:var(--ai-scrollbar-thumb-hover)}.chat-container.left,.chat-container.right{position:fixed;top:0;bottom:0;transition:transform 300ms cubic-bezier(0.4, 0, 0.2, 1)}.chat-container.left{left:0;transform:translateX(-100%)}.chat-container.right{right:0;transform:translateX(100%)}.chat-container.left.open,.chat-container.right.open{transform:translateX(0)}.chat-container.float{position:fixed;border-radius:16px;box-shadow:var(--ai-shadow-float);opacity:0;pointer-events:none;transform:scale(0.95);transform-origin:bottom left;transition:opacity 200ms ease, transform 200ms ease}.chat-container.float.open{opacity:1;pointer-events:auto;transform:scale(1)}.watermark{position:absolute;top:50%;left:50%;transform:translate(-50%, -50%);pointer-events:none}.watermark ai-icon{opacity:0.8;filter:var(--ai-shadow-watermark)}.chat-container.mobile{width:100% !important}.chat-container.float.mobile{left:0 !important;right:0 !important;top:0 !important;bottom:0 !important;height:100% !important;border-radius:0 !important}@media (max-width: 767px){.chat-container{width:100% !important}.chat-container.float{left:0 !important;right:0 !important;top:0 !important;bottom:0 !important;height:100% !important;border-radius:0 !important}}:host(.dark) .watermark ai-icon{opacity:0.6}`;
6
6
 
7
7
  const ChatContainer = class {
8
- constructor(hostRef) {
9
- index.registerInstance(this, hostRef);
10
- }
11
8
  get el() { return index.getElement(this); }
12
9
  /** Controls visibility of the chat panel */
13
10
  isOpen = false;
@@ -21,32 +18,90 @@ const ChatContainer = class {
21
18
  showWatermark = false;
22
19
  /** Height of the panel when position='float' */
23
20
  floatHeight = '600px';
21
+ /** Color theme for the panel */
22
+ theme = 'light';
24
23
  isMobile = false;
24
+ floatLeft = '24px';
25
+ floatTop = '24px';
25
26
  containerRef;
27
+ messagesAreaRef;
26
28
  dragState = null;
27
- resizeObserver;
29
+ // Named arrow so we can reliably add/remove it without leaking
30
+ dragListener = (e) => {
31
+ const container = this.containerRef;
32
+ if (!container)
33
+ return;
34
+ const { clientX, clientY } = e.detail;
35
+ const rect = container.getBoundingClientRect();
36
+ this.dragState = {
37
+ startX: clientX,
38
+ startY: clientY,
39
+ initLeft: rect.left,
40
+ initTop: rect.top,
41
+ };
42
+ // Capture current rendered position into state so subsequent re-renders don't jump
43
+ this.floatLeft = `${rect.left}px`;
44
+ this.floatTop = `${rect.top}px`;
45
+ const onMove = (me) => {
46
+ if (!this.dragState)
47
+ return;
48
+ const dx = me.clientX - this.dragState.startX;
49
+ const dy = me.clientY - this.dragState.startY;
50
+ let newLeft = this.dragState.initLeft + dx;
51
+ let newTop = this.dragState.initTop + dy;
52
+ const vw = window.innerWidth;
53
+ const vh = window.innerHeight;
54
+ const w = container.offsetWidth;
55
+ const h = container.offsetHeight;
56
+ newLeft = Math.max(0, Math.min(newLeft, vw - w));
57
+ newTop = Math.max(0, Math.min(newTop, vh - h));
58
+ this.floatLeft = `${newLeft}px`;
59
+ this.floatTop = `${newTop}px`;
60
+ };
61
+ const onUp = () => {
62
+ this.dragState = null;
63
+ document.removeEventListener('pointermove', onMove);
64
+ document.removeEventListener('pointerup', onUp);
65
+ };
66
+ document.addEventListener('pointermove', onMove);
67
+ document.addEventListener('pointerup', onUp);
68
+ };
69
+ constructor(hostRef) {
70
+ index.registerInstance(this, hostRef);
71
+ // Bind so window.removeEventListener can match the reference
72
+ this.checkMobile = this.checkMobile.bind(this);
73
+ }
28
74
  componentWillLoad() {
29
75
  this.checkMobile();
30
76
  }
31
77
  componentDidLoad() {
32
78
  if (typeof window !== 'undefined') {
33
- this.resizeObserver = new ResizeObserver(() => {
34
- this.checkMobile();
35
- });
36
- this.resizeObserver.observe(document.body);
79
+ window.addEventListener('resize', this.checkMobile);
37
80
  if (this.position === 'float') {
38
81
  this.setupDrag();
39
82
  }
40
83
  }
41
84
  }
85
+ isOpenChanged(newVal) {
86
+ if (newVal && this.autoScroll && this.messagesAreaRef) {
87
+ requestAnimationFrame(() => {
88
+ this.messagesAreaRef.scrollTop = this.messagesAreaRef.scrollHeight;
89
+ });
90
+ }
91
+ }
42
92
  positionChanged(newVal) {
43
93
  if (newVal === 'float') {
44
94
  this.setupDrag();
45
95
  }
46
96
  }
47
97
  disconnectedCallback() {
48
- if (this.resizeObserver) {
49
- this.resizeObserver.disconnect();
98
+ window.removeEventListener('resize', this.checkMobile);
99
+ this.el.removeEventListener('headerDragStart', this.dragListener);
100
+ }
101
+ /** Programmatically scroll the messages area to the bottom */
102
+ async scrollToBottom() {
103
+ if (this.messagesAreaRef) {
104
+ this.messagesAreaRef.scrollTop = this.messagesAreaRef.scrollHeight;
50
105
  }
51
106
  }
52
107
  checkMobile() {
@@ -55,50 +110,9 @@ const ChatContainer = class {
55
110
  }
56
111
  }
57
112
  setupDrag() {
58
- const container = this.containerRef;
59
- if (!container)
60
- return;
61
- // Listen on the host element so composed events from ai-chat-header's shadow DOM
62
- // are received. (composedPath() hides cross-shadow-root elements from shadow listeners.)
63
- this.el.addEventListener('headerDragStart', (e) => {
64
- const { clientX, clientY } = e.detail;
65
- const rect = container.getBoundingClientRect();
66
- this.dragState = {
67
- startX: clientX,
68
- startY: clientY,
69
- initLeft: rect.left,
70
- initTop: rect.top,
71
- };
72
- // Switch from bottom/right anchoring to top/left so we can move freely
73
- container.style.right = 'auto';
74
- container.style.bottom = 'auto';
75
- container.style.left = `${rect.left}px`;
76
- container.style.top = `${rect.top}px`;
77
- const onMove = (me) => {
78
- if (!this.dragState)
79
- return;
80
- const dx = me.clientX - this.dragState.startX;
81
- const dy = me.clientY - this.dragState.startY;
82
- let newLeft = this.dragState.initLeft + dx;
83
- let newTop = this.dragState.initTop + dy;
84
- // Clamp to viewport edges
85
- const vw = window.innerWidth;
86
- const vh = window.innerHeight;
87
- const w = container.offsetWidth;
88
- const h = container.offsetHeight;
89
- newLeft = Math.max(0, Math.min(newLeft, vw - w));
90
- newTop = Math.max(0, Math.min(newTop, vh - h));
91
- container.style.left = `${newLeft}px`;
92
- container.style.top = `${newTop}px`;
93
- };
94
- const onUp = () => {
95
- this.dragState = null;
96
- document.removeEventListener('pointermove', onMove);
97
- document.removeEventListener('pointerup', onUp);
98
- };
99
- document.addEventListener('pointermove', onMove);
100
- document.addEventListener('pointerup', onUp);
101
- });
113
+ // Remove any existing listener before adding to prevent accumulation
114
+ this.el.removeEventListener('headerDragStart', this.dragListener);
115
+ this.el.addEventListener('headerDragStart', this.dragListener);
102
116
  }
103
117
  getContainerClasses() {
104
118
  const classes = ['chat-container', this.position];
@@ -118,16 +132,29 @@ const ChatContainer = class {
118
132
  if (this.position === 'float') {
119
133
  style.width = this.width;
120
134
  style.height = this.floatHeight;
135
+ style.left = this.floatLeft;
136
+ style.top = this.floatTop;
121
137
  }
122
138
  else {
123
139
  style.width = this.width;
124
140
  }
125
141
  return style;
126
142
  }
143
+ isDark() {
144
+ if (this.theme === 'dark')
145
+ return true;
146
+ if (this.theme === 'auto' && typeof window !== 'undefined') {
147
+ return window.matchMedia('(prefers-color-scheme: dark)').matches;
148
+ }
149
+ return false;
150
+ }
127
151
  render() {
128
- return (index.h(index.Host, { key: '5048010bf45a26985c92bfb9a6caf01d8aa938c0' }, index.h("div", { key: '08491cff2361071bc0635914cc665281b80321ac', class: this.getContainerClasses(), style: this.getContainerStyle(), ref: el => (this.containerRef = el) }, this.showWatermark && (index.h("div", { key: '366140a61929689fc522dddfb1485bbd4d2cbef9', class: "watermark" }, index.h("ai-icon", { key: '5e210929feeb519889344385fa2fb75373ff8fed', name: "watermark", size: 133 }))), index.h("slot", { key: '57eef4d0c273009feeeb4f03400e05352acdf6cd', name: "header" }), index.h("div", { key: '15b14f49819f886ce1d56de87c770bb7241dcd77', class: "messages-area" }, index.h("slot", { key: '050cd0fde5bc3de75df0747031dc84214c125d5d' })), index.h("slot", { key: '195ab33291da775299e0d7c0c53df92fcf46a4ca', name: "footer" }))));
152
+ return (index.h(index.Host, { key: 'dd656127f6974b6eef12f64c78c072f2c1f92a6a', class: { dark: this.isDark() } }, index.h("div", { key: '0eb43bc5c8b80e5576146f01998e5279eb860162', class: this.getContainerClasses(), style: this.getContainerStyle(), ref: el => (this.containerRef = el) }, this.showWatermark && (index.h("div", { key: '363046f0e73ab7aa0209d5f41562031fb34d6c2d', class: "watermark" }, index.h("ai-icon", { key: '1f3c26ba6a145f8532f6e1a40ea344249e8e5b43', name: "watermark", size: 133 }))), index.h("slot", { key: '3ec10548660ff721c094be36a15a152fdf6dac78', name: "header" }), index.h("div", { key: '9babb87041287ac400322b910aa64f7a7b1743a5', class: "messages-area", ref: el => (this.messagesAreaRef = el) }, index.h("slot", { key: '937c0c0bd675e5a619d46883e7c1f890754aae4b' })), index.h("slot", { key: '0982b8bc96537c6cecca757926d5849ba386bd69', name: "footer" }))));
129
153
  }
130
154
  static get watchers() { return {
155
+ "isOpen": [{
156
+ "isOpenChanged": 0
157
+ }],
131
158
  "position": [{
132
159
  "positionChanged": 0
133
160
  }]
@@ -1,9 +1,9 @@
1
1
  'use strict';
2
2
 
3
- var index = require('./index-DLJcLHFH.js');
4
- var iconRegistry = require('./icon-registry-dmfLA-Dj.js');
3
+ var index = require('./index-BkNg07SW.js');
4
+ var iconRegistry = require('./icon-registry-BKb9-2Nt.js');
5
5
 
6
- const aiChatHeaderCss = () => `:host{display:block;font-family:var(--ai-font-family, "PingARLT", sans-serif)}.header-container{display:flex;align-items:center;gap:8px;padding:16px;background:var(--ai-bg-card, white);border-bottom:1px solid var(--ai-border-light, #f4f4f4);width:100%;box-sizing:border-box}.header-container{direction:rtl}.drag-btn{cursor:grab;color:var(--ai-text-muted)}.drag-btn:active{cursor:grabbing}.action-btn,.back-btn{width:40px;height:40px;padding:4px;display:flex;align-items:center;justify-content:center;background:var(--ai-bg-card, white);border:none;border-radius:8px;cursor:pointer;flex-shrink:0;color:var(--ai-text-primary);transition:background 0.15s ease}.action-btn:hover,.back-btn:hover{background:var(--ai-bg-surface, #f9fafb)}.action-btn:focus-visible,.back-btn:focus-visible{outline:2px solid var(--ai-focus-ring);outline-offset:2px}.action-btn:active,.back-btn:active{background:var(--ai-bg-surface, #f3f4f6)}.actions{display:flex;align-items:center;gap:8px;flex-shrink:0}.content{flex:1 0 0;display:flex;align-items:center;justify-content:flex-start;min-width:0}.content.agent{gap:4px;height:40px}.content.human{gap:8px}.dropdown-trigger{display:flex;align-items:center;gap:4px;background:none;border:none;cursor:pointer;padding:0;flex-shrink:0;color:var(--ai-text-primary)}.dropdown-trigger:focus-visible{outline:2px solid var(--ai-focus-ring);outline-offset:2px}.title{font-size:16px;font-weight:700;color:var(--ai-text-primary, #444444);white-space:nowrap;line-height:normal;min-width:0;overflow:hidden;text-overflow:ellipsis}.avatar-wrapper{position:relative;width:40px;height:40px;flex-shrink:0}.avatar{width:40px;height:40px;border-radius:9999px;border:1px solid var(--ai-border-default, #eeeeee);object-fit:cover;display:block}.online-dot{position:absolute;bottom:0;left:0;width:10px;height:10px;display:inline-flex;align-items:center;justify-content:center;color:var(--ai-bg-card);}.text-block{display:flex;flex-direction:column;align-items:flex-end;gap:0;flex-shrink:0}.agent-name{font-size:14px;font-weight:500;color:var(--ai-text-primary, #333333);line-height:20px;white-space:nowrap}.agent-status{font-size:14px;font-weight:400;color:var(--ai-text-secondary, #737373);line-height:20px;white-space:nowrap}.icon-wrap{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0}.icon-wrap svg{display:block}`;
6
+ const aiChatHeaderCss = () => `:host{display:block}.header-container{display:flex;align-items:center;gap:8px;padding:16px;background:var(--ai-bg-card);border-bottom:1px solid var(--ai-border-light);width:100%;box-sizing:border-box}.drag-btn{cursor:grab;color:var(--ai-text-muted)}.drag-btn:active{cursor:grabbing}.action-btn,.back-btn{width:40px;height:40px;padding:4px;display:flex;align-items:center;justify-content:center;background:var(--ai-bg-card);border:none;border-radius:8px;cursor:pointer;flex-shrink:0;color:var(--ai-text-primary);transition:background 0.15s ease}.action-btn:hover,.back-btn:hover{background:var(--ai-bg-surface)}.action-btn:focus-visible,.back-btn:focus-visible{outline:2px solid var(--ai-focus-ring);outline-offset:2px}.action-btn:active,.back-btn:active{background:var(--ai-bg-surface)}.actions{display:flex;align-items:center;gap:8px;flex-shrink:0}.content{flex:1 0 0;display:flex;align-items:center;justify-content:flex-start;min-width:0}.content.agent{gap:4px;height:40px}.content.human{gap:8px}.dropdown-trigger{display:flex;align-items:center;gap:4px;background:none;border:none;cursor:pointer;padding:0;flex-shrink:0;color:var(--ai-text-primary)}.dropdown-trigger:focus-visible{outline:2px solid var(--ai-focus-ring);outline-offset:2px}.title{font-size:16px;font-weight:700;color:var(--ai-text-primary);white-space:nowrap;line-height:normal;min-width:0;overflow:hidden;text-overflow:ellipsis}.avatar-wrapper{position:relative;width:40px;height:40px;flex-shrink:0}.avatar{width:40px;height:40px;border-radius:9999px;border:1px solid var(--ai-border-default);object-fit:cover;display:block}.avatar-fallback{width:40px;height:40px;border-radius:9999px;border:1px solid var(--ai-border-default);background:var(--ai-bg-surface);color:var(--ai-text-primary);font-size:16px;font-weight:600;display:flex;align-items:center;justify-content:center;flex-shrink:0}.online-dot{position:absolute;bottom:0;inset-inline-end:0;width:10px;height:10px;display:inline-flex;align-items:center;justify-content:center;color:var(--ai-bg-card);}.online-dot.status-online{color:#22c55e;}.online-dot.status-offline{color:#9ca3af;}.online-dot.status-busy{color:#ef4444;}.online-dot.status-away{color:#f59e0b;}.text-block{display:flex;flex-direction:column;align-items:flex-start;gap:0;flex-shrink:0}.agent-name{font-size:14px;font-weight:500;color:var(--ai-text-primary);line-height:20px;white-space:nowrap}.agent-status{font-size:14px;font-weight:400;color:var(--ai-text-secondary);line-height:20px;white-space:nowrap}.icon-wrap{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0}.icon-wrap svg{display:block}:host-context([dir='ltr']) .back-btn .icon-wrap,:host([dir='ltr']) .back-btn .icon-wrap{transform:scaleX(-1)}`;
7
7
 
8
8
  const AiChatHeader = class {
9
9
  constructor(hostRef) {
@@ -11,7 +11,7 @@ const AiChatHeader = class {
11
11
  this.closeClick = index.createEvent(this, "closeClick");
12
12
  this.editClick = index.createEvent(this, "editClick");
13
13
  this.dropdownClick = index.createEvent(this, "dropdownClick");
14
- this.moreClick = index.createEvent(this, "moreClick");
14
+ this.positionClick = index.createEvent(this, "positionClick");
15
15
  this.backClick = index.createEvent(this, "backClick");
16
16
  this.headerDragStart = index.createEvent(this, "headerDragStart");
17
17
  }
@@ -28,14 +28,17 @@ const AiChatHeader = class {
28
28
  /** Human mode: show the back button */
29
29
  showBack = true;
30
30
  isDraggable = false;
31
+ /** Human mode: status indicator variant */
32
+ statusIndicator = 'online';
33
+ avatarError = false;
31
34
  /** Cancel / close button */
32
35
  closeClick;
33
36
  /** Pencil-edit button (agent mode) */
34
37
  editClick;
35
38
  /** Title / chevron click → open conversation list (agent mode) */
36
39
  dropdownClick;
37
- /** Chevron-down button (human mode) */
38
- moreClick;
40
+ /** More options button */
41
+ positionClick;
39
42
  /** Back-arrow button (human mode) */
40
43
  backClick;
41
44
  /**
@@ -50,28 +53,35 @@ const AiChatHeader = class {
50
53
  const svg = `<svg width="${width}" height="${height}" viewBox="${icon.viewBox}" fill="none" xmlns="http://www.w3.org/2000/svg">${icon.content}</svg>`;
51
54
  return index.h("span", { class: "icon-wrap", innerHTML: svg });
52
55
  }
56
+ renderAvatar() {
57
+ const fallbackLetter = this.agentName ? this.agentName.charAt(0) : '?';
58
+ if (!this.agentAvatar || this.avatarError) {
59
+ return index.h("div", { class: "avatar-fallback" }, fallbackLetter);
60
+ }
61
+ return (index.h("img", { class: "avatar", src: this.agentAvatar, alt: this.agentName, onError: () => { this.avatarError = true; } }));
62
+ }
63
+ renderDragBtn() {
64
+ return this.isDraggable && (index.h("button", { class: "action-btn drag-btn", "aria-label": "\u0633\u062D\u0628 / Drag", onPointerDown: (e) => {
65
+ e.preventDefault();
66
+ this.headerDragStart.emit({ clientX: e.clientX, clientY: e.clientY });
67
+ } }, this.renderIcon('drag', 11, 15)));
68
+ }
53
69
  renderAgentMode() {
54
70
  return [
55
- this.isDraggable && (index.h("button", { class: "action-btn drag-btn", onPointerDown: (e) => {
56
- e.preventDefault();
57
- this.headerDragStart.emit({ clientX: e.clientX, clientY: e.clientY });
58
- } }, this.renderIcon('drag', 11, 15))),
59
- index.h("div", { class: "content agent" }, index.h("span", { class: "title" }, this.conversation), index.h("button", { class: "dropdown-trigger", onClick: () => this.dropdownClick.emit() }, this.renderIcon('chevron-down', 24, 24))),
60
- index.h("div", { class: "actions" }, index.h("button", { class: "action-btn", onClick: () => this.editClick.emit() }, this.renderIcon('pencil-edit', 22, 22)), index.h("button", { class: "action-btn", onClick: () => this.moreClick.emit() }, this.renderIcon('hand', 22, 22)), index.h("button", { class: "action-btn", onClick: () => this.closeClick.emit() }, this.renderIcon('cancel', 22, 22))),
71
+ this.renderDragBtn(),
72
+ index.h("div", { class: "content agent dropdown-trigger", role: "button", onClick: () => this.dropdownClick.emit(), "aria-haspopup": "listbox", "aria-expanded": false, "aria-label": `${this.conversation}, افتح قائمة المحادثات` }, index.h("span", { class: "title" }, this.conversation), index.h("span", { class: "dropdown-chevron" }, this.renderIcon('chevron-down', 24, 24))),
73
+ index.h("div", { class: "actions" }, index.h("button", { class: "action-btn", "aria-label": "\u062A\u0639\u062F\u064A\u0644 / Edit", onClick: () => this.editClick.emit() }, this.renderIcon('pencil-edit', 22, 22)), index.h("button", { class: "action-btn", "aria-label": "\u0627\u0644\u0639\u0631\u0636 / Position", onClick: () => this.positionClick.emit() }, this.renderIcon('hand', 22, 22)), index.h("button", { class: "action-btn", "aria-label": "\u0625\u063A\u0644\u0627\u0642 / Close", onClick: () => this.closeClick.emit() }, this.renderIcon('cancel', 22, 22))),
61
74
  ];
62
75
  }
63
76
  renderHumanMode() {
64
77
  return [
65
- this.isDraggable && (index.h("button", { class: "action-btn drag-btn", onPointerDown: (e) => {
66
- e.preventDefault();
67
- this.headerDragStart.emit({ clientX: e.clientX, clientY: e.clientY });
68
- } }, this.renderIcon('drag', 11, 15))),
69
- index.h("div", { class: "content human" }, this.showBack && (index.h("button", { class: "back-btn", onClick: () => this.backClick.emit() }, this.renderIcon('arrow-right', 24, 24))), index.h("div", { class: "avatar-wrapper" }, index.h("img", { class: "avatar", src: this.agentAvatar, alt: this.agentName }), index.h("span", { class: "online-dot" }, this.renderIcon('online-dot', 10, 10))), index.h("div", { class: "text-block" }, index.h("span", { class: "agent-name" }, this.agentName), index.h("span", { class: "agent-status" }, this.agentStatus))),
70
- index.h("div", { class: "actions" }, index.h("button", { class: "action-btn", onClick: () => this.moreClick.emit() }, this.renderIcon('hand', 22, 22)), index.h("button", { class: "action-btn", onClick: () => this.closeClick.emit() }, this.renderIcon('cancel', 22, 22))),
78
+ this.renderDragBtn(),
79
+ index.h("div", { class: "content human" }, this.showBack && (index.h("button", { class: "back-btn", "aria-label": "\u0631\u062C\u0648\u0639 / Back", onClick: () => this.backClick.emit() }, this.renderIcon('arrow-right', 24, 24))), index.h("div", { class: "avatar-wrapper" }, this.renderAvatar(), index.h("span", { class: `online-dot status-${this.statusIndicator}` }, this.renderIcon('online-dot', 10, 10))), index.h("div", { class: "text-block" }, index.h("span", { class: "agent-name" }, this.agentName), this.agentStatus && index.h("span", { class: "agent-status" }, this.agentStatus))),
80
+ index.h("div", { class: "actions" }, index.h("button", { class: "action-btn", "aria-label": "\u0627\u0644\u0639\u0631\u0636 / Position", onClick: () => this.positionClick.emit() }, this.renderIcon('hand', 22, 22)), index.h("button", { class: "action-btn", "aria-label": "\u0625\u063A\u0644\u0627\u0642 / Close", onClick: () => this.closeClick.emit() }, this.renderIcon('cancel', 22, 22))),
71
81
  ];
72
82
  }
73
83
  render() {
74
- return (index.h(index.Host, { key: '93fe332abe1339f7235aa18717d63aa65d9aac13' }, index.h("div", { key: 'b496695911f7d1f959c4f98506b0d230e77a86c3', class: "header-container" }, this.mode === 'agent' ? this.renderAgentMode() : this.renderHumanMode())));
84
+ return (index.h(index.Host, { key: 'f96f4d5c533747b2843706c165866769b834fb98' }, index.h("div", { key: '8643a8cb214cbe40f0ee1a0b64c483829b5de6c9', class: "header-container" }, this.mode === 'agent' ? this.renderAgentMode() : this.renderHumanMode())));
75
85
  }
76
86
  };
77
87
  AiChatHeader.style = aiChatHeaderCss();