nerdagent-chat-widget 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 (80) hide show
  1. package/README.md +257 -0
  2. package/dist/angular/index.d.ts +38 -0
  3. package/dist/angular/index.js +5 -0
  4. package/dist/angular/index.js.map +1 -0
  5. package/dist/angular/nerd-chat-widget.d.ts +11 -0
  6. package/dist/angular/nerd-chat-widget.js +289 -0
  7. package/dist/angular/nerd-chat-widget.js.map +1 -0
  8. package/dist/cjs/app-globals-V2Kpy_OQ.js +8 -0
  9. package/dist/cjs/app-globals-V2Kpy_OQ.js.map +1 -0
  10. package/dist/cjs/index-CURqjGGU.js +1471 -0
  11. package/dist/cjs/index-CURqjGGU.js.map +1 -0
  12. package/dist/cjs/index.cjs.js +235 -0
  13. package/dist/cjs/index.cjs.js.map +1 -0
  14. package/dist/cjs/loader.cjs.js +14 -0
  15. package/dist/cjs/loader.cjs.js.map +1 -0
  16. package/dist/cjs/nerd-chat-widget.cjs.entry.js +9 -0
  17. package/dist/cjs/nerd-chat-widget.entry.cjs.js.map +1 -0
  18. package/dist/cjs/nerdagent-chat-widget.cjs.js +26 -0
  19. package/dist/cjs/nerdagent-chat-widget.cjs.js.map +1 -0
  20. package/dist/collection/collection-manifest.json +12 -0
  21. package/dist/collection/components/chat-widget/chat-widget.js +808 -0
  22. package/dist/collection/components/chat-widget/chat-widget.js.map +1 -0
  23. package/dist/collection/components/chat-widget/chat-widget.scss +420 -0
  24. package/dist/collection/index.js +2 -0
  25. package/dist/collection/index.js.map +1 -0
  26. package/dist/collection/script.js +323 -0
  27. package/dist/components/index.d.ts +33 -0
  28. package/dist/components/index.js +1514 -0
  29. package/dist/components/index.js.map +1 -0
  30. package/dist/components/nerd-chat-widget.d.ts +11 -0
  31. package/dist/components/nerd-chat-widget.js +9 -0
  32. package/dist/components/nerd-chat-widget.js.map +1 -0
  33. package/dist/esm/app-globals-DQuL1Twl.js +6 -0
  34. package/dist/esm/app-globals-DQuL1Twl.js.map +1 -0
  35. package/dist/esm/index-Dlv_7oUh.js +1444 -0
  36. package/dist/esm/index-Dlv_7oUh.js.map +1 -0
  37. package/dist/esm/index.js +233 -0
  38. package/dist/esm/index.js.map +1 -0
  39. package/dist/esm/loader.js +12 -0
  40. package/dist/esm/loader.js.map +1 -0
  41. package/dist/esm/nerd-chat-widget.entry.js +3 -0
  42. package/dist/esm/nerd-chat-widget.entry.js.map +1 -0
  43. package/dist/esm/nerdagent-chat-widget.js +22 -0
  44. package/dist/esm/nerdagent-chat-widget.js.map +1 -0
  45. package/dist/index.cjs.js +1 -0
  46. package/dist/index.js +1 -0
  47. package/dist/nerdagent-chat-widget/index.esm.js +2 -0
  48. package/dist/nerdagent-chat-widget/index.esm.js.map +1 -0
  49. package/dist/nerdagent-chat-widget/loader.esm.js.map +1 -0
  50. package/dist/nerdagent-chat-widget/nerd-chat-widget.entry.esm.js.map +1 -0
  51. package/dist/nerdagent-chat-widget/nerdagent-chat-widget.esm.js +2 -0
  52. package/dist/nerdagent-chat-widget/nerdagent-chat-widget.esm.js.map +1 -0
  53. package/dist/nerdagent-chat-widget/p-395fe7e7.entry.js +2 -0
  54. package/dist/nerdagent-chat-widget/p-395fe7e7.entry.js.map +1 -0
  55. package/dist/nerdagent-chat-widget/p-DQuL1Twl.js +2 -0
  56. package/dist/nerdagent-chat-widget/p-DQuL1Twl.js.map +1 -0
  57. package/dist/nerdagent-chat-widget/p-Dlv_7oUh.js +3 -0
  58. package/dist/nerdagent-chat-widget/p-Dlv_7oUh.js.map +1 -0
  59. package/dist/react/index.d.ts +38 -0
  60. package/dist/react/index.js +5 -0
  61. package/dist/react/index.js.map +1 -0
  62. package/dist/react/nerd-chat-widget.d.ts +11 -0
  63. package/dist/react/nerd-chat-widget.js +289 -0
  64. package/dist/react/nerd-chat-widget.js.map +1 -0
  65. package/dist/types/components/chat-widget/chat-widget.d.ts +95 -0
  66. package/dist/types/components.d.ts +251 -0
  67. package/dist/types/index.d.ts +2 -0
  68. package/dist/types/stencil-public-runtime.d.ts +1730 -0
  69. package/dist/vue/index.d.ts +38 -0
  70. package/dist/vue/index.js +5 -0
  71. package/dist/vue/index.js.map +1 -0
  72. package/dist/vue/nerd-chat-widget.d.ts +11 -0
  73. package/dist/vue/nerd-chat-widget.js +289 -0
  74. package/dist/vue/nerd-chat-widget.js.map +1 -0
  75. package/loader/cdn.js +1 -0
  76. package/loader/index.cjs.js +1 -0
  77. package/loader/index.d.ts +24 -0
  78. package/loader/index.es2017.js +1 -0
  79. package/loader/index.js +2 -0
  80. package/package.json +76 -0
