@nexvio-ai/widget-js 0.1.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.
package/dist/index.cjs ADDED
@@ -0,0 +1,1284 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __typeError = (msg) => {
7
+ throw TypeError(msg);
8
+ };
9
+ var __export = (target, all) => {
10
+ for (var name in all)
11
+ __defProp(target, name, { get: all[name], enumerable: true });
12
+ };
13
+ var __copyProps = (to, from, except, desc) => {
14
+ if (from && typeof from === "object" || typeof from === "function") {
15
+ for (let key of __getOwnPropNames(from))
16
+ if (!__hasOwnProp.call(to, key) && key !== except)
17
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
18
+ }
19
+ return to;
20
+ };
21
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
22
+ var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
23
+ var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
24
+ var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
25
+ var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
26
+ var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
27
+
28
+ // src/index.ts
29
+ var src_exports = {};
30
+ __export(src_exports, {
31
+ NexvioChatbotElement: () => NexvioChatbotElement,
32
+ NexvioWidgetElement: () => NexvioWidgetElement,
33
+ registerNexvioChatbot: () => registerNexvioChatbot,
34
+ registerNexvioWidget: () => registerNexvioWidget
35
+ });
36
+ module.exports = __toCommonJS(src_exports);
37
+
38
+ // src/utils/debug.ts
39
+ function debugEnabled() {
40
+ try {
41
+ return typeof window !== "undefined" && window.__NEXVIO_WIDGET_DEBUG === true;
42
+ } catch {
43
+ return false;
44
+ }
45
+ }
46
+ function log(...args) {
47
+ if (debugEnabled()) console.log(...args);
48
+ }
49
+ function warn(...args) {
50
+ if (debugEnabled()) console.warn(...args);
51
+ }
52
+ function debug(...args) {
53
+ if (debugEnabled()) console.debug(...args);
54
+ }
55
+
56
+ // src/utils/EventEmitter.ts
57
+ var _listeners;
58
+ var EventEmitter = class {
59
+ constructor() {
60
+ __privateAdd(this, _listeners, /* @__PURE__ */ new Map());
61
+ }
62
+ on(event, listener) {
63
+ if (!__privateGet(this, _listeners).has(event)) {
64
+ __privateGet(this, _listeners).set(event, /* @__PURE__ */ new Set());
65
+ }
66
+ __privateGet(this, _listeners).get(event)?.add(listener);
67
+ }
68
+ once(event, listener) {
69
+ const onceListener = (payload) => {
70
+ this.off(event, onceListener);
71
+ listener(payload);
72
+ };
73
+ this.on(event, onceListener);
74
+ }
75
+ emit(event, payload) {
76
+ __privateGet(this, _listeners).get(event)?.forEach((listener) => listener(payload));
77
+ }
78
+ off(event, listener) {
79
+ if (!listener) {
80
+ __privateGet(this, _listeners).delete(event);
81
+ return;
82
+ }
83
+ __privateGet(this, _listeners).get(event)?.delete(listener);
84
+ }
85
+ clear() {
86
+ __privateGet(this, _listeners).clear();
87
+ }
88
+ };
89
+ _listeners = new WeakMap();
90
+
91
+ // src/utils/serializeError.ts
92
+ function serializeError(error) {
93
+ if (error instanceof Error) {
94
+ return {
95
+ name: error.name,
96
+ message: error.message,
97
+ stack: error.stack
98
+ };
99
+ }
100
+ if (typeof error === "object" && error !== null) {
101
+ const obj = error;
102
+ return {
103
+ name: typeof obj.name === "string" ? obj.name : "Error",
104
+ message: typeof obj.message === "string" ? obj.message : "Unknown error",
105
+ stack: typeof obj.stack === "string" ? obj.stack : void 0,
106
+ metadata: Object.fromEntries(Object.entries(obj).filter(([key]) => !["name", "message", "stack"].includes(key)))
107
+ };
108
+ }
109
+ return {
110
+ name: "Error",
111
+ message: String(error)
112
+ };
113
+ }
114
+ function deserializeError(serialized) {
115
+ const error = new Error(serialized.message);
116
+ error.name = serialized.name;
117
+ if (serialized.stack) {
118
+ error.stack = serialized.stack;
119
+ }
120
+ return error;
121
+ }
122
+
123
+ // src/messenger/BaseMessenger.ts
124
+ var MESSAGE_TOKEN = "__nexvioWidget";
125
+ var DEFAULT_COMMAND_CAPABILITY = () => true;
126
+ var _target, _targetOrigin, _handlers, _fetch, _events, _canReceiveCommand, _pending, _abortControllers, _BaseMessenger_instances, sendMessage_fn, sendCommand_fn, _handleMessage, isWidgetMessage_fn;
127
+ var BaseMessenger = class {
128
+ constructor(config) {
129
+ __privateAdd(this, _BaseMessenger_instances);
130
+ __privateAdd(this, _target);
131
+ __privateAdd(this, _targetOrigin);
132
+ __privateAdd(this, _handlers);
133
+ __privateAdd(this, _fetch);
134
+ __privateAdd(this, _events, new EventEmitter());
135
+ __privateAdd(this, _canReceiveCommand);
136
+ __privateAdd(this, _pending, /* @__PURE__ */ new Map());
137
+ __privateAdd(this, _abortControllers, /* @__PURE__ */ new Map());
138
+ this.commands = new Proxy(
139
+ {},
140
+ {
141
+ get: (_, command) => {
142
+ return (payload, transfer) => {
143
+ return __privateMethod(this, _BaseMessenger_instances, sendCommand_fn).call(this, command, payload, transfer);
144
+ };
145
+ }
146
+ }
147
+ );
148
+ __privateAdd(this, _handleMessage, async (event) => {
149
+ debug("[NexvioWidget][Messenger] window.message", {
150
+ origin: event.origin,
151
+ hasToken: !!(event.data && typeof event.data === "object" && event.data[MESSAGE_TOKEN] === true)
152
+ });
153
+ if (!__privateMethod(this, _BaseMessenger_instances, isWidgetMessage_fn).call(this, event)) {
154
+ return;
155
+ }
156
+ const data = event.data;
157
+ switch (data.type) {
158
+ case "event": {
159
+ log("[NexvioWidget][Messenger] <- event", { event: data.event, payload: data.payload });
160
+ __privateGet(this, _events).emit(data.event, data.payload);
161
+ break;
162
+ }
163
+ case "response": {
164
+ const handler = __privateGet(this, _pending).get(data.nonce);
165
+ if (!handler) {
166
+ warn("[NexvioWidget][Messenger] missing pending handler for response", data.nonce);
167
+ return;
168
+ }
169
+ __privateGet(this, _pending).delete(data.nonce);
170
+ if (data.error) {
171
+ handler.reject(deserializeError(data.error));
172
+ } else {
173
+ handler.resolve(data.payload);
174
+ }
175
+ break;
176
+ }
177
+ case "command": {
178
+ if (!__privateGet(this, _canReceiveCommand).call(this, data.command)) {
179
+ __privateMethod(this, _BaseMessenger_instances, sendMessage_fn).call(this, {
180
+ type: "response",
181
+ nonce: data.nonce,
182
+ error: serializeError(new Error(`Command "${data.command}" is not supported by the host`))
183
+ });
184
+ return;
185
+ }
186
+ const commandCapitalized = `on${data.command.charAt(0).toUpperCase()}${data.command.slice(1)}`;
187
+ const handler = __privateGet(this, _handlers)[commandCapitalized];
188
+ if (!handler) {
189
+ __privateMethod(this, _BaseMessenger_instances, sendMessage_fn).call(this, {
190
+ type: "response",
191
+ nonce: data.nonce,
192
+ error: serializeError(new Error(`Command handler "${data.command}" not implemented by host`))
193
+ });
194
+ return;
195
+ }
196
+ try {
197
+ log("[NexvioWidget][Messenger] <- command", { command: data.command, payload: data.payload });
198
+ const result = await handler(data.payload);
199
+ __privateMethod(this, _BaseMessenger_instances, sendMessage_fn).call(this, { type: "response", nonce: data.nonce, payload: result });
200
+ } catch (error) {
201
+ __privateMethod(this, _BaseMessenger_instances, sendMessage_fn).call(this, {
202
+ type: "response",
203
+ nonce: data.nonce,
204
+ error: serializeError(error)
205
+ });
206
+ }
207
+ break;
208
+ }
209
+ case "fetch": {
210
+ log("[NexvioWidget][Messenger] <- fetch", { url: data.url });
211
+ const controller = new AbortController();
212
+ __privateGet(this, _abortControllers).set(data.nonce, controller);
213
+ try {
214
+ const response = await __privateGet(this, _fetch).call(this, data.url, {
215
+ ...data.init,
216
+ signal: controller.signal
217
+ });
218
+ const contentType = response.headers.get("content-type") ?? "";
219
+ let payload;
220
+ if (contentType.includes("application/json")) {
221
+ payload = await response.json();
222
+ } else {
223
+ payload = await response.text();
224
+ }
225
+ __privateMethod(this, _BaseMessenger_instances, sendMessage_fn).call(this, {
226
+ type: "response",
227
+ nonce: data.nonce,
228
+ payload: {
229
+ ok: response.ok,
230
+ status: response.status,
231
+ statusText: response.statusText,
232
+ headers: Object.fromEntries(response.headers.entries()),
233
+ body: payload
234
+ }
235
+ });
236
+ } catch (error) {
237
+ __privateMethod(this, _BaseMessenger_instances, sendMessage_fn).call(this, {
238
+ type: "response",
239
+ nonce: data.nonce,
240
+ error: serializeError(error)
241
+ });
242
+ } finally {
243
+ __privateGet(this, _abortControllers).delete(data.nonce);
244
+ }
245
+ break;
246
+ }
247
+ case "abort": {
248
+ const controller = __privateGet(this, _abortControllers).get(data.nonce);
249
+ controller?.abort(data.reason);
250
+ __privateGet(this, _abortControllers).delete(data.nonce);
251
+ break;
252
+ }
253
+ default:
254
+ break;
255
+ }
256
+ });
257
+ __privateSet(this, _target, config.target);
258
+ __privateSet(this, _targetOrigin, config.targetOrigin);
259
+ __privateSet(this, _handlers, config.handlers);
260
+ __privateSet(this, _fetch, config.fetch ?? fetch.bind(globalThis));
261
+ __privateSet(this, _canReceiveCommand, config.canReceiveCommand ?? DEFAULT_COMMAND_CAPABILITY);
262
+ }
263
+ connect() {
264
+ log("[NexvioWidget][Messenger] connect", { targetOrigin: __privateGet(this, _targetOrigin) });
265
+ window.addEventListener("message", __privateGet(this, _handleMessage));
266
+ }
267
+ disconnect() {
268
+ log("[NexvioWidget][Messenger] disconnect");
269
+ window.removeEventListener("message", __privateGet(this, _handleMessage));
270
+ __privateGet(this, _events).clear();
271
+ __privateGet(this, _pending).clear();
272
+ __privateGet(this, _abortControllers).forEach((controller) => controller.abort());
273
+ __privateGet(this, _abortControllers).clear();
274
+ }
275
+ on(event, listener) {
276
+ __privateGet(this, _events).on(event, listener);
277
+ }
278
+ off(event, listener) {
279
+ __privateGet(this, _events).off(event, listener);
280
+ }
281
+ };
282
+ _target = new WeakMap();
283
+ _targetOrigin = new WeakMap();
284
+ _handlers = new WeakMap();
285
+ _fetch = new WeakMap();
286
+ _events = new WeakMap();
287
+ _canReceiveCommand = new WeakMap();
288
+ _pending = new WeakMap();
289
+ _abortControllers = new WeakMap();
290
+ _BaseMessenger_instances = new WeakSet();
291
+ sendMessage_fn = function(message, transfer) {
292
+ const target = __privateGet(this, _target).call(this);
293
+ if (!target) {
294
+ throw new Error("Widget frame not ready");
295
+ }
296
+ const payload = { ...message, [MESSAGE_TOKEN]: true };
297
+ try {
298
+ debug("[NexvioWidget][Messenger] postMessage", {
299
+ type: message.type,
300
+ command: message.command,
301
+ targetOrigin: __privateGet(this, _targetOrigin)
302
+ });
303
+ target.postMessage(payload, __privateGet(this, _targetOrigin), transfer);
304
+ } catch (error) {
305
+ const shouldRetryWithAnyOrigin = __privateGet(this, _targetOrigin) !== "*" && error instanceof DOMException && (error.name === "SecurityError" || /target origin provided/i.test(error.message));
306
+ if (shouldRetryWithAnyOrigin) {
307
+ warn('[NexvioWidget][Messenger] SecurityError posting to targetOrigin. Retrying with "*"');
308
+ target.postMessage(payload, "*", transfer);
309
+ return;
310
+ }
311
+ throw error;
312
+ }
313
+ };
314
+ sendCommand_fn = async function(command, payload, transfer) {
315
+ const nonce = crypto.randomUUID();
316
+ return new Promise((resolve, reject) => {
317
+ __privateGet(this, _pending).set(nonce, { resolve, reject, stack: new Error().stack ?? "" });
318
+ try {
319
+ __privateMethod(this, _BaseMessenger_instances, sendMessage_fn).call(this, { type: "command", command, payload, nonce }, transfer);
320
+ } catch (error) {
321
+ __privateGet(this, _pending).delete(nonce);
322
+ reject(error);
323
+ }
324
+ });
325
+ };
326
+ _handleMessage = new WeakMap();
327
+ isWidgetMessage_fn = function(event) {
328
+ if (!event.data || typeof event.data !== "object" || event.data[MESSAGE_TOKEN] !== true) {
329
+ return false;
330
+ }
331
+ const targetWin = __privateGet(this, _target).call(this);
332
+ if (targetWin && event.source && event.source !== targetWin) {
333
+ debug("[NexvioWidget][Messenger] drop message: source mismatch");
334
+ return false;
335
+ }
336
+ if (event.origin !== __privateGet(this, _targetOrigin)) {
337
+ if (targetWin && event.source === targetWin) {
338
+ warn("[NexvioWidget][Messenger] learning targetOrigin from first message", {
339
+ from: __privateGet(this, _targetOrigin),
340
+ to: event.origin
341
+ });
342
+ __privateSet(this, _targetOrigin, event.origin);
343
+ } else {
344
+ debug("[NexvioWidget][Messenger] drop message: origin mismatch", {
345
+ expected: __privateGet(this, _targetOrigin),
346
+ got: event.origin
347
+ });
348
+ return false;
349
+ }
350
+ }
351
+ return true;
352
+ };
353
+
354
+ // src/messenger/WidgetFrameMessenger.ts
355
+ var WidgetFrameMessenger = class extends BaseMessenger {
356
+ constructor(config) {
357
+ super({
358
+ target: config.target,
359
+ targetOrigin: config.targetOrigin,
360
+ handlers: config.handlers,
361
+ fetch: config.fetch,
362
+ canReceiveCommand: () => true
363
+ });
364
+ }
365
+ };
366
+
367
+ // src/utils/base64.ts
368
+ function toBase64(input) {
369
+ if (typeof globalThis.btoa === "function") {
370
+ return globalThis.btoa(input);
371
+ }
372
+ const buffer = globalThis.Buffer;
373
+ if (buffer) {
374
+ return buffer.from(input, "binary").toString("base64");
375
+ }
376
+ throw new Error("No base64 encoder available in this environment");
377
+ }
378
+ function encodeBase64(value) {
379
+ if (value === void 0) {
380
+ throw new TypeError("encodeBase64: `undefined` cannot be serialized. Pass null instead.");
381
+ }
382
+ const json = JSON.stringify(value);
383
+ const bytes = new TextEncoder().encode(json);
384
+ let binary = "";
385
+ for (const byte of bytes) {
386
+ binary += String.fromCharCode(byte);
387
+ }
388
+ return toBase64(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
389
+ }
390
+
391
+ // src/utils/stripFunctions.ts
392
+ function stripFunctions(input, cloneMap = /* @__PURE__ */ new WeakMap()) {
393
+ if (typeof input !== "object" || input === null) {
394
+ return input;
395
+ }
396
+ if (cloneMap.has(input)) {
397
+ return cloneMap.get(input);
398
+ }
399
+ if (Array.isArray(input)) {
400
+ const arrClone = [];
401
+ cloneMap.set(input, arrClone);
402
+ for (const item of input) {
403
+ arrClone.push(stripFunctions(item, cloneMap));
404
+ }
405
+ return arrClone;
406
+ }
407
+ const clone = {};
408
+ cloneMap.set(input, clone);
409
+ for (const [key, value] of Object.entries(input)) {
410
+ if (typeof value === "function") {
411
+ continue;
412
+ }
413
+ clone[key] = stripFunctions(value, cloneMap);
414
+ }
415
+ return clone;
416
+ }
417
+
418
+ // src/utils/zod-to-json-schema.ts
419
+ function zodToJsonSchema(schema) {
420
+ if (!schema || !schema._def) {
421
+ return { type: "object", properties: {}, additionalProperties: false };
422
+ }
423
+ const def = schema._def;
424
+ const typeName = def.typeName;
425
+ if (typeName === "ZodObject") {
426
+ const shape = def.shape();
427
+ const properties = {};
428
+ const required = [];
429
+ for (const key in shape) {
430
+ const fieldSchema = shape[key];
431
+ properties[key] = zodToJsonSchema(fieldSchema);
432
+ if (fieldSchema._def.typeName !== "ZodOptional") {
433
+ required.push(key);
434
+ }
435
+ }
436
+ return {
437
+ type: "object",
438
+ properties,
439
+ required: required.length > 0 ? required : void 0,
440
+ additionalProperties: false
441
+ };
442
+ }
443
+ if (typeName === "ZodString") {
444
+ const result = { type: "string" };
445
+ if (def.description) {
446
+ result.description = def.description;
447
+ }
448
+ return result;
449
+ }
450
+ if (typeName === "ZodNumber") {
451
+ const result = { type: "number" };
452
+ if (def.description) {
453
+ result.description = def.description;
454
+ }
455
+ return result;
456
+ }
457
+ if (typeName === "ZodBoolean") {
458
+ const result = { type: "boolean" };
459
+ if (def.description) {
460
+ result.description = def.description;
461
+ }
462
+ return result;
463
+ }
464
+ if (typeName === "ZodArray") {
465
+ const result = {
466
+ type: "array",
467
+ items: zodToJsonSchema(def.type)
468
+ };
469
+ if (def.description) {
470
+ result.description = def.description;
471
+ }
472
+ return result;
473
+ }
474
+ if (typeName === "ZodEnum") {
475
+ const result = {
476
+ type: "string",
477
+ enum: def.values
478
+ };
479
+ if (def.description) {
480
+ result.description = def.description;
481
+ }
482
+ return result;
483
+ }
484
+ if (typeName === "ZodOptional") {
485
+ return zodToJsonSchema(def.innerType);
486
+ }
487
+ if (typeName === "ZodNullable") {
488
+ const innerSchema = zodToJsonSchema(def.innerType);
489
+ return {
490
+ ...innerSchema,
491
+ nullable: true
492
+ };
493
+ }
494
+ if (typeName === "ZodLiteral") {
495
+ return {
496
+ type: typeof def.value,
497
+ enum: [def.value]
498
+ };
499
+ }
500
+ if (typeName === "ZodUnion") {
501
+ const options = def.options;
502
+ if (options && options.length > 0) {
503
+ return {
504
+ anyOf: options.map((opt) => zodToJsonSchema(opt))
505
+ };
506
+ }
507
+ }
508
+ return { type: "object", additionalProperties: true };
509
+ }
510
+
511
+ // src/NexvioWidgetElement.ts
512
+ var DEFAULT_WIDGET_URL = "https://chatwidget.app";
513
+ var WIDGET_VERSION = "0.1.0";
514
+ var styleContent = `
515
+ :host {
516
+ display: block;
517
+ position: relative;
518
+ width: 100%;
519
+ height: 100%;
520
+ }
521
+ .nx-wrapper {
522
+ position: absolute;
523
+ inset: 0;
524
+ width: 100%;
525
+ height: 100%;
526
+ opacity: 0;
527
+ transition: opacity 160ms ease-in-out;
528
+ }
529
+ :host([data-loaded='true']) .nx-wrapper {
530
+ opacity: 1;
531
+ }
532
+ .nx-frame {
533
+ border: none;
534
+ width: 100%;
535
+ height: 100%;
536
+ position: absolute;
537
+ inset: 0;
538
+ background: transparent;
539
+ }
540
+ `;
541
+ var BaseHTMLElement = typeof HTMLElement === "undefined" ? class {
542
+ } : HTMLElement;
543
+ var _shadowRootRef, _frame, _wrapper, _options, _sanitized, _messenger, _loadedResolve, _loaded, _targetOrigin2, _initialized, _frameReady, _pendingOptions, _NexvioWidgetElement_instances, sanitizeOptions_fn, ensureStructure_fn, initializeFrame_fn, _handleFrameLoad, ensureMessenger_fn, buildFrameUrl_fn, updateDataAttributes_fn, handleFrameEvent_fn, handleClientAction_fn, handleExecuteClientTool_fn, dispatchReady_fn, dispatchError_fn, dispatchEvent_fn, handleResize_fn, flushOptionsIfReady_fn;
544
+ var NexvioWidgetElement = class extends BaseHTMLElement {
545
+ constructor() {
546
+ super();
547
+ __privateAdd(this, _NexvioWidgetElement_instances);
548
+ __privateAdd(this, _shadowRootRef, null);
549
+ __privateAdd(this, _frame);
550
+ __privateAdd(this, _wrapper);
551
+ __privateAdd(this, _options);
552
+ __privateAdd(this, _sanitized);
553
+ __privateAdd(this, _messenger);
554
+ __privateAdd(this, _loadedResolve);
555
+ __privateAdd(this, _loaded);
556
+ __privateAdd(this, _targetOrigin2);
557
+ __privateAdd(this, _initialized, false);
558
+ __privateAdd(this, _frameReady, false);
559
+ __privateAdd(this, _pendingOptions);
560
+ __privateAdd(this, _handleFrameLoad, () => {
561
+ var _a;
562
+ debug("[NexvioWidget] frame load event");
563
+ this.dataset.loaded = "true";
564
+ (_a = __privateGet(this, _loadedResolve)) == null ? void 0 : _a.call(this);
565
+ __privateMethod(this, _NexvioWidgetElement_instances, flushOptionsIfReady_fn).call(this);
566
+ });
567
+ if (typeof window !== "undefined" && typeof this.attachShadow === "function") {
568
+ __privateSet(this, _shadowRootRef, this.attachShadow({ mode: "open" }));
569
+ }
570
+ log("[NexvioWidget] element: constructed");
571
+ __privateSet(this, _loaded, new Promise((resolve) => {
572
+ __privateSet(this, _loadedResolve, resolve);
573
+ }));
574
+ }
575
+ connectedCallback() {
576
+ log("[NexvioWidget] element: connectedCallback");
577
+ __privateMethod(this, _NexvioWidgetElement_instances, ensureStructure_fn).call(this);
578
+ if (__privateGet(this, _sanitized) && !__privateGet(this, _initialized)) {
579
+ __privateMethod(this, _NexvioWidgetElement_instances, initializeFrame_fn).call(this);
580
+ }
581
+ }
582
+ disconnectedCallback() {
583
+ log("[NexvioWidget] element: disconnectedCallback");
584
+ __privateGet(this, _messenger)?.disconnect();
585
+ }
586
+ setOptions(options) {
587
+ log("[NexvioWidget] setOptions: received", options);
588
+ const sanitized = __privateMethod(this, _NexvioWidgetElement_instances, sanitizeOptions_fn).call(this, options);
589
+ const previous = __privateGet(this, _sanitized);
590
+ const baseUrl = sanitized.host?.baseUrl ?? DEFAULT_WIDGET_URL;
591
+ debug("[NexvioWidget] setOptions: sanitized", sanitized);
592
+ __privateMethod(this, _NexvioWidgetElement_instances, ensureMessenger_fn).call(this, new URL(baseUrl).origin, options.fetch);
593
+ __privateSet(this, _options, options);
594
+ __privateSet(this, _sanitized, sanitized);
595
+ __privateSet(this, _pendingOptions, sanitized);
596
+ const requiresReload = !__privateGet(this, _initialized) || !previous || previous.publicKey !== sanitized.publicKey || (previous.host?.baseUrl ?? DEFAULT_WIDGET_URL) !== (sanitized.host?.baseUrl ?? DEFAULT_WIDGET_URL) || // Reload if clientTools changed (added, removed, or modified)
597
+ JSON.stringify(previous.clientTools) !== JSON.stringify(sanitized.clientTools);
598
+ debug("[NexvioWidget] setOptions: requiresReload", {
599
+ requiresReload,
600
+ reasons: {
601
+ notInitialized: !__privateGet(this, _initialized),
602
+ noPrevious: !previous,
603
+ publicKeyChanged: previous && previous.publicKey !== sanitized.publicKey,
604
+ baseUrlChanged: previous && (previous.host?.baseUrl ?? DEFAULT_WIDGET_URL) !== (sanitized.host?.baseUrl ?? DEFAULT_WIDGET_URL),
605
+ clientToolsChanged: previous && JSON.stringify(previous.clientTools) !== JSON.stringify(sanitized.clientTools)
606
+ }
607
+ });
608
+ __privateMethod(this, _NexvioWidgetElement_instances, updateDataAttributes_fn).call(this, sanitized);
609
+ if (requiresReload) {
610
+ __privateMethod(this, _NexvioWidgetElement_instances, initializeFrame_fn).call(this, true);
611
+ return;
612
+ }
613
+ __privateMethod(this, _NexvioWidgetElement_instances, flushOptionsIfReady_fn).call(this);
614
+ }
615
+ async focusInput() {
616
+ await __privateGet(this, _loaded);
617
+ await __privateGet(this, _messenger)?.commands.focusInput();
618
+ }
619
+ async refresh() {
620
+ await __privateGet(this, _loaded);
621
+ await __privateGet(this, _messenger)?.commands.refresh();
622
+ }
623
+ async setVisitor(visitor) {
624
+ await __privateGet(this, _loaded);
625
+ await __privateGet(this, _messenger)?.commands.updateVisitor(visitor);
626
+ }
627
+ async reload() {
628
+ if (!__privateGet(this, _sanitized)) return;
629
+ __privateSet(this, _initialized, false);
630
+ __privateMethod(this, _NexvioWidgetElement_instances, initializeFrame_fn).call(this, true);
631
+ }
632
+ get options() {
633
+ return __privateGet(this, _options);
634
+ }
635
+ };
636
+ _shadowRootRef = new WeakMap();
637
+ _frame = new WeakMap();
638
+ _wrapper = new WeakMap();
639
+ _options = new WeakMap();
640
+ _sanitized = new WeakMap();
641
+ _messenger = new WeakMap();
642
+ _loadedResolve = new WeakMap();
643
+ _loaded = new WeakMap();
644
+ _targetOrigin2 = new WeakMap();
645
+ _initialized = new WeakMap();
646
+ _frameReady = new WeakMap();
647
+ _pendingOptions = new WeakMap();
648
+ _NexvioWidgetElement_instances = new WeakSet();
649
+ sanitizeOptions_fn = function(options) {
650
+ if (!options || typeof options.publicKey !== "string" || options.publicKey.trim().length === 0) {
651
+ throw new Error("Nexvio widget requires a non-empty `publicKey`.");
652
+ }
653
+ const hostBase = options.host?.baseUrl ?? DEFAULT_WIDGET_URL;
654
+ let validatedHost;
655
+ try {
656
+ validatedHost = new URL(hostBase);
657
+ } catch (error) {
658
+ throw new Error(`Invalid host baseUrl provided to Nexvio widget: ${error}`);
659
+ }
660
+ const sanitized = stripFunctions({
661
+ publicKey: options.publicKey.trim(),
662
+ appearance: options.appearance,
663
+ messageActions: options.messageActions,
664
+ metadata: options.metadata,
665
+ context: options.context,
666
+ startScreen: options.startScreen,
667
+ host: {
668
+ baseUrl: validatedHost.toString().replace(/\/$/, ""),
669
+ query: options.host?.query
670
+ }
671
+ });
672
+ if (options.client?.tools && Array.isArray(options.client.tools)) {
673
+ log("[NexvioWidget] sanitizeOptions: converting client tools", options.client.tools);
674
+ sanitized.clientTools = options.client.tools.map((tool) => ({
675
+ name: tool.name,
676
+ description: tool.description,
677
+ parameters: zodToJsonSchema(tool.parameters)
678
+ }));
679
+ log("[NexvioWidget] sanitizeOptions: sanitized clientTools", sanitized.clientTools);
680
+ } else {
681
+ log("[NexvioWidget] sanitizeOptions: no client tools found", {
682
+ hasClient: !!options.client,
683
+ hasTools: !!options.client?.tools
684
+ });
685
+ }
686
+ return sanitized;
687
+ };
688
+ ensureStructure_fn = function() {
689
+ if (__privateGet(this, _wrapper)) return;
690
+ if (!__privateGet(this, _shadowRootRef)) return;
691
+ const style = document.createElement("style");
692
+ style.textContent = styleContent;
693
+ const wrapper = document.createElement("div");
694
+ wrapper.className = "nx-wrapper";
695
+ const frame = document.createElement("iframe");
696
+ frame.className = "nx-frame";
697
+ frame.setAttribute("allow", "clipboard-read; clipboard-write");
698
+ frame.setAttribute("referrerpolicy", "strict-origin-when-cross-origin");
699
+ frame.name = "nexvio-widget";
700
+ frame.tabIndex = -1;
701
+ wrapper.appendChild(frame);
702
+ __privateGet(this, _shadowRootRef).append(style, wrapper);
703
+ __privateSet(this, _frame, frame);
704
+ __privateSet(this, _wrapper, wrapper);
705
+ };
706
+ initializeFrame_fn = function(forceReload = false) {
707
+ if (!__privateGet(this, _frame) || !__privateGet(this, _sanitized)) return;
708
+ if (__privateGet(this, _initialized) && !forceReload) return;
709
+ __privateSet(this, _initialized, true);
710
+ __privateSet(this, _frameReady, false);
711
+ this.dataset.loaded = "false";
712
+ __privateSet(this, _loaded, new Promise((resolve) => {
713
+ __privateSet(this, _loadedResolve, resolve);
714
+ }));
715
+ const frameUrl = __privateMethod(this, _NexvioWidgetElement_instances, buildFrameUrl_fn).call(this, __privateGet(this, _sanitized));
716
+ debug("[NexvioWidget] initializeFrame", { forceReload, frameUrl: frameUrl.toString() });
717
+ __privateGet(this, _frame).addEventListener("load", __privateGet(this, _handleFrameLoad), { once: true });
718
+ __privateGet(this, _frame).src = frameUrl.toString();
719
+ __privateMethod(this, _NexvioWidgetElement_instances, updateDataAttributes_fn).call(this, __privateGet(this, _sanitized));
720
+ };
721
+ _handleFrameLoad = new WeakMap();
722
+ ensureMessenger_fn = function(origin, customFetch) {
723
+ if (__privateGet(this, _messenger) && __privateGet(this, _targetOrigin2) === origin) {
724
+ debug("[NexvioWidget] messenger: reuse", { origin });
725
+ return;
726
+ }
727
+ __privateGet(this, _messenger)?.disconnect();
728
+ __privateSet(this, _targetOrigin2, origin);
729
+ log("[NexvioWidget] messenger: create", { origin });
730
+ __privateSet(this, _messenger, new WidgetFrameMessenger({
731
+ target: () => __privateGet(this, _frame)?.contentWindow ?? null,
732
+ targetOrigin: origin,
733
+ fetch: customFetch,
734
+ handlers: {
735
+ onEmitEvent: (payload) => __privateMethod(this, _NexvioWidgetElement_instances, handleFrameEvent_fn).call(this, payload),
736
+ onRequestClientAction: (payload) => __privateMethod(this, _NexvioWidgetElement_instances, handleClientAction_fn).call(this, payload),
737
+ onExecuteClientTool: (payload) => __privateMethod(this, _NexvioWidgetElement_instances, handleExecuteClientTool_fn).call(this, payload)
738
+ }
739
+ }));
740
+ __privateGet(this, _messenger).connect();
741
+ __privateGet(this, _messenger).on("widget.ready", (payload) => __privateMethod(this, _NexvioWidgetElement_instances, dispatchReady_fn).call(this, payload));
742
+ __privateGet(this, _messenger).on("widget.error", (payload) => __privateMethod(this, _NexvioWidgetElement_instances, dispatchError_fn).call(this, payload));
743
+ __privateGet(this, _messenger).on("widget.event", (payload) => __privateMethod(this, _NexvioWidgetElement_instances, dispatchEvent_fn).call(this, payload));
744
+ __privateGet(this, _messenger).on("widget.resize", (payload) => __privateMethod(this, _NexvioWidgetElement_instances, handleResize_fn).call(this, payload));
745
+ };
746
+ buildFrameUrl_fn = function(options) {
747
+ const base = options.host?.baseUrl ?? DEFAULT_WIDGET_URL;
748
+ const trimmedBase = base.endsWith("/") ? base.slice(0, -1) : base;
749
+ const url = new URL(`${trimmedBase}/${encodeURIComponent(options.publicKey)}`);
750
+ url.searchParams.set("embed", "1");
751
+ const query = options.host?.query ?? {};
752
+ for (const [key, value] of Object.entries(query)) {
753
+ if (value === void 0) continue;
754
+ url.searchParams.set(key, String(value));
755
+ }
756
+ const payload = stripFunctions({
757
+ appearance: options.appearance,
758
+ metadata: options.metadata,
759
+ context: options.context,
760
+ startScreen: options.startScreen,
761
+ version: WIDGET_VERSION,
762
+ clientTools: options.clientTools
763
+ });
764
+ log("[NexvioWidget] buildFrameUrl: payload with clientTools", payload);
765
+ if (Object.values(payload).some((value) => value !== void 0)) {
766
+ url.hash = encodeBase64(payload);
767
+ }
768
+ debug("[NexvioWidget] buildFrameUrl", { url: url.toString() });
769
+ return url;
770
+ };
771
+ updateDataAttributes_fn = function(options) {
772
+ const colorScheme = typeof options.appearance?.colorScheme === "string" ? options.appearance.colorScheme : void 0;
773
+ if (colorScheme) {
774
+ this.dataset.colorScheme = colorScheme;
775
+ } else {
776
+ delete this.dataset.colorScheme;
777
+ }
778
+ };
779
+ handleFrameEvent_fn = function({ name, detail }) {
780
+ log("[NexvioWidget] event", { name, detail });
781
+ const event = { name, detail };
782
+ __privateGet(this, _options)?.onEvent?.(event);
783
+ this.dispatchEvent(
784
+ new CustomEvent("nexvio.event", {
785
+ detail: event,
786
+ bubbles: true,
787
+ composed: true
788
+ })
789
+ );
790
+ this.dispatchEvent(
791
+ new CustomEvent(`nexvio.${name}`, {
792
+ detail,
793
+ bubbles: true,
794
+ composed: true
795
+ })
796
+ );
797
+ };
798
+ handleClientAction_fn = async function({
799
+ action,
800
+ data
801
+ }) {
802
+ const handler = __privateGet(this, _options)?.clientActions?.[action];
803
+ if (!handler) {
804
+ throw new Error(`No client action handler registered for "${action}"`);
805
+ }
806
+ return handler(data);
807
+ };
808
+ handleExecuteClientTool_fn = async function({
809
+ toolName,
810
+ toolArgs
811
+ }) {
812
+ log("[NexvioWidget] executeClientTool", { toolName, toolArgs });
813
+ const tool = __privateGet(this, _options)?.client?.tools?.find((t) => t.name === toolName);
814
+ if (!tool) {
815
+ throw new Error(`No client tool registered with name "${toolName}"`);
816
+ }
817
+ try {
818
+ const validated = tool.parameters.parse(toolArgs);
819
+ const result = await Promise.resolve(tool.execute(validated));
820
+ log("[NexvioWidget] executeClientTool: success", { toolName, result });
821
+ return result;
822
+ } catch (error) {
823
+ console.error("[NexvioWidget] executeClientTool: error", { toolName, error });
824
+ throw new Error(`Tool execution failed for "${toolName}": ${error.message}`);
825
+ }
826
+ };
827
+ dispatchReady_fn = function(payload) {
828
+ log("[NexvioWidget] ready", payload);
829
+ __privateSet(this, _frameReady, true);
830
+ __privateMethod(this, _NexvioWidgetElement_instances, flushOptionsIfReady_fn).call(this);
831
+ this.dispatchEvent(
832
+ new CustomEvent("nexvio.ready", {
833
+ detail: payload,
834
+ bubbles: true,
835
+ composed: true
836
+ })
837
+ );
838
+ };
839
+ dispatchError_fn = function(payload) {
840
+ const error = new Error(payload.message);
841
+ if (payload.stack) {
842
+ error.stack = payload.stack;
843
+ }
844
+ log("[NexvioWidget] error", payload);
845
+ this.dispatchEvent(
846
+ new CustomEvent("nexvio.error", {
847
+ detail: { error },
848
+ bubbles: true,
849
+ composed: true
850
+ })
851
+ );
852
+ };
853
+ dispatchEvent_fn = function(payload) {
854
+ __privateMethod(this, _NexvioWidgetElement_instances, handleFrameEvent_fn).call(this, payload);
855
+ };
856
+ handleResize_fn = function(payload) {
857
+ if (typeof payload?.height === "number") {
858
+ this.style.setProperty("--nexvio-widget-height", `${payload.height}px`);
859
+ }
860
+ };
861
+ flushOptionsIfReady_fn = function() {
862
+ if (!__privateGet(this, _frameReady)) return;
863
+ if (!__privateGet(this, _pendingOptions)) return;
864
+ const options = __privateGet(this, _pendingOptions);
865
+ __privateSet(this, _pendingOptions, void 0);
866
+ if (!__privateGet(this, _messenger)) return;
867
+ debug("[NexvioWidget] flushOptionsIfReady: syncing options to frame");
868
+ void __privateGet(this, _messenger).commands.setOptions(options).catch((error) => {
869
+ console.error("Failed to sync widget options:", error);
870
+ });
871
+ };
872
+ function registerNexvioWidget(tagName = "nexvio-chat-widget") {
873
+ if (typeof customElements === "undefined") return;
874
+ if (!customElements.get(tagName)) {
875
+ customElements.define(tagName, NexvioWidgetElement);
876
+ }
877
+ }
878
+
879
+ // src/NexvioChatbotElement.ts
880
+ var styleContent2 = `
881
+ :host {
882
+ --chatbot-button-size: 60px;
883
+ --chatbot-button-bg: #3B82F6;
884
+ --chatbot-button-color: white;
885
+ --chatbot-widget-width: 420px;
886
+ --chatbot-widget-height: 600px;
887
+ --chatbot-widget-gap: 20px;
888
+
889
+ position: fixed;
890
+ bottom: var(--chatbot-widget-gap);
891
+ right: var(--chatbot-widget-gap);
892
+ z-index: 999999;
893
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
894
+ }
895
+
896
+ .nx-chatbot-button {
897
+ width: var(--chatbot-button-size);
898
+ height: var(--chatbot-button-size);
899
+ border-radius: 50%;
900
+ background: var(--chatbot-button-bg);
901
+ color: var(--chatbot-button-color);
902
+ border: none;
903
+ cursor: pointer;
904
+ display: flex;
905
+ align-items: center;
906
+ justify-content: center;
907
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
908
+ transition: transform 0.2s ease, box-shadow 0.2s ease;
909
+ position: relative;
910
+ overflow: hidden;
911
+ }
912
+
913
+ .nx-chatbot-button:hover {
914
+ transform: scale(1.05);
915
+ box-shadow: 0 6px 16px rgba(0, 0, 0, 0.2);
916
+ }
917
+
918
+ .nx-chatbot-button:active {
919
+ transform: scale(0.95);
920
+ }
921
+
922
+ .nx-chatbot-button svg {
923
+ width: 28px;
924
+ height: 28px;
925
+ transition: transform 0.3s ease, opacity 0.3s ease;
926
+ }
927
+
928
+ .nx-chatbot-button.open svg.icon-chat {
929
+ transform: rotate(90deg) scale(0);
930
+ opacity: 0;
931
+ }
932
+
933
+ .nx-chatbot-button svg.icon-close {
934
+ position: absolute;
935
+ transform: rotate(-90deg) scale(0);
936
+ opacity: 0;
937
+ }
938
+
939
+ .nx-chatbot-button.open svg.icon-close {
940
+ transform: rotate(0deg) scale(1);
941
+ opacity: 1;
942
+ }
943
+
944
+ .nx-chatbot-widget-container {
945
+ position: absolute;
946
+ bottom: calc(var(--chatbot-button-size) + 16px);
947
+ right: 0;
948
+ width: var(--chatbot-widget-width);
949
+ height: var(--chatbot-widget-height);
950
+ max-height: calc(100vh - var(--chatbot-button-size) - var(--chatbot-widget-gap) - 32px);
951
+ border-radius: 12px;
952
+ box-shadow: 0 8px 32px rgba(0, 0, 0, 0.12);
953
+ overflow: hidden;
954
+ transform-origin: bottom right;
955
+ transform: scale(0.8);
956
+ opacity: 0;
957
+ pointer-events: none;
958
+ transition: transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1),
959
+ opacity 0.3s ease;
960
+ }
961
+
962
+ .nx-chatbot-widget-container.open {
963
+ transform: scale(1);
964
+ opacity: 1;
965
+ pointer-events: auto;
966
+ }
967
+
968
+ .nx-chatbot-widget-container nexvio-chat-widget {
969
+ display: block;
970
+ width: 100%;
971
+ height: 100%;
972
+ }
973
+
974
+ .nx-chatbot-badge {
975
+ position: absolute;
976
+ top: -4px;
977
+ right: -4px;
978
+ min-width: 20px;
979
+ height: 20px;
980
+ padding: 0 6px;
981
+ background: #EF4444;
982
+ color: white;
983
+ border-radius: 10px;
984
+ font-size: 11px;
985
+ font-weight: 600;
986
+ display: flex;
987
+ align-items: center;
988
+ justify-content: center;
989
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
990
+ transform: scale(0);
991
+ transition: transform 0.2s ease;
992
+ }
993
+
994
+ .nx-chatbot-badge.visible {
995
+ transform: scale(1);
996
+ }
997
+
998
+ @media (max-width: 768px) {
999
+ :host {
1000
+ bottom: 16px;
1001
+ right: 16px;
1002
+ --chatbot-widget-gap: 16px;
1003
+ }
1004
+
1005
+ .nx-chatbot-widget-container {
1006
+ position: fixed;
1007
+ bottom: 0;
1008
+ right: 0;
1009
+ left: 0;
1010
+ top: 0;
1011
+ width: 100%;
1012
+ height: 100%;
1013
+ max-width: 100%;
1014
+ max-height: 100%;
1015
+ border-radius: 0;
1016
+ }
1017
+
1018
+ .nx-chatbot-widget-container.open {
1019
+ transform: scale(1);
1020
+ }
1021
+ }
1022
+ `;
1023
+ var BaseHTMLElement2 = typeof HTMLElement === "undefined" ? class {
1024
+ } : HTMLElement;
1025
+ var _shadowRootRef2, _button, _widgetContainer, _widget, _badge, _isOpen, _options2, _initialized2, _NexvioChatbotElement_instances, ensureStructure_fn2, initialize_fn, updateWidget_fn, updateStyles_fn, updateBadge_fn;
1026
+ var NexvioChatbotElement = class extends BaseHTMLElement2 {
1027
+ constructor() {
1028
+ super();
1029
+ __privateAdd(this, _NexvioChatbotElement_instances);
1030
+ __privateAdd(this, _shadowRootRef2, null);
1031
+ __privateAdd(this, _button);
1032
+ __privateAdd(this, _widgetContainer);
1033
+ __privateAdd(this, _widget);
1034
+ __privateAdd(this, _badge);
1035
+ __privateAdd(this, _isOpen, false);
1036
+ __privateAdd(this, _options2);
1037
+ __privateAdd(this, _initialized2, false);
1038
+ if (typeof window !== "undefined" && typeof this.attachShadow === "function") {
1039
+ __privateSet(this, _shadowRootRef2, this.attachShadow({ mode: "open" }));
1040
+ }
1041
+ log("[NexvioChatbot] element: constructed");
1042
+ }
1043
+ connectedCallback() {
1044
+ log("[NexvioChatbot] element: connectedCallback");
1045
+ __privateMethod(this, _NexvioChatbotElement_instances, ensureStructure_fn2).call(this);
1046
+ if (__privateGet(this, _options2) && !__privateGet(this, _initialized2)) {
1047
+ __privateMethod(this, _NexvioChatbotElement_instances, initialize_fn).call(this);
1048
+ }
1049
+ }
1050
+ disconnectedCallback() {
1051
+ log("[NexvioChatbot] element: disconnectedCallback");
1052
+ }
1053
+ setOptions(options) {
1054
+ log("[NexvioChatbot] setOptions:", options);
1055
+ __privateSet(this, _options2, options);
1056
+ __privateMethod(this, _NexvioChatbotElement_instances, ensureStructure_fn2).call(this);
1057
+ if (!__privateGet(this, _initialized2)) {
1058
+ __privateMethod(this, _NexvioChatbotElement_instances, initialize_fn).call(this);
1059
+ } else {
1060
+ __privateMethod(this, _NexvioChatbotElement_instances, updateWidget_fn).call(this);
1061
+ }
1062
+ __privateMethod(this, _NexvioChatbotElement_instances, updateStyles_fn).call(this);
1063
+ __privateMethod(this, _NexvioChatbotElement_instances, updateBadge_fn).call(this);
1064
+ }
1065
+ open() {
1066
+ if (__privateGet(this, _isOpen)) return;
1067
+ __privateSet(this, _isOpen, true);
1068
+ __privateGet(this, _button)?.classList.add("open");
1069
+ __privateGet(this, _widgetContainer)?.classList.add("open");
1070
+ this.dispatchEvent(new CustomEvent("chatbot.opened", { bubbles: true, composed: true }));
1071
+ }
1072
+ close() {
1073
+ if (!__privateGet(this, _isOpen)) return;
1074
+ __privateSet(this, _isOpen, false);
1075
+ __privateGet(this, _button)?.classList.remove("open");
1076
+ __privateGet(this, _widgetContainer)?.classList.remove("open");
1077
+ this.dispatchEvent(new CustomEvent("chatbot.closed", { bubbles: true, composed: true }));
1078
+ }
1079
+ toggle() {
1080
+ if (__privateGet(this, _isOpen)) {
1081
+ this.close();
1082
+ } else {
1083
+ this.open();
1084
+ }
1085
+ }
1086
+ get isOpen() {
1087
+ return __privateGet(this, _isOpen);
1088
+ }
1089
+ get widget() {
1090
+ return __privateGet(this, _widget);
1091
+ }
1092
+ get options() {
1093
+ return __privateGet(this, _options2);
1094
+ }
1095
+ };
1096
+ _shadowRootRef2 = new WeakMap();
1097
+ _button = new WeakMap();
1098
+ _widgetContainer = new WeakMap();
1099
+ _widget = new WeakMap();
1100
+ _badge = new WeakMap();
1101
+ _isOpen = new WeakMap();
1102
+ _options2 = new WeakMap();
1103
+ _initialized2 = new WeakMap();
1104
+ _NexvioChatbotElement_instances = new WeakSet();
1105
+ ensureStructure_fn2 = function() {
1106
+ if (__privateGet(this, _button) && __privateGet(this, _widgetContainer)) return;
1107
+ if (!__privateGet(this, _shadowRootRef2)) return;
1108
+ if (typeof window !== "undefined" && typeof customElements !== "undefined") {
1109
+ registerNexvioWidget();
1110
+ }
1111
+ const style = document.createElement("style");
1112
+ style.textContent = styleContent2;
1113
+ const button = document.createElement("button");
1114
+ button.className = "nx-chatbot-button";
1115
+ button.setAttribute("aria-label", "Open chat");
1116
+ button.innerHTML = `
1117
+ <svg class="icon-chat" xmlns="http://www.w3.org/2000/svg"
1118
+ viewBox="0 0 24 24" fill="none" stroke="currentColor"
1119
+ stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
1120
+ <path d="M6 4h12a3 3 0 0 1 3 3v7a3 3 0 0 1-3 3H9l-4 3v-3H6a3 3 0 0 1-3-3V7a3 3 0 0 1 3-3z"/>
1121
+ </svg>
1122
+ <svg class="icon-close" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
1123
+ <path d="M18 6L6 18M6 6l12 12"></path>
1124
+ </svg>
1125
+ `;
1126
+ const badge = document.createElement("span");
1127
+ badge.className = "nx-chatbot-badge";
1128
+ button.appendChild(badge);
1129
+ const widgetContainer = document.createElement("div");
1130
+ widgetContainer.className = "nx-chatbot-widget-container";
1131
+ const widget = document.createElement("nexvio-chat-widget");
1132
+ widgetContainer.appendChild(widget);
1133
+ __privateGet(this, _shadowRootRef2).append(style, button, widgetContainer);
1134
+ __privateSet(this, _button, button);
1135
+ __privateSet(this, _widgetContainer, widgetContainer);
1136
+ __privateSet(this, _widget, widget);
1137
+ __privateSet(this, _badge, badge);
1138
+ button.addEventListener("click", () => this.toggle());
1139
+ widget.addEventListener("nexvio.event", ((event) => {
1140
+ this.dispatchEvent(
1141
+ new CustomEvent("nexvio.event", {
1142
+ detail: event.detail,
1143
+ bubbles: true,
1144
+ composed: true
1145
+ })
1146
+ );
1147
+ }));
1148
+ };
1149
+ initialize_fn = function() {
1150
+ if (__privateGet(this, _initialized2) || !__privateGet(this, _options2) || !__privateGet(this, _widget)) return;
1151
+ __privateSet(this, _initialized2, true);
1152
+ const widgetOptions = { ...__privateGet(this, _options2) };
1153
+ delete widgetOptions.position;
1154
+ delete widgetOptions.defaultOpen;
1155
+ delete widgetOptions.buttonColor;
1156
+ delete widgetOptions.badge;
1157
+ delete widgetOptions.buttonIcon;
1158
+ delete widgetOptions.gap;
1159
+ const setWidgetOptions = () => {
1160
+ if (__privateGet(this, _widget) && typeof __privateGet(this, _widget).setOptions === "function") {
1161
+ __privateGet(this, _widget).setOptions(widgetOptions);
1162
+ if (__privateGet(this, _options2)?.defaultOpen) {
1163
+ setTimeout(() => this.open(), 100);
1164
+ }
1165
+ debug("[NexvioChatbot] initialized");
1166
+ } else if (typeof window !== "undefined" && typeof customElements !== "undefined") {
1167
+ customElements.whenDefined("nexvio-chat-widget").then(() => {
1168
+ if (__privateGet(this, _widget) && typeof __privateGet(this, _widget).setOptions === "function") {
1169
+ __privateGet(this, _widget).setOptions(widgetOptions);
1170
+ if (__privateGet(this, _options2)?.defaultOpen) {
1171
+ setTimeout(() => this.open(), 100);
1172
+ }
1173
+ debug("[NexvioChatbot] initialized");
1174
+ }
1175
+ }).catch(() => {
1176
+ console.error("[NexvioChatbot] Failed to initialize widget element");
1177
+ });
1178
+ }
1179
+ };
1180
+ setWidgetOptions();
1181
+ };
1182
+ updateWidget_fn = function() {
1183
+ if (!__privateGet(this, _widget) || !__privateGet(this, _options2)) return;
1184
+ const widgetOptions = { ...__privateGet(this, _options2) };
1185
+ delete widgetOptions.position;
1186
+ delete widgetOptions.defaultOpen;
1187
+ delete widgetOptions.buttonColor;
1188
+ delete widgetOptions.badge;
1189
+ delete widgetOptions.buttonIcon;
1190
+ delete widgetOptions.gap;
1191
+ if (typeof __privateGet(this, _widget).setOptions === "function") {
1192
+ __privateGet(this, _widget).setOptions(widgetOptions);
1193
+ } else if (typeof window !== "undefined" && typeof customElements !== "undefined") {
1194
+ customElements.whenDefined("nexvio-chat-widget").then(() => {
1195
+ if (__privateGet(this, _widget) && typeof __privateGet(this, _widget).setOptions === "function") {
1196
+ __privateGet(this, _widget).setOptions(widgetOptions);
1197
+ }
1198
+ }).catch(() => {
1199
+ console.error("[NexvioChatbot] Failed to update widget element");
1200
+ });
1201
+ }
1202
+ };
1203
+ updateStyles_fn = function() {
1204
+ if (!__privateGet(this, _options2)) return;
1205
+ const host = __privateGet(this, _shadowRootRef2)?.host;
1206
+ if (!host) return;
1207
+ if (__privateGet(this, _options2).buttonColor) {
1208
+ host.style.setProperty("--chatbot-button-bg", __privateGet(this, _options2).buttonColor);
1209
+ }
1210
+ if (__privateGet(this, _options2).gap !== void 0) {
1211
+ host.style.setProperty("--chatbot-widget-gap", `${__privateGet(this, _options2).gap}px`);
1212
+ }
1213
+ if (__privateGet(this, _options2).position) {
1214
+ const positions = {
1215
+ "bottom-right": {
1216
+ bottom: "var(--chatbot-widget-gap)",
1217
+ right: "var(--chatbot-widget-gap)",
1218
+ top: "auto",
1219
+ left: "auto"
1220
+ },
1221
+ "bottom-left": {
1222
+ bottom: "var(--chatbot-widget-gap)",
1223
+ left: "var(--chatbot-widget-gap)",
1224
+ top: "auto",
1225
+ right: "auto"
1226
+ },
1227
+ "top-right": {
1228
+ top: "var(--chatbot-widget-gap)",
1229
+ right: "var(--chatbot-widget-gap)",
1230
+ bottom: "auto",
1231
+ left: "auto"
1232
+ },
1233
+ "top-left": {
1234
+ top: "var(--chatbot-widget-gap)",
1235
+ left: "var(--chatbot-widget-gap)",
1236
+ bottom: "auto",
1237
+ right: "auto"
1238
+ }
1239
+ };
1240
+ const pos = positions[__privateGet(this, _options2).position];
1241
+ Object.entries(pos).forEach(([key, value]) => {
1242
+ host.style.setProperty(key, value);
1243
+ });
1244
+ }
1245
+ if (__privateGet(this, _options2).buttonIcon && __privateGet(this, _button)) {
1246
+ const chatIcon = __privateGet(this, _button).querySelector(".icon-chat");
1247
+ if (chatIcon) {
1248
+ chatIcon.innerHTML = __privateGet(this, _options2).buttonIcon;
1249
+ }
1250
+ }
1251
+ };
1252
+ updateBadge_fn = function() {
1253
+ if (!__privateGet(this, _badge) || !__privateGet(this, _options2)) return;
1254
+ const badgeValue = __privateGet(this, _options2).badge;
1255
+ if (typeof badgeValue === "number" && badgeValue > 0) {
1256
+ __privateGet(this, _badge).textContent = badgeValue > 99 ? "99+" : String(badgeValue);
1257
+ __privateGet(this, _badge).classList.add("visible");
1258
+ } else if (badgeValue === true) {
1259
+ __privateGet(this, _badge).textContent = "";
1260
+ __privateGet(this, _badge).classList.add("visible");
1261
+ } else {
1262
+ __privateGet(this, _badge).classList.remove("visible");
1263
+ }
1264
+ };
1265
+ function registerNexvioChatbot(tagName = "nexvio-chat-bot") {
1266
+ if (typeof customElements === "undefined") return;
1267
+ if (!customElements.get(tagName)) {
1268
+ customElements.define(tagName, NexvioChatbotElement);
1269
+ }
1270
+ }
1271
+
1272
+ // src/index.ts
1273
+ if (typeof window !== "undefined") {
1274
+ registerNexvioWidget();
1275
+ registerNexvioChatbot();
1276
+ }
1277
+ // Annotate the CommonJS export names for ESM import in node:
1278
+ 0 && (module.exports = {
1279
+ NexvioChatbotElement,
1280
+ NexvioWidgetElement,
1281
+ registerNexvioChatbot,
1282
+ registerNexvioWidget
1283
+ });
1284
+ //# sourceMappingURL=index.cjs.map