@salla.sa/ui-ai-kit-core 1.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/LICENSE +21 -0
  2. package/dist/cjs/ai-card.cjs.entry.js +25 -0
  3. package/dist/cjs/ai-chat-container.cjs.entry.js +138 -0
  4. package/dist/cjs/ai-chat-header.cjs.entry.js +79 -0
  5. package/dist/cjs/ai-chat-message.cjs.entry.js +164 -0
  6. package/dist/cjs/ai-icon.cjs.entry.js +25 -0
  7. package/dist/cjs/ai-link.cjs.entry.js +34 -0
  8. package/dist/cjs/ai-loading.cjs.entry.js +77 -0
  9. package/dist/cjs/ai-message-input.cjs.entry.js +65 -0
  10. package/dist/cjs/ai-rating.cjs.entry.js +57 -0
  11. package/dist/cjs/ai-suggestion.cjs.entry.js +31 -0
  12. package/dist/cjs/ai-voice-input.cjs.entry.js +233 -0
  13. package/dist/cjs/icon-registry-dmfLA-Dj.js +82 -0
  14. package/dist/cjs/index-DLJcLHFH.js +1622 -0
  15. package/dist/cjs/index.cjs.js +7 -0
  16. package/dist/cjs/loader.cjs.js +12 -0
  17. package/dist/cjs/ui-ai-kit.cjs.js +24 -0
  18. package/dist/collection/collection-manifest.json +23 -0
  19. package/dist/collection/components/ai-card/ai-card.css +40 -0
  20. package/dist/collection/components/ai-card/ai-card.js +70 -0
  21. package/dist/collection/components/ai-card/ai-card.stories.js +52 -0
  22. package/dist/collection/components/ai-chat-container/ai-chat-container.css +137 -0
  23. package/dist/collection/components/ai-chat-container/ai-chat-container.js +270 -0
  24. package/dist/collection/components/ai-chat-container/ai-chat-container.stories.js +160 -0
  25. package/dist/collection/components/ai-chat-header/ai-chat-header.css +186 -0
  26. package/dist/collection/components/ai-chat-header/ai-chat-header.js +311 -0
  27. package/dist/collection/components/ai-chat-header/ai-chat-header.stories.js +138 -0
  28. package/dist/collection/components/ai-chat-message/ai-chat-message.css +304 -0
  29. package/dist/collection/components/ai-chat-message/ai-chat-message.js +379 -0
  30. package/dist/collection/components/ai-chat-message/ai-chat-message.stories.js +164 -0
  31. package/dist/collection/components/ai-icon/ai-icon.css +9 -0
  32. package/dist/collection/components/ai-icon/ai-icon.js +76 -0
  33. package/dist/collection/components/ai-link/ai-link.css +62 -0
  34. package/dist/collection/components/ai-link/ai-link.js +119 -0
  35. package/dist/collection/components/ai-link/ai-link.stories.js +79 -0
  36. package/dist/collection/components/ai-loading/ai-loading.css +202 -0
  37. package/dist/collection/components/ai-loading/ai-loading.js +244 -0
  38. package/dist/collection/components/ai-loading/ai-loading.stories.js +145 -0
  39. package/dist/collection/components/ai-message-input/ai-message-input.css +175 -0
  40. package/dist/collection/components/ai-message-input/ai-message-input.js +192 -0
  41. package/dist/collection/components/ai-message-input/ai-message-input.stories.js +125 -0
  42. package/dist/collection/components/ai-rating/ai-rating.css +145 -0
  43. package/dist/collection/components/ai-rating/ai-rating.js +176 -0
  44. package/dist/collection/components/ai-rating/ai-rating.stories.js +78 -0
  45. package/dist/collection/components/ai-suggestion/ai-suggestion.css +69 -0
  46. package/dist/collection/components/ai-suggestion/ai-suggestion.js +93 -0
  47. package/dist/collection/components/ai-suggestion/ai-suggestion.stories.js +62 -0
  48. package/dist/collection/components/ai-voice-input/ai-voice-input.css +136 -0
  49. package/dist/collection/components/ai-voice-input/ai-voice-input.js +341 -0
  50. package/dist/collection/components/ai-voice-input/ai-voice-input.stories.js +118 -0
  51. package/dist/collection/index.js +10 -0
  52. package/dist/collection/utils/icon-registry.js +78 -0
  53. package/dist/collection/utils/utils.js +3 -0
  54. package/dist/components/ai-card.d.ts +11 -0
  55. package/dist/components/ai-card.js +1 -0
  56. package/dist/components/ai-chat-container.d.ts +11 -0
  57. package/dist/components/ai-chat-container.js +1 -0
  58. package/dist/components/ai-chat-header.d.ts +11 -0
  59. package/dist/components/ai-chat-header.js +1 -0
  60. package/dist/components/ai-chat-message.d.ts +11 -0
  61. package/dist/components/ai-chat-message.js +1 -0
  62. package/dist/components/ai-icon.d.ts +11 -0
  63. package/dist/components/ai-icon.js +1 -0
  64. package/dist/components/ai-link.d.ts +11 -0
  65. package/dist/components/ai-link.js +1 -0
  66. package/dist/components/ai-loading.d.ts +11 -0
  67. package/dist/components/ai-loading.js +1 -0
  68. package/dist/components/ai-message-input.d.ts +11 -0
  69. package/dist/components/ai-message-input.js +1 -0
  70. package/dist/components/ai-rating.d.ts +11 -0
  71. package/dist/components/ai-rating.js +1 -0
  72. package/dist/components/ai-suggestion.d.ts +11 -0
  73. package/dist/components/ai-suggestion.js +1 -0
  74. package/dist/components/ai-voice-input.d.ts +11 -0
  75. package/dist/components/ai-voice-input.js +1 -0
  76. package/dist/components/index.d.ts +35 -0
  77. package/dist/components/index.js +1 -0
  78. package/dist/components/p-CWjXxYJI.js +1 -0
  79. package/dist/components/p-CY6emva2.js +1 -0
  80. package/dist/components/p-DYv5ef4M.js +1 -0
  81. package/dist/esm/ai-card.entry.js +23 -0
  82. package/dist/esm/ai-chat-container.entry.js +136 -0
  83. package/dist/esm/ai-chat-header.entry.js +77 -0
  84. package/dist/esm/ai-chat-message.entry.js +162 -0
  85. package/dist/esm/ai-icon.entry.js +23 -0
  86. package/dist/esm/ai-link.entry.js +32 -0
  87. package/dist/esm/ai-loading.entry.js +75 -0
  88. package/dist/esm/ai-message-input.entry.js +63 -0
  89. package/dist/esm/ai-rating.entry.js +55 -0
  90. package/dist/esm/ai-suggestion.entry.js +29 -0
  91. package/dist/esm/ai-voice-input.entry.js +231 -0
  92. package/dist/esm/icon-registry-DYv5ef4M.js +80 -0
  93. package/dist/esm/index-7hrZ8FOQ.js +1612 -0
  94. package/dist/esm/index.js +5 -0
  95. package/dist/esm/loader.js +10 -0
  96. package/dist/esm/ui-ai-kit.js +20 -0
  97. package/dist/index.cjs.js +1 -0
  98. package/dist/index.js +1 -0
  99. package/dist/types/components/ai-card/ai-card.d.ts +7 -0
  100. package/dist/types/components/ai-card/ai-card.stories.d.ts +7 -0
  101. package/dist/types/components/ai-chat-container/ai-chat-container.d.ts +28 -0
  102. package/dist/types/components/ai-chat-container/ai-chat-container.stories.d.ts +7 -0
  103. package/dist/types/components/ai-chat-header/ai-chat-header.d.ts +38 -0
  104. package/dist/types/components/ai-chat-header/ai-chat-header.stories.d.ts +8 -0
  105. package/dist/types/components/ai-chat-message/ai-chat-message.d.ts +27 -0
  106. package/dist/types/components/ai-chat-message/ai-chat-message.stories.d.ts +10 -0
  107. package/dist/types/components/ai-icon/ai-icon.d.ts +8 -0
  108. package/dist/types/components/ai-link/ai-link.d.ts +12 -0
  109. package/dist/types/components/ai-link/ai-link.stories.d.ts +8 -0
  110. package/dist/types/components/ai-loading/ai-loading.d.ts +33 -0
  111. package/dist/types/components/ai-loading/ai-loading.stories.d.ts +10 -0
  112. package/dist/types/components/ai-message-input/ai-message-input.d.ts +22 -0
  113. package/dist/types/components/ai-message-input/ai-message-input.stories.d.ts +13 -0
  114. package/dist/types/components/ai-rating/ai-rating.d.ts +17 -0
  115. package/dist/types/components/ai-rating/ai-rating.stories.d.ts +8 -0
  116. package/dist/types/components/ai-suggestion/ai-suggestion.d.ts +10 -0
  117. package/dist/types/components/ai-suggestion/ai-suggestion.stories.d.ts +8 -0
  118. package/dist/types/components/ai-voice-input/ai-voice-input.d.ts +43 -0
  119. package/dist/types/components/ai-voice-input/ai-voice-input.stories.d.ts +9 -0
  120. package/dist/types/components.d.ts +860 -0
  121. package/dist/types/index.d.ts +11 -0
  122. package/dist/types/stencil-public-runtime.d.ts +1860 -0
  123. package/dist/types/utils/icon-registry.d.ts +5 -0
  124. package/dist/types/utils/utils.d.ts +1 -0
  125. package/dist/ui-ai-kit/index.esm.js +1 -0
  126. package/dist/ui-ai-kit/p-11facfad.entry.js +1 -0
  127. package/dist/ui-ai-kit/p-128a2ed4.entry.js +1 -0
  128. package/dist/ui-ai-kit/p-227bdb8f.entry.js +1 -0
  129. package/dist/ui-ai-kit/p-455daa17.entry.js +1 -0
  130. package/dist/ui-ai-kit/p-56163e8c.entry.js +1 -0
  131. package/dist/ui-ai-kit/p-6d21d0fd.entry.js +1 -0
  132. package/dist/ui-ai-kit/p-6ddcd77b.entry.js +1 -0
  133. package/dist/ui-ai-kit/p-7hrZ8FOQ.js +2 -0
  134. package/dist/ui-ai-kit/p-8e90143e.entry.js +1 -0
  135. package/dist/ui-ai-kit/p-9938c277.entry.js +1 -0
  136. package/dist/ui-ai-kit/p-DYv5ef4M.js +1 -0
  137. package/dist/ui-ai-kit/p-dc5b4a7f.entry.js +1 -0
  138. package/dist/ui-ai-kit/p-fb1702de.entry.js +1 -0
  139. package/dist/ui-ai-kit/ui-ai-kit.css +1 -0
  140. package/dist/ui-ai-kit/ui-ai-kit.esm.js +1 -0
  141. package/loader/cdn.js +1 -0
  142. package/loader/index.cjs.js +1 -0
  143. package/loader/index.d.ts +24 -0
  144. package/loader/index.es2017.js +1 -0
  145. package/loader/index.js +2 -0
  146. package/package.json +77 -0
  147. package/readme.md +111 -0
