Documentation
Viewer

Viewer

A UI component that renders a multicanvas IIIF item viewer with pan-zoom support for Image via OpenSeadragon (opens in a new tab) and Video and Sound content resources using the HTML video element (opens in a new tab).

Manifest or Collection

Features

Provide a IIIF Presentation API (opens in a new tab) Manifest or Collection and the component:

  • Renders a multi-canvas Video, Sound, and Image viewer
  • Renders thumbnails as navigation between canvases
  • Renders annotations with the motivation (opens in a new tab) of supplementing with a content resource having the format of text/vtt for Video and Sound
  • Video and Sound are rendered within a HTML5 <video> element
  • Image canvases are renderered with OpenSeadragon (opens in a new tab)
  • Supports HLS streaming for Video and Audio canvases
  • Supports IIIF Collections and toggling between child Manifests
  • Supports placeholderCanvas for Image canvases.

Installation

  npm install @samvera/clover-iiif

Usage

React

Add the Viewer component to your jsx or tsx code.

import Viewer from "@samvera/clover-iiif/viewer";

Render Viewer with a IIIF Manifest or Collection URI. The only required prop is the iiifContent, which is the URI of the IIIF Manifest or Collection.

<Viewer iiifContent="https://api.dc.library.northwestern.edu/api/v2/works/8a833741-74a8-40dc-bd1d-c416a3b1bb38?as=iiif" />

Vanilla JavaScript

The Viewer can also be implemented in Vanilla Javascript by use of a web component. This web component example sources a registered <clover-viewer> web component.

<html>
  <head>
    <title>Clover IIIF - Viewer - Web Component</title>
    <meta charset="UTF-8" />
  </head>
  <body>
    <script src="https://www.unpkg.com/@samvera/clover-iiif@latest/dist/web-components/index.umd.js"></script>
 
    <clover-viewer
      id="https://api.dc.library.northwestern.edu/api/v2/works/8a833741-74a8-40dc-bd1d-c416a3b1bb38?as=iiif"
    />
  </body>
</html>

Next.js

Implementation with Next.js requires a dynamic import (opens in a new tab) utilizing next/dynamic. This is due to Next's node compilation method creating issue with an OpenSeadragon (a dependency of Clover IIIF) assumption of a browser document object.

import dynamic from "next/dynamic";
 
const Viewer = dynamic(
  () => import("@samvera/clover-iiif").then((Clover) => Clover.Viewer),
  {
    ssr: false,
  },
);
 
const MyCustomViewer = () => {
  const iiifContent =
    "https://api.dc.library.northwestern.edu/api/v2/collections/c373ecd2-2c45-45f2-9f9e-52dc244870bd?as=iiif";
 
  return <Viewer iiifContent={iiifContent} />;
};

API Reference

Viewer can configured through an options prop, which will serve as a object for common options.

PropTypeRequiredDefault
iiifContentstringYes
canvasIdCallbackfunctionNo
customDisplaysSee Custom DisplaysNo
customThemeobjectNo
optionsobjectNo
options.backgroundstring CSS (opens in a new tab)Notransparent
options.canvasBackgroundColorstring CSS (opens in a new tab)No#1a1d1e
options.canvasHeightstring CSS (opens in a new tab)No500px
options.ignoreCaptionLabelsstring[]No[]
options.openSeadragonOpenSeadragon.OptionsNo
options.informationPanelSee Information PanelNo
options.requestHeadersIncomingHttpHeadersNo{ "Content-Type": "application/json" }
options.showDownloadbooleanNotrue
options.showIIIFBadgebooleanNotrue
options.showTitlebooleanNotrue
options.withCredentialsbooleanNofalse
  • Options canvasBackgroundColor and canvasHeight will apply to both <video> elements and the OpenseaDragon canvas.
  • Option withCredentials being set as true will inform IIIF resource requests to be made using credentials (opens in a new tab) such as cookies, authorization headers or TLS client certificates.
  • Option options.openSeadragon will grant you ability to override the OpenSeadragon default options (opens in a new tab) set within the Clover IIIF Viewer to adjust touch and mouse gesture settings and various other configurations.

Canvas Height

The height of the canvas can be set using the options.canvasHeight prop. This prop accepts a string value that is a valid CSS height value. The default value is 500px.

Automatic Height

If the height is set to auto or 100%, the Viewer will expand to the height of its wrapping container element. The wrapping element must have a position relative, along with a defined height for this to display as expected. Be aware to set a z-index value of 0 or an applicable value within your consuming application to ensure the viewer does not conflict with other page elements.

