Viewer
A ready-made viewer for IIIF Manifests and Collections, laid out by a template.
import Viewer from "@nulib/clover";
import { Default } from "@nulib/clover/templates";
import "@nulib/clover/styles.css";
<Viewer
iiifContent="https://clover.iiif.library.northwestern.edu/mocks/paged/manifest.json"
template={}
items=
panelLayout=
header={}
/>;<script type="module">
import "@nulib/clover/web-components";
</script>
<clover-viewer
iiif-content="https://clover.iiif.library.northwestern.edu/mocks/paged/manifest.json"
template=
items=
panel-layout=
header="">
</clover-viewer>import Viewer from "@nulib/clover";
import { Document } from "@nulib/clover/templates";
import "@nulib/clover/styles.css";
import "@nulib/clover/templates.css";
<Viewer
iiifContent="https://clover.iiif.library.northwestern.edu/mocks/paged/manifest.json"
template={}
defaultSidebarOpen={}
defaultPanelOpen={}
panelLayout=
/>;<script type="module">
import "@nulib/clover/web-components";
</script>
<clover-viewer
iiif-content="https://clover.iiif.library.northwestern.edu/mocks/paged/manifest.json"
template=
sidebar-open=""
panel-open=""
panel-layout=>
</clover-viewer>import Viewer from "@nulib/clover";
import { Gallery } from "@nulib/clover/templates";
import "@nulib/clover/styles.css";
import "@nulib/clover/templates.css";
<Viewer
iiifContent="https://clover.iiif.library.northwestern.edu/mocks/paged/manifest.json"
template={}
size="rem"
/>;<script type="module">
import "@nulib/clover/web-components";
</script>
<clover-viewer
iiif-content="https://clover.iiif.library.northwestern.edu/mocks/paged/manifest.json"
template=
size="rem">
</clover-viewer>API reference
Viewer<clover-viewer> is the package’s default export. It draws its template, and hands every other
prop to it: the template’s own, below, and those of Root<clover-root>, which
every template is built on.
Viewer
iiifContent can be:
- A Manifest, shown from its
startCanvas, or its first. - A Collection. Its first Manifest is shown, or the one
manifestIdnames, and its members are listed in the panel’s Collection section. Paged Collections are followed throughnext, and a nested Collection is entered. - A Canvas, shown on its own. Where it is
partOfa Manifest, About names it, with a button that opens the Manifest at this Canvas. - A content state, as JSON or base64url. It opens at the Canvas it points to, framing
its region or seeking to its time. One that carries a
bodyshows that note on the Canvas, as an annotation. - Annotations: an AnnotationPage or AnnotationCollection made apart from any Manifest. The Viewer opens the first one’s Manifest at its Canvas.
- An object of any of these. It is known by its
id, so a new object with the sameiddoes not reload.
Everything is upgraded to IIIF Presentation 4 as it loads, so every part reads one shape.
toPresentation4() does the same for data you hold yourself.
Default
The Viewer’s own layout, drawn when it is given no template: the title over the Body,
the thumbnails under it, and the information panel beside them, as in Clover 3.x.
Document
Reads like a PDF viewer: a toolbar with the title and Download, page thumbnails down the left, the pages down one column, and the information panel sliding out on the right.
Gallery
A grid of the views, a spread one cell, that opens one in a lightbox to pan, zoom and page through.
<clover-viewer>
Clover's Viewer, in one of its templates: Default (the title over the Body, the thumbnails under it, the information panel beside them), Document (a PDF reader's pages, thumbnails beside them) or Gallery (a grid, each item opening in a lightbox). Each template loads when used, its styles with it.
Examples
Templates
Pass a template from @nulib/clover/templates as template. A page loads only the
template it passes, and the parts that template uses: a Gallery loads no information
panel.
Given none, the Viewer loads Default the first time it draws, as a chunk of its own: one
request before the Manifest loads, and nothing drawn on the server. To have it up front,
pass it like any other.
import { Default } from "@nulib/clover/templates";
<Viewer iiifContent={url} template={Default} />;<script type="module">
import "@nulib/clover/web-components";
</script>
<clover-viewer
iiif-content="https://iiif.io/api/cookbook/recipe/0009-book-1/manifest.json"
template="default"></clover-viewer>Every template is built only from parts @nulib/clover exports. To change one, copy its
source, in packages/clover/src/templates/, into your app. To start from nothing, see
Composing layouts.
Panel layout
Use panelLayoutpanel-layout to lay the information panel’s sections out as tabs rather than stacked
boxes.
<Viewer iiifContent={url} panelLayout="accordion" /><clover-viewer
iiif-content="https://clover.iiif.library.northwestern.edu/mocks/paged/manifest.json"
panel-layout="accordion"></clover-viewer><Viewer iiifContent={url} panelLayout="tabs" /><clover-viewer
iiif-content="https://clover.iiif.library.northwestern.edu/mocks/paged/manifest.json"
panel-layout="tabs"></clover-viewer>Thumbnails
Use items to lay the thumbnails under the Body out as a slider, a list or a grid, or
false to leave them out.
<Viewer iiifContent={url} items="slider" /><clover-viewer
iiif-content="https://clover.iiif.library.northwestern.edu/mocks/paged/manifest.json"
items="slider"></clover-viewer><Viewer iiifContent={url} items="list" /><clover-viewer
iiif-content="https://clover.iiif.library.northwestern.edu/mocks/paged/manifest.json"
items="list"></clover-viewer><Viewer iiifContent={url} items="grid" /><clover-viewer
iiif-content="https://clover.iiif.library.northwestern.edu/mocks/paged/manifest.json"
items="grid"></clover-viewer><Viewer iiifContent={url} items={false} /><clover-viewer
iiif-content="https://clover.iiif.library.northwestern.edu/mocks/paged/manifest.json"
items="false"></clover-viewer>Header and panel
Use header={false}header="false" to leave out the title over the Body, and panel={false}panel="false" to leave
out the information panel and its toggle. defaultPanelOpenpanel-open starts the panel open or
closed beside the Body. On a phone, where it would cover the Body, it starts closed
whatever you pass, and the reader opens it with its toggle.
<Viewer
iiifContent="https://api.dc.library.northwestern.edu/api/v2/works/d8fb6329-f7fb-48bf-8bb7-70a64ded5a15?as=iiif"
header={false}
panel={false}
/><clover-viewer
iiif-content="https://api.dc.library.northwestern.edu/api/v2/works/d8fb6329-f7fb-48bf-8bb7-70a64ded5a15?as=iiif"
header="false"
panel="false"></clover-viewer>Fill
Use fill to have the Viewer fill a box of a set height, the window under a page’s own
header, say. The Body takes what the title and the thumbnails leave, never less than
16rem; a shorter box scrolls.
<div style={{ height: "34rem" }}>
<Viewer
iiifContent="https://api.dc.library.northwestern.edu/api/v2/works/0e66d6d8-5dc5-4686-b056-d18682c79ebf?as=iiif"
fill
/>
</div><div style="height: 34rem">
<clover-viewer
iiif-content="https://api.dc.library.northwestern.edu/api/v2/works/0e66d6d8-5dc5-4686-b056-d18682c79ebf?as=iiif"
fill></clover-viewer>
</div>Heading level
Use headingLevelheading-level to fit the Viewer into the page’s outline. Its title is an h2, and
the panel’s sections h3s. Under a heading of your own, pass the level below it: the
Viewers on this page sit under h3s, and pass 4.
<h3>The catalog</h3>
<Viewer iiifContent={url} headingLevel={4} /><h3>The catalog</h3>
<clover-viewer
iiif-content="https://iiif.io/api/cookbook/recipe/0009-book-1/manifest.json"
heading-level="4"></clover-viewer>With header={false}header="false" there is no title, and the panel’s sections take its place, at
headingLevelheading-level itself.
Gallery size
Use size to set the width of Gallery’s cells.
<Viewer iiifContent={url} template={Gallery} size="8rem" /><clover-viewer
iiif-content="https://clover.iiif.library.northwestern.edu/mocks/paged/manifest.json"
template="gallery"
size="8rem"></clover-viewer>Collection
Give a Collection as iiifContentiiif-content, and the Viewer shows its first Manifest and lists its
members in the panel’s Collection section. Choosing one shows it. manifestIdmanifest-id with
onManifestChangeclover-manifest-change makes the Manifest controlled, as canvasIdcanvas-id does the Canvas.
<Viewer iiifContent="https://api.dc.library.northwestern.edu/api/v2/collections/c373ecd2-2c45-45f2-9f9e-52dc244870bd?as=iiif" /><clover-viewer
iiif-content="https://api.dc.library.northwestern.edu/api/v2/collections/c373ecd2-2c45-45f2-9f9e-52dc244870bd?as=iiif"></clover-viewer>Opening at a place
Give a content state as iiifContentiiif-content to open at a Canvas, framing a region of it
(xywh=) or seeking to a time (t=). This one opens the catalog at Page 4, framed on the
plate its “Then” tags.
import Viewer, { encodeContentState } from "@nulib/clover";
const state = {
type: "Annotation",
motivation: ["contentState"],
target: {
type: "SpecificResource",
source: {
id: "https://clover.iiif.library.northwestern.edu/mocks/paged/canvas/5",
type: "Canvas",
partOf: [
{
id: "https://clover.iiif.library.northwestern.edu/mocks/paged/manifest.json",
type: "Manifest",
},
],
},
selector: { type: "FragmentSelector", value: "xywh=2705,66,1419,1518" },
},
};
<Viewer iiifContent={encodeContentState(state)} />;<clover-viewer></clover-viewer>
<script type="module">
document.querySelector("clover-viewer").iiifContent = {
type: "Annotation",
motivation: ["contentState"],
target: {
type: "SpecificResource",
source: {
id: "https://clover.iiif.library.northwestern.edu/mocks/paged/canvas/5",
type: "Canvas",
partOf: [
{
id: "https://clover.iiif.library.northwestern.edu/mocks/paged/manifest.json",
type: "Manifest",
},
],
},
selector: { type: "FragmentSelector", value: "xywh=2705,66,1419,1518" },
},
};
</script>onContentStateChangeclover-content-state-change hands you a content state whenever the reader settles: the Canvas
and region, or the moment in a recording, they are at. Put it in a link to share it.
<Viewer
iiifContent={url}
onContentStateChange={({ encoded }) =>
history.replaceState(null, "", `?iiif-content=${encoded}`)
}
/><clover-viewer
iiif-content="https://clover.iiif.library.northwestern.edu/mocks/paged/manifest.json"
></clover-viewer>
<script type="module">
document
.querySelector("clover-viewer")
.addEventListener("clover-content-state-change", ({ detail }) =>
history.replaceState(null, "", `?iiif-content=${detail.encoded}`),
);
</script>Annotations
Annotations on the Manifest’s Canvases (comments, tags, transcriptions) are listed in the panel’s Annotations section and drawn on the Canvas. Picking one frames it, moving to its Canvas first. This catalog has each plate’s “Then” and “Now” tagged where they are.
<Viewer iiifContent="https://clover.iiif.library.northwestern.edu/mocks/paged/manifest.json" /><clover-viewer
iiif-content="https://clover.iiif.library.northwestern.edu/mocks/paged/manifest.json"></clover-viewer>Use annotations to show pages of your own beside the Manifest’s.
<Viewer iiifContent={url} annotations={annotationPageUrl} /><clover-viewer
iiif-content="https://clover.iiif.library.northwestern.edu/mocks/paged/manifest.json"
annotations="https://example.org/annotation-page.json"
></clover-viewer>Content Search
A Manifest with a IIIF Content Search service, version 1 or 2, gets a Search section: its
hits listed by page and drawn on the Canvas, the first gone to as they arrive. Use
searchQuerysearch-query to search as it opens. This is the homepage’s catalog, its words read by
machine and searchable (mock), searched for “steel”.
<Viewer
iiifContent="https://clover.iiif.library.northwestern.edu/mocks/paged/manifest.json"
searchQuery="steel"
/><clover-viewer
iiif-content="https://clover.iiif.library.northwestern.edu/mocks/paged/manifest.json"
search-query="steel"></clover-viewer>Video and sound
Video and sound play in the Canvas’s own controls. Their captions are drawn over the
picture and listed in the Transcript section, chapters come from the Manifest’s Ranges,
and an annotation can follow a region through time (xywh=…&t=…). In this example,
Clover plays a film whose annotations each follow a region as it moves, with its
captions and chapters beside it.
<Viewer iiifContent="https://clover.iiif.library.northwestern.edu/mocks/rudolf-hess-nuremberg/manifest.json" /><clover-viewer
iiif-content="https://clover.iiif.library.northwestern.edu/mocks/rudolf-hess-nuremberg/manifest.json"></clover-viewer>Animation
A Canvas whose images are timed, one per frame, plays as an animation, with a frame bar to
step, scrub and pause it. auto-advance plays it on arrival and repeat loops it.
Nothing plays for a reader who asks for reduced motion.
<Viewer iiifContent="https://nulib-ds.github.io/muybridge/iiif/plate-number-700-buffalo-galloping.json" /><clover-viewer
iiif-content="https://nulib-ds.github.io/muybridge/iiif/plate-number-700-buffalo-galloping.json"></clover-viewer>Places
A Manifest with a navPlace.navPlace, or a Canvas with a georeference, gets a Map section: its
places, or the sheet laid over the ground. See Map.
<Viewer iiifContent="https://clover.iiif.library.northwestern.edu/mocks/georeference/manifest.json" /><clover-viewer
iiif-content="https://clover.iiif.library.northwestern.edu/mocks/georeference/manifest.json"></clover-viewer>Requests
Use request.request for every request the Viewer makes: the Manifest, annotation pages,
info.json, image tiles, captions and HLS segments.
<Viewer
iiifContent={url}
request={{
credentials: "include",
headers: { Authorization: `Bearer ${token}` },
}}
/><clover-viewer
iiif-content="https://clover.iiif.library.northwestern.edu/mocks/paged/manifest.json"
></clover-viewer>
<script type="module">
document.querySelector("clover-viewer").request = {
credentials: "include",
headers: { Authorization: `Bearer ${token}` },
};
</script>A <video> element cannot send headers, so plain video and sound get only the
credentials. So does an image served without CORS, which Clover shows as an <img>.
Renderers
Use renderers.renderers to draw a view with a component of your own: one Clover does not draw, a
PDF say, or one you want drawn otherwise. See
Renderers of your own.
Styles
Import @nulib/clover/styles.css once, and @nulib/clover/templates.css for Document
and Gallery. Size the Body with --clover-body-height.
.catalog {
--clover-body-height: 32rem;
}The rest is in Styling.
From Clover 3.x
Clover 3.x’s Viewer, @samvera/clover-iiif, is documented at
Clover 3.x › Viewer. Its iiifContentSearchQuery is searchQuerysearch-query,
and its customDisplays are renderers.renderers. Its options.informationPanel is set out on
Panel.