@f-ewald/components 0.5.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. package/README.md +27 -0
  2. package/custom-elements.json +3290 -835
  3. package/dist/chat-message.d.ts +39 -0
  4. package/dist/chat-message.d.ts.map +1 -0
  5. package/dist/chat-message.js +155 -0
  6. package/dist/chat-message.js.map +1 -0
  7. package/dist/data-table.d.ts +39 -0
  8. package/dist/data-table.d.ts.map +1 -0
  9. package/dist/data-table.js +119 -0
  10. package/dist/data-table.js.map +1 -0
  11. package/dist/editable-text.d.ts +52 -0
  12. package/dist/editable-text.d.ts.map +1 -0
  13. package/dist/editable-text.js +224 -0
  14. package/dist/editable-text.js.map +1 -0
  15. package/dist/form-select.d.ts +40 -0
  16. package/dist/form-select.d.ts.map +1 -0
  17. package/dist/form-select.js +236 -0
  18. package/dist/form-select.js.map +1 -0
  19. package/dist/gallery-item-variant.d.ts +21 -0
  20. package/dist/gallery-item-variant.d.ts.map +1 -0
  21. package/dist/gallery-item-variant.js +44 -0
  22. package/dist/gallery-item-variant.js.map +1 -0
  23. package/dist/gallery-item.d.ts +28 -0
  24. package/dist/gallery-item.d.ts.map +1 -0
  25. package/dist/gallery-item.js +54 -0
  26. package/dist/gallery-item.js.map +1 -0
  27. package/dist/icons.d.ts +7 -0
  28. package/dist/icons.d.ts.map +1 -1
  29. package/dist/icons.js +7 -0
  30. package/dist/icons.js.map +1 -1
  31. package/dist/index.d.ts +13 -1
  32. package/dist/index.d.ts.map +1 -1
  33. package/dist/index.js +13 -1
  34. package/dist/index.js.map +1 -1
  35. package/dist/live-timer.d.ts +31 -0
  36. package/dist/live-timer.d.ts.map +1 -0
  37. package/dist/live-timer.js +78 -0
  38. package/dist/live-timer.js.map +1 -0
  39. package/dist/photo-gallery.d.ts +117 -0
  40. package/dist/photo-gallery.d.ts.map +1 -0
  41. package/dist/photo-gallery.js +620 -0
  42. package/dist/photo-gallery.js.map +1 -0
  43. package/dist/popover-panel.d.ts +34 -0
  44. package/dist/popover-panel.d.ts.map +1 -0
  45. package/dist/popover-panel.js +173 -0
  46. package/dist/popover-panel.js.map +1 -0
  47. package/dist/status-pill.d.ts +24 -0
  48. package/dist/status-pill.d.ts.map +1 -0
  49. package/dist/status-pill.js +101 -0
  50. package/dist/status-pill.js.map +1 -0
  51. package/dist/tile-grid.d.ts +32 -0
  52. package/dist/tile-grid.d.ts.map +1 -0
  53. package/dist/tile-grid.js +102 -0
  54. package/dist/tile-grid.js.map +1 -0
  55. package/dist/tokens.css +39 -0
  56. package/dist/tokens.d.ts +28 -3
  57. package/dist/tokens.d.ts.map +1 -1
  58. package/dist/tokens.js +42 -43
  59. package/dist/tokens.js.map +1 -1
  60. package/dist/user-avatar.d.ts +5 -2
  61. package/dist/user-avatar.d.ts.map +1 -1
  62. package/dist/user-avatar.js +22 -6
  63. package/dist/user-avatar.js.map +1 -1
  64. package/dist/utils/duration.d.ts +12 -0
  65. package/dist/utils/duration.d.ts.map +1 -0
  66. package/dist/utils/duration.js +27 -0
  67. package/dist/utils/duration.js.map +1 -0
  68. package/docs/chat-message.md +59 -0
  69. package/docs/data-table.md +63 -0
  70. package/docs/editable-text.md +51 -0
  71. package/docs/form-select.md +64 -0
  72. package/docs/gallery-item-variant.md +37 -0
  73. package/docs/gallery-item.md +47 -0
  74. package/docs/live-timer.md +39 -0
  75. package/docs/photo-gallery.md +77 -0
  76. package/docs/popover-panel.md +66 -0
  77. package/docs/status-pill.md +43 -0
  78. package/docs/tile-grid.md +58 -0
  79. package/docs/user-avatar.md +1 -1
  80. package/llms.txt +280 -1
  81. package/package.json +1 -1