package/README.md ADDED
@@ -0,0 +1,257 @@
1
+ # NerdAgent Chat Widget 💬
2
+
3
+ A universal, customizable chat widget built with Stencil that works seamlessly across Angular, React, Vue, and vanilla JavaScript applications.
4
+
5
+ [![npm version](https://badge.fury.io/js/nerdagent-chat-widget.svg)](https://badge.fury.io/js/nerdagent-chat-widget)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
+
8
+ ## ✨ Features
9
+
10
+ - 🌐 **Universal**: Works with Angular, React, Vue, and vanilla JS
11
+ - 🎨 **Customizable**: Full theming and configuration options
12
+ - 📱 **Responsive**: Mobile-friendly design
13
+ - ⚡ **Lightweight**: Optimized bundle sizes
14
+ - 🔧 **TypeScript**: Full TypeScript support
15
+ - 🎯 **Framework-Specific**: Dedicated packages for each framework
16
+ - 🚀 **Modern**: Built with Web Components using Stencil
17
+
18
+ ## 🚀 Quick Start
19
+
20
+ ### Vanilla JavaScript / HTML
21
+
22
+ ```html
23
+ <script src="https://unpkg.com/nerdagent-chat-widget/dist/nerdagent-chat-widget/nerdagent-chat-widget.esm.js" type="module"></script>
24
+
25
+ <nerd-chat-widget
26
+ agent-name="Support Agent"
27
+ primary-color="#2d3e50"
28
+ accent-color="#4e8cff">
29
+ </nerd-chat-widget>
30
+ ```
31
+
32
+ ### Angular
33
+
34
+ ```bash
35
+ npm install @nerdagent/chat-widget-angular
36
+ ```
37
+
38
+ ```typescript
39
+ import { NerdChatWidgetModule } from '@nerdagent/chat-widget-angular';
40
+
41
+ @NgModule({
42
+ imports: [NerdChatWidgetModule],
43
+ })
44
+ export class AppModule {}
45
+ ```
46
+
47
+ ```html
48
+ <nerd-chat-widget
49
+ agentName="Support Agent"
50
+ primaryColor="#2d3e50"
51
+ (messageSent)="onMessageSent($event)">
52
+ </nerd-chat-widget>
53
+ ```
54
+
55
+ ### React
56
+
57
+ ```bash
58
+ npm install @nerdagent/chat-widget-react
59
+ ```
60
+
61
+ ```jsx
62
+ import { NerdChatWidget } from '@nerdagent/chat-widget-react';
63
+
64
+ function App() {
65
+ return (
66
+ <NerdChatWidget
67
+ agentName="Support Agent"
68
+ primaryColor="#2d3e50"
69
+ onMessageSent={(event) => console.log(event)}
70
+ />
71
+ );
72
+ }
73
+ ```
74
+
75
+ ### Vue
76
+
77
+ ```bash
78
+ npm install @nerdagent/chat-widget-vue
79
+ ```
80
+
81
+ ```vue
82
+ <template>
83
+ <NerdChatWidget
84
+ agent-name="Support Agent"
85
+ primary-color="#2d3e50"
86
+ @messageSent="onMessageSent"
87
+ />
88
+ </template>
89
+
90
+ <script setup>
91
+ import { NerdChatWidget } from '@nerdagent/chat-widget-vue';
92
+ </script>
93
+ ```
94
+
95
+ ## 📦 Packages
96
+
97
+ | Package | Description | Size |
98
+ |---------|-------------|------|
99
+ | [`nerdagent-chat-widget`](https://www.npmjs.com/package/nerdagent-chat-widget) | Core Stencil component | ~50KB |
100
+ | [`@nerdagent/chat-widget-angular`](https://www.npmjs.com/package/@nerdagent/chat-widget-angular) | Angular wrapper | ~5KB |
101
+ | [`@nerdagent/chat-widget-react`](https://www.npmjs.com/package/@nerdagent/chat-widget-react) | React wrapper | ~3KB |
102
+ | [`@nerdagent/chat-widget-vue`](https://www.npmjs.com/package/@nerdagent/chat-widget-vue) | Vue wrapper | ~4KB |
103
+
104
+ ## 🎨 Configuration
105
+
106
+ ### Props
107
+
108
+ | Property | Type | Default | Description |
109
+ |----------|------|---------|-------------|
110
+ | `agentName` | `string` | `'Support Agent'` | Name of the chat agent |
111
+ | `agentRole` | `string` | `'Customer Support'` | Role/title of the agent |
112
+ | `primaryColor` | `string` | `'#2d3e50'` | Primary theme color |
113
+ | `accentColor` | `string` | `'#4e8cff'` | Accent color for buttons |
114
+ | `welcomeMessage` | `string` | `'Hi! How can I help?'` | Initial message from agent |
115
+ | `placeholderText` | `string` | `'Type your message...'` | Input placeholder text |
116
+ | `position` | `WidgetPosition` | `'bottom-right'` | Widget position on screen |
117
+ | `width` | `string` | `'350'` | Widget width in pixels |
118
+ | `height` | `string` | `'500'` | Widget height in pixels |
119
+ | `showMinimizeButton` | `boolean` | `true` | Show/hide minimize button |
120
+ | `showTimestamps` | `boolean` | `true` | Show/hide message timestamps |
121
+ | `enableFileUpload` | `boolean` | `false` | Enable file upload feature |
122
+ | `enableSpeech` | `boolean` | `false` | Enable speech input |
123
+ | `showPoweredBy` | `boolean` | `true` | Show/hide "Powered by" footer |
124
+
125
+ ### Events
126
+
127
+ | Event | Payload | Description |
128
+ |-------|---------|-------------|
129
+ | `messageSent` | `{ message: string; timestamp: Date }` | Emitted when a message is sent |
130
+ | `widgetOpened` | `void` | Emitted when the widget is opened |
131
+ | `widgetClosed` | `void` | Emitted when the widget is closed |
132
+
133
+ ### Types
134
+
135
+ ```typescript
136
+ type WidgetPosition = 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left';
137
+ ```
138
+
139
+ ## 🛠️ Development
140
+
141
+ ### Prerequisites
142
+
143
+ - Node.js 16+
144
+ - npm or yarn
145
+
146
+ ### Setup
147
+
148
+ ```bash
149
+ # Clone the repository
150
+ git clone https://github.com/nerdagent/chat-widget.git
151
+ cd chat-widget
152
+
153
+ # Install dependencies
154
+ npm install
155
+
156
+ # Build the core component
157
+ npm run build
158
+
159
+ # Start development server
160
+ npm start
161
+ ```
162
+
163
+ ### Building Framework Packages
164
+
165
+ ```bash
166
+ # Build all packages
167
+ npm run build:packages
168
+
169
+ # Build individual packages
170
+ cd packages/angular && npm run build
171
+ cd packages/react && npm run build
172
+ cd packages/vue && npm run build
173
+ ```
174
+
175
+ ### Testing
176
+
177
+ ```bash
178
+ # Run tests
179
+ npm test
180
+
181
+ # Test with examples
182
+ cd examples/angular-chat-widget-test && npm start
183
+ cd examples/react-chat-widget-test && npm start
184
+ cd examples/vue-chat-widget-test && npm start
185
+ ```
186
+
187
+ ## 🏗️ Architecture
188
+
189
+ ```
190
+ ┌─────────────────────────────────────────────┐
191
+ │ Core Stencil │
192
+ │ (Web Component) │
193
+ ├─────────────────────────────────────────────┤
194
+ │ Angular │ React │ Vue │ JS │
195
+ │ Wrapper │ Wrapper │ Wrapper │ │
196
+ └─────────────────────────────────────────────┘
197
+ ```
198
+
199
+ The architecture consists of:
200
+
201
+ 1. **Core Stencil Component**: Universal Web Component
202
+ 2. **Framework Wrappers**: Native integrations for each framework
203
+ 3. **Build System**: Automated builds and publishing
204
+ 4. **Type Definitions**: Full TypeScript support
205
+
206
+ ## 📚 Examples
207
+
208
+ Check out the `examples/` directory for complete implementation examples:
209
+
210
+ - [Angular Example](./examples/angular-chat-widget-test/)
211
+ - [React Example](./examples/react-chat-widget-test/)
212
+ - [Vue Example](./examples/vue-chat-widget-test/)
213
+
214
+ ## 🤝 Contributing
215
+
216
+ 1. Fork the repository
217
+ 2. Create your feature branch (`git checkout -b feature/amazing-feature`)
218
+ 3. Commit your changes (`git commit -m 'Add amazing feature'`)
219
+ 4. Push to the branch (`git push origin feature/amazing-feature`)
220
+ 5. Open a Pull Request
221
+
222
+ ### Development Guidelines
223
+
224
+ - Follow TypeScript best practices
225
+ - Add tests for new features
226
+ - Update documentation
227
+ - Ensure all examples work
228
+ - Test across all supported frameworks
229
+
230
+ ## 📄 License
231
+
232
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
233
+
234
+ ## 🆘 Support
235
+
236
+ - 📧 **Email**: support@nerdagent.ai
237
+ - 🐛 **Issues**: [GitHub Issues](https://github.com/nerdagent/chat-widget/issues)
238
+ - 💬 **Discussions**: [GitHub Discussions](https://github.com/nerdagent/chat-widget/discussions)
239
+ - 📖 **Documentation**: [Full Documentation](https://docs.nerdagent.ai/chat-widget)
240
+
241
+ ## 🗺️ Roadmap
242
+
243
+ - [ ] **v1.1**: Voice messaging support
244
+ - [ ] **v1.2**: File upload functionality
245
+ - [ ] **v1.3**: Multi-language support
246
+ - [ ] **v1.4**: Custom themes marketplace
247
+ - [ ] **v2.0**: Real-time backend integration
248
+
249
+ ## ⭐ Show Your Support
250
+
251
+ Give a ⭐️ if this project helped you!
252
+
253
+ ---
254
+
255
+ <p align="center">
256
+ Made with ❤️ by the <a href="https://nerdagent.ai">NerdAgent</a> team
257
+ </p>
@@ -0,0 +1,38 @@
1
+ /* NerdagentChatWidget custom elements */
2
+ export { ChatWidget as NerdChatWidget } from '../types/components/chat-widget/chat-widget';
3
+ export { defineCustomElement as defineCustomElementNerdChatWidget } from './nerd-chat-widget';
4
+
5
+ /**
6
+ * Get the base path to where the assets can be found. Use "setAssetPath(path)"
7
+ * if the path needs to be customized.
8
+ */
9
+ export declare const getAssetPath: (path: string) => string;
10
+
11
+ /**
12
+ * Used to manually set the base path where assets can be found.
13
+ * If the script is used as "module", it's recommended to use "import.meta.url",
14
+ * such as "setAssetPath(import.meta.url)". Other options include
15
+ * "setAssetPath(document.currentScript.src)", or using a bundler's replace plugin to
16
+ * dynamically set the path at build time, such as "setAssetPath(process.env.ASSET_PATH)".
17
+ * But do note that this configuration depends on how your script is bundled, or lack of
18
+ * bundling, and where your assets can be loaded from. Additionally custom bundling
19
+ * will have to ensure the static assets are copied to its build directory.
20
+ */
21
+ export declare const setAssetPath: (path: string) => void;
22
+
23
+ /**
24
+ * Used to specify a nonce value that corresponds with an application's CSP.
25
+ * When set, the nonce will be added to all dynamically created script and style tags at runtime.
26
+ * Alternatively, the nonce value can be set on a meta tag in the DOM head
27
+ * (<meta name="csp-nonce" content="{ nonce value here }" />) which
28
+ * will result in the same behavior.
29
+ */
30
+ export declare const setNonce: (nonce: string) => void
31
+
32
+ export interface SetPlatformOptions {
33
+ raf?: (c: FrameRequestCallback) => number;
34
+ ael?: (el: EventTarget, eventName: string, listener: EventListenerOrEventListenerObject, options: boolean | AddEventListenerOptions) => void;
35
+ rel?: (el: EventTarget, eventName: string, listener: EventListenerOrEventListenerObject, options: boolean | AddEventListenerOptions) => void;
36
+ }
37
+ export declare const setPlatformOptions: (opts: SetPlatformOptions) => void;
38
+ export * from '../types';
@@ -0,0 +1,5 @@
1
+ export { getAssetPath, render, setAssetPath, setNonce, setPlatformOptions } from '@stencil/core/internal/client';
2
+ export { C as ChatWidget, NerdChatWidget, d as defineCustomElement, defineCustomElement as defineCustomElementNerdChatWidget } from './nerd-chat-widget.js';
3
+ //# sourceMappingURL=index.js.map
4
+
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"file":"index.js","mappings":";","names":[],"sources":[],"sourcesContent":[],"version":3}
@@ -0,0 +1,11 @@
1
+ import type { Components, JSX } from "../types/components";
2
+
3
+ interface NerdChatWidget extends Components.NerdChatWidget, HTMLElement {}
4
+ export const NerdChatWidget: {
5
+ prototype: NerdChatWidget;
6
+ new (): NerdChatWidget;
7
+ };
8
+ /**
9
+ * Used to define this component and all nested components recursively.
10
+ */
11
+ export const defineCustomElement: () => void;
@@ -0,0 +1,289 @@
1
+ import { proxyCustomElement, HTMLElement, createEvent, h, Host } from '@stencil/core/internal/client';
2
+
3
+ const chatWidgetScss = ":host {\n --primary-color: #2d3e50;\n --accent-color: #4e8cff;\n --widget-width: 350px;\n --widget-height: 500px;\n --font-family: 'Segoe UI', Arial, sans-serif;\n \n position: fixed;\n z-index: 10000;\n font-family: var(--font-family);\n}\n\n.chat-widget {\n position: fixed !important;\n width: var(--widget-width);\n height: var(--widget-height);\n background: white;\n border-radius: 16px;\n box-shadow: 0 8px 32px rgba(0, 0, 0, 0.15);\n overflow: hidden;\n transition: all 0.3s ease;\n display: flex;\n flex-direction: column;\n\n &.position-bottom-right {\n bottom: 20px !important;\n right: 20px !important;\n top: auto !important;\n left: auto !important;\n }\n\n &.position-bottom-left {\n bottom: 20px !important;\n left: 20px !important;\n top: auto !important;\n right: auto !important;\n }\n\n &.position-top-right {\n top: 20px !important;\n right: 20px !important;\n bottom: auto !important;\n left: auto !important;\n }\n\n &.position-top-left {\n top: 20px !important;\n left: 20px !important;\n bottom: auto !important;\n right: auto !important;\n }\n\n &.minimized {\n width: 60px !important;\n height: 60px !important;\n border-radius: 50% !important;\n cursor: pointer;\n\n .chat-header,\n .messages-container,\n .input-container,\n .tabs,\n .powered-by {\n display: none;\n }\n\n .minimize-icon {\n display: flex !important;\n }\n }\n\n &.hidden {\n display: none !important;\n }\n}\n\n.chat-header {\n background: var(--primary-color);\n color: white;\n padding: 16px;\n display: flex;\n align-items: center;\n justify-content: space-between;\n flex-shrink: 0;\n\n .agent-info {\n display: flex;\n align-items: center;\n gap: 12px;\n\n .agent-avatar {\n width: 44px;\n height: 44px;\n border-radius: 50%;\n border: 2px solid rgba(255, 255, 255, 0.3);\n object-fit: cover;\n }\n\n .agent-details {\n h4 {\n margin: 0;\n font-size: 1.1em;\n font-weight: 600;\n }\n\n p {\n margin: 0;\n font-size: 0.95em;\n opacity: 0.8;\n }\n }\n }\n\n .controls {\n display: flex;\n gap: 6px;\n\n .control-btn {\n background: rgba(0, 0, 0, 0.1);\n border: none;\n color: #fff;\n width: 28px;\n height: 28px;\n border-radius: 50%;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 1.1em;\n transition: background 0.2s;\n\n &:hover {\n background: rgba(0, 0, 0, 0.2);\n }\n\n &.close-btn {\n &:hover {\n background: rgba(255, 0, 0, 0.3);\n }\n }\n }\n }\n}\n\n.messages-container {\n flex: 1;\n overflow-y: auto;\n padding: 18px 16px 12px 16px;\n background: #f7f7f7;\n display: flex;\n flex-direction: column;\n gap: 16px;\n\n .message {\n display: flex;\n align-items: flex-start;\n gap: 8px;\n\n &.user {\n flex-direction: row-reverse;\n }\n\n .message-avatar {\n width: 28px;\n height: 28px;\n border-radius: 50%;\n flex-shrink: 0;\n object-fit: cover;\n border: 1px solid #eee;\n }\n\n .message-content {\n max-width: 70%;\n\n .message-text {\n padding: 10px 14px;\n border-radius: 10px;\n font-size: 1em;\n line-height: 1.4;\n }\n\n .message-time {\n font-size: 11px;\n opacity: 0.6;\n margin-top: 4px;\n }\n }\n\n &.agent .message-content .message-text {\n background: #eafbe7;\n color: #222;\n border-radius: 10px 10px 10px 0;\n }\n\n &.user .message-content .message-text {\n background: #e6f4ff;\n color: #222;\n border-radius: 10px 10px 0 10px;\n }\n }\n\n .typing-indicator {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 16px;\n font-size: 12px;\n color: #666;\n font-style: italic;\n\n .typing-dots {\n display: flex;\n gap: 2px;\n\n .dot {\n width: 4px;\n height: 4px;\n border-radius: 50%;\n background: #666;\n animation: typing 1.4s infinite;\n\n &:nth-child(2) {\n animation-delay: 0.2s;\n }\n\n &:nth-child(3) {\n animation-delay: 0.4s;\n }\n }\n }\n }\n}\n\n.input-container {\n background: #fff;\n border-top: 1px solid #eee;\n padding: 10px 12px 8px 12px;\n display: flex;\n align-items: center;\n gap: 8px;\n flex-shrink: 0;\n\n .message-input {\n flex: 1;\n border: 1px solid #e0e0e0;\n border-radius: 20px;\n padding: 8px 14px;\n font-size: 1em;\n outline: none;\n background: #fafbfc;\n font-family: var(--font-family);\n\n &:focus {\n border-color: var(--accent-color);\n }\n }\n\n .send-btn {\n background: var(--primary-color);\n color: #fff;\n border: none;\n border-radius: 50%;\n width: 36px;\n height: 36px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 1.2em;\n box-shadow: 0 1px 4px rgba(0, 0, 0, 0.07);\n transition: opacity 0.2s;\n position: relative;\n\n &:hover {\n opacity: 0.9;\n }\n\n // Show fallback icons by default\n i {\n font-size: 1em;\n display: none;\n }\n\n .fallback-icon {\n font-size: 1em;\n display: block;\n }\n }\n\n .feature-btn {\n background: var(--primary-color);\n color: var(--accent-color);\n border: none;\n border-radius: 50%;\n width: 36px;\n height: 36px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 1.2em;\n position: relative;\n\n // Show fallback icons by default\n i {\n font-size: 1em;\n display: none;\n }\n\n .fallback-icon {\n font-size: 1em;\n display: block;\n }\n }\n}\n\n.tabs {\n background: #f8f8f8;\n border-top: 1.5px solid #e0e7ff;\n padding: 0;\n display: flex;\n align-items: center;\n justify-content: space-around;\n height: 48px;\n flex-shrink: 0;\n\n .tab {\n flex: 1;\n text-align: center;\n padding: 7px 0;\n color: var(--primary-color);\n font-weight: 600;\n cursor: pointer;\n transition: background 0.2s;\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 2px;\n\n &:hover {\n background: rgba(0, 0, 0, 0.05);\n }\n\n // Show fallback icons by default\n i {\n font-size: 1.1em;\n display: none;\n }\n\n .fallback-icon {\n font-size: 1.1em;\n display: block;\n }\n\n span:not(.fallback-icon) {\n font-size: 0.91em;\n }\n }\n}\n\n.powered-by {\n text-align: center;\n font-size: 0.95em;\n color: #aaa;\n padding: 7px 0 3px 0;\n background: #fff;\n border-top: 1px solid #f3f3f3;\n flex-shrink: 0;\n\n img {\n height: 18px;\n vertical-align: middle;\n margin-right: 6px;\n opacity: 0.85;\n object-fit: contain;\n }\n\n span {\n font-weight: 500;\n }\n}\n\n.minimize-icon {\n display: none;\n align-items: center;\n justify-content: center;\n width: 100%;\n height: 100%;\n font-size: 24px;\n color: white;\n background: var(--primary-color);\n border-radius: 50%;\n cursor: pointer;\n}\n\n@keyframes typing {\n 0%, 60%, 100% {\n transform: translateY(0);\n }\n 30% {\n transform: translateY(-10px);\n }\n}\n\n// Mobile responsiveness\n@media (max-width: 768px) {\n .chat-widget {\n width: 100% !important;\n height: 100% !important;\n top: 0 !important;\n left: 0 !important;\n right: 0 !important;\n bottom: 0 !important;\n border-radius: 0 !important;\n\n .messages-container {\n height: calc(100vh - 200px);\n }\n }\n}";
4
+
5
+ const ChatWidget = /*@__PURE__*/ proxyCustomElement(class ChatWidget extends HTMLElement {
6
+ constructor(registerHost) {
7
+ super();
8
+ if (registerHost !== false) {
9
+ this.__registerHost();
10
+ }
11
+ this.__attachShadow();
12
+ this.messageSent = createEvent(this, "messageSent", 7);
13
+ this.widgetOpened = createEvent(this, "widgetOpened", 7);
14
+ this.widgetClosed = createEvent(this, "widgetClosed", 7);
15
+ // Configuration props
16
+ this.config = {};
17
+ this.agentName = 'Support Agent';
18
+ this.agentRole = 'Customer Support';
19
+ this.agentAvatar = 'https://ui-avatars.com/api/?name=Agent&background=2d3e50&color=ffffff&size=44';
20
+ this.primaryColor = '#2d3e50';
21
+ this.accentColor = '#4e8cff';
22
+ this.welcomeMessage = 'Hi! How can I help you today?';
23
+ this.position = 'bottom-right';
24
+ this.showMinimizeButton = true;
25
+ this.enableFileUpload = false;
26
+ this.enableSpeech = false;
27
+ this.showTimestamps = true;
28
+ this.apiEndpoint = '';
29
+ this.apiKey = '';
30
+ this.placeholderText = 'Type your message...';
31
+ this.thankYouMessage = 'Thank you for chatting with us!';
32
+ this.showPoweredBy = true;
33
+ this.poweredByLogo = 'https://innovationincubator.com/wp-content/uploads/2023/05/Innovation-Incubator-logo.png';
34
+ this.poweredByText = 'Powered by';
35
+ this.poweredByBrand = 'NerdAgent';
36
+ this.poweredByColor = '#4e8cff';
37
+ this.width = 350;
38
+ this.height = 500;
39
+ this.fontFamily = 'Segoe UI, Arial, sans-serif';
40
+ // State
41
+ this.messages = [];
42
+ this.isMinimized = false;
43
+ this.isTyping = false;
44
+ this.inputValue = '';
45
+ this.isChatOpen = true;
46
+ this.currentPosition = 'bottom-right';
47
+ this.messageIdCounter = 0;
48
+ }
49
+ componentDidLoad() {
50
+ // Initialize position
51
+ this.currentPosition = this.position;
52
+ // Load Font Awesome if not already loaded
53
+ this.loadFontAwesome();
54
+ // Add welcome message
55
+ if (this.getConfig().welcomeMessage) {
56
+ setTimeout(() => {
57
+ this.addMessage(this.getConfig().welcomeMessage, false);
58
+ }, 500);
59
+ }
60
+ }
61
+ configChanged() {
62
+ // React to config changes - Stencil automatically re-renders when @Prop changes
63
+ // No need to manually trigger re-render
64
+ }
65
+ positionChanged() {
66
+ // Force re-render when position changes
67
+ console.log('Position changed to:', this.position);
68
+ this.currentPosition = this.position;
69
+ // Debug: Check what styles are applied
70
+ setTimeout(() => {
71
+ const widgetEl = this.el.shadowRoot.querySelector('.chat-widget');
72
+ if (widgetEl) {
73
+ console.log('Widget classes:', widgetEl.className);
74
+ console.log('Widget inline styles:', widgetEl.style.cssText);
75
+ console.log('Widget computed styles:', {
76
+ position: window.getComputedStyle(widgetEl).position,
77
+ top: window.getComputedStyle(widgetEl).top,
78
+ right: window.getComputedStyle(widgetEl).right,
79
+ bottom: window.getComputedStyle(widgetEl).bottom,
80
+ left: window.getComputedStyle(widgetEl).left
81
+ });
82
+ }
83
+ }, 100);
84
+ }
85
+ getConfig() {
86
+ return Object.assign({ agentName: this.agentName, agentRole: this.agentRole, agentAvatar: this.agentAvatar, primaryColor: this.primaryColor, accentColor: this.accentColor, welcomeMessage: this.welcomeMessage, position: this.position, showMinimizeButton: this.showMinimizeButton, enableFileUpload: this.enableFileUpload, enableSpeech: this.enableSpeech, showTimestamps: this.showTimestamps, apiEndpoint: this.apiEndpoint, apiKey: this.apiKey, placeholderText: this.placeholderText, thankYouMessage: this.thankYouMessage, showPoweredBy: this.showPoweredBy, poweredByLogo: this.poweredByLogo, poweredByText: this.poweredByText, poweredByBrand: this.poweredByBrand, poweredByColor: this.poweredByColor, width: this.width, height: this.height, fontFamily: this.fontFamily }, this.config);
87
+ }
88
+ loadFontAwesome() {
89
+ if (!document.getElementById('fa-cdn-stencil')) {
90
+ const link = document.createElement('link');
91
+ link.id = 'fa-cdn-stencil';
92
+ link.rel = 'stylesheet';
93
+ link.href = 'https://use.fontawesome.com/releases/v6.4.2/css/all.css';
94
+ link.crossOrigin = 'anonymous';
95
+ document.head.appendChild(link);
96
+ console.log('Loading FontAwesome...');
97
+ }
98
+ else {
99
+ console.log('FontAwesome already loaded');
100
+ }
101
+ }
102
+ addMessage(text, isUser = false) {
103
+ const message = {
104
+ id: `msg-${++this.messageIdCounter}`,
105
+ text,
106
+ isUser,
107
+ timestamp: new Date()
108
+ };
109
+ this.messages = [...this.messages, message];
110
+ }
111
+ async sendMessage() {
112
+ const text = this.inputValue.trim();
113
+ if (!text)
114
+ return;
115
+ this.addMessage(text, true);
116
+ this.inputValue = '';
117
+ // Emit event
118
+ this.messageSent.emit({ message: text, widget: this.el });
119
+ // Handle API or simulate response
120
+ const config = this.getConfig();
121
+ if (config.apiEndpoint) {
122
+ await this.sendToAPI(text);
123
+ }
124
+ else {
125
+ this.simulateResponse();
126
+ }
127
+ }
128
+ async sendToAPI(message) {
129
+ const config = this.getConfig();
130
+ this.isTyping = true;
131
+ try {
132
+ const response = await fetch(config.apiEndpoint, {
133
+ method: 'POST',
134
+ headers: Object.assign({ 'Content-Type': 'application/json' }, (config.apiKey && { 'Authorization': `Bearer ${config.apiKey}` })),
135
+ body: JSON.stringify({
136
+ message,
137
+ timestamp: new Date().toISOString(),
138
+ sessionId: this.getSessionId()
139
+ })
140
+ });
141
+ const data = await response.json();
142
+ this.isTyping = false;
143
+ if (data.response) {
144
+ this.addMessage(data.response, false);
145
+ }
146
+ }
147
+ catch (error) {
148
+ this.isTyping = false;
149
+ this.addMessage('Sorry, I encountered an error. Please try again.', false);
150
+ }
151
+ }
152
+ simulateResponse() {
153
+ const responses = [
154
+ "Thanks for your message! How can I help you further?",
155
+ "I understand. Let me assist you with that.",
156
+ "That's a great question! Let me help you.",
157
+ "I'm here to help! Could you provide more details?"
158
+ ];
159
+ this.isTyping = true;
160
+ setTimeout(() => {
161
+ this.isTyping = false;
162
+ const response = responses[Math.floor(Math.random() * responses.length)];
163
+ this.addMessage(response, false);
164
+ }, 1500);
165
+ }
166
+ toggleMinimize() {
167
+ this.isMinimized = !this.isMinimized;
168
+ if (this.isMinimized) {
169
+ this.widgetClosed.emit({ widget: this.el });
170
+ }
171
+ else {
172
+ this.widgetOpened.emit({ widget: this.el });
173
+ }
174
+ }
175
+ closeWidget() {
176
+ this.isChatOpen = false;
177
+ this.widgetClosed.emit({ widget: this.el });
178
+ }
179
+ openWidget() {
180
+ this.isChatOpen = true;
181
+ this.isMinimized = false;
182
+ this.widgetOpened.emit({ widget: this.el });
183
+ }
184
+ handleKeyPress(event) {
185
+ if (event.key === 'Enter') {
186
+ this.sendMessage();
187
+ }
188
+ }
189
+ handleInputChange(event) {
190
+ const target = event.target;
191
+ this.inputValue = target.value;
192
+ }
193
+ getSessionId() {
194
+ let sessionId = localStorage.getItem('nerd-chat-session');
195
+ if (!sessionId) {
196
+ sessionId = 'session-' + Math.random().toString(36).substr(2, 9);
197
+ localStorage.setItem('nerd-chat-session', sessionId);
198
+ }
199
+ return sessionId;
200
+ }
201
+ formatTime(date) {
202
+ return date.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
203
+ }
204
+ render() {
205
+ const config = this.getConfig();
206
+ console.log('Rendering with position:', this.currentPosition);
207
+ // Get position styles directly
208
+ const getPositionStyles = () => {
209
+ switch (this.currentPosition) {
210
+ case 'bottom-left':
211
+ return { bottom: '20px', left: '20px', top: 'auto', right: 'auto' };
212
+ case 'top-right':
213
+ return { top: '20px', right: '20px', bottom: 'auto', left: 'auto' };
214
+ case 'top-left':
215
+ return { top: '20px', left: '20px', bottom: 'auto', right: 'auto' };
216
+ case 'bottom-right':
217
+ default:
218
+ return { bottom: '20px', right: '20px', top: 'auto', left: 'auto' };
219
+ }
220
+ };
221
+ const widgetClasses = {
222
+ 'chat-widget': true,
223
+ 'minimized': this.isMinimized,
224
+ 'hidden': !this.isChatOpen
225
+ };
226
+ return (h(Host, null, h("div", { class: widgetClasses, style: Object.assign({ '--primary-color': config.primaryColor || '#2d3e50', '--accent-color': config.accentColor || '#4e8cff', '--widget-width': `${config.width || 350}px`, '--widget-height': `${config.height || 500}px`, '--font-family': config.fontFamily || 'Segoe UI, Arial, sans-serif' }, getPositionStyles()) }, h("div", { class: "chat-header" }, h("div", { class: "agent-info" }, h("img", { src: config.agentAvatar, alt: "Agent", class: "agent-avatar" }), h("div", { class: "agent-details" }, h("h4", null, config.agentName), h("p", null, config.agentRole))), h("div", { class: "controls" }, config.showMinimizeButton && (h("button", { class: "control-btn minimize-btn", onClick: () => this.toggleMinimize(), title: this.isMinimized ? 'Maximize' : 'Minimize' }, this.isMinimized ? '🔼' : '🔽')), h("button", { class: "control-btn close-btn", onClick: () => this.closeWidget(), title: "Close" }, "\u00D7"))), h("div", { class: "messages-container" }, this.messages.map(message => (h("div", { key: message.id, class: `message ${message.isUser ? 'user' : 'agent'}` }, h("img", { src: message.isUser ? 'https://ui-avatars.com/api/?name=User&background=4e8cff&color=ffffff&size=28' : config.agentAvatar, alt: message.isUser ? 'User' : 'Agent', class: "message-avatar" }), h("div", { class: "message-content" }, h("div", { class: "message-text" }, message.text), config.showTimestamps && (h("div", { class: "message-time" }, this.formatTime(message.timestamp))))))), this.isTyping && (h("div", { class: "typing-indicator" }, h("span", null, config.agentName, " is typing"), h("div", { class: "typing-dots" }, h("div", { class: "dot" }), h("div", { class: "dot" }), h("div", { class: "dot" }))))), h("div", { class: "input-container" }, h("input", { type: "text", class: "message-input", placeholder: config.placeholderText || 'Type your message...', value: this.inputValue, onInput: (e) => this.handleInputChange(e), onKeyPress: (e) => this.handleKeyPress(e) }), h("button", { class: "send-btn", onClick: () => this.sendMessage() }, h("i", { class: "fas fa-paper-plane" }), h("span", { class: "fallback-icon" }, "\u27A4")), config.enableFileUpload && (h("button", { class: "feature-btn file-upload" }, h("i", { class: "fas fa-paperclip" }), h("span", { class: "fallback-icon" }, "\uD83D\uDCCE"))), config.enableSpeech && (h("button", { class: "feature-btn speech" }, h("i", { class: "fas fa-microphone" }), h("span", { class: "fallback-icon" }, "\uD83C\uDFA4")))), h("div", { class: "tabs" }, h("div", { class: "tab active" }, h("i", { class: "fas fa-comment-dots" }), h("span", null, "Chat")), h("div", { class: "tab" }, h("i", { class: "fas fa-microphone" }), h("span", null, "Voice")), h("div", { class: "tab" }, h("i", { class: "fas fa-clock" }), h("span", null, "History"))), config.showPoweredBy && (h("div", { class: "powered-by" }, h("img", { src: config.poweredByLogo, alt: "Powered By Logo" }), config.poweredByText, " ", h("span", { style: { color: config.poweredByColor } }, config.poweredByBrand))), h("div", { class: "minimize-icon", onClick: () => this.isChatOpen ? this.toggleMinimize() : this.openWidget() }, "\uD83D\uDCAC"))));
227
+ }
228
+ get el() { return this; }
229
+ static get watchers() { return {
230
+ "config": ["configChanged"],
231
+ "position": ["positionChanged"]
232
+ }; }
233
+ static get style() { return chatWidgetScss; }
234
+ }, [257, "nerd-chat-widget", {
235
+ "config": [16],
236
+ "agentName": [1, "agent-name"],
237
+ "agentRole": [1, "agent-role"],
238
+ "agentAvatar": [1, "agent-avatar"],
239
+ "primaryColor": [1, "primary-color"],
240
+ "accentColor": [1, "accent-color"],
241
+ "welcomeMessage": [1, "welcome-message"],
242
+ "position": [1],
243
+ "showMinimizeButton": [4, "show-minimize-button"],
244
+ "enableFileUpload": [4, "enable-file-upload"],
245
+ "enableSpeech": [4, "enable-speech"],
246
+ "showTimestamps": [4, "show-timestamps"],
247
+ "apiEndpoint": [1, "api-endpoint"],
248
+ "apiKey": [1, "api-key"],
249
+ "placeholderText": [1, "placeholder-text"],
250
+ "thankYouMessage": [1, "thank-you-message"],
251
+ "showPoweredBy": [4, "show-powered-by"],
252
+ "poweredByLogo": [1, "powered-by-logo"],
253
+ "poweredByText": [1, "powered-by-text"],
254
+ "poweredByBrand": [1, "powered-by-brand"],
255
+ "poweredByColor": [1, "powered-by-color"],
256
+ "width": [2],
257
+ "height": [2],
258
+ "fontFamily": [1, "font-family"],
259
+ "messages": [32],
260
+ "isMinimized": [32],
261
+ "isTyping": [32],
262
+ "inputValue": [32],
263
+ "isChatOpen": [32],
264
+ "currentPosition": [32]
265
+ }, undefined, {
266
+ "config": ["configChanged"],
267
+ "position": ["positionChanged"]
268
+ }]);
269
+ function defineCustomElement$1() {
270
+ if (typeof customElements === "undefined") {
271
+ return;
272
+ }
273
+ const components = ["nerd-chat-widget"];
274
+ components.forEach(tagName => { switch (tagName) {
275
+ case "nerd-chat-widget":
276
+ if (!customElements.get(tagName)) {
277
+ customElements.define(tagName, ChatWidget);
278
+ }
279
+ break;
280
+ } });
281
+ }
282
+
283
+ const NerdChatWidget = ChatWidget;
284
+ const defineCustomElement = defineCustomElement$1;
285
+
286
+ export { ChatWidget as C, NerdChatWidget, defineCustomElement$1 as d, defineCustomElement };
287
+ //# sourceMappingURL=nerd-chat-widget.js.map
288
+
289
+ //# sourceMappingURL=nerd-chat-widget.js.map