UNPKG

@chayns-components/core

Version:

A set of beautiful React components for developing your own applications with chayns.

122 lines 5.51 kB
import React, { useCallback } from 'react'; import { StyledCornerElement, StyledCornerImage, StyledGroupedImage, StyledGroupImageElement } from './GroupedImage.styles'; import CareOfClipPath from './clip-paths/CareOfClipPath'; import { useUuid } from '../../hooks/uuid'; import SecondImageClipPath from './clip-paths/SecondImageClipPath'; import { useKeyboardFocusHighlighting } from '../../hooks/useKeyboardFocusHighlighting'; import { useColorScheme } from '../color-scheme-provider/ColorSchemeProvider'; const GROUPED_IMAGE_SERVICE_ORIGIN = 'https://tsimg.cloud'; const IMAGE_SERVICE_PARAM_PATTERN = /^(?:[whsbd]\d+|f(?:webp|avif|json|none)|c(?:c|f)|m(?:cr|sd|ct|pd|cv))$/i; const getGroupedImageDisplayUrl = (url, size) => { try { const urlObject = new URL(url); if (urlObject.origin !== GROUPED_IMAGE_SERVICE_ORIGIN) { return url; } const pathSegments = urlObject.pathname.split('/'); const fileName = pathSegments.pop(); if (!fileName) { return url; } const extensionIndex = fileName.lastIndexOf('.'); const extension = extensionIndex > -1 ? fileName.slice(extensionIndex) : ''; const fileBaseName = extensionIndex > -1 ? fileName.slice(0, extensionIndex) : fileName; const parameterSegment = fileBaseName.split('_').pop() ?? ''; const hasImageServiceParameters = Boolean(parameterSegment && parameterSegment !== fileBaseName && parameterSegment.split('-').every(parameter => IMAGE_SERVICE_PARAM_PATTERN.test(parameter))); const normalizedSize = Math.max(1, Math.round(size)); if (hasImageServiceParameters) { const fileBaseNameWithoutParams = fileBaseName.slice(0, fileBaseName.lastIndexOf('_')); const preservedParams = parameterSegment.split('-').filter(p => !/^[whs]\d+$/i.test(p)); const newParams = [...preservedParams, `w${normalizedSize}`, `h${normalizedSize}`]; pathSegments.push(`${fileBaseNameWithoutParams}_${newParams.join('-')}${extension}`); } else { pathSegments.push(`${fileBaseName}_w${normalizedSize}-h${normalizedSize}${extension}`); } urlObject.pathname = pathSegments.join('/'); return urlObject.toString(); } catch { return url; } }; const GroupedImage = ({ cornerImage, height = 40, imageBackground, images, onClick, shouldPreventBackground = false, shouldShowRoundImage = false, cornerElement, onImageError, shouldEnableKeyboardHighlighting }) => { const colorScheme = useColorScheme(); const shouldEnableKeyboardHighlightingEffective = shouldEnableKeyboardHighlighting ?? colorScheme?.shouldEnableKeyboardHighlighting ?? false; const hasCornerImage = Boolean(cornerImage); const hasCornerElement = Boolean(cornerElement); const hasMultipleImages = images.length > 1; const uuid = useUuid(); const cornerImageDisplayUrl = cornerImage ? getGroupedImageDisplayUrl(cornerImage, height) : undefined; const isClickable = typeof onClick === 'function'; const isKeyboardFocusable = isClickable && shouldEnableKeyboardHighlightingEffective; const shouldShowKeyboardHighlighting = useKeyboardFocusHighlighting(isKeyboardFocusable); const handleKeyDown = useCallback(event => { if (!isClickable) { return; } if (event.key === 'Enter' || event.key === ' ') { event.preventDefault(); onClick?.(event); } }, [isClickable, onClick]); const imageElements = images.slice(0, 2).map((src, index) => /*#__PURE__*/React.createElement(StyledGroupImageElement, { $background: imageBackground, $isSecondImage: index === 1, $hasCornerImage: hasCornerImage, $hasMultipleImages: hasMultipleImages, $shouldPreventBackground: shouldPreventBackground, $shouldShowRoundImage: shouldShowRoundImage, $uuid: uuid // eslint-disable-next-line react/no-array-index-key , key: index }, /*#__PURE__*/React.createElement("svg", { width: "100%", height: "100%", viewBox: "0 0 40 40", xmlns: "http://www.w3.org/2000/svg", preserveAspectRatio: "xMidYMid slice" }, /*#__PURE__*/React.createElement("foreignObject", { width: "40", height: "40" }, /*#__PURE__*/React.createElement("img", { alt: `image--${index}`, src: getGroupedImageDisplayUrl(src, height), onError: event => typeof onImageError === 'function' && onImageError(event, index) }))))); return /*#__PURE__*/React.createElement(StyledGroupedImage, { onClick: isClickable ? onClick : undefined, onKeyDown: isKeyboardFocusable ? handleKeyDown : undefined, tabIndex: isKeyboardFocusable ? 0 : -1, role: isClickable ? 'button' : undefined, $height: height, $shouldShowKeyboardHighlighting: shouldShowKeyboardHighlighting }, hasCornerImage && /*#__PURE__*/React.createElement(CareOfClipPath, { height: height, uuid: uuid, imageFactors: hasMultipleImages ? [0.76, 0.8] : [1] }), hasMultipleImages && /*#__PURE__*/React.createElement(SecondImageClipPath, { height: height, uuid: uuid, shouldShowRoundImage: shouldShowRoundImage }), imageElements, hasCornerImage && /*#__PURE__*/React.createElement(StyledCornerImage, { $background: imageBackground, $shouldPreventBackground: shouldPreventBackground, $hasMultipleImages: hasMultipleImages, src: cornerImageDisplayUrl, key: "corner-image" }), hasCornerElement && /*#__PURE__*/React.createElement(StyledCornerElement, null, cornerElement)); }; GroupedImage.displayName = 'GroupedImage'; export default GroupedImage; //# sourceMappingURL=GroupedImage.js.map