@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,7 @@
1
+ 'use strict';
2
+
3
+ function format(first, middle, last) {
4
+ return (first || '') + (middle ? ` ${middle}` : '') + (last ? ` ${last}` : '');
5
+ }
6
+
7
+ exports.format = format;
@@ -0,0 +1,12 @@
1
+ 'use strict';
2
+
3
+ var index = require('./index-DLJcLHFH.js');
4
+
5
+ const defineCustomElements = async (win, options) => {
6
+ if (typeof window === 'undefined') return undefined;
7
+ await index.globalScripts();
8
+ return index.bootstrapLazy([["ai-chat-container.cjs",[[769,"ai-chat-container",{"isOpen":[4,"is-open"],"position":[1],"width":[1],"autoScroll":[4,"auto-scroll"],"showWatermark":[4,"show-watermark"],"floatHeight":[1,"float-height"],"isMobile":[32]},null,{"position":[{"positionChanged":0}]}]]],["ai-message-input.cjs",[[513,"ai-message-input",{"placeholder":[1],"disabled":[4],"showVoiceButton":[4,"show-voice-button"],"inputValue":[32],"setInputValue":[64]}]]],["ai-voice-input.cjs",[[513,"ai-voice-input",{"disabled":[4],"showWaveform":[4,"show-waveform"],"autoStart":[4,"auto-start"],"state":[32],"error":[32],"recordingDuration":[32]}]]],["ai-card.cjs",[[769,"ai-card",{"noPadding":[4,"no-padding"],"noShadow":[4,"no-shadow"]}]]],["ai-chat-header.cjs",[[513,"ai-chat-header",{"mode":[1],"conversation":[1],"agentName":[1,"agent-name"],"agentStatus":[1,"agent-status"],"agentAvatar":[1,"agent-avatar"],"showBack":[4,"show-back"],"isDraggable":[4,"is-draggable"]}]]],["ai-chat-message.cjs",[[769,"ai-chat-message",{"role":[1],"content":[1],"format":[1],"agentName":[1,"agent-name"],"timestamp":[1],"showActions":[4,"show-actions"],"enableRegenerate":[4,"enable-regenerate"],"feedbackValue":[1025,"feedback-value"],"copySuccess":[32]}]]],["ai-link.cjs",[[769,"ai-link",{"label":[1],"href":[1],"target":[1],"rel":[1]}]]],["ai-loading.cjs",[[513,"ai-loading",{"mode":[1],"statusText":[1,"status-text"],"steps":[1],"headerTitle":[1,"header-title"],"expanded":[1028],"collapsible":[4],"_expanded":[32]}]]],["ai-rating.cjs",[[513,"ai-rating",{"question":[1],"subtitle":[1],"value":[1026],"disabled":[4],"hovered":[32]}]]],["ai-suggestion.cjs",[[769,"ai-suggestion",{"label":[1],"disabled":[4]}]]],["ai-icon.cjs",[[513,"ai-icon",{"name":[1],"size":[2]}]]]], options);
9
+ };
10
+
11
+ exports.setNonce = index.setNonce;
12
+ exports.defineCustomElements = defineCustomElements;
@@ -0,0 +1,24 @@
1
+ 'use strict';
2
+
3
+ var index = require('./index-DLJcLHFH.js');
4
+
5
+ var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
6
+ /*
7
+ Stencil Client Patch Browser v4.43.2 | MIT Licensed | https://stenciljs.com
8
+ */
9
+
10
+ var patchBrowser = () => {
11
+ const importMeta = (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('ui-ai-kit.cjs.js', document.baseURI).href));
12
+ const opts = {};
13
+ if (importMeta !== "") {
14
+ opts.resourcesUrl = new URL(".", importMeta).href;
15
+ }
16
+ return index.promiseResolve(opts);
17
+ };
18
+
19
+ patchBrowser().then(async (options) => {
20
+ await index.globalScripts();
21
+ return index.bootstrapLazy([["ai-chat-container.cjs",[[769,"ai-chat-container",{"isOpen":[4,"is-open"],"position":[1],"width":[1],"autoScroll":[4,"auto-scroll"],"showWatermark":[4,"show-watermark"],"floatHeight":[1,"float-height"],"isMobile":[32]},null,{"position":[{"positionChanged":0}]}]]],["ai-message-input.cjs",[[513,"ai-message-input",{"placeholder":[1],"disabled":[4],"showVoiceButton":[4,"show-voice-button"],"inputValue":[32],"setInputValue":[64]}]]],["ai-voice-input.cjs",[[513,"ai-voice-input",{"disabled":[4],"showWaveform":[4,"show-waveform"],"autoStart":[4,"auto-start"],"state":[32],"error":[32],"recordingDuration":[32]}]]],["ai-card.cjs",[[769,"ai-card",{"noPadding":[4,"no-padding"],"noShadow":[4,"no-shadow"]}]]],["ai-chat-header.cjs",[[513,"ai-chat-header",{"mode":[1],"conversation":[1],"agentName":[1,"agent-name"],"agentStatus":[1,"agent-status"],"agentAvatar":[1,"agent-avatar"],"showBack":[4,"show-back"],"isDraggable":[4,"is-draggable"]}]]],["ai-chat-message.cjs",[[769,"ai-chat-message",{"role":[1],"content":[1],"format":[1],"agentName":[1,"agent-name"],"timestamp":[1],"showActions":[4,"show-actions"],"enableRegenerate":[4,"enable-regenerate"],"feedbackValue":[1025,"feedback-value"],"copySuccess":[32]}]]],["ai-link.cjs",[[769,"ai-link",{"label":[1],"href":[1],"target":[1],"rel":[1]}]]],["ai-loading.cjs",[[513,"ai-loading",{"mode":[1],"statusText":[1,"status-text"],"steps":[1],"headerTitle":[1,"header-title"],"expanded":[1028],"collapsible":[4],"_expanded":[32]}]]],["ai-rating.cjs",[[513,"ai-rating",{"question":[1],"subtitle":[1],"value":[1026],"disabled":[4],"hovered":[32]}]]],["ai-suggestion.cjs",[[769,"ai-suggestion",{"label":[1],"disabled":[4]}]]],["ai-icon.cjs",[[513,"ai-icon",{"name":[1],"size":[2]}]]]], options);
22
+ });
23
+
24
+ exports.setNonce = index.setNonce;
@@ -0,0 +1,23 @@
1
+ {
2
+ "entries": [
3
+ "components/ai-loading/ai-loading.js",
4
+ "components/ai-rating/ai-rating.js",
5
+ "components/ai-card/ai-card.js",
6
+ "components/ai-chat-container/ai-chat-container.js",
7
+ "components/ai-chat-header/ai-chat-header.js",
8
+ "components/ai-chat-message/ai-chat-message.js",
9
+ "components/ai-icon/ai-icon.js",
10
+ "components/ai-link/ai-link.js",
11
+ "components/ai-message-input/ai-message-input.js",
12
+ "components/ai-suggestion/ai-suggestion.js",
13
+ "components/ai-voice-input/ai-voice-input.js"
14
+ ],
15
+ "mixins": [],
16
+ "compiler": {
17
+ "name": "@stencil/core",
18
+ "version": "4.43.2",
19
+ "typescriptVersion": "5.8.3"
20
+ },
21
+ "collections": [],
22
+ "bundles": []
23
+ }
@@ -0,0 +1,40 @@
1
+ /* ─── Custom Properties ──────────────────────────────────────────────────── */
2
+ :host {
3
+ --ai-card-bg: var(--ai-bg-card, #ffffff);
4
+ --ai-card-border: 1px solid var(--ai-border-default, #eeeeee);
5
+ --ai-card-radius: 16px;
6
+ --ai-card-padding: 16px;
7
+ --ai-card-gap: 12px;
8
+ --ai-card-shadow: 0px 1px 2px 0px rgba(18, 18, 23, 0.05);
9
+ --ai-text-color: var(--ai-text-primary, #333333);
10
+ display: block;
11
+ direction: rtl;
12
+ }
13
+
14
+ /* ─── Card Shell ─────────────────────────────────────────────────────────── */
15
+ .card {
16
+ background: var(--ai-card-bg);
17
+ border: var(--ai-card-border);
18
+ border-radius: var(--ai-card-radius);
19
+ padding: var(--ai-card-padding);
20
+ box-shadow: var(--ai-card-shadow);
21
+ box-sizing: border-box;
22
+ overflow: hidden;
23
+ color: var(--ai-text-color);
24
+ width: 100%;
25
+ /* Inner layout — flex column so slotted children stack with consistent gap */
26
+ display: flex;
27
+ flex-direction: column;
28
+ gap: var(--ai-card-gap);
29
+ text-align: right;
30
+ font-size: 14px;
31
+ line-height: 20px;
32
+ }
33
+
34
+ .card--no-padding {
35
+ padding: 0;
36
+ }
37
+
38
+ .card--no-shadow {
39
+ box-shadow: none;
40
+ }
@@ -0,0 +1,70 @@
1
+ import { Host, h } from "@stencil/core";
2
+ export class AiCard {
3
+ /** Remove the default padding */
4
+ noPadding = false;
5
+ /** Remove the shadow */
6
+ noShadow = false;
7
+ render() {
8
+ return (h(Host, { key: '4805b02b4eee8e01d0233de788a58770a85db2aa' }, h("div", { key: '75576f8a791fc49c3a750d491b0e835d0e5ce8cb', class: {
9
+ card: true,
10
+ 'card--no-padding': this.noPadding,
11
+ 'card--no-shadow': this.noShadow,
12
+ } }, h("slot", { key: 'e16cdb10e803451fdd47006a98656168fe2495f4' }))));
13
+ }
14
+ static get is() { return "ai-card"; }
15
+ static get encapsulation() { return "shadow"; }
16
+ static get originalStyleUrls() {
17
+ return {
18
+ "$": ["ai-card.css"]
19
+ };
20
+ }
21
+ static get styleUrls() {
22
+ return {
23
+ "$": ["ai-card.css"]
24
+ };
25
+ }
26
+ static get properties() {
27
+ return {
28
+ "noPadding": {
29
+ "type": "boolean",
30
+ "mutable": false,
31
+ "complexType": {
32
+ "original": "boolean",
33
+ "resolved": "boolean",
34
+ "references": {}
35
+ },
36
+ "required": false,
37
+ "optional": false,
38
+ "docs": {
39
+ "tags": [],
40
+ "text": "Remove the default padding"
41
+ },
42
+ "getter": false,
43
+ "setter": false,
44
+ "reflect": false,
45
+ "attribute": "no-padding",
46
+ "defaultValue": "false"
47
+ },
48
+ "noShadow": {
49
+ "type": "boolean",
50
+ "mutable": false,
51
+ "complexType": {
52
+ "original": "boolean",
53
+ "resolved": "boolean",
54
+ "references": {}
55
+ },
56
+ "required": false,
57
+ "optional": false,
58
+ "docs": {
59
+ "tags": [],
60
+ "text": "Remove the shadow"
61
+ },
62
+ "getter": false,
63
+ "setter": false,
64
+ "reflect": false,
65
+ "attribute": "no-shadow",
66
+ "defaultValue": "false"
67
+ }
68
+ };
69
+ }
70
+ }
@@ -0,0 +1,52 @@
1
+ import { html } from "lit";
2
+ const meta = {
3
+ title: 'UI/Card',
4
+ component: 'ai-card',
5
+ tags: ['autodocs'],
6
+ argTypes: {
7
+ noPadding: { control: 'boolean' },
8
+ noShadow: { control: 'boolean' },
9
+ },
10
+ };
11
+ export default meta;
12
+ const wrapStyle = 'padding: 24px; background: #f3f4f6; direction: rtl; max-width: 420px;';
13
+ /* ─── AI Reply (matches Figma node 1422-47585) ───────────────────────────── */
14
+ export const AiReply = {
15
+ render: () => html `
16
+ <div style="${wrapStyle}">
17
+ <ai-card>
18
+ <p style="margin:0; font-size:14px; font-weight:500; color:#333; line-height:20px;">
19
+ أهلاً بك في ذكاء سلة الاصطناعي!
20
+ </p>
21
+ <p style="margin:0; font-size:14px; color:#737373; line-height:20px;">
22
+ أنا هنا لمساعدتك في إنشاء شرائح عملاء قوية لحملاتك التسويقية باستخدام لغة بسيطة وتفاعلية.
23
+ </p>
24
+ <p style="margin:0; font-size:14px; color:#737373; line-height:20px;">
25
+ يمكنك أن تطلب مني العثور على العملاء بناءً على تاريخ مشترياتهم، مثل "أظهر لي كل من اشترى الشهر الماضي." ما نوع الجمهور الذي ترغب في بنائه اليوم؟
26
+ </p>
27
+ </ai-card>
28
+ </div>
29
+ `,
30
+ };
31
+ /* ─── With Rating (Figma node 1532-65078) ────────────────────────────────── */
32
+ export const WithRating = {
33
+ render: () => html `
34
+ <div style="${wrapStyle}">
35
+ <ai-card>
36
+ <ai-rating></ai-rating>
37
+ </ai-card>
38
+ </div>
39
+ `,
40
+ };
41
+ /* ─── No Padding ─────────────────────────────────────────────────────────── */
42
+ export const NoPadding = {
43
+ render: () => html `
44
+ <div style="${wrapStyle}">
45
+ <ai-card no-padding>
46
+ <div style="padding:16px; background:#f4f4f4; color:#333; font-size:14px;">
47
+ محتوى بدون padding من البطاقة
48
+ </div>
49
+ </ai-card>
50
+ </div>
51
+ `,
52
+ };
@@ -0,0 +1,137 @@
1
+ :host {
2
+ display: contents;
3
+ }
4
+
5
+ /* ── Base ─────────────────────────────────────────────────────────────────── */
6
+
7
+ .chat-container {
8
+ font-family: var(--ai-font-family, 'PingARLT', sans-serif);
9
+ display: flex;
10
+ flex-direction: column;
11
+ overflow: hidden;
12
+ position: relative;
13
+ background-color: var(--ai-container-bg, var(--ai-bg-card, white));
14
+ border: 1px solid var(--border-default, var(--ai-border-default, #eee));
15
+ z-index: 50;
16
+ box-sizing: border-box;
17
+ }
18
+
19
+ /* ── Messages scroll area ────────────────────────────────────────────────── */
20
+
21
+ .messages-area {
22
+ flex: 1;
23
+ overflow-y: auto;
24
+ min-height: 0;
25
+ scrollbar-width: thin;
26
+ scrollbar-color: var(--ai-scrollbar-thumb, rgba(0, 0, 0, 0.15)) transparent;
27
+ }
28
+
29
+ .messages-area::-webkit-scrollbar {
30
+ width: 3px;
31
+ }
32
+
33
+ .messages-area::-webkit-scrollbar-track {
34
+ background: transparent;
35
+ }
36
+
37
+ .messages-area::-webkit-scrollbar-thumb {
38
+ background: var(--ai-scrollbar-thumb, rgba(0, 0, 0, 0.15));
39
+ border-radius: 99px;
40
+ }
41
+
42
+ .messages-area::-webkit-scrollbar-thumb:hover {
43
+ background: var(--ai-scrollbar-thumb, rgba(0, 0, 0, 0.28));
44
+ }
45
+
46
+ /* ── Sticky modes (left / right) ─────────────────────────────────────────── */
47
+
48
+ .chat-container.left,
49
+ .chat-container.right {
50
+ position: fixed;
51
+ top: 0;
52
+ bottom: 0;
53
+ transition: transform 300ms cubic-bezier(0.4, 0, 0.2, 1);
54
+ }
55
+
56
+ .chat-container.left {
57
+ left: 0;
58
+ transform: translateX(-100%);
59
+ }
60
+
61
+ .chat-container.right {
62
+ right: 0;
63
+ transform: translateX(100%);
64
+ }
65
+
66
+ .chat-container.left.open,
67
+ .chat-container.right.open {
68
+ transform: translateX(0);
69
+ }
70
+
71
+ /* ── Float mode ──────────────────────────────────────────────────────────── */
72
+
73
+ .chat-container.float {
74
+ position: fixed;
75
+ top: 24px;
76
+ left: 24px;
77
+ border-radius: 16px;
78
+ box-shadow:
79
+ 0 8px 32px rgba(0, 0, 0, 0.12),
80
+ 0 2px 8px rgba(0, 0, 0, 0.08);
81
+ display: none;
82
+ }
83
+
84
+ .chat-container.float.open {
85
+ display: flex;
86
+ }
87
+
88
+ /* ── Watermark (empty / idle state) ──────────────────────────────────────── */
89
+
90
+ .watermark {
91
+ position: absolute;
92
+ top: 50%;
93
+ left: 50%;
94
+ transform: translate(-50%, -50%);
95
+ pointer-events: none;
96
+ }
97
+
98
+ .watermark ai-icon {
99
+ opacity: 0.8;
100
+ filter: drop-shadow(0 4px 6px rgba(0, 0, 0, 0.05));
101
+ }
102
+
103
+ /* ── Mobile ──────────────────────────────────────────────────────────────── */
104
+
105
+ .chat-container.mobile {
106
+ width: 100% !important;
107
+ }
108
+
109
+ .chat-container.float.mobile {
110
+ left: 0 !important;
111
+ right: 0 !important;
112
+ top: 0 !important;
113
+ bottom: 0 !important;
114
+ height: 100% !important;
115
+ border-radius: 0 !important;
116
+ }
117
+
118
+ @media (max-width: 767px) {
119
+ .chat-container {
120
+ width: 100% !important;
121
+ }
122
+
123
+ .chat-container.float {
124
+ left: 0 !important;
125
+ right: 0 !important;
126
+ top: 0 !important;
127
+ bottom: 0 !important;
128
+ height: 100% !important;
129
+ border-radius: 0 !important;
130
+ }
131
+ }
132
+
133
+ /* ── Dark mode watermark tweak ───────────────────────────────────────────── */
134
+
135
+ :host(.dark) .watermark ai-icon {
136
+ opacity: 0.6;
137
+ }
@@ -0,0 +1,270 @@
1
+ import { h, Host } from "@stencil/core";
2
+ export class ChatContainer {
3
+ el;
4
+ /** Controls visibility of the chat panel */
5
+ isOpen = false;
6
+ /** Position of the panel: 'left', 'right', or 'float' */
7
+ position = 'right';
8
+ /** Width of the panel (CSS value, e.g., '400px', '30%', '28rem') */
9
+ width = '28rem';
10
+ /** Enable/disable auto-scroll to latest message */
11
+ autoScroll = true;
12
+ /** Show AI watermark in the top half of the container */
13
+ showWatermark = false;
14
+ /** Height of the panel when position='float' */
15
+ floatHeight = '600px';
16
+ isMobile = false;
17
+ containerRef;
18
+ dragState = null;
19
+ resizeObserver;
20
+ componentWillLoad() {
21
+ this.checkMobile();
22
+ }
23
+ componentDidLoad() {
24
+ if (typeof window !== 'undefined') {
25
+ this.resizeObserver = new ResizeObserver(() => {
26
+ this.checkMobile();
27
+ });
28
+ this.resizeObserver.observe(document.body);
29
+ if (this.position === 'float') {
30
+ this.setupDrag();
31
+ }
32
+ }
33
+ }
34
+ positionChanged(newVal) {
35
+ if (newVal === 'float') {
36
+ this.setupDrag();
37
+ }
38
+ }
39
+ disconnectedCallback() {
40
+ if (this.resizeObserver) {
41
+ this.resizeObserver.disconnect();
42
+ }
43
+ }
44
+ checkMobile() {
45
+ if (typeof window !== 'undefined') {
46
+ this.isMobile = window.innerWidth < 768;
47
+ }
48
+ }
49
+ setupDrag() {
50
+ const container = this.containerRef;
51
+ if (!container)
52
+ return;
53
+ // Listen on the host element so composed events from ai-chat-header's shadow DOM
54
+ // are received. (composedPath() hides cross-shadow-root elements from shadow listeners.)
55
+ this.el.addEventListener('headerDragStart', (e) => {
56
+ const { clientX, clientY } = e.detail;
57
+ const rect = container.getBoundingClientRect();
58
+ this.dragState = {
59
+ startX: clientX,
60
+ startY: clientY,
61
+ initLeft: rect.left,
62
+ initTop: rect.top,
63
+ };
64
+ // Switch from bottom/right anchoring to top/left so we can move freely
65
+ container.style.right = 'auto';
66
+ container.style.bottom = 'auto';
67
+ container.style.left = `${rect.left}px`;
68
+ container.style.top = `${rect.top}px`;
69
+ const onMove = (me) => {
70
+ if (!this.dragState)
71
+ return;
72
+ const dx = me.clientX - this.dragState.startX;
73
+ const dy = me.clientY - this.dragState.startY;
74
+ let newLeft = this.dragState.initLeft + dx;
75
+ let newTop = this.dragState.initTop + dy;
76
+ // Clamp to viewport edges
77
+ const vw = window.innerWidth;
78
+ const vh = window.innerHeight;
79
+ const w = container.offsetWidth;
80
+ const h = container.offsetHeight;
81
+ newLeft = Math.max(0, Math.min(newLeft, vw - w));
82
+ newTop = Math.max(0, Math.min(newTop, vh - h));
83
+ container.style.left = `${newLeft}px`;
84
+ container.style.top = `${newTop}px`;
85
+ };
86
+ const onUp = () => {
87
+ this.dragState = null;
88
+ document.removeEventListener('pointermove', onMove);
89
+ document.removeEventListener('pointerup', onUp);
90
+ };
91
+ document.addEventListener('pointermove', onMove);
92
+ document.addEventListener('pointerup', onUp);
93
+ });
94
+ }
95
+ getContainerClasses() {
96
+ const classes = ['chat-container', this.position];
97
+ if (this.isOpen) {
98
+ classes.push('open');
99
+ }
100
+ if (this.isMobile) {
101
+ classes.push('mobile');
102
+ }
103
+ return classes.join(' ');
104
+ }
105
+ getContainerStyle() {
106
+ const style = {};
107
+ if (this.isMobile) {
108
+ return style;
109
+ }
110
+ if (this.position === 'float') {
111
+ style.width = this.width;
112
+ style.height = this.floatHeight;
113
+ }
114
+ else {
115
+ style.width = this.width;
116
+ }
117
+ return style;
118
+ }
119
+ render() {
120
+ 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" }))));
121
+ }
122
+ static get is() { return "ai-chat-container"; }
123
+ static get encapsulation() { return "shadow"; }
124
+ static get originalStyleUrls() {
125
+ return {
126
+ "$": ["ai-chat-container.css"]
127
+ };
128
+ }
129
+ static get styleUrls() {
130
+ return {
131
+ "$": ["ai-chat-container.css"]
132
+ };
133
+ }
134
+ static get properties() {
135
+ return {
136
+ "isOpen": {
137
+ "type": "boolean",
138
+ "mutable": false,
139
+ "complexType": {
140
+ "original": "boolean",
141
+ "resolved": "boolean",
142
+ "references": {}
143
+ },
144
+ "required": false,
145
+ "optional": false,
146
+ "docs": {
147
+ "tags": [],
148
+ "text": "Controls visibility of the chat panel"
149
+ },
150
+ "getter": false,
151
+ "setter": false,
152
+ "reflect": false,
153
+ "attribute": "is-open",
154
+ "defaultValue": "false"
155
+ },
156
+ "position": {
157
+ "type": "string",
158
+ "mutable": false,
159
+ "complexType": {
160
+ "original": "'left' | 'right' | 'float'",
161
+ "resolved": "\"float\" | \"left\" | \"right\"",
162
+ "references": {}
163
+ },
164
+ "required": false,
165
+ "optional": false,
166
+ "docs": {
167
+ "tags": [],
168
+ "text": "Position of the panel: 'left', 'right', or 'float'"
169
+ },
170
+ "getter": false,
171
+ "setter": false,
172
+ "reflect": false,
173
+ "attribute": "position",
174
+ "defaultValue": "'right'"
175
+ },
176
+ "width": {
177
+ "type": "string",
178
+ "mutable": false,
179
+ "complexType": {
180
+ "original": "string",
181
+ "resolved": "string",
182
+ "references": {}
183
+ },
184
+ "required": false,
185
+ "optional": false,
186
+ "docs": {
187
+ "tags": [],
188
+ "text": "Width of the panel (CSS value, e.g., '400px', '30%', '28rem')"
189
+ },
190
+ "getter": false,
191
+ "setter": false,
192
+ "reflect": false,
193
+ "attribute": "width",
194
+ "defaultValue": "'28rem'"
195
+ },
196
+ "autoScroll": {
197
+ "type": "boolean",
198
+ "mutable": false,
199
+ "complexType": {
200
+ "original": "boolean",
201
+ "resolved": "boolean",
202
+ "references": {}
203
+ },
204
+ "required": false,
205
+ "optional": false,
206
+ "docs": {
207
+ "tags": [],
208
+ "text": "Enable/disable auto-scroll to latest message"
209
+ },
210
+ "getter": false,
211
+ "setter": false,
212
+ "reflect": false,
213
+ "attribute": "auto-scroll",
214
+ "defaultValue": "true"
215
+ },
216
+ "showWatermark": {
217
+ "type": "boolean",
218
+ "mutable": false,
219
+ "complexType": {
220
+ "original": "boolean",
221
+ "resolved": "boolean",
222
+ "references": {}
223
+ },
224
+ "required": false,
225
+ "optional": false,
226
+ "docs": {
227
+ "tags": [],
228
+ "text": "Show AI watermark in the top half of the container"
229
+ },
230
+ "getter": false,
231
+ "setter": false,
232
+ "reflect": false,
233
+ "attribute": "show-watermark",
234
+ "defaultValue": "false"
235
+ },
236
+ "floatHeight": {
237
+ "type": "string",
238
+ "mutable": false,
239
+ "complexType": {
240
+ "original": "string",
241
+ "resolved": "string",
242
+ "references": {}
243
+ },
244
+ "required": false,
245
+ "optional": false,
246
+ "docs": {
247
+ "tags": [],
248
+ "text": "Height of the panel when position='float'"
249
+ },
250
+ "getter": false,
251
+ "setter": false,
252
+ "reflect": false,
253
+ "attribute": "float-height",
254
+ "defaultValue": "'600px'"
255
+ }
256
+ };
257
+ }
258
+ static get states() {
259
+ return {
260
+ "isMobile": {}
261
+ };
262
+ }
263
+ static get elementRef() { return "el"; }
264
+ static get watchers() {
265
+ return [{
266
+ "propName": "position",
267
+ "methodName": "positionChanged"
268
+ }];
269
+ }
270
+ }