@@ -0,0 +1,620 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { LitElement, css, html, nothing } from "lit";
8
+ import { customElement, property, queryAssignedElements, state } from "lit/decorators.js";
9
+ import { ifDefined } from "lit/directives/if-defined.js";
10
+ import { styleMap } from "lit/directives/style-map.js";
11
+ import { iconChevronLeft, iconChevronRight } from "./icons.js";
12
+ import { tokens } from "./tokens.js";
13
+ const transitionDurationMs = 250;
14
+ const swipeThresholdPx = 40;
15
+ const booleanAttribute = {
16
+ fromAttribute(value) {
17
+ return value !== null && value !== "false";
18
+ },
19
+ };
20
+ /**
21
+ * Responsive, accessible image carousel composed from declarative
22
+ * `gallery-item` children.
23
+ *
24
+ * @element photo-gallery
25
+ * @slot - `gallery-item` elements rendered as slides.
26
+ * @fires slide-change - The active image changed.
27
+ */
28
+ let PhotoGallery = class PhotoGallery extends LitElement {
29
+ constructor() {
30
+ super(...arguments);
31
+ /** Zero-based active image index. */
32
+ this.currentIndex = 0;
33
+ /** Autoplay interval in milliseconds. Set to zero to disable autoplay. */
34
+ this.delay = 0;
35
+ /** Whether previous and next buttons are shown. */
36
+ this.showControls = true;
37
+ /** Whether a current/total counter is shown. */
38
+ this.showCounter = false;
39
+ /** Whether clickable slide indicators are shown. */
40
+ this.showIndicators = false;
41
+ /** Whether autoplay includes a built-in pause/play control. */
42
+ this.showAutoplayControl = true;
43
+ /** Whether autoplay is explicitly paused. */
44
+ this.paused = false;
45
+ /** CSS aspect ratio used by the image viewport. */
46
+ this.aspectRatio = "16 / 9";
47
+ /** How images fit within the stable viewport. */
48
+ this.objectFit = "cover";
49
+ this._previousIndex = null;
50
+ this._itemsVersion = 0;
51
+ this._hovered = false;
52
+ this._focusWithin = false;
53
+ this._nextChangeReason = null;
54
+ this._itemsChanged = false;
55
+ this._renderedIndex = 0;
56
+ /** Pauses or resumes scheduling when page visibility changes. */
57
+ this._handleVisibilityChange = () => {
58
+ this._restartAutoplay();
59
+ };
60
+ }
61
+ static { this.styles = [
62
+ tokens,
63
+ css `
64
+ :host {
65
+ display: block;
66
+ color: var(--ui-text, #0f172a);
67
+ font-family: var(--ui-font, ui-sans-serif, system-ui, sans-serif);
68
+ font-size: var(--ui-font-size, 0.875rem);
69
+ }
70
+ .gallery {
71
+ outline: none;
72
+ }
73
+ figure {
74
+ margin: 0;
75
+ }
76
+ .viewport {
77
+ position: relative;
78
+ overflow: hidden;
79
+ aspect-ratio: var(--photo-gallery-aspect-ratio, 16 / 9);
80
+ border-radius: var(--ui-radius, 0.5rem);
81
+ background: var(--ui-surface-muted, #f8fafc);
82
+ touch-action: pan-y;
83
+ user-select: none;
84
+ }
85
+ .gallery:focus-visible .viewport {
86
+ box-shadow: var(--ui-focus-ring, 0 0 0 3px rgb(79 70 229 / 0.35));
87
+ }
88
+ .slides {
89
+ display: grid;
90
+ width: 100%;
91
+ height: 100%;
92
+ }
93
+ picture {
94
+ grid-area: 1 / 1;
95
+ display: block;
96
+ width: 100%;
97
+ height: 100%;
98
+ }
99
+ picture img {
100
+ display: block;
101
+ width: 100%;
102
+ height: 100%;
103
+ object-fit: var(--photo-gallery-object-fit, cover);
104
+ }
105
+ .entering {
106
+ z-index: 2;
107
+ animation: gallery-fade-in 250ms ease both;
108
+ }
109
+ .leaving {
110
+ z-index: 1;
111
+ pointer-events: none;
112
+ animation: gallery-fade-out 250ms ease both;
113
+ }
114
+ .arrow-controls {
115
+ position: absolute;
116
+ z-index: 3;
117
+ inset: 0;
118
+ display: flex;
119
+ align-items: center;
120
+ justify-content: space-between;
121
+ padding: 0.5rem;
122
+ pointer-events: none;
123
+ }
124
+ button {
125
+ border: 0;
126
+ font: inherit;
127
+ cursor: pointer;
128
+ }
129
+ button:focus-visible {
130
+ outline: none;
131
+ box-shadow: var(--ui-focus-ring, 0 0 0 3px rgb(79 70 229 / 0.35));
132
+ }
133
+ .arrow-button {
134
+ display: inline-flex;
135
+ align-items: center;
136
+ justify-content: center;
137
+ width: 2.5rem;
138
+ height: 2.5rem;
139
+ padding: 0;
140
+ color: var(--ui-surface, #fff);
141
+ background: var(--ui-overlay, rgb(15 23 42 / 0.45));
142
+ border-radius: 9999px;
143
+ pointer-events: auto;
144
+ }
145
+ .arrow-button:hover {
146
+ background: color-mix(in srgb, var(--ui-text, #0f172a) 70%, transparent);
147
+ }
148
+ figcaption {
149
+ padding: 0.5rem 0.25rem 0;
150
+ color: var(--ui-text-muted, #64748b);
151
+ }
152
+ .footer {
153
+ display: flex;
154
+ align-items: center;
155
+ justify-content: space-between;
156
+ gap: 0.75rem;
157
+ min-height: 2rem;
158
+ padding-top: 0.5rem;
159
+ }
160
+ .counter {
161
+ color: var(--ui-text-muted, #64748b);
162
+ font-size: var(--ui-font-size-sm, 0.75rem);
163
+ white-space: nowrap;
164
+ }
165
+ .indicators {
166
+ display: flex;
167
+ flex: 1 1 auto;
168
+ align-items: center;
169
+ justify-content: center;
170
+ gap: 0.375rem;
171
+ }
172
+ .indicator {
173
+ width: 0.625rem;
174
+ height: 0.625rem;
175
+ padding: 0;
176
+ background: var(--ui-border, #e2e8f0);
177
+ border-radius: 9999px;
178
+ }
179
+ .indicator[aria-current="true"] {
180
+ background: var(--ui-primary, #4f46e5);
181
+ }
182
+ .autoplay-button {
183
+ padding: 0.25rem 0.625rem;
184
+ color: var(--ui-text, #0f172a);
185
+ background: var(--ui-surface-muted, #f8fafc);
186
+ border: 1px solid var(--ui-border, #e2e8f0);
187
+ border-radius: var(--ui-radius-sm, 0.25rem);
188
+ font-size: var(--ui-font-size-sm, 0.75rem);
189
+ white-space: nowrap;
190
+ }
191
+ .autoplay-button:hover {
192
+ background: var(--ui-surface, #fff);
193
+ }
194
+ slot {
195
+ display: none;
196
+ }
197
+ @keyframes gallery-fade-in {
198
+ from {
199
+ opacity: 0;
200
+ }
201
+ to {
202
+ opacity: 1;
203
+ }
204
+ }
205
+ @keyframes gallery-fade-out {
206
+ from {
207
+ opacity: 1;
208
+ }
209
+ to {
210
+ opacity: 0;
211
+ }
212
+ }
213
+ @media (prefers-reduced-motion: reduce) {
214
+ .entering,
215
+ .leaving {
216
+ animation: none;
217
+ }
218
+ }
219
+ `,
220
+ ]; }
221
+ /** Starts observers and autoplay integration when the element connects. */
222
+ connectedCallback() {
223
+ super.connectedCallback();
224
+ this._metadataObserver ??= new MutationObserver(() => this._handleMetadataChange());
225
+ this._metadataObserver.observe(this, {
226
+ attributes: true,
227
+ attributeFilter: ["alt", "caption", "media", "src", "srcset"],
228
+ childList: true,
229
+ subtree: true,
230
+ });
231
+ document.addEventListener("visibilitychange", this._handleVisibilityChange);
232
+ }
233
+ /** Releases timers and observers when the element disconnects. */
234
+ disconnectedCallback() {
235
+ this._clearAutoplay();
236
+ this._clearTransition();
237
+ this._metadataObserver?.disconnect();
238
+ document.removeEventListener("visibilitychange", this._handleVisibilityChange);
239
+ super.disconnectedCallback();
240
+ }
241
+ /** Normalizes external index changes before rendering. */
242
+ willUpdate(changed) {
243
+ if (!changed.has("currentIndex"))
244
+ return;
245
+ const normalized = this._normalizeIndex(this.currentIndex);
246
+ if (normalized !== this.currentIndex) {
247
+ this.currentIndex = normalized;
248
+ }
249
+ const previousValue = changed.get("currentIndex");
250
+ if (previousValue === undefined || this._galleryItems.length === 0) {
251
+ this._nextChangeReason = null;
252
+ return;
253
+ }
254
+ const previousIndex = this._normalizeIndex(Number(previousValue));
255
+ if (previousIndex === normalized) {
256
+ this._nextChangeReason = null;
257
+ return;
258
+ }
259
+ const reason = this._nextChangeReason ?? "programmatic";
260
+ this._previousIndex = reason === "items" ? null : previousIndex;
261
+ this._pendingChange = {
262
+ previousIndex,
263
+ currentIndex: normalized,
264
+ item: this._galleryItems[normalized],
265
+ reason,
266
+ };
267
+ this._nextChangeReason = null;
268
+ }
269
+ /** Emits completed changes and keeps autoplay synchronized with properties. */
270
+ updated(changed) {
271
+ if (this._pendingChange) {
272
+ this.dispatchEvent(new CustomEvent("slide-change", {
273
+ bubbles: true,
274
+ composed: true,
275
+ detail: this._pendingChange,
276
+ }));
277
+ this._pendingChange = undefined;
278
+ this._scheduleTransitionCleanup();
279
+ }
280
+ if (changed.has("currentIndex") || changed.has("delay") || changed.has("paused") || this._itemsChanged) {
281
+ this._itemsChanged = false;
282
+ this._restartAutoplay();
283
+ }
284
+ this._activeItem = this._galleryItems[this.currentIndex];
285
+ this._renderedIndex = this.currentIndex;
286
+ }
287
+ /** Wraps any requested index into the current item range. */
288
+ _normalizeIndex(index) {
289
+ const count = this._galleryItems.length;
290
+ if (count === 0 || !Number.isFinite(index))
291
+ return 0;
292
+ return ((Math.trunc(index) % count) + count) % count;
293
+ }
294
+ /** Returns responsive variants declared directly under an item. */
295
+ _variantsFor(item) {
296
+ return Array.from(item.children).filter((child) => child.tagName.toLowerCase() === "gallery-item-variant");
297
+ }
298
+ /** Changes slides through the shared state and event path. */
299
+ _goTo(index, reason) {
300
+ const normalized = this._normalizeIndex(index);
301
+ if (this._galleryItems.length < 2 || normalized === this.currentIndex) {
302
+ this._restartAutoplay();
303
+ return;
304
+ }
305
+ this._nextChangeReason = reason;
306
+ this.currentIndex = normalized;
307
+ }
308
+ /** Moves to the previous image. */
309
+ _showPrevious(reason = "previous") {
310
+ this._goTo(this.currentIndex - 1, reason);
311
+ }
312
+ /** Moves to the next image. */
313
+ _showNext(reason = "next") {
314
+ this._goTo(this.currentIndex + 1, reason);
315
+ }
316
+ /** Toggles explicit autoplay pause state. */
317
+ _togglePaused() {
318
+ this.paused = !this.paused;
319
+ }
320
+ /** Clears and conditionally schedules the next autoplay advance. */
321
+ _restartAutoplay() {
322
+ this._clearAutoplay();
323
+ if (!this._canAutoplay())
324
+ return;
325
+ this._autoplayTimer = window.setTimeout(() => {
326
+ this._showNext("autoplay");
327
+ }, this.delay);
328
+ }
329
+ /** Reports whether autoplay may currently schedule a transition. */
330
+ _canAutoplay() {
331
+ return (this.delay > 0 &&
332
+ this._galleryItems.length > 1 &&
333
+ !this.paused &&
334
+ !this._hovered &&
335
+ !this._focusWithin &&
336
+ !document.hidden);
337
+ }
338
+ /** Clears the pending autoplay timeout. */
339
+ _clearAutoplay() {
340
+ if (this._autoplayTimer === undefined)
341
+ return;
342
+ window.clearTimeout(this._autoplayTimer);
343
+ this._autoplayTimer = undefined;
344
+ }
345
+ /** Removes the outgoing crossfade layer after the animation completes. */
346
+ _scheduleTransitionCleanup() {
347
+ this._clearTransition();
348
+ this._transitionTimer = window.setTimeout(() => {
349
+ this._previousIndex = null;
350
+ this._transitionTimer = undefined;
351
+ }, transitionDurationMs);
352
+ }
353
+ /** Clears pending transition cleanup. */
354
+ _clearTransition() {
355
+ if (this._transitionTimer === undefined)
356
+ return;
357
+ window.clearTimeout(this._transitionTimer);
358
+ this._transitionTimer = undefined;
359
+ }
360
+ /** Refreshes item metadata and clamps the active index after light-DOM changes. */
361
+ _handleMetadataChange() {
362
+ this._itemsChanged = true;
363
+ this._itemsVersion += 1;
364
+ const preserveActiveItem = this.currentIndex === this._renderedIndex;
365
+ const preservedIndex = preserveActiveItem && this._activeItem ? this._galleryItems.indexOf(this._activeItem) : -1;
366
+ const normalized = preservedIndex >= 0 ? preservedIndex : this._normalizeIndex(this.currentIndex);
367
+ if (normalized === this.currentIndex) {
368
+ const item = this._galleryItems[normalized];
369
+ const activeItemRemoved = Boolean(this._activeItem && !this._galleryItems.includes(this._activeItem));
370
+ if (item && activeItemRemoved) {
371
+ this._previousIndex = null;
372
+ this._pendingChange = {
373
+ previousIndex: this._renderedIndex,
374
+ currentIndex: normalized,
375
+ item,
376
+ reason: "items",
377
+ };
378
+ }
379
+ return;
380
+ }
381
+ this._nextChangeReason = "items";
382
+ this.currentIndex = normalized;
383
+ }
384
+ /** Refreshes item state after the default slot changes. */
385
+ _handleSlotChange() {
386
+ this._handleMetadataChange();
387
+ }
388
+ /** Temporarily pauses autoplay while the pointer is over the gallery. */
389
+ _handleMouseEnter() {
390
+ this._hovered = true;
391
+ this._restartAutoplay();
392
+ }
393
+ /** Resumes autoplay with a fresh delay after hover ends. */
394
+ _handleMouseLeave() {
395
+ this._hovered = false;
396
+ this._restartAutoplay();
397
+ }
398
+ /** Temporarily pauses autoplay while focus is inside the gallery. */
399
+ _handleFocusIn() {
400
+ this._focusWithin = true;
401
+ this._restartAutoplay();
402
+ }
403
+ /** Resumes autoplay with a fresh delay after focus leaves the gallery. */
404
+ _handleFocusOut() {
405
+ queueMicrotask(() => {
406
+ this._focusWithin = this.matches(":focus-within");
407
+ this._restartAutoplay();
408
+ });
409
+ }
410
+ /** Handles Left and Right arrow keyboard navigation. */
411
+ _handleKeyDown(event) {
412
+ if (event.key === "ArrowLeft") {
413
+ event.preventDefault();
414
+ this._showPrevious("keyboard");
415
+ return;
416
+ }
417
+ if (event.key === "ArrowRight") {
418
+ event.preventDefault();
419
+ this._showNext("keyboard");
420
+ }
421
+ }
422
+ /** Records the starting point of a primary pointer gesture. */
423
+ _handlePointerDown(event) {
424
+ if (!event.isPrimary || event.button !== 0)
425
+ return;
426
+ if (event.composedPath().some((target) => target instanceof HTMLButtonElement))
427
+ return;
428
+ this._pointerStart = { id: event.pointerId, x: event.clientX, y: event.clientY };
429
+ event.currentTarget.setPointerCapture(event.pointerId);
430
+ }
431
+ /** Converts a sufficiently horizontal pointer gesture into navigation. */
432
+ _handlePointerUp(event) {
433
+ const start = this._pointerStart;
434
+ this._pointerStart = undefined;
435
+ if (!start || start.id !== event.pointerId)
436
+ return;
437
+ const deltaX = event.clientX - start.x;
438
+ const deltaY = event.clientY - start.y;
439
+ if (Math.abs(deltaX) < swipeThresholdPx || Math.abs(deltaX) <= Math.abs(deltaY))
440
+ return;
441
+ event.preventDefault();
442
+ if (deltaX < 0) {
443
+ this._showNext("swipe");
444
+ return;
445
+ }
446
+ this._showPrevious("swipe");
447
+ }
448
+ /** Cancels an incomplete pointer gesture. */
449
+ _handlePointerCancel() {
450
+ this._pointerStart = undefined;
451
+ }
452
+ /** Renders one responsive image layer for the crossfade stack. */
453
+ _renderPicture(index, state) {
454
+ const item = this._galleryItems[index];
455
+ if (!item)
456
+ return nothing;
457
+ const isPrevious = state === "previous";
458
+ const transitionClass = this._previousIndex === null ? "" : isPrevious ? "leaving" : "entering";
459
+ return html `
460
+ <picture class=${transitionClass} aria-hidden=${isPrevious ? "true" : nothing}>
461
+ ${this._variantsFor(item)
462
+ .filter((variant) => variant.srcset)
463
+ .map((variant) => html `<source media=${ifDefined(variant.media || undefined)} srcset=${variant.srcset} />`)}
464
+ <img src=${item.src} alt=${isPrevious ? "" : item.alt} draggable="false" />
465
+ </picture>
466
+ `;
467
+ }
468
+ /** Renders enabled counter, indicator, and autoplay controls. */
469
+ _renderFooter(itemCount) {
470
+ const showIndicators = this.showIndicators && itemCount > 1;
471
+ const showAutoplay = this.showAutoplayControl && this.delay > 0 && itemCount > 1;
472
+ if (!this.showCounter && !showIndicators && !showAutoplay)
473
+ return nothing;
474
+ return html `
475
+ <div class="footer">
476
+ ${this.showCounter
477
+ ? html `<span class="counter">${this.currentIndex + 1} / ${itemCount}</span>`
478
+ : nothing}
479
+ ${showIndicators
480
+ ? html `
481
+ <div class="indicators" role="group" aria-label="Choose image">
482
+ ${this._galleryItems.map((_item, index) => html `
483
+ <button
484
+ class="indicator"
485
+ type="button"
486
+ aria-label="Show image ${index + 1} of ${itemCount}"
487
+ aria-current=${String(index === this.currentIndex)}
488
+ @click=${() => this._goTo(index, "indicator")}
489
+ ></button>
490
+ `)}
491
+ </div>
492
+ `
493
+ : nothing}
494
+ ${showAutoplay
495
+ ? html `
496
+ <button
497
+ class="autoplay-button"
498
+ type="button"
499
+ aria-label=${this.paused ? "Resume slideshow" : "Pause slideshow"}
500
+ @click=${this._togglePaused}
501
+ >
502
+ ${this.paused ? "Play" : "Pause"}
503
+ </button>
504
+ `
505
+ : nothing}
506
+ </div>
507
+ `;
508
+ }
509
+ /** Renders the active image, navigation, caption, and hidden metadata slot. */
510
+ render() {
511
+ const itemCount = this._galleryItems.length;
512
+ const currentItem = this._galleryItems[this.currentIndex];
513
+ const objectFit = this.objectFit === "contain" ? "contain" : "cover";
514
+ const viewportStyles = {
515
+ "--photo-gallery-aspect-ratio": this.aspectRatio.trim() || "16 / 9",
516
+ "--photo-gallery-object-fit": objectFit,
517
+ };
518
+ return html `
519
+ <div
520
+ class="gallery"
521
+ role="region"
522
+ aria-roledescription="carousel"
523
+ aria-label="Photo gallery"
524
+ tabindex="0"
525
+ @keydown=${this._handleKeyDown}
526
+ @mouseenter=${this._handleMouseEnter}
527
+ @mouseleave=${this._handleMouseLeave}
528
+ @focusin=${this._handleFocusIn}
529
+ @focusout=${this._handleFocusOut}
530
+ >
531
+ ${currentItem
532
+ ? html `
533
+ <figure>
534
+ <div
535
+ class="viewport"
536
+ style=${styleMap(viewportStyles)}
537
+ @pointerdown=${this._handlePointerDown}
538
+ @pointerup=${this._handlePointerUp}
539
+ @pointercancel=${this._handlePointerCancel}
540
+ >
541
+ <div class="slides">
542
+ ${this._previousIndex === null
543
+ ? nothing
544
+ : this._renderPicture(this._previousIndex, "previous")}
545
+ ${this._renderPicture(this.currentIndex, "current")}
546
+ </div>
547
+ ${this.showControls && itemCount > 1
548
+ ? html `
549
+ <div class="arrow-controls">
550
+ <button
551
+ class="arrow-button previous"
552
+ type="button"
553
+ aria-label="Previous image"
554
+ @click=${() => this._showPrevious()}
555
+ >
556
+ ${iconChevronLeft(24)}
557
+ </button>
558
+ <button
559
+ class="arrow-button next"
560
+ type="button"
561
+ aria-label="Next image"
562
+ @click=${() => this._showNext()}
563
+ >
564
+ ${iconChevronRight(24)}
565
+ </button>
566
+ </div>
567
+ `
568
+ : nothing}
569
+ </div>
570
+ ${currentItem.caption ? html `<figcaption>${currentItem.caption}</figcaption>` : nothing}
571
+ </figure>
572
+ ${this._renderFooter(itemCount)}
573
+ `
574
+ : nothing}
575
+ <slot @slotchange=${this._handleSlotChange}></slot>
576
+ </div>
577
+ `;
578
+ }
579
+ };
580
+ __decorate([
581
+ property({ type: Number, attribute: "current-index", reflect: true })
582
+ ], PhotoGallery.prototype, "currentIndex", void 0);
583
+ __decorate([
584
+ property({ type: Number })
585
+ ], PhotoGallery.prototype, "delay", void 0);
586
+ __decorate([
587
+ property({ attribute: "show-controls", converter: booleanAttribute })
588
+ ], PhotoGallery.prototype, "showControls", void 0);
589
+ __decorate([
590
+ property({ type: Boolean, attribute: "show-counter" })
591
+ ], PhotoGallery.prototype, "showCounter", void 0);
592
+ __decorate([
593
+ property({ type: Boolean, attribute: "show-indicators" })
594
+ ], PhotoGallery.prototype, "showIndicators", void 0);
595
+ __decorate([
596
+ property({ attribute: "show-autoplay-control", converter: booleanAttribute })
597
+ ], PhotoGallery.prototype, "showAutoplayControl", void 0);
598
+ __decorate([
599
+ property({ type: Boolean, reflect: true })
600
+ ], PhotoGallery.prototype, "paused", void 0);
601
+ __decorate([
602
+ property({ attribute: "aspect-ratio" })
603
+ ], PhotoGallery.prototype, "aspectRatio", void 0);
604
+ __decorate([
605
+ property({ attribute: "object-fit" })
606
+ ], PhotoGallery.prototype, "objectFit", void 0);
607
+ __decorate([
608
+ queryAssignedElements({ selector: "gallery-item" })
609
+ ], PhotoGallery.prototype, "_galleryItems", void 0);
610
+ __decorate([
611
+ state()
612
+ ], PhotoGallery.prototype, "_previousIndex", void 0);
613
+ __decorate([
614
+ state()
615
+ ], PhotoGallery.prototype, "_itemsVersion", void 0);
616
+ PhotoGallery = __decorate([
617
+ customElement("photo-gallery")
618
+ ], PhotoGallery);
619
+ export { PhotoGallery };
620
+ //# sourceMappingURL=photo-gallery.js.map