@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
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,25 @@
1
+ 'use strict';
2
+
3
+ var index = require('./index-DLJcLHFH.js');
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}`;
6
+
7
+ const AiCard = class {
8
+ constructor(hostRef) {
9
+ index.registerInstance(this, hostRef);
10
+ }
11
+ /** Remove the default padding */
12
+ noPadding = false;
13
+ /** Remove the shadow */
14
+ noShadow = false;
15
+ render() {
16
+ return (index.h(index.Host, { key: '4805b02b4eee8e01d0233de788a58770a85db2aa' }, index.h("div", { key: '75576f8a791fc49c3a750d491b0e835d0e5ce8cb', class: {
17
+ card: true,
18
+ 'card--no-padding': this.noPadding,
19
+ 'card--no-shadow': this.noShadow,
20
+ } }, index.h("slot", { key: 'e16cdb10e803451fdd47006a98656168fe2495f4' }))));
21
+ }
22
+ };
23
+ AiCard.style = aiCardCss();
24
+
25
+ exports.ai_card = AiCard;
@@ -0,0 +1,138 @@
1
+ 'use strict';
2
+
3
+ var index = require('./index-DLJcLHFH.js');
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}`;
6
+
7
+ const ChatContainer = class {
8
+ constructor(hostRef) {
9
+ index.registerInstance(this, hostRef);
10
+ }
11
+ get el() { return index.getElement(this); }
12
+ /** Controls visibility of the chat panel */
13
+ isOpen = false;
14
+ /** Position of the panel: 'left', 'right', or 'float' */
15
+ position = 'right';
16
+ /** Width of the panel (CSS value, e.g., '400px', '30%', '28rem') */
17
+ width = '28rem';
18
+ /** Enable/disable auto-scroll to latest message */
19
+ autoScroll = true;
20
+ /** Show AI watermark in the top half of the container */
21
+ showWatermark = false;
22
+ /** Height of the panel when position='float' */
23
+ floatHeight = '600px';
24
+ isMobile = false;
25
+ containerRef;
26
+ dragState = null;
27
+ resizeObserver;
28
+ componentWillLoad() {
29
+ this.checkMobile();
30
+ }
31
+ componentDidLoad() {
32
+ if (typeof window !== 'undefined') {
33
+ this.resizeObserver = new ResizeObserver(() => {
34
+ this.checkMobile();
35
+ });
36
+ this.resizeObserver.observe(document.body);
37
+ if (this.position === 'float') {
38
+ this.setupDrag();
39
+ }
40
+ }
41
+ }
42
+ positionChanged(newVal) {
43
+ if (newVal === 'float') {
44
+ this.setupDrag();
45
+ }
46
+ }
47
+ disconnectedCallback() {
48
+ if (this.resizeObserver) {
49
+ this.resizeObserver.disconnect();
50
+ }
51
+ }
52
+ checkMobile() {
53
+ if (typeof window !== 'undefined') {
54
+ this.isMobile = window.innerWidth < 768;
55
+ }
56
+ }
57
+ 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
+ });
102
+ }
103
+ getContainerClasses() {
104
+ const classes = ['chat-container', this.position];
105
+ if (this.isOpen) {
106
+ classes.push('open');
107
+ }
108
+ if (this.isMobile) {
109
+ classes.push('mobile');
110
+ }
111
+ return classes.join(' ');
112
+ }
113
+ getContainerStyle() {
114
+ const style = {};
115
+ if (this.isMobile) {
116
+ return style;
117
+ }
118
+ if (this.position === 'float') {
119
+ style.width = this.width;
120
+ style.height = this.floatHeight;
121
+ }
122
+ else {
123
+ style.width = this.width;
124
+ }
125
+ return style;
126
+ }
127
+ 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" }))));
129
+ }
130
+ static get watchers() { return {
131
+ "position": [{
132
+ "positionChanged": 0
133
+ }]
134
+ }; }
135
+ };
136
+ ChatContainer.style = aiChatContainerCss();
137
+
138
+ exports.ai_chat_container = ChatContainer;
@@ -0,0 +1,79 @@
1
+ 'use strict';
2
+
3
+ var index = require('./index-DLJcLHFH.js');
4
+ var iconRegistry = require('./icon-registry-dmfLA-Dj.js');
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}`;
7
+
8
+ const AiChatHeader = class {
9
+ constructor(hostRef) {
10
+ index.registerInstance(this, hostRef);
11
+ this.closeClick = index.createEvent(this, "closeClick");
12
+ this.editClick = index.createEvent(this, "editClick");
13
+ this.dropdownClick = index.createEvent(this, "dropdownClick");
14
+ this.moreClick = index.createEvent(this, "moreClick");
15
+ this.backClick = index.createEvent(this, "backClick");
16
+ this.headerDragStart = index.createEvent(this, "headerDragStart");
17
+ }
18
+ /** Layout variant */
19
+ mode = 'agent';
20
+ /** Agent mode: conversation title */
21
+ conversation = 'محادثة جديدة';
22
+ /** Human mode: agent's display name */
23
+ agentName = '';
24
+ /** Human mode: status label (e.g. "Active") */
25
+ agentStatus = '';
26
+ /** Human mode: avatar image URL */
27
+ agentAvatar = '';
28
+ /** Human mode: show the back button */
29
+ showBack = true;
30
+ isDraggable = false;
31
+ /** Cancel / close button */
32
+ closeClick;
33
+ /** Pencil-edit button (agent mode) */
34
+ editClick;
35
+ /** Title / chevron click → open conversation list (agent mode) */
36
+ dropdownClick;
37
+ /** Chevron-down button (human mode) */
38
+ moreClick;
39
+ /** Back-arrow button (human mode) */
40
+ backClick;
41
+ /**
42
+ * Fired on pointerdown of the drag handle.
43
+ * Composed + bubbling so ai-chat-container can receive it across shadow roots.
44
+ */
45
+ headerDragStart;
46
+ renderIcon(name, width, height) {
47
+ const icon = iconRegistry.iconRegistry[name];
48
+ if (!icon)
49
+ return null;
50
+ const svg = `<svg width="${width}" height="${height}" viewBox="${icon.viewBox}" fill="none" xmlns="http://www.w3.org/2000/svg">${icon.content}</svg>`;
51
+ return index.h("span", { class: "icon-wrap", innerHTML: svg });
52
+ }
53
+ renderAgentMode() {
54
+ 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))),
61
+ ];
62
+ }
63
+ renderHumanMode() {
64
+ 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))),
71
+ ];
72
+ }
73
+ render() {
74
+ return (index.h(index.Host, { key: '93fe332abe1339f7235aa18717d63aa65d9aac13' }, index.h("div", { key: 'b496695911f7d1f959c4f98506b0d230e77a86c3', class: "header-container" }, this.mode === 'agent' ? this.renderAgentMode() : this.renderHumanMode())));
75
+ }
76
+ };
77
+ AiChatHeader.style = aiChatHeaderCss();
78
+
79
+ exports.ai_chat_header = AiChatHeader;
@@ -0,0 +1,164 @@
1
+ 'use strict';
2
+
3
+ var index = require('./index-DLJcLHFH.js');
4
+ var iconRegistry = require('./icon-registry-dmfLA-Dj.js');
5
+
6
+ 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}}`;
7
+
8
+ const AiChatMessage = class {
9
+ constructor(hostRef) {
10
+ index.registerInstance(this, hostRef);
11
+ this.messageCopy = index.createEvent(this, "messageCopy");
12
+ this.messageFeedback = index.createEvent(this, "messageFeedback");
13
+ this.messageRegenerate = index.createEvent(this, "messageRegenerate");
14
+ }
15
+ role = 'user';
16
+ content = '';
17
+ format = 'text';
18
+ agentName = '';
19
+ timestamp = '';
20
+ showActions = true;
21
+ enableRegenerate = false;
22
+ feedbackValue = null;
23
+ messageCopy;
24
+ messageFeedback;
25
+ messageRegenerate;
26
+ copySuccess = false;
27
+ copyTimeout;
28
+ disconnectedCallback() {
29
+ if (this.copyTimeout)
30
+ clearTimeout(this.copyTimeout);
31
+ }
32
+ renderIcon(name, size = 16) {
33
+ const icon = iconRegistry.iconRegistry[name];
34
+ if (!icon)
35
+ return null;
36
+ const svg = `<svg width="${size}" height="${size}" viewBox="${icon.viewBox}" fill="none" xmlns="http://www.w3.org/2000/svg">${icon.content}</svg>`;
37
+ return index.h("span", { class: "icon-wrap", innerHTML: svg });
38
+ }
39
+ parseMarkdown(text) {
40
+ let html = text.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
41
+ const blocks = [];
42
+ html = html.replace(/```(?:\w+)?\n?([\s\S]*?)```/g, (_, code) => {
43
+ const idx = blocks.length;
44
+ blocks.push(`<pre><code>${code}</code></pre>`);
45
+ return `\x00BLOCK${idx}\x00`;
46
+ });
47
+ html = html.replace(/`([^`]+)`/g, '<code>$1</code>');
48
+ html = html.replace(/^## (.+)$/gm, '<h2>$1</h2>');
49
+ html = html.replace(/^### (.+)$/gm, '<h3>$1</h3>');
50
+ html = html.replace(/\*\*(.+?)\*\*/g, '<strong>$1</strong>');
51
+ html = html.replace(/\*([^*\n]+)\*/g, '<em>$1</em>');
52
+ html = html.replace(/((?:^[ \t]*[-*] .+\n?)+)/gm, match => {
53
+ const items = match
54
+ .trim()
55
+ .split('\n')
56
+ .filter(l => l.trim())
57
+ .map(l => `<li>${l.replace(/^[ \t]*[-*] /, '')}</li>`)
58
+ .join('');
59
+ return `\x00BLOCK${blocks.length}\x00${(() => {
60
+ blocks.push(`<ul>${items}</ul>`);
61
+ return '';
62
+ })()}`;
63
+ });
64
+ html = html.replace(/((?:^[ \t]*\d+\. .+\n?)+)/gm, match => {
65
+ const items = match
66
+ .trim()
67
+ .split('\n')
68
+ .filter(l => l.trim())
69
+ .map(l => `<li>${l.replace(/^[ \t]*\d+\. /, '')}</li>`)
70
+ .join('');
71
+ return `\x00BLOCK${blocks.length}\x00${(() => {
72
+ blocks.push(`<ol>${items}</ol>`);
73
+ return '';
74
+ })()}`;
75
+ });
76
+ html = html
77
+ .split(/\n{2,}/)
78
+ .map(chunk => {
79
+ const trimmed = chunk.trim();
80
+ if (!trimmed)
81
+ return '';
82
+ if (/^\x00BLOCK\d+\x00$/.test(trimmed))
83
+ return trimmed;
84
+ return `<p>${trimmed.replace(/\n/g, '<br>')}</p>`;
85
+ })
86
+ .join('');
87
+ html = html.replace(/\x00BLOCK(\d+)\x00/g, (_, i) => blocks[parseInt(i, 10)] || '');
88
+ return html;
89
+ }
90
+ getRenderedContent() {
91
+ if (!this.content)
92
+ return '';
93
+ let html = this.parseMarkdown(this.content);
94
+ return html;
95
+ }
96
+ getRelativeTime() {
97
+ if (!this.timestamp)
98
+ return '';
99
+ try {
100
+ const date = new Date(this.timestamp);
101
+ if (isNaN(date.getTime()))
102
+ return this.timestamp;
103
+ const diffMin = Math.floor((Date.now() - date.getTime()) / 60000);
104
+ if (diffMin < 1)
105
+ return 'الآن';
106
+ if (diffMin < 60)
107
+ return `منذ ${diffMin} دقيقة`;
108
+ const hours = Math.floor(diffMin / 60);
109
+ if (hours < 24)
110
+ return `منذ ${hours} ساعة`;
111
+ return `منذ ${Math.floor(hours / 24)} يوم`;
112
+ }
113
+ catch {
114
+ return this.timestamp;
115
+ }
116
+ }
117
+ async handleCopy() {
118
+ try {
119
+ await navigator.clipboard.writeText(this.content);
120
+ }
121
+ catch (_) { }
122
+ this.copySuccess = true;
123
+ this.messageCopy.emit();
124
+ this.copyTimeout = setTimeout(() => (this.copySuccess = false), 1500);
125
+ }
126
+ handleFeedback(val) {
127
+ this.feedbackValue = this.feedbackValue === val ? null : val;
128
+ this.messageFeedback.emit(val);
129
+ }
130
+ renderActionsBar() {
131
+ return (index.h("div", { class: "actions-bar" }, this.enableRegenerate && index.h("button", { class: 'action-btn', onClick: () => this.messageRegenerate.emit(), title: "\u0625\u0639\u0627\u062F\u0629 \u062A\u062D\u0645\u064A\u0644" }, this.renderIcon('reload', 16)), index.h("button", { class: `action-btn copy-btn${this.copySuccess ? ' copy-success' : ''}`, onClick: () => this.handleCopy(), title: "\u0646\u0633\u062E" }, this.renderIcon('copy', 16)), index.h("div", { class: "feedback-group" }, index.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)), index.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)))));
132
+ }
133
+ renderUserMessage() {
134
+ return (index.h("div", { class: "message-row user-row" }, index.h("div", { class: "bubble user-bubble" }, index.h("div", { class: "message-content", ref: el => {
135
+ if (!el)
136
+ return;
137
+ if (this.format === 'markdown') {
138
+ el.innerHTML = this.getRenderedContent();
139
+ }
140
+ else {
141
+ el.textContent = this.content;
142
+ }
143
+ } }))));
144
+ }
145
+ renderAgentMessage() {
146
+ const showActions = this.showActions;
147
+ return (index.h("div", { class: "message-row agent-row" }, index.h("div", { class: "agent-bubble-wrapper" }, index.h("div", { class: "bubble agent-bubble" }, this.content && (index.h("div", { class: "message-content", ref: el => {
148
+ if (!el)
149
+ return;
150
+ if (this.format === 'markdown') {
151
+ el.innerHTML = this.getRenderedContent();
152
+ }
153
+ else {
154
+ el.textContent = this.content;
155
+ }
156
+ } })), index.h("slot", null), showActions && this.renderActionsBar()), (this.agentName || this.timestamp) && (index.h("div", { class: "agent-info" }, this.agentName && index.h("span", { class: "agent-info-name" }, this.agentName), this.agentName && this.timestamp && this.renderIcon('eclipse', 10), this.timestamp && index.h("span", { class: "agent-info-time" }, this.getRelativeTime()))))));
157
+ }
158
+ render() {
159
+ return index.h(index.Host, { key: '77dd0c46a676c211fdfba283d51bd0e0d2594b24' }, this.role === 'user' ? this.renderUserMessage() : this.renderAgentMessage());
160
+ }
161
+ };
162
+ AiChatMessage.style = aiChatMessageCss();
163
+
164
+ exports.ai_chat_message = AiChatMessage;
@@ -0,0 +1,25 @@
1
+ 'use strict';
2
+
3
+ var index = require('./index-DLJcLHFH.js');
4
+ var iconRegistry = require('./icon-registry-dmfLA-Dj.js');
5
+
6
+ const aiIconCss = () => `:host{display:inline-flex;align-items:center;justify-content:center}svg{display:block}`;
7
+
8
+ const AiIcon = class {
9
+ constructor(hostRef) {
10
+ index.registerInstance(this, hostRef);
11
+ }
12
+ /** Icon name from the registry */
13
+ name;
14
+ /** Size in pixels for width and height */
15
+ size = 16;
16
+ render() {
17
+ const icon = iconRegistry.iconRegistry[this.name];
18
+ if (!icon)
19
+ return null;
20
+ return (index.h(index.Host, null, index.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" })));
21
+ }
22
+ };
23
+ AiIcon.style = aiIconCss();
24
+
25
+ exports.ai_icon = AiIcon;
@@ -0,0 +1,34 @@
1
+ 'use strict';
2
+
3
+ var index = require('./index-DLJcLHFH.js');
4
+ var iconRegistry = require('./icon-registry-dmfLA-Dj.js');
5
+
6
+ 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}`;
7
+
8
+ const AiLink = class {
9
+ constructor(hostRef) {
10
+ index.registerInstance(this, hostRef);
11
+ }
12
+ /** Link display label */
13
+ label = '';
14
+ /** Href URL */
15
+ href = '#';
16
+ /** Link target */
17
+ target = '_blank';
18
+ /** Rel attribute — defaults to noopener noreferrer for _blank */
19
+ rel = '';
20
+ renderShareIcon() {
21
+ const icon = iconRegistry.iconRegistry['share'];
22
+ if (!icon)
23
+ return null;
24
+ const svg = `<svg width="16" height="16" viewBox="${icon.viewBox}" fill="none" xmlns="http://www.w3.org/2000/svg">${icon.content}</svg>`;
25
+ return index.h("span", { class: "link__icon", innerHTML: svg });
26
+ }
27
+ render() {
28
+ const rel = this.rel || (this.target === '_blank' ? 'noopener noreferrer' : undefined);
29
+ return (index.h(index.Host, { key: '58a742b11ef7dcc1094031e804be6032311cea9d' }, index.h("span", { key: 'bf45468deb328c2d8ed70ac299d36968c16ababe', class: "link__label" }, this.label, index.h("slot", { key: 'bd43bc12d120ab806c895922ede0a08d4ec2f882' })), index.h("a", { key: 'b7c75a59bf18b1f1dc2e713b9e78c045afaa82e2', class: "link", href: this.href, target: this.target, rel: rel }, this.renderShareIcon())));
30
+ }
31
+ };
32
+ AiLink.style = aiLinkCss();
33
+
34
+ exports.ai_link = AiLink;
@@ -0,0 +1,77 @@
1
+ 'use strict';
2
+
3
+ var index = require('./index-DLJcLHFH.js');
4
+ var iconRegistry = require('./icon-registry-dmfLA-Dj.js');
5
+
6
+ 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}`;
7
+
8
+ const AiLoading = class {
9
+ constructor(hostRef) {
10
+ index.registerInstance(this, hostRef);
11
+ this.toggleExpand = index.createEvent(this, "toggleExpand");
12
+ this.stepClick = index.createEvent(this, "stepClick");
13
+ }
14
+ /** Main mode switch */
15
+ mode = 'thinking';
16
+ /** Thinking mode status text */
17
+ statusText = 'جاري التفكير...';
18
+ /** Steps as JSON string array of LoadingStep */
19
+ steps = '[]';
20
+ /** Steps mode title */
21
+ headerTitle = 'خطة التنفيذ';
22
+ /** Steps mode expand state */
23
+ expanded = true;
24
+ /** Whether steps card is collapsible */
25
+ collapsible = true;
26
+ toggleExpand;
27
+ stepClick;
28
+ _expanded = true;
29
+ componentWillLoad() {
30
+ this._expanded = this.expanded;
31
+ }
32
+ renderIcon(name, width, height) {
33
+ const icon = iconRegistry.iconRegistry[name];
34
+ if (!icon)
35
+ return null;
36
+ const svg = `<svg width="${width}" height="${height}" viewBox="${icon.viewBox}" fill="none" xmlns="http://www.w3.org/2000/svg">${icon.content}</svg>`;
37
+ return index.h("span", { class: "icon-wrap", innerHTML: svg });
38
+ }
39
+ renderSparkleAvatar() {
40
+ return index.h("div", { class: "sparkle-avatar" }, this.renderIcon('sparkle', 14, 14));
41
+ }
42
+ renderStepBadge(step, index$1) {
43
+ const isCompleted = step.status === 'completed';
44
+ return (index.h("div", { class: "step-badge-outer" }, index.h("div", { class: `step-badge-inner ${isCompleted ? 'completed' : ''}` }, isCompleted ? this.renderIcon('check', 14, 14) : index.h("span", { class: "step-number" }, index$1 + 1))));
45
+ }
46
+ getStepsList() {
47
+ try {
48
+ return JSON.parse(this.steps) || [];
49
+ }
50
+ catch {
51
+ return [];
52
+ }
53
+ }
54
+ handleToggle() {
55
+ if (!this.collapsible)
56
+ return;
57
+ this._expanded = !this._expanded;
58
+ this.expanded = this._expanded;
59
+ this.toggleExpand.emit(this._expanded);
60
+ }
61
+ renderThinkingMode() {
62
+ return (index.h("div", { class: "thinking-row" }, this.renderSparkleAvatar(), index.h("span", { class: "shimmer-text" }, this.statusText)));
63
+ }
64
+ renderStepsMode() {
65
+ const stepsList = this.getStepsList();
66
+ const completedCount = stepsList.filter(s => s.status === 'completed').length;
67
+ const total = stepsList.length;
68
+ const allDone = total > 0 && completedCount === total;
69
+ return (index.h("div", { class: "steps-card" }, index.h("div", { class: `steps-header ${this.collapsible ? 'collapsible' : ''}`, onClick: () => this.handleToggle() }, this.renderSparkleAvatar(), index.h("div", { class: "steps-header-center" }, index.h("span", { class: "steps-title" }, this.headerTitle), total > 0 && index.h("span", { class: "progress-badge" }, allDone ? 'مكتمل' : `${completedCount}/${total}`)), this.collapsible && index.h("button", { class: `collapse-btn ${this._expanded ? 'expanded' : ''}` }, this.renderIcon('chevron-down', 20, 20))), this._expanded && stepsList.length > 0 && (index.h("div", { class: "steps-body" }, stepsList.map((step, i) => (index.h("div", { class: "step-row", onClick: () => this.stepClick.emit(step) }, index.h("div", { class: "step-badge-col" }, this.renderStepBadge(step, i), i < stepsList.length - 1 && index.h("div", { class: "step-separator" })), index.h("span", { class: "step-text" }, step.title))))))));
70
+ }
71
+ render() {
72
+ return index.h(index.Host, { key: '8a994758abe21c8a333088eeda498d158631bae6' }, this.mode === 'thinking' ? this.renderThinkingMode() : this.renderStepsMode());
73
+ }
74
+ };
75
+ AiLoading.style = aiLoadingCss();
76
+
77
+ exports.ai_loading = AiLoading;