diff --git a/pages/docs/rendering.mdx b/pages/docs/rendering.mdx new file mode 100644 index 000000000..8f410482a --- /dev/null +++ b/pages/docs/rendering.mdx @@ -0,0 +1,144 @@ +--- +title: Rendering +--- + +import IIIFBadge from "docs/components/IIIFBadge"; +import { Rendering } from "src/components/Primitives"; +import { Tabs, Tab } from "nextra/components"; + +# Rendering + +The Rendering component is used to display a list of alternate formats related to a resource. Whereas SeeAlso is used +to link to a machine-readable resource such as metadata, the Rendering component alerts users that the resource is +available in another format such as PDF or ePub or has a related format. Because of the wide variety of formats that +resources can be available in, the Rendering component is flexible and be of any media type and contain any type of +data. + + + + + + ```jsx + + ``` + + + + + + ```html + + ``` + + + +## Usage + +### React + +```jsx +import { Rendering } from "@samvera/clover-iiif/primitives"; + +const CustomRendering = ({ rendering }) => { + return ; +}; + +export default CustomRendering; +``` + +## API Reference + +| Prop | Type | Default | Required | +| ----------- | ------------------------------------------------------------ | ------- | -------- | +| `as` | `ol`, `ul` | `ul` | -- | +| `rendering` | [rendering](https://iiif.io/api/presentation/3.0/#rendering) | -- | **Yes** | +| `className` | `string`, `undefined` | -- | -- | +| `style` | `CSSProperties`, `undefined` | -- | -- | +| `lang` | `string`, `undefined` | -- | -- | +| `title` | `string`, `undefined` | -- | -- | +| `data-*` | `string`, `undefined` | -- | -- | +| `aria-*` | `AriaAttributes`, `undefined` | -- | -- | + +### Custom Element + +The `Rendering` component can be rendered as either `ol` or `ul` elements. The default is `ul`. + + + + ```jsx + + ``` + + + + + + ```html +
    +
  1. + + PDF version + +
  2. +
