@canopy-iiif/app 0.10.17 → 0.10.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/build/build.js +2 -0
- package/lib/build/iiif.js +12 -1
- package/lib/build/pages.js +20 -0
- package/lib/components/referenced.js +212 -0
- package/package.json +1 -1
- package/ui/dist/index.mjs +5 -3
- package/ui/dist/index.mjs.map +2 -2
- package/ui/dist/server.mjs +227 -29
- package/ui/dist/server.mjs.map +4 -4
- package/ui/styles/base/_markdown.scss +5 -6
- package/ui/styles/components/_referenced-items.scss +74 -0
- package/ui/styles/components/index.scss +1 -0
- package/ui/styles/index.css +80 -5
package/ui/dist/server.mjs
CHANGED
|
@@ -1766,8 +1766,204 @@ function Container({
|
|
|
1766
1766
|
);
|
|
1767
1767
|
}
|
|
1768
1768
|
|
|
1769
|
+
// ui/src/content/ReferencedItems.jsx
|
|
1770
|
+
import React23 from "react";
|
|
1771
|
+
import navigationHelpers3 from "@canopy-iiif/app/lib/components/navigation.js";
|
|
1772
|
+
|
|
1773
|
+
// ui/src/layout/Card.jsx
|
|
1774
|
+
import React22, { useEffect as useEffect5, useRef, useState as useState5 } from "react";
|
|
1775
|
+
function Card({
|
|
1776
|
+
href,
|
|
1777
|
+
src,
|
|
1778
|
+
alt,
|
|
1779
|
+
title,
|
|
1780
|
+
subtitle,
|
|
1781
|
+
// Optional intrinsic dimensions or aspect ratio to compute a responsive height
|
|
1782
|
+
imgWidth,
|
|
1783
|
+
imgHeight,
|
|
1784
|
+
aspectRatio,
|
|
1785
|
+
className,
|
|
1786
|
+
style,
|
|
1787
|
+
children,
|
|
1788
|
+
lazy = true,
|
|
1789
|
+
...rest
|
|
1790
|
+
}) {
|
|
1791
|
+
const containerRef = useRef(null);
|
|
1792
|
+
const [inView, setInView] = useState5(!lazy);
|
|
1793
|
+
const [imageLoaded, setImageLoaded] = useState5(!lazy);
|
|
1794
|
+
useEffect5(() => {
|
|
1795
|
+
if (!lazy) return;
|
|
1796
|
+
if (!containerRef.current) return;
|
|
1797
|
+
if (typeof IntersectionObserver !== "function") {
|
|
1798
|
+
setInView(true);
|
|
1799
|
+
return;
|
|
1800
|
+
}
|
|
1801
|
+
const el = containerRef.current;
|
|
1802
|
+
const obs = new IntersectionObserver(
|
|
1803
|
+
(entries) => {
|
|
1804
|
+
for (const entry of entries) {
|
|
1805
|
+
if (entry.isIntersecting) {
|
|
1806
|
+
setInView(true);
|
|
1807
|
+
try {
|
|
1808
|
+
obs.unobserve(el);
|
|
1809
|
+
} catch (_) {
|
|
1810
|
+
}
|
|
1811
|
+
break;
|
|
1812
|
+
}
|
|
1813
|
+
}
|
|
1814
|
+
},
|
|
1815
|
+
{ root: null, rootMargin: "100px", threshold: 0.1 }
|
|
1816
|
+
);
|
|
1817
|
+
try {
|
|
1818
|
+
obs.observe(el);
|
|
1819
|
+
} catch (_) {
|
|
1820
|
+
}
|
|
1821
|
+
return () => {
|
|
1822
|
+
try {
|
|
1823
|
+
obs.disconnect();
|
|
1824
|
+
} catch (_) {
|
|
1825
|
+
}
|
|
1826
|
+
};
|
|
1827
|
+
}, [lazy]);
|
|
1828
|
+
const w = Number(imgWidth);
|
|
1829
|
+
const h = Number(imgHeight);
|
|
1830
|
+
const ratio = Number.isFinite(Number(aspectRatio)) && Number(aspectRatio) > 0 ? Number(aspectRatio) : Number.isFinite(w) && w > 0 && Number.isFinite(h) && h > 0 ? w / h : void 0;
|
|
1831
|
+
const paddingPercent = ratio ? 100 / ratio : 100;
|
|
1832
|
+
const caption = /* @__PURE__ */ React22.createElement("figcaption", null, title && /* @__PURE__ */ React22.createElement("span", null, title), subtitle && /* @__PURE__ */ React22.createElement("span", null, subtitle), children);
|
|
1833
|
+
return /* @__PURE__ */ React22.createElement(
|
|
1834
|
+
"a",
|
|
1835
|
+
{
|
|
1836
|
+
href,
|
|
1837
|
+
className: ["canopy-card", className].filter(Boolean).join(" "),
|
|
1838
|
+
style,
|
|
1839
|
+
ref: containerRef,
|
|
1840
|
+
"data-aspect-ratio": ratio,
|
|
1841
|
+
"data-in-view": inView ? "true" : "false",
|
|
1842
|
+
"data-image-loaded": imageLoaded ? "true" : "false",
|
|
1843
|
+
...rest
|
|
1844
|
+
},
|
|
1845
|
+
/* @__PURE__ */ React22.createElement("figure", null, src ? ratio ? /* @__PURE__ */ React22.createElement(
|
|
1846
|
+
"div",
|
|
1847
|
+
{
|
|
1848
|
+
className: "canopy-card-media",
|
|
1849
|
+
style: { "--canopy-card-padding": `${paddingPercent}%` }
|
|
1850
|
+
},
|
|
1851
|
+
inView ? /* @__PURE__ */ React22.createElement(
|
|
1852
|
+
"img",
|
|
1853
|
+
{
|
|
1854
|
+
src,
|
|
1855
|
+
alt: alt || title || "",
|
|
1856
|
+
loading: "lazy",
|
|
1857
|
+
onLoad: () => setImageLoaded(true),
|
|
1858
|
+
onError: () => setImageLoaded(true)
|
|
1859
|
+
}
|
|
1860
|
+
) : null
|
|
1861
|
+
) : /* @__PURE__ */ React22.createElement(
|
|
1862
|
+
"img",
|
|
1863
|
+
{
|
|
1864
|
+
src,
|
|
1865
|
+
alt: alt || title || "",
|
|
1866
|
+
loading: "lazy",
|
|
1867
|
+
onLoad: () => setImageLoaded(true),
|
|
1868
|
+
onError: () => setImageLoaded(true),
|
|
1869
|
+
className: "canopy-card-image"
|
|
1870
|
+
}
|
|
1871
|
+
) : null, caption)
|
|
1872
|
+
);
|
|
1873
|
+
}
|
|
1874
|
+
|
|
1875
|
+
// ui/src/content/ReferencedItems.jsx
|
|
1876
|
+
function useReferencedItems(itemsProp) {
|
|
1877
|
+
if (Array.isArray(itemsProp)) return itemsProp;
|
|
1878
|
+
const PageContext = navigationHelpers3 && typeof navigationHelpers3.getPageContext === "function" ? navigationHelpers3.getPageContext() : null;
|
|
1879
|
+
if (!PageContext) return [];
|
|
1880
|
+
const context = React23.useContext(PageContext);
|
|
1881
|
+
const items = context && context.page ? context.page.referencedItems : null;
|
|
1882
|
+
return Array.isArray(items) ? items : [];
|
|
1883
|
+
}
|
|
1884
|
+
function ReferencedItems({
|
|
1885
|
+
items: itemsProp,
|
|
1886
|
+
emptyLabel = null,
|
|
1887
|
+
className = "",
|
|
1888
|
+
children,
|
|
1889
|
+
...rest
|
|
1890
|
+
}) {
|
|
1891
|
+
const items = useReferencedItems(itemsProp);
|
|
1892
|
+
const hasItems = items.length > 0;
|
|
1893
|
+
if (!hasItems) {
|
|
1894
|
+
if (!emptyLabel) return null;
|
|
1895
|
+
const emptyClass = [
|
|
1896
|
+
"referenced-items",
|
|
1897
|
+
"referenced-items--empty",
|
|
1898
|
+
className
|
|
1899
|
+
].filter(Boolean).join(" ");
|
|
1900
|
+
return /* @__PURE__ */ React23.createElement("div", { className: emptyClass, ...rest }, typeof emptyLabel === "function" ? emptyLabel() : emptyLabel);
|
|
1901
|
+
}
|
|
1902
|
+
const containerClassName = ["referenced-items", className].filter(Boolean).join(" ");
|
|
1903
|
+
return /* @__PURE__ */ React23.createElement("section", { className: containerClassName, ...rest }, children, /* @__PURE__ */ React23.createElement("div", { className: "referenced-items__grid", role: "list" }, items.map((item) => {
|
|
1904
|
+
if (!item) return null;
|
|
1905
|
+
const key = item.href || item.slug || item.id;
|
|
1906
|
+
return /* @__PURE__ */ React23.createElement("div", { className: "referenced-items__item", role: "listitem", key }, /* @__PURE__ */ React23.createElement(
|
|
1907
|
+
Card,
|
|
1908
|
+
{
|
|
1909
|
+
href: item.href,
|
|
1910
|
+
src: item.thumbnail,
|
|
1911
|
+
imgWidth: item.thumbnailWidth,
|
|
1912
|
+
imgHeight: item.thumbnailHeight,
|
|
1913
|
+
title: item.title,
|
|
1914
|
+
subtitle: item.summary,
|
|
1915
|
+
className: "referenced-items__card",
|
|
1916
|
+
lazy: false
|
|
1917
|
+
}
|
|
1918
|
+
));
|
|
1919
|
+
})));
|
|
1920
|
+
}
|
|
1921
|
+
|
|
1922
|
+
// ui/src/content/References.jsx
|
|
1923
|
+
import React24 from "react";
|
|
1924
|
+
import navigationHelpers4 from "@canopy-iiif/app/lib/components/navigation.js";
|
|
1925
|
+
function getPageContext() {
|
|
1926
|
+
if (!navigationHelpers4 || typeof navigationHelpers4.getPageContext !== "function") {
|
|
1927
|
+
return null;
|
|
1928
|
+
}
|
|
1929
|
+
try {
|
|
1930
|
+
return navigationHelpers4.getPageContext();
|
|
1931
|
+
} catch (_) {
|
|
1932
|
+
return null;
|
|
1933
|
+
}
|
|
1934
|
+
}
|
|
1935
|
+
function resolveReferences(manifestId, contextList) {
|
|
1936
|
+
if (contextList && contextList.length) return contextList;
|
|
1937
|
+
if (!manifestId) return [];
|
|
1938
|
+
try {
|
|
1939
|
+
return referenced.getReferencesForManifest(manifestId);
|
|
1940
|
+
} catch (_) {
|
|
1941
|
+
return [];
|
|
1942
|
+
}
|
|
1943
|
+
}
|
|
1944
|
+
function References({
|
|
1945
|
+
id = "",
|
|
1946
|
+
title = "Referenced by",
|
|
1947
|
+
emptyLabel = null,
|
|
1948
|
+
className = "",
|
|
1949
|
+
children,
|
|
1950
|
+
...rest
|
|
1951
|
+
}) {
|
|
1952
|
+
const PageContext = getPageContext();
|
|
1953
|
+
const context = PageContext ? React24.useContext(PageContext) : null;
|
|
1954
|
+
const contextPage = context && context.page ? context.page : null;
|
|
1955
|
+
const manifestId = id || contextPage && contextPage.manifestId || "";
|
|
1956
|
+
const contextReferences = !id && contextPage && Array.isArray(contextPage.referencedBy) ? contextPage.referencedBy : null;
|
|
1957
|
+
const references = resolveReferences(manifestId, contextReferences);
|
|
1958
|
+
if (!manifestId) return null;
|
|
1959
|
+
const containerClass = ["references", className].filter(Boolean).join(" ");
|
|
1960
|
+
const list = references.length ? references : null;
|
|
1961
|
+
const entries = list && list.length ? list : null;
|
|
1962
|
+
return /* @__PURE__ */ React24.createElement("dl", { className: containerClass, ...rest }, /* @__PURE__ */ React24.createElement("div", { className: "references__group" }, /* @__PURE__ */ React24.createElement("dt", null, title), entries ? entries.map((entry) => /* @__PURE__ */ React24.createElement("dd", { key: entry.href, className: "references__item" }, /* @__PURE__ */ React24.createElement("a", { href: entry.href }, entry.title || entry.href))) : emptyLabel ? /* @__PURE__ */ React24.createElement("dd", { className: "references__empty" }, typeof emptyLabel === "function" ? emptyLabel() : emptyLabel) : null));
|
|
1963
|
+
}
|
|
1964
|
+
|
|
1769
1965
|
// ui/src/search/MdxSearchResults.jsx
|
|
1770
|
-
import
|
|
1966
|
+
import React25 from "react";
|
|
1771
1967
|
function MdxSearchResults(props) {
|
|
1772
1968
|
let json = "{}";
|
|
1773
1969
|
try {
|
|
@@ -1775,11 +1971,11 @@ function MdxSearchResults(props) {
|
|
|
1775
1971
|
} catch (_) {
|
|
1776
1972
|
json = "{}";
|
|
1777
1973
|
}
|
|
1778
|
-
return /* @__PURE__ */
|
|
1974
|
+
return /* @__PURE__ */ React25.createElement("div", { "data-canopy-search-results": "1" }, /* @__PURE__ */ React25.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: json } }));
|
|
1779
1975
|
}
|
|
1780
1976
|
|
|
1781
1977
|
// ui/src/search/SearchSummary.jsx
|
|
1782
|
-
import
|
|
1978
|
+
import React26 from "react";
|
|
1783
1979
|
function SearchSummary(props) {
|
|
1784
1980
|
let json = "{}";
|
|
1785
1981
|
try {
|
|
@@ -1787,11 +1983,11 @@ function SearchSummary(props) {
|
|
|
1787
1983
|
} catch (_) {
|
|
1788
1984
|
json = "{}";
|
|
1789
1985
|
}
|
|
1790
|
-
return /* @__PURE__ */
|
|
1986
|
+
return /* @__PURE__ */ React26.createElement("div", { "data-canopy-search-summary": "1" }, /* @__PURE__ */ React26.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: json } }));
|
|
1791
1987
|
}
|
|
1792
1988
|
|
|
1793
1989
|
// ui/src/search/MdxSearchTabs.jsx
|
|
1794
|
-
import
|
|
1990
|
+
import React27 from "react";
|
|
1795
1991
|
function MdxSearchTabs(props) {
|
|
1796
1992
|
let json = "{}";
|
|
1797
1993
|
try {
|
|
@@ -1799,11 +1995,11 @@ function MdxSearchTabs(props) {
|
|
|
1799
1995
|
} catch (_) {
|
|
1800
1996
|
json = "{}";
|
|
1801
1997
|
}
|
|
1802
|
-
return /* @__PURE__ */
|
|
1998
|
+
return /* @__PURE__ */ React27.createElement("div", { "data-canopy-search-tabs": "1" }, /* @__PURE__ */ React27.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: json } }));
|
|
1803
1999
|
}
|
|
1804
2000
|
|
|
1805
2001
|
// ui/src/search-form/MdxSearchFormModal.jsx
|
|
1806
|
-
import
|
|
2002
|
+
import React28 from "react";
|
|
1807
2003
|
function MdxSearchFormModal(props = {}) {
|
|
1808
2004
|
const {
|
|
1809
2005
|
placeholder = "Search\u2026",
|
|
@@ -1819,11 +2015,11 @@ function MdxSearchFormModal(props = {}) {
|
|
|
1819
2015
|
const text = typeof label === "string" && label.trim() ? label.trim() : buttonLabel;
|
|
1820
2016
|
const resolvedSearchPath = resolveSearchPath(searchPath);
|
|
1821
2017
|
const data = { placeholder, hotkey, maxResults, groupOrder, label: text, searchPath: resolvedSearchPath };
|
|
1822
|
-
return /* @__PURE__ */
|
|
2018
|
+
return /* @__PURE__ */ React28.createElement("div", { "data-canopy-search-form": true, className: "flex-1 min-w-0" }, /* @__PURE__ */ React28.createElement("div", { className: "relative w-full" }, /* @__PURE__ */ React28.createElement(SearchPanelForm, { placeholder, buttonLabel, label, searchPath: resolvedSearchPath }), /* @__PURE__ */ React28.createElement(SearchPanelTeaserResults, null)), /* @__PURE__ */ React28.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: JSON.stringify(data) } }));
|
|
1823
2019
|
}
|
|
1824
2020
|
|
|
1825
2021
|
// ui/src/iiif/ManifestPrimitives.jsx
|
|
1826
|
-
import
|
|
2022
|
+
import React29 from "react";
|
|
1827
2023
|
import {
|
|
1828
2024
|
Label as CloverLabel,
|
|
1829
2025
|
Metadata as CloverMetadata,
|
|
@@ -1848,28 +2044,28 @@ function ensureMetadata(items) {
|
|
|
1848
2044
|
function Label({ manifest, label, ...rest }) {
|
|
1849
2045
|
const intl = label || manifest && manifest.label;
|
|
1850
2046
|
if (!hasInternationalValue(intl)) return null;
|
|
1851
|
-
return /* @__PURE__ */
|
|
2047
|
+
return /* @__PURE__ */ React29.createElement(CloverLabel, { label: intl, ...rest });
|
|
1852
2048
|
}
|
|
1853
2049
|
function Summary({ manifest, summary, ...rest }) {
|
|
1854
2050
|
const intl = summary || manifest && manifest.summary;
|
|
1855
2051
|
if (!hasInternationalValue(intl)) return null;
|
|
1856
|
-
return /* @__PURE__ */
|
|
2052
|
+
return /* @__PURE__ */ React29.createElement(CloverSummary, { summary: intl, ...rest });
|
|
1857
2053
|
}
|
|
1858
2054
|
function Metadata({ manifest, metadata, ...rest }) {
|
|
1859
2055
|
const items = ensureMetadata(metadata || manifest && manifest.metadata);
|
|
1860
2056
|
if (!items.length) return null;
|
|
1861
|
-
return /* @__PURE__ */
|
|
2057
|
+
return /* @__PURE__ */ React29.createElement(CloverMetadata, { metadata: items, ...rest });
|
|
1862
2058
|
}
|
|
1863
2059
|
function RequiredStatement({ manifest, requiredStatement, ...rest }) {
|
|
1864
2060
|
const stmt = requiredStatement || manifest && manifest.requiredStatement;
|
|
1865
2061
|
if (!stmt || !hasInternationalValue(stmt.label) || !hasInternationalValue(stmt.value)) {
|
|
1866
2062
|
return null;
|
|
1867
2063
|
}
|
|
1868
|
-
return /* @__PURE__ */
|
|
2064
|
+
return /* @__PURE__ */ React29.createElement(CloverRequiredStatement, { requiredStatement: stmt, ...rest });
|
|
1869
2065
|
}
|
|
1870
2066
|
|
|
1871
2067
|
// ui/src/docs/CodeBlock.jsx
|
|
1872
|
-
import
|
|
2068
|
+
import React30 from "react";
|
|
1873
2069
|
function parseHighlightAttr(attr) {
|
|
1874
2070
|
if (!attr) return /* @__PURE__ */ new Set();
|
|
1875
2071
|
const cleaned = String(attr || "").trim();
|
|
@@ -1915,10 +2111,10 @@ var highlightBaseStyle = {
|
|
|
1915
2111
|
};
|
|
1916
2112
|
function DocsCodeBlock(props = {}) {
|
|
1917
2113
|
const { children, ...rest } = props;
|
|
1918
|
-
const childArray =
|
|
1919
|
-
const codeElement = childArray.find((el) =>
|
|
2114
|
+
const childArray = React30.Children.toArray(children);
|
|
2115
|
+
const codeElement = childArray.find((el) => React30.isValidElement(el));
|
|
1920
2116
|
if (!codeElement || !codeElement.props) {
|
|
1921
|
-
return
|
|
2117
|
+
return React30.createElement("pre", props);
|
|
1922
2118
|
}
|
|
1923
2119
|
const {
|
|
1924
2120
|
className = "",
|
|
@@ -1933,8 +2129,8 @@ function DocsCodeBlock(props = {}) {
|
|
|
1933
2129
|
const highlightSet = parseHighlightAttr(highlightAttr);
|
|
1934
2130
|
const copyAttr = codeProps["data-copy"];
|
|
1935
2131
|
const enableCopy = copyAttr !== void 0 ? copyAttr === true || copyAttr === "true" || copyAttr === "" : false;
|
|
1936
|
-
const [copied, setCopied] =
|
|
1937
|
-
const handleCopy =
|
|
2132
|
+
const [copied, setCopied] = React30.useState(false);
|
|
2133
|
+
const handleCopy = React30.useCallback(async () => {
|
|
1938
2134
|
const text = rawCode;
|
|
1939
2135
|
try {
|
|
1940
2136
|
if (typeof navigator !== "undefined" && navigator.clipboard && navigator.clipboard.writeText) {
|
|
@@ -1998,20 +2194,20 @@ function DocsCodeBlock(props = {}) {
|
|
|
1998
2194
|
const highlight = highlightSet.has(lineNumber);
|
|
1999
2195
|
const style = highlight ? { ...baseLineStyle, ...highlightBaseStyle } : baseLineStyle;
|
|
2000
2196
|
const displayLine = line === "" ? " " : line;
|
|
2001
|
-
return
|
|
2197
|
+
return React30.createElement(
|
|
2002
2198
|
"span",
|
|
2003
2199
|
{ key: lineNumber, style },
|
|
2004
|
-
|
|
2200
|
+
React30.createElement("span", { style: lineContentStyle }, displayLine)
|
|
2005
2201
|
);
|
|
2006
2202
|
});
|
|
2007
|
-
return
|
|
2203
|
+
return React30.createElement(
|
|
2008
2204
|
"div",
|
|
2009
2205
|
{ style: containerStyle },
|
|
2010
|
-
|
|
2206
|
+
React30.createElement(
|
|
2011
2207
|
"div",
|
|
2012
2208
|
{ style: headerStyle },
|
|
2013
|
-
|
|
2014
|
-
enableCopy ?
|
|
2209
|
+
React30.createElement("span", null, showFilename ? filename : null),
|
|
2210
|
+
enableCopy ? React30.createElement(
|
|
2015
2211
|
"button",
|
|
2016
2212
|
{
|
|
2017
2213
|
type: "button",
|
|
@@ -2030,19 +2226,19 @@ function DocsCodeBlock(props = {}) {
|
|
|
2030
2226
|
copied ? "Copied" : "Copy"
|
|
2031
2227
|
) : null
|
|
2032
2228
|
),
|
|
2033
|
-
|
|
2229
|
+
React30.createElement(
|
|
2034
2230
|
"pre",
|
|
2035
2231
|
{ ...preRest, className: preClassName, style: mergedPreStyle },
|
|
2036
|
-
|
|
2232
|
+
React30.createElement("code", { style: codeStyle }, lineElements)
|
|
2037
2233
|
)
|
|
2038
2234
|
);
|
|
2039
2235
|
}
|
|
2040
2236
|
|
|
2041
2237
|
// ui/src/docs/MarkdownTable.jsx
|
|
2042
|
-
import
|
|
2238
|
+
import React31 from "react";
|
|
2043
2239
|
function MarkdownTable({ className = "", ...rest }) {
|
|
2044
2240
|
const merged = ["markdown-table", className].filter(Boolean).join(" ");
|
|
2045
|
-
return /* @__PURE__ */
|
|
2241
|
+
return /* @__PURE__ */ React31.createElement("div", { className: "markdown-table__frame" }, /* @__PURE__ */ React31.createElement("table", { className: merged, ...rest }));
|
|
2046
2242
|
}
|
|
2047
2243
|
export {
|
|
2048
2244
|
Button,
|
|
@@ -2060,6 +2256,8 @@ export {
|
|
|
2060
2256
|
Label,
|
|
2061
2257
|
Layout,
|
|
2062
2258
|
Metadata,
|
|
2259
|
+
ReferencedItems,
|
|
2260
|
+
References,
|
|
2063
2261
|
MdxRelatedItems as RelatedItems,
|
|
2064
2262
|
RequiredStatement,
|
|
2065
2263
|
Scroll,
|