UNPKG

mirador

Version:

An open-source, web-based 'multi-up' viewer that supports zoom-pan-rotate functionality, ability to display/compare simple images, and images with annotations.

133 lines (123 loc) 4.46 kB
import { PureComponent } from 'react'; import PropTypes from 'prop-types'; import { styled } from '@mui/material/styles'; import classNames from 'classnames'; import IIIFThumbnail from '../containers/IIIFThumbnail'; import ns from '../config/css-ns'; const StyledCanvas = styled('div')(({ theme }) => ({ boxSizing: 'border-box', color: theme.palette.common.white, cursor: 'pointer', display: 'inline-block', whiteSpace: 'nowrap', })); /** */ export class ThumbnailCanvasGrouping extends PureComponent { /** */ constructor(props) { super(props); this.setCanvas = this.setCanvas.bind(this); } /** */ setCanvas(e) { const { setCanvas } = this.props; setCanvas(e.currentTarget.dataset.canvasId); } /** * Determines whether the current index is the rendered canvas, providing * a useful class. */ currentCanvasClass(canvasIndices) { const { index } = this.props; if (canvasIndices.includes(index)) return 'current-canvas-grouping'; return ''; } /** */ render() { const { index, columnIndex, style, canvasGroupings, position, height, currentCanvasId, showThumbnailLabels } = this.props; // For Grid (horizontal), use columnIndex; for List (vertical), use index const itemIndex = columnIndex !== undefined ? columnIndex : index; const currentGroupings = canvasGroupings[itemIndex]; const SPACING = 12; // In react-window v2 Grid (horizontal layout), columnWidth is passed as style.height // For List (vertical layout), rowHeight is passed as style.height const isHorizontal = position === 'far-bottom'; let calculatedWidth = null; if (isHorizontal && style.height) { calculatedWidth = style.height - SPACING; } else if (Number.isInteger(style.width)) { calculatedWidth = style.width - SPACING; } const isSelected = currentGroupings.map((canvas) => canvas.id).includes(currentCanvasId); return ( <div style={{ ...style, boxSizing: 'content-box', height: Number.isInteger(style.height) ? style.height - SPACING : null, left: Number.isInteger(style.left) ? style.left + SPACING / 2 : null, padding: SPACING / 2, top: Number.isInteger(style.top) ? style.top + SPACING / 2 : null, width: calculatedWidth, }} className={ns('thumbnail-nav-container')} role="gridcell" aria-colindex={itemIndex + 1} > <StyledCanvas role="button" data-canvas-id={currentGroupings[0].id} data-canvas-index={currentGroupings[0].index} onClick={this.setCanvas} tabIndex={-1} sx={(theme) => ({ '&:not(:hover)': { outline: isSelected ? `2px solid ${theme.palette.primary.main}` : 0, ...(isSelected && { outlineOffset: '3px', }), }, '&:hover': { outline: isSelected ? `2px solid ${theme.palette.primary.main}` : `2px solid ${theme.palette.action.hover}`, outlineOffset: isSelected ? '3px' : '-2px', }, height: position === 'far-right' ? 'auto' : `${height - SPACING}px`, width: position === 'far-bottom' ? 'auto' : `${style.width}px`, })} className={classNames( ns([ 'thumbnail-nav-canvas', `thumbnail-nav-canvas-${itemIndex}`, this.currentCanvasClass(currentGroupings.map((canvas) => canvas.index)), ]), )} > {currentGroupings.map((canvas, i) => ( <IIIFThumbnail key={canvas.id} resource={canvas} labelled={showThumbnailLabels} maxHeight={position === 'far-right' ? style.height - 1.5 * SPACING : height - 1.5 * SPACING} variant="inside" /> ))} </StyledCanvas> </div> ); } } ThumbnailCanvasGrouping.propTypes = { canvasGroupings: PropTypes.array.isRequired, columnIndex: PropTypes.number, currentCanvasId: PropTypes.string.isRequired, height: PropTypes.number.isRequired, index: PropTypes.number, position: PropTypes.string.isRequired, setCanvas: PropTypes.func.isRequired, showThumbnailLabels: PropTypes.bool.isRequired, style: PropTypes.object.isRequired, }; ThumbnailCanvasGrouping.defaultProps = { columnIndex: undefined, index: undefined, };