@@ -0,0 +1,136 @@
1
+ import { r as registerInstance, a as getElement, h, H as Host } from './index-7hrZ8FOQ.js';
2
+
3
+ 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}`;
4
+
5
+ const ChatContainer = class {
6
+ constructor(hostRef) {
7
+ registerInstance(this, hostRef);
8
+ }
9
+ get el() { return getElement(this); }
10
+ /** Controls visibility of the chat panel */
11
+ isOpen = false;
12
+ /** Position of the panel: 'left', 'right', or 'float' */
13
+ position = 'right';
14
+ /** Width of the panel (CSS value, e.g., '400px', '30%', '28rem') */
15
+ width = '28rem';
16
+ /** Enable/disable auto-scroll to latest message */
17
+ autoScroll = true;
18
+ /** Show AI watermark in the top half of the container */
19
+ showWatermark = false;
20
+ /** Height of the panel when position='float' */
21
+ floatHeight = '600px';
22
+ isMobile = false;
23
+ containerRef;
24
+ dragState = null;
25
+ resizeObserver;
26
+ componentWillLoad() {
27
+ this.checkMobile();
28
+ }
29
+ componentDidLoad() {
30
+ if (typeof window !== 'undefined') {
31
+ this.resizeObserver = new ResizeObserver(() => {
32
+ this.checkMobile();
33
+ });
34
+ this.resizeObserver.observe(document.body);
35
+ if (this.position === 'float') {
36
+ this.setupDrag();
37
+ }
38
+ }
39
+ }
40
+ positionChanged(newVal) {
41
+ if (newVal === 'float') {
42
+ this.setupDrag();
43
+ }
44
+ }
45
+ disconnectedCallback() {
46
+ if (this.resizeObserver) {
47
+ this.resizeObserver.disconnect();
48
+ }
49
+ }
50
+ checkMobile() {
51
+ if (typeof window !== 'undefined') {
52
+ this.isMobile = window.innerWidth < 768;
53
+ }
54
+ }
55
+ setupDrag() {
56
+ const container = this.containerRef;
57
+ if (!container)
58
+ return;
59
+ // Listen on the host element so composed events from ai-chat-header's shadow DOM
60
+ // are received. (composedPath() hides cross-shadow-root elements from shadow listeners.)
61
+ this.el.addEventListener('headerDragStart', (e) => {
62
+ const { clientX, clientY } = e.detail;
63
+ const rect = container.getBoundingClientRect();
64
+ this.dragState = {
65
+ startX: clientX,
66
+ startY: clientY,
67
+ initLeft: rect.left,
68
+ initTop: rect.top,
69
+ };
70
+ // Switch from bottom/right anchoring to top/left so we can move freely
71
+ container.style.right = 'auto';
72
+ container.style.bottom = 'auto';
73
+ container.style.left = `${rect.left}px`;
74
+ container.style.top = `${rect.top}px`;
75
+ const onMove = (me) => {
76
+ if (!this.dragState)
77
+ return;
78
+ const dx = me.clientX - this.dragState.startX;
79
+ const dy = me.clientY - this.dragState.startY;
80
+ let newLeft = this.dragState.initLeft + dx;
81
+ let newTop = this.dragState.initTop + dy;
82
+ // Clamp to viewport edges
83
+ const vw = window.innerWidth;
84
+ const vh = window.innerHeight;
85
+ const w = container.offsetWidth;
86
+ const h = container.offsetHeight;
87
+ newLeft = Math.max(0, Math.min(newLeft, vw - w));
88
+ newTop = Math.max(0, Math.min(newTop, vh - h));
89
+ container.style.left = `${newLeft}px`;
90
+ container.style.top = `${newTop}px`;
91
+ };
92
+ const onUp = () => {
93
+ this.dragState = null;
94
+ document.removeEventListener('pointermove', onMove);
95
+ document.removeEventListener('pointerup', onUp);
96
+ };
97
+ document.addEventListener('pointermove', onMove);
98
+ document.addEventListener('pointerup', onUp);
99
+ });
100
+ }
101
+ getContainerClasses() {
102
+ const classes = ['chat-container', this.position];
103
+ if (this.isOpen) {
104
+ classes.push('open');
105
+ }
106
+ if (this.isMobile) {
107
+ classes.push('mobile');
108
+ }
109
+ return classes.join(' ');
110
+ }
111
+ getContainerStyle() {
112
+ const style = {};
113
+ if (this.isMobile) {
114
+ return style;
115
+ }
116
+ if (this.position === 'float') {
117
+ style.width = this.width;
118
+ style.height = this.floatHeight;
119
+ }
120
+ else {
121
+ style.width = this.width;
122
+ }
123
+ return style;
124
+ }
125
+ render() {
126
+ return (h(Host, { key: '5048010bf45a26985c92bfb9a6caf01d8aa938c0' }, h("div", { key: '08491cff2361071bc0635914cc665281b80321ac', class: this.getContainerClasses(), style: this.getContainerStyle(), ref: el => (this.containerRef = el) }, this.showWatermark && (h("div", { key: '366140a61929689fc522dddfb1485bbd4d2cbef9', class: "watermark" }, h("ai-icon", { key: '5e210929feeb519889344385fa2fb75373ff8fed', name: "watermark", size: 133 }))), h("slot", { key: '57eef4d0c273009feeeb4f03400e05352acdf6cd', name: "header" }), h("div", { key: '15b14f49819f886ce1d56de87c770bb7241dcd77', class: "messages-area" }, h("slot", { key: '050cd0fde5bc3de75df0747031dc84214c125d5d' })), h("slot", { key: '195ab33291da775299e0d7c0c53df92fcf46a4ca', name: "footer" }))));
127
+ }
128
+ static get watchers() { return {
129
+ "position": [{
130
+ "positionChanged": 0
131
+ }]
132
+ }; }
133
+ };
134
+ ChatContainer.style = aiChatContainerCss();
135
+
136
+ export { ChatContainer as ai_chat_container };
@@ -0,0 +1,77 @@
1
+ import { r as registerInstance, c as createEvent, h, H as Host } from './index-7hrZ8FOQ.js';
2
+ import { i as iconRegistry } from './icon-registry-DYv5ef4M.js';
3
+
4
+ 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}`;
5
+
6
+ const AiChatHeader = class {
7
+ constructor(hostRef) {
8
+ registerInstance(this, hostRef);
9
+ this.closeClick = createEvent(this, "closeClick");
10
+ this.editClick = createEvent(this, "editClick");
11
+ this.dropdownClick = createEvent(this, "dropdownClick");
12
+ this.moreClick = createEvent(this, "moreClick");
13
+ this.backClick = createEvent(this, "backClick");
14
+ this.headerDragStart = createEvent(this, "headerDragStart");
15
+ }
16
+ /** Layout variant */
17
+ mode = 'agent';
18
+ /** Agent mode: conversation title */
19
+ conversation = 'محادثة جديدة';
20
+ /** Human mode: agent's display name */
21
+ agentName = '';
22
+ /** Human mode: status label (e.g. "Active") */
23
+ agentStatus = '';
24
+ /** Human mode: avatar image URL */
25
+ agentAvatar = '';
26
+ /** Human mode: show the back button */
27
+ showBack = true;
28
+ isDraggable = false;
29
+ /** Cancel / close button */
30
+ closeClick;
31
+ /** Pencil-edit button (agent mode) */
32
+ editClick;
33
+ /** Title / chevron click → open conversation list (agent mode) */
34
+ dropdownClick;
35
+ /** Chevron-down button (human mode) */
36
+ moreClick;
37
+ /** Back-arrow button (human mode) */
38
+ backClick;
39
+ /**
40
+ * Fired on pointerdown of the drag handle.
41
+ * Composed + bubbling so ai-chat-container can receive it across shadow roots.
42
+ */
43
+ headerDragStart;
44
+ renderIcon(name, width, height) {
45
+ const icon = iconRegistry[name];
46
+ if (!icon)
47
+ return null;
48
+ const svg = `<svg width="${width}" height="${height}" viewBox="${icon.viewBox}" fill="none" xmlns="http://www.w3.org/2000/svg">${icon.content}</svg>`;
49
+ return h("span", { class: "icon-wrap", innerHTML: svg });
50
+ }
51
+ renderAgentMode() {
52
+ return [
53
+ this.isDraggable && (h("button", { class: "action-btn drag-btn", onPointerDown: (e) => {
54
+ e.preventDefault();
55
+ this.headerDragStart.emit({ clientX: e.clientX, clientY: e.clientY });
56
+ } }, this.renderIcon('drag', 11, 15))),
57
+ h("div", { class: "content agent" }, h("span", { class: "title" }, this.conversation), h("button", { class: "dropdown-trigger", onClick: () => this.dropdownClick.emit() }, this.renderIcon('chevron-down', 24, 24))),
58
+ h("div", { class: "actions" }, h("button", { class: "action-btn", onClick: () => this.editClick.emit() }, this.renderIcon('pencil-edit', 22, 22)), h("button", { class: "action-btn", onClick: () => this.moreClick.emit() }, this.renderIcon('hand', 22, 22)), h("button", { class: "action-btn", onClick: () => this.closeClick.emit() }, this.renderIcon('cancel', 22, 22))),
59
+ ];
60
+ }
61
+ renderHumanMode() {
62
+ return [
63
+ this.isDraggable && (h("button", { class: "action-btn drag-btn", onPointerDown: (e) => {
64
+ e.preventDefault();
65
+ this.headerDragStart.emit({ clientX: e.clientX, clientY: e.clientY });
66
+ } }, this.renderIcon('drag', 11, 15))),
67
+ h("div", { class: "content human" }, this.showBack && (h("button", { class: "back-btn", onClick: () => this.backClick.emit() }, this.renderIcon('arrow-right', 24, 24))), h("div", { class: "avatar-wrapper" }, h("img", { class: "avatar", src: this.agentAvatar, alt: this.agentName }), h("span", { class: "online-dot" }, this.renderIcon('online-dot', 10, 10))), h("div", { class: "text-block" }, h("span", { class: "agent-name" }, this.agentName), h("span", { class: "agent-status" }, this.agentStatus))),
68
+ h("div", { class: "actions" }, h("button", { class: "action-btn", onClick: () => this.moreClick.emit() }, this.renderIcon('hand', 22, 22)), h("button", { class: "action-btn", onClick: () => this.closeClick.emit() }, this.renderIcon('cancel', 22, 22))),
69
+ ];
70
+ }
71
+ render() {
72
+ return (h(Host, { key: '93fe332abe1339f7235aa18717d63aa65d9aac13' }, h("div", { key: 'b496695911f7d1f959c4f98506b0d230e77a86c3', class: "header-container" }, this.mode === 'agent' ? this.renderAgentMode() : this.renderHumanMode())));
73
+ }
74
+ };
75
+ AiChatHeader.style = aiChatHeaderCss();
76
+
77
+ export { AiChatHeader as ai_chat_header };
@@ -0,0 +1,162 @@
1
+ import { r as registerInstance, c as createEvent, h, H as Host } from './index-7hrZ8FOQ.js';
2
+ import { i as iconRegistry } from './icon-registry-DYv5ef4M.js';
3
+
4
+ const aiChatMessageCss = () => `:host{--ai-msg-user-bg:var(--ai-user-bubble-bg, #F4F4F4);--ai-msg-user-color:var(--ai-text-primary, #333333);--ai-msg-user-border:1px solid var(--ai-border-default, #eee);--ai-msg-agent-bg:var(--ai-agent-bubble-bg, #ffffff);--ai-msg-agent-color:var(--ai-text-primary, #333333);--ai-msg-agent-border:1px solid var(--ai-border-default, #eee);--ai-msg-border-radius:16px;--ai-msg-padding:16px;--ai-msg-font-size:14px;--ai-msg-action-active-bg:var(--ai-accent, #a4ffe5);--ai-msg-timestamp-color:var(--ai-text-secondary, #737373);--ai-user-msg-max-width:80%;--ai-agent-msg-max-width:80%;display:block;direction:rtl;font-family:var(--ai-font-family, "PingARLT", sans-serif)}.message-row{display:flex}.user-row{flex-direction:column;align-items:flex-end}.user-bubble{background:var(--ai-msg-user-bg);color:var(--ai-msg-user-color);border:var(--ai-msg-user-border);border-radius:var(--ai-msg-border-radius);padding:var(--ai-msg-padding);font-size:var(--ai-msg-font-size);max-width:var(--ai-user-msg-max-width);line-height:1.5;word-break:break-word;box-shadow:0px 1px 2px 0px rgba(18, 18, 23, 0.05)}.user-row .timestamp{font-size:12px;color:var(--ai-msg-timestamp-color);margin-top:4px}.agent-row{flex-direction:row;justify-content:flex-start}.agent-bubble-wrapper{display:flex;flex-direction:column;gap:6px;width:100%;max-width:var(--ai-msg-agent-max-width);min-width:0}.agent-bubble{background:var(--ai-msg-agent-bg);color:var(--ai-msg-agent-color);border:var(--ai-msg-agent-border);border-radius:var(--ai-msg-border-radius);padding:var(--ai-msg-padding);font-size:var(--ai-msg-font-size);line-height:1.6;word-break:break-word;box-shadow:0px 1px 2px 0px rgba(18, 18, 23, 0.05);display:flex;flex-direction:column;gap:12px}.message-content{white-space:pre-wrap}.message-content p{margin:0 0 8px 0}.message-content p:last-child{margin-bottom:0}.message-content h2{font-size:16px;font-weight:700;margin:0 0 8px 0}.message-content h3{font-size:15px;font-weight:600;margin:0 0 6px 0}.message-content strong{font-weight:700}.message-content em{font-style:italic}.message-content code{background:var(--ai-bg-surface, #f3f4f6);border-radius:4px;padding:1px 5px;font-family:monospace;font-size:13px;color:var(--ai-text-primary, #374151)}.message-content pre{background:var(--ai-bg-surface, #f3f4f6);border-radius:8px;padding:10px 12px;overflow-x:auto;margin:8px 0}.message-content pre code{background:none;padding:0;font-size:13px}.message-content ul,.message-content ol{padding-inline-start:20px;margin:4px 0 8px 0}.message-content li{margin-bottom:3px}.actions-bar{display:flex;flex-direction:row;align-items:center;justify-content:flex-start;gap:6px;height:0;overflow:hidden;opacity:0;pointer-events:none;transition:height 0.15s ease, opacity 0.15s ease}.agent-bubble:hover .actions-bar{height:32px;opacity:1;pointer-events:auto}.action-btn{display:flex;align-items:center;justify-content:center;width:32px;height:32px;border-radius:8px;background:var(--ai-bg-card, #ffffff);border:1px solid var(--ai-border-default, #eee);cursor:pointer;color:var(--ai-text-primary, #333333);transition:background 0.15s, color 0.15s;padding:0;flex-shrink:0}.action-btn:hover{background:var(--ai-bg-surface, #f3f4f6)}.action-btn.copy-success{background:var(--ai-msg-action-active-bg);color:var(--ai-accent-text);border-color:var(--ai-accent)}.feedback-group{display:flex;align-items:center;border:1px solid var(--ai-border-default, #eee);border-radius:8px;overflow:hidden;background:var(--ai-bg-card, #ffffff)}.feedback-btn{display:flex;align-items:center;justify-content:center;height:32px;padding:0 8px;background:var(--ai-bg-card, #ffffff);border:none;border-inline-start:1px solid var(--ai-border-default, #eee);cursor:pointer;color:var(--ai-text-primary, #333333);transition:background 0.15s, color 0.15s}.feedback-btn:first-child{border-inline-start:none}.feedback-btn:hover{background:var(--ai-bg-surface, #f3f4f6)}.feedback-btn.active{background:var(--ai-msg-action-active-bg);color:var(--ai-accent-text)}.icon-wrap{display:flex;align-items:center;justify-content:center;line-height:0}.agent-info{display:flex;flex-direction:row;align-items:center;justify-content:flex-start;gap:6px;color:var(--ai-text-muted, #9ca3af)}.agent-info-name,.agent-info-time{font-size:12px;color:inherit;line-height:16px;white-space:nowrap}.agent-info .icon-wrap{display:flex;align-items:center;color:inherit;opacity:0.6;flex-shrink:0}.typing-indicator{display:flex;align-items:center;gap:5px;padding:4px 2px}.typing-dot{width:8px;height:8px;border-radius:50%;background:var(--ai-text-muted, #9ca3af);animation:typingBounce 1.2s ease-in-out infinite}.typing-dot:nth-child(2){animation-delay:0.2s}.typing-dot:nth-child(3){animation-delay:0.4s}@keyframes typingBounce{0%,60%,100%{transform:translateY(0)}30%{transform:translateY(-6px)}}.streaming-cursor{display:inline-block;width:2px;height:1em;background:currentColor;vertical-align:text-bottom;margin-inline-start:2px;animation:cursorBlink 0.8s step-start infinite}@keyframes cursorBlink{0%,100%{opacity:1}50%{opacity:0}}`;
5
+
6
+ const AiChatMessage = class {
7
+ constructor(hostRef) {
8
+ registerInstance(this, hostRef);
9
+ this.messageCopy = createEvent(this, "messageCopy");
10
+ this.messageFeedback = createEvent(this, "messageFeedback");
11
+ this.messageRegenerate = createEvent(this, "messageRegenerate");
12
+ }
13
+ role = 'user';
14
+ content = '';
15
+ format = 'text';
16
+ agentName = '';
17
+ timestamp = '';
18
+ showActions = true;
19
+ enableRegenerate = false;
20
+ feedbackValue = null;
21
+ messageCopy;
22
+ messageFeedback;
23
+ messageRegenerate;
24
+ copySuccess = false;
25
+ copyTimeout;
26
+ disconnectedCallback() {
27
+ if (this.copyTimeout)
28
+ clearTimeout(this.copyTimeout);
29
+ }
30
+ renderIcon(name, size = 16) {
31
+ const icon = iconRegistry[name];
32
+ if (!icon)
33
+ return null;
34
+ const svg = `<svg width="${size}" height="${size}" viewBox="${icon.viewBox}" fill="none" xmlns="http://www.w3.org/2000/svg">${icon.content}</svg>`;
35
+ return h("span", { class: "icon-wrap", innerHTML: svg });
36
+ }
37
+ parseMarkdown(text) {
38
+ let html = text.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
39
+ const blocks = [];
40
+ html = html.replace(/```(?:\w+)?\n?([\s\S]*?)```/g, (_, code) => {
41
+ const idx = blocks.length;
42
+ blocks.push(`<pre><code>${code}</code></pre>`);
43
+ return `\x00BLOCK${idx}\x00`;
44
+ });
45
+ html = html.replace(/`([^`]+)`/g, '<code>$1</code>');
46
+ html = html.replace(/^## (.+)$/gm, '<h2>$1</h2>');
47
+ html = html.replace(/^### (.+)$/gm, '<h3>$1</h3>');
48
+ html = html.replace(/\*\*(.+?)\*\*/g, '<strong>$1</strong>');
49
+ html = html.replace(/\*([^*\n]+)\*/g, '<em>$1</em>');
50
+ html = html.replace(/((?:^[ \t]*[-*] .+\n?)+)/gm, match => {
51
+ const items = match
52
+ .trim()
53
+ .split('\n')
54
+ .filter(l => l.trim())
55
+ .map(l => `<li>${l.replace(/^[ \t]*[-*] /, '')}</li>`)
56
+ .join('');
57
+ return `\x00BLOCK${blocks.length}\x00${(() => {
58
+ blocks.push(`<ul>${items}</ul>`);
59
+ return '';
60
+ })()}`;
61
+ });
62
+ html = html.replace(/((?:^[ \t]*\d+\. .+\n?)+)/gm, match => {
63
+ const items = match
64
+ .trim()
65
+ .split('\n')
66
+ .filter(l => l.trim())
67
+ .map(l => `<li>${l.replace(/^[ \t]*\d+\. /, '')}</li>`)
68
+ .join('');
69
+ return `\x00BLOCK${blocks.length}\x00${(() => {
70
+ blocks.push(`<ol>${items}</ol>`);
71
+ return '';
72
+ })()}`;
73
+ });
74
+ html = html
75
+ .split(/\n{2,}/)
76
+ .map(chunk => {
77
+ const trimmed = chunk.trim();
78
+ if (!trimmed)
79
+ return '';
80
+ if (/^\x00BLOCK\d+\x00$/.test(trimmed))
81
+ return trimmed;
82
+ return `<p>${trimmed.replace(/\n/g, '<br>')}</p>`;
83
+ })
84
+ .join('');
85
+ html = html.replace(/\x00BLOCK(\d+)\x00/g, (_, i) => blocks[parseInt(i, 10)] || '');
86
+ return html;
87
+ }
88
+ getRenderedContent() {
89
+ if (!this.content)
90
+ return '';
91
+ let html = this.parseMarkdown(this.content);
92
+ return html;
93
+ }
94
+ getRelativeTime() {
95
+ if (!this.timestamp)
96
+ return '';
97
+ try {
98
+ const date = new Date(this.timestamp);
99
+ if (isNaN(date.getTime()))
100
+ return this.timestamp;
101
+ const diffMin = Math.floor((Date.now() - date.getTime()) / 60000);
102
+ if (diffMin < 1)
103
+ return 'الآن';
104
+ if (diffMin < 60)
105
+ return `منذ ${diffMin} دقيقة`;
106
+ const hours = Math.floor(diffMin / 60);
107
+ if (hours < 24)
108
+ return `منذ ${hours} ساعة`;
109
+ return `منذ ${Math.floor(hours / 24)} يوم`;
110
+ }
111
+ catch {
112
+ return this.timestamp;
113
+ }
114
+ }
115
+ async handleCopy() {
116
+ try {
117
+ await navigator.clipboard.writeText(this.content);
118
+ }
119
+ catch (_) { }
120
+ this.copySuccess = true;
121
+ this.messageCopy.emit();
122
+ this.copyTimeout = setTimeout(() => (this.copySuccess = false), 1500);
123
+ }
124
+ handleFeedback(val) {
125
+ this.feedbackValue = this.feedbackValue === val ? null : val;
126
+ this.messageFeedback.emit(val);
127
+ }
128
+ renderActionsBar() {
129
+ return (h("div", { class: "actions-bar" }, this.enableRegenerate && h("button", { class: 'action-btn', onClick: () => this.messageRegenerate.emit(), title: "\u0625\u0639\u0627\u062F\u0629 \u062A\u062D\u0645\u064A\u0644" }, this.renderIcon('reload', 16)), h("button", { class: `action-btn copy-btn${this.copySuccess ? ' copy-success' : ''}`, onClick: () => this.handleCopy(), title: "\u0646\u0633\u062E" }, this.renderIcon('copy', 16)), h("div", { class: "feedback-group" }, h("button", { class: `feedback-btn thumbs-down-btn${this.feedbackValue === 'down' ? ' active' : ''}`, onClick: () => this.handleFeedback('down'), title: "\u063A\u064A\u0631 \u0645\u0641\u064A\u062F" }, this.renderIcon('thumbs-down', 16)), h("button", { class: `feedback-btn thumbs-up-btn${this.feedbackValue === 'up' ? ' active' : ''}`, onClick: () => this.handleFeedback('up'), title: "\u0645\u0641\u064A\u062F" }, this.renderIcon('thumbs-up', 16)))));
130
+ }
131
+ renderUserMessage() {
132
+ return (h("div", { class: "message-row user-row" }, h("div", { class: "bubble user-bubble" }, h("div", { class: "message-content", ref: el => {
133
+ if (!el)
134
+ return;
135
+ if (this.format === 'markdown') {
136
+ el.innerHTML = this.getRenderedContent();
137
+ }
138
+ else {
139
+ el.textContent = this.content;
140
+ }
141
+ } }))));
142
+ }
143
+ renderAgentMessage() {
144
+ const showActions = this.showActions;
145
+ return (h("div", { class: "message-row agent-row" }, h("div", { class: "agent-bubble-wrapper" }, h("div", { class: "bubble agent-bubble" }, this.content && (h("div", { class: "message-content", ref: el => {
146
+ if (!el)
147
+ return;
148
+ if (this.format === 'markdown') {
149
+ el.innerHTML = this.getRenderedContent();
150
+ }
151
+ else {
152
+ el.textContent = this.content;
153
+ }
154
+ } })), h("slot", null), showActions && this.renderActionsBar()), (this.agentName || this.timestamp) && (h("div", { class: "agent-info" }, this.agentName && h("span", { class: "agent-info-name" }, this.agentName), this.agentName && this.timestamp && this.renderIcon('eclipse', 10), this.timestamp && h("span", { class: "agent-info-time" }, this.getRelativeTime()))))));
155
+ }
156
+ render() {
157
+ return h(Host, { key: '77dd0c46a676c211fdfba283d51bd0e0d2594b24' }, this.role === 'user' ? this.renderUserMessage() : this.renderAgentMessage());
158
+ }
159
+ };
160
+ AiChatMessage.style = aiChatMessageCss();
161
+
162
+ export { AiChatMessage as ai_chat_message };
@@ -0,0 +1,23 @@
1
+ import { r as registerInstance, h, H as Host } from './index-7hrZ8FOQ.js';
2
+ import { i as iconRegistry } from './icon-registry-DYv5ef4M.js';
3
+
4
+ const aiIconCss = () => `:host{display:inline-flex;align-items:center;justify-content:center}svg{display:block}`;
5
+
6
+ const AiIcon = class {
7
+ constructor(hostRef) {
8
+ registerInstance(this, hostRef);
9
+ }
10
+ /** Icon name from the registry */
11
+ name;
12
+ /** Size in pixels for width and height */
13
+ size = 16;
14
+ render() {
15
+ const icon = iconRegistry[this.name];
16
+ if (!icon)
17
+ return null;
18
+ return (h(Host, null, h("svg", { width: this.size, height: this.size, viewBox: icon.viewBox, xmlns: "http://www.w3.org/2000/svg", ref: (el) => el && (el.innerHTML = icon.content), "aria-hidden": "true" })));
19
+ }
20
+ };
21
+ AiIcon.style = aiIconCss();
22
+
23
+ export { AiIcon as ai_icon };
@@ -0,0 +1,32 @@
1
+ import { r as registerInstance, h, H as Host } from './index-7hrZ8FOQ.js';
2
+ import { i as iconRegistry } from './icon-registry-DYv5ef4M.js';
3
+
4
+ const aiLinkCss = () => `:host{--ai-link-color:var(--ai-accent-dark);--ai-link-color-hover:var(--ai-accent-dark);--ai-link-font-size:14px;--ai-link-font-weight:700;--ai-link-line-height:20px;--ai-link-gap:4px;--ai-link-icon-size:16px;display:flex;align-items:center;gap:var(--ai-link-gap);direction:rtl;font-family:var(--ai-font-family, 'PingARLT', sans-serif)}.link{display:inline-flex;align-items:center;justify-content:flex-end;gap:var(--ai-link-gap);color:var(--ai-link-color);font-size:var(--ai-link-font-size);font-weight:var(--ai-link-font-weight);font-family:inherit;line-height:var(--ai-link-line-height);text-decoration:none;white-space:nowrap;cursor:pointer;transition:color 0.15s ease;outline:none}.link:hover{color:var(--ai-link-color-hover);text-decoration:underline}.link:focus-visible{outline:2px solid var(--ai-accent);outline-offset:2px;border-radius:4px}.link__icon{display:inline-flex;align-items:center;justify-content:center;width:var(--ai-link-icon-size);height:var(--ai-link-icon-size);flex-shrink:0;line-height:0}.link__label{color:var(--ai-link-color);font-weight:bold}`;
5
+
6
+ const AiLink = class {
7
+ constructor(hostRef) {
8
+ registerInstance(this, hostRef);
9
+ }
10
+ /** Link display label */
11
+ label = '';
12
+ /** Href URL */
13
+ href = '#';
14
+ /** Link target */
15
+ target = '_blank';
16
+ /** Rel attribute — defaults to noopener noreferrer for _blank */
17
+ rel = '';
18
+ renderShareIcon() {
19
+ const icon = iconRegistry['share'];
20
+ if (!icon)
21
+ return null;
22
+ const svg = `<svg width="16" height="16" viewBox="${icon.viewBox}" fill="none" xmlns="http://www.w3.org/2000/svg">${icon.content}</svg>`;
23
+ return h("span", { class: "link__icon", innerHTML: svg });
24
+ }
25
+ render() {
26
+ const rel = this.rel || (this.target === '_blank' ? 'noopener noreferrer' : undefined);
27
+ return (h(Host, { key: '58a742b11ef7dcc1094031e804be6032311cea9d' }, h("span", { key: 'bf45468deb328c2d8ed70ac299d36968c16ababe', class: "link__label" }, this.label, h("slot", { key: 'bd43bc12d120ab806c895922ede0a08d4ec2f882' })), h("a", { key: 'b7c75a59bf18b1f1dc2e713b9e78c045afaa82e2', class: "link", href: this.href, target: this.target, rel: rel }, this.renderShareIcon())));
28
+ }
29
+ };
30
+ AiLink.style = aiLinkCss();
31
+
32
+ export { AiLink as ai_link };
@@ -0,0 +1,75 @@
1
+ import { r as registerInstance, c as createEvent, h, H as Host } from './index-7hrZ8FOQ.js';
2
+ import { i as iconRegistry } from './icon-registry-DYv5ef4M.js';
3
+
4
+ const aiLoadingCss = () => `:host{display:block;direction:rtl}.icon-wrap{display:inline-flex;align-items:center;justify-content:center;line-height:0}.sparkle-avatar{width:24px;height:24px;border-radius:9999px;background:var(--ai-bg-card, #FCFCFC);box-shadow:inset 0px 0px 3px 1px rgba(18, 18, 23, 0.06);display:flex;align-items:center;justify-content:center;flex-shrink:0;color:var(--ai-amber)}.thinking-row{display:inline-flex;align-items:center;gap:8px;flex-direction:row}@keyframes shimmer{0%{background-position:200% center}100%{background-position:-200% center}}.shimmer-text{font-size:14px;font-weight:400;line-height:1.5;background:var(--ai-glow-gradient, linear-gradient(90deg, #737373 0%, #c5c5c5 50%, #737373 100%));background-size:200% auto;-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text;animation:shimmer 2s linear infinite}.steps-card{background:var(--ai-bg-card, #ffffff);border:1px solid var(--ai-border-default, #eeeeee);border-radius:16px;box-shadow:0px 1px 2px 0px rgba(18, 18, 23, 0.05);overflow:hidden}.steps-header{padding:16px;display:flex;align-items:center;gap:8px;border-bottom:1px solid var(--ai-border-default, #eeeeee)}.steps-header.collapsible{cursor:pointer;user-select:none}.steps-header-center{flex:1;display:flex;align-items:center;gap:8px;min-width:0}.steps-title{font-size:16px;font-weight:500;color:var(--ai-text-primary, #333333);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.progress-badge{font-size:12px;font-weight:500;color:var(--ai-accent-dark);background:var(--ai-accent-bg);padding:2px 8px;border-radius:9999px;white-space:nowrap;flex-shrink:0}.collapse-btn{display:inline-flex;align-items:center;justify-content:center;background:none;border:none;padding:0;cursor:pointer;color:var(--ai-text-secondary, #737373);flex-shrink:0;transition:transform 0.2s ease;transform:rotate(180deg)}.collapse-btn.expanded{transform:rotate(0deg)}.steps-body{padding:12px 16px;display:flex;flex-direction:column}.step-row{display:flex;align-items:flex-start;gap:12px;cursor:pointer;padding:4px 0}.step-row:hover .step-text{color:var(--ai-text-primary, #333333)}.step-text{flex:1;font-size:14px;font-weight:400;color:var(--ai-text-secondary, #737373);line-height:1.5;padding-top:4px}.step-badge-col{display:flex;flex-direction:column;align-items:center;flex-shrink:0}.step-separator{width:1px;height:16px;background:var(--ai-border-default, #eeeeee);margin:2px 0}.step-badge-outer{padding:2px;border-radius:9999px;background:var(--ai-bg-surface, #f4f4f4);display:inline-flex;align-items:center;justify-content:center}.step-badge-inner{width:26px;height:26px;border-radius:9999px;background:var(--ai-bg-card, #ffffff);box-shadow:0px 0px 2px 1px rgba(18, 18, 23, 0.08);display:flex;align-items:center;justify-content:center;color:var(--ai-text-secondary, #737373)}.step-badge-inner.completed{background:var(--ai-success-bg);color:var(--ai-success-text)}.step-number{font-size:14px;font-weight:500;color:var(--ai-text-secondary, #737373);line-height:1}`;
5
+
6
+ const AiLoading = class {
7
+ constructor(hostRef) {
8
+ registerInstance(this, hostRef);
9
+ this.toggleExpand = createEvent(this, "toggleExpand");
10
+ this.stepClick = createEvent(this, "stepClick");
11
+ }
12
+ /** Main mode switch */
13
+ mode = 'thinking';
14
+ /** Thinking mode status text */
15
+ statusText = 'جاري التفكير...';
16
+ /** Steps as JSON string array of LoadingStep */
17
+ steps = '[]';
18
+ /** Steps mode title */
19
+ headerTitle = 'خطة التنفيذ';
20
+ /** Steps mode expand state */
21
+ expanded = true;
22
+ /** Whether steps card is collapsible */
23
+ collapsible = true;
24
+ toggleExpand;
25
+ stepClick;
26
+ _expanded = true;
27
+ componentWillLoad() {
28
+ this._expanded = this.expanded;
29
+ }
30
+ renderIcon(name, width, height) {
31
+ const icon = iconRegistry[name];
32
+ if (!icon)
33
+ return null;
34
+ const svg = `<svg width="${width}" height="${height}" viewBox="${icon.viewBox}" fill="none" xmlns="http://www.w3.org/2000/svg">${icon.content}</svg>`;
35
+ return h("span", { class: "icon-wrap", innerHTML: svg });
36
+ }
37
+ renderSparkleAvatar() {
38
+ return h("div", { class: "sparkle-avatar" }, this.renderIcon('sparkle', 14, 14));
39
+ }
40
+ renderStepBadge(step, index) {
41
+ const isCompleted = step.status === 'completed';
42
+ return (h("div", { class: "step-badge-outer" }, h("div", { class: `step-badge-inner ${isCompleted ? 'completed' : ''}` }, isCompleted ? this.renderIcon('check', 14, 14) : h("span", { class: "step-number" }, index + 1))));
43
+ }
44
+ getStepsList() {
45
+ try {
46
+ return JSON.parse(this.steps) || [];
47
+ }
48
+ catch {
49
+ return [];
50
+ }
51
+ }
52
+ handleToggle() {
53
+ if (!this.collapsible)
54
+ return;
55
+ this._expanded = !this._expanded;
56
+ this.expanded = this._expanded;
57
+ this.toggleExpand.emit(this._expanded);
58
+ }
59
+ renderThinkingMode() {
60
+ return (h("div", { class: "thinking-row" }, this.renderSparkleAvatar(), h("span", { class: "shimmer-text" }, this.statusText)));
61
+ }
62
+ renderStepsMode() {
63
+ const stepsList = this.getStepsList();
64
+ const completedCount = stepsList.filter(s => s.status === 'completed').length;
65
+ const total = stepsList.length;
66
+ const allDone = total > 0 && completedCount === total;
67
+ return (h("div", { class: "steps-card" }, h("div", { class: `steps-header ${this.collapsible ? 'collapsible' : ''}`, onClick: () => this.handleToggle() }, this.renderSparkleAvatar(), h("div", { class: "steps-header-center" }, h("span", { class: "steps-title" }, this.headerTitle), total > 0 && h("span", { class: "progress-badge" }, allDone ? 'مكتمل' : `${completedCount}/${total}`)), this.collapsible && h("button", { class: `collapse-btn ${this._expanded ? 'expanded' : ''}` }, this.renderIcon('chevron-down', 20, 20))), this._expanded && stepsList.length > 0 && (h("div", { class: "steps-body" }, stepsList.map((step, i) => (h("div", { class: "step-row", onClick: () => this.stepClick.emit(step) }, h("div", { class: "step-badge-col" }, this.renderStepBadge(step, i), i < stepsList.length - 1 && h("div", { class: "step-separator" })), h("span", { class: "step-text" }, step.title))))))));
68
+ }
69
+ render() {
70
+ return h(Host, { key: '8a994758abe21c8a333088eeda498d158631bae6' }, this.mode === 'thinking' ? this.renderThinkingMode() : this.renderStepsMode());
71
+ }
72
+ };
73
+ AiLoading.style = aiLoadingCss();
74
+
75
+ export { AiLoading as ai_loading };
@@ -0,0 +1,63 @@
1
+ import { r as registerInstance, c as createEvent, a as getElement, h, H as Host } from './index-7hrZ8FOQ.js';
2
+
3
+ const aiMessageInputCss = () => `:host{display:block;font-family:var(--ai-font-family, "PingARLT", sans-serif);width:100%;--ai-input-bg:var(--ai-bg-input, #ffffff);--ai-input-border-color:var(--ai-border-default, #eeeeee);--ai-input-text-color:var(--ai-text-primary, #333333);--ai-input-placeholder-color:var(--ai-text-secondary, #737373);--ai-voice-button-color:var(--ai-text-secondary, #737373);--ai-send-button-bg:var(--ai-border-default, #eeeeee);--ai-send-button-border:var(--ai-border-default, #eeeeee);--ai-send-button-color:var(--ai-text-secondary, #737373);--ai-send-button-active-color:var(--ai-text-primary, #333333)}.wrapper{position:relative;padding:var(--ai-input-wrapper-padding, 16px)}.glow{position:absolute;bottom:20px;left:39px;right:39px;height:29px;border-radius:9999px;background:var(--ai-input-glow);filter:blur(20px);opacity:0.9;pointer-events:none}.input-container{position:relative;background-color:var(--ai-input-bg, #ffffff);border-radius:var(--ai-input-border-radius, 9999px);border:1px solid var(--ai-input-border-color, #eeeeee);box-shadow:0 1px 2px 0 var(--ai-input-shadow-color, rgba(18, 18, 23, 0.05));padding:var(--ai-input-padding, 12px);overflow:hidden}.input-row{display:flex;align-items:center;gap:var(--ai-input-gap, 12px)}.actions{display:flex;align-items:center;gap:var(--ai-actions-gap, 8px);flex-shrink:0}.send-button{display:inline-flex;align-items:center;justify-content:center;gap:4px;min-height:32px;max-height:32px;padding:4px 8px;border-radius:32px;border:2px solid var(--ai-send-button-border, #eeeeee);background-color:var(--ai-send-button-bg, #eeeeee);color:var(--ai-send-button-color, #737373);cursor:not-allowed;transition:background-color 0.2s ease, border-color 0.2s ease, color 0.2s ease;flex-shrink:0}.send-button.active{background-color:var(--ai-send-button-active-bg, var(--ai-accent));border-color:var(--ai-send-button-active-border, var(--ai-accent));color:var(--ai-accent-text);cursor:pointer}.send-button.active:hover{background-color:var(--ai-send-button-active-hover-bg, var(--ai-accent));border-color:var(--ai-send-button-active-hover-border, var(--ai-accent))}.send-button:focus{outline:none}.voice-button{display:inline-flex;align-items:center;justify-content:center;width:32px;height:32px;border-radius:32px;border:none;background-color:transparent;color:var(--ai-voice-button-color, #737373);cursor:pointer;transition:background-color 0.2s ease, color 0.2s ease;flex-shrink:0}.voice-button:hover:not(:disabled){background-color:var(--ai-voice-button-hover-bg, rgba(0, 0, 0, 0.06));color:var(--ai-voice-button-hover-color, var(--ai-text-secondary))}.voice-button:disabled{cursor:not-allowed;opacity:0.5}.voice-button:focus{outline:none;box-shadow:0 0 0 2px var(--ai-focus-ring-color, var(--ai-focus-ring))}.textarea{flex:1;resize:none;outline:none;border:none;background:transparent;font-size:var(--ai-input-font-size, 14px);line-height:var(--ai-input-line-height, 20px);color:var(--ai-input-text-color, #333333);font-family:inherit;min-height:20px;text-align:right;direction:rtl;padding:0;overflow:hidden}.textarea::placeholder{color:var(--ai-input-placeholder-color, #737373)}.textarea:disabled{cursor:not-allowed;opacity:0.6}.input-container:focus-within{border-color:var(--ai-input-focus-border-color, var(--ai-accent));box-shadow:0 0 10px 4px rgba(227, 255, 247, 0.4)}:host([disabled]) .wrapper{opacity:0.6;pointer-events:none}:host([dir='ltr']) .textarea{text-align:left;direction:ltr}`;
4
+
5
+ const MessageInput = class {
6
+ constructor(hostRef) {
7
+ registerInstance(this, hostRef);
8
+ this.sendMessage = createEvent(this, "sendMessage");
9
+ this.voiceButtonClick = createEvent(this, "voiceButtonClick");
10
+ }
11
+ get el() { return getElement(this); }
12
+ /** Placeholder text for the textarea */
13
+ placeholder = 'ايش في بالك؟';
14
+ /** Whether the input is disabled */
15
+ disabled = false;
16
+ /** Whether to show the voice recording button */
17
+ showVoiceButton = true;
18
+ inputValue = '';
19
+ textareaRef;
20
+ /** Event emitted when a message is sent */
21
+ sendMessage;
22
+ /** Event emitted when the voice button is clicked — caller controls rendering the voice recorder */
23
+ voiceButtonClick;
24
+ /** Set the textarea value programmatically (e.g. after speech-to-text transcription) */
25
+ async setInputValue(value) {
26
+ this.inputValue = value;
27
+ if (this.textareaRef) {
28
+ this.textareaRef.style.height = 'auto';
29
+ this.textareaRef.style.height = `${this.textareaRef.scrollHeight}px`;
30
+ this.textareaRef.focus();
31
+ }
32
+ }
33
+ handleSendMessage = () => {
34
+ if (!this.inputValue.trim() || this.disabled)
35
+ return;
36
+ this.sendMessage.emit(this.inputValue.trim());
37
+ this.inputValue = '';
38
+ if (this.textareaRef) {
39
+ this.textareaRef.style.height = 'auto';
40
+ }
41
+ };
42
+ handleKeyPress = (e) => {
43
+ if (e.key === 'Enter' && !e.shiftKey) {
44
+ e.preventDefault();
45
+ this.handleSendMessage();
46
+ }
47
+ };
48
+ handleInputChange = (e) => {
49
+ const target = e.target;
50
+ this.inputValue = target.value;
51
+ if (this.textareaRef) {
52
+ this.textareaRef.style.height = 'auto';
53
+ this.textareaRef.style.height = `${this.textareaRef.scrollHeight}px`;
54
+ }
55
+ };
56
+ render() {
57
+ const canSend = !!this.inputValue.trim() && !this.disabled;
58
+ return (h(Host, { key: '97dfe627b89657d36e4f7281a8bdb708cc913374' }, h("div", { key: 'a3efb2a0b95ec3a86cc5f575d0fdb2bb6dd2eb6c', part: "wrapper", class: "wrapper" }, h("div", { key: '5986fa2946a44757c143999a72b25ea3b6e7c336', part: "glow", class: "glow", "aria-hidden": "true" }), h("div", { key: 'd5b9d346495de00e8b0e0900ef3e766756844626', part: "container", class: "input-container" }, h("div", { key: '8313695b2e4d7557a5362e9b9d2a5c5803a4ec0c', class: "input-row" }, h("div", { key: '9c184f8097e28527b5d18fccf92010fb36b14a9c', class: "actions" }, h("button", { key: '39ad3feb24a53fd5a08e8a8388f7bcee71413a91', part: "send-button", class: `send-button${canSend ? ' active' : ''}`, onClick: this.handleSendMessage, disabled: !canSend, type: "button", "aria-label": "Send message" }, h("ai-icon", { key: '1fe555709288d33551696312fb3329b1c656d063', name: "send", size: 16 })), this.showVoiceButton && !this.inputValue && (h("button", { key: 'a7bcc3b9ca5f5e59c32a34ab33c2fbbd607bb298', part: "voice-button", class: "voice-button", onClick: () => this.voiceButtonClick.emit(), disabled: this.disabled, type: "button", "aria-label": "Record voice" }, h("ai-icon", { key: '98fea04c79e841e4a2b8ee50a480bb554212b055', name: "mic", size: 16 })))), h("textarea", { key: '798af74ca2298a31f37459dfa1c176182d740839', part: "textarea", ref: el => (this.textareaRef = el), value: this.inputValue, onInput: this.handleInputChange, onKeyPress: this.handleKeyPress, disabled: this.disabled, placeholder: this.placeholder, rows: 1, class: "textarea" }))))));
59
+ }
60
+ };
61
+ MessageInput.style = aiMessageInputCss();
62
+
63
+ export { MessageInput as ai_message_input };