first deployment of kikomiko with url photos
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
co-authored by
Cursor
parent
8d98304137
commit
ae3ed7c7b7
Vendored
+136
@@ -0,0 +1,136 @@
|
||||
/**
|
||||
* Collaboration framed carousel — dots + arrows (no pause/progress bars).
|
||||
* Distinct from the full-bleed promo hero under the atelier section.
|
||||
*/
|
||||
export function initCollabBanners() {
|
||||
const root = document.querySelector("[data-collab-banners]");
|
||||
if (!(root instanceof HTMLElement)) return;
|
||||
|
||||
const slides = [...root.querySelectorAll("[data-collab-slide]")];
|
||||
const dots = [...root.querySelectorAll("[data-collab-goto]")];
|
||||
const nextBtn = root.querySelector("[data-collab-next]");
|
||||
const prevBtn = root.querySelector("[data-collab-prev]");
|
||||
if (slides.length < 1) return;
|
||||
|
||||
const reduce = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
||||
let index = 0;
|
||||
let timer = 0;
|
||||
let paused = reduce;
|
||||
|
||||
const durationOf = (i) => {
|
||||
const raw = Number(slides[i]?.getAttribute("data-cbs-duration") || 7000);
|
||||
return Number.isFinite(raw) && raw > 0 ? raw : 7000;
|
||||
};
|
||||
|
||||
const show = (next) => {
|
||||
const i = ((next % slides.length) + slides.length) % slides.length;
|
||||
index = i;
|
||||
slides.forEach((slide, si) => {
|
||||
const on = si === i;
|
||||
slide.classList.toggle("is-active", on);
|
||||
slide.setAttribute("aria-hidden", on ? "false" : "true");
|
||||
});
|
||||
dots.forEach((dot, di) => {
|
||||
const on = di === i;
|
||||
dot.classList.toggle("is-active", on);
|
||||
dot.setAttribute("aria-current", on ? "true" : "false");
|
||||
});
|
||||
root.dataset.active = String(i);
|
||||
};
|
||||
|
||||
const stop = () => {
|
||||
window.clearInterval(timer);
|
||||
timer = 0;
|
||||
};
|
||||
|
||||
const start = () => {
|
||||
stop();
|
||||
if (paused || reduce || slides.length < 2) return;
|
||||
timer = window.setInterval(() => {
|
||||
show(index + 1);
|
||||
}, durationOf(index));
|
||||
};
|
||||
|
||||
const goTo = (i) => {
|
||||
show(i);
|
||||
start();
|
||||
};
|
||||
|
||||
dots.forEach((dot) => {
|
||||
dot.addEventListener("click", () => {
|
||||
const i = Number(dot.getAttribute("data-collab-goto"));
|
||||
if (!Number.isFinite(i)) return;
|
||||
goTo(i);
|
||||
});
|
||||
});
|
||||
|
||||
nextBtn?.addEventListener("click", () => goTo(index + 1));
|
||||
prevBtn?.addEventListener("click", () => goTo(index - 1));
|
||||
|
||||
root.addEventListener("mouseenter", () => {
|
||||
paused = true;
|
||||
stop();
|
||||
});
|
||||
root.addEventListener("mouseleave", () => {
|
||||
paused = reduce;
|
||||
start();
|
||||
});
|
||||
root.addEventListener("focusin", () => {
|
||||
paused = true;
|
||||
stop();
|
||||
});
|
||||
root.addEventListener("focusout", (e) => {
|
||||
if (e.relatedTarget instanceof Node && root.contains(e.relatedTarget)) return;
|
||||
paused = reduce;
|
||||
start();
|
||||
});
|
||||
|
||||
let touchX = 0;
|
||||
let locked = "";
|
||||
root.addEventListener(
|
||||
"touchstart",
|
||||
(e) => {
|
||||
const t = e.changedTouches[0];
|
||||
if (!t) return;
|
||||
touchX = t.clientX;
|
||||
locked = "";
|
||||
},
|
||||
{ passive: true }
|
||||
);
|
||||
root.addEventListener(
|
||||
"touchmove",
|
||||
(e) => {
|
||||
const t = e.changedTouches[0];
|
||||
if (!t || locked === "y") return;
|
||||
const dx = t.clientX - touchX;
|
||||
if (!locked && Math.abs(dx) > 12) locked = "x";
|
||||
},
|
||||
{ passive: true }
|
||||
);
|
||||
root.addEventListener(
|
||||
"touchend",
|
||||
(e) => {
|
||||
const t = e.changedTouches[0];
|
||||
if (!t || locked !== "x") return;
|
||||
const dx = t.clientX - touchX;
|
||||
if (Math.abs(dx) < 48) return;
|
||||
if (dx < 0) goTo(index + 1);
|
||||
else goTo(index - 1);
|
||||
},
|
||||
{ passive: true }
|
||||
);
|
||||
|
||||
const io = new IntersectionObserver(
|
||||
(entries) => {
|
||||
const e = entries[0];
|
||||
if (!e) return;
|
||||
if (!e.isIntersecting) stop();
|
||||
else if (!paused) start();
|
||||
},
|
||||
{ threshold: 0.25 }
|
||||
);
|
||||
io.observe(root);
|
||||
|
||||
show(0);
|
||||
if (!reduce) start();
|
||||
}
|
||||
Reference in New Issue
Block a user