@canopy-iiif/app 0.13.4 → 1.0.0

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/ui/dist/index.mjs CHANGED
@@ -1594,12 +1594,34 @@ function MdxSearchTabs(props) {
1594
1594
  return /* @__PURE__ */ React24.createElement("div", { "data-canopy-search-tabs": "1" }, /* @__PURE__ */ React24.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: json } }));
1595
1595
  }
1596
1596
 
1597
- // ui/src/search/SearchResults.jsx
1597
+ // ui/src/search/MdxSearch.jsx
1598
1598
  import React25 from "react";
1599
+ function MdxSearch(props = {}) {
1600
+ const {
1601
+ layout,
1602
+ tabsProps = {},
1603
+ summaryProps = {},
1604
+ resultsProps = {},
1605
+ className = "",
1606
+ showTabs = true,
1607
+ showSummary = true,
1608
+ showResults = true,
1609
+ children
1610
+ } = props || {};
1611
+ const resultsPayload = resultsProps && typeof resultsProps === "object" ? { ...resultsProps } : {};
1612
+ if (typeof layout !== "undefined" && layout !== null && !resultsPayload.layout) {
1613
+ resultsPayload.layout = layout;
1614
+ }
1615
+ const classes = ["canopy-search", className].filter(Boolean).join(" ");
1616
+ return /* @__PURE__ */ React25.createElement("section", { className: classes, "data-canopy-search": "1" }, showTabs ? /* @__PURE__ */ React25.createElement(MdxSearchTabs, { ...tabsProps }) : null, showSummary ? /* @__PURE__ */ React25.createElement(SearchSummary, { ...summaryProps }) : null, showResults ? /* @__PURE__ */ React25.createElement(MdxSearchResults, { ...resultsPayload }) : null, children || null);
1617
+ }
1618
+
1619
+ // ui/src/search/SearchResults.jsx
1620
+ import React26 from "react";
1599
1621
  function DefaultArticleTemplate({ record, query }) {
1600
1622
  if (!record) return null;
1601
1623
  const metadata = Array.isArray(record.metadata) ? record.metadata : [];
1602
- return /* @__PURE__ */ React25.createElement(
1624
+ return /* @__PURE__ */ React26.createElement(
1603
1625
  ArticleCard,
1604
1626
  {
1605
1627
  href: record.href,
@@ -1617,7 +1639,7 @@ function DefaultFigureTemplate({ record, thumbnailAspectRatio }) {
1617
1639
  if (!record) return null;
1618
1640
  const hasDims = Number.isFinite(Number(record.thumbnailWidth)) && Number(record.thumbnailWidth) > 0 && Number.isFinite(Number(record.thumbnailHeight)) && Number(record.thumbnailHeight) > 0;
1619
1641
  const aspect = Number.isFinite(Number(thumbnailAspectRatio)) && Number(thumbnailAspectRatio) > 0 ? Number(thumbnailAspectRatio) : hasDims ? Number(record.thumbnailWidth) / Number(record.thumbnailHeight) : void 0;
1620
- return /* @__PURE__ */ React25.createElement(
1642
+ return /* @__PURE__ */ React26.createElement(
1621
1643
  Card,
1622
1644
  {
1623
1645
  href: record.href,
@@ -1638,7 +1660,7 @@ function SearchResults({
1638
1660
  variant = "auto"
1639
1661
  }) {
1640
1662
  if (!results.length) {
1641
- return /* @__PURE__ */ React25.createElement("div", { className: "text-slate-600" }, /* @__PURE__ */ React25.createElement("em", null, "No results"));
1663
+ return /* @__PURE__ */ React26.createElement("div", { className: "text-slate-600" }, /* @__PURE__ */ React26.createElement("em", null, "No results"));
1642
1664
  }
1643
1665
  const normalizedType = String(type || "all").toLowerCase();
1644
1666
  const normalizedVariant = variant === "figure" || variant === "article" ? variant : "auto";
@@ -1646,9 +1668,9 @@ function SearchResults({
1646
1668
  const FigureTemplate = templates && templates.figure ? templates.figure : DefaultFigureTemplate;
1647
1669
  const ArticleTemplate = templates && templates.article ? templates.article : DefaultArticleTemplate;
1648
1670
  if (isAnnotationView) {
1649
- return /* @__PURE__ */ React25.createElement("div", { id: "search-results", className: "space-y-4" }, results.map((r, i) => {
1671
+ return /* @__PURE__ */ React26.createElement("div", { id: "search-results", className: "space-y-4" }, results.map((r, i) => {
1650
1672
  if (!r) return null;
1651
- return /* @__PURE__ */ React25.createElement(
1673
+ return /* @__PURE__ */ React26.createElement(
1652
1674
  ArticleTemplate,
1653
1675
  {
1654
1676
  key: r.id || i,
@@ -1666,20 +1688,20 @@ function SearchResults({
1666
1688
  return !isWorkRecord(record) || normalizedType !== "work";
1667
1689
  };
1668
1690
  if (layout === "list") {
1669
- return /* @__PURE__ */ React25.createElement("div", { id: "search-results", className: "space-y-6" }, results.map((r, i) => {
1691
+ return /* @__PURE__ */ React26.createElement("div", { id: "search-results", className: "space-y-6" }, results.map((r, i) => {
1670
1692
  if (shouldRenderAsArticle(r)) {
1671
- return /* @__PURE__ */ React25.createElement("div", { key: i, className: `search-result ${r && r.type}` }, /* @__PURE__ */ React25.createElement(ArticleTemplate, { record: r, query, layout }));
1693
+ return /* @__PURE__ */ React26.createElement("div", { key: i, className: `search-result ${r && r.type}` }, /* @__PURE__ */ React26.createElement(ArticleTemplate, { record: r, query, layout }));
1672
1694
  }
1673
1695
  const hasDims = Number.isFinite(Number(r.thumbnailWidth)) && Number(r.thumbnailWidth) > 0 && Number.isFinite(Number(r.thumbnailHeight)) && Number(r.thumbnailHeight) > 0;
1674
1696
  const aspect = hasDims ? Number(r.thumbnailWidth) / Number(r.thumbnailHeight) : void 0;
1675
- return /* @__PURE__ */ React25.createElement(
1697
+ return /* @__PURE__ */ React26.createElement(
1676
1698
  "div",
1677
1699
  {
1678
1700
  key: i,
1679
1701
  className: `search-result ${r.type}`,
1680
1702
  "data-thumbnail-aspect-ratio": aspect
1681
1703
  },
1682
- /* @__PURE__ */ React25.createElement(
1704
+ /* @__PURE__ */ React26.createElement(
1683
1705
  FigureTemplate,
1684
1706
  {
1685
1707
  record: r,
@@ -1691,20 +1713,20 @@ function SearchResults({
1691
1713
  );
1692
1714
  }));
1693
1715
  }
1694
- return /* @__PURE__ */ React25.createElement("div", { id: "search-results" }, /* @__PURE__ */ React25.createElement(Grid, null, results.map((r, i) => {
1716
+ return /* @__PURE__ */ React26.createElement("div", { id: "search-results" }, /* @__PURE__ */ React26.createElement(Grid, null, results.map((r, i) => {
1695
1717
  if (shouldRenderAsArticle(r)) {
1696
- return /* @__PURE__ */ React25.createElement(GridItem, { key: i, className: `search-result ${r && r.type}` }, /* @__PURE__ */ React25.createElement(ArticleTemplate, { record: r, query, layout }));
1718
+ return /* @__PURE__ */ React26.createElement(GridItem, { key: i, className: `search-result ${r && r.type}` }, /* @__PURE__ */ React26.createElement(ArticleTemplate, { record: r, query, layout }));
1697
1719
  }
1698
1720
  const hasDims = Number.isFinite(Number(r.thumbnailWidth)) && Number(r.thumbnailWidth) > 0 && Number.isFinite(Number(r.thumbnailHeight)) && Number(r.thumbnailHeight) > 0;
1699
1721
  const aspect = hasDims ? Number(r.thumbnailWidth) / Number(r.thumbnailHeight) : void 0;
1700
- return /* @__PURE__ */ React25.createElement(
1722
+ return /* @__PURE__ */ React26.createElement(
1701
1723
  GridItem,
1702
1724
  {
1703
1725
  key: i,
1704
1726
  className: `search-result ${r.type}`,
1705
1727
  "data-thumbnail-aspect-ratio": aspect
1706
1728
  },
1707
- /* @__PURE__ */ React25.createElement(
1729
+ /* @__PURE__ */ React26.createElement(
1708
1730
  FigureTemplate,
1709
1731
  {
1710
1732
  record: r,
@@ -1718,7 +1740,7 @@ function SearchResults({
1718
1740
  }
1719
1741
 
1720
1742
  // ui/src/search/SearchTabs.jsx
1721
- import React26, { useRef as useRef2, useState as useState6, useEffect as useEffect6 } from "react";
1743
+ import React27, { useRef as useRef2, useState as useState6, useEffect as useEffect6 } from "react";
1722
1744
  function SearchTabs({
1723
1745
  type = "all",
1724
1746
  onTypeChange,
@@ -1772,7 +1794,7 @@ function SearchTabs({
1772
1794
  width: `${itemBoundingBox.width}px`
1773
1795
  };
1774
1796
  }
1775
- return /* @__PURE__ */ React26.createElement("div", { className: "canopy-search-tabs-wrapper" }, /* @__PURE__ */ React26.createElement(
1797
+ return /* @__PURE__ */ React27.createElement("div", { className: "canopy-search-tabs-wrapper" }, /* @__PURE__ */ React27.createElement(
1776
1798
  "div",
1777
1799
  {
1778
1800
  role: "tablist",
@@ -1781,7 +1803,7 @@ function SearchTabs({
1781
1803
  ref: wrapperRef,
1782
1804
  onMouseLeave: resetHighlight
1783
1805
  },
1784
- /* @__PURE__ */ React26.createElement(
1806
+ /* @__PURE__ */ React27.createElement(
1785
1807
  "div",
1786
1808
  {
1787
1809
  ref: highlightRef,
@@ -1793,7 +1815,7 @@ function SearchTabs({
1793
1815
  const active = String(type).toLowerCase() === String(t).toLowerCase();
1794
1816
  const cRaw = counts && Object.prototype.hasOwnProperty.call(counts, t) ? counts[t] : void 0;
1795
1817
  const c = Number.isFinite(Number(cRaw)) ? Number(cRaw) : 0;
1796
- return /* @__PURE__ */ React26.createElement(
1818
+ return /* @__PURE__ */ React27.createElement(
1797
1819
  "button",
1798
1820
  {
1799
1821
  key: t,
@@ -1811,7 +1833,7 @@ function SearchTabs({
1811
1833
  ")"
1812
1834
  );
1813
1835
  })
1814
- ), hasFilters ? /* @__PURE__ */ React26.createElement(
1836
+ ), hasFilters ? /* @__PURE__ */ React27.createElement(
1815
1837
  "button",
1816
1838
  {
1817
1839
  type: "button",
@@ -1819,12 +1841,12 @@ function SearchTabs({
1819
1841
  "aria-expanded": filtersOpen ? "true" : "false",
1820
1842
  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"
1821
1843
  },
1822
- /* @__PURE__ */ React26.createElement("span", null, filtersLabel, filterBadge)
1844
+ /* @__PURE__ */ React27.createElement("span", null, filtersLabel, filterBadge)
1823
1845
  ) : null);
1824
1846
  }
1825
1847
 
1826
1848
  // ui/src/search/SearchFiltersDialog.jsx
1827
- import React27 from "react";
1849
+ import React28 from "react";
1828
1850
  function toArray(input) {
1829
1851
  if (!input) return [];
1830
1852
  if (Array.isArray(input)) return input;
@@ -1863,20 +1885,20 @@ function FacetSection({ facet, selected, onToggle }) {
1863
1885
  const selectedValues = selected.get(String(slug)) || /* @__PURE__ */ new Set();
1864
1886
  const checkboxId = (valueSlug) => `filter-${slug}-${valueSlug}`;
1865
1887
  const hasSelection = selectedValues.size > 0;
1866
- const [quickQuery, setQuickQuery] = React27.useState("");
1888
+ const [quickQuery, setQuickQuery] = React28.useState("");
1867
1889
  const hasQuery = quickQuery.trim().length > 0;
1868
- const filteredValues = React27.useMemo(
1890
+ const filteredValues = React28.useMemo(
1869
1891
  () => facetMatches(values, quickQuery),
1870
1892
  [values, quickQuery]
1871
1893
  );
1872
- return /* @__PURE__ */ React27.createElement(
1894
+ return /* @__PURE__ */ React28.createElement(
1873
1895
  "details",
1874
1896
  {
1875
1897
  className: "canopy-search-filters__facet",
1876
1898
  open: hasSelection
1877
1899
  },
1878
- /* @__PURE__ */ React27.createElement("summary", { className: "canopy-search-filters__facet-summary" }, /* @__PURE__ */ React27.createElement("span", null, label), /* @__PURE__ */ React27.createElement("span", { className: "canopy-search-filters__facet-count" }, values.length)),
1879
- /* @__PURE__ */ React27.createElement("div", { className: "canopy-search-filters__facet-content" }, /* @__PURE__ */ React27.createElement("div", { className: "canopy-search-filters__quick" }, /* @__PURE__ */ React27.createElement(
1900
+ /* @__PURE__ */ React28.createElement("summary", { className: "canopy-search-filters__facet-summary" }, /* @__PURE__ */ React28.createElement("span", null, label), /* @__PURE__ */ React28.createElement("span", { className: "canopy-search-filters__facet-count" }, values.length)),
1901
+ /* @__PURE__ */ React28.createElement("div", { className: "canopy-search-filters__facet-content" }, /* @__PURE__ */ React28.createElement("div", { className: "canopy-search-filters__quick" }, /* @__PURE__ */ React28.createElement(
1880
1902
  "input",
1881
1903
  {
1882
1904
  type: "search",
@@ -1886,7 +1908,7 @@ function FacetSection({ facet, selected, onToggle }) {
1886
1908
  className: "canopy-search-filters__quick-input",
1887
1909
  "aria-label": `Filter ${label} values`
1888
1910
  }
1889
- ), quickQuery ? /* @__PURE__ */ React27.createElement(
1911
+ ), quickQuery ? /* @__PURE__ */ React28.createElement(
1890
1912
  "button",
1891
1913
  {
1892
1914
  type: "button",
@@ -1894,11 +1916,11 @@ function FacetSection({ facet, selected, onToggle }) {
1894
1916
  className: "canopy-search-filters__quick-clear"
1895
1917
  },
1896
1918
  "Clear"
1897
- ) : null), hasQuery && !filteredValues.length ? /* @__PURE__ */ React27.createElement("p", { className: "canopy-search-filters__facet-notice" }, "No matches found.") : null, /* @__PURE__ */ React27.createElement("ul", { className: "canopy-search-filters__facet-list" }, filteredValues.map((entry) => {
1919
+ ) : null), hasQuery && !filteredValues.length ? /* @__PURE__ */ React28.createElement("p", { className: "canopy-search-filters__facet-notice" }, "No matches found.") : null, /* @__PURE__ */ React28.createElement("ul", { className: "canopy-search-filters__facet-list" }, filteredValues.map((entry) => {
1898
1920
  const valueSlug = String(entry.slug || entry.value || "");
1899
1921
  const isChecked = selectedValues.has(valueSlug);
1900
1922
  const inputId = checkboxId(valueSlug);
1901
- return /* @__PURE__ */ React27.createElement("li", { key: valueSlug, className: "canopy-search-filters__facet-item" }, /* @__PURE__ */ React27.createElement(
1923
+ return /* @__PURE__ */ React28.createElement("li", { key: valueSlug, className: "canopy-search-filters__facet-item" }, /* @__PURE__ */ React28.createElement(
1902
1924
  "input",
1903
1925
  {
1904
1926
  id: inputId,
@@ -1910,15 +1932,15 @@ function FacetSection({ facet, selected, onToggle }) {
1910
1932
  if (onToggle) onToggle(slug, valueSlug, nextChecked);
1911
1933
  }
1912
1934
  }
1913
- ), /* @__PURE__ */ React27.createElement(
1935
+ ), /* @__PURE__ */ React28.createElement(
1914
1936
  "label",
1915
1937
  {
1916
1938
  htmlFor: inputId,
1917
1939
  className: "canopy-search-filters__facet-label"
1918
1940
  },
1919
- /* @__PURE__ */ React27.createElement("span", null, entry.value, " ", Number.isFinite(entry.doc_count) ? /* @__PURE__ */ React27.createElement("span", { className: "canopy-search-filters__facet-count" }, "(", entry.doc_count, ")") : null)
1941
+ /* @__PURE__ */ React28.createElement("span", null, entry.value, " ", Number.isFinite(entry.doc_count) ? /* @__PURE__ */ React28.createElement("span", { className: "canopy-search-filters__facet-count" }, "(", entry.doc_count, ")") : null)
1920
1942
  ));
1921
- }), !filteredValues.length && !hasQuery ? /* @__PURE__ */ React27.createElement("li", { className: "canopy-search-filters__facet-empty" }, "No values available.") : null))
1943
+ }), !filteredValues.length && !hasQuery ? /* @__PURE__ */ React28.createElement("li", { className: "canopy-search-filters__facet-empty" }, "No values available.") : null))
1922
1944
  );
1923
1945
  }
1924
1946
  function SearchFiltersDialog(props = {}) {
@@ -1940,7 +1962,7 @@ function SearchFiltersDialog(props = {}) {
1940
1962
  (total, set) => total + set.size,
1941
1963
  0
1942
1964
  );
1943
- React27.useEffect(() => {
1965
+ React28.useEffect(() => {
1944
1966
  if (!open) return void 0;
1945
1967
  if (typeof document === "undefined") return void 0;
1946
1968
  const body = document.body;
@@ -1957,7 +1979,7 @@ function SearchFiltersDialog(props = {}) {
1957
1979
  if (!open) return null;
1958
1980
  const brandId = "canopy-modal-filters-label";
1959
1981
  const subtitleText = subtitle != null ? subtitle : title;
1960
- return /* @__PURE__ */ React27.createElement(
1982
+ return /* @__PURE__ */ React28.createElement(
1961
1983
  CanopyModal,
1962
1984
  {
1963
1985
  id: "canopy-modal-filters",
@@ -1972,8 +1994,8 @@ function SearchFiltersDialog(props = {}) {
1972
1994
  onBackgroundClick: () => onOpenChange && onOpenChange(false),
1973
1995
  bodyClassName: "canopy-modal__body--filters"
1974
1996
  },
1975
- subtitleText ? /* @__PURE__ */ React27.createElement("p", { className: "canopy-search-filters__subtitle" }, subtitleText) : null,
1976
- /* @__PURE__ */ React27.createElement("div", { className: "canopy-search-filters__body" }, Array.isArray(facets) && facets.length ? /* @__PURE__ */ React27.createElement("div", { className: "canopy-search-filters__facets" }, facets.map((facet) => /* @__PURE__ */ React27.createElement(
1997
+ subtitleText ? /* @__PURE__ */ React28.createElement("p", { className: "canopy-search-filters__subtitle" }, subtitleText) : null,
1998
+ /* @__PURE__ */ React28.createElement("div", { className: "canopy-search-filters__body" }, Array.isArray(facets) && facets.length ? /* @__PURE__ */ React28.createElement("div", { className: "canopy-search-filters__facets" }, facets.map((facet) => /* @__PURE__ */ React28.createElement(
1977
1999
  FacetSection,
1978
2000
  {
1979
2001
  key: facet.slug || facet.label,
@@ -1981,8 +2003,8 @@ function SearchFiltersDialog(props = {}) {
1981
2003
  selected: selectedMap,
1982
2004
  onToggle
1983
2005
  }
1984
- ))) : /* @__PURE__ */ React27.createElement("p", { className: "canopy-search-filters__empty" }, "No filters are available for this collection.")),
1985
- /* @__PURE__ */ React27.createElement("footer", { className: "canopy-search-filters__footer" }, /* @__PURE__ */ React27.createElement("div", null, activeCount ? `${activeCount} filter${activeCount === 1 ? "" : "s"} applied` : "No filters applied"), /* @__PURE__ */ React27.createElement("div", { className: "canopy-search-filters__footer-actions" }, /* @__PURE__ */ React27.createElement(
2006
+ ))) : /* @__PURE__ */ React28.createElement("p", { className: "canopy-search-filters__empty" }, "No filters are available for this collection.")),
2007
+ /* @__PURE__ */ React28.createElement("footer", { className: "canopy-search-filters__footer" }, /* @__PURE__ */ React28.createElement("div", null, activeCount ? `${activeCount} filter${activeCount === 1 ? "" : "s"} applied` : "No filters applied"), /* @__PURE__ */ React28.createElement("div", { className: "canopy-search-filters__footer-actions" }, /* @__PURE__ */ React28.createElement(
1986
2008
  "button",
1987
2009
  {
1988
2010
  type: "button",
@@ -1993,7 +2015,7 @@ function SearchFiltersDialog(props = {}) {
1993
2015
  className: "canopy-search-filters__button canopy-search-filters__button--secondary"
1994
2016
  },
1995
2017
  "Clear all"
1996
- ), /* @__PURE__ */ React27.createElement(
2018
+ ), /* @__PURE__ */ React28.createElement(
1997
2019
  "button",
1998
2020
  {
1999
2021
  type: "button",
@@ -2006,7 +2028,7 @@ function SearchFiltersDialog(props = {}) {
2006
2028
  }
2007
2029
 
2008
2030
  // ui/src/search-form/MdxSearchFormModal.jsx
2009
- import React28 from "react";
2031
+ import React29 from "react";
2010
2032
  function MdxSearchFormModal(props = {}) {
2011
2033
  const {
2012
2034
  placeholder = "Search\u2026",
@@ -2022,24 +2044,24 @@ function MdxSearchFormModal(props = {}) {
2022
2044
  const text = typeof label === "string" && label.trim() ? label.trim() : buttonLabel;
2023
2045
  const resolvedSearchPath = resolveSearchPath(searchPath);
2024
2046
  const data = { placeholder, hotkey, maxResults, groupOrder, label: text, searchPath: resolvedSearchPath };
2025
- 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) } }));
2047
+ return /* @__PURE__ */ React29.createElement("div", { "data-canopy-search-form": true, className: "flex-1 min-w-0" }, /* @__PURE__ */ React29.createElement("div", { className: "relative w-full" }, /* @__PURE__ */ React29.createElement(SearchPanelForm, { placeholder, buttonLabel, label, searchPath: resolvedSearchPath }), /* @__PURE__ */ React29.createElement(SearchPanelTeaserResults, null)), /* @__PURE__ */ React29.createElement("script", { type: "application/json", dangerouslySetInnerHTML: { __html: JSON.stringify(data) } }));
2026
2048
  }
2027
2049
 
2028
2050
  // ui/src/docs/MarkdownTable.jsx
2029
- import React29 from "react";
2051
+ import React30 from "react";
2030
2052
  function MarkdownTable({ className = "", ...rest }) {
2031
2053
  const merged = ["markdown-table", className].filter(Boolean).join(" ");
2032
- return /* @__PURE__ */ React29.createElement("div", { className: "markdown-table__frame" }, /* @__PURE__ */ React29.createElement("table", { className: merged, ...rest }));
2054
+ return /* @__PURE__ */ React30.createElement("div", { className: "markdown-table__frame" }, /* @__PURE__ */ React30.createElement("table", { className: merged, ...rest }));
2033
2055
  }
2034
2056
 
2035
2057
  // ui/src/docs/Diagram.jsx
2036
- import React30 from "react";
2058
+ import React31 from "react";
2037
2059
  function CanopyDiagram() {
2038
- return /* @__PURE__ */ React30.createElement("div", { className: "canopy-diagram" }, /* @__PURE__ */ React30.createElement("section", { className: "canopy-diagram__section canopy-diagram__section--collections" }, /* @__PURE__ */ React30.createElement("h3", null, "IIIF Collection(s)"), /* @__PURE__ */ React30.createElement("span", { className: "canopy-diagram__section-summary" }, "Source collections contribute 105 total manifests that Canopy retrieves as-is via IIIF endpoints."), /* @__PURE__ */ React30.createElement("div", { className: "canopy-diagram__grid" }, /* @__PURE__ */ React30.createElement("article", null, /* @__PURE__ */ React30.createElement("h4", null, "Collection A"), /* @__PURE__ */ React30.createElement("ul", null, /* @__PURE__ */ React30.createElement("li", null, "70 Manifests"), /* @__PURE__ */ React30.createElement("li", null, "IIIF Images + A/V"), /* @__PURE__ */ React30.createElement("li", null, "Textual Annotations"))), /* @__PURE__ */ React30.createElement("article", null, /* @__PURE__ */ React30.createElement("h4", null, "Collection B"), /* @__PURE__ */ React30.createElement("ul", null, /* @__PURE__ */ React30.createElement("li", null, "35 Manifests"), /* @__PURE__ */ React30.createElement("li", null, "IIIF Images + A/V"), /* @__PURE__ */ React30.createElement("li", null, "Textual Annotations"))))), /* @__PURE__ */ React30.createElement("div", { className: "canopy-diagram__arrow", "aria-hidden": "true" }, /* @__PURE__ */ React30.createElement("span", { className: "canopy-diagram__arrow-line" }), /* @__PURE__ */ React30.createElement("span", { className: "canopy-diagram__arrow-head" })), /* @__PURE__ */ React30.createElement("section", { className: "canopy-diagram__section canopy-diagram__section--build" }, /* @__PURE__ */ React30.createElement("h3", null, "Canopy Build Process"), /* @__PURE__ */ React30.createElement("span", { className: "canopy-diagram__section-summary" }, "Canopy syncs manifests, page content, and annotations before bundling the site."), /* @__PURE__ */ React30.createElement("div", { className: "canopy-diagram__grid" }, /* @__PURE__ */ React30.createElement("article", null, /* @__PURE__ */ React30.createElement("h4", null, "Automated content"), /* @__PURE__ */ React30.createElement("ul", null, /* @__PURE__ */ React30.createElement("li", null, "105 manifests \u2192 105 work pages"), /* @__PURE__ */ React30.createElement("li", null, "One page per manifest"), /* @__PURE__ */ React30.createElement("li", null, "Customize page layout"))), /* @__PURE__ */ React30.createElement("article", null, /* @__PURE__ */ React30.createElement("h4", null, "Contextual content"), /* @__PURE__ */ React30.createElement("ul", null, /* @__PURE__ */ React30.createElement("li", null, "Markdown & MDX pages"), /* @__PURE__ */ React30.createElement("li", null, "Author narratives & tours"), /* @__PURE__ */ React30.createElement("li", null, "Reference manifests inline"))), /* @__PURE__ */ React30.createElement("article", null, /* @__PURE__ */ React30.createElement("h4", null, "Search index"), /* @__PURE__ */ React30.createElement("ul", null, /* @__PURE__ */ React30.createElement("li", null, "Combines works + pages"), /* @__PURE__ */ React30.createElement("li", null, "Customize result layout"), /* @__PURE__ */ React30.createElement("li", null, "Optional annotations"))))), /* @__PURE__ */ React30.createElement("div", { className: "canopy-diagram__arrow", "aria-hidden": "true" }, /* @__PURE__ */ React30.createElement("span", { className: "canopy-diagram__arrow-line" }), /* @__PURE__ */ React30.createElement("span", { className: "canopy-diagram__arrow-head" })), /* @__PURE__ */ React30.createElement("section", { className: "canopy-diagram__section canopy-diagram__section--output" }, /* @__PURE__ */ React30.createElement("h3", null, "Static Digital Project"), /* @__PURE__ */ React30.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__ */ React30.createElement("div", { className: "canopy-diagram__grid" }, /* @__PURE__ */ React30.createElement("article", null, /* @__PURE__ */ React30.createElement("h4", null, "Work pages"), /* @__PURE__ */ React30.createElement("ul", null, /* @__PURE__ */ React30.createElement("li", null, "105 generated HTML pages"), /* @__PURE__ */ React30.createElement("li", null, "Each links back to source manifests"), /* @__PURE__ */ React30.createElement("li", null, "Styled with Canopy components"))), /* @__PURE__ */ React30.createElement("article", null, /* @__PURE__ */ React30.createElement("h4", null, "Custom pages"), /* @__PURE__ */ React30.createElement("ul", null, /* @__PURE__ */ React30.createElement("li", null, "Markdown & MDX-authored content"), /* @__PURE__ */ React30.createElement("li", null, "Reusable layouts for narratives"), /* @__PURE__ */ React30.createElement("li", null, "Embed IIIF media & interstitials"))), /* @__PURE__ */ React30.createElement("article", null, /* @__PURE__ */ React30.createElement("h4", null, "Search bundle"), /* @__PURE__ */ React30.createElement("ul", null, /* @__PURE__ */ React30.createElement("li", null, "Static FlexSearch index"), /* @__PURE__ */ React30.createElement("li", null, "Works + pages share records"), /* @__PURE__ */ React30.createElement("li", null, "Optional annotation dataset"))))));
2060
+ return /* @__PURE__ */ React31.createElement("div", { className: "canopy-diagram" }, /* @__PURE__ */ React31.createElement("section", { className: "canopy-diagram__section canopy-diagram__section--collections" }, /* @__PURE__ */ React31.createElement("h3", null, "IIIF Collection(s)"), /* @__PURE__ */ React31.createElement("span", { className: "canopy-diagram__section-summary" }, "Source collections contribute 105 total manifests that Canopy retrieves as-is via IIIF endpoints."), /* @__PURE__ */ React31.createElement("div", { className: "canopy-diagram__grid" }, /* @__PURE__ */ React31.createElement("article", null, /* @__PURE__ */ React31.createElement("h4", null, "Collection A"), /* @__PURE__ */ React31.createElement("ul", null, /* @__PURE__ */ React31.createElement("li", null, "70 Manifests"), /* @__PURE__ */ React31.createElement("li", null, "IIIF Images + A/V"), /* @__PURE__ */ React31.createElement("li", null, "Textual Annotations"))), /* @__PURE__ */ React31.createElement("article", null, /* @__PURE__ */ React31.createElement("h4", null, "Collection B"), /* @__PURE__ */ React31.createElement("ul", null, /* @__PURE__ */ React31.createElement("li", null, "35 Manifests"), /* @__PURE__ */ React31.createElement("li", null, "IIIF Images + A/V"), /* @__PURE__ */ React31.createElement("li", null, "Textual Annotations"))))), /* @__PURE__ */ React31.createElement("div", { className: "canopy-diagram__arrow", "aria-hidden": "true" }, /* @__PURE__ */ React31.createElement("span", { className: "canopy-diagram__arrow-line" }), /* @__PURE__ */ React31.createElement("span", { className: "canopy-diagram__arrow-head" })), /* @__PURE__ */ React31.createElement("section", { className: "canopy-diagram__section canopy-diagram__section--build" }, /* @__PURE__ */ React31.createElement("h3", null, "Canopy Build Process"), /* @__PURE__ */ React31.createElement("span", { className: "canopy-diagram__section-summary" }, "Canopy syncs manifests, page content, and annotations before bundling the site."), /* @__PURE__ */ React31.createElement("div", { className: "canopy-diagram__grid" }, /* @__PURE__ */ React31.createElement("article", null, /* @__PURE__ */ React31.createElement("h4", null, "Automated content"), /* @__PURE__ */ React31.createElement("ul", null, /* @__PURE__ */ React31.createElement("li", null, "105 manifests \u2192 105 work pages"), /* @__PURE__ */ React31.createElement("li", null, "One page per manifest"), /* @__PURE__ */ React31.createElement("li", null, "Customize page layout"))), /* @__PURE__ */ React31.createElement("article", null, /* @__PURE__ */ React31.createElement("h4", null, "Contextual content"), /* @__PURE__ */ React31.createElement("ul", null, /* @__PURE__ */ React31.createElement("li", null, "Markdown & MDX pages"), /* @__PURE__ */ React31.createElement("li", null, "Author narratives & tours"), /* @__PURE__ */ React31.createElement("li", null, "Reference manifests inline"))), /* @__PURE__ */ React31.createElement("article", null, /* @__PURE__ */ React31.createElement("h4", null, "Search index"), /* @__PURE__ */ React31.createElement("ul", null, /* @__PURE__ */ React31.createElement("li", null, "Combines works + pages"), /* @__PURE__ */ React31.createElement("li", null, "Customize result layout"), /* @__PURE__ */ React31.createElement("li", null, "Optional annotations"))))), /* @__PURE__ */ React31.createElement("div", { className: "canopy-diagram__arrow", "aria-hidden": "true" }, /* @__PURE__ */ React31.createElement("span", { className: "canopy-diagram__arrow-line" }), /* @__PURE__ */ React31.createElement("span", { className: "canopy-diagram__arrow-head" })), /* @__PURE__ */ React31.createElement("section", { className: "canopy-diagram__section canopy-diagram__section--output" }, /* @__PURE__ */ React31.createElement("h3", null, "Static Digital Project"), /* @__PURE__ */ React31.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__ */ React31.createElement("div", { className: "canopy-diagram__grid" }, /* @__PURE__ */ React31.createElement("article", null, /* @__PURE__ */ React31.createElement("h4", null, "Work pages"), /* @__PURE__ */ React31.createElement("ul", null, /* @__PURE__ */ React31.createElement("li", null, "105 generated HTML pages"), /* @__PURE__ */ React31.createElement("li", null, "Each links back to source manifests"), /* @__PURE__ */ React31.createElement("li", null, "Styled with Canopy components"))), /* @__PURE__ */ React31.createElement("article", null, /* @__PURE__ */ React31.createElement("h4", null, "Custom pages"), /* @__PURE__ */ React31.createElement("ul", null, /* @__PURE__ */ React31.createElement("li", null, "Markdown & MDX-authored content"), /* @__PURE__ */ React31.createElement("li", null, "Reusable layouts for narratives"), /* @__PURE__ */ React31.createElement("li", null, "Embed IIIF media & interstitials"))), /* @__PURE__ */ React31.createElement("article", null, /* @__PURE__ */ React31.createElement("h4", null, "Search bundle"), /* @__PURE__ */ React31.createElement("ul", null, /* @__PURE__ */ React31.createElement("li", null, "Static FlexSearch index"), /* @__PURE__ */ React31.createElement("li", null, "Works + pages share records"), /* @__PURE__ */ React31.createElement("li", null, "Optional annotation dataset"))))));
2039
2061
  }
2040
2062
 
2041
2063
  // ui/src/content/timeline/Timeline.jsx
2042
- import React31 from "react";
2064
+ import React32 from "react";
2043
2065
 
2044
2066
  // ui/src/content/timeline/date-utils.js
2045
2067
  var FALLBACK_LOCALE = (() => {
@@ -2358,14 +2380,14 @@ function TimelineConnector({ side, isActive, highlight }) {
2358
2380
  "canopy-timeline__connector-dot",
2359
2381
  highlight || isActive ? "is-active" : ""
2360
2382
  ].filter(Boolean).join(" ");
2361
- return /* @__PURE__ */ React31.createElement("span", { className: connectorClasses, "aria-hidden": "true" }, side === "left" ? /* @__PURE__ */ React31.createElement(React31.Fragment, null, /* @__PURE__ */ React31.createElement("span", { className: "canopy-timeline__connector-line" }), /* @__PURE__ */ React31.createElement("span", { className: dotClasses })) : /* @__PURE__ */ React31.createElement(React31.Fragment, null, /* @__PURE__ */ React31.createElement("span", { className: dotClasses }), /* @__PURE__ */ React31.createElement("span", { className: "canopy-timeline__connector-line" })));
2383
+ return /* @__PURE__ */ React32.createElement("span", { className: connectorClasses, "aria-hidden": "true" }, side === "left" ? /* @__PURE__ */ React32.createElement(React32.Fragment, null, /* @__PURE__ */ React32.createElement("span", { className: "canopy-timeline__connector-line" }), /* @__PURE__ */ React32.createElement("span", { className: dotClasses })) : /* @__PURE__ */ React32.createElement(React32.Fragment, null, /* @__PURE__ */ React32.createElement("span", { className: dotClasses }), /* @__PURE__ */ React32.createElement("span", { className: "canopy-timeline__connector-line" })));
2362
2384
  }
2363
2385
  function renderResourceSection(point) {
2364
2386
  if (!point) return null;
2365
2387
  const manifestCards = Array.isArray(point.manifests) ? point.manifests.filter(Boolean) : [];
2366
2388
  const legacyResources = Array.isArray(point.resources) ? point.resources.filter(Boolean) : [];
2367
2389
  if (!manifestCards.length && !legacyResources.length) return null;
2368
- return /* @__PURE__ */ React31.createElement("div", { className: "canopy-timeline__resources" }, /* @__PURE__ */ React31.createElement("div", { className: "canopy-timeline__resources-list" }, manifestCards.map((manifest) => /* @__PURE__ */ React31.createElement("div", { key: manifest.id || manifest.href }, /* @__PURE__ */ React31.createElement(
2390
+ return /* @__PURE__ */ React32.createElement("div", { className: "canopy-timeline__resources" }, /* @__PURE__ */ React32.createElement("div", { className: "canopy-timeline__resources-list" }, manifestCards.map((manifest) => /* @__PURE__ */ React32.createElement("div", { key: manifest.id || manifest.href }, /* @__PURE__ */ React32.createElement(
2369
2391
  TeaserCard,
2370
2392
  {
2371
2393
  href: manifest.href,
@@ -2375,7 +2397,7 @@ function renderResourceSection(point) {
2375
2397
  thumbnail: manifest.thumbnail,
2376
2398
  type: manifest.type || "work"
2377
2399
  }
2378
- ))), legacyResources.map((resource, idx) => /* @__PURE__ */ React31.createElement("div", { key: resource.id || resource.href || `legacy-${idx}` }, /* @__PURE__ */ React31.createElement(
2400
+ ))), legacyResources.map((resource, idx) => /* @__PURE__ */ React32.createElement("div", { key: resource.id || resource.href || `legacy-${idx}` }, /* @__PURE__ */ React32.createElement(
2379
2401
  TeaserCard,
2380
2402
  {
2381
2403
  href: resource.href,
@@ -2400,26 +2422,26 @@ function Timeline({
2400
2422
  ...rest
2401
2423
  }) {
2402
2424
  const payloadPoints = payload && Array.isArray(payload.points) ? payload.points : null;
2403
- const rawPoints = React31.useMemo(() => {
2425
+ const rawPoints = React32.useMemo(() => {
2404
2426
  if (Array.isArray(pointsProp) && pointsProp.length) return pointsProp;
2405
2427
  if (payloadPoints && payloadPoints.length) return payloadPoints;
2406
2428
  return [];
2407
2429
  }, [pointsProp, payloadPoints]);
2408
- const sanitizedPoints = React31.useMemo(
2430
+ const sanitizedPoints = React32.useMemo(
2409
2431
  () => sanitizePoints(rawPoints),
2410
2432
  [rawPoints]
2411
2433
  );
2412
2434
  const localeValue = payload && payload.locale ? payload.locale : localeProp;
2413
- const baseLocale = React31.useMemo(
2435
+ const baseLocale = React32.useMemo(
2414
2436
  () => createLocale(localeValue),
2415
2437
  [localeValue]
2416
2438
  );
2417
2439
  const rangeInput = payload && payload.range ? payload.range : rangeProp || {};
2418
- const rangeOverrides = React31.useMemo(
2440
+ const rangeOverrides = React32.useMemo(
2419
2441
  () => deriveRangeOverrides(sanitizedPoints, rangeInput),
2420
2442
  [sanitizedPoints, rangeInput]
2421
2443
  );
2422
- const effectiveRange = React31.useMemo(
2444
+ const effectiveRange = React32.useMemo(
2423
2445
  () => normalizeRange({
2424
2446
  ...rangeOverrides,
2425
2447
  locale: baseLocale
@@ -2428,7 +2450,7 @@ function Timeline({
2428
2450
  );
2429
2451
  const spanStart = effectiveRange.startDate.getTime();
2430
2452
  const span = effectiveRange.span;
2431
- const pointsWithPosition = React31.useMemo(() => {
2453
+ const pointsWithPosition = React32.useMemo(() => {
2432
2454
  if (!sanitizedPoints.length) return [];
2433
2455
  return sanitizedPoints.map((point, index) => {
2434
2456
  const timestamp = point.meta.timestamp;
@@ -2442,29 +2464,29 @@ function Timeline({
2442
2464
  };
2443
2465
  });
2444
2466
  }, [sanitizedPoints, spanStart, span]);
2445
- const [activeId, setActiveId] = React31.useState(
2467
+ const [activeId, setActiveId] = React32.useState(
2446
2468
  () => getActivePointId(pointsWithPosition)
2447
2469
  );
2448
- React31.useEffect(() => {
2470
+ React32.useEffect(() => {
2449
2471
  setActiveId(getActivePointId(pointsWithPosition));
2450
2472
  }, [pointsWithPosition]);
2451
2473
  const thresholdValue = typeof thresholdProp === "number" ? thresholdProp : payload && payload.threshold != null ? payload.threshold : null;
2452
2474
  const stepsValue = typeof steps === "number" ? Number(steps) : payload && typeof payload.steps === "number" ? Number(payload.steps) : null;
2453
- const thresholdMs = React31.useMemo(
2475
+ const thresholdMs = React32.useMemo(
2454
2476
  () => getThresholdMs(thresholdValue, effectiveRange.granularity),
2455
2477
  [thresholdValue, effectiveRange.granularity]
2456
2478
  );
2457
- const groupedEntries = React31.useMemo(
2479
+ const groupedEntries = React32.useMemo(
2458
2480
  () => buildGroupedEntries(pointsWithPosition, thresholdMs, {
2459
2481
  granularity: effectiveRange.granularity,
2460
2482
  locale: baseLocale
2461
2483
  }),
2462
2484
  [pointsWithPosition, thresholdMs, effectiveRange.granularity, baseLocale]
2463
2485
  );
2464
- const [expandedGroupIds, setExpandedGroupIds] = React31.useState(
2486
+ const [expandedGroupIds, setExpandedGroupIds] = React32.useState(
2465
2487
  () => /* @__PURE__ */ new Set()
2466
2488
  );
2467
- React31.useEffect(() => {
2489
+ React32.useEffect(() => {
2468
2490
  setExpandedGroupIds((prev) => {
2469
2491
  if (!prev || prev.size === 0) return prev;
2470
2492
  const validIds = new Set(
@@ -2479,7 +2501,7 @@ function Timeline({
2479
2501
  return changed ? next : prev;
2480
2502
  });
2481
2503
  }, [groupedEntries]);
2482
- const toggleGroup = React31.useCallback((groupId) => {
2504
+ const toggleGroup = React32.useCallback((groupId) => {
2483
2505
  setExpandedGroupIds((prev) => {
2484
2506
  const next = new Set(prev || []);
2485
2507
  if (next.has(groupId)) next.delete(groupId);
@@ -2502,7 +2524,7 @@ function Timeline({
2502
2524
  point.id === activeId ? "is-active" : "",
2503
2525
  point.highlight ? "is-highlighted" : ""
2504
2526
  ].filter(Boolean).join(" ");
2505
- const connector = /* @__PURE__ */ React31.createElement(
2527
+ const connector = /* @__PURE__ */ React32.createElement(
2506
2528
  TimelineConnector,
2507
2529
  {
2508
2530
  side: point.side,
@@ -2510,9 +2532,9 @@ function Timeline({
2510
2532
  highlight: point.highlight
2511
2533
  }
2512
2534
  );
2513
- const body = /* @__PURE__ */ React31.createElement("div", { className: "canopy-timeline__point-body" }, /* @__PURE__ */ React31.createElement("span", { className: "canopy-timeline__point-date" }, point.meta.label), /* @__PURE__ */ React31.createElement("span", { className: "canopy-timeline__point-title" }, point.title), point.summary ? /* @__PURE__ */ React31.createElement("span", { className: "canopy-timeline__point-summary" }, point.summary) : null);
2535
+ const body = /* @__PURE__ */ React32.createElement("div", { className: "canopy-timeline__point-body" }, /* @__PURE__ */ React32.createElement("span", { className: "canopy-timeline__point-date" }, point.meta.label), /* @__PURE__ */ React32.createElement("span", { className: "canopy-timeline__point-title" }, point.title), point.summary ? /* @__PURE__ */ React32.createElement("span", { className: "canopy-timeline__point-summary" }, point.summary) : null);
2514
2536
  const resourceSection = renderResourceSection(point);
2515
- return /* @__PURE__ */ React31.createElement(
2537
+ return /* @__PURE__ */ React32.createElement(
2516
2538
  "div",
2517
2539
  {
2518
2540
  key: point.id,
@@ -2520,7 +2542,7 @@ function Timeline({
2520
2542
  style: wrapperStyle,
2521
2543
  role: "listitem"
2522
2544
  },
2523
- point.side === "left" ? /* @__PURE__ */ React31.createElement(React31.Fragment, null, /* @__PURE__ */ React31.createElement("div", { className: cardClasses }, body, resourceSection), connector) : /* @__PURE__ */ React31.createElement(React31.Fragment, null, connector, /* @__PURE__ */ React31.createElement("div", { className: cardClasses }, body, resourceSection))
2545
+ point.side === "left" ? /* @__PURE__ */ React32.createElement(React32.Fragment, null, /* @__PURE__ */ React32.createElement("div", { className: cardClasses }, body, resourceSection), connector) : /* @__PURE__ */ React32.createElement(React32.Fragment, null, connector, /* @__PURE__ */ React32.createElement("div", { className: cardClasses }, body, resourceSection))
2524
2546
  );
2525
2547
  }
2526
2548
  function renderGroupEntry(entry) {
@@ -2531,7 +2553,7 @@ function Timeline({
2531
2553
  const wrapperStyle = { top: `${entry.progress * 100}%` };
2532
2554
  const isExpanded = expandedGroupIds.has(entry.id);
2533
2555
  const hasActivePoint = entry.points.some((point) => point.id === activeId);
2534
- const connector = /* @__PURE__ */ React31.createElement(
2556
+ const connector = /* @__PURE__ */ React32.createElement(
2535
2557
  TimelineConnector,
2536
2558
  {
2537
2559
  side: entry.side,
@@ -2545,7 +2567,7 @@ function Timeline({
2545
2567
  hasActivePoint ? "is-active" : ""
2546
2568
  ].filter(Boolean).join(" ");
2547
2569
  const countLabel = `${entry.count} event${entry.count > 1 ? "s" : ""}`;
2548
- const header = /* @__PURE__ */ React31.createElement("div", { className: "canopy-timeline__group-header" }, /* @__PURE__ */ React31.createElement("div", { className: "canopy-timeline__group-summary" }, /* @__PURE__ */ React31.createElement("span", { className: "canopy-timeline__point-date" }, entry.label), /* @__PURE__ */ React31.createElement("span", { className: "canopy-timeline__group-count" }, countLabel)), /* @__PURE__ */ React31.createElement(
2570
+ const header = /* @__PURE__ */ React32.createElement("div", { className: "canopy-timeline__group-header" }, /* @__PURE__ */ React32.createElement("div", { className: "canopy-timeline__group-summary" }, /* @__PURE__ */ React32.createElement("span", { className: "canopy-timeline__point-date" }, entry.label), /* @__PURE__ */ React32.createElement("span", { className: "canopy-timeline__group-count" }, countLabel)), /* @__PURE__ */ React32.createElement(
2549
2571
  "button",
2550
2572
  {
2551
2573
  type: "button",
@@ -2555,7 +2577,7 @@ function Timeline({
2555
2577
  },
2556
2578
  isExpanded ? "Hide details" : "Show details"
2557
2579
  ));
2558
- const groupPoints = isExpanded ? /* @__PURE__ */ React31.createElement("div", { className: "canopy-timeline__group-points" }, entry.points.map((point) => /* @__PURE__ */ React31.createElement(
2580
+ const groupPoints = isExpanded ? /* @__PURE__ */ React32.createElement("div", { className: "canopy-timeline__group-points" }, entry.points.map((point) => /* @__PURE__ */ React32.createElement(
2559
2581
  "button",
2560
2582
  {
2561
2583
  key: point.id,
@@ -2566,11 +2588,11 @@ function Timeline({
2566
2588
  ].filter(Boolean).join(" "),
2567
2589
  onClick: () => setActiveId(point.id)
2568
2590
  },
2569
- /* @__PURE__ */ React31.createElement("span", { className: "canopy-timeline__point-date" }, point.meta.label),
2570
- /* @__PURE__ */ React31.createElement("span", { className: "canopy-timeline__group-point-title" }, point.title)
2591
+ /* @__PURE__ */ React32.createElement("span", { className: "canopy-timeline__point-date" }, point.meta.label),
2592
+ /* @__PURE__ */ React32.createElement("span", { className: "canopy-timeline__group-point-title" }, point.title)
2571
2593
  ))) : null;
2572
- const groupCard = /* @__PURE__ */ React31.createElement("div", { className: groupClasses }, header, groupPoints);
2573
- return /* @__PURE__ */ React31.createElement(
2594
+ const groupCard = /* @__PURE__ */ React32.createElement("div", { className: groupClasses }, header, groupPoints);
2595
+ return /* @__PURE__ */ React32.createElement(
2574
2596
  "div",
2575
2597
  {
2576
2598
  key: entry.id,
@@ -2578,17 +2600,17 @@ function Timeline({
2578
2600
  style: wrapperStyle,
2579
2601
  role: "listitem"
2580
2602
  },
2581
- entry.side === "left" ? /* @__PURE__ */ React31.createElement(React31.Fragment, null, groupCard, connector) : /* @__PURE__ */ React31.createElement(React31.Fragment, null, connector, groupCard)
2603
+ entry.side === "left" ? /* @__PURE__ */ React32.createElement(React32.Fragment, null, groupCard, connector) : /* @__PURE__ */ React32.createElement(React32.Fragment, null, connector, groupCard)
2582
2604
  );
2583
2605
  }
2584
- return /* @__PURE__ */ React31.createElement("section", { className: containerClasses, ...rest }, title ? /* @__PURE__ */ React31.createElement("h2", { className: "canopy-timeline__title" }, title) : null, description ? /* @__PURE__ */ React31.createElement("p", { className: "canopy-timeline__description" }, description) : null, rangeLabel ? /* @__PURE__ */ React31.createElement("p", { className: "canopy-timeline__range", "aria-live": "polite" }, rangeLabel) : null, /* @__PURE__ */ React31.createElement("div", { className: "canopy-timeline__body" }, /* @__PURE__ */ React31.createElement(
2606
+ return /* @__PURE__ */ React32.createElement("section", { className: containerClasses, ...rest }, title ? /* @__PURE__ */ React32.createElement("h2", { className: "canopy-timeline__title" }, title) : null, description ? /* @__PURE__ */ React32.createElement("p", { className: "canopy-timeline__description" }, description) : null, rangeLabel ? /* @__PURE__ */ React32.createElement("p", { className: "canopy-timeline__range", "aria-live": "polite" }, rangeLabel) : null, /* @__PURE__ */ React32.createElement("div", { className: "canopy-timeline__body" }, /* @__PURE__ */ React32.createElement(
2585
2607
  "div",
2586
2608
  {
2587
2609
  className: "canopy-timeline__list",
2588
2610
  role: "list",
2589
2611
  style: { minHeight: trackHeight }
2590
2612
  },
2591
- /* @__PURE__ */ React31.createElement("div", { className: "canopy-timeline__spine", "aria-hidden": "true" }),
2613
+ /* @__PURE__ */ React32.createElement("div", { className: "canopy-timeline__spine", "aria-hidden": "true" }),
2592
2614
  renderSteps(stepsValue, effectiveRange),
2593
2615
  groupedEntries.map((entry) => {
2594
2616
  if (entry.type === "group") return renderGroupEntry(entry);
@@ -2603,7 +2625,7 @@ function renderSteps(stepSize, range) {
2603
2625
  const markers = [];
2604
2626
  if (startYear < endYear) {
2605
2627
  markers.push(
2606
- /* @__PURE__ */ React31.createElement(
2628
+ /* @__PURE__ */ React32.createElement(
2607
2629
  "span",
2608
2630
  {
2609
2631
  key: "timeline-step-start",
@@ -2611,12 +2633,12 @@ function renderSteps(stepSize, range) {
2611
2633
  style: { top: "0%" },
2612
2634
  "aria-hidden": "true"
2613
2635
  },
2614
- /* @__PURE__ */ React31.createElement("span", { className: "canopy-timeline__step-line" }),
2615
- /* @__PURE__ */ React31.createElement("span", { className: "canopy-timeline__step-label" }, startYear)
2636
+ /* @__PURE__ */ React32.createElement("span", { className: "canopy-timeline__step-line" }),
2637
+ /* @__PURE__ */ React32.createElement("span", { className: "canopy-timeline__step-label" }, startYear)
2616
2638
  )
2617
2639
  );
2618
2640
  markers.push(
2619
- /* @__PURE__ */ React31.createElement(
2641
+ /* @__PURE__ */ React32.createElement(
2620
2642
  "span",
2621
2643
  {
2622
2644
  key: "timeline-step-end",
@@ -2624,8 +2646,8 @@ function renderSteps(stepSize, range) {
2624
2646
  style: { top: "100%" },
2625
2647
  "aria-hidden": "true"
2626
2648
  },
2627
- /* @__PURE__ */ React31.createElement("span", { className: "canopy-timeline__step-line" }),
2628
- /* @__PURE__ */ React31.createElement("span", { className: "canopy-timeline__step-label" }, endYear)
2649
+ /* @__PURE__ */ React32.createElement("span", { className: "canopy-timeline__step-line" }),
2650
+ /* @__PURE__ */ React32.createElement("span", { className: "canopy-timeline__step-label" }, endYear)
2629
2651
  )
2630
2652
  );
2631
2653
  }
@@ -2635,7 +2657,7 @@ function renderSteps(stepSize, range) {
2635
2657
  const progress = (timestamp - range.startDate.getTime()) / range.span;
2636
2658
  if (progress <= 0 || progress >= 1) continue;
2637
2659
  markers.push(
2638
- /* @__PURE__ */ React31.createElement(
2660
+ /* @__PURE__ */ React32.createElement(
2639
2661
  "span",
2640
2662
  {
2641
2663
  key: `timeline-step-${year}`,
@@ -2643,8 +2665,8 @@ function renderSteps(stepSize, range) {
2643
2665
  style: { top: `calc(${progress * 100}% - 0.5px)` },
2644
2666
  "aria-hidden": "true"
2645
2667
  },
2646
- /* @__PURE__ */ React31.createElement("span", { className: "canopy-timeline__step-line" }),
2647
- /* @__PURE__ */ React31.createElement("span", { className: "canopy-timeline__step-label" }, year)
2668
+ /* @__PURE__ */ React32.createElement("span", { className: "canopy-timeline__step-line" }),
2669
+ /* @__PURE__ */ React32.createElement("span", { className: "canopy-timeline__step-label" }, year)
2648
2670
  )
2649
2671
  );
2650
2672
  }
@@ -2674,6 +2696,7 @@ export {
2674
2696
  Image,
2675
2697
  MdxRelatedItems as RelatedItems,
2676
2698
  Scroll,
2699
+ MdxSearch as Search,
2677
2700
  SearchFiltersDialog,
2678
2701
  MdxSearchFormModal as SearchFormModal,
2679
2702
  SearchPanel,