@crestapps/ai-chat-ui 2.0.0-preview.203 → 2.0.0-preview.215

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,485 @@
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 _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t["return"] || t["return"](); } finally { if (u) throw o; } } }; }
7
+ function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
8
+ function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
9
+ /*
10
+ * Stacks the pictures a single answer shows one after another into one carousel.
11
+ *
12
+ * A tool that previews a document -- slides, sheets, pages -- hands back one figure marker per picture, all on a
13
+ * line of their own, and each one renders at full thumbnail size: eight slides is eight thumbnails running down
14
+ * the conversation. Here a run of two or more pictures with nothing but whitespace between them becomes a stack
15
+ * of cards instead: the current picture in front, its neighbours fanned out behind it, moved through by swiping,
16
+ * clicking a neighbour, the arrows, the dots or the arrow keys. A picture written mid-sentence keeps its place.
17
+ *
18
+ * It works on the sanitized HTML every chat surface already produces, so the surfaces share one implementation
19
+ * without sharing a renderer, and the carousel is written in the same pass as the message -- there is no frame
20
+ * of full-size pictures before they are gathered up. HTML with no such run is handed back exactly as it came.
21
+ *
22
+ * Loaded on its own, like chat-markers.js, and optional: a surface without it renders the pictures as before.
23
+ */
24
+ window.CoreAIChatImageCarousel = window.CoreAIChatImageCarousel || function () {
25
+ 'use strict';
26
+
27
+ var imageContainerClass = 'generated-image-container';
28
+
29
+ // How far a drag has to travel before it counts as a swipe rather than a click.
30
+ var swipeThreshold = 40;
31
+
32
+ // How far a drag has to travel before the card starts following the pointer.
33
+ var dragStartThreshold = 8;
34
+
35
+ // Cards further than this from the current one are stacked out of sight behind the last visible one.
36
+ var furthestVisibleOffset = 2;
37
+
38
+ // Anything that is content in its own right, so pictures either side of it are not one run.
39
+ var contentBetweenSelector = 'img, svg, canvas, video, audio, iframe, table, hr, input';
40
+ var previousIcon = '<svg viewBox="0 0 16 16" width="12" height="12" aria-hidden="true" focusable="false"><path d="M10 3 5 8l5 5" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path></svg>';
41
+ var nextIcon = '<svg viewBox="0 0 16 16" width="12" height="12" aria-hidden="true" focusable="false"><path d="m6 3 5 5-5 5" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path></svg>';
42
+
43
+ // How large the reader wants previews drawn. It is the reader's taste rather than the answer's, so one choice
44
+ // applies to every carousel on the page and is kept in the browser for the next visit.
45
+ var sizes = [{
46
+ name: 'small',
47
+ text: 'S',
48
+ label: 'Small previews'
49
+ }, {
50
+ name: 'medium',
51
+ text: 'M',
52
+ label: 'Medium previews'
53
+ }, {
54
+ name: 'large',
55
+ text: 'L',
56
+ label: 'Large previews'
57
+ }];
58
+ var defaultSize = 'medium';
59
+ var sizeStorageKey = 'coreai-image-carousel-size';
60
+
61
+ // A streamed answer is re-rendered on every chunk, and every render builds the carousel afresh. The picture
62
+ // the reader moved to is remembered here so the next render opens on it rather than back on the first.
63
+ var activeIndexByCarouselKey = new Map();
64
+ var drag = null;
65
+ var suppressNextClick = false;
66
+ function stackAdjacentImages(html) {
67
+ if (typeof document === 'undefined' || !html) {
68
+ return html;
69
+ }
70
+ var firstContainerIndex = html.indexOf(imageContainerClass);
71
+ if (firstContainerIndex < 0 || html.indexOf(imageContainerClass, firstContainerIndex + imageContainerClass.length) < 0) {
72
+ return html;
73
+ }
74
+ var template = document.createElement('template');
75
+ template.innerHTML = html;
76
+ var runs = findImageRuns(template.content);
77
+ if (runs.length === 0) {
78
+ return html;
79
+ }
80
+ var _iterator = _createForOfIteratorHelper(runs),
81
+ _step;
82
+ try {
83
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
84
+ var run = _step.value;
85
+ buildCarousel(run);
86
+ }
87
+ } catch (err) {
88
+ _iterator.e(err);
89
+ } finally {
90
+ _iterator.f();
91
+ }
92
+ return template.innerHTML;
93
+ }
94
+ function findImageRuns(root) {
95
+ var runs = [];
96
+ var run = [];
97
+ var _iterator2 = _createForOfIteratorHelper(root.querySelectorAll('.' + imageContainerClass)),
98
+ _step2;
99
+ try {
100
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
101
+ var container = _step2.value;
102
+ // Only a picture standing in a paragraph is gathered. One in a list, a table cell or a link belongs
103
+ // to that structure, and lifting it out would change what the answer says.
104
+ if (!container.parentElement || container.parentElement.tagName !== 'P') {
105
+ runs.push(run);
106
+ run = [];
107
+ continue;
108
+ }
109
+ if (run.length > 0 && !isOnlyWhitespaceBetween(run[run.length - 1], container)) {
110
+ runs.push(run);
111
+ run = [];
112
+ }
113
+ run.push(container);
114
+ }
115
+ } catch (err) {
116
+ _iterator2.e(err);
117
+ } finally {
118
+ _iterator2.f();
119
+ }
120
+ runs.push(run);
121
+ return runs.filter(function (candidate) {
122
+ return candidate.length > 1;
123
+ });
124
+ }
125
+
126
+ // Two pictures belong to one run when nothing a reader would read sits between them: spaces and line breaks
127
+ // within a paragraph, or the boundary between two paragraphs that hold nothing else.
128
+ function isOnlyWhitespaceBetween(previous, next) {
129
+ var range = previous.ownerDocument.createRange();
130
+ range.setStartAfter(previous);
131
+ range.setEndBefore(next);
132
+ var between = range.cloneContents();
133
+ return between.textContent.trim() === '' && !between.querySelector(contentBetweenSelector);
134
+ }
135
+ function buildCarousel(containers) {
136
+ var ownerDocument = containers[0].ownerDocument;
137
+ var firstParagraph = containers[0].parentElement;
138
+ var vacatedParagraphs = new Set();
139
+
140
+ // Spans throughout, for the same reason the picture's own wrapper is one: the carousel sits inside the
141
+ // paragraph the first picture was in, and a block element there would close that paragraph.
142
+ var carousel = createElement(ownerDocument, 'span', 'ai-image-carousel');
143
+ carousel.tabIndex = 0;
144
+ carousel.setAttribute('role', 'region');
145
+ carousel.setAttribute('aria-roledescription', 'carousel');
146
+ carousel.setAttribute('aria-label', "".concat(containers.length, " images"));
147
+ carousel.dataset.carouselKey = getCarouselKey(containers);
148
+ carousel.dataset.carouselSize = getPreferredSize();
149
+ var stage = createElement(ownerDocument, 'span', 'ai-image-carousel-stage');
150
+ var controls = createElement(ownerDocument, 'span', 'ai-image-carousel-controls');
151
+ var caption = createElement(ownerDocument, 'span', 'ai-image-carousel-caption');
152
+ var navigation = createElement(ownerDocument, 'span', 'ai-image-carousel-navigation');
153
+ var dots = createElement(ownerDocument, 'span', 'ai-image-carousel-dots');
154
+ caption.setAttribute('aria-live', 'polite');
155
+ containers[0].before(carousel);
156
+ containers.forEach(function (container, index) {
157
+ removeSeparatorsBefore(container);
158
+ if (container.parentElement !== firstParagraph) {
159
+ vacatedParagraphs.add(container.parentElement);
160
+ }
161
+ container.classList.add('ai-image-carousel-item');
162
+ var image = container.querySelector('img');
163
+
164
+ // The browser's own image drag would otherwise take over the pointer the moment a swipe starts.
165
+ if (image) {
166
+ image.setAttribute('draggable', 'false');
167
+ }
168
+ var dot = createElement(ownerDocument, 'button', 'ai-image-carousel-dot');
169
+ dot.type = 'button';
170
+ dot.dataset.carouselTarget = index;
171
+ dot.setAttribute('aria-label', "Show image ".concat(index + 1));
172
+ dots.appendChild(dot);
173
+ stage.appendChild(container);
174
+ });
175
+ navigation.append(createStepButton(ownerDocument, -1, 'Previous image', previousIcon), dots, createStepButton(ownerDocument, 1, 'Next image', nextIcon));
176
+ controls.append(caption, createSizePicker(ownerDocument, carousel.dataset.carouselSize), navigation);
177
+ carousel.append(stage, controls);
178
+ var _iterator3 = _createForOfIteratorHelper(vacatedParagraphs),
179
+ _step3;
180
+ try {
181
+ for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
182
+ var paragraph = _step3.value;
183
+ if (paragraph.textContent.trim() === '' && !paragraph.querySelector(contentBetweenSelector)) {
184
+ paragraph.remove();
185
+ }
186
+ }
187
+ } catch (err) {
188
+ _iterator3.e(err);
189
+ } finally {
190
+ _iterator3.f();
191
+ }
192
+ showImage(carousel, activeIndexByCarouselKey.get(carousel.dataset.carouselKey) || 0);
193
+ }
194
+
195
+ // Whatever separated this picture from the one before it -- a space, a line break -- is all that is left once
196
+ // the pictures have moved into the carousel, and it would otherwise trail the carousel as a blank line.
197
+ function removeSeparatorsBefore(container) {
198
+ var sibling = container.previousSibling;
199
+ while (sibling && (sibling.nodeType === Node.TEXT_NODE && sibling.textContent.trim() === '' || sibling.nodeName === 'BR')) {
200
+ var previousSibling = sibling.previousSibling;
201
+ sibling.remove();
202
+ sibling = previousSibling;
203
+ }
204
+ }
205
+
206
+ // Cheap rather than exact: a generated image can be a data URI hundreds of kilobytes long, so only the tail
207
+ // of the first address -- where a served document's identifier sits -- and the number of pictures are used.
208
+ function getCarouselKey(containers) {
209
+ var firstImage = containers[0].querySelector('img');
210
+ var firstSource = firstImage ? firstImage.getAttribute('src') || '' : '';
211
+ return "".concat(containers.length, ":").concat(firstSource.slice(-120));
212
+ }
213
+ function createElement(ownerDocument, tagName, className) {
214
+ var element = ownerDocument.createElement(tagName);
215
+ element.className = className;
216
+ return element;
217
+ }
218
+ function createStepButton(ownerDocument, step, label, icon) {
219
+ var button = createElement(ownerDocument, 'button', 'ai-image-carousel-button');
220
+ button.type = 'button';
221
+ button.dataset.carouselStep = step;
222
+ button.setAttribute('aria-label', label);
223
+ button.innerHTML = icon;
224
+ return button;
225
+ }
226
+
227
+ // A segmented S / M / L control.
228
+ function createSizePicker(ownerDocument, selectedSize) {
229
+ var picker = createElement(ownerDocument, 'span', 'ai-image-carousel-sizes');
230
+ picker.setAttribute('role', 'group');
231
+ picker.setAttribute('aria-label', 'Preview size');
232
+ var _iterator4 = _createForOfIteratorHelper(sizes),
233
+ _step4;
234
+ try {
235
+ for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
236
+ var size = _step4.value;
237
+ var button = createElement(ownerDocument, 'button', 'ai-image-carousel-size');
238
+ button.type = 'button';
239
+ button.title = size.label;
240
+ button.textContent = size.text;
241
+ button.dataset.carouselSizeOption = size.name;
242
+ button.setAttribute('aria-label', size.label);
243
+ button.setAttribute('aria-pressed', size.name === selectedSize ? 'true' : 'false');
244
+ picker.appendChild(button);
245
+ }
246
+ } catch (err) {
247
+ _iterator4.e(err);
248
+ } finally {
249
+ _iterator4.f();
250
+ }
251
+ return picker;
252
+ }
253
+
254
+ // Storage can be missing or refuse access -- a private window, blocked site data -- and the default is a fine
255
+ // answer then.
256
+ function getPreferredSize() {
257
+ try {
258
+ var storedSize = localStorage.getItem(sizeStorageKey);
259
+ return sizes.some(function (size) {
260
+ return size.name === storedSize;
261
+ }) ? storedSize : defaultSize;
262
+ } catch (_) {
263
+ return defaultSize;
264
+ }
265
+ }
266
+ function setPreferredSize(selectedSize) {
267
+ try {
268
+ localStorage.setItem(sizeStorageKey, selectedSize);
269
+ } catch (_) {
270
+ // Still applied to the page; only remembering it for the next visit is lost.
271
+ }
272
+ var _iterator5 = _createForOfIteratorHelper(document.querySelectorAll('.ai-image-carousel')),
273
+ _step5;
274
+ try {
275
+ for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
276
+ var carousel = _step5.value;
277
+ carousel.dataset.carouselSize = selectedSize;
278
+ }
279
+ } catch (err) {
280
+ _iterator5.e(err);
281
+ } finally {
282
+ _iterator5.f();
283
+ }
284
+ var _iterator6 = _createForOfIteratorHelper(document.querySelectorAll('[data-carousel-size-option]')),
285
+ _step6;
286
+ try {
287
+ for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) {
288
+ var button = _step6.value;
289
+ button.setAttribute('aria-pressed', button.dataset.carouselSizeOption === selectedSize ? 'true' : 'false');
290
+ }
291
+ } catch (err) {
292
+ _iterator6.e(err);
293
+ } finally {
294
+ _iterator6.f();
295
+ }
296
+ }
297
+ function getItems(carousel) {
298
+ return carousel.querySelectorAll('.ai-image-carousel-stage > .ai-image-carousel-item');
299
+ }
300
+ function getActiveIndex(carousel) {
301
+ return Number(carousel.dataset.activeIndex) || 0;
302
+ }
303
+ function showImage(carousel, requestedIndex) {
304
+ var items = getItems(carousel);
305
+ if (items.length === 0) {
306
+ carousel.remove();
307
+ return;
308
+ }
309
+ var activeIndex = Math.max(0, Math.min(items.length - 1, requestedIndex));
310
+ var dots = carousel.querySelector('.ai-image-carousel-dots');
311
+ while (dots.children.length > items.length) {
312
+ dots.lastElementChild.remove();
313
+ }
314
+ items.forEach(function (item, index) {
315
+ var offset = index - activeIndex;
316
+ var isActive = offset === 0;
317
+ var downloadLink = item.querySelector('a');
318
+ item.dataset.stackOffset = Math.max(-furthestVisibleOffset - 1, Math.min(furthestVisibleOffset + 1, offset));
319
+ item.classList.toggle('is-active', isActive);
320
+ item.setAttribute('aria-hidden', isActive ? 'false' : 'true');
321
+
322
+ // A card behind the current one is hidden from assistive technology, so nothing in it may take focus.
323
+ if (downloadLink) {
324
+ downloadLink.tabIndex = isActive ? 0 : -1;
325
+ }
326
+ dots.children[index].classList.toggle('is-active', isActive);
327
+ dots.children[index].setAttribute('aria-current', isActive ? 'true' : 'false');
328
+ });
329
+ var activeImage = items[activeIndex].querySelector('img');
330
+ var altText = activeImage ? activeImage.getAttribute('alt') : '';
331
+ carousel.dataset.activeIndex = activeIndex;
332
+ carousel.dataset.imageCount = items.length;
333
+ carousel.querySelector('[data-carousel-step="-1"]').disabled = activeIndex === 0;
334
+ carousel.querySelector('[data-carousel-step="1"]').disabled = activeIndex === items.length - 1;
335
+ carousel.querySelector('.ai-image-carousel-caption').textContent = altText ? "".concat(activeIndex + 1, " / ").concat(items.length, " \xB7 ").concat(altText) : "".concat(activeIndex + 1, " / ").concat(items.length);
336
+ activeIndexByCarouselKey.set(carousel.dataset.carouselKey, activeIndex);
337
+ }
338
+ function stopEvent(event) {
339
+ event.preventDefault();
340
+ event.stopPropagation();
341
+ }
342
+
343
+ // Captured, so it runs before anything bound to the picture itself: a card behind the current one is brought
344
+ // to the front, and is not zoomed or downloaded on the way.
345
+ function onClick(event) {
346
+ var carousel = event.target.closest && event.target.closest('.ai-image-carousel');
347
+ if (!carousel) {
348
+ return;
349
+ }
350
+
351
+ // A click raised from the keyboard has no pointer behind it, so a swipe that ended without one -- a touch
352
+ // swipe, or a drag released outside the carousel -- must not swallow it.
353
+ if (suppressNextClick && event.detail > 0) {
354
+ suppressNextClick = false;
355
+ stopEvent(event);
356
+ return;
357
+ }
358
+ var stepButton = event.target.closest('[data-carousel-step]');
359
+ if (stepButton) {
360
+ stopEvent(event);
361
+ showImage(carousel, getActiveIndex(carousel) + Number(stepButton.dataset.carouselStep));
362
+ return;
363
+ }
364
+ var sizeButton = event.target.closest('[data-carousel-size-option]');
365
+ if (sizeButton) {
366
+ stopEvent(event);
367
+ setPreferredSize(sizeButton.dataset.carouselSizeOption);
368
+ return;
369
+ }
370
+ var dot = event.target.closest('[data-carousel-target]');
371
+ if (dot) {
372
+ stopEvent(event);
373
+ showImage(carousel, Number(dot.dataset.carouselTarget));
374
+ return;
375
+ }
376
+ var item = event.target.closest('.ai-image-carousel-item');
377
+ if (item && !item.classList.contains('is-active')) {
378
+ stopEvent(event);
379
+ showImage(carousel, Array.prototype.indexOf.call(getItems(carousel), item));
380
+ }
381
+ }
382
+
383
+ // Only while the carousel has focus, so the arrow keys still move the caret in the prompt.
384
+ function onKeyDown(event) {
385
+ if (event.key !== 'ArrowLeft' && event.key !== 'ArrowRight') {
386
+ return;
387
+ }
388
+ var carousel = event.target.closest && event.target.closest('.ai-image-carousel');
389
+ if (!carousel) {
390
+ return;
391
+ }
392
+ event.preventDefault();
393
+ showImage(carousel, getActiveIndex(carousel) + (event.key === 'ArrowRight' ? 1 : -1));
394
+ }
395
+ function onPointerDown(event) {
396
+ suppressNextClick = false;
397
+ var stage = event.button === 0 && event.target.closest && event.target.closest('.ai-image-carousel-stage');
398
+ if (!stage) {
399
+ return;
400
+ }
401
+ drag = {
402
+ stage: stage,
403
+ pointerId: event.pointerId,
404
+ startX: event.clientX,
405
+ startY: event.clientY,
406
+ distance: 0,
407
+ isSwiping: false
408
+ };
409
+ }
410
+
411
+ // The pointer is not captured: a captured pointer retargets the click that follows to the stage, and the click
412
+ // is what brings a card forward or opens the zoom. Listening on the document follows the pointer anyway.
413
+ function onPointerMove(event) {
414
+ if (!drag || event.pointerId !== drag.pointerId) {
415
+ return;
416
+ }
417
+ var distance = event.clientX - drag.startX;
418
+ if (!drag.isSwiping) {
419
+ if (Math.abs(distance) < dragStartThreshold || Math.abs(distance) < Math.abs(event.clientY - drag.startY)) {
420
+ return;
421
+ }
422
+ drag.isSwiping = true;
423
+ drag.stage.classList.add('is-dragging');
424
+ }
425
+ drag.distance = distance;
426
+ drag.stage.style.setProperty('--ai-image-carousel-drag', "".concat(distance, "px"));
427
+ }
428
+ function onPointerUp(event) {
429
+ if (!drag || event.pointerId !== drag.pointerId) {
430
+ return;
431
+ }
432
+ var _drag = drag,
433
+ stage = _drag.stage,
434
+ distance = _drag.distance,
435
+ isSwiping = _drag.isSwiping;
436
+ endDrag();
437
+ if (!isSwiping) {
438
+ return;
439
+ }
440
+
441
+ // The click the browser fires at the end of a drag is not a click on whatever the pointer ended over.
442
+ suppressNextClick = true;
443
+ if (Math.abs(distance) >= swipeThreshold) {
444
+ var carousel = stage.closest('.ai-image-carousel');
445
+ showImage(carousel, getActiveIndex(carousel) + (distance < 0 ? 1 : -1));
446
+ }
447
+ }
448
+ function endDrag() {
449
+ if (!drag) {
450
+ return;
451
+ }
452
+ drag.stage.classList.remove('is-dragging');
453
+ drag.stage.style.removeProperty('--ai-image-carousel-drag');
454
+ drag = null;
455
+ }
456
+
457
+ // A picture the server will not serve is taken out of the stack and put back just after it, where the
458
+ // surface's own handler hides it and says it could not be loaded, exactly as it does for a lone picture.
459
+ // Captured on the document because an image's error event does not bubble.
460
+ function onImageError(event) {
461
+ var item = event.target.tagName === 'IMG' && event.target.closest('.ai-image-carousel-item');
462
+ if (!item) {
463
+ return;
464
+ }
465
+ var carousel = item.closest('.ai-image-carousel');
466
+ item.classList.remove('ai-image-carousel-item', 'is-active');
467
+ item.removeAttribute('data-stack-offset');
468
+ item.removeAttribute('aria-hidden');
469
+ carousel.after(item);
470
+ showImage(carousel, getActiveIndex(carousel));
471
+ }
472
+ if (typeof document !== 'undefined') {
473
+ document.addEventListener('click', onClick, true);
474
+ document.addEventListener('keydown', onKeyDown);
475
+ document.addEventListener('pointerdown', onPointerDown);
476
+ document.addEventListener('pointermove', onPointerMove);
477
+ document.addEventListener('pointerup', onPointerUp);
478
+ document.addEventListener('pointercancel', endDrag);
479
+ document.addEventListener('error', onImageError, true);
480
+ }
481
+ return {
482
+ stackAdjacentImages: stackAdjacentImages
483
+ };
484
+ }();
485
+ //# sourceMappingURL=chat-image-carousel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["chat-image-carousel.js"],"names":["window","CoreAIChatImageCarousel","imageContainerClass","swipeThreshold","dragStartThreshold","furthestVisibleOffset","contentBetweenSelector","previousIcon","nextIcon","sizes","name","text","label","defaultSize","sizeStorageKey","activeIndexByCarouselKey","Map","drag","suppressNextClick","stackAdjacentImages","html","document","firstContainerIndex","indexOf","length","template","createElement","innerHTML","runs","findImageRuns","content","_iterator","_createForOfIteratorHelper","_step","s","n","done","run","value","buildCarousel","err","e","f","root","_iterator2","querySelectorAll","_step2","container","parentElement","tagName","push","isOnlyWhitespaceBetween","filter","candidate","previous","next","range","ownerDocument","createRange","setStartAfter","setEndBefore","between","cloneContents","textContent","trim","querySelector","containers","firstParagraph","vacatedParagraphs","Set","carousel","tabIndex","setAttribute","concat","dataset","carouselKey","getCarouselKey","carouselSize","getPreferredSize","stage","controls","caption","navigation","dots","before","forEach","index","removeSeparatorsBefore","add","classList","image","dot","type","carouselTarget","appendChild","append","createStepButton","createSizePicker","_iterator3","_step3","paragraph","remove","showImage","get","sibling","previousSibling","nodeType","Node","TEXT_NODE","nodeName","firstImage","firstSource","getAttribute","slice","className","element","step","icon","button","carouselStep","selectedSize","picker","_iterator4","_step4","size","title","carouselSizeOption","storedSize","localStorage","getItem","some","_","setPreferredSize","setItem","_iterator5","_step5","_iterator6","_step6","getItems","getActiveIndex","Number","activeIndex","requestedIndex","items","Math","max","min","children","lastElementChild","item","offset","isActive","downloadLink","stackOffset","toggle","activeImage","altText","imageCount","disabled","set","stopEvent","event","preventDefault","stopPropagation","onClick","target","closest","detail","stepButton","sizeButton","contains","Array","prototype","call","onKeyDown","key","onPointerDown","pointerId","startX","clientX","startY","clientY","distance","isSwiping","onPointerMove","abs","style","setProperty","onPointerUp","_drag","endDrag","removeProperty","onImageError","removeAttribute","after","addEventListener"],"mappings":"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","file":"chat-image-carousel.js","sourcesContent":["/*\n * Stacks the pictures a single answer shows one after another into one carousel.\n *\n * A tool that previews a document -- slides, sheets, pages -- hands back one figure marker per picture, all on a\n * line of their own, and each one renders at full thumbnail size: eight slides is eight thumbnails running down\n * the conversation. Here a run of two or more pictures with nothing but whitespace between them becomes a stack\n * of cards instead: the current picture in front, its neighbours fanned out behind it, moved through by swiping,\n * clicking a neighbour, the arrows, the dots or the arrow keys. A picture written mid-sentence keeps its place.\n *\n * It works on the sanitized HTML every chat surface already produces, so the surfaces share one implementation\n * without sharing a renderer, and the carousel is written in the same pass as the message -- there is no frame\n * of full-size pictures before they are gathered up. HTML with no such run is handed back exactly as it came.\n *\n * Loaded on its own, like chat-markers.js, and optional: a surface without it renders the pictures as before.\n */\nwindow.CoreAIChatImageCarousel = window.CoreAIChatImageCarousel || (function () {\n 'use strict';\n\n const imageContainerClass = 'generated-image-container';\n\n // How far a drag has to travel before it counts as a swipe rather than a click.\n const swipeThreshold = 40;\n\n // How far a drag has to travel before the card starts following the pointer.\n const dragStartThreshold = 8;\n\n // Cards further than this from the current one are stacked out of sight behind the last visible one.\n const furthestVisibleOffset = 2;\n\n // Anything that is content in its own right, so pictures either side of it are not one run.\n const contentBetweenSelector = 'img, svg, canvas, video, audio, iframe, table, hr, input';\n\n const previousIcon = '<svg viewBox=\"0 0 16 16\" width=\"12\" height=\"12\" aria-hidden=\"true\" focusable=\"false\"><path d=\"M10 3 5 8l5 5\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path></svg>';\n const nextIcon = '<svg viewBox=\"0 0 16 16\" width=\"12\" height=\"12\" aria-hidden=\"true\" focusable=\"false\"><path d=\"m6 3 5 5-5 5\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path></svg>';\n\n // How large the reader wants previews drawn. It is the reader's taste rather than the answer's, so one choice\n // applies to every carousel on the page and is kept in the browser for the next visit.\n const sizes = [\n { name: 'small', text: 'S', label: 'Small previews' },\n { name: 'medium', text: 'M', label: 'Medium previews' },\n { name: 'large', text: 'L', label: 'Large previews' },\n ];\n const defaultSize = 'medium';\n const sizeStorageKey = 'coreai-image-carousel-size';\n\n // A streamed answer is re-rendered on every chunk, and every render builds the carousel afresh. The picture\n // the reader moved to is remembered here so the next render opens on it rather than back on the first.\n const activeIndexByCarouselKey = new Map();\n\n let drag = null;\n let suppressNextClick = false;\n\n\n function stackAdjacentImages(html) {\n if (typeof document === 'undefined' || !html) {\n return html;\n }\n\n const firstContainerIndex = html.indexOf(imageContainerClass);\n\n if (firstContainerIndex < 0 || html.indexOf(imageContainerClass, firstContainerIndex + imageContainerClass.length) < 0) {\n return html;\n }\n\n const template = document.createElement('template');\n template.innerHTML = html;\n\n const runs = findImageRuns(template.content);\n\n if (runs.length === 0) {\n return html;\n }\n\n for (const run of runs) {\n buildCarousel(run);\n }\n\n return template.innerHTML;\n }\n\n\n function findImageRuns(root) {\n const runs = [];\n let run = [];\n\n for (const container of root.querySelectorAll('.' + imageContainerClass)) {\n // Only a picture standing in a paragraph is gathered. One in a list, a table cell or a link belongs\n // to that structure, and lifting it out would change what the answer says.\n if (!container.parentElement || container.parentElement.tagName !== 'P') {\n runs.push(run);\n run = [];\n continue;\n }\n\n if (run.length > 0 && !isOnlyWhitespaceBetween(run[run.length - 1], container)) {\n runs.push(run);\n run = [];\n }\n\n run.push(container);\n }\n\n runs.push(run);\n\n return runs.filter(candidate => candidate.length > 1);\n }\n\n\n // Two pictures belong to one run when nothing a reader would read sits between them: spaces and line breaks\n // within a paragraph, or the boundary between two paragraphs that hold nothing else.\n function isOnlyWhitespaceBetween(previous, next) {\n const range = previous.ownerDocument.createRange();\n range.setStartAfter(previous);\n range.setEndBefore(next);\n\n const between = range.cloneContents();\n\n return between.textContent.trim() === '' && !between.querySelector(contentBetweenSelector);\n }\n\n\n function buildCarousel(containers) {\n const ownerDocument = containers[0].ownerDocument;\n const firstParagraph = containers[0].parentElement;\n const vacatedParagraphs = new Set();\n\n // Spans throughout, for the same reason the picture's own wrapper is one: the carousel sits inside the\n // paragraph the first picture was in, and a block element there would close that paragraph.\n const carousel = createElement(ownerDocument, 'span', 'ai-image-carousel');\n carousel.tabIndex = 0;\n carousel.setAttribute('role', 'region');\n carousel.setAttribute('aria-roledescription', 'carousel');\n carousel.setAttribute('aria-label', `${containers.length} images`);\n carousel.dataset.carouselKey = getCarouselKey(containers);\n carousel.dataset.carouselSize = getPreferredSize();\n\n const stage = createElement(ownerDocument, 'span', 'ai-image-carousel-stage');\n const controls = createElement(ownerDocument, 'span', 'ai-image-carousel-controls');\n const caption = createElement(ownerDocument, 'span', 'ai-image-carousel-caption');\n const navigation = createElement(ownerDocument, 'span', 'ai-image-carousel-navigation');\n const dots = createElement(ownerDocument, 'span', 'ai-image-carousel-dots');\n\n caption.setAttribute('aria-live', 'polite');\n containers[0].before(carousel);\n\n containers.forEach((container, index) => {\n removeSeparatorsBefore(container);\n\n if (container.parentElement !== firstParagraph) {\n vacatedParagraphs.add(container.parentElement);\n }\n\n container.classList.add('ai-image-carousel-item');\n\n const image = container.querySelector('img');\n\n // The browser's own image drag would otherwise take over the pointer the moment a swipe starts.\n if (image) {\n image.setAttribute('draggable', 'false');\n }\n\n const dot = createElement(ownerDocument, 'button', 'ai-image-carousel-dot');\n dot.type = 'button';\n dot.dataset.carouselTarget = index;\n dot.setAttribute('aria-label', `Show image ${index + 1}`);\n dots.appendChild(dot);\n\n stage.appendChild(container);\n });\n\n navigation.append(\n createStepButton(ownerDocument, -1, 'Previous image', previousIcon),\n dots,\n createStepButton(ownerDocument, 1, 'Next image', nextIcon));\n\n controls.append(caption, createSizePicker(ownerDocument, carousel.dataset.carouselSize), navigation);\n carousel.append(stage, controls);\n\n for (const paragraph of vacatedParagraphs) {\n if (paragraph.textContent.trim() === '' && !paragraph.querySelector(contentBetweenSelector)) {\n paragraph.remove();\n }\n }\n\n showImage(carousel, activeIndexByCarouselKey.get(carousel.dataset.carouselKey) || 0);\n }\n\n\n // Whatever separated this picture from the one before it -- a space, a line break -- is all that is left once\n // the pictures have moved into the carousel, and it would otherwise trail the carousel as a blank line.\n function removeSeparatorsBefore(container) {\n let sibling = container.previousSibling;\n\n while (sibling && ((sibling.nodeType === Node.TEXT_NODE && sibling.textContent.trim() === '') || sibling.nodeName === 'BR')) {\n const previousSibling = sibling.previousSibling;\n sibling.remove();\n sibling = previousSibling;\n }\n }\n\n\n // Cheap rather than exact: a generated image can be a data URI hundreds of kilobytes long, so only the tail\n // of the first address -- where a served document's identifier sits -- and the number of pictures are used.\n function getCarouselKey(containers) {\n const firstImage = containers[0].querySelector('img');\n const firstSource = firstImage ? firstImage.getAttribute('src') || '' : '';\n\n return `${containers.length}:${firstSource.slice(-120)}`;\n }\n\n\n function createElement(ownerDocument, tagName, className) {\n const element = ownerDocument.createElement(tagName);\n element.className = className;\n\n return element;\n }\n\n\n function createStepButton(ownerDocument, step, label, icon) {\n const button = createElement(ownerDocument, 'button', 'ai-image-carousel-button');\n button.type = 'button';\n button.dataset.carouselStep = step;\n button.setAttribute('aria-label', label);\n button.innerHTML = icon;\n\n return button;\n }\n\n\n // A segmented S / M / L control.\n function createSizePicker(ownerDocument, selectedSize) {\n const picker = createElement(ownerDocument, 'span', 'ai-image-carousel-sizes');\n picker.setAttribute('role', 'group');\n picker.setAttribute('aria-label', 'Preview size');\n\n for (const size of sizes) {\n const button = createElement(ownerDocument, 'button', 'ai-image-carousel-size');\n button.type = 'button';\n button.title = size.label;\n button.textContent = size.text;\n button.dataset.carouselSizeOption = size.name;\n button.setAttribute('aria-label', size.label);\n button.setAttribute('aria-pressed', size.name === selectedSize ? 'true' : 'false');\n picker.appendChild(button);\n }\n\n return picker;\n }\n\n\n // Storage can be missing or refuse access -- a private window, blocked site data -- and the default is a fine\n // answer then.\n function getPreferredSize() {\n try {\n const storedSize = localStorage.getItem(sizeStorageKey);\n\n return sizes.some(size => size.name === storedSize) ? storedSize : defaultSize;\n } catch (_) {\n return defaultSize;\n }\n }\n\n\n function setPreferredSize(selectedSize) {\n try {\n localStorage.setItem(sizeStorageKey, selectedSize);\n } catch (_) {\n // Still applied to the page; only remembering it for the next visit is lost.\n }\n\n for (const carousel of document.querySelectorAll('.ai-image-carousel')) {\n carousel.dataset.carouselSize = selectedSize;\n }\n\n for (const button of document.querySelectorAll('[data-carousel-size-option]')) {\n button.setAttribute('aria-pressed', button.dataset.carouselSizeOption === selectedSize ? 'true' : 'false');\n }\n }\n\n\n function getItems(carousel) {\n return carousel.querySelectorAll('.ai-image-carousel-stage > .ai-image-carousel-item');\n }\n\n\n function getActiveIndex(carousel) {\n return Number(carousel.dataset.activeIndex) || 0;\n }\n\n\n function showImage(carousel, requestedIndex) {\n const items = getItems(carousel);\n\n if (items.length === 0) {\n carousel.remove();\n\n return;\n }\n\n const activeIndex = Math.max(0, Math.min(items.length - 1, requestedIndex));\n const dots = carousel.querySelector('.ai-image-carousel-dots');\n\n while (dots.children.length > items.length) {\n dots.lastElementChild.remove();\n }\n\n items.forEach((item, index) => {\n const offset = index - activeIndex;\n const isActive = offset === 0;\n const downloadLink = item.querySelector('a');\n\n item.dataset.stackOffset = Math.max(-furthestVisibleOffset - 1, Math.min(furthestVisibleOffset + 1, offset));\n item.classList.toggle('is-active', isActive);\n item.setAttribute('aria-hidden', isActive ? 'false' : 'true');\n\n // A card behind the current one is hidden from assistive technology, so nothing in it may take focus.\n if (downloadLink) {\n downloadLink.tabIndex = isActive ? 0 : -1;\n }\n\n dots.children[index].classList.toggle('is-active', isActive);\n dots.children[index].setAttribute('aria-current', isActive ? 'true' : 'false');\n });\n\n const activeImage = items[activeIndex].querySelector('img');\n const altText = activeImage ? activeImage.getAttribute('alt') : '';\n\n carousel.dataset.activeIndex = activeIndex;\n carousel.dataset.imageCount = items.length;\n carousel.querySelector('[data-carousel-step=\"-1\"]').disabled = activeIndex === 0;\n carousel.querySelector('[data-carousel-step=\"1\"]').disabled = activeIndex === items.length - 1;\n carousel.querySelector('.ai-image-carousel-caption').textContent = altText\n ? `${activeIndex + 1} / ${items.length} · ${altText}`\n : `${activeIndex + 1} / ${items.length}`;\n\n activeIndexByCarouselKey.set(carousel.dataset.carouselKey, activeIndex);\n }\n\n\n function stopEvent(event) {\n event.preventDefault();\n event.stopPropagation();\n }\n\n\n // Captured, so it runs before anything bound to the picture itself: a card behind the current one is brought\n // to the front, and is not zoomed or downloaded on the way.\n function onClick(event) {\n const carousel = event.target.closest && event.target.closest('.ai-image-carousel');\n\n if (!carousel) {\n return;\n }\n\n // A click raised from the keyboard has no pointer behind it, so a swipe that ended without one -- a touch\n // swipe, or a drag released outside the carousel -- must not swallow it.\n if (suppressNextClick && event.detail > 0) {\n suppressNextClick = false;\n stopEvent(event);\n\n return;\n }\n\n const stepButton = event.target.closest('[data-carousel-step]');\n\n if (stepButton) {\n stopEvent(event);\n showImage(carousel, getActiveIndex(carousel) + Number(stepButton.dataset.carouselStep));\n\n return;\n }\n\n const sizeButton = event.target.closest('[data-carousel-size-option]');\n\n if (sizeButton) {\n stopEvent(event);\n setPreferredSize(sizeButton.dataset.carouselSizeOption);\n\n return;\n }\n\n const dot = event.target.closest('[data-carousel-target]');\n\n if (dot) {\n stopEvent(event);\n showImage(carousel, Number(dot.dataset.carouselTarget));\n\n return;\n }\n\n const item = event.target.closest('.ai-image-carousel-item');\n\n if (item && !item.classList.contains('is-active')) {\n stopEvent(event);\n showImage(carousel, Array.prototype.indexOf.call(getItems(carousel), item));\n }\n }\n\n\n // Only while the carousel has focus, so the arrow keys still move the caret in the prompt.\n function onKeyDown(event) {\n if (event.key !== 'ArrowLeft' && event.key !== 'ArrowRight') {\n return;\n }\n\n const carousel = event.target.closest && event.target.closest('.ai-image-carousel');\n\n if (!carousel) {\n return;\n }\n\n event.preventDefault();\n showImage(carousel, getActiveIndex(carousel) + (event.key === 'ArrowRight' ? 1 : -1));\n }\n\n\n function onPointerDown(event) {\n suppressNextClick = false;\n\n const stage = event.button === 0 && event.target.closest && event.target.closest('.ai-image-carousel-stage');\n\n if (!stage) {\n return;\n }\n\n drag = {\n stage: stage,\n pointerId: event.pointerId,\n startX: event.clientX,\n startY: event.clientY,\n distance: 0,\n isSwiping: false,\n };\n }\n\n\n // The pointer is not captured: a captured pointer retargets the click that follows to the stage, and the click\n // is what brings a card forward or opens the zoom. Listening on the document follows the pointer anyway.\n function onPointerMove(event) {\n if (!drag || event.pointerId !== drag.pointerId) {\n return;\n }\n\n const distance = event.clientX - drag.startX;\n\n if (!drag.isSwiping) {\n if (Math.abs(distance) < dragStartThreshold || Math.abs(distance) < Math.abs(event.clientY - drag.startY)) {\n return;\n }\n\n drag.isSwiping = true;\n drag.stage.classList.add('is-dragging');\n }\n\n drag.distance = distance;\n drag.stage.style.setProperty('--ai-image-carousel-drag', `${distance}px`);\n }\n\n\n function onPointerUp(event) {\n if (!drag || event.pointerId !== drag.pointerId) {\n return;\n }\n\n const { stage, distance, isSwiping } = drag;\n\n endDrag();\n\n if (!isSwiping) {\n return;\n }\n\n // The click the browser fires at the end of a drag is not a click on whatever the pointer ended over.\n suppressNextClick = true;\n\n if (Math.abs(distance) >= swipeThreshold) {\n const carousel = stage.closest('.ai-image-carousel');\n showImage(carousel, getActiveIndex(carousel) + (distance < 0 ? 1 : -1));\n }\n }\n\n\n function endDrag() {\n if (!drag) {\n return;\n }\n\n drag.stage.classList.remove('is-dragging');\n drag.stage.style.removeProperty('--ai-image-carousel-drag');\n drag = null;\n }\n\n\n // A picture the server will not serve is taken out of the stack and put back just after it, where the\n // surface's own handler hides it and says it could not be loaded, exactly as it does for a lone picture.\n // Captured on the document because an image's error event does not bubble.\n function onImageError(event) {\n const item = event.target.tagName === 'IMG' && event.target.closest('.ai-image-carousel-item');\n\n if (!item) {\n return;\n }\n\n const carousel = item.closest('.ai-image-carousel');\n\n item.classList.remove('ai-image-carousel-item', 'is-active');\n item.removeAttribute('data-stack-offset');\n item.removeAttribute('aria-hidden');\n carousel.after(item);\n showImage(carousel, getActiveIndex(carousel));\n }\n\n\n if (typeof document !== 'undefined') {\n document.addEventListener('click', onClick, true);\n document.addEventListener('keydown', onKeyDown);\n document.addEventListener('pointerdown', onPointerDown);\n document.addEventListener('pointermove', onPointerMove);\n document.addEventListener('pointerup', onPointerUp);\n document.addEventListener('pointercancel', endDrag);\n document.addEventListener('error', onImageError, true);\n }\n\n return {\n stackAdjacentImages: stackAdjacentImages,\n };\n})();\n"]}
@@ -0,0 +1 @@
1
+ .ai-image-carousel{--ai-image-carousel-card-width:70%;display:block;width:100%;max-width:520px;margin:.5rem 0;border-radius:.5rem;transition:max-width .25s ease}.ai-image-carousel[data-carousel-size=small]{max-width:360px}.ai-image-carousel[data-carousel-size=large]{max-width:760px}.ai-image-carousel:focus{outline:0}.ai-image-carousel:focus-visible{outline:2px solid var(--bs-primary,#0d6efd);outline-offset:4px}.ai-chat-widget-messages .ai-image-carousel{--ai-image-carousel-card-width:78%}.ai-image-carousel-stage{display:grid;align-items:center;justify-items:center;padding:.25rem 0;isolation:isolate;touch-action:pan-y;user-select:none;-webkit-user-select:none}.ai-image-carousel-stage>.generated-image-container.ai-image-carousel-item{grid-area:1/1;display:block;width:var(--ai-image-carousel-card-width);margin:0;cursor:pointer;transform-origin:center;transition:transform .35s cubic-bezier(.2,.7,.2,1),opacity .35s ease,filter .35s ease}.ai-image-carousel-stage>.generated-image-container.ai-image-carousel-item img{display:block;width:100%;max-width:100%!important;-webkit-user-drag:none;box-shadow:0 .375rem 1.25rem rgba(0,0,0,.14)}.ai-image-carousel-stage>.ai-image-carousel-item[data-stack-offset="0"]{z-index:4;cursor:default;transform:translateX(var(--ai-image-carousel-drag,0))}.ai-image-carousel-stage>.ai-image-carousel-item[data-stack-offset="-1"],.ai-image-carousel-stage>.ai-image-carousel-item[data-stack-offset="1"]{z-index:3;opacity:.85;filter:brightness(.94)}.ai-image-carousel-stage>.ai-image-carousel-item[data-stack-offset="-1"]{transform:translateX(-16%) scale(.88)}.ai-image-carousel-stage>.ai-image-carousel-item[data-stack-offset="1"]{transform:translateX(16%) scale(.88)}.ai-image-carousel-stage>.ai-image-carousel-item[data-stack-offset="-2"],.ai-image-carousel-stage>.ai-image-carousel-item[data-stack-offset="2"]{z-index:2;opacity:.55;filter:brightness(.9)}.ai-image-carousel-stage>.ai-image-carousel-item[data-stack-offset="-2"]{transform:translateX(-26%) scale(.76)}.ai-image-carousel-stage>.ai-image-carousel-item[data-stack-offset="2"]{transform:translateX(26%) scale(.76)}.ai-image-carousel-stage>.ai-image-carousel-item[data-stack-offset="-3"],.ai-image-carousel-stage>.ai-image-carousel-item[data-stack-offset="3"]{z-index:1;opacity:0;pointer-events:none}.ai-image-carousel-stage>.ai-image-carousel-item[data-stack-offset="-3"]{transform:translateX(-26%) scale(.7)}.ai-image-carousel-stage>.ai-image-carousel-item[data-stack-offset="3"]{transform:translateX(26%) scale(.7)}.ai-image-carousel-stage>.ai-image-carousel-item:not(.is-active):hover{opacity:1;filter:none}.ai-image-carousel-stage>.generated-image-container.ai-image-carousel-item:not(.is-active) img{cursor:pointer}.ai-image-carousel-stage>.ai-image-carousel-item:not(.is-active) .ai-download-image{display:none}.ai-image-carousel-stage.is-dragging>.ai-image-carousel-item{transition:none}.ai-image-carousel-controls{display:flex;align-items:center;gap:.75rem;margin-top:.5rem;font-size:.8125rem;line-height:1.25;color:var(--bs-secondary-color,#6c757d)}.ai-image-carousel-caption{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ai-image-carousel-navigation{display:inline-flex;flex:none;align-items:center;gap:.375rem}.ai-image-carousel-button{display:inline-flex;align-items:center;justify-content:center;width:1.75rem;height:1.75rem;padding:0;border:1px solid var(--bs-border-color,#dee2e6);border-radius:50%;color:var(--bs-body-color,#212529);background-color:var(--bs-body-bg,#fff);transition:background-color .15s ease,opacity .15s ease}.ai-image-carousel-button:hover:not(:disabled){background-color:var(--bs-tertiary-bg,#f8f9fa)}.ai-image-carousel-button:disabled{opacity:.4;cursor:default}.ai-image-carousel-dots{display:inline-flex;align-items:center;gap:.375rem}.ai-image-carousel-dot{position:relative;width:.5rem;height:.5rem;padding:0;border:0;border-radius:999px;background-color:var(--bs-border-color,#dee2e6);transition:width .2s ease,background-color .2s ease}.ai-image-carousel-dot::after{content:"";position:absolute;inset:-.375rem -.25rem}.ai-image-carousel-dot.is-active{width:1.25rem;background-color:var(--bs-primary,#0d6efd)}.ai-image-carousel-sizes{display:inline-flex;flex:none;overflow:hidden;border:1px solid var(--bs-border-color,#dee2e6);border-radius:.375rem}.ai-image-carousel-size{min-width:1.5rem;height:1.5rem;padding:0 .375rem;border:0;font-size:.6875rem;font-weight:600;line-height:1;color:var(--bs-secondary-color,#6c757d);background-color:var(--bs-body-bg,#fff);transition:background-color .15s ease,color .15s ease}.ai-image-carousel-size+.ai-image-carousel-size{border-left:1px solid var(--bs-border-color,#dee2e6)}.ai-image-carousel-size:hover{color:var(--bs-body-color,#212529);background-color:var(--bs-tertiary-bg,#f8f9fa)}.ai-image-carousel-size[aria-pressed=true]{color:#fff;background-color:var(--bs-primary,#0d6efd)}.ai-chat-widget-messages .ai-image-carousel-sizes{display:none}.ai-image-carousel[data-image-count="1"] .ai-image-carousel-navigation{display:none}@media (prefers-reduced-motion:reduce){.ai-image-carousel-dot,.ai-image-carousel-stage>.generated-image-container.ai-image-carousel-item{transition:none}}
@@ -0,0 +1,2 @@
1
+ function _createForOfIteratorHelper(e,t){var a="undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(!a){if(Array.isArray(e)||(a=_unsupportedIterableToArray(e))||t&&e&&"number"==typeof e.length){a&&(e=a);var r=0,n=function(){};return{s:n,n:function(){return r>=e.length?{done:!0}:{done:!1,value:e[r++]}},e:function(e){throw e},f:n}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var i,o=!0,s=!1;return{s:function(){a=a.call(e)},n:function(){var e=a.next();return o=e.done,e},e:function(e){s=!0,i=e},f:function(){try{o||null==a.return||a.return()}finally{if(s)throw i}}}}function _unsupportedIterableToArray(e,t){if(e){if("string"==typeof e)return _arrayLikeToArray(e,t);var a={}.toString.call(e).slice(8,-1);return"Object"===a&&e.constructor&&(a=e.constructor.name),"Map"===a||"Set"===a?Array.from(e):"Arguments"===a||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(a)?_arrayLikeToArray(e,t):void 0}}function _arrayLikeToArray(e,t){(null==t||t>e.length)&&(t=e.length);for(var a=0,r=Array(t);a<t;a++)r[a]=e[a];return r}window.CoreAIChatImageCarousel=window.CoreAIChatImageCarousel||function(){"use strict";var e="generated-image-container",t="img, svg, canvas, video, audio, iframe, table, hr, input",a=[{name:"small",text:"S",label:"Small previews"},{name:"medium",text:"M",label:"Medium previews"},{name:"large",text:"L",label:"Large previews"}],r="medium",n="coreai-image-carousel-size",i=new Map,o=null,s=!1;function l(e,a){var r=e.ownerDocument.createRange();r.setStartAfter(e),r.setEndBefore(a);var n=r.cloneContents();return""===n.textContent.trim()&&!n.querySelector(t)}function c(e){var o=e[0].ownerDocument,s=e[0].parentElement,l=new Set,c=u(o,"span","ai-image-carousel");c.tabIndex=0,c.setAttribute("role","region"),c.setAttribute("aria-roledescription","carousel"),c.setAttribute("aria-label","".concat(e.length," images")),c.dataset.carouselKey=function(e){var t=e[0].querySelector("img"),a=t&&t.getAttribute("src")||"";return"".concat(e.length,":").concat(a.slice(-120))}(e),c.dataset.carouselSize=function(){try{var e=localStorage.getItem(n);return a.some(function(t){return t.name===e})?e:r}catch(e){return r}}();var g=u(o,"span","ai-image-carousel-stage"),f=u(o,"span","ai-image-carousel-controls"),p=u(o,"span","ai-image-carousel-caption"),v=u(o,"span","ai-image-carousel-navigation"),h=u(o,"span","ai-image-carousel-dots");p.setAttribute("aria-live","polite"),e[0].before(c),e.forEach(function(e,t){!function(e){var t=e.previousSibling;for(;t&&(t.nodeType===Node.TEXT_NODE&&""===t.textContent.trim()||"BR"===t.nodeName);){var a=t.previousSibling;t.remove(),t=a}}(e),e.parentElement!==s&&l.add(e.parentElement),e.classList.add("ai-image-carousel-item");var a=e.querySelector("img");a&&a.setAttribute("draggable","false");var r=u(o,"button","ai-image-carousel-dot");r.type="button",r.dataset.carouselTarget=t,r.setAttribute("aria-label","Show image ".concat(t+1)),h.appendChild(r),g.appendChild(e)}),v.append(d(o,-1,"Previous image",'<svg viewBox="0 0 16 16" width="12" height="12" aria-hidden="true" focusable="false"><path d="M10 3 5 8l5 5" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path></svg>'),h,d(o,1,"Next image",'<svg viewBox="0 0 16 16" width="12" height="12" aria-hidden="true" focusable="false"><path d="m6 3 5 5-5 5" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path></svg>')),f.append(p,function(e,t){var r=u(e,"span","ai-image-carousel-sizes");r.setAttribute("role","group"),r.setAttribute("aria-label","Preview size");var n,i=_createForOfIteratorHelper(a);try{for(i.s();!(n=i.n()).done;){var o=n.value,s=u(e,"button","ai-image-carousel-size");s.type="button",s.title=o.label,s.textContent=o.text,s.dataset.carouselSizeOption=o.name,s.setAttribute("aria-label",o.label),s.setAttribute("aria-pressed",o.name===t?"true":"false"),r.appendChild(s)}}catch(e){i.e(e)}finally{i.f()}return r}(o,c.dataset.carouselSize),v),c.append(g,f);var y,b=_createForOfIteratorHelper(l);try{for(b.s();!(y=b.n()).done;){var A=y.value;""!==A.textContent.trim()||A.querySelector(t)||A.remove()}}catch(e){b.e(e)}finally{b.f()}m(c,i.get(c.dataset.carouselKey)||0)}function u(e,t,a){var r=e.createElement(t);return r.className=a,r}function d(e,t,a,r){var n=u(e,"button","ai-image-carousel-button");return n.type="button",n.dataset.carouselStep=t,n.setAttribute("aria-label",a),n.innerHTML=r,n}function g(e){return e.querySelectorAll(".ai-image-carousel-stage > .ai-image-carousel-item")}function f(e){return Number(e.dataset.activeIndex)||0}function m(e,t){var a=g(e);if(0!==a.length){for(var r=Math.max(0,Math.min(a.length-1,t)),n=e.querySelector(".ai-image-carousel-dots");n.children.length>a.length;)n.lastElementChild.remove();a.forEach(function(e,t){var a=t-r,i=0===a,o=e.querySelector("a");e.dataset.stackOffset=Math.max(-3,Math.min(3,a)),e.classList.toggle("is-active",i),e.setAttribute("aria-hidden",i?"false":"true"),o&&(o.tabIndex=i?0:-1),n.children[t].classList.toggle("is-active",i),n.children[t].setAttribute("aria-current",i?"true":"false")});var o=a[r].querySelector("img"),s=o?o.getAttribute("alt"):"";e.dataset.activeIndex=r,e.dataset.imageCount=a.length,e.querySelector('[data-carousel-step="-1"]').disabled=0===r,e.querySelector('[data-carousel-step="1"]').disabled=r===a.length-1,e.querySelector(".ai-image-carousel-caption").textContent=s?"".concat(r+1," / ").concat(a.length," · ").concat(s):"".concat(r+1," / ").concat(a.length),i.set(e.dataset.carouselKey,r)}else e.remove()}function p(e){e.preventDefault(),e.stopPropagation()}function v(){o&&(o.stage.classList.remove("is-dragging"),o.stage.style.removeProperty("--ai-image-carousel-drag"),o=null)}return"undefined"!=typeof document&&(document.addEventListener("click",function(e){var t=e.target.closest&&e.target.closest(".ai-image-carousel");if(t){if(s&&e.detail>0)return s=!1,void p(e);var a=e.target.closest("[data-carousel-step]");if(a)return p(e),void m(t,f(t)+Number(a.dataset.carouselStep));var r=e.target.closest("[data-carousel-size-option]");if(r)return p(e),void function(e){try{localStorage.setItem(n,e)}catch(e){}var t,a=_createForOfIteratorHelper(document.querySelectorAll(".ai-image-carousel"));try{for(a.s();!(t=a.n()).done;)t.value.dataset.carouselSize=e}catch(e){a.e(e)}finally{a.f()}var r,i=_createForOfIteratorHelper(document.querySelectorAll("[data-carousel-size-option]"));try{for(i.s();!(r=i.n()).done;){var o=r.value;o.setAttribute("aria-pressed",o.dataset.carouselSizeOption===e?"true":"false")}}catch(e){i.e(e)}finally{i.f()}}(r.dataset.carouselSizeOption);var i=e.target.closest("[data-carousel-target]");if(i)return p(e),void m(t,Number(i.dataset.carouselTarget));var o=e.target.closest(".ai-image-carousel-item");o&&!o.classList.contains("is-active")&&(p(e),m(t,Array.prototype.indexOf.call(g(t),o)))}},!0),document.addEventListener("keydown",function(e){if("ArrowLeft"===e.key||"ArrowRight"===e.key){var t=e.target.closest&&e.target.closest(".ai-image-carousel");t&&(e.preventDefault(),m(t,f(t)+("ArrowRight"===e.key?1:-1)))}}),document.addEventListener("pointerdown",function(e){s=!1;var t=0===e.button&&e.target.closest&&e.target.closest(".ai-image-carousel-stage");t&&(o={stage:t,pointerId:e.pointerId,startX:e.clientX,startY:e.clientY,distance:0,isSwiping:!1})}),document.addEventListener("pointermove",function(e){if(o&&e.pointerId===o.pointerId){var t=e.clientX-o.startX;if(!o.isSwiping){if(Math.abs(t)<8||Math.abs(t)<Math.abs(e.clientY-o.startY))return;o.isSwiping=!0,o.stage.classList.add("is-dragging")}o.distance=t,o.stage.style.setProperty("--ai-image-carousel-drag","".concat(t,"px"))}}),document.addEventListener("pointerup",function(e){if(o&&e.pointerId===o.pointerId){var t=o,a=t.stage,r=t.distance,n=t.isSwiping;if(v(),n&&(s=!0,Math.abs(r)>=40)){var i=a.closest(".ai-image-carousel");m(i,f(i)+(r<0?1:-1))}}}),document.addEventListener("pointercancel",v),document.addEventListener("error",function(e){var t="IMG"===e.target.tagName&&e.target.closest(".ai-image-carousel-item");if(t){var a=t.closest(".ai-image-carousel");t.classList.remove("ai-image-carousel-item","is-active"),t.removeAttribute("data-stack-offset"),t.removeAttribute("aria-hidden"),a.after(t),m(a,f(a))}},!0)),{stackAdjacentImages:function(t){if("undefined"==typeof document||!t)return t;var a=t.indexOf(e);if(a<0||t.indexOf(e,a+25)<0)return t;var r=document.createElement("template");r.innerHTML=t;var n=function(t){var a,r=[],n=[],i=_createForOfIteratorHelper(t.querySelectorAll("."+e));try{for(i.s();!(a=i.n()).done;){var o=a.value;o.parentElement&&"P"===o.parentElement.tagName?(n.length>0&&!l(n[n.length-1],o)&&(r.push(n),n=[]),n.push(o)):(r.push(n),n=[])}}catch(e){i.e(e)}finally{i.f()}return r.push(n),r.filter(function(e){return e.length>1})}(r.content);if(0===n.length)return t;var i,o=_createForOfIteratorHelper(n);try{for(o.s();!(i=o.n()).done;){c(i.value)}}catch(e){o.e(e)}finally{o.f()}return r.innerHTML}}}();
2
+ //# sourceMappingURL=chat-image-carousel.min.js.map