export default function App() {
  const iiifContent =
    "https://api.dc.library.northwestern.edu/api/v2/works/8a833741-74a8-40dc-bd1d-c416a3b1bb38?as=iiif";
 
  const options = {
    canvasHeight: "auto", // or "100%"
  };
 
  return (
    <div style={{ position: "relative", height: "80vh", zIndex: "0" }}>
      <Viewer iiifContent={iiifContent} options={options} />
    </div>
  );
}

Information Panel

The information panel is a collapsible panel that displays information about the current Manifest and renders supplementing resources for the active canvas. It is rendered by default, but can be configured to be hidden or to render only certain tabs.

PropTypeRequiredDefault
options.informationPanel.openbooleanNotrue
options.informationPanel.vtt.autoScrollSee Auto ScrollNotrue
options.informationPanel.renderAboutbooleanNotrue
options.informationPanel.renderAnnotationbooleanNotrue
options.informationPanel.renderSupplementingbooleanNotrue
options.informationPanel.renderTogglebooleanNotrue

Auto Scroll

When VTT annotations are displayed, the Clover IIIF Viewer can automatically scroll the information panel to keep the currently active caption in view. Whether it does so (and how) is governed by the informationPanel.vtt.autoScroll configuration option. The possible values are:

  • { behavior: (behavior), block: (block) }: auto-scroll using the given settings (see below).
  • true: Auto-scroll using the default behavior. This is equivalent to { behavior: "smooth", block: "center" }.
  • false: Do not auto-scroll.

The settings take the form { behavior: "auto" | "instant" | "smooth", block: "center" | "end" | "nearest" | "start" }, and have the same effect as the scrollIntoViewOptions object documented with the Element.scrollIntoView() (opens in a new tab) Web API method. (The inline option does not apply since there is no horizontal scrolling involved.)

Custom Displays

Clients may wish to use their own display components (for example a PDF Viewer, or an audio player, etc). To configure custom displays, use the customDisplays prop, which is an array of objects defining display and target properties. See an example implementation

display.component is a custom React component, and display.componentProps are pass-through props which Viewer will attach to your Custom Display component. The target object provides two methods of matching a Canvas to a Custom Display: target.canvasId which is a manifest's canvas id. Or by target.paintingFormat (ie. application/pdf) which is the body.type in a canvas's Annotation of type "painting".

PropTypeRequiredDefault
customDisplays.display.componentReact.NodeNo
customDisplays.display.componentPropsobjectNo
customDisplays.target.canvasIdstring[]No
customDisplays.target.paintingFormatstring[]No

Deprecated Options

PropIn Favor OfDeprecated
idiiifContentv2.0.0
manifestIdiiifContentv2.0.0
options.renderAboutoptions.informationPanel.renderAboutv2.0.3
options.showInformationToggleoptions.informationPanel.renderTogglev2.0.3

Basic Configuration

Example customization of various options.

const options = {
  // Primary title (Manifest label) for top level canvas.  Defaults to true
  showTitle: false,
 
  // IIIF Badge and popover containing options.  Defaults to true
  showIIIFBadge: false,
 
  // Ignore supplementing canvases by label value that are not for captioning
  ignoreCaptionLabels: ['Chapters'],
 
  // Override canvas background color, defaults to #1a1d1e
  canvasBackgroundColor: "#000",
 
  // Set canvas zooming onScoll (this defaults to false)
  openSeadragon: {
    gestureSettingsMouse: {
      scrollToZoom: true;
    }
  }
}
 
<Viewer
  iiifContent="https://api.dc.library.northwestern.edu/api/v2/works/8a833741-74a8-40dc-bd1d-c416a3b1bb38?as=iiif"
  options={options}
/>

Active Canvas

Example on using canvasIdCallback to return to your consuming application the active canvas ID. This will return as a string.

const iiifContent =
  "https://api.dc.library.northwestern.edu/api/v2/works/8a833741-74a8-40dc-bd1d-c416a3b1bb38?as=iiif";
 
const handlCanvasIdCallback = (activeCanvasId) => {
  if (activeCanvasId) console.log(activeCanvasId);
};
 
return (
  <Viewer iiifContent={iiifContent} canvasIdCallback={handlCanvasIdCallback} />
);

Captions

WebVTT content resources are the source for both content mapped closed captioning <track/> elements in the HTML 5 video player and to the navigator panel adjacent to it. You may ignore these resources as tracks if they are not intended for closed captioning or subtitling by string values matching the label of the content resource. This is a manual option within the viewer as there is no defined way for a manifest to prescribe motivation for these resources beyond supplementing.

export default function App() {
  const iiifContent =
    "https://raw.githubusercontent.com/samvera-labs/clover-iiif/main/public/fixtures/iiif/manifests/captions.json";
 
  const options = {
    ignoreCaptionLabels: ["Chapters"],
  };
 
  return <Viewer iiifContent={iiifContent} options={options} />;
}

Custom Theme

