@crestapps/ai-chat-ui 1.0.0-preview.10 → 1.0.0-preview.11

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