react-photo-album
Version:
Responsive photo gallery component for React
158 lines (157 loc) • 5.07 kB
JavaScript
import { jsx, jsxs } from "react/jsx-runtime";
import { forwardRef, createElement } from "react";
import { clsx, cssClass, cssVar, round, unwrap, srcSetAndSizes } from "../utils/index.js";
function Component({
as,
render,
context,
classes = [],
variables = {},
style: styleProp,
className: classNameProp,
children,
...rest
}, ref) {
const className = clsx(
...(Array.isArray(classes) ? classes : [classes]).filter((el) => typeof el === "string").map(cssClass),
classNameProp
);
const style = {
...Object.fromEntries(
Object.entries(variables).map(([key, value]) => [
cssVar(key.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase()),
typeof value === "number" ? round(value, 5) : value
])
),
...styleProp
};
const props = { style, className, children, ...rest };
if (render) {
const rendered = render({ ref, ...props }, context);
if (rendered) return rendered;
}
const Element = as || "div";
return jsx(Element, { ref, ...props });
}
const Component$1 = forwardRef(Component);
function PhotoComponent({
photo,
index,
width,
height,
onClick,
render: { wrapper, link, button, image, extras } = {},
componentsProps: { link: linkProps, button: buttonProps, wrapper: wrapperProps, image: imageProps } = {}
}, ref) {
const { href } = photo;
const context = { photo, index, width: round(width, 3), height: round(height, 3) };
let props;
if (href) {
props = { ...linkProps, as: "a", render: link, classes: ["photo", "link"], href, onClick };
} else if (onClick) {
props = { ...buttonProps, as: "button", type: "button", render: button, classes: ["photo", "button"], onClick };
} else {
props = { ...wrapperProps, render: wrapper, classes: "photo" };
}
return jsxs(
Component$1,
{
ref,
variables: { photoWidth: context.width, photoHeight: context.height },
...{ context, ...props },
children: [
jsx(Component$1, { as: "img", classes: "image", render: image, context, ...imageProps }),
extras?.({}, context)
]
}
);
}
const PhotoComponent$1 = forwardRef(PhotoComponent);
function StaticPhotoAlbum({
layout,
sizes,
model,
skeleton,
onClick: onClickCallback,
render: { container, track, photo: renderPhoto, ...restRender } = {},
componentsProps: {
container: containerProps,
track: trackProps,
link: linkProps,
button: buttonProps,
wrapper: wrapperProps,
image: imageProps
} = {}
}, ref) {
const { spacing, padding, containerWidth, tracks, variables, horizontal } = model || {};
return jsxs(
Component$1,
{
role: "group",
"aria-label": "Photo album",
...containerProps,
variables: { spacing, padding, containerWidth, ...variables },
classes: ["", layout],
render: container,
ref,
children: [
spacing !== void 0 && padding !== void 0 && containerWidth !== void 0 && tracks?.map(({ photos, variables: trackVariables }, trackIndex) => {
const trackSize = photos.length;
const photosCount = horizontal ? trackSize : tracks.length;
return createElement(
Component$1,
{
...trackProps,
key: trackIndex,
render: track,
classes: "track",
variables: { trackSize, ...trackVariables }
},
photos.map((context) => {
const { photo, index, width } = context;
const { key, src, alt, title, label } = photo;
const onClick = onClickCallback ? (event) => {
onClickCallback({ event, photo, index });
} : void 0;
if (renderPhoto) {
const rendered = renderPhoto({ onClick }, context);
if (rendered) return rendered;
}
const ariaLabel = (props) => {
return label ? { "aria-label": label, ...props } : props;
};
return jsx(
PhotoComponent$1,
{
onClick,
render: restRender,
componentsProps: {
image: {
loading: "lazy",
decoding: "async",
src,
alt,
title,
...srcSetAndSizes(photo, sizes, width, containerWidth, photosCount, spacing, padding),
...unwrap(imageProps, context)
},
link: ariaLabel(unwrap(linkProps, context)),
button: ariaLabel(unwrap(buttonProps, context)),
wrapper: unwrap(wrapperProps, context)
},
...context
},
key ?? src
);
})
);
}),
containerWidth === void 0 && skeleton
]
}
);
}
const StaticPhotoAlbum$1 = forwardRef(StaticPhotoAlbum);
export {
StaticPhotoAlbum$1 as default
};