@canopy-iiif/app 1.4.10 → 1.4.12
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/base-path.js +67 -0
- package/lib/common.js +4 -5
- package/package.json +6 -1
- package/types/base-path.d.ts +4 -0
- package/ui/dist/index.mjs +127 -120
- package/ui/dist/index.mjs.map +4 -4
- package/ui/dist/server.mjs +54 -47
- package/ui/dist/server.mjs.map +4 -4
- package/ui/styles/components/{_biblography.scss → _bibliography.scss} +15 -15
- package/ui/styles/components/index.scss +1 -1
- package/ui/styles/components/search/_tabs.scss +6 -6
- package/ui/styles/index.css +21 -21
package/ui/dist/index.mjs
CHANGED
|
@@ -1554,8 +1554,14 @@ var Image = (props = {}) => {
|
|
|
1554
1554
|
return /* @__PURE__ */ React21.createElement(CloverImage, { ...props, className: rootClassName });
|
|
1555
1555
|
};
|
|
1556
1556
|
|
|
1557
|
-
// ui/src/iiif/
|
|
1557
|
+
// ui/src/iiif/Properties/Id.jsx
|
|
1558
1558
|
import React22 from "react";
|
|
1559
|
+
function Id({ title = "IIIF Manifest", id, ...props }) {
|
|
1560
|
+
return /* @__PURE__ */ React22.createElement("dl", null, /* @__PURE__ */ React22.createElement("dt", null, title), /* @__PURE__ */ React22.createElement("dd", null, /* @__PURE__ */ React22.createElement("a", { href: id }, id)));
|
|
1561
|
+
}
|
|
1562
|
+
|
|
1563
|
+
// ui/src/iiif/MdxRelatedItems.jsx
|
|
1564
|
+
import React23 from "react";
|
|
1559
1565
|
function MdxRelatedItems(props) {
|
|
1560
1566
|
let json = "{}";
|
|
1561
1567
|
try {
|
|
@@ -1563,7 +1569,7 @@ function MdxRelatedItems(props) {
|
|
|
1563
1569
|
} catch (_) {
|
|
1564
1570
|
json = "{}";
|
|
1565
1571
|
}
|
|
1566
|
-
return /* @__PURE__ */
|
|
1572
|
+
return /* @__PURE__ */ React23.createElement("div", { "data-canopy-related-items": "1" }, /* @__PURE__ */ React23.createElement(
|
|
1567
1573
|
"script",
|
|
1568
1574
|
{
|
|
1569
1575
|
type: "application/json",
|
|
@@ -1573,7 +1579,7 @@ function MdxRelatedItems(props) {
|
|
|
1573
1579
|
}
|
|
1574
1580
|
|
|
1575
1581
|
// ui/src/search/MdxSearchResults.jsx
|
|
1576
|
-
import
|
|
1582
|
+
import React24 from "react";
|
|
1577
1583
|
function MdxSearchResults(props) {
|
|
1578
1584
|
let json = "{}";
|
|
1579
1585
|
try {
|
|
@@ -1581,11 +1587,11 @@ function MdxSearchResults(props) {
|
|
|
1581
1587
|
} catch (_) {
|
|
1582
1588
|
json = "{}";
|
|
1583
1589
|
}
|
|
1584
|
-
return /* @__PURE__ */
|
|
1590
|
+
return /* @__PURE__ */ React24.createElement("div", { "data-canopy-search-results": "1" }, /* @__PURE__ */ React24.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: json } }));
|
|
1585
1591
|
}
|
|
1586
1592
|
|
|
1587
1593
|
// ui/src/search/SearchSummary.jsx
|
|
1588
|
-
import
|
|
1594
|
+
import React25 from "react";
|
|
1589
1595
|
function SearchSummary(props) {
|
|
1590
1596
|
let json = "{}";
|
|
1591
1597
|
try {
|
|
@@ -1593,11 +1599,11 @@ function SearchSummary(props) {
|
|
|
1593
1599
|
} catch (_) {
|
|
1594
1600
|
json = "{}";
|
|
1595
1601
|
}
|
|
1596
|
-
return /* @__PURE__ */
|
|
1602
|
+
return /* @__PURE__ */ React25.createElement("div", { "data-canopy-search-summary": "1" }, /* @__PURE__ */ React25.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: json } }));
|
|
1597
1603
|
}
|
|
1598
1604
|
|
|
1599
1605
|
// ui/src/search/MdxSearchTabs.jsx
|
|
1600
|
-
import
|
|
1606
|
+
import React26 from "react";
|
|
1601
1607
|
function MdxSearchTabs(props) {
|
|
1602
1608
|
let json = "{}";
|
|
1603
1609
|
try {
|
|
@@ -1605,11 +1611,11 @@ function MdxSearchTabs(props) {
|
|
|
1605
1611
|
} catch (_) {
|
|
1606
1612
|
json = "{}";
|
|
1607
1613
|
}
|
|
1608
|
-
return /* @__PURE__ */
|
|
1614
|
+
return /* @__PURE__ */ React26.createElement("div", { "data-canopy-search-tabs": "1" }, /* @__PURE__ */ React26.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: json } }));
|
|
1609
1615
|
}
|
|
1610
1616
|
|
|
1611
1617
|
// ui/src/search/MdxSearch.jsx
|
|
1612
|
-
import
|
|
1618
|
+
import React27 from "react";
|
|
1613
1619
|
function MdxSearch(props = {}) {
|
|
1614
1620
|
const {
|
|
1615
1621
|
layout,
|
|
@@ -1627,15 +1633,15 @@ function MdxSearch(props = {}) {
|
|
|
1627
1633
|
resultsPayload.layout = layout;
|
|
1628
1634
|
}
|
|
1629
1635
|
const classes = ["canopy-search", className].filter(Boolean).join(" ");
|
|
1630
|
-
return /* @__PURE__ */
|
|
1636
|
+
return /* @__PURE__ */ React27.createElement("section", { className: classes, "data-canopy-search": "1" }, showTabs ? /* @__PURE__ */ React27.createElement(MdxSearchTabs, { ...tabsProps }) : null, showSummary ? /* @__PURE__ */ React27.createElement(SearchSummary, { ...summaryProps }) : null, showResults ? /* @__PURE__ */ React27.createElement(MdxSearchResults, { ...resultsPayload }) : null, children || null);
|
|
1631
1637
|
}
|
|
1632
1638
|
|
|
1633
1639
|
// ui/src/search/SearchResults.jsx
|
|
1634
|
-
import
|
|
1640
|
+
import React28 from "react";
|
|
1635
1641
|
function DefaultArticleTemplate({ record, query }) {
|
|
1636
1642
|
if (!record) return null;
|
|
1637
1643
|
const metadata = Array.isArray(record.metadata) ? record.metadata : [];
|
|
1638
|
-
return /* @__PURE__ */
|
|
1644
|
+
return /* @__PURE__ */ React28.createElement(
|
|
1639
1645
|
ArticleCard,
|
|
1640
1646
|
{
|
|
1641
1647
|
href: record.href,
|
|
@@ -1653,7 +1659,7 @@ function DefaultFigureTemplate({ record, thumbnailAspectRatio }) {
|
|
|
1653
1659
|
if (!record) return null;
|
|
1654
1660
|
const hasDims = Number.isFinite(Number(record.thumbnailWidth)) && Number(record.thumbnailWidth) > 0 && Number.isFinite(Number(record.thumbnailHeight)) && Number(record.thumbnailHeight) > 0;
|
|
1655
1661
|
const aspect = Number.isFinite(Number(thumbnailAspectRatio)) && Number(thumbnailAspectRatio) > 0 ? Number(thumbnailAspectRatio) : hasDims ? Number(record.thumbnailWidth) / Number(record.thumbnailHeight) : void 0;
|
|
1656
|
-
return /* @__PURE__ */
|
|
1662
|
+
return /* @__PURE__ */ React28.createElement(
|
|
1657
1663
|
Card,
|
|
1658
1664
|
{
|
|
1659
1665
|
href: record.href,
|
|
@@ -1674,7 +1680,7 @@ function SearchResults({
|
|
|
1674
1680
|
variant = "auto"
|
|
1675
1681
|
}) {
|
|
1676
1682
|
if (!results.length) {
|
|
1677
|
-
return /* @__PURE__ */
|
|
1683
|
+
return /* @__PURE__ */ React28.createElement("div", { className: "text-slate-600" }, /* @__PURE__ */ React28.createElement("em", null, "No results"));
|
|
1678
1684
|
}
|
|
1679
1685
|
const normalizedType = String(type || "all").toLowerCase();
|
|
1680
1686
|
const normalizedVariant = variant === "figure" || variant === "article" ? variant : "auto";
|
|
@@ -1682,9 +1688,9 @@ function SearchResults({
|
|
|
1682
1688
|
const FigureTemplate = templates && templates.figure ? templates.figure : DefaultFigureTemplate;
|
|
1683
1689
|
const ArticleTemplate = templates && templates.article ? templates.article : DefaultArticleTemplate;
|
|
1684
1690
|
if (isAnnotationView) {
|
|
1685
|
-
return /* @__PURE__ */
|
|
1691
|
+
return /* @__PURE__ */ React28.createElement("div", { id: "search-results", className: "space-y-4" }, results.map((r, i) => {
|
|
1686
1692
|
if (!r) return null;
|
|
1687
|
-
return /* @__PURE__ */
|
|
1693
|
+
return /* @__PURE__ */ React28.createElement(
|
|
1688
1694
|
ArticleTemplate,
|
|
1689
1695
|
{
|
|
1690
1696
|
key: r.id || i,
|
|
@@ -1702,20 +1708,20 @@ function SearchResults({
|
|
|
1702
1708
|
return !isWorkRecord(record) || normalizedType !== "work";
|
|
1703
1709
|
};
|
|
1704
1710
|
if (layout === "list") {
|
|
1705
|
-
return /* @__PURE__ */
|
|
1711
|
+
return /* @__PURE__ */ React28.createElement("div", { id: "search-results", className: "space-y-6" }, results.map((r, i) => {
|
|
1706
1712
|
if (shouldRenderAsArticle(r)) {
|
|
1707
|
-
return /* @__PURE__ */
|
|
1713
|
+
return /* @__PURE__ */ React28.createElement("div", { key: i, className: `search-result ${r && r.type}` }, /* @__PURE__ */ React28.createElement(ArticleTemplate, { record: r, query, layout }));
|
|
1708
1714
|
}
|
|
1709
1715
|
const hasDims = Number.isFinite(Number(r.thumbnailWidth)) && Number(r.thumbnailWidth) > 0 && Number.isFinite(Number(r.thumbnailHeight)) && Number(r.thumbnailHeight) > 0;
|
|
1710
1716
|
const aspect = hasDims ? Number(r.thumbnailWidth) / Number(r.thumbnailHeight) : void 0;
|
|
1711
|
-
return /* @__PURE__ */
|
|
1717
|
+
return /* @__PURE__ */ React28.createElement(
|
|
1712
1718
|
"div",
|
|
1713
1719
|
{
|
|
1714
1720
|
key: i,
|
|
1715
1721
|
className: `search-result ${r.type}`,
|
|
1716
1722
|
"data-thumbnail-aspect-ratio": aspect
|
|
1717
1723
|
},
|
|
1718
|
-
/* @__PURE__ */
|
|
1724
|
+
/* @__PURE__ */ React28.createElement(
|
|
1719
1725
|
FigureTemplate,
|
|
1720
1726
|
{
|
|
1721
1727
|
record: r,
|
|
@@ -1727,20 +1733,20 @@ function SearchResults({
|
|
|
1727
1733
|
);
|
|
1728
1734
|
}));
|
|
1729
1735
|
}
|
|
1730
|
-
return /* @__PURE__ */
|
|
1736
|
+
return /* @__PURE__ */ React28.createElement("div", { id: "search-results" }, /* @__PURE__ */ React28.createElement(Grid, null, results.map((r, i) => {
|
|
1731
1737
|
if (shouldRenderAsArticle(r)) {
|
|
1732
|
-
return /* @__PURE__ */
|
|
1738
|
+
return /* @__PURE__ */ React28.createElement(GridItem, { key: i, className: `search-result ${r && r.type}` }, /* @__PURE__ */ React28.createElement(ArticleTemplate, { record: r, query, layout }));
|
|
1733
1739
|
}
|
|
1734
1740
|
const hasDims = Number.isFinite(Number(r.thumbnailWidth)) && Number(r.thumbnailWidth) > 0 && Number.isFinite(Number(r.thumbnailHeight)) && Number(r.thumbnailHeight) > 0;
|
|
1735
1741
|
const aspect = hasDims ? Number(r.thumbnailWidth) / Number(r.thumbnailHeight) : void 0;
|
|
1736
|
-
return /* @__PURE__ */
|
|
1742
|
+
return /* @__PURE__ */ React28.createElement(
|
|
1737
1743
|
GridItem,
|
|
1738
1744
|
{
|
|
1739
1745
|
key: i,
|
|
1740
1746
|
className: `search-result ${r.type}`,
|
|
1741
1747
|
"data-thumbnail-aspect-ratio": aspect
|
|
1742
1748
|
},
|
|
1743
|
-
/* @__PURE__ */
|
|
1749
|
+
/* @__PURE__ */ React28.createElement(
|
|
1744
1750
|
FigureTemplate,
|
|
1745
1751
|
{
|
|
1746
1752
|
record: r,
|
|
@@ -1754,7 +1760,7 @@ function SearchResults({
|
|
|
1754
1760
|
}
|
|
1755
1761
|
|
|
1756
1762
|
// ui/src/search/SearchTabs.jsx
|
|
1757
|
-
import
|
|
1763
|
+
import React29, { useRef as useRef2, useState as useState6, useEffect as useEffect6 } from "react";
|
|
1758
1764
|
function SearchTabs({
|
|
1759
1765
|
type = "all",
|
|
1760
1766
|
onTypeChange,
|
|
@@ -1808,7 +1814,7 @@ function SearchTabs({
|
|
|
1808
1814
|
width: `${itemBoundingBox.width}px`
|
|
1809
1815
|
};
|
|
1810
1816
|
}
|
|
1811
|
-
return /* @__PURE__ */
|
|
1817
|
+
return /* @__PURE__ */ React29.createElement("div", { className: "canopy-search-tabs-wrapper" }, /* @__PURE__ */ React29.createElement(
|
|
1812
1818
|
"div",
|
|
1813
1819
|
{
|
|
1814
1820
|
role: "tablist",
|
|
@@ -1817,7 +1823,7 @@ function SearchTabs({
|
|
|
1817
1823
|
ref: wrapperRef,
|
|
1818
1824
|
onMouseLeave: resetHighlight
|
|
1819
1825
|
},
|
|
1820
|
-
/* @__PURE__ */
|
|
1826
|
+
/* @__PURE__ */ React29.createElement(
|
|
1821
1827
|
"div",
|
|
1822
1828
|
{
|
|
1823
1829
|
ref: highlightRef,
|
|
@@ -1829,7 +1835,7 @@ function SearchTabs({
|
|
|
1829
1835
|
const active = String(type).toLowerCase() === String(t).toLowerCase();
|
|
1830
1836
|
const cRaw = counts && Object.prototype.hasOwnProperty.call(counts, t) ? counts[t] : void 0;
|
|
1831
1837
|
const c = Number.isFinite(Number(cRaw)) ? Number(cRaw) : 0;
|
|
1832
|
-
return /* @__PURE__ */
|
|
1838
|
+
return /* @__PURE__ */ React29.createElement(
|
|
1833
1839
|
"button",
|
|
1834
1840
|
{
|
|
1835
1841
|
key: t,
|
|
@@ -1847,7 +1853,7 @@ function SearchTabs({
|
|
|
1847
1853
|
")"
|
|
1848
1854
|
);
|
|
1849
1855
|
})
|
|
1850
|
-
), hasFilters ? /* @__PURE__ */
|
|
1856
|
+
), hasFilters ? /* @__PURE__ */ React29.createElement(
|
|
1851
1857
|
"button",
|
|
1852
1858
|
{
|
|
1853
1859
|
type: "button",
|
|
@@ -1855,12 +1861,12 @@ function SearchTabs({
|
|
|
1855
1861
|
"aria-expanded": filtersOpen ? "true" : "false",
|
|
1856
1862
|
className: "inline-flex items-center gap-2 rounded-md border border-slate-200 bg-white px-3 py-1.5 text-sm font-medium text-slate-700 shadow-sm transition hover:border-brand-200 hover:bg-brand-50 hover:text-brand-700"
|
|
1857
1863
|
},
|
|
1858
|
-
/* @__PURE__ */
|
|
1864
|
+
/* @__PURE__ */ React29.createElement("span", null, filtersLabel, filterBadge)
|
|
1859
1865
|
) : null);
|
|
1860
1866
|
}
|
|
1861
1867
|
|
|
1862
1868
|
// ui/src/search/SearchFiltersDialog.jsx
|
|
1863
|
-
import
|
|
1869
|
+
import React30 from "react";
|
|
1864
1870
|
function toArray(input) {
|
|
1865
1871
|
if (!input) return [];
|
|
1866
1872
|
if (Array.isArray(input)) return input;
|
|
@@ -1899,20 +1905,20 @@ function FacetSection({ facet, selected, onToggle }) {
|
|
|
1899
1905
|
const selectedValues = selected.get(String(slug)) || /* @__PURE__ */ new Set();
|
|
1900
1906
|
const checkboxId = (valueSlug) => `filter-${slug}-${valueSlug}`;
|
|
1901
1907
|
const hasSelection = selectedValues.size > 0;
|
|
1902
|
-
const [quickQuery, setQuickQuery] =
|
|
1908
|
+
const [quickQuery, setQuickQuery] = React30.useState("");
|
|
1903
1909
|
const hasQuery = quickQuery.trim().length > 0;
|
|
1904
|
-
const filteredValues =
|
|
1910
|
+
const filteredValues = React30.useMemo(
|
|
1905
1911
|
() => facetMatches(values, quickQuery),
|
|
1906
1912
|
[values, quickQuery]
|
|
1907
1913
|
);
|
|
1908
|
-
return /* @__PURE__ */
|
|
1914
|
+
return /* @__PURE__ */ React30.createElement(
|
|
1909
1915
|
"details",
|
|
1910
1916
|
{
|
|
1911
1917
|
className: "canopy-search-filters__facet",
|
|
1912
1918
|
open: hasSelection
|
|
1913
1919
|
},
|
|
1914
|
-
/* @__PURE__ */
|
|
1915
|
-
/* @__PURE__ */
|
|
1920
|
+
/* @__PURE__ */ React30.createElement("summary", { className: "canopy-search-filters__facet-summary" }, /* @__PURE__ */ React30.createElement("span", null, label), /* @__PURE__ */ React30.createElement("span", { className: "canopy-search-filters__facet-count" }, values.length)),
|
|
1921
|
+
/* @__PURE__ */ React30.createElement("div", { className: "canopy-search-filters__facet-content" }, /* @__PURE__ */ React30.createElement("div", { className: "canopy-search-filters__quick" }, /* @__PURE__ */ React30.createElement(
|
|
1916
1922
|
"input",
|
|
1917
1923
|
{
|
|
1918
1924
|
type: "search",
|
|
@@ -1922,7 +1928,7 @@ function FacetSection({ facet, selected, onToggle }) {
|
|
|
1922
1928
|
className: "canopy-search-filters__quick-input",
|
|
1923
1929
|
"aria-label": `Filter ${label} values`
|
|
1924
1930
|
}
|
|
1925
|
-
), quickQuery ? /* @__PURE__ */
|
|
1931
|
+
), quickQuery ? /* @__PURE__ */ React30.createElement(
|
|
1926
1932
|
"button",
|
|
1927
1933
|
{
|
|
1928
1934
|
type: "button",
|
|
@@ -1930,11 +1936,11 @@ function FacetSection({ facet, selected, onToggle }) {
|
|
|
1930
1936
|
className: "canopy-search-filters__quick-clear"
|
|
1931
1937
|
},
|
|
1932
1938
|
"Clear"
|
|
1933
|
-
) : null), hasQuery && !filteredValues.length ? /* @__PURE__ */
|
|
1939
|
+
) : null), hasQuery && !filteredValues.length ? /* @__PURE__ */ React30.createElement("p", { className: "canopy-search-filters__facet-notice" }, "No matches found.") : null, /* @__PURE__ */ React30.createElement("ul", { className: "canopy-search-filters__facet-list" }, filteredValues.map((entry) => {
|
|
1934
1940
|
const valueSlug = String(entry.slug || entry.value || "");
|
|
1935
1941
|
const isChecked = selectedValues.has(valueSlug);
|
|
1936
1942
|
const inputId = checkboxId(valueSlug);
|
|
1937
|
-
return /* @__PURE__ */
|
|
1943
|
+
return /* @__PURE__ */ React30.createElement("li", { key: valueSlug, className: "canopy-search-filters__facet-item" }, /* @__PURE__ */ React30.createElement(
|
|
1938
1944
|
"input",
|
|
1939
1945
|
{
|
|
1940
1946
|
id: inputId,
|
|
@@ -1946,15 +1952,15 @@ function FacetSection({ facet, selected, onToggle }) {
|
|
|
1946
1952
|
if (onToggle) onToggle(slug, valueSlug, nextChecked);
|
|
1947
1953
|
}
|
|
1948
1954
|
}
|
|
1949
|
-
), /* @__PURE__ */
|
|
1955
|
+
), /* @__PURE__ */ React30.createElement(
|
|
1950
1956
|
"label",
|
|
1951
1957
|
{
|
|
1952
1958
|
htmlFor: inputId,
|
|
1953
1959
|
className: "canopy-search-filters__facet-label"
|
|
1954
1960
|
},
|
|
1955
|
-
/* @__PURE__ */
|
|
1961
|
+
/* @__PURE__ */ React30.createElement("span", null, entry.value, " ", Number.isFinite(entry.doc_count) ? /* @__PURE__ */ React30.createElement("span", { className: "canopy-search-filters__facet-count" }, "(", entry.doc_count, ")") : null)
|
|
1956
1962
|
));
|
|
1957
|
-
}), !filteredValues.length && !hasQuery ? /* @__PURE__ */
|
|
1963
|
+
}), !filteredValues.length && !hasQuery ? /* @__PURE__ */ React30.createElement("li", { className: "canopy-search-filters__facet-empty" }, "No values available.") : null))
|
|
1958
1964
|
);
|
|
1959
1965
|
}
|
|
1960
1966
|
function SearchFiltersDialog(props = {}) {
|
|
@@ -1976,7 +1982,7 @@ function SearchFiltersDialog(props = {}) {
|
|
|
1976
1982
|
(total, set) => total + set.size,
|
|
1977
1983
|
0
|
|
1978
1984
|
);
|
|
1979
|
-
|
|
1985
|
+
React30.useEffect(() => {
|
|
1980
1986
|
if (!open) return void 0;
|
|
1981
1987
|
if (typeof document === "undefined") return void 0;
|
|
1982
1988
|
const body = document.body;
|
|
@@ -1993,7 +1999,7 @@ function SearchFiltersDialog(props = {}) {
|
|
|
1993
1999
|
if (!open) return null;
|
|
1994
2000
|
const brandId = "canopy-modal-filters-label";
|
|
1995
2001
|
const subtitleText = subtitle != null ? subtitle : title;
|
|
1996
|
-
return /* @__PURE__ */
|
|
2002
|
+
return /* @__PURE__ */ React30.createElement(
|
|
1997
2003
|
CanopyModal,
|
|
1998
2004
|
{
|
|
1999
2005
|
id: "canopy-modal-filters",
|
|
@@ -2008,8 +2014,8 @@ function SearchFiltersDialog(props = {}) {
|
|
|
2008
2014
|
onBackgroundClick: () => onOpenChange && onOpenChange(false),
|
|
2009
2015
|
bodyClassName: "canopy-modal__body--filters"
|
|
2010
2016
|
},
|
|
2011
|
-
subtitleText ? /* @__PURE__ */
|
|
2012
|
-
/* @__PURE__ */
|
|
2017
|
+
subtitleText ? /* @__PURE__ */ React30.createElement("p", { className: "canopy-search-filters__subtitle" }, subtitleText) : null,
|
|
2018
|
+
/* @__PURE__ */ React30.createElement("div", { className: "canopy-search-filters__body" }, Array.isArray(facets) && facets.length ? /* @__PURE__ */ React30.createElement("div", { className: "canopy-search-filters__facets" }, facets.map((facet) => /* @__PURE__ */ React30.createElement(
|
|
2013
2019
|
FacetSection,
|
|
2014
2020
|
{
|
|
2015
2021
|
key: facet.slug || facet.label,
|
|
@@ -2017,8 +2023,8 @@ function SearchFiltersDialog(props = {}) {
|
|
|
2017
2023
|
selected: selectedMap,
|
|
2018
2024
|
onToggle
|
|
2019
2025
|
}
|
|
2020
|
-
))) : /* @__PURE__ */
|
|
2021
|
-
/* @__PURE__ */
|
|
2026
|
+
))) : /* @__PURE__ */ React30.createElement("p", { className: "canopy-search-filters__empty" }, "No filters are available for this collection.")),
|
|
2027
|
+
/* @__PURE__ */ React30.createElement("footer", { className: "canopy-search-filters__footer" }, /* @__PURE__ */ React30.createElement("div", null, activeCount ? `${activeCount} filter${activeCount === 1 ? "" : "s"} applied` : "No filters applied"), /* @__PURE__ */ React30.createElement("div", { className: "canopy-search-filters__footer-actions" }, /* @__PURE__ */ React30.createElement(
|
|
2022
2028
|
"button",
|
|
2023
2029
|
{
|
|
2024
2030
|
type: "button",
|
|
@@ -2029,7 +2035,7 @@ function SearchFiltersDialog(props = {}) {
|
|
|
2029
2035
|
className: "canopy-search-filters__button canopy-search-filters__button--secondary"
|
|
2030
2036
|
},
|
|
2031
2037
|
"Clear all"
|
|
2032
|
-
), /* @__PURE__ */
|
|
2038
|
+
), /* @__PURE__ */ React30.createElement(
|
|
2033
2039
|
"button",
|
|
2034
2040
|
{
|
|
2035
2041
|
type: "button",
|
|
@@ -2042,7 +2048,7 @@ function SearchFiltersDialog(props = {}) {
|
|
|
2042
2048
|
}
|
|
2043
2049
|
|
|
2044
2050
|
// ui/src/search-form/MdxSearchFormModal.jsx
|
|
2045
|
-
import
|
|
2051
|
+
import React31 from "react";
|
|
2046
2052
|
function MdxSearchFormModal(props = {}) {
|
|
2047
2053
|
const {
|
|
2048
2054
|
placeholder = "Search\u2026",
|
|
@@ -2058,24 +2064,24 @@ function MdxSearchFormModal(props = {}) {
|
|
|
2058
2064
|
const text = typeof label === "string" && label.trim() ? label.trim() : buttonLabel;
|
|
2059
2065
|
const resolvedSearchPath = resolveSearchPath(searchPath);
|
|
2060
2066
|
const data = { placeholder, hotkey, maxResults, groupOrder, label: text, searchPath: resolvedSearchPath };
|
|
2061
|
-
return /* @__PURE__ */
|
|
2067
|
+
return /* @__PURE__ */ React31.createElement("div", { "data-canopy-search-form": true, className: "flex-1 min-w-0" }, /* @__PURE__ */ React31.createElement("div", { className: "relative w-full" }, /* @__PURE__ */ React31.createElement(SearchPanelForm, { placeholder, buttonLabel, label, searchPath: resolvedSearchPath }), /* @__PURE__ */ React31.createElement(SearchPanelTeaserResults, null)), /* @__PURE__ */ React31.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: JSON.stringify(data) } }));
|
|
2062
2068
|
}
|
|
2063
2069
|
|
|
2064
2070
|
// ui/src/docs/MarkdownTable.jsx
|
|
2065
|
-
import
|
|
2071
|
+
import React32 from "react";
|
|
2066
2072
|
function MarkdownTable({ className = "", ...rest }) {
|
|
2067
2073
|
const merged = ["markdown-table", className].filter(Boolean).join(" ");
|
|
2068
|
-
return /* @__PURE__ */
|
|
2074
|
+
return /* @__PURE__ */ React32.createElement("div", { className: "markdown-table__frame" }, /* @__PURE__ */ React32.createElement("table", { className: merged, ...rest }));
|
|
2069
2075
|
}
|
|
2070
2076
|
|
|
2071
2077
|
// ui/src/docs/Diagram.jsx
|
|
2072
|
-
import
|
|
2078
|
+
import React33 from "react";
|
|
2073
2079
|
function CanopyDiagram() {
|
|
2074
|
-
return /* @__PURE__ */
|
|
2080
|
+
return /* @__PURE__ */ React33.createElement("div", { className: "canopy-diagram" }, /* @__PURE__ */ React33.createElement("section", { className: "canopy-diagram__section canopy-diagram__section--collections" }, /* @__PURE__ */ React33.createElement("h3", null, "IIIF Collection(s)"), /* @__PURE__ */ React33.createElement("span", { className: "canopy-diagram__section-summary" }, "Source collections contribute 105 total manifests that Canopy retrieves as-is via IIIF endpoints."), /* @__PURE__ */ React33.createElement("div", { className: "canopy-diagram__grid" }, /* @__PURE__ */ React33.createElement("article", null, /* @__PURE__ */ React33.createElement("h4", null, "Collection A"), /* @__PURE__ */ React33.createElement("ul", null, /* @__PURE__ */ React33.createElement("li", null, "70 Manifests"), /* @__PURE__ */ React33.createElement("li", null, "IIIF Images + A/V"), /* @__PURE__ */ React33.createElement("li", null, "Textual Annotations"))), /* @__PURE__ */ React33.createElement("article", null, /* @__PURE__ */ React33.createElement("h4", null, "Collection B"), /* @__PURE__ */ React33.createElement("ul", null, /* @__PURE__ */ React33.createElement("li", null, "35 Manifests"), /* @__PURE__ */ React33.createElement("li", null, "IIIF Images + A/V"), /* @__PURE__ */ React33.createElement("li", null, "Textual Annotations"))))), /* @__PURE__ */ React33.createElement("div", { className: "canopy-diagram__arrow", "aria-hidden": "true" }, /* @__PURE__ */ React33.createElement("span", { className: "canopy-diagram__arrow-line" }), /* @__PURE__ */ React33.createElement("span", { className: "canopy-diagram__arrow-head" })), /* @__PURE__ */ React33.createElement("section", { className: "canopy-diagram__section canopy-diagram__section--build" }, /* @__PURE__ */ React33.createElement("h3", null, "Canopy Build Process"), /* @__PURE__ */ React33.createElement("span", { className: "canopy-diagram__section-summary" }, "Canopy syncs manifests, page content, and annotations before bundling the site."), /* @__PURE__ */ React33.createElement("div", { className: "canopy-diagram__grid" }, /* @__PURE__ */ React33.createElement("article", null, /* @__PURE__ */ React33.createElement("h4", null, "Automated content"), /* @__PURE__ */ React33.createElement("ul", null, /* @__PURE__ */ React33.createElement("li", null, "105 manifests \u2192 105 work pages"), /* @__PURE__ */ React33.createElement("li", null, "One page per manifest"), /* @__PURE__ */ React33.createElement("li", null, "Customize page layout"))), /* @__PURE__ */ React33.createElement("article", null, /* @__PURE__ */ React33.createElement("h4", null, "Contextual content"), /* @__PURE__ */ React33.createElement("ul", null, /* @__PURE__ */ React33.createElement("li", null, "Markdown & MDX pages"), /* @__PURE__ */ React33.createElement("li", null, "Author narratives"), /* @__PURE__ */ React33.createElement("li", null, "Reference manifests inline"))), /* @__PURE__ */ React33.createElement("article", null, /* @__PURE__ */ React33.createElement("h4", null, "Search index"), /* @__PURE__ */ React33.createElement("ul", null, /* @__PURE__ */ React33.createElement("li", null, "Combines works + pages"), /* @__PURE__ */ React33.createElement("li", null, "Customize result layout"), /* @__PURE__ */ React33.createElement("li", null, "Optional annotations"))))), /* @__PURE__ */ React33.createElement("div", { className: "canopy-diagram__arrow", "aria-hidden": "true" }, /* @__PURE__ */ React33.createElement("span", { className: "canopy-diagram__arrow-line" }), /* @__PURE__ */ React33.createElement("span", { className: "canopy-diagram__arrow-head" })), /* @__PURE__ */ React33.createElement("section", { className: "canopy-diagram__section canopy-diagram__section--output" }, /* @__PURE__ */ React33.createElement("h3", null, "Static Digital Project"), /* @__PURE__ */ React33.createElement("span", { className: "canopy-diagram__section-summary" }, "The output is a lightweight bundle of HTML, CSS, JS, and JSON assets that can deploy anywhere."), /* @__PURE__ */ React33.createElement("div", { className: "canopy-diagram__grid" }, /* @__PURE__ */ React33.createElement("article", null, /* @__PURE__ */ React33.createElement("h4", null, "Work pages"), /* @__PURE__ */ React33.createElement("ul", null, /* @__PURE__ */ React33.createElement("li", null, "105 generated HTML pages"), /* @__PURE__ */ React33.createElement("li", null, "Each links back to source manifests"), /* @__PURE__ */ React33.createElement("li", null, "Styled with Canopy components"))), /* @__PURE__ */ React33.createElement("article", null, /* @__PURE__ */ React33.createElement("h4", null, "Custom pages"), /* @__PURE__ */ React33.createElement("ul", null, /* @__PURE__ */ React33.createElement("li", null, "Markdown & MDX-authored content"), /* @__PURE__ */ React33.createElement("li", null, "Reusable layouts for narratives"), /* @__PURE__ */ React33.createElement("li", null, "Embed IIIF media & interstitials"))), /* @__PURE__ */ React33.createElement("article", null, /* @__PURE__ */ React33.createElement("h4", null, "Search bundle"), /* @__PURE__ */ React33.createElement("ul", null, /* @__PURE__ */ React33.createElement("li", null, "Static FlexSearch index"), /* @__PURE__ */ React33.createElement("li", null, "Works + pages share records"), /* @__PURE__ */ React33.createElement("li", null, "Optional annotation dataset"))))));
|
|
2075
2081
|
}
|
|
2076
2082
|
|
|
2077
2083
|
// ui/src/content/timeline/Timeline.jsx
|
|
2078
|
-
import
|
|
2084
|
+
import React35 from "react";
|
|
2079
2085
|
|
|
2080
2086
|
// ui/src/content/timeline/date-utils.js
|
|
2081
2087
|
var FALLBACK_LOCALE = (() => {
|
|
@@ -2228,7 +2234,7 @@ function clampProgress(value) {
|
|
|
2228
2234
|
}
|
|
2229
2235
|
|
|
2230
2236
|
// ui/src/layout/ReferencedManifestCard.jsx
|
|
2231
|
-
import
|
|
2237
|
+
import React34 from "react";
|
|
2232
2238
|
function normalizeMetadata(metadata, summary) {
|
|
2233
2239
|
if (Array.isArray(metadata) && metadata.length) {
|
|
2234
2240
|
return metadata.filter(Boolean);
|
|
@@ -2262,7 +2268,7 @@ function ReferencedManifestCard({
|
|
|
2262
2268
|
"canopy-referenced-manifest-card",
|
|
2263
2269
|
className
|
|
2264
2270
|
].filter(Boolean).join(" ");
|
|
2265
|
-
return /* @__PURE__ */
|
|
2271
|
+
return /* @__PURE__ */ React34.createElement(
|
|
2266
2272
|
TeaserCard,
|
|
2267
2273
|
{
|
|
2268
2274
|
href: resolvedHref || void 0,
|
|
@@ -2444,14 +2450,14 @@ function TimelineConnector({ side, isActive, highlight }) {
|
|
|
2444
2450
|
"canopy-timeline__connector-dot",
|
|
2445
2451
|
highlight || isActive ? "is-active" : ""
|
|
2446
2452
|
].filter(Boolean).join(" ");
|
|
2447
|
-
return /* @__PURE__ */
|
|
2453
|
+
return /* @__PURE__ */ React35.createElement("span", { className: connectorClasses, "aria-hidden": "true" }, side === "left" ? /* @__PURE__ */ React35.createElement(React35.Fragment, null, /* @__PURE__ */ React35.createElement("span", { className: "canopy-timeline__connector-line" }), /* @__PURE__ */ React35.createElement("span", { className: dotClasses })) : /* @__PURE__ */ React35.createElement(React35.Fragment, null, /* @__PURE__ */ React35.createElement("span", { className: dotClasses }), /* @__PURE__ */ React35.createElement("span", { className: "canopy-timeline__connector-line" })));
|
|
2448
2454
|
}
|
|
2449
2455
|
function renderResourceSection(point) {
|
|
2450
2456
|
if (!point) return null;
|
|
2451
2457
|
const manifestCards = Array.isArray(point.manifests) ? point.manifests.filter(Boolean) : [];
|
|
2452
2458
|
const legacyResources = Array.isArray(point.resources) ? point.resources.filter(Boolean) : [];
|
|
2453
2459
|
if (!manifestCards.length && !legacyResources.length) return null;
|
|
2454
|
-
return /* @__PURE__ */
|
|
2460
|
+
return /* @__PURE__ */ React35.createElement("div", { className: "canopy-timeline__resources" }, /* @__PURE__ */ React35.createElement("div", { className: "canopy-timeline__resources-list" }, manifestCards.map((manifest) => /* @__PURE__ */ React35.createElement("div", { key: manifest.id || manifest.href }, /* @__PURE__ */ React35.createElement(ReferencedManifestCard, { manifest }))), legacyResources.map((resource, idx) => /* @__PURE__ */ React35.createElement("div", { key: resource.id || resource.href || `legacy-${idx}` }, /* @__PURE__ */ React35.createElement(
|
|
2455
2461
|
TeaserCard,
|
|
2456
2462
|
{
|
|
2457
2463
|
href: resource.href,
|
|
@@ -2476,26 +2482,26 @@ function Timeline({
|
|
|
2476
2482
|
...rest
|
|
2477
2483
|
}) {
|
|
2478
2484
|
const payloadPoints = payload && Array.isArray(payload.points) ? payload.points : null;
|
|
2479
|
-
const rawPoints =
|
|
2485
|
+
const rawPoints = React35.useMemo(() => {
|
|
2480
2486
|
if (Array.isArray(pointsProp) && pointsProp.length) return pointsProp;
|
|
2481
2487
|
if (payloadPoints && payloadPoints.length) return payloadPoints;
|
|
2482
2488
|
return [];
|
|
2483
2489
|
}, [pointsProp, payloadPoints]);
|
|
2484
|
-
const sanitizedPoints =
|
|
2490
|
+
const sanitizedPoints = React35.useMemo(
|
|
2485
2491
|
() => sanitizePoints(rawPoints),
|
|
2486
2492
|
[rawPoints]
|
|
2487
2493
|
);
|
|
2488
2494
|
const localeValue = payload && payload.locale ? payload.locale : localeProp;
|
|
2489
|
-
const baseLocale =
|
|
2495
|
+
const baseLocale = React35.useMemo(
|
|
2490
2496
|
() => createLocale(localeValue),
|
|
2491
2497
|
[localeValue]
|
|
2492
2498
|
);
|
|
2493
2499
|
const rangeInput = payload && payload.range ? payload.range : rangeProp || {};
|
|
2494
|
-
const rangeOverrides =
|
|
2500
|
+
const rangeOverrides = React35.useMemo(
|
|
2495
2501
|
() => deriveRangeOverrides(sanitizedPoints, rangeInput),
|
|
2496
2502
|
[sanitizedPoints, rangeInput]
|
|
2497
2503
|
);
|
|
2498
|
-
const effectiveRange =
|
|
2504
|
+
const effectiveRange = React35.useMemo(
|
|
2499
2505
|
() => normalizeRange({
|
|
2500
2506
|
...rangeOverrides,
|
|
2501
2507
|
locale: baseLocale
|
|
@@ -2504,7 +2510,7 @@ function Timeline({
|
|
|
2504
2510
|
);
|
|
2505
2511
|
const spanStart = effectiveRange.startDate.getTime();
|
|
2506
2512
|
const span = effectiveRange.span;
|
|
2507
|
-
const pointsWithPosition =
|
|
2513
|
+
const pointsWithPosition = React35.useMemo(() => {
|
|
2508
2514
|
if (!sanitizedPoints.length) return [];
|
|
2509
2515
|
return sanitizedPoints.map((point, index) => {
|
|
2510
2516
|
const timestamp = point.meta.timestamp;
|
|
@@ -2518,29 +2524,29 @@ function Timeline({
|
|
|
2518
2524
|
};
|
|
2519
2525
|
});
|
|
2520
2526
|
}, [sanitizedPoints, spanStart, span]);
|
|
2521
|
-
const [activeId, setActiveId] =
|
|
2527
|
+
const [activeId, setActiveId] = React35.useState(
|
|
2522
2528
|
() => getActivePointId(pointsWithPosition)
|
|
2523
2529
|
);
|
|
2524
|
-
|
|
2530
|
+
React35.useEffect(() => {
|
|
2525
2531
|
setActiveId(getActivePointId(pointsWithPosition));
|
|
2526
2532
|
}, [pointsWithPosition]);
|
|
2527
2533
|
const thresholdValue = typeof thresholdProp === "number" ? thresholdProp : payload && payload.threshold != null ? payload.threshold : null;
|
|
2528
2534
|
const stepsValue = typeof steps === "number" ? Number(steps) : payload && typeof payload.steps === "number" ? Number(payload.steps) : null;
|
|
2529
|
-
const thresholdMs =
|
|
2535
|
+
const thresholdMs = React35.useMemo(
|
|
2530
2536
|
() => getThresholdMs(thresholdValue, effectiveRange.granularity),
|
|
2531
2537
|
[thresholdValue, effectiveRange.granularity]
|
|
2532
2538
|
);
|
|
2533
|
-
const groupedEntries =
|
|
2539
|
+
const groupedEntries = React35.useMemo(
|
|
2534
2540
|
() => buildGroupedEntries(pointsWithPosition, thresholdMs, {
|
|
2535
2541
|
granularity: effectiveRange.granularity,
|
|
2536
2542
|
locale: baseLocale
|
|
2537
2543
|
}),
|
|
2538
2544
|
[pointsWithPosition, thresholdMs, effectiveRange.granularity, baseLocale]
|
|
2539
2545
|
);
|
|
2540
|
-
const [expandedGroupIds, setExpandedGroupIds] =
|
|
2546
|
+
const [expandedGroupIds, setExpandedGroupIds] = React35.useState(
|
|
2541
2547
|
() => /* @__PURE__ */ new Set()
|
|
2542
2548
|
);
|
|
2543
|
-
|
|
2549
|
+
React35.useEffect(() => {
|
|
2544
2550
|
setExpandedGroupIds((prev) => {
|
|
2545
2551
|
if (!prev || prev.size === 0) return prev;
|
|
2546
2552
|
const validIds = new Set(
|
|
@@ -2555,7 +2561,7 @@ function Timeline({
|
|
|
2555
2561
|
return changed ? next : prev;
|
|
2556
2562
|
});
|
|
2557
2563
|
}, [groupedEntries]);
|
|
2558
|
-
const toggleGroup =
|
|
2564
|
+
const toggleGroup = React35.useCallback((groupId) => {
|
|
2559
2565
|
setExpandedGroupIds((prev) => {
|
|
2560
2566
|
const next = new Set(prev || []);
|
|
2561
2567
|
if (next.has(groupId)) next.delete(groupId);
|
|
@@ -2578,7 +2584,7 @@ function Timeline({
|
|
|
2578
2584
|
point.id === activeId ? "is-active" : "",
|
|
2579
2585
|
point.highlight ? "is-highlighted" : ""
|
|
2580
2586
|
].filter(Boolean).join(" ");
|
|
2581
|
-
const connector = /* @__PURE__ */
|
|
2587
|
+
const connector = /* @__PURE__ */ React35.createElement(
|
|
2582
2588
|
TimelineConnector,
|
|
2583
2589
|
{
|
|
2584
2590
|
side: point.side,
|
|
@@ -2586,9 +2592,9 @@ function Timeline({
|
|
|
2586
2592
|
highlight: point.highlight
|
|
2587
2593
|
}
|
|
2588
2594
|
);
|
|
2589
|
-
const body = /* @__PURE__ */
|
|
2595
|
+
const body = /* @__PURE__ */ React35.createElement("div", { className: "canopy-timeline__point-body" }, /* @__PURE__ */ React35.createElement("span", { className: "canopy-timeline__point-date" }, point.meta.label), /* @__PURE__ */ React35.createElement("span", { className: "canopy-timeline__point-title" }, point.title), point.summary ? /* @__PURE__ */ React35.createElement("span", { className: "canopy-timeline__point-summary" }, point.summary) : null);
|
|
2590
2596
|
const resourceSection = renderResourceSection(point);
|
|
2591
|
-
return /* @__PURE__ */
|
|
2597
|
+
return /* @__PURE__ */ React35.createElement(
|
|
2592
2598
|
"div",
|
|
2593
2599
|
{
|
|
2594
2600
|
key: point.id,
|
|
@@ -2596,7 +2602,7 @@ function Timeline({
|
|
|
2596
2602
|
style: wrapperStyle,
|
|
2597
2603
|
role: "listitem"
|
|
2598
2604
|
},
|
|
2599
|
-
point.side === "left" ? /* @__PURE__ */
|
|
2605
|
+
point.side === "left" ? /* @__PURE__ */ React35.createElement(React35.Fragment, null, /* @__PURE__ */ React35.createElement("div", { className: cardClasses }, body, resourceSection), connector) : /* @__PURE__ */ React35.createElement(React35.Fragment, null, connector, /* @__PURE__ */ React35.createElement("div", { className: cardClasses }, body, resourceSection))
|
|
2600
2606
|
);
|
|
2601
2607
|
}
|
|
2602
2608
|
function renderGroupEntry(entry) {
|
|
@@ -2607,7 +2613,7 @@ function Timeline({
|
|
|
2607
2613
|
const wrapperStyle = { top: `${entry.progress * 100}%` };
|
|
2608
2614
|
const isExpanded = expandedGroupIds.has(entry.id);
|
|
2609
2615
|
const hasActivePoint = entry.points.some((point) => point.id === activeId);
|
|
2610
|
-
const connector = /* @__PURE__ */
|
|
2616
|
+
const connector = /* @__PURE__ */ React35.createElement(
|
|
2611
2617
|
TimelineConnector,
|
|
2612
2618
|
{
|
|
2613
2619
|
side: entry.side,
|
|
@@ -2621,7 +2627,7 @@ function Timeline({
|
|
|
2621
2627
|
hasActivePoint ? "is-active" : ""
|
|
2622
2628
|
].filter(Boolean).join(" ");
|
|
2623
2629
|
const countLabel = `${entry.count} event${entry.count > 1 ? "s" : ""}`;
|
|
2624
|
-
const header = /* @__PURE__ */
|
|
2630
|
+
const header = /* @__PURE__ */ React35.createElement("div", { className: "canopy-timeline__group-header" }, /* @__PURE__ */ React35.createElement("div", { className: "canopy-timeline__group-summary" }, /* @__PURE__ */ React35.createElement("span", { className: "canopy-timeline__point-date" }, entry.label), /* @__PURE__ */ React35.createElement("span", { className: "canopy-timeline__group-count" }, countLabel)), /* @__PURE__ */ React35.createElement(
|
|
2625
2631
|
"button",
|
|
2626
2632
|
{
|
|
2627
2633
|
type: "button",
|
|
@@ -2631,7 +2637,7 @@ function Timeline({
|
|
|
2631
2637
|
},
|
|
2632
2638
|
isExpanded ? "Hide details" : "Show details"
|
|
2633
2639
|
));
|
|
2634
|
-
const groupPoints = isExpanded ? /* @__PURE__ */
|
|
2640
|
+
const groupPoints = isExpanded ? /* @__PURE__ */ React35.createElement("div", { className: "canopy-timeline__group-points" }, entry.points.map((point) => /* @__PURE__ */ React35.createElement(
|
|
2635
2641
|
"button",
|
|
2636
2642
|
{
|
|
2637
2643
|
key: point.id,
|
|
@@ -2642,11 +2648,11 @@ function Timeline({
|
|
|
2642
2648
|
].filter(Boolean).join(" "),
|
|
2643
2649
|
onClick: () => setActiveId(point.id)
|
|
2644
2650
|
},
|
|
2645
|
-
/* @__PURE__ */
|
|
2646
|
-
/* @__PURE__ */
|
|
2651
|
+
/* @__PURE__ */ React35.createElement("span", { className: "canopy-timeline__point-date" }, point.meta.label),
|
|
2652
|
+
/* @__PURE__ */ React35.createElement("span", { className: "canopy-timeline__group-point-title" }, point.title)
|
|
2647
2653
|
))) : null;
|
|
2648
|
-
const groupCard = /* @__PURE__ */
|
|
2649
|
-
return /* @__PURE__ */
|
|
2654
|
+
const groupCard = /* @__PURE__ */ React35.createElement("div", { className: groupClasses }, header, groupPoints);
|
|
2655
|
+
return /* @__PURE__ */ React35.createElement(
|
|
2650
2656
|
"div",
|
|
2651
2657
|
{
|
|
2652
2658
|
key: entry.id,
|
|
@@ -2654,17 +2660,17 @@ function Timeline({
|
|
|
2654
2660
|
style: wrapperStyle,
|
|
2655
2661
|
role: "listitem"
|
|
2656
2662
|
},
|
|
2657
|
-
entry.side === "left" ? /* @__PURE__ */
|
|
2663
|
+
entry.side === "left" ? /* @__PURE__ */ React35.createElement(React35.Fragment, null, groupCard, connector) : /* @__PURE__ */ React35.createElement(React35.Fragment, null, connector, groupCard)
|
|
2658
2664
|
);
|
|
2659
2665
|
}
|
|
2660
|
-
return /* @__PURE__ */
|
|
2666
|
+
return /* @__PURE__ */ React35.createElement("section", { className: containerClasses, ...rest }, title ? /* @__PURE__ */ React35.createElement("h2", { className: "canopy-timeline__title" }, title) : null, description ? /* @__PURE__ */ React35.createElement("p", { className: "canopy-timeline__description" }, description) : null, rangeLabel ? /* @__PURE__ */ React35.createElement("p", { className: "canopy-timeline__range", "aria-live": "polite" }, rangeLabel) : null, /* @__PURE__ */ React35.createElement("div", { className: "canopy-timeline__body" }, /* @__PURE__ */ React35.createElement(
|
|
2661
2667
|
"div",
|
|
2662
2668
|
{
|
|
2663
2669
|
className: "canopy-timeline__list",
|
|
2664
2670
|
role: "list",
|
|
2665
2671
|
style: { minHeight: trackHeight }
|
|
2666
2672
|
},
|
|
2667
|
-
/* @__PURE__ */
|
|
2673
|
+
/* @__PURE__ */ React35.createElement("div", { className: "canopy-timeline__spine", "aria-hidden": "true" }),
|
|
2668
2674
|
renderSteps(stepsValue, effectiveRange),
|
|
2669
2675
|
groupedEntries.map((entry) => {
|
|
2670
2676
|
if (entry.type === "group") return renderGroupEntry(entry);
|
|
@@ -2679,7 +2685,7 @@ function renderSteps(stepSize, range) {
|
|
|
2679
2685
|
const markers = [];
|
|
2680
2686
|
if (startYear < endYear) {
|
|
2681
2687
|
markers.push(
|
|
2682
|
-
/* @__PURE__ */
|
|
2688
|
+
/* @__PURE__ */ React35.createElement(
|
|
2683
2689
|
"span",
|
|
2684
2690
|
{
|
|
2685
2691
|
key: "timeline-step-start",
|
|
@@ -2687,12 +2693,12 @@ function renderSteps(stepSize, range) {
|
|
|
2687
2693
|
style: { top: "0%" },
|
|
2688
2694
|
"aria-hidden": "true"
|
|
2689
2695
|
},
|
|
2690
|
-
/* @__PURE__ */
|
|
2691
|
-
/* @__PURE__ */
|
|
2696
|
+
/* @__PURE__ */ React35.createElement("span", { className: "canopy-timeline__step-line" }),
|
|
2697
|
+
/* @__PURE__ */ React35.createElement("span", { className: "canopy-timeline__step-label" }, startYear)
|
|
2692
2698
|
)
|
|
2693
2699
|
);
|
|
2694
2700
|
markers.push(
|
|
2695
|
-
/* @__PURE__ */
|
|
2701
|
+
/* @__PURE__ */ React35.createElement(
|
|
2696
2702
|
"span",
|
|
2697
2703
|
{
|
|
2698
2704
|
key: "timeline-step-end",
|
|
@@ -2700,8 +2706,8 @@ function renderSteps(stepSize, range) {
|
|
|
2700
2706
|
style: { top: "100%" },
|
|
2701
2707
|
"aria-hidden": "true"
|
|
2702
2708
|
},
|
|
2703
|
-
/* @__PURE__ */
|
|
2704
|
-
/* @__PURE__ */
|
|
2709
|
+
/* @__PURE__ */ React35.createElement("span", { className: "canopy-timeline__step-line" }),
|
|
2710
|
+
/* @__PURE__ */ React35.createElement("span", { className: "canopy-timeline__step-label" }, endYear)
|
|
2705
2711
|
)
|
|
2706
2712
|
);
|
|
2707
2713
|
}
|
|
@@ -2711,7 +2717,7 @@ function renderSteps(stepSize, range) {
|
|
|
2711
2717
|
const progress = (timestamp - range.startDate.getTime()) / range.span;
|
|
2712
2718
|
if (progress <= 0 || progress >= 1) continue;
|
|
2713
2719
|
markers.push(
|
|
2714
|
-
/* @__PURE__ */
|
|
2720
|
+
/* @__PURE__ */ React35.createElement(
|
|
2715
2721
|
"span",
|
|
2716
2722
|
{
|
|
2717
2723
|
key: `timeline-step-${year}`,
|
|
@@ -2719,8 +2725,8 @@ function renderSteps(stepSize, range) {
|
|
|
2719
2725
|
style: { top: `calc(${progress * 100}% - 0.5px)` },
|
|
2720
2726
|
"aria-hidden": "true"
|
|
2721
2727
|
},
|
|
2722
|
-
/* @__PURE__ */
|
|
2723
|
-
/* @__PURE__ */
|
|
2728
|
+
/* @__PURE__ */ React35.createElement("span", { className: "canopy-timeline__step-line" }),
|
|
2729
|
+
/* @__PURE__ */ React35.createElement("span", { className: "canopy-timeline__step-label" }, year)
|
|
2724
2730
|
)
|
|
2725
2731
|
);
|
|
2726
2732
|
}
|
|
@@ -2734,7 +2740,7 @@ function TimelinePoint() {
|
|
|
2734
2740
|
TimelinePoint.displayName = "TimelinePoint";
|
|
2735
2741
|
|
|
2736
2742
|
// ui/src/content/map/Map.jsx
|
|
2737
|
-
import
|
|
2743
|
+
import React36 from "react";
|
|
2738
2744
|
import { createRoot } from "react-dom/client";
|
|
2739
2745
|
var DEFAULT_TILE_LAYERS = [
|
|
2740
2746
|
{
|
|
@@ -3001,7 +3007,7 @@ function MapPopupContent({ marker }) {
|
|
|
3001
3007
|
...manifest,
|
|
3002
3008
|
href: manifest.href ? withBasePath(manifest.href) : manifest.href || ""
|
|
3003
3009
|
}));
|
|
3004
|
-
return /* @__PURE__ */
|
|
3010
|
+
return /* @__PURE__ */ React36.createElement("div", { className: "canopy-map__popup" }, thumbnail ? /* @__PURE__ */ React36.createElement("div", { className: "canopy-map__popup-media" }, /* @__PURE__ */ React36.createElement(
|
|
3005
3011
|
"img",
|
|
3006
3012
|
{
|
|
3007
3013
|
src: thumbnail,
|
|
@@ -3010,19 +3016,19 @@ function MapPopupContent({ marker }) {
|
|
|
3010
3016
|
width: typeof thumbWidth === "number" && thumbWidth > 0 ? thumbWidth : void 0,
|
|
3011
3017
|
height: typeof thumbHeight === "number" && thumbHeight > 0 ? thumbHeight : void 0
|
|
3012
3018
|
}
|
|
3013
|
-
)) : null, /* @__PURE__ */
|
|
3019
|
+
)) : null, /* @__PURE__ */ React36.createElement("div", { className: "canopy-map__popup-body" }, title ? href ? /* @__PURE__ */ React36.createElement("a", { href, className: "canopy-map__popup-title" }, title) : /* @__PURE__ */ React36.createElement("span", { className: "canopy-map__popup-title" }, title) : null, summary ? /* @__PURE__ */ React36.createElement("p", { className: "canopy-map__popup-summary" }, summary) : null, marker.detailsHtml ? /* @__PURE__ */ React36.createElement(
|
|
3014
3020
|
"div",
|
|
3015
3021
|
{
|
|
3016
3022
|
className: "canopy-map__popup-details",
|
|
3017
3023
|
dangerouslySetInnerHTML: { __html: marker.detailsHtml }
|
|
3018
3024
|
}
|
|
3019
|
-
) : null, !summary && !marker.detailsHtml && href && !title ? /* @__PURE__ */
|
|
3025
|
+
) : null, !summary && !marker.detailsHtml && href && !title ? /* @__PURE__ */ React36.createElement("a", { href, className: "canopy-map__popup-link" }, "View item") : null, normalizedManifests.length ? /* @__PURE__ */ React36.createElement("div", { className: "canopy-map__popup-manifests" }, /* @__PURE__ */ React36.createElement("div", { className: "canopy-map__popup-manifests-list" }, normalizedManifests.map((manifest, index) => /* @__PURE__ */ React36.createElement(
|
|
3020
3026
|
"div",
|
|
3021
3027
|
{
|
|
3022
3028
|
key: manifest.id || manifest.href || `manifest-${index}`,
|
|
3023
3029
|
className: "canopy-map__popup-manifests-item"
|
|
3024
3030
|
},
|
|
3025
|
-
/* @__PURE__ */
|
|
3031
|
+
/* @__PURE__ */ React36.createElement(ReferencedManifestCard, { manifest })
|
|
3026
3032
|
)))) : null));
|
|
3027
3033
|
}
|
|
3028
3034
|
function renderPopup(marker) {
|
|
@@ -3034,7 +3040,7 @@ function renderPopup(marker) {
|
|
|
3034
3040
|
if (hadError) return;
|
|
3035
3041
|
try {
|
|
3036
3042
|
if (!root) root = createRoot(container);
|
|
3037
|
-
root.render(/* @__PURE__ */
|
|
3043
|
+
root.render(/* @__PURE__ */ React36.createElement(MapPopupContent, { marker }));
|
|
3038
3044
|
} catch (error) {
|
|
3039
3045
|
hadError = true;
|
|
3040
3046
|
if (root) {
|
|
@@ -3159,26 +3165,26 @@ function Map2({
|
|
|
3159
3165
|
defaultCenter = null,
|
|
3160
3166
|
defaultZoom = null
|
|
3161
3167
|
} = {}) {
|
|
3162
|
-
const containerRef =
|
|
3163
|
-
const mapRef =
|
|
3164
|
-
const layerRef =
|
|
3165
|
-
const [leafletLib, setLeafletLib] =
|
|
3166
|
-
const [leafletError, setLeafletError] =
|
|
3168
|
+
const containerRef = React36.useRef(null);
|
|
3169
|
+
const mapRef = React36.useRef(null);
|
|
3170
|
+
const layerRef = React36.useRef(null);
|
|
3171
|
+
const [leafletLib, setLeafletLib] = React36.useState(() => resolveGlobalLeaflet());
|
|
3172
|
+
const [leafletError, setLeafletError] = React36.useState(null);
|
|
3167
3173
|
const datasetInfo = navDataset && typeof navDataset === "object" ? navDataset : null;
|
|
3168
3174
|
const datasetHref = datasetInfo && datasetInfo.href || "/api/navplace.json";
|
|
3169
3175
|
const datasetVersion = datasetInfo && datasetInfo.version;
|
|
3170
3176
|
const datasetHasFeatures = !!(datasetInfo && datasetInfo.hasFeatures);
|
|
3171
|
-
const [navState, setNavState] =
|
|
3177
|
+
const [navState, setNavState] = React36.useState(() => ({
|
|
3172
3178
|
loading: false,
|
|
3173
3179
|
error: null,
|
|
3174
3180
|
markers: []
|
|
3175
3181
|
}));
|
|
3176
|
-
const [iiifTargets, setIiifTargets] =
|
|
3182
|
+
const [iiifTargets, setIiifTargets] = React36.useState(() => ({
|
|
3177
3183
|
loading: false,
|
|
3178
3184
|
error: null,
|
|
3179
3185
|
keys: []
|
|
3180
3186
|
}));
|
|
3181
|
-
|
|
3187
|
+
React36.useEffect(() => {
|
|
3182
3188
|
if (!iiifContent) {
|
|
3183
3189
|
setIiifTargets({ loading: false, error: null, keys: [] });
|
|
3184
3190
|
return;
|
|
@@ -3226,7 +3232,7 @@ function Map2({
|
|
|
3226
3232
|
const navTargets = iiifTargets.keys || [];
|
|
3227
3233
|
const navTargetsKey = navTargets.join("|");
|
|
3228
3234
|
const shouldFetchNav = datasetHasFeatures && navTargets.length > 0;
|
|
3229
|
-
|
|
3235
|
+
React36.useEffect(() => {
|
|
3230
3236
|
if (!shouldFetchNav) {
|
|
3231
3237
|
setNavState({ loading: false, error: null, markers: [] });
|
|
3232
3238
|
return void 0;
|
|
@@ -3258,7 +3264,7 @@ function Map2({
|
|
|
3258
3264
|
cancelled = true;
|
|
3259
3265
|
};
|
|
3260
3266
|
}, [datasetHref, datasetVersion, navTargetsKey, shouldFetchNav]);
|
|
3261
|
-
|
|
3267
|
+
React36.useEffect(() => {
|
|
3262
3268
|
if (leafletLib) return;
|
|
3263
3269
|
let cancelled = false;
|
|
3264
3270
|
waitForLeaflet().then((lib) => {
|
|
@@ -3270,7 +3276,7 @@ function Map2({
|
|
|
3270
3276
|
cancelled = true;
|
|
3271
3277
|
};
|
|
3272
3278
|
}, [leafletLib]);
|
|
3273
|
-
const navMatchMap =
|
|
3279
|
+
const navMatchMap = React36.useMemo(() => {
|
|
3274
3280
|
const matchMap = createMarkerMap();
|
|
3275
3281
|
(navState.markers || []).forEach((marker) => {
|
|
3276
3282
|
if (!marker || !Array.isArray(marker.matchKeys)) return;
|
|
@@ -3281,7 +3287,7 @@ function Map2({
|
|
|
3281
3287
|
});
|
|
3282
3288
|
return matchMap;
|
|
3283
3289
|
}, [navState.markers]);
|
|
3284
|
-
const normalizedCustom =
|
|
3290
|
+
const normalizedCustom = React36.useMemo(() => {
|
|
3285
3291
|
return normalizeCustomMarkers(customPoints).map((point) => {
|
|
3286
3292
|
if (!point || point.thumbnail || !point.href) return point;
|
|
3287
3293
|
const match = navMatchMap.get(normalizeKey(point.href));
|
|
@@ -3296,11 +3302,11 @@ function Map2({
|
|
|
3296
3302
|
};
|
|
3297
3303
|
});
|
|
3298
3304
|
}, [customPoints, navMatchMap]);
|
|
3299
|
-
const allMarkers =
|
|
3305
|
+
const allMarkers = React36.useMemo(() => {
|
|
3300
3306
|
return [...navState.markers || [], ...normalizedCustom];
|
|
3301
3307
|
}, [navState.markers, normalizedCustom]);
|
|
3302
|
-
const clusterOptions =
|
|
3303
|
-
|
|
3308
|
+
const clusterOptions = React36.useMemo(() => buildClusterOptions(leafletLib), [leafletLib]);
|
|
3309
|
+
React36.useEffect(() => {
|
|
3304
3310
|
if (!containerRef.current || mapRef.current || !leafletLib) return void 0;
|
|
3305
3311
|
const map = leafletLib.map(containerRef.current, {
|
|
3306
3312
|
zoomControl: true,
|
|
@@ -3338,7 +3344,7 @@ function Map2({
|
|
|
3338
3344
|
layerRef.current = null;
|
|
3339
3345
|
};
|
|
3340
3346
|
}, [tileLayers, scrollWheelZoom, cluster, clusterOptions, leafletLib]);
|
|
3341
|
-
|
|
3347
|
+
React36.useEffect(() => {
|
|
3342
3348
|
const map = mapRef.current;
|
|
3343
3349
|
const layer = layerRef.current;
|
|
3344
3350
|
if (!map || !layer || !leafletLib) return;
|
|
@@ -3442,14 +3448,14 @@ function Map2({
|
|
|
3442
3448
|
].filter(Boolean).join(" ");
|
|
3443
3449
|
const statusLabel = leafletError ? leafletError.message || "Failed to load map library" : !leafletLib ? "Loading map\u2026" : iiifTargets.error ? iiifTargets.error : datasetUnavailable ? "Map data is unavailable for this site." : navState.error ? navState.error : isLoadingMarkers ? "Loading map data\u2026" : !iiifContent && !hasCustomPoints ? "Add iiifContent or MapPoint markers to populate this map." : !hasMarkers ? "No map locations available." : "";
|
|
3444
3450
|
const showStatus = Boolean(statusLabel);
|
|
3445
|
-
return /* @__PURE__ */
|
|
3451
|
+
return /* @__PURE__ */ React36.createElement("div", { className: rootClass, id: id || void 0, style: style || void 0 }, /* @__PURE__ */ React36.createElement(
|
|
3446
3452
|
"div",
|
|
3447
3453
|
{
|
|
3448
3454
|
ref: containerRef,
|
|
3449
3455
|
className: "canopy-map__canvas",
|
|
3450
3456
|
style: { height: height || "600px" }
|
|
3451
3457
|
}
|
|
3452
|
-
), showStatus ? /* @__PURE__ */
|
|
3458
|
+
), showStatus ? /* @__PURE__ */ React36.createElement("div", { className: "canopy-map__status", "aria-live": "polite" }, statusLabel) : null);
|
|
3453
3459
|
}
|
|
3454
3460
|
|
|
3455
3461
|
// ui/src/content/map/MapPoint.jsx
|
|
@@ -3473,6 +3479,7 @@ export {
|
|
|
3473
3479
|
Grid,
|
|
3474
3480
|
GridItem,
|
|
3475
3481
|
HelloWorld,
|
|
3482
|
+
Id,
|
|
3476
3483
|
Image,
|
|
3477
3484
|
Map2 as Map,
|
|
3478
3485
|
MapPoint,
|