You may choose to override the base theme by setting optional colors and fonts. Naming conventions for colors are limited to those shown in the config example below.

const iiifContent =
  "https://api.dc.library.northwestern.edu/api/v2/works/8a833741-74a8-40dc-bd1d-c416a3b1bb38?as=iiif";
 
const customTheme = {
  colors: {
    /**
     * Black and dark grays in a light theme.
     * All must contrast to 4.5 or greater with `secondary`.
     */
    primary: "#37474F",
    primaryMuted: "#546E7A",
    primaryAlt: "#263238",
 
    /**
     * Key brand color(s).
     * `accent` must contrast to 4.5 or greater with `secondary`.
     */
    accent: "#C62828",
    accentMuted: "#E57373",
    accentAlt: "#B71C1C",
 
    /**
     * White and light grays in a light theme.
     * All must must contrast to 4.5 or greater with `primary` and  `accent`.
     */
    secondary: "#FFFFFF",
    secondaryMuted: "#ECEFF1",
    secondaryAlt: "#CFD8DC",
  },
  fonts: {
    sans: "'Helvetica Neue', sans-serif",
    display: "Optima, Georgia, Arial, sans-serif",
  },
};
 
return <Viewer iiifContent={iiifContent} customTheme={customTheme} />;

CSS Classes

Additional CSS classes are made available on structural HTML elements in the Viewer, which may be referenced in a client's own CSS files/style definitions to further customize the Viewer's appearance. You may inspect the DOM to see classes applied to each element, but in general it follows a pattern similar to:

<div class="clover-viewer">
  <header class="clover-viewer-header" />
  <div class="clover-viewer-content">
    <div class="clover-viewer-painting">...</div>
  </div>
</div>

Request Headers

In some cases, a client may need to request Manifest or Collection resources with custom request headers, ex: Authorization. This can be done by passing a requestHeaders object to the options prop. This object will be passed to the request call made by the Viewer. Accepted header keys are defined in the IncomingHttpHeaders (opens in a new tab) interface.

const iiifContent =
  "https://api.dc.library.northwestern.edu/api/v2/works/8a833741-74a8-40dc-bd1d-c416a3b1bb38?as=iiif";
 
const token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...";
 
return (
  <Viewer
    iiifContent={iiifContent}
    options={{
      requestHeaders: {
        "Content-Type": "application/json",
        Authorization: `Bearer ${token}`,
      },
    }}
  />
);

Custom canvas displays

Clients may wish to use their own display components instead of Clover Viewer's default displays (OpenSeadragon (opens in a new tab) for images and HTML Video Player (opens in a new tab) for audio/video). The Viewer component allows a client to target individual canvas items in a IIIF Manifest by either direct reference to a canvas id or format (ie. video/ogg). See the Type Definition below for CustomDisplay, and an example implementation.

import AnotherCustomDisplay from "./AnotherCustomDisplay";
 
type CustomDisplay = {
  display: {
    component: React.ElementType;
    componentProps: {
      // Any custom props you want to pass to your component
      [key: string]: any;
    };
  };
  target: {
    canvasId: string[];
    paintingFormat: string[]; // "application/pdf" or "application/epub+zip"
  };
};
 
function MyCustomDisplay({ id, annotationBody, ...restProps }: CustomDisplay) {
  return (
    <div>
      <h1>My Custom Display</h1>
      <p>Canvas ID: {id}</p>
      <p>Annotation Body:</p>
      <pre>{JSON.stringify(annotationBody)}</pre>
      <p>Custom props:</p>
      <pre>{JSON.stringify(restProps)}</pre>
      ...your display here
    </div>
  );
}
 
<Viewer
  iiifContent={iiifContent}
  customDisplays={[
    {
      display: {
        component: MyCustomDisplay,
        componentProps: {
          foo: "bar",
        },
      },
      target: {
        canvasId: [
          "https://uri-for-a-canvas-id/access/0",
          "https://uri-for-a-canvas-id/access/1",
        ],
      },
    },
    {
      display: {
        component: AnotherCustomDisplay,
      },
      target: {
        paintingFormat: ["application/pdf", "image/gif"],
      },
    },
  ]}
/>;

The Viewer component will pass the following props to your custom display component:

  • id: The canvas id for the resource being rendered. This may be helpful if you wanted to use the canvas id to fetch additional data from your application's API.
  • annotationBody: The body value for a canvas Annotation item with motivation "painting".
{
  "id": "https://uri-for-a-canvas-id/access/0",
  "type": "Annotation",
  "motivation": "painting",
  "body": {
    "format": "application/pdf",
    "height": 1686,
    "id": "http://localhost:3000/media/pdf/file-sample_150kB.pdf",
    "width": 1192
  }
}

See a complete recipe for a PDF Viewer (opens in a new tab) using custom canvas displays.