+ ``` +
+
diff --git a/pages/index.mdx b/pages/index.mdx index 9e41cc42a..8eda9fa69 100644 --- a/pages/index.mdx +++ b/pages/index.mdx @@ -10,6 +10,7 @@ import { Label, Metadata, PartOf, + Rendering, RequiredStatement, SeeAlso, Summary, @@ -306,6 +307,32 @@ import "swiper/css/pagination"; ``` + + } + href="docs/rendering" + > + ```jsx + + ``` + = (props) => { + const { as, rendering } = props; + + /** + * Create attributes and remove React props + */ + const remove = ["as", "rendering"]; + const attributes = sanitizeAttributes(props, remove); + + return ( + + {rendering && + rendering.map((resource) => { + const label = getLabelAsString( + resource.label, + attributes.lang, + ) as string; + return ( + + + {label ? label : resource.id} + + + ); + })} + + ); +}; + +export default Rendering; diff --git a/src/components/Primitives/index.tsx b/src/components/Primitives/index.tsx index 25c5803c3..937683231 100644 --- a/src/components/Primitives/index.tsx +++ b/src/components/Primitives/index.tsx @@ -5,6 +5,7 @@ import Markup from "src/components/Primitives/Markup/Markup"; import Metadata from "src/components/Primitives/Metadata/Metadata"; import MetadataItem from "src/components/Primitives/Metadata/Item"; import PartOf from "src/components/Primitives/PartOf/PartOf"; +import Rendering from "src/components/Primitives/Rendering/Rendering"; import RequiredStatement from "src/components/Primitives/RequiredStatement/RequiredStatement"; import SeeAlso from "src/components/Primitives/SeeAlso/SeeAlso"; import Summary from "src/components/Primitives/Summary/Summary"; @@ -18,6 +19,7 @@ import { PrimitivesMetadata, PrimitivesMetadataItem, PrimitivesPartOf, + PrimitivesRendering, PrimitivesRequiredStatement, PrimitivesSeeAlso, PrimitivesSummary, @@ -33,6 +35,7 @@ export interface CloverPrimitivesComposition { Metadata: React.FC; MetadataItem: React.FC; PartOf: React.FC; + Rendering: React.FC; RequiredStatement: React.FC; SeeAlso: React.FC; Summary: React.FC; @@ -52,6 +55,7 @@ Primitives.Markup = Markup; Primitives.Metadata = Metadata; Primitives.MetadataItem = MetadataItem; Primitives.PartOf = PartOf; +Primitives.Rendering = Rendering; Primitives.RequiredStatement = RequiredStatement; Primitives.SeeAlso = SeeAlso; Primitives.Summary = Summary; @@ -66,6 +70,7 @@ export { Metadata, MetadataItem, PartOf, + Rendering, RequiredStatement, SeeAlso, Summary, diff --git a/src/components/Viewer/InformationPanel/About/About.tsx b/src/components/Viewer/InformationPanel/About/About.tsx index 8eb179d27..0e96a969c 100644 --- a/src/components/Viewer/InformationPanel/About/About.tsx +++ b/src/components/Viewer/InformationPanel/About/About.tsx @@ -6,6 +6,7 @@ import { Homepage, Id, Metadata, + Rendering, RequiredStatement, Rights, SeeAlso, @@ -29,6 +30,7 @@ const About: React.FC = () => { const [homepage, setHomepage] = useState([]); const [seeAlso, setSeeAlso] = useState([]); + const [rendering, setRendering] = useState([]); const [thumbnail, setThumbnail] = useState([]); useEffect(() => { @@ -37,6 +39,7 @@ const About: React.FC = () => { if (data.homepage?.length > 0) setHomepage(vault.get(data.homepage)); if (data.seeAlso?.length > 0) setSeeAlso(vault.get(data.seeAlso)); + if (data.rendering?.length > 0) setRendering(vault.get(data.rendering)); if (data.thumbnail?.length > 0) setThumbnail(vault.get(data.thumbnail)); }, [activeManifest, vault]); @@ -56,6 +59,9 @@ const About: React.FC = () => { + diff --git a/src/components/Viewer/Properties/Rendering.test.tsx b/src/components/Viewer/Properties/Rendering.test.tsx new file mode 100644 index 000000000..efc766689 --- /dev/null +++ b/src/components/Viewer/Properties/Rendering.test.tsx @@ -0,0 +1,41 @@ +import { render, screen } from "@testing-library/react"; +import { PrimitivesExternalWebResource } from "src/types/primitives"; +import PropertiesRendering from "src/components/Viewer/Properties/Rendering"; +import React from "react"; + +const json: PrimitivesExternalWebResource[] = [ + { + id: "https://drive.google.com/file/d/1aWo1lORRVTQ0VveV3aP5Ym6hfVXUqr8_/view?usp=sharing", + type: "Text", + label: { + en: ['Download "A study guide: Josh MacPhee"'], + }, + format: "application/pdf", + }, + { + id: "https://fixtures.iiif.io/other/UCLA/kabuki_ezukushi_rtl.pdf", + type: "Text", + label: { + en: ["PDF version"], + }, + format: "application/pdf", + }, +]; + +describe("IIIF rendering property component", () => { + it("renders", () => { + render(); + + /** + * test anchors + */ + const links = screen.getAllByRole("link"); + links.forEach((element, index) => { + const text = json[index].label?.en?.join(", ") as string; + expect(element).toHaveTextContent(text); + + const href = json[index].id as string; + expect(element.getAttribute("href")).toBe(href); + }); + }); +}); diff --git a/src/components/Viewer/Properties/Rendering.tsx b/src/components/Viewer/Properties/Rendering.tsx new file mode 100644 index 000000000..116e251f5 --- /dev/null +++ b/src/components/Viewer/Properties/Rendering.tsx @@ -0,0 +1,22 @@ +import { PrimitivesExternalWebResource } from "src/types/primitives"; +import { Rendering } from "src/components/Primitives"; +import React from "react"; + +interface PropertiesRenderingProps { + rendering: PrimitivesExternalWebResource[]; +} + +const PropertiesRendering: React.FC = ({ + rendering, +}) => { + if (rendering?.length === 0) return <>; + + return ( + <> + Alternate formats + + + ); +}; + +export default PropertiesRendering; diff --git a/src/components/Viewer/Properties/index.ts b/src/components/Viewer/Properties/index.ts index 4cca36d98..2d960734b 100644 --- a/src/components/Viewer/Properties/index.ts +++ b/src/components/Viewer/Properties/index.ts @@ -1,6 +1,7 @@ import PropertiesHomepage from "src/components/Viewer/Properties/Homepage"; import PropertiesId from "src/components/Viewer/Properties/Id"; import PropertiesMetadata from "src/components/Viewer/Properties/Metadata"; +import PropertiesRendering from "src/components/Viewer/Properties/Rendering"; import PropertiesRequiredStatement from "src/components/Viewer/Properties/RequiredStatement"; import PropertiesRights from "src/components/Viewer/Properties/Rights"; import PropertiesSeeAlso from "src/components/Viewer/Properties/SeeAlso"; @@ -11,6 +12,7 @@ export { PropertiesHomepage as Homepage, PropertiesId as Id, PropertiesMetadata as Metadata, + PropertiesRendering as Rendering, PropertiesRequiredStatement as RequiredStatement, PropertiesRights as Rights, PropertiesSeeAlso as SeeAlso, diff --git a/src/dev.tsx b/src/dev.tsx index e342cc648..c73c4569f 100644 --- a/src/dev.tsx +++ b/src/dev.tsx @@ -7,6 +7,7 @@ import { Label, Metadata, PartOf, + Rendering, RequiredStatement, SeeAlso, Summary, @@ -63,6 +64,9 @@ const App = () => { +