@sankhyatronics/sankhya-cms 0.1.18 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/custom-elements.json +11634 -3153
- package/dist/attention-panel/index.js +2 -2
- package/dist/bar-chart/index.js +2 -2
- package/dist/bento-grid/index.d.ts +33 -1
- package/dist/bento-grid/index.js +4 -3
- package/dist/booking/index.d.ts +309 -0
- package/dist/booking/index.js +20 -0
- package/dist/booking/index.js.map +1 -0
- package/dist/card/index.d.ts +3 -4
- package/dist/card/index.js +2 -2
- package/dist/carousel/index.d.ts +20 -6
- package/dist/carousel/index.js +3 -3
- package/dist/chip/index.js +2 -2
- package/dist/{chunk-JQY2G4QK.js → chunk-2GTR37PU.js} +2 -2
- package/dist/chunk-2GTR37PU.js.map +1 -0
- package/dist/{chunk-FLY7TNRT.js → chunk-2HMOX253.js} +128 -25
- package/dist/chunk-2HMOX253.js.map +1 -0
- package/dist/{chunk-DH53HZPB.js → chunk-37KFBKPD.js} +32 -4
- package/dist/chunk-37KFBKPD.js.map +1 -0
- package/dist/{chunk-ALI26WOB.js → chunk-4XPKKYVZ.js} +54 -15
- package/dist/chunk-4XPKKYVZ.js.map +1 -0
- package/dist/chunk-535QAZ6A.js +236 -0
- package/dist/chunk-535QAZ6A.js.map +1 -0
- package/dist/{chunk-AKJQ345O.js → chunk-5AWGZQWU.js} +2 -2
- package/dist/chunk-6OZKZG5J.js +300 -0
- package/dist/chunk-6OZKZG5J.js.map +1 -0
- package/dist/chunk-AYNT7G3J.js +805 -0
- package/dist/chunk-AYNT7G3J.js.map +1 -0
- package/dist/chunk-BEWX3E6P.js +32 -0
- package/dist/chunk-BEWX3E6P.js.map +1 -0
- package/dist/chunk-CZUGPKXV.js +275 -0
- package/dist/chunk-CZUGPKXV.js.map +1 -0
- package/dist/{chunk-LEXZKGQX.js → chunk-DJFWZOZM.js} +107 -11
- package/dist/chunk-DJFWZOZM.js.map +1 -0
- package/dist/chunk-DPANTC3O.js +1714 -0
- package/dist/chunk-DPANTC3O.js.map +1 -0
- package/dist/chunk-EKZFFY45.js +426 -0
- package/dist/chunk-EKZFFY45.js.map +1 -0
- package/dist/chunk-ER7MCPDV.js +7 -0
- package/dist/chunk-ER7MCPDV.js.map +1 -0
- package/dist/chunk-EW2RK5Y6.js +383 -0
- package/dist/chunk-EW2RK5Y6.js.map +1 -0
- package/dist/{chunk-BLQV2YMO.js → chunk-EZOKT7NJ.js} +2 -2
- package/dist/chunk-FF2LWEF3.js +386 -0
- package/dist/chunk-FF2LWEF3.js.map +1 -0
- package/dist/chunk-FOUK3NHR.js +7 -0
- package/dist/chunk-FOUK3NHR.js.map +1 -0
- package/dist/chunk-GB4NGCZI.js +181 -0
- package/dist/chunk-GB4NGCZI.js.map +1 -0
- package/dist/{chunk-7NLZND6Q.js → chunk-GOFSMD6W.js} +35 -11
- package/dist/chunk-GOFSMD6W.js.map +1 -0
- package/dist/{chunk-6D6ROU7X.js → chunk-IGMVF3KK.js} +2 -2
- package/dist/{chunk-INMSEYT6.js → chunk-IVPVYVWG.js} +2 -2
- package/dist/chunk-JURCF4OD.js +381 -0
- package/dist/chunk-JURCF4OD.js.map +1 -0
- package/dist/{chunk-FZ36KL73.js → chunk-KZ7PMFWS.js} +11 -1
- package/dist/chunk-KZ7PMFWS.js.map +1 -0
- package/dist/{chunk-EMCQBT3S.js → chunk-LO6TZBGD.js} +129 -35
- package/dist/chunk-LO6TZBGD.js.map +1 -0
- package/dist/chunk-MFRGAT6D.js +860 -0
- package/dist/chunk-MFRGAT6D.js.map +1 -0
- package/dist/chunk-MIBVQXRU.js +1098 -0
- package/dist/chunk-MIBVQXRU.js.map +1 -0
- package/dist/{chunk-35TX3AOA.js → chunk-NABSRUXG.js} +2 -2
- package/dist/{chunk-R5G6KFTJ.js → chunk-NXKDZWS7.js} +44 -6
- package/dist/chunk-NXKDZWS7.js.map +1 -0
- package/dist/{chunk-KMU6ABQF.js → chunk-NXUS2CH7.js} +14 -1
- package/dist/chunk-NXUS2CH7.js.map +1 -0
- package/dist/{chunk-GJO3RGOB.js → chunk-OCPGOLVF.js} +56 -11
- package/dist/chunk-OCPGOLVF.js.map +1 -0
- package/dist/chunk-OEOE6IFY.js +628 -0
- package/dist/chunk-OEOE6IFY.js.map +1 -0
- package/dist/{chunk-SMLR736E.js → chunk-PV6OCXXN.js} +2 -2
- package/dist/chunk-PV6OCXXN.js.map +1 -0
- package/dist/chunk-Q66CJO3P.js +534 -0
- package/dist/chunk-Q66CJO3P.js.map +1 -0
- package/dist/{chunk-MG2VTZA4.js → chunk-QS3ANOWN.js} +2 -2
- package/dist/{chunk-ZN4LIKVG.js → chunk-QSJ543V2.js} +2 -2
- package/dist/chunk-QSJ543V2.js.map +1 -0
- package/dist/{chunk-FML6AG2V.js → chunk-RANC3OI6.js} +2 -2
- package/dist/chunk-T4BIN37Q.js +32 -0
- package/dist/chunk-T4BIN37Q.js.map +1 -0
- package/dist/{chunk-YVTFQHVY.js → chunk-TEAZZPDQ.js} +2 -2
- package/dist/chunk-TJK55CJ2.js +49 -0
- package/dist/chunk-TJK55CJ2.js.map +1 -0
- package/dist/chunk-UKIVLF7S.js +32 -0
- package/dist/chunk-UKIVLF7S.js.map +1 -0
- package/dist/chunk-V4R7PYP5.js +905 -0
- package/dist/chunk-V4R7PYP5.js.map +1 -0
- package/dist/{chunk-AG2COC64.js → chunk-VVYQ2DDS.js} +2 -2
- package/dist/chunk-WAMOAAMN.js +16 -0
- package/dist/chunk-WAMOAAMN.js.map +1 -0
- package/dist/chunk-WAYHHL4J.js +1234 -0
- package/dist/chunk-WAYHHL4J.js.map +1 -0
- package/dist/{chunk-YQ42EBK5.js → chunk-WH6HE6SY.js} +10 -4
- package/dist/chunk-WH6HE6SY.js.map +1 -0
- package/dist/chunk-XP6DI3VY.js +180 -0
- package/dist/chunk-XP6DI3VY.js.map +1 -0
- package/dist/{chunk-5EBWMPJS.js → chunk-XS6LNTSH.js} +76 -14
- package/dist/chunk-XS6LNTSH.js.map +1 -0
- package/dist/{chunk-WT4OATGP.js → chunk-ZKFCDVB4.js} +16 -7
- package/dist/chunk-ZKFCDVB4.js.map +1 -0
- package/dist/cms-theme.css +29 -0
- package/dist/contact-form/index.d.ts +220 -0
- package/dist/contact-form/index.js +16 -0
- package/dist/contact-form/index.js.map +1 -0
- package/dist/content-block/index.d.ts +39 -4
- package/dist/content-block/index.js +8 -4
- package/dist/cookie-consent/index.d.ts +60 -12
- package/dist/cookie-consent/index.js +3 -2
- package/dist/date-tile/index.js +2 -2
- package/dist/dropdown/index.d.ts +29 -11
- package/dist/dropdown/index.js +4 -2
- package/dist/feature-split/index.d.ts +6 -1
- package/dist/feature-split/index.js +5 -4
- package/dist/features-section/index.d.ts +53 -9
- package/dist/features-section/index.js +6 -5
- package/dist/flow/index.d.ts +35 -0
- package/dist/flow/index.js +9 -0
- package/dist/flow/index.js.map +1 -0
- package/dist/footer/index.d.ts +13 -0
- package/dist/footer/index.js +2 -2
- package/dist/header/index.d.ts +135 -16
- package/dist/header/index.js +3 -2
- package/dist/hero/index.d.ts +92 -8
- package/dist/hero/index.js +6 -3
- package/dist/icon-button/index.d.ts +7 -7
- package/dist/icon-button/index.js +2 -2
- package/dist/index.d.ts +12 -3
- package/dist/index.js +121 -47
- package/dist/items-accordion/index.d.ts +9 -0
- package/dist/items-accordion/index.js +4 -3
- package/dist/kpi-card/index.js +2 -2
- package/dist/markdown/index.d.ts +19 -2
- package/dist/markdown/index.js +3 -2
- package/dist/mega-menu/index.d.ts +95 -7
- package/dist/mega-menu/index.js +7 -2
- package/dist/menu-grid/index.d.ts +2 -3
- package/dist/menu-grid/index.js +2 -2
- package/dist/menu-grid-item/index.d.ts +6 -8
- package/dist/menu-grid-item/index.js +2 -2
- package/dist/menu-item/index.d.ts +11 -7
- package/dist/menu-item/index.js +3 -2
- package/dist/plan-cards/index.d.ts +69 -0
- package/dist/plan-cards/index.js +13 -0
- package/dist/plan-cards/index.js.map +1 -0
- package/dist/product-nav/index.d.ts +127 -0
- package/dist/product-nav/index.js +11 -0
- package/dist/product-nav/index.js.map +1 -0
- package/dist/promo-banner/index.d.ts +42 -4
- package/dist/promo-banner/index.js +6 -3
- package/dist/quote-dialog/index.d.ts +174 -0
- package/dist/quote-dialog/index.js +22 -0
- package/dist/quote-dialog/index.js.map +1 -0
- package/dist/schema/index.d.ts +11 -0
- package/dist/schema/index.js +9 -0
- package/dist/schema/index.js.map +1 -1
- package/dist/screenshot-tour/index.d.ts +54 -0
- package/dist/screenshot-tour/index.js +9 -0
- package/dist/screenshot-tour/index.js.map +1 -0
- package/dist/section/index.d.ts +3 -0
- package/dist/section/index.js +3 -3
- package/dist/segmented-control/index.js +2 -2
- package/dist/select/index.js +2 -2
- package/dist/shared/styles.d.ts +7 -1
- package/dist/shared/styles.js +3 -1
- package/dist/stats/index.js +2 -2
- package/dist/steps/index.d.ts +45 -0
- package/dist/steps/index.js +11 -0
- package/dist/steps/index.js.map +1 -0
- package/dist/tag-strip/index.d.ts +33 -0
- package/dist/tag-strip/index.js +9 -0
- package/dist/tag-strip/index.js.map +1 -0
- package/dist/testimonials/index.d.ts +9 -1
- package/dist/testimonials/index.js +3 -3
- package/dist/tooltip/index.js +2 -2
- package/package.json +38 -2
- package/dist/chunk-5EBWMPJS.js.map +0 -1
- package/dist/chunk-76AVBQUA.js +0 -252
- package/dist/chunk-76AVBQUA.js.map +0 -1
- package/dist/chunk-7NLZND6Q.js.map +0 -1
- package/dist/chunk-ALI26WOB.js.map +0 -1
- package/dist/chunk-BMHMNXIA.js +0 -158
- package/dist/chunk-BMHMNXIA.js.map +0 -1
- package/dist/chunk-DH53HZPB.js.map +0 -1
- package/dist/chunk-EMCQBT3S.js.map +0 -1
- package/dist/chunk-FLY7TNRT.js.map +0 -1
- package/dist/chunk-FZ36KL73.js.map +0 -1
- package/dist/chunk-GJO3RGOB.js.map +0 -1
- package/dist/chunk-J6EO4R73.js +0 -633
- package/dist/chunk-J6EO4R73.js.map +0 -1
- package/dist/chunk-JKBWZLG4.js +0 -348
- package/dist/chunk-JKBWZLG4.js.map +0 -1
- package/dist/chunk-JQY2G4QK.js.map +0 -1
- package/dist/chunk-KMU6ABQF.js.map +0 -1
- package/dist/chunk-LEXZKGQX.js.map +0 -1
- package/dist/chunk-MSSH3HFK.js +0 -205
- package/dist/chunk-MSSH3HFK.js.map +0 -1
- package/dist/chunk-R5G6KFTJ.js.map +0 -1
- package/dist/chunk-SMLR736E.js.map +0 -1
- package/dist/chunk-VWS53WY4.js +0 -157
- package/dist/chunk-VWS53WY4.js.map +0 -1
- package/dist/chunk-WT4OATGP.js.map +0 -1
- package/dist/chunk-XWB4CKDU.js +0 -708
- package/dist/chunk-XWB4CKDU.js.map +0 -1
- package/dist/chunk-YQ42EBK5.js.map +0 -1
- package/dist/chunk-ZN4LIKVG.js.map +0 -1
- /package/dist/{chunk-AKJQ345O.js.map → chunk-5AWGZQWU.js.map} +0 -0
- /package/dist/{chunk-BLQV2YMO.js.map → chunk-EZOKT7NJ.js.map} +0 -0
- /package/dist/{chunk-6D6ROU7X.js.map → chunk-IGMVF3KK.js.map} +0 -0
- /package/dist/{chunk-INMSEYT6.js.map → chunk-IVPVYVWG.js.map} +0 -0
- /package/dist/{chunk-35TX3AOA.js.map → chunk-NABSRUXG.js.map} +0 -0
- /package/dist/{chunk-MG2VTZA4.js.map → chunk-QS3ANOWN.js.map} +0 -0
- /package/dist/{chunk-FML6AG2V.js.map → chunk-RANC3OI6.js.map} +0 -0
- /package/dist/{chunk-YVTFQHVY.js.map → chunk-TEAZZPDQ.js.map} +0 -0
- /package/dist/{chunk-AG2COC64.js.map → chunk-VVYQ2DDS.js.map} +0 -0
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
reducedMotionStyles
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-KZ7PMFWS.js";
|
|
4
4
|
import {
|
|
5
5
|
buttonResetStyles,
|
|
6
6
|
controlBaseStyles
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-NXUS2CH7.js";
|
|
8
8
|
import {
|
|
9
9
|
__decorateClass
|
|
10
10
|
} from "./chunk-EUXUH3YW.js";
|
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
// src/carousel/Carousel.ts
|
|
13
13
|
import { LitElement, css, html, nothing } from "lit";
|
|
14
14
|
import { customElement, property, state } from "lit/decorators.js";
|
|
15
|
+
var REDUCED_MOTION_QUERY = "(prefers-reduced-motion: reduce)";
|
|
15
16
|
var Carousel = class extends LitElement {
|
|
16
17
|
constructor() {
|
|
17
18
|
super(...arguments);
|
|
@@ -27,42 +28,62 @@ var Carousel = class extends LitElement {
|
|
|
27
28
|
this.count = 0;
|
|
28
29
|
this.slideLabels = [];
|
|
29
30
|
this.userPaused = false;
|
|
30
|
-
|
|
31
|
-
this.
|
|
31
|
+
this.hovered = false;
|
|
32
|
+
this.focused = false;
|
|
33
|
+
this.turned = false;
|
|
32
34
|
/** Time left on the current slide, so a pause resumes where it stopped. */
|
|
33
35
|
this.remaining = 0;
|
|
34
36
|
this.startedAt = 0;
|
|
35
|
-
this.
|
|
36
|
-
|
|
37
|
-
if (this.pauseOnHover) this.pause();
|
|
37
|
+
this.onReducedMotionChange = (event) => {
|
|
38
|
+
if (event.matches) this.hold(() => this.userPaused = true);
|
|
38
39
|
};
|
|
39
|
-
this.
|
|
40
|
-
|
|
40
|
+
this.onPointerEnter = () => {
|
|
41
|
+
if (this.pauseOnHover) this.hold(() => this.hovered = true);
|
|
42
|
+
};
|
|
43
|
+
this.onPointerLeave = () => this.hold(() => this.hovered = false);
|
|
44
|
+
/** Focus inside the carousel pauses it (WCAG 2.2.2), but focusing the play button does not, so pressing play starts it. */
|
|
45
|
+
this.onFocusIn = (event) => {
|
|
46
|
+
const target = event.composedPath()[0];
|
|
47
|
+
const onPlay = target instanceof Element && target.classList.contains("play");
|
|
48
|
+
this.hold(() => this.focused = !onPlay);
|
|
49
|
+
};
|
|
50
|
+
this.onFocusOut = () => this.hold(() => this.focused = false);
|
|
51
|
+
this.togglePlay = () => this.hold(() => {
|
|
52
|
+
this.userPaused = !this.userPaused;
|
|
53
|
+
this.hovered = false;
|
|
54
|
+
});
|
|
41
55
|
}
|
|
42
56
|
connectedCallback() {
|
|
43
57
|
super.connectedCallback();
|
|
44
|
-
this.
|
|
45
|
-
this.
|
|
46
|
-
this.
|
|
47
|
-
this.
|
|
58
|
+
if (!this.hasAttribute("role")) this.setAttribute("role", "region");
|
|
59
|
+
this.setAttribute("aria-roledescription", "carousel");
|
|
60
|
+
this.reducedMotion = typeof window !== "undefined" && window.matchMedia ? window.matchMedia(REDUCED_MOTION_QUERY) : void 0;
|
|
61
|
+
if (this.reducedMotion?.matches) this.hold(() => this.userPaused = true);
|
|
62
|
+
this.reducedMotion?.addEventListener("change", this.onReducedMotionChange);
|
|
63
|
+
this.addEventListener("mouseenter", this.onPointerEnter);
|
|
64
|
+
this.addEventListener("mouseleave", this.onPointerLeave);
|
|
65
|
+
this.addEventListener("focusin", this.onFocusIn);
|
|
66
|
+
this.addEventListener("focusout", this.onFocusOut);
|
|
48
67
|
}
|
|
49
68
|
disconnectedCallback() {
|
|
50
69
|
this.stopTimer();
|
|
51
|
-
this.removeEventListener("
|
|
52
|
-
this.
|
|
53
|
-
this.removeEventListener("
|
|
54
|
-
this.removeEventListener("
|
|
70
|
+
this.reducedMotion?.removeEventListener("change", this.onReducedMotionChange);
|
|
71
|
+
this.reducedMotion = void 0;
|
|
72
|
+
this.removeEventListener("mouseenter", this.onPointerEnter);
|
|
73
|
+
this.removeEventListener("mouseleave", this.onPointerLeave);
|
|
74
|
+
this.removeEventListener("focusin", this.onFocusIn);
|
|
75
|
+
this.removeEventListener("focusout", this.onFocusOut);
|
|
55
76
|
super.disconnectedCallback();
|
|
56
77
|
}
|
|
57
78
|
willUpdate(changed) {
|
|
58
79
|
if (changed.has("interval")) this.style.setProperty("--st-carousel-interval", `${this.interval}ms`);
|
|
59
80
|
}
|
|
60
81
|
updated(changed) {
|
|
61
|
-
if (changed.has("index") || changed.has("count") || changed.has("indicatorStyle") || changed.has("tabLabels")) this.syncSlides();
|
|
82
|
+
if (changed.has("index") || changed.has("count") || changed.has("indicatorStyle") || changed.has("tabLabels") || changed.has("turned")) this.syncSlides();
|
|
62
83
|
if (changed.has("autoPlay") || changed.has("interval") || changed.has("count")) this.restartTimer();
|
|
63
84
|
}
|
|
64
85
|
get halted() {
|
|
65
|
-
return this.
|
|
86
|
+
return this.hovered || this.focused || this.userPaused;
|
|
66
87
|
}
|
|
67
88
|
/** Applies a pause-state change, freezing or resuming the timer (and the tab progress bar). */
|
|
68
89
|
hold(update) {
|
|
@@ -85,16 +106,14 @@ var Carousel = class extends LitElement {
|
|
|
85
106
|
return this.tabLabels[i] || this.slideLabels[i] || `Slide ${i + 1}`;
|
|
86
107
|
}
|
|
87
108
|
syncSlides() {
|
|
88
|
-
const
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
el.removeAttribute("aria-label");
|
|
97
|
-
}
|
|
109
|
+
const slides = this.slides;
|
|
110
|
+
slides.forEach((el, i) => {
|
|
111
|
+
const active = i === this.index;
|
|
112
|
+
el.toggleAttribute("data-st-active", active);
|
|
113
|
+
el.toggleAttribute("data-st-still", active && !this.turned);
|
|
114
|
+
el.setAttribute("role", "group");
|
|
115
|
+
el.setAttribute("aria-roledescription", "slide");
|
|
116
|
+
el.setAttribute("aria-label", `${i + 1} of ${slides.length}`);
|
|
98
117
|
});
|
|
99
118
|
}
|
|
100
119
|
onSlotChange() {
|
|
@@ -102,8 +121,25 @@ var Carousel = class extends LitElement {
|
|
|
102
121
|
this.count = slides.length;
|
|
103
122
|
this.slideLabels = slides.map((el) => el.dataset.tabLabel || el.title || "");
|
|
104
123
|
if (this.index >= this.count) this.index = 0;
|
|
124
|
+
this.preloadImage(slides[0]);
|
|
105
125
|
this.syncSlides();
|
|
106
126
|
}
|
|
127
|
+
/**
|
|
128
|
+
* The first slide's image is the one visitors see first, so it is preloaded at high priority. The
|
|
129
|
+
* other slides are display:none (their CSS backgrounds are not fetched) until they are shown.
|
|
130
|
+
*/
|
|
131
|
+
preloadImage(slide) {
|
|
132
|
+
const src = slide?.imageSrc || slide?.getAttribute("image-src");
|
|
133
|
+
if (!src) return;
|
|
134
|
+
const preloaded = Array.from(document.head.querySelectorAll('link[rel="preload"]')).some((link2) => link2.getAttribute("href") === src);
|
|
135
|
+
if (preloaded) return;
|
|
136
|
+
const link = document.createElement("link");
|
|
137
|
+
link.rel = "preload";
|
|
138
|
+
link.as = "image";
|
|
139
|
+
link.href = src;
|
|
140
|
+
link.setAttribute("fetchpriority", "high");
|
|
141
|
+
document.head.append(link);
|
|
142
|
+
}
|
|
107
143
|
stopTimer() {
|
|
108
144
|
if (this.timer !== void 0) clearTimeout(this.timer);
|
|
109
145
|
this.timer = void 0;
|
|
@@ -120,6 +156,7 @@ var Carousel = class extends LitElement {
|
|
|
120
156
|
}
|
|
121
157
|
go(target, direction) {
|
|
122
158
|
if (this.count === 0) return;
|
|
159
|
+
this.turned = true;
|
|
123
160
|
this.setAttribute("data-direction", direction);
|
|
124
161
|
this.index = (target + this.count) % this.count;
|
|
125
162
|
this.dispatchEvent(
|
|
@@ -155,6 +192,7 @@ var Carousel = class extends LitElement {
|
|
|
155
192
|
part="tab"
|
|
156
193
|
type="button"
|
|
157
194
|
role="tab"
|
|
195
|
+
aria-label=${this.labelFor(i)}
|
|
158
196
|
class="tab ${active ? "active" : ""} ${running ? "running" : ""}"
|
|
159
197
|
aria-selected=${active ? "true" : "false"}
|
|
160
198
|
tabindex=${active ? 0 : -1}
|
|
@@ -197,7 +235,10 @@ var Carousel = class extends LitElement {
|
|
|
197
235
|
render() {
|
|
198
236
|
const multiple = this.count > 1;
|
|
199
237
|
return html`
|
|
200
|
-
<
|
|
238
|
+
<div class="viewport" part="viewport">
|
|
239
|
+
<slot @slotchange=${this.onSlotChange}></slot>
|
|
240
|
+
</div>
|
|
241
|
+
${multiple ? html`<div class="sr-only" aria-live=${this.halted ? "polite" : "off"} aria-atomic="true">${this.index + 1} of ${this.count}</div>` : nothing}
|
|
201
242
|
${this.showArrows && multiple ? html`
|
|
202
243
|
<button part="nav-button prev" class="nav prev" aria-label="Previous Slide" @click=${() => this.go(this.index - 1, "prev")}>❮</button>
|
|
203
244
|
<button part="nav-button next" class="nav next" aria-label="Next Slide" @click=${() => this.go(this.index + 1, "next")}>❯</button>
|
|
@@ -218,22 +259,51 @@ Carousel.styles = css`
|
|
|
218
259
|
|
|
219
260
|
::slotted(*) {
|
|
220
261
|
display: none !important;
|
|
262
|
+
box-sizing: border-box;
|
|
263
|
+
width: 100%;
|
|
264
|
+
min-width: 100%;
|
|
265
|
+
max-width: 100%;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/* The slides sit in a clipping viewport and each is exactly the carousel's width, so the next
|
|
269
|
+
slide never shows at the edge; the slide animations move inside the viewport. */
|
|
270
|
+
.viewport {
|
|
271
|
+
position: relative;
|
|
272
|
+
width: 100%;
|
|
273
|
+
overflow: hidden;
|
|
221
274
|
}
|
|
222
275
|
|
|
223
276
|
::slotted([data-st-active]) {
|
|
224
277
|
display: block !important;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/* data-st-still (set on the first slide until the first change) keeps the entrance off on first
|
|
281
|
+
paint, so the copy is there at once; later changes animate. */
|
|
282
|
+
::slotted([data-st-active]:not([data-st-still])) {
|
|
225
283
|
animation: st-carousel-in-next 0.4s ease both;
|
|
226
284
|
}
|
|
227
285
|
|
|
228
|
-
:host([data-direction='prev']) ::slotted([data-st-active]) {
|
|
286
|
+
:host([data-direction='prev']) ::slotted([data-st-active]:not([data-st-still])) {
|
|
229
287
|
animation-name: st-carousel-in-prev;
|
|
230
288
|
}
|
|
231
289
|
|
|
232
|
-
:host([transition='fade']) ::slotted([data-st-active]),
|
|
233
|
-
:host([transition='fade'][data-direction]) ::slotted([data-st-active]) {
|
|
290
|
+
:host([transition='fade']) ::slotted([data-st-active]:not([data-st-still])),
|
|
291
|
+
:host([transition='fade'][data-direction]) ::slotted([data-st-active]:not([data-st-still])) {
|
|
234
292
|
animation: st-carousel-fade 0.7s ease both;
|
|
235
293
|
}
|
|
236
294
|
|
|
295
|
+
.sr-only {
|
|
296
|
+
position: absolute;
|
|
297
|
+
width: 1px;
|
|
298
|
+
height: 1px;
|
|
299
|
+
margin: -1px;
|
|
300
|
+
padding: 0;
|
|
301
|
+
overflow: hidden;
|
|
302
|
+
clip: rect(0 0 0 0);
|
|
303
|
+
white-space: nowrap;
|
|
304
|
+
border: 0;
|
|
305
|
+
}
|
|
306
|
+
|
|
237
307
|
@keyframes st-carousel-in-next {
|
|
238
308
|
from {
|
|
239
309
|
transform: translateX(10%);
|
|
@@ -366,6 +436,7 @@ Carousel.styles = css`
|
|
|
366
436
|
|
|
367
437
|
.tab {
|
|
368
438
|
${buttonResetStyles}
|
|
439
|
+
position: relative;
|
|
369
440
|
display: flex;
|
|
370
441
|
flex-direction: column;
|
|
371
442
|
gap: var(--st-space-12);
|
|
@@ -390,6 +461,19 @@ Carousel.styles = css`
|
|
|
390
461
|
outline-offset: 4px;
|
|
391
462
|
}
|
|
392
463
|
|
|
464
|
+
/* Touch targets: the tab and the pause button keep their look; a pseudo-element extends the tap
|
|
465
|
+
area to at least 44x44 CSS px. */
|
|
466
|
+
.tab::after,
|
|
467
|
+
.play::after {
|
|
468
|
+
content: '';
|
|
469
|
+
position: absolute;
|
|
470
|
+
top: 50%;
|
|
471
|
+
left: 50%;
|
|
472
|
+
width: max(100%, 44px);
|
|
473
|
+
height: max(100%, 44px);
|
|
474
|
+
transform: translate(-50%, -50%);
|
|
475
|
+
}
|
|
476
|
+
|
|
393
477
|
.progress {
|
|
394
478
|
position: relative;
|
|
395
479
|
display: block;
|
|
@@ -430,6 +514,7 @@ Carousel.styles = css`
|
|
|
430
514
|
|
|
431
515
|
.play {
|
|
432
516
|
${buttonResetStyles}
|
|
517
|
+
position: relative;
|
|
433
518
|
flex: none;
|
|
434
519
|
display: inline-flex;
|
|
435
520
|
align-items: center;
|
|
@@ -481,7 +566,7 @@ Carousel.styles = css`
|
|
|
481
566
|
${reducedMotionStyles}
|
|
482
567
|
@media (prefers-reduced-motion: reduce) {
|
|
483
568
|
::slotted([data-st-active]) {
|
|
484
|
-
animation: none;
|
|
569
|
+
animation: none !important;
|
|
485
570
|
}
|
|
486
571
|
.tab.active.running .fill {
|
|
487
572
|
animation: none;
|
|
@@ -524,6 +609,15 @@ __decorateClass([
|
|
|
524
609
|
__decorateClass([
|
|
525
610
|
state()
|
|
526
611
|
], Carousel.prototype, "userPaused", 2);
|
|
612
|
+
__decorateClass([
|
|
613
|
+
state()
|
|
614
|
+
], Carousel.prototype, "hovered", 2);
|
|
615
|
+
__decorateClass([
|
|
616
|
+
state()
|
|
617
|
+
], Carousel.prototype, "focused", 2);
|
|
618
|
+
__decorateClass([
|
|
619
|
+
state()
|
|
620
|
+
], Carousel.prototype, "turned", 2);
|
|
527
621
|
Carousel = __decorateClass([
|
|
528
622
|
customElement("st-carousel")
|
|
529
623
|
], Carousel);
|
|
@@ -531,4 +625,4 @@ Carousel = __decorateClass([
|
|
|
531
625
|
export {
|
|
532
626
|
Carousel
|
|
533
627
|
};
|
|
534
|
-
//# sourceMappingURL=chunk-
|
|
628
|
+
//# sourceMappingURL=chunk-LO6TZBGD.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/carousel/Carousel.ts"],"sourcesContent":["import { LitElement, css, html, nothing } from 'lit';\nimport { customElement, property, state } from 'lit/decorators.js';\n\nimport { buttonResetStyles, controlBaseStyles } from '../shared/styles';\nimport { reducedMotionStyles } from '../shared/section-styles';\nimport type { CarouselChangeEventDetail } from './CarouselEvents';\n\nconst REDUCED_MOTION_QUERY = '(prefers-reduced-motion: reduce)';\n\n/**\n * Cycles through its slotted children, one visible at a time, with optional autoplay, arrows and\n * dot indicators. The incoming slide slides in from the travel direction (CSS keyframes in place\n * of the source's framer-motion spring), or fades in with `transition=\"fade\"`. Autoplay pauses\n * while hovered (unless `pause-on-hover` is turned off, e.g. for a full-screen hero the pointer\n * nearly always rests on) or focused, and stops when the element is disconnected; a paused slide\n * keeps the time it had left. Under `prefers-reduced-motion: reduce` autoplay starts paused; the\n * tabs' play button still starts it.\n *\n * `indicator-style=\"tabs\"` replaces the dots with a row of labelled tabs along the bottom, each\n * with a progress bar that fills while its slide is showing, plus a pause button — the tabbed hero\n * carousel layout (put `st-hero`s in it). Tab labels come from `tab-labels`, else each slide's\n * `data-tab-label` attribute, else its `title`.\n *\n * @fires carousel-change - Detail `{ index }`, when the visible slide changes.\n * @cssprop --st-carousel-tab-color - Tab text and progress colour (default: light, for slides with a dark image).\n * @cssprop --st-carousel-tabs-space - Room kept free under each slide's content for the tabs (default `6rem`).\n * @csspart tabs - The tab row.\n * @csspart tab - One tab button.\n * @csspart progress - A tab's progress bar.\n */\n@customElement('st-carousel')\nexport class Carousel extends LitElement {\n static styles = css`\n ${controlBaseStyles}\n\n :host {\n display: block;\n position: relative;\n width: 100%;\n overflow: hidden;\n }\n\n ::slotted(*) {\n display: none !important;\n box-sizing: border-box;\n width: 100%;\n min-width: 100%;\n max-width: 100%;\n }\n\n /* The slides sit in a clipping viewport and each is exactly the carousel's width, so the next\n slide never shows at the edge; the slide animations move inside the viewport. */\n .viewport {\n position: relative;\n width: 100%;\n overflow: hidden;\n }\n\n ::slotted([data-st-active]) {\n display: block !important;\n }\n\n /* data-st-still (set on the first slide until the first change) keeps the entrance off on first\n paint, so the copy is there at once; later changes animate. */\n ::slotted([data-st-active]:not([data-st-still])) {\n animation: st-carousel-in-next 0.4s ease both;\n }\n\n :host([data-direction='prev']) ::slotted([data-st-active]:not([data-st-still])) {\n animation-name: st-carousel-in-prev;\n }\n\n :host([transition='fade']) ::slotted([data-st-active]:not([data-st-still])),\n :host([transition='fade'][data-direction]) ::slotted([data-st-active]:not([data-st-still])) {\n animation: st-carousel-fade 0.7s ease both;\n }\n\n .sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n margin: -1px;\n padding: 0;\n overflow: hidden;\n clip: rect(0 0 0 0);\n white-space: nowrap;\n border: 0;\n }\n\n @keyframes st-carousel-in-next {\n from {\n transform: translateX(10%);\n opacity: 0;\n }\n to {\n transform: none;\n opacity: 1;\n }\n }\n\n @keyframes st-carousel-in-prev {\n from {\n transform: translateX(-10%);\n opacity: 0;\n }\n to {\n transform: none;\n opacity: 1;\n }\n }\n\n @keyframes st-carousel-fade {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n }\n\n .nav {\n ${buttonResetStyles}\n position: absolute;\n top: 50%;\n transform: translateY(-50%);\n z-index: 10;\n display: flex;\n align-items: center;\n justify-content: center;\n width: var(--st-size-38);\n height: var(--st-size-38);\n border-radius: var(--st-radius-circle);\n border: 1px solid var(--st-color-border);\n background: var(--st-color-surface);\n color: var(--st-color-text-strong);\n font-size: var(--st-text-xl);\n opacity: 0.8;\n transition:\n opacity 0.3s ease,\n transform 0.3s ease;\n }\n\n .nav:hover {\n opacity: 1;\n transform: translateY(-50%) scale(1.1);\n }\n\n .prev {\n left: var(--st-space-12);\n }\n\n .next {\n right: var(--st-space-12);\n }\n\n .indicators {\n position: absolute;\n bottom: var(--st-space-24);\n left: 50%;\n transform: translateX(-50%);\n z-index: 10;\n display: flex;\n gap: var(--st-space-12);\n }\n\n .dot {\n ${buttonResetStyles}\n width: var(--st-space-12);\n height: var(--st-space-12);\n padding: 0;\n border-radius: var(--st-radius-circle);\n background: var(--st-color-border-strong);\n transition:\n background 0.3s ease,\n transform 0.3s ease;\n }\n\n .dot:hover {\n background: var(--st-color-text-muted);\n }\n\n .dot.active {\n background: var(--st-color-text-strong);\n transform: scale(1.2);\n }\n\n /* ---- indicator-style=\"tabs\" ---- */\n\n :host([indicator-style='tabs']) ::slotted(*) {\n padding-bottom: var(--st-carousel-tabs-space, 6rem);\n }\n\n .tabs {\n position: absolute;\n left: 0;\n right: 0;\n bottom: 0;\n z-index: 10;\n color: var(--st-carousel-tab-color, var(--st-color-on-solid));\n }\n\n .tabs-inner {\n display: flex;\n align-items: flex-start;\n gap: var(--st-space-24);\n max-width: var(--st-cms-container-max);\n margin: 0 auto;\n box-sizing: border-box;\n padding: 0 var(--st-space-24) var(--st-space-24);\n }\n\n .tablist {\n flex: 1;\n display: grid;\n grid-auto-flow: column;\n grid-auto-columns: minmax(0, 1fr);\n gap: var(--st-space-24);\n }\n\n .tab {\n ${buttonResetStyles}\n position: relative;\n display: flex;\n flex-direction: column;\n gap: var(--st-space-12);\n padding: var(--st-space-12) 0;\n color: inherit;\n text-align: left;\n font-size: var(--st-text-base);\n font-weight: var(--st-font-weight-semibold);\n line-height: 1.3;\n opacity: 0.7;\n transition: opacity 0.2s ease;\n }\n\n .tab:hover,\n .tab.active {\n opacity: 1;\n }\n\n .tab:focus-visible,\n .play:focus-visible {\n outline: 2px solid currentColor;\n outline-offset: 4px;\n }\n\n /* Touch targets: the tab and the pause button keep their look; a pseudo-element extends the tap\n area to at least 44x44 CSS px. */\n .tab::after,\n .play::after {\n content: '';\n position: absolute;\n top: 50%;\n left: 50%;\n width: max(100%, 44px);\n height: max(100%, 44px);\n transform: translate(-50%, -50%);\n }\n\n .progress {\n position: relative;\n display: block;\n height: 3px;\n border-radius: 2px;\n overflow: hidden;\n background: color-mix(in oklch, currentColor 30%, transparent);\n }\n\n .fill {\n position: absolute;\n inset: 0;\n background: currentColor;\n transform: scaleX(0);\n transform-origin: left center;\n }\n\n .tab.active .fill {\n transform: scaleX(1);\n }\n\n .tab.active.running .fill {\n animation: st-carousel-progress var(--st-carousel-interval, 5000ms) linear both;\n }\n\n :host([data-paused]) .tab.active.running .fill {\n animation-play-state: paused;\n }\n\n @keyframes st-carousel-progress {\n from {\n transform: scaleX(0);\n }\n to {\n transform: scaleX(1);\n }\n }\n\n .play {\n ${buttonResetStyles}\n position: relative;\n flex: none;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: var(--st-size-32);\n height: var(--st-size-32);\n margin-top: var(--st-space-4);\n border-radius: var(--st-radius-circle);\n color: inherit;\n box-shadow: inset 0 0 0 1.5px color-mix(in oklch, currentColor 60%, transparent);\n }\n\n .play:hover {\n background: color-mix(in oklch, currentColor 15%, transparent);\n }\n\n .tab-current {\n display: none;\n }\n\n @media (max-width: 768px) {\n .tablist {\n gap: var(--st-space-8);\n }\n\n .tab-label {\n display: none;\n }\n\n .tab-current {\n display: block;\n margin: 0 0 var(--st-space-4);\n font-size: var(--st-text-base);\n font-weight: var(--st-font-weight-semibold);\n }\n\n .tabs-inner {\n flex-wrap: wrap;\n align-items: center;\n }\n }\n\n @media (min-width: 1024px) {\n .tabs-inner {\n padding: 0 var(--st-space-32) var(--st-space-32);\n }\n }\n\n ${reducedMotionStyles}\n @media (prefers-reduced-motion: reduce) {\n ::slotted([data-st-active]) {\n animation: none !important;\n }\n .tab.active.running .fill {\n animation: none;\n }\n }\n `;\n\n @property({ type: Boolean, attribute: 'auto-play' })\n autoPlay = true;\n\n /** Autoplay delay in milliseconds. */\n @property({ type: Number })\n interval = 5000;\n\n /** Pause autoplay while the pointer is over the carousel. Turn off for a hero that fills the\n * screen; the tabs' pause button and keyboard focus still pause it. */\n @property({ type: Boolean, attribute: 'pause-on-hover' })\n pauseOnHover = true;\n\n @property({ type: Boolean, attribute: 'show-arrows' })\n showArrows = true;\n\n @property({ type: Boolean, attribute: 'show-indicators' })\n showIndicators = true;\n\n /** `dots` (default) or `tabs`: labelled tabs with progress bars along the bottom. */\n @property({ type: String, reflect: true, attribute: 'indicator-style' })\n indicatorStyle: 'dots' | 'tabs' = 'dots';\n\n /** `slide` (default) or `fade`. */\n @property({ type: String, reflect: true })\n transition: 'slide' | 'fade' = 'slide';\n\n /** Tab labels, one per slide, for `indicator-style=\"tabs\"`. Missing entries fall back to the slide's `data-tab-label`, then its `title`. */\n @property({ attribute: false })\n tabLabels: string[] = [];\n\n @state() private index = 0;\n @state() private count = 0;\n @state() private slideLabels: string[] = [];\n /** Paused with the pause button; stays paused until the button is pressed again. */\n @state() private userPaused = false;\n /** Pointer is over the carousel (only counts with `pause-on-hover`). */\n @state() private hovered = false;\n /** Focus is inside the carousel, other than the play button. */\n @state() private focused = false;\n /** False until the slides first change: the first slide is on screen at first paint and does not animate. */\n @state() private turned = false;\n private timer?: ReturnType<typeof setTimeout>;\n /** Time left on the current slide, so a pause resumes where it stopped. */\n private remaining = 0;\n private startedAt = 0;\n private reducedMotion?: MediaQueryList;\n\n private onReducedMotionChange = (event: MediaQueryListEvent) => {\n if (event.matches) this.hold(() => (this.userPaused = true));\n };\n\n connectedCallback() {\n super.connectedCallback();\n if (!this.hasAttribute('role')) this.setAttribute('role', 'region');\n this.setAttribute('aria-roledescription', 'carousel');\n // Visitors who ask for reduced motion get a still carousel: autoplay starts paused (the play\n // button still starts it), and turning the OS setting on later pauses it too.\n this.reducedMotion = typeof window !== 'undefined' && window.matchMedia ? window.matchMedia(REDUCED_MOTION_QUERY) : undefined;\n if (this.reducedMotion?.matches) this.hold(() => (this.userPaused = true));\n this.reducedMotion?.addEventListener('change', this.onReducedMotionChange);\n this.addEventListener('mouseenter', this.onPointerEnter);\n this.addEventListener('mouseleave', this.onPointerLeave);\n this.addEventListener('focusin', this.onFocusIn);\n this.addEventListener('focusout', this.onFocusOut);\n }\n\n disconnectedCallback() {\n this.stopTimer();\n this.reducedMotion?.removeEventListener('change', this.onReducedMotionChange);\n this.reducedMotion = undefined;\n this.removeEventListener('mouseenter', this.onPointerEnter);\n this.removeEventListener('mouseleave', this.onPointerLeave);\n this.removeEventListener('focusin', this.onFocusIn);\n this.removeEventListener('focusout', this.onFocusOut);\n super.disconnectedCallback();\n }\n\n protected willUpdate(changed: Map<string, unknown>) {\n if (changed.has('interval')) this.style.setProperty('--st-carousel-interval', `${this.interval}ms`);\n }\n\n protected updated(changed: Map<string, unknown>) {\n if (changed.has('index') || changed.has('count') || changed.has('indicatorStyle') || changed.has('tabLabels') || changed.has('turned')) this.syncSlides();\n if (changed.has('autoPlay') || changed.has('interval') || changed.has('count')) this.restartTimer();\n }\n\n private get halted(): boolean {\n return this.hovered || this.focused || this.userPaused;\n }\n\n /** Applies a pause-state change, freezing or resuming the timer (and the tab progress bar). */\n private hold(update: () => void) {\n const was = this.halted;\n update();\n const now = this.halted;\n if (was === now) return;\n this.toggleAttribute('data-paused', now);\n if (now) {\n if (this.timer !== undefined) this.remaining -= performance.now() - this.startedAt;\n this.stopTimer();\n } else {\n this.startTimer();\n }\n }\n\n private onPointerEnter = () => {\n if (this.pauseOnHover) this.hold(() => (this.hovered = true));\n };\n\n private onPointerLeave = () => this.hold(() => (this.hovered = false));\n\n /** Focus inside the carousel pauses it (WCAG 2.2.2), but focusing the play button does not, so pressing play starts it. */\n private onFocusIn = (event: FocusEvent) => {\n const target = event.composedPath()[0];\n const onPlay = target instanceof Element && target.classList.contains('play');\n this.hold(() => (this.focused = !onPlay));\n };\n\n private onFocusOut = () => this.hold(() => (this.focused = false));\n\n private togglePlay = () =>\n this.hold(() => {\n this.userPaused = !this.userPaused;\n // A press while the pointer rests on the carousel starts it; hover pausing applies again on re-entry.\n this.hovered = false;\n });\n\n private get slides(): Element[] {\n return this.shadowRoot?.querySelector('slot')?.assignedElements({ flatten: true }) ?? [];\n }\n\n private labelFor(i: number): string {\n return this.tabLabels[i] || this.slideLabels[i] || `Slide ${i + 1}`;\n }\n\n private syncSlides() {\n const slides = this.slides;\n slides.forEach((el, i) => {\n const active = i === this.index;\n el.toggleAttribute('data-st-active', active);\n el.toggleAttribute('data-st-still', active && !this.turned);\n el.setAttribute('role', 'group');\n el.setAttribute('aria-roledescription', 'slide');\n el.setAttribute('aria-label', `${i + 1} of ${slides.length}`);\n });\n }\n\n private onSlotChange() {\n const slides = this.slides;\n this.count = slides.length;\n this.slideLabels = slides.map(el => (el as HTMLElement).dataset.tabLabel || (el as HTMLElement).title || '');\n if (this.index >= this.count) this.index = 0;\n this.preloadImage(slides[0]);\n this.syncSlides();\n }\n\n /**\n * The first slide's image is the one visitors see first, so it is preloaded at high priority. The\n * other slides are display:none (their CSS backgrounds are not fetched) until they are shown.\n */\n private preloadImage(slide?: Element) {\n const src = (slide as (Element & { imageSrc?: string }) | undefined)?.imageSrc || slide?.getAttribute('image-src');\n if (!src) return;\n const preloaded = Array.from(document.head.querySelectorAll('link[rel=\"preload\"]')).some(link => link.getAttribute('href') === src);\n if (preloaded) return;\n const link = document.createElement('link');\n link.rel = 'preload';\n link.as = 'image';\n link.href = src;\n link.setAttribute('fetchpriority', 'high');\n document.head.append(link);\n }\n\n private stopTimer() {\n if (this.timer !== undefined) clearTimeout(this.timer);\n this.timer = undefined;\n }\n\n private startTimer() {\n this.stopTimer();\n if (!this.autoPlay || this.count < 2 || this.halted) return;\n this.startedAt = performance.now();\n this.timer = setTimeout(() => this.go(this.index + 1, 'next'), Math.max(0, this.remaining));\n }\n\n private restartTimer() {\n this.remaining = this.interval;\n this.startTimer();\n }\n\n private go(target: number, direction: 'next' | 'prev') {\n if (this.count === 0) return;\n this.turned = true;\n this.setAttribute('data-direction', direction);\n this.index = (target + this.count) % this.count;\n this.dispatchEvent(\n new CustomEvent<CarouselChangeEventDetail>('carousel-change', {\n detail: { index: this.index },\n bubbles: true,\n composed: true,\n }),\n );\n this.restartTimer();\n }\n\n private onTabKeydown(event: KeyboardEvent) {\n const step = { ArrowRight: 1, ArrowLeft: -1 }[event.key];\n let target: number | undefined;\n if (step !== undefined) target = this.index + step;\n else if (event.key === 'Home') target = 0;\n else if (event.key === 'End') target = this.count - 1;\n if (target === undefined) return;\n event.preventDefault();\n this.go(target, step === -1 || target < this.index ? 'prev' : 'next');\n void this.updateComplete.then(() => this.renderRoot.querySelector<HTMLElement>('.tab.active')?.focus());\n }\n\n private renderTabs() {\n const running = this.autoPlay && this.count > 1;\n return html`<div class=\"tabs\" part=\"tabs\">\n <div class=\"tabs-inner\">\n <p class=\"tab-current\" aria-hidden=\"true\">${this.labelFor(this.index)}</p>\n <div class=\"tablist\" role=\"tablist\" aria-label=\"Slides\" @keydown=${this.onTabKeydown}>\n ${Array.from({ length: this.count }, (_, i) => {\n const active = i === this.index;\n return html`\n <button\n part=\"tab\"\n type=\"button\"\n role=\"tab\"\n aria-label=${this.labelFor(i)}\n class=\"tab ${active ? 'active' : ''} ${running ? 'running' : ''}\"\n aria-selected=${active ? 'true' : 'false'}\n tabindex=${active ? 0 : -1}\n @click=${() => active || this.go(i, i > this.index ? 'next' : 'prev')}\n >\n <span class=\"progress\" part=\"progress\"><span class=\"fill\"></span></span>\n <span class=\"tab-label\">${this.labelFor(i)}</span>\n </button>\n `;\n })}\n </div>\n ${running\n ? html`<button\n part=\"play-button\"\n type=\"button\"\n class=\"play\"\n aria-label=${this.userPaused ? 'Play slides' : 'Pause slides'}\n @click=${this.togglePlay}\n >\n ${this.userPaused\n ? html`<svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" aria-hidden=\"true\"><path d=\"M3 1.5v9l7.5-4.5z\" fill=\"currentColor\" /></svg>`\n : html`<svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" aria-hidden=\"true\"><path d=\"M2.5 1.5h2.5v9H2.5zM7 1.5h2.5v9H7z\" fill=\"currentColor\" /></svg>`}\n </button>`\n : nothing}\n </div>\n </div>`;\n }\n\n private renderDots() {\n return html`<div class=\"indicators\" part=\"indicators\">\n ${Array.from(\n { length: this.count },\n (_, i) => html`\n <button\n part=\"dot\"\n class=\"dot ${i === this.index ? 'active' : ''}\"\n aria-label=\"Go to slide ${i + 1}\"\n aria-current=${i === this.index ? 'true' : 'false'}\n @click=${() => this.go(i, i > this.index ? 'next' : 'prev')}\n ></button>\n `,\n )}\n </div>`;\n }\n\n render() {\n const multiple = this.count > 1;\n return html`\n <div class=\"viewport\" part=\"viewport\">\n <slot @slotchange=${this.onSlotChange}></slot>\n </div>\n ${multiple\n ? html`<div class=\"sr-only\" aria-live=${this.halted ? 'polite' : 'off'} aria-atomic=\"true\">${this.index + 1} of ${this.count}</div>`\n : nothing}\n ${this.showArrows && multiple\n ? html`\n <button part=\"nav-button prev\" class=\"nav prev\" aria-label=\"Previous Slide\" @click=${() => this.go(this.index - 1, 'prev')}>❮</button>\n <button part=\"nav-button next\" class=\"nav next\" aria-label=\"Next Slide\" @click=${() => this.go(this.index + 1, 'next')}>❯</button>\n `\n : nothing}\n ${this.showIndicators && multiple ? (this.indicatorStyle === 'tabs' ? this.renderTabs() : this.renderDots()) : nothing}\n `;\n }\n}\n"],"mappings":"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AAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAwFf,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QA6CjB,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAsDjB,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QA8EjB,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAkDnB,mBAAmB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAYvB;AAAA,EADC,SAAS,EAAE,MAAM,SAAS,WAAW,YAAY,CAAC;AAAA,GAxUxC,SAyUX;AAIA;AAAA,EADC,SAAS,EAAE,MAAM,OAAO,CAAC;AAAA,GA5Uf,SA6UX;AAKA;AAAA,EADC,SAAS,EAAE,MAAM,SAAS,WAAW,iBAAiB,CAAC;AAAA,GAjV7C,SAkVX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,SAAS,WAAW,cAAc,CAAC;AAAA,GApV1C,SAqVX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,SAAS,WAAW,kBAAkB,CAAC;AAAA,GAvV9C,SAwVX;AAIA;AAAA,EADC,SAAS,EAAE,MAAM,QAAQ,SAAS,MAAM,WAAW,kBAAkB,CAAC;AAAA,GA3V5D,SA4VX;AAIA;AAAA,EADC,SAAS,EAAE,MAAM,QAAQ,SAAS,KAAK,CAAC;AAAA,GA/V9B,SAgWX;AAIA;AAAA,EADC,SAAS,EAAE,WAAW,MAAM,CAAC;AAAA,GAnWnB,SAoWX;AAEiB;AAAA,EAAhB,MAAM;AAAA,GAtWI,SAsWM;AACA;AAAA,EAAhB,MAAM;AAAA,GAvWI,SAuWM;AACA;AAAA,EAAhB,MAAM;AAAA,GAxWI,SAwWM;AAEA;AAAA,EAAhB,MAAM;AAAA,GA1WI,SA0WM;AAEA;AAAA,EAAhB,MAAM;AAAA,GA5WI,SA4WM;AAEA;AAAA,EAAhB,MAAM;AAAA,GA9WI,SA8WM;AAEA;AAAA,EAAhB,MAAM;AAAA,GAhXI,SAgXM;AAhXN,WAAN;AAAA,EADN,cAAc,aAAa;AAAA,GACf;","names":["link"]}
|