104 lines
2.7 KiB
TypeScript
104 lines
2.7 KiB
TypeScript
import type { FlatTemplatable } from "tempstream";
|
|
import { TempstreamJSX } from "tempstream";
|
|
import type {
|
|
ComponentToHTMLArgs,
|
|
ExtractStructuredComponentArgumentsParsed,
|
|
JDDContext,
|
|
} from "@sealcode/jdd";
|
|
import { Component, ComponentArguments, insert_nbsp } from "@sealcode/jdd";
|
|
import { horizontalScroller } from "../../routes/common/horizontal-scroller/horizontal-scroller.js";
|
|
import { htmlEscape } from "escape-goat";
|
|
|
|
const component_arguments = {
|
|
title: new ComponentArguments.ShortText(),
|
|
images: new ComponentArguments.List(
|
|
new ComponentArguments.Structured({
|
|
image: new ComponentArguments.Image(),
|
|
alt: new ComponentArguments.ShortText().setExampleValues([""]),
|
|
caption: new ComponentArguments.ShortText().setExampleValues([""]),
|
|
})
|
|
),
|
|
} as const;
|
|
|
|
export class HorizontalGallery extends Component<typeof component_arguments> {
|
|
getArguments() {
|
|
return component_arguments;
|
|
}
|
|
|
|
getTitle(
|
|
_: JDDContext,
|
|
args: ExtractStructuredComponentArgumentsParsed<typeof component_arguments>
|
|
) {
|
|
return args.title || null;
|
|
}
|
|
|
|
toHTML({
|
|
args: { title, images },
|
|
classes,
|
|
jdd_context: { render_image },
|
|
index,
|
|
}: ComponentToHTMLArgs<typeof component_arguments>): FlatTemplatable {
|
|
return (
|
|
<div
|
|
class={["horizontal-gallery", ...classes]}
|
|
style={`--jdd-index: ${index}`}
|
|
data-controller="glightbox"
|
|
>
|
|
{horizontalScroller({
|
|
elements: (images || []).map((image) => (
|
|
<>
|
|
<div
|
|
class="image-wrapper"
|
|
data-glightbox-target="pictureWrapper"
|
|
data-glightbox-caption={htmlEscape(image.caption || "")}
|
|
>
|
|
{render_image(image.image, {
|
|
sizesAttr: "100vw",
|
|
container: {
|
|
width: 800,
|
|
height: 500,
|
|
objectFit: "contain",
|
|
},
|
|
alt: image.alt,
|
|
})}
|
|
</div>
|
|
{image.caption.trim() ? (
|
|
<div class="caption">{image.caption}</div>
|
|
) : (
|
|
""
|
|
)}
|
|
</>
|
|
)),
|
|
render: async ({ scroller, markers }) => (
|
|
<div>
|
|
<div class="horizontal-gallery__top-bar">
|
|
<h2>{insert_nbsp(title)}</h2>
|
|
<div class="horizontal-gallery__buttons">
|
|
<button
|
|
class="prev-button"
|
|
data-action="horizontal-scroller#scrollLeft"
|
|
type="button"
|
|
>
|
|
<span style="transform: rotate(180deg); margin-right: 16px;">
|
|
←
|
|
</span>
|
|
</button>
|
|
<button
|
|
class="next-button"
|
|
data-action="horizontal-scroller#scrollRight"
|
|
type="button"
|
|
>
|
|
<span>→</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
{scroller}
|
|
{markers}
|
|
</div>
|
|
),
|
|
})}
|
|
</div>
|
|
);
|
|
}
|
|
}
|