@crestapps/ai-chat-ui 1.0.0-preview.9 → 1.0.0-preview.90

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.
@@ -0,0 +1,814 @@
1
+ /*
2
+ ** NOTE: This file is generated by Gulp and should not be edited directly!
3
+ ** Any changes made directly to this file will be overwritten next time its asset group is processed by Gulp.
4
+ */
5
+
6
+ function clampWidgetValue(value, min, max) {
7
+ return Math.min(Math.max(value, min), max);
8
+ }
9
+ window.openAIChatWidgetBehavior = window.openAIChatWidgetBehavior || function () {
10
+ function parsePixelValue(value) {
11
+ if (typeof value === 'number' && Number.isFinite(value)) {
12
+ return value;
13
+ }
14
+ if (typeof value !== 'string') {
15
+ return null;
16
+ }
17
+ var parsed = parseFloat(value);
18
+ return Number.isFinite(parsed) ? parsed : null;
19
+ }
20
+ function attach(app, config) {
21
+ if (!app || app.__aiChatWidgetAttached) {
22
+ return;
23
+ }
24
+ app.__aiChatWidgetAttached = true;
25
+ app.chatWidgetStateName = null;
26
+ app.chatWidgetStateSession = null;
27
+ app.chatWidgetStateDocuments = null;
28
+ app.chatWidgetLayoutKey = null;
29
+ app.chatHistorySection = null;
30
+ app.widgetContainerElement = null;
31
+ app.widgetToggleButtonElement = null;
32
+ app.widgetResetSizeButtonElement = null;
33
+ app.widgetResizeObserver = null;
34
+ app.widgetViewportResizeHandler = null;
35
+ app.widgetDefaultWidth = null;
36
+ app.widgetDefaultHeight = null;
37
+ app.widgetIsInitialized = false;
38
+ app.getStoredWidgetLayout = function () {
39
+ if (!this.chatWidgetLayoutKey || !config.widget.persistLayout) {
40
+ return {};
41
+ }
42
+ try {
43
+ var storedLayout = localStorage.getItem(this.chatWidgetLayoutKey);
44
+ return storedLayout ? JSON.parse(storedLayout) || {} : {};
45
+ } catch (error) {
46
+ console.warn('Failed to read widget layout state.', error);
47
+ return {};
48
+ }
49
+ };
50
+ app.saveStoredWidgetLayout = function (partialLayout) {
51
+ if (!this.chatWidgetLayoutKey || !config.widget.persistLayout) {
52
+ return;
53
+ }
54
+ var currentLayout = this.getStoredWidgetLayout();
55
+ var nextLayout = Object.assign({}, currentLayout);
56
+ if (partialLayout.panel !== undefined) {
57
+ nextLayout.panel = Object.assign({}, currentLayout.panel || {}, partialLayout.panel || {});
58
+ }
59
+ if (partialLayout.position !== undefined) {
60
+ nextLayout.position = Object.assign({}, currentLayout.position || {}, partialLayout.position || {});
61
+ }
62
+ localStorage.setItem(this.chatWidgetLayoutKey, JSON.stringify(nextLayout));
63
+ };
64
+ app.getElementSize = function (element, fallbackWidth, fallbackHeight) {
65
+ if (!element) {
66
+ return {
67
+ width: fallbackWidth || 0,
68
+ height: fallbackHeight || 0
69
+ };
70
+ }
71
+ var rect = element.getBoundingClientRect();
72
+ var computed = window.getComputedStyle(element);
73
+ return {
74
+ width: Math.round(rect.width || parsePixelValue(computed.width) || fallbackWidth || 0),
75
+ height: Math.round(rect.height || parsePixelValue(computed.height) || fallbackHeight || 0)
76
+ };
77
+ };
78
+ app.getElementPosition = function (element) {
79
+ if (!element) {
80
+ return {
81
+ left: 0,
82
+ top: 0
83
+ };
84
+ }
85
+ var rect = element.getBoundingClientRect();
86
+ var computed = window.getComputedStyle(element);
87
+ var inlineLeft = parsePixelValue(element.style.left);
88
+ var inlineTop = parsePixelValue(element.style.top);
89
+ var computedLeft = parsePixelValue(computed.left);
90
+ var computedTop = parsePixelValue(computed.top);
91
+ var isHidden = computed.display === 'none';
92
+ return {
93
+ left: Math.round(isHidden && Number.isFinite(inlineLeft) ? inlineLeft : rect.left || inlineLeft || computedLeft || 0),
94
+ top: Math.round(isHidden && Number.isFinite(inlineTop) ? inlineTop : rect.top || inlineTop || computedTop || 0)
95
+ };
96
+ };
97
+ app.getAvailableWidgetPositionRange = function (width, height) {
98
+ var viewportPadding = 8;
99
+ return {
100
+ padding: viewportPadding,
101
+ maxLeft: Math.max(viewportPadding, window.innerWidth - width - viewportPadding),
102
+ maxTop: Math.max(viewportPadding, window.innerHeight - height - viewportPadding)
103
+ };
104
+ };
105
+ app.createStoredPosition = function (left, top, width, height) {
106
+ var range = this.getAvailableWidgetPositionRange(width, height);
107
+ var leftSpan = Math.max(0, range.maxLeft - range.padding);
108
+ var topSpan = Math.max(0, range.maxTop - range.padding);
109
+ return {
110
+ left: Math.round(left),
111
+ top: Math.round(top),
112
+ leftRatio: leftSpan === 0 ? 0 : (left - range.padding) / leftSpan,
113
+ topRatio: topSpan === 0 ? 0 : (top - range.padding) / topSpan
114
+ };
115
+ };
116
+ app.resolveStoredPosition = function (storedPosition, width, height) {
117
+ if (!storedPosition) {
118
+ return null;
119
+ }
120
+ var range = this.getAvailableWidgetPositionRange(width, height);
121
+ var left = Number(storedPosition.left);
122
+ var top = Number(storedPosition.top);
123
+ var leftRatio = Number(storedPosition.leftRatio);
124
+ var topRatio = Number(storedPosition.topRatio);
125
+ if (Number.isFinite(leftRatio)) {
126
+ left = range.padding + Math.max(0, range.maxLeft - range.padding) * leftRatio;
127
+ }
128
+ if (Number.isFinite(topRatio)) {
129
+ top = range.padding + Math.max(0, range.maxTop - range.padding) * topRatio;
130
+ }
131
+ if (!Number.isFinite(left) || !Number.isFinite(top)) {
132
+ return null;
133
+ }
134
+ return this.clampWidgetPosition(left, top, width, height);
135
+ };
136
+ app.clampWidgetPosition = function (left, top, width, height) {
137
+ var range = this.getAvailableWidgetPositionRange(width, height);
138
+ return {
139
+ left: Math.round(clampWidgetValue(left, range.padding, range.maxLeft)),
140
+ top: Math.round(clampWidgetValue(top, range.padding, range.maxTop))
141
+ };
142
+ };
143
+ app.getStoredWidgetDocuments = function () {
144
+ this.clearStoredWidgetDocuments();
145
+ return [];
146
+ };
147
+ app.saveStoredWidgetDocuments = function () {
148
+ this.clearStoredWidgetDocuments();
149
+ };
150
+ app.clearStoredWidgetDocuments = function () {
151
+ if (!this.chatWidgetStateDocuments) {
152
+ return;
153
+ }
154
+ localStorage.removeItem(this.chatWidgetStateDocuments);
155
+ };
156
+ app.applyAbsolutePosition = function (element, left, top) {
157
+ if (!element) {
158
+ return;
159
+ }
160
+ element.style.left = left + 'px';
161
+ element.style.top = top + 'px';
162
+ element.style.right = 'auto';
163
+ element.style.bottom = 'auto';
164
+ };
165
+ app.getWidgetDefaultSize = function () {
166
+ return {
167
+ width: this.widgetDefaultWidth || parsePixelValue(config.widget.defaultWidth) || 380,
168
+ height: this.widgetDefaultHeight || parsePixelValue(config.widget.defaultHeight) || 520
169
+ };
170
+ };
171
+ app.getWidgetToggleGap = function () {
172
+ return 8;
173
+ };
174
+ app.isWidgetPanelVisible = function () {
175
+ if (!this.widgetContainerElement) {
176
+ return false;
177
+ }
178
+ var computed = window.getComputedStyle(this.widgetContainerElement);
179
+ return this.widgetContainerElement.classList.contains('open') && computed.display !== 'none';
180
+ };
181
+ app.persistWidgetPanelPosition = function () {
182
+ if (!this.widgetContainerElement || !config.widget.persistLayout) {
183
+ return;
184
+ }
185
+ var panelDefaultSize = this.getWidgetDefaultSize();
186
+ var panelPosition = this.getElementPosition(this.widgetContainerElement);
187
+ var panelSize = this.getElementSize(this.widgetContainerElement, panelDefaultSize.width, panelDefaultSize.height);
188
+ var toggleSize = this.getElementSize(this.widgetToggleButtonElement, 52, 52);
189
+ var linkedPosition = this.clampWidgetPosition(panelPosition.left + panelSize.width - toggleSize.width, panelPosition.top + panelSize.height + this.getWidgetToggleGap(), toggleSize.width, toggleSize.height);
190
+ this.saveStoredWidgetLayout({
191
+ position: this.createStoredPosition(linkedPosition.left, linkedPosition.top, toggleSize.width, toggleSize.height)
192
+ });
193
+ };
194
+ app.persistWidgetTogglePosition = function () {
195
+ if (!this.widgetToggleButtonElement || !config.widget.persistLayout) {
196
+ return;
197
+ }
198
+ var togglePosition = this.getElementPosition(this.widgetToggleButtonElement);
199
+ var toggleSize = this.getElementSize(this.widgetToggleButtonElement, 52, 52);
200
+ this.saveStoredWidgetLayout({
201
+ position: this.createStoredPosition(togglePosition.left, togglePosition.top, toggleSize.width, toggleSize.height)
202
+ });
203
+ };
204
+ app.persistWidgetPanelSize = function () {
205
+ if (!this.widgetContainerElement || !config.widget.enableResizing || !config.widget.persistLayout) {
206
+ return;
207
+ }
208
+ var defaultSize = this.getWidgetDefaultSize();
209
+ var currentSize = this.getElementSize(this.widgetContainerElement, defaultSize.width, defaultSize.height);
210
+ this.saveStoredWidgetLayout({
211
+ panel: {
212
+ width: Math.abs(currentSize.width - defaultSize.width) <= 1 ? null : currentSize.width,
213
+ height: Math.abs(currentSize.height - defaultSize.height) <= 1 ? null : currentSize.height
214
+ }
215
+ });
216
+ };
217
+ app.syncTogglePositionToPanel = function (persistLayout) {
218
+ if (persistLayout === undefined) {
219
+ persistLayout = true;
220
+ }
221
+ if (!this.widgetContainerElement || !this.widgetToggleButtonElement) {
222
+ return;
223
+ }
224
+ var panelDefaultSize = this.getWidgetDefaultSize();
225
+ var panelSize = this.getElementSize(this.widgetContainerElement, panelDefaultSize.width, panelDefaultSize.height);
226
+ var toggleSize = this.getElementSize(this.widgetToggleButtonElement, 52, 52);
227
+ var panelPosition = this.getElementPosition(this.widgetContainerElement);
228
+ var linkedPosition = this.clampWidgetPosition(panelPosition.left + panelSize.width - toggleSize.width, panelPosition.top + panelSize.height + this.getWidgetToggleGap(), toggleSize.width, toggleSize.height);
229
+ this.applyAbsolutePosition(this.widgetToggleButtonElement, linkedPosition.left, linkedPosition.top);
230
+ if (persistLayout && config.widget.persistLayout) {
231
+ this.persistWidgetTogglePosition();
232
+ }
233
+ };
234
+ app.syncPanelPositionToToggle = function (persistLayout) {
235
+ if (persistLayout === undefined) {
236
+ persistLayout = true;
237
+ }
238
+ if (!this.widgetContainerElement || !this.widgetToggleButtonElement) {
239
+ return;
240
+ }
241
+ var panelDefaultSize = this.getWidgetDefaultSize();
242
+ var panelSize = this.getElementSize(this.widgetContainerElement, panelDefaultSize.width, panelDefaultSize.height);
243
+ var toggleSize = this.getElementSize(this.widgetToggleButtonElement, 52, 52);
244
+ var togglePosition = this.getElementPosition(this.widgetToggleButtonElement);
245
+ var linkedPosition = this.clampWidgetPosition(togglePosition.left + toggleSize.width - panelSize.width, togglePosition.top - panelSize.height - this.getWidgetToggleGap(), panelSize.width, panelSize.height);
246
+ this.applyAbsolutePosition(this.widgetContainerElement, linkedPosition.left, linkedPosition.top);
247
+ if (persistLayout && config.widget.persistLayout) {
248
+ this.persistWidgetPanelPosition();
249
+ }
250
+ };
251
+ app.updateWidgetResetSizeButtonVisibility = function () {
252
+ if (!this.widgetResetSizeButtonElement) {
253
+ return;
254
+ }
255
+ if (!config.widget.enableResizing || !this.widgetContainerElement) {
256
+ this.widgetResetSizeButtonElement.classList.add('d-none');
257
+ return;
258
+ }
259
+ var defaultSize = this.getWidgetDefaultSize();
260
+ var currentSize = this.getElementSize(this.widgetContainerElement, defaultSize.width, defaultSize.height);
261
+ var isResized = Math.abs(currentSize.width - defaultSize.width) > 1 || Math.abs(currentSize.height - defaultSize.height) > 1 || !!this.widgetContainerElement.style.width || !!this.widgetContainerElement.style.height;
262
+ this.widgetResetSizeButtonElement.classList.toggle('d-none', !isResized);
263
+ };
264
+ app.resetWidgetSize = function () {
265
+ if (!this.widgetContainerElement || !config.widget.enableResizing) {
266
+ return;
267
+ }
268
+ this.widgetContainerElement.style.removeProperty('width');
269
+ this.widgetContainerElement.style.removeProperty('height');
270
+ this.persistWidgetPanelSize();
271
+ this.constrainWidgetElementsToViewport();
272
+ this.updateWidgetResetSizeButtonVisibility();
273
+ };
274
+ app.restoreWidgetLayout = function () {
275
+ var storedLayout = this.getStoredWidgetLayout();
276
+ if (this.widgetContainerElement && config.widget.enableResizing) {
277
+ if (Number.isFinite(storedLayout.panel && storedLayout.panel.width)) {
278
+ this.widgetContainerElement.style.width = storedLayout.panel.width + 'px';
279
+ } else {
280
+ this.widgetContainerElement.style.removeProperty('width');
281
+ }
282
+ if (Number.isFinite(storedLayout.panel && storedLayout.panel.height)) {
283
+ this.widgetContainerElement.style.height = storedLayout.panel.height + 'px';
284
+ } else {
285
+ this.widgetContainerElement.style.removeProperty('height');
286
+ }
287
+ }
288
+ var toggleSize = this.getElementSize(this.widgetToggleButtonElement, 52, 52);
289
+ var storedTogglePosition = this.resolveStoredPosition(storedLayout.position, toggleSize.width, toggleSize.height);
290
+ if (this.widgetToggleButtonElement && config.widget.enableDragging && storedTogglePosition) {
291
+ this.applyAbsolutePosition(this.widgetToggleButtonElement, storedTogglePosition.left, storedTogglePosition.top);
292
+ this.syncPanelPositionToToggle(false);
293
+ } else if (this.widgetToggleButtonElement && config.widget.enableDragging && Number.isFinite(storedLayout.toggle && storedLayout.toggle.left) && Number.isFinite(storedLayout.toggle && storedLayout.toggle.top)) {
294
+ this.applyAbsolutePosition(this.widgetToggleButtonElement, storedLayout.toggle.left, storedLayout.toggle.top);
295
+ this.syncPanelPositionToToggle(false);
296
+ } else if (this.widgetContainerElement && config.widget.enableDragging && Number.isFinite(storedLayout.panel && storedLayout.panel.left) && Number.isFinite(storedLayout.panel && storedLayout.panel.top)) {
297
+ this.applyAbsolutePosition(this.widgetContainerElement, storedLayout.panel.left, storedLayout.panel.top);
298
+ this.syncTogglePositionToPanel(false);
299
+ }
300
+ this.constrainWidgetElementsToViewport();
301
+ this.updateWidgetResetSizeButtonVisibility();
302
+ };
303
+ app.attachDraggableWidgetElement = function (element, handle, layoutKey, suppressClickOnDrag) {
304
+ if (!element || !handle || !config.widget.enableDragging) {
305
+ return;
306
+ }
307
+ var activePointerId = null;
308
+ var startX = 0;
309
+ var startY = 0;
310
+ var startLeft = 0;
311
+ var startTop = 0;
312
+ var dragged = false;
313
+ var dragThreshold = 4;
314
+ var interactiveSelector = 'button, a, input, textarea, select, option, label';
315
+ var self = this;
316
+ function stopDragging(event) {
317
+ if (activePointerId === null) {
318
+ return;
319
+ }
320
+ if (event && event.pointerId !== undefined && event.pointerId !== activePointerId) {
321
+ return;
322
+ }
323
+ document.removeEventListener('pointermove', onPointerMove);
324
+ document.removeEventListener('pointerup', stopDragging);
325
+ document.removeEventListener('pointercancel', stopDragging);
326
+ element.classList.remove('ai-chat-widget-dragging');
327
+ activePointerId = null;
328
+ if (!dragged) {
329
+ return;
330
+ }
331
+ if (layoutKey === 'panel') {
332
+ self.syncTogglePositionToPanel(false);
333
+ self.persistWidgetPanelPosition();
334
+ } else if (layoutKey === 'toggle') {
335
+ self.syncPanelPositionToToggle(false);
336
+ self.persistWidgetTogglePosition();
337
+ }
338
+ if (config.widget.persistLayout) {
339
+ self.persistWidgetPanelPosition();
340
+ self.persistWidgetTogglePosition();
341
+ }
342
+ if (suppressClickOnDrag) {
343
+ element.dataset.dragSuppressClick = 'true';
344
+ window.setTimeout(function () {
345
+ if (element.dataset.dragSuppressClick === 'true') {
346
+ element.dataset.dragSuppressClick = 'false';
347
+ }
348
+ }, 0);
349
+ }
350
+ }
351
+ function onPointerMove(event) {
352
+ if (activePointerId === null || event.pointerId !== activePointerId) {
353
+ return;
354
+ }
355
+ var deltaX = event.clientX - startX;
356
+ var deltaY = event.clientY - startY;
357
+ if (!dragged && Math.hypot(deltaX, deltaY) < dragThreshold) {
358
+ return;
359
+ }
360
+ dragged = true;
361
+ var defaultSize = self.getWidgetDefaultSize();
362
+ var currentSize = self.getElementSize(element, layoutKey === 'panel' ? defaultSize.width : 52, layoutKey === 'panel' ? defaultSize.height : 52);
363
+ var nextPosition = self.clampWidgetPosition(startLeft + deltaX, startTop + deltaY, currentSize.width, currentSize.height);
364
+ self.applyAbsolutePosition(element, nextPosition.left, nextPosition.top);
365
+ if (layoutKey === 'panel') {
366
+ self.syncTogglePositionToPanel(false);
367
+ } else if (layoutKey === 'toggle') {
368
+ self.syncPanelPositionToToggle(false);
369
+ }
370
+ }
371
+ handle.addEventListener('pointerdown', function (event) {
372
+ if (event.button !== 0) {
373
+ return;
374
+ }
375
+ if (layoutKey === 'panel' && event.target.closest(interactiveSelector)) {
376
+ return;
377
+ }
378
+ var rect = element.getBoundingClientRect();
379
+ startX = event.clientX;
380
+ startY = event.clientY;
381
+ startLeft = rect.left;
382
+ startTop = rect.top;
383
+ dragged = false;
384
+ activePointerId = event.pointerId;
385
+ element.classList.add('ai-chat-widget-dragging');
386
+ if (handle.setPointerCapture) {
387
+ handle.setPointerCapture(event.pointerId);
388
+ }
389
+ document.addEventListener('pointermove', onPointerMove);
390
+ document.addEventListener('pointerup', stopDragging);
391
+ document.addEventListener('pointercancel', stopDragging);
392
+ event.preventDefault();
393
+ });
394
+ };
395
+ app.constrainWidgetElementsToViewport = function () {
396
+ if (this.widgetContainerElement && this.widgetContainerElement.style.left && this.isWidgetPanelVisible()) {
397
+ var panelDefaultSize = this.getWidgetDefaultSize();
398
+ var panelSize = this.getElementSize(this.widgetContainerElement, panelDefaultSize.width, panelDefaultSize.height);
399
+ var panelPosition = this.getElementPosition(this.widgetContainerElement);
400
+ var clampedPanel = this.clampWidgetPosition(panelPosition.left, panelPosition.top, panelSize.width, panelSize.height);
401
+ this.applyAbsolutePosition(this.widgetContainerElement, clampedPanel.left, clampedPanel.top);
402
+ this.syncTogglePositionToPanel(false);
403
+ if (config.widget.persistLayout) {
404
+ this.persistWidgetPanelPosition();
405
+ this.persistWidgetTogglePosition();
406
+ }
407
+ } else if (this.widgetToggleButtonElement && this.widgetToggleButtonElement.style.left) {
408
+ var toggleSize = this.getElementSize(this.widgetToggleButtonElement, 52, 52);
409
+ var togglePosition = this.getElementPosition(this.widgetToggleButtonElement);
410
+ var clampedToggle = this.clampWidgetPosition(togglePosition.left, togglePosition.top, toggleSize.width, toggleSize.height);
411
+ this.applyAbsolutePosition(this.widgetToggleButtonElement, clampedToggle.left, clampedToggle.top);
412
+ this.syncPanelPositionToToggle(false);
413
+ if (config.widget.persistLayout) {
414
+ this.persistWidgetTogglePosition();
415
+ this.persistWidgetPanelPosition();
416
+ }
417
+ }
418
+ };
419
+ app.showChatScreen = function () {
420
+ if (!this.chatHistorySection) {
421
+ return;
422
+ }
423
+ this.chatHistorySection.classList.remove('show');
424
+ };
425
+ }
426
+ function initialize(app, config) {
427
+ if (!app || app.widgetIsInitialized) {
428
+ return;
429
+ }
430
+ if (!config.widget.chatWidgetContainer) {
431
+ console.error('The widget chatWidgetContainer is required.');
432
+ return;
433
+ }
434
+ if (!config.widget.chatWidgetStateName) {
435
+ console.error('The widget chatWidgetStateName is required.');
436
+ return;
437
+ }
438
+ var chatWidgetContainer = document.querySelector(config.widget.chatWidgetContainer);
439
+ if (!chatWidgetContainer) {
440
+ return;
441
+ }
442
+ if (config.widget.chatHistorySection) {
443
+ app.chatHistorySection = document.querySelector(config.widget.chatHistorySection);
444
+ }
445
+ app.chatWidgetStateName = config.widget.chatWidgetStateName;
446
+ app.chatWidgetStateSession = config.widget.chatWidgetStateName + 'Session';
447
+ app.chatWidgetStateDocuments = config.widget.chatWidgetStateName + 'Documents';
448
+ app.chatWidgetLayoutKey = config.widget.chatWidgetStateName + 'Layout';
449
+ app.widgetContainerElement = chatWidgetContainer;
450
+ app.widgetToggleButtonElement = config.widget.toggleButtonSelector ? document.querySelector(config.widget.toggleButtonSelector) : null;
451
+ app.widgetResetSizeButtonElement = config.widget.resetSizeButtonSelector ? document.querySelector(config.widget.resetSizeButtonSelector) : null;
452
+ app.widgetDefaultWidth = parsePixelValue(config.widget.defaultWidth) || parsePixelValue(window.getComputedStyle(chatWidgetContainer).width) || 380;
453
+ app.widgetDefaultHeight = parsePixelValue(config.widget.defaultHeight) || parsePixelValue(window.getComputedStyle(chatWidgetContainer).height) || 520;
454
+ app.widgetIsInitialized = true;
455
+ app.clearStoredWidgetDocuments();
456
+ app.documents = [];
457
+ if (config.widget.enableResizing) {
458
+ chatWidgetContainer.classList.add('ai-chat-widget-resizable');
459
+ chatWidgetContainer.style.minWidth = (parsePixelValue(config.widget.minWidth) || 320) + 'px';
460
+ chatWidgetContainer.style.minHeight = (parsePixelValue(config.widget.minHeight) || 420) + 'px';
461
+ if (typeof ResizeObserver !== 'undefined') {
462
+ app.widgetResizeObserver = new ResizeObserver(function () {
463
+ app.persistWidgetPanelSize();
464
+ app.constrainWidgetElementsToViewport();
465
+ app.updateWidgetResetSizeButtonVisibility();
466
+ });
467
+ app.widgetResizeObserver.observe(chatWidgetContainer);
468
+ }
469
+ }
470
+ var dragHandleSelector = config.widget.dragHandleSelector || '.ai-chat-widget-header';
471
+ var dragHandle = chatWidgetContainer.querySelector(dragHandleSelector);
472
+ if (config.widget.enableDragging && dragHandle) {
473
+ dragHandle.classList.add('ai-chat-widget-drag-handle');
474
+ chatWidgetContainer.classList.add('ai-chat-widget-draggable');
475
+ app.attachDraggableWidgetElement(chatWidgetContainer, dragHandle, 'panel', false);
476
+ }
477
+ if (config.widget.enableDragging && app.widgetToggleButtonElement) {
478
+ app.widgetToggleButtonElement.classList.add('ai-chat-widget-draggable');
479
+ app.attachDraggableWidgetElement(app.widgetToggleButtonElement, app.widgetToggleButtonElement, 'toggle', true);
480
+ }
481
+ if (app.widgetResetSizeButtonElement) {
482
+ app.widgetResetSizeButtonElement.addEventListener('click', function (event) {
483
+ event.preventDefault();
484
+ app.resetWidgetSize();
485
+ });
486
+ }
487
+ app.restoreWidgetLayout();
488
+ if (!app.widgetViewportResizeHandler) {
489
+ app.widgetViewportResizeHandler = function () {
490
+ if (config.widget.persistLayout) {
491
+ app.restoreWidgetLayout();
492
+ } else {
493
+ app.constrainWidgetElementsToViewport();
494
+ }
495
+ app.updateWidgetResetSizeButtonVisibility();
496
+ };
497
+ window.addEventListener('resize', app.widgetViewportResizeHandler);
498
+ }
499
+ app.reloadCurrentSession();
500
+ if (config.autoCreateSession && !app.getSessionId()) {
501
+ app.startNewSession();
502
+ }
503
+ if (config.widget.showHistoryButton && app.chatHistorySection) {
504
+ var showHistoryButton = document.querySelector(config.widget.showHistoryButton);
505
+ if (showHistoryButton) {
506
+ showHistoryButton.addEventListener('click', function () {
507
+ app.chatHistorySection.classList.toggle('show');
508
+ });
509
+ }
510
+ if (config.widget.closeHistoryButton) {
511
+ var closeHistoryButton = document.querySelector(config.widget.closeHistoryButton);
512
+ if (closeHistoryButton) {
513
+ closeHistoryButton.addEventListener('click', function () {
514
+ app.showChatScreen();
515
+ });
516
+ }
517
+ }
518
+ }
519
+ if (config.widget.newChatButton) {
520
+ var newChatButton = document.querySelector(config.widget.newChatButton);
521
+ if (newChatButton) {
522
+ newChatButton.addEventListener('click', function () {
523
+ app.resetSession();
524
+ app.showChatScreen();
525
+ });
526
+ }
527
+ }
528
+ }
529
+ function resolveSessionId(app) {
530
+ if (!app || !app.widgetIsInitialized) {
531
+ return null;
532
+ }
533
+ return localStorage.getItem(app.chatWidgetStateSession);
534
+ }
535
+ function onSessionInitialized(app, sessionId) {
536
+ if (app && app.widgetIsInitialized) {
537
+ localStorage.setItem(app.chatWidgetStateSession, sessionId);
538
+ }
539
+ }
540
+ function onSessionReset(app) {
541
+ if (app && app.widgetIsInitialized) {
542
+ localStorage.removeItem(app.chatWidgetStateSession);
543
+ app.clearStoredWidgetDocuments();
544
+ }
545
+ }
546
+ function onDocumentsChanged(app, documents) {
547
+ if (app && app.widgetIsInitialized) {
548
+ app.saveStoredWidgetDocuments(documents);
549
+ }
550
+ }
551
+ function handleReceiveError(app) {
552
+ if (app && app.widgetIsInitialized && !app.isSessionStarted && !app._attemptedSessionRecovery) {
553
+ app._attemptedSessionRecovery = true;
554
+ localStorage.removeItem(app.chatWidgetStateSession);
555
+ app.clearStoredWidgetDocuments();
556
+ app.startNewSession();
557
+ }
558
+ }
559
+ function dispose(app) {
560
+ if (!app) {
561
+ return;
562
+ }
563
+ if (app.widgetResizeObserver) {
564
+ app.widgetResizeObserver.disconnect();
565
+ app.widgetResizeObserver = null;
566
+ }
567
+ if (app.widgetViewportResizeHandler) {
568
+ window.removeEventListener('resize', app.widgetViewportResizeHandler);
569
+ app.widgetViewportResizeHandler = null;
570
+ }
571
+ }
572
+ return {
573
+ attach: attach,
574
+ initialize: initialize,
575
+ onMounted: initialize,
576
+ resolveSessionId: resolveSessionId,
577
+ onSessionInitialized: onSessionInitialized,
578
+ onSessionReset: onSessionReset,
579
+ onDocumentsChanged: onDocumentsChanged,
580
+ handleReceiveError: handleReceiveError,
581
+ dispose: dispose,
582
+ onBeforeUnmount: dispose
583
+ };
584
+ }();
585
+ window.openAIChatWidgetManager = window.openAIChatWidgetManager || function () {
586
+ function initialize(options) {
587
+ if (!options) {
588
+ return null;
589
+ }
590
+ var chatConfig = options.chatConfig;
591
+ if (!chatConfig && options.configElementSelector) {
592
+ var configElement = document.querySelector(options.configElementSelector);
593
+ chatConfig = configElement ? JSON.parse(configElement.getAttribute('data-config')) : null;
594
+ }
595
+ if (!chatConfig) {
596
+ return null;
597
+ }
598
+ if (options.messageTemplateSelector) {
599
+ var messageTemplate = document.querySelector(options.messageTemplateSelector);
600
+ if (messageTemplate) {
601
+ chatConfig.messageTemplate = messageTemplate.innerHTML;
602
+ }
603
+ }
604
+ if (options.indicatorTemplateSelector) {
605
+ var indicatorTemplate = document.querySelector(options.indicatorTemplateSelector);
606
+ if (indicatorTemplate) {
607
+ chatConfig.indicatorTemplate = indicatorTemplate.innerHTML;
608
+ }
609
+ }
610
+ var shell = document.querySelector(options.shellSelector);
611
+ var widgetContainer = document.querySelector(options.widgetContainerSelector);
612
+ var toggleButton = document.querySelector(options.toggleButtonSelector);
613
+ var closeButton = document.querySelector(options.closeButtonSelector);
614
+ var profileInput = options.inputSelector ? document.querySelector(options.inputSelector) : null;
615
+ var widgetStateName = options.widgetStateName || chatConfig.widget.chatWidgetStateName;
616
+ var widgetOpenStateKey = options.widgetOpenStateKey || widgetStateName + 'Open';
617
+ var widgetLayoutKey = widgetStateName + 'Layout';
618
+ var openStateValue = options.openStateValue || 'open';
619
+ var closedStateValue = options.closedStateValue || 'closed';
620
+ if (profileInput && options.profile && options.profile.id) {
621
+ profileInput.setAttribute('data-profile-id', options.profile.id);
622
+ }
623
+ try {
624
+ var storedLayout = localStorage.getItem(widgetLayoutKey);
625
+ var layout = storedLayout ? JSON.parse(storedLayout) || {} : {};
626
+ var position = layout.position || {};
627
+ var panelLayout = layout.panel || {};
628
+ var toggleLeft = Number(position.left);
629
+ var toggleTop = Number(position.top);
630
+ var isOpen = localStorage.getItem(widgetOpenStateKey) === openStateValue;
631
+ var viewportPadding = 8;
632
+ if (shell) {
633
+ shell.dataset.deferReveal = isOpen ? 'true' : 'false';
634
+ shell.dataset.initialOpen = isOpen ? 'true' : 'false';
635
+ }
636
+ if (widgetContainer && toggleButton) {
637
+ var toggleSize = 52;
638
+ var panelWidth = Number.isFinite(Number(panelLayout.width)) ? Number(panelLayout.width) : Math.round(parseFloat(window.getComputedStyle(widgetContainer).width) || 380);
639
+ var panelHeight = Number.isFinite(Number(panelLayout.height)) ? Number(panelLayout.height) : Math.round(parseFloat(window.getComputedStyle(widgetContainer).height) || 520);
640
+ var maxLeft = Math.max(viewportPadding, window.innerWidth - toggleSize - viewportPadding);
641
+ var maxTop = Math.max(viewportPadding, window.innerHeight - toggleSize - viewportPadding);
642
+ if (Number.isFinite(Number(position.leftRatio))) {
643
+ toggleLeft = viewportPadding + Math.max(0, maxLeft - viewportPadding) * Number(position.leftRatio);
644
+ }
645
+ if (Number.isFinite(Number(position.topRatio))) {
646
+ toggleTop = viewportPadding + Math.max(0, maxTop - viewportPadding) * Number(position.topRatio);
647
+ }
648
+ if (Number.isFinite(toggleLeft) && Number.isFinite(toggleTop)) {
649
+ toggleLeft = Math.round(clampWidgetValue(toggleLeft, viewportPadding, maxLeft));
650
+ toggleTop = Math.round(clampWidgetValue(toggleTop, viewportPadding, maxTop));
651
+ }
652
+ if (Number.isFinite(toggleLeft) && Number.isFinite(toggleTop)) {
653
+ toggleButton.style.left = toggleLeft + 'px';
654
+ toggleButton.style.top = toggleTop + 'px';
655
+ toggleButton.style.right = 'auto';
656
+ toggleButton.style.bottom = 'auto';
657
+ var toggleGap = 8;
658
+ widgetContainer.style.left = toggleLeft + toggleSize - panelWidth + 'px';
659
+ widgetContainer.style.top = toggleTop - panelHeight - toggleGap + 'px';
660
+ widgetContainer.style.right = 'auto';
661
+ widgetContainer.style.bottom = 'auto';
662
+ }
663
+ }
664
+ if (widgetContainer) {
665
+ widgetContainer.classList.remove('open');
666
+ widgetContainer.style.display = 'none';
667
+ widgetContainer.setAttribute('aria-hidden', 'true');
668
+ }
669
+ if (toggleButton) {
670
+ toggleButton.innerHTML = isOpen ? options.openIconHtml : options.closedIconHtml;
671
+ }
672
+ } catch (error) {
673
+ console.warn('Failed to restore widget layout before initialization.', error);
674
+ } finally {
675
+ if (shell && shell.dataset.deferReveal !== 'true') {
676
+ shell.style.visibility = '';
677
+ }
678
+ }
679
+ var widgetApp = window.openAIChatManager.initialize(chatConfig);
680
+ if (options.applySessionProfilePatch !== false && window.crestAppsAIChat && window.crestAppsAIChat.patchSessionProfileSync) {
681
+ window.crestAppsAIChat.patchSessionProfileSync(widgetApp);
682
+ }
683
+ function revealShell() {
684
+ if (!shell) {
685
+ return;
686
+ }
687
+ shell.style.visibility = '';
688
+ shell.dataset.deferReveal = 'false';
689
+ }
690
+ function syncOpenPanelPosition() {
691
+ if (!widgetApp || typeof widgetApp.syncPanelPositionToToggle !== 'function') {
692
+ return;
693
+ }
694
+ widgetApp.syncPanelPositionToToggle(false);
695
+ }
696
+ function updateTtsPlaybackButtons() {
697
+ if (!widgetContainer) {
698
+ return;
699
+ }
700
+ var buttons = widgetContainer.querySelectorAll('[data-tts-message-index]');
701
+ buttons.forEach(function (button) {
702
+ var buttonIndex = Number(button.getAttribute('data-tts-message-index'));
703
+ var isPlaying = buttonIndex === widgetApp.ttsPlayingMessageIndex;
704
+ button.classList.toggle('tts-playing', isPlaying);
705
+ button.setAttribute('title', isPlaying ? 'Pause audio' : 'Read aloud');
706
+ });
707
+ }
708
+ function queueTtsPlaybackButtonUpdate() {
709
+ requestAnimationFrame(updateTtsPlaybackButtons);
710
+ }
711
+ function revealShellWhenStable(initialOpen) {
712
+ if (!shell || shell.dataset.deferReveal !== 'true' || !initialOpen) {
713
+ revealShell();
714
+ return;
715
+ }
716
+ var hasRevealed = false;
717
+ var resizeObserver = null;
718
+ function finalizeReveal() {
719
+ if (hasRevealed) {
720
+ return;
721
+ }
722
+ hasRevealed = true;
723
+ if (resizeObserver) {
724
+ resizeObserver.disconnect();
725
+ }
726
+ requestAnimationFrame(function () {
727
+ syncOpenPanelPosition();
728
+ requestAnimationFrame(function () {
729
+ revealShell();
730
+ });
731
+ });
732
+ }
733
+ if (typeof ResizeObserver === 'undefined') {
734
+ window.setTimeout(finalizeReveal, 0);
735
+ return;
736
+ }
737
+ var lastWidth = 0;
738
+ var lastHeight = 0;
739
+ var stablePasses = 0;
740
+ resizeObserver = new ResizeObserver(function (entries) {
741
+ var entry = entries && entries[0];
742
+ if (!entry) {
743
+ return;
744
+ }
745
+ var width = Math.round(entry.contentRect.width);
746
+ var height = Math.round(entry.contentRect.height);
747
+ if (!width || !height) {
748
+ return;
749
+ }
750
+ syncOpenPanelPosition();
751
+ if (width === lastWidth && height === lastHeight) {
752
+ stablePasses++;
753
+ } else {
754
+ lastWidth = width;
755
+ lastHeight = height;
756
+ stablePasses = 0;
757
+ }
758
+ if (stablePasses >= 1) {
759
+ finalizeReveal();
760
+ }
761
+ });
762
+ resizeObserver.observe(widgetContainer);
763
+ window.setTimeout(finalizeReveal, 150);
764
+ }
765
+ function setWidgetOpen(isOpen) {
766
+ if (widgetApp) {
767
+ var isCurrentlyOpen = widgetContainer.classList.contains('open');
768
+ if (isOpen && !isCurrentlyOpen && typeof widgetApp.syncPanelPositionToToggle === 'function') {
769
+ widgetApp.syncPanelPositionToToggle();
770
+ } else if (!isOpen && isCurrentlyOpen && typeof widgetApp.syncTogglePositionToPanel === 'function') {
771
+ widgetApp.syncTogglePositionToPanel();
772
+ }
773
+ }
774
+ widgetContainer.classList.toggle('open', isOpen);
775
+ widgetContainer.style.display = isOpen ? 'flex' : 'none';
776
+ widgetContainer.setAttribute('aria-hidden', isOpen ? 'false' : 'true');
777
+ toggleButton.innerHTML = isOpen ? options.openIconHtml : options.closedIconHtml;
778
+ localStorage.setItem(widgetOpenStateKey, isOpen ? openStateValue : closedStateValue);
779
+ if (isOpen && typeof window.renderPendingCharts === 'function') {
780
+ setTimeout(function () {
781
+ window.renderPendingCharts();
782
+ }, 100);
783
+ }
784
+ }
785
+ var initialOpen = shell && shell.dataset.initialOpen === 'true';
786
+ setWidgetOpen(initialOpen);
787
+ revealShellWhenStable(initialOpen);
788
+ if (widgetApp && typeof widgetApp.$watch === 'function') {
789
+ widgetApp.$watch('ttsPlayingMessageIndex', function () {
790
+ queueTtsPlaybackButtonUpdate();
791
+ });
792
+ }
793
+ queueTtsPlaybackButtonUpdate();
794
+ if (toggleButton) {
795
+ toggleButton.addEventListener('click', function () {
796
+ if (toggleButton.dataset.dragSuppressClick === 'true') {
797
+ toggleButton.dataset.dragSuppressClick = 'false';
798
+ return;
799
+ }
800
+ setWidgetOpen(!widgetContainer.classList.contains('open'));
801
+ });
802
+ }
803
+ if (closeButton) {
804
+ closeButton.addEventListener('click', function () {
805
+ setWidgetOpen(false);
806
+ });
807
+ }
808
+ return widgetApp;
809
+ }
810
+ return {
811
+ initialize: initialize
812
+ };
813
+ }();
814
+ //# sourceMappingURL=ai-chat-widget.js.map