159 lines
5.0 KiB
TypeScript
159 lines
5.0 KiB
TypeScript
import { TempstreamJSX } from "tempstream";
|
|
import type { ComponentToHTMLArgs } from "@sealcode/jdd";
|
|
import { Component, ComponentArguments } from "@sealcode/jdd";
|
|
|
|
import arrow from "./autoscrolling-images-arrow.svg";
|
|
|
|
const component_arguments = {
|
|
title: new ComponentArguments.ShortText(),
|
|
interval: new ComponentArguments.ShortText().setExampleValues(["5"]),
|
|
imagesPerPage: new ComponentArguments.ShortText().setExampleValues(["6"]),
|
|
images: new ComponentArguments.List(
|
|
new ComponentArguments.Structured({
|
|
image: new ComponentArguments.Image(),
|
|
alt: new ComponentArguments.ShortText(),
|
|
})
|
|
),
|
|
} as const;
|
|
|
|
export class AutoscrollingImages extends Component<typeof component_arguments> {
|
|
getArguments() {
|
|
return component_arguments;
|
|
}
|
|
|
|
toHTML({
|
|
args: { title, interval, imagesPerPage, images },
|
|
jdd_context: { render_image },
|
|
}: ComponentToHTMLArgs<typeof component_arguments>) {
|
|
const imageNumberPerPage = parseInt(imagesPerPage);
|
|
const parsedImagesArray = [];
|
|
|
|
for (let i = 0; i < images.length; i += imageNumberPerPage) {
|
|
parsedImagesArray.push(images.slice(i, i + imageNumberPerPage));
|
|
}
|
|
|
|
const radioButtonIdPrefix = "r" + Math.floor(100 + Math.random() * 900);
|
|
const radioButton_name = `autoscrolling-images__radio--${radioButtonIdPrefix}`;
|
|
const numberOfImages = images.length * 5;
|
|
const titleUpperCase = title.toUpperCase();
|
|
|
|
return (
|
|
<div
|
|
class="autoscrolling-images"
|
|
data-controller="autoscrolling-images"
|
|
data-autoscrolling-images-interval={interval}
|
|
>
|
|
<style>
|
|
{parsedImagesArray
|
|
.map(
|
|
(_, pageIndex) =>
|
|
`#${radioButtonIdPrefix}-autoscrolling-images__radio-${pageIndex}:checked ~ .autoscrolling-images__imgs-carousel > .autoscrolling-images__carousel {
|
|
transform: translateX(calc(${pageIndex} * (-100%)));
|
|
}
|
|
|
|
#${radioButtonIdPrefix}-autoscrolling-images__radio-${pageIndex}:checked ~ .autoscrolling-images__arrow-carousel-container
|
|
> .autoscrolling-images__arrow-carousel {
|
|
transform: translateX(calc(${pageIndex} * (-100%)));
|
|
|
|
}
|
|
|
|
#${radioButtonIdPrefix}-autoscrolling-images__radio-${pageIndex}:checked ~ .autoscrolling-images__dots-container
|
|
> label:nth-child(${pageIndex + 1}) {
|
|
background-color: #0d4d69;
|
|
|
|
}`
|
|
)
|
|
.join("\n")}
|
|
</style>
|
|
|
|
<div
|
|
class="autoscrolling-images-wrapper"
|
|
data-carousel-id-prefix={radioButtonIdPrefix}
|
|
>
|
|
<div class="autoscrolling-images__title-wrapper">
|
|
<h2 class="autoscrolling-images__title">{titleUpperCase}</h2>
|
|
</div>
|
|
|
|
<div class="autoscrolling-images__carousel-container">
|
|
{parsedImagesArray.map((_, pageIndex) => (
|
|
<input
|
|
class="autoscrolling-images__radio"
|
|
type="radio"
|
|
name={radioButton_name}
|
|
title={`page ${pageIndex + 1}`}
|
|
value={pageIndex}
|
|
id={`${radioButtonIdPrefix}-autoscrolling-images__radio-${pageIndex}`}
|
|
checked={pageIndex === 0}
|
|
data-action="autoscrolling-images#handleRadiochange"
|
|
/>
|
|
))}
|
|
<div class="autoscrolling-images__arrow-carousel-container">
|
|
<div class="autoscrolling-images__arrow-carousel">
|
|
{parsedImagesArray.map((_, pageIndex) => (
|
|
<div class="autoscrolling-images__arrow-container">
|
|
<label
|
|
for={`${radioButtonIdPrefix}-autoscrolling-images__radio-${
|
|
pageIndex == 0
|
|
? parsedImagesArray.length - 1
|
|
: pageIndex - 1
|
|
}`}
|
|
class="autoscrolling-images__arrow"
|
|
>
|
|
<img
|
|
class="autoscrolling-images__img-arrow-left"
|
|
src={arrow.url}
|
|
alt="←"
|
|
/>
|
|
</label>
|
|
<label
|
|
for={`${radioButtonIdPrefix}-autoscrolling-images__radio-${
|
|
pageIndex == parsedImagesArray.length - 1
|
|
? 0
|
|
: pageIndex + 1
|
|
}`}
|
|
class="autoscrolling-images__arrow"
|
|
>
|
|
<img src={arrow.url} alt="→" />
|
|
</label>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
<div class="autoscrolling-images__imgs-carousel">
|
|
<div
|
|
class="autoscrolling-images__carousel"
|
|
style={`--animation-length: ${numberOfImages}s`}
|
|
>
|
|
{parsedImagesArray.map((page) => (
|
|
<div class="autoscrolling-images__carousel-page">
|
|
{page.map((image) => (
|
|
<div class="autoscrolling-images__img-wrapper">
|
|
{render_image(image.image, {
|
|
container: {
|
|
width: 288,
|
|
height: 150,
|
|
objectFit: "contain",
|
|
},
|
|
alt: image.alt,
|
|
})}
|
|
</div>
|
|
))}
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
<div class="autoscrolling-images__dots-container">
|
|
{parsedImagesArray.map((_, pageIndex) => (
|
|
<label
|
|
for={`${radioButtonIdPrefix}-autoscrolling-images__radio-${pageIndex}`}
|
|
class="autoscrolling-images__dots"
|
|
></label>